diff options
Diffstat (limited to 'source/blender/editors')
328 files changed, 37837 insertions, 21904 deletions
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt index 1559512d713..757fca0a1b2 100644 --- a/source/blender/editors/CMakeLists.txt +++ b/source/blender/editors/CMakeLists.txt @@ -29,13 +29,14 @@ if(WITH_BLENDER) add_subdirectory(gpencil) add_subdirectory(interface) add_subdirectory(io) + add_subdirectory(manipulator_library) add_subdirectory(mask) add_subdirectory(mesh) add_subdirectory(metaball) add_subdirectory(object) add_subdirectory(physics) add_subdirectory(render) - add_subdirectory(screen) + add_subdirectory(scene) add_subdirectory(sculpt_paint) add_subdirectory(sound) add_subdirectory(space_action) @@ -60,6 +61,7 @@ if(WITH_BLENDER) add_subdirectory(transform) add_subdirectory(util) add_subdirectory(uvedit) + add_subdirectory(screen) endif() add_subdirectory(datafiles) diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt index 1bf1bb2a474..13432e38669 100644 --- a/source/blender/editors/animation/CMakeLists.txt +++ b/source/blender/editors/animation/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../gpu ../../makesdna ../../makesrna diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index dba060bfb29..9fb30dc8066 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -68,6 +68,8 @@ #include "BKE_nla.h" #include "BKE_context.h" +#include "GPU_immediate.h" + #include "UI_interface.h" #include "UI_interface_icons.h" #include "UI_resources.h" @@ -76,7 +78,6 @@ #include "ED_keyframing.h" #include "BIF_gl.h" -#include "BIF_glutil.h" #include "WM_api.h" #include "WM_types.h" @@ -119,11 +120,10 @@ static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, floa /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); - glColor3fv(color); /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ UI_draw_roundbox_corner_set((expanded) ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); - UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8); + UI_draw_roundbox_3fvAlpha(true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); } @@ -141,13 +141,19 @@ static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale View2D *v2d = &ac->ar->v2d; short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; float color[3]; - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); - glColor3fv(color); - + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3fv(color); + /* no rounded corner - just rectangular box */ - glRectf(offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc); + immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc); + + immUnbindProgram(); } /* helper method to test if group colors should be drawn */ @@ -224,13 +230,19 @@ static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, f View2D *v2d = &ac->ar->v2d; short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; float color[3]; + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); - glColor3fv(color); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3fv(color); /* no rounded corners - just rectangular box */ - glRectf(offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc); + immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc); + + immUnbindProgram(); } /* Indention + Offset ------------------------------------------- */ @@ -421,14 +433,13 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); - glColor3fv(color); /* rounded corners on LHS only * - top and bottom * - special hack: make the top a bit higher, since we are first... */ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT); - UI_draw_roundbox_gl_mode(GL_POLYGON, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8); + UI_draw_roundbox_3fvAlpha(true, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); } /* name for summary entries */ @@ -814,11 +825,10 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); - glColor3fv(color); /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); - UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8); + UI_draw_roundbox_3fvAlpha(true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); } /* name for group entries */ @@ -1071,11 +1081,10 @@ static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, floa /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); - glColor3fv(color); - /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ + /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); - UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5); + UI_draw_roundbox_3fvAlpha(true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f); } /* name for nla controls expander entries */ @@ -2018,7 +2027,7 @@ static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ - return PART_DS_EXPAND; + return 0; case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */ return ADT_NLA_EVAL_OFF; @@ -2036,22 +2045,18 @@ static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin } /* get pointer to the setting */ -static void *acf_dspart_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type) +static void *acf_dspart_setting_ptr(bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting, short *type) { - ParticleSettings *part = (ParticleSettings *)ale->data; - /* clear extra return data first */ *type = 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ - return GET_ACF_FLAG_PTR(part->flag, type); + return NULL; case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ - if (part->adt) - return GET_ACF_FLAG_PTR(part->adt->flag, type); return NULL; default: /* unsupported */ @@ -3420,24 +3425,20 @@ static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float y */ nla_action_get_color(adt, (bAction *)ale->data, color); - if (adt && (adt->flag & ADT_NLA_EDIT_ON)) { - /* Yes, the color vector has 4 components, BUT we only want to be using 3 of them! */ - glColor3fv(color); - } - else { - float alpha = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f; - glColor4f(color[0], color[1], color[2], alpha); - } - - /* only on top left corner, to show that this channel sits on top of the preceding ones + if (adt && (adt->flag & ADT_NLA_EDIT_ON)) + color[3] = 1.0f; + else + color[3] = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f; + + /* only on top left corner, to show that this channel sits on top of the preceding ones * while still linking into the action line strip to the right */ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT); - + /* draw slightly shifted up vertically to look like it has more separation from other channels, * but we then need to slightly shorten it so that it doesn't look like it overlaps */ - UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8); + UI_draw_roundbox_4fv(true, offset, yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8, color); } /* name for nla action entries */ @@ -3861,15 +3862,20 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float /* for F-Curves, draw color-preview of curve behind checkbox */ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) { FCurve *fcu = (FCurve *)ale->data; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever * color the curve has stored */ - glColor3fv(fcu->color); + immUniformColor3fv(fcu->color); /* just a solid color rect */ - glRectf(offset, yminc, offset + ICON_WIDTH, ymaxc); + immRectf(pos, offset, yminc, offset + ICON_WIDTH, ymaxc); + + immUnbindProgram(); } /* icon is drawn as widget now... */ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) { @@ -3894,27 +3900,39 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float if (acf->name && !achannel_is_being_renamed(ac, acf, channel_index)) { const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */ - + unsigned char col[4]; + /* set text color */ /* XXX: if active, highlight differently? */ + if (selected) - UI_ThemeColor(TH_TEXT_HI); + UI_GetThemeColor4ubv(TH_TEXT_HI, col); else - UI_ThemeColor(TH_TEXT); - + UI_GetThemeColor4ubv(TH_TEXT, col); + /* get name */ acf->name(ale, name); offset += 3; - UI_fontstyle_draw_simple(fstyle, offset, ytext, name); + UI_fontstyle_draw_simple(fstyle, offset, ytext, name, col); /* draw red underline if channel is disabled */ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE) && (ale->flag & FCURVE_DISABLED)) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* FIXME: replace hardcoded color here, and check on extents! */ - glColor3f(1.0f, 0.0f, 0.0f); - glLineWidth(2.0); - fdrawline((float)(offset), yminc, - (float)(v2d->cur.xmax), yminc); + immUniformColor3f(1.0f, 0.0f, 0.0f); + + glLineWidth(2.0f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, (float)offset, yminc); + immVertex2f(pos, (float)v2d->cur.xmax, yminc); + immEnd(); + + immUnbindProgram(); } } @@ -3928,10 +3946,13 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float short draw_sliders = 0; float ymin_ofs = 0.0f; float color[3]; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* get and set backdrop color */ acf->get_backdrop_color(ac, ale, color); - glColor3fv(color); + immUniformColor3fv(color); /* check if we need to show the sliders */ if ((ac->sl) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) { @@ -3989,7 +4010,9 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float * - starts from the point where the first toggle/slider starts, * - ends past the space that might be reserved for a scroller */ - glRectf(v2d->cur.xmax - (float)offset, yminc + ymin_ofs, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc); + immRectf(pos, v2d->cur.xmax - (float)offset, yminc + ymin_ofs, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc); + + immUnbindProgram(); } } diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 82f24c91df1..80a388408a5 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -50,13 +50,15 @@ #include "BKE_animsys.h" #include "BKE_action.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_gpencil.h" #include "BKE_context.h" +#include "BKE_library.h" #include "BKE_mask.h" #include "BKE_global.h" -#include "BKE_library.h" +#include "BKE_scene.h" + +#include "DEG_depsgraph_build.h" #include "UI_view2d.h" @@ -1720,7 +1722,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op)) /* send notifier that things have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); return OPERATOR_FINISHED; } @@ -2682,16 +2684,17 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, { bDopeSheet *ads = (bDopeSheet *)ac->data; Scene *sce = (Scene *)ads->source; + SceneLayer *scene_layer = ac->scene_layer; Base *base = (Base *)ale->data; Object *ob = base->object; AnimData *adt = ob->adt; /* set selection status */ - if ((ob->restrictflag & OB_RESTRICT_SELECT) == 0) { + if (base->flag & BASE_SELECTABLED) { if (selectmode == SELECT_INVERT) { /* swap select */ - base->flag ^= SELECT; - ob->flag = base->flag; + ED_object_base_select(base, BA_INVERT); + BKE_scene_object_base_flag_sync_from_base(base); if (adt) adt->flag ^= ADT_UI_SELECTED; } @@ -2700,20 +2703,20 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, /* deselect all */ /* TODO: should this deselect all other types of channels too? */ - for (b = sce->base.first; b; b = b->next) { - b->flag &= ~SELECT; - b->object->flag = b->flag; + for (b = scene_layer->object_bases.first; b; b = b->next) { + ED_object_base_select(b, BA_DESELECT); + BKE_scene_object_base_flag_sync_from_base(b); if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE); } /* select object now */ - base->flag |= SELECT; - ob->flag |= SELECT; + ED_object_base_select(base, BA_SELECT); + BKE_scene_object_base_flag_sync_from_base(base); if (adt) adt->flag |= ADT_UI_SELECTED; } /* change active object - regardless of whether it is now selected [T37883] */ - ED_base_object_activate(C, base); /* adds notifier */ + ED_object_base_activate(C, base); /* adds notifier */ if ((adt) && (adt->flag & ADT_UI_SELECTED)) adt->flag |= ADT_UI_ACTIVE; diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index cc77a321a89..abdc6450abd 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -49,11 +49,12 @@ #include "BKE_fcurve.h" #include "BKE_gpencil.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_node.h" #include "BKE_sequencer.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "ED_anim_api.h" @@ -77,7 +78,7 @@ void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale) adt = BKE_animdata_from_id(id); if (adt) { adt->recalc |= ADT_RECALC_ANIM; - DAG_id_tag_update(id, OB_RECALC_TIME); + DEG_id_tag_update(id, OB_RECALC_TIME); } /* update data */ @@ -98,7 +99,7 @@ void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale) else { /* in other case we do standard depsgraph update, ideally * we'd be calling property update functions here too ... */ - DAG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); // XXX or do we want something more restrictive? + DEG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); // XXX or do we want something more restrictive? } } @@ -114,7 +115,7 @@ void ANIM_id_update(Scene *UNUSED(scene), ID *id) adt->recalc |= ADT_RECALC_ANIM; /* set recalc flags */ - DAG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); // XXX or do we want something more restrictive? + DEG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); // XXX or do we want something more restrictive? } } diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index a6febdb575e..08851cebf51 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -58,12 +58,13 @@ #include "RNA_access.h" -#include "BIF_gl.h" - #include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" + /* *************************************************** */ /* CURRENT FRAME DRAWING */ @@ -71,13 +72,17 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const bool time) { const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; - float xscale, yscale, x, y; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned char col[4]; + float xscale, x, y; char numstr[32] = " t"; /* t is the character to start replacing from */ int slen; /* because the frame number text is subject to the same scaling as the contents of the view */ - UI_view2d_scale_get(v2d, &xscale, &yscale); - glScalef(1.0f / xscale, 1.0f, 1.0f); + UI_view2d_scale_get(v2d, &xscale, NULL); + gpuPushMatrix(); + gpuScale2f(1.0f / xscale, 1.0f); /* get timecode string * - padding on str-buf passed so that it doesn't sit on the frame indicator @@ -96,17 +101,21 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const /* get starting coordinates for drawing */ x = cfra * xscale; y = 0.9f * U.widget_unit; - + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* draw green box around/behind text */ - UI_ThemeColorShade(TH_CFRAME, 0); - glRectf(x, y, x + slen, y + 0.75f * U.widget_unit); - - /* draw current frame number - black text */ - UI_ThemeColor(TH_TEXT); - UI_fontstyle_draw_simple(fstyle, x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr); - + immUniformThemeColorShade(TH_CFRAME, 0); + + immRectf(pos, x, y, x + slen, y + 0.75f * U.widget_unit); + immUnbindProgram(); + + /* draw current frame number */ + UI_GetThemeColor4ubv(TH_TEXT, col); + UI_fontstyle_draw_simple(fstyle, x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr, col); + /* restore view transform */ - glScalef(xscale, 1.0, 1.0); + gpuPopMatrix(); } /* General call for drawing current frame indicator in animation editor */ @@ -114,18 +123,24 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag) { Scene *scene = CTX_data_scene(C); - /* Draw a light green line to indicate current frame */ - UI_ThemeColor(TH_CFRAME); - const float time = scene->r.cfra + scene->r.subframe; const float x = (float)(time * scene->r.framelen); glLineWidth((flag & DRAWCFRA_WIDE) ? 3.0 : 2.0); - glBegin(GL_LINES); - glVertex2f(x, v2d->cur.ymin - 500.0f); /* XXX arbitrary... want it go to bottom */ - glVertex2f(x, v2d->cur.ymax); - glEnd(); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* Draw a light green line to indicate current frame */ + immUniformThemeColor(TH_CFRAME); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, x, v2d->cur.ymin - 500.0f); /* XXX arbitrary... want it go to bottom */ + immVertex2f(pos, x, v2d->cur.ymax); + immEnd(); + immUnbindProgram(); /* Draw current frame number in a little box */ if (flag & DRAWCFRA_SHOW_NUMBOX) { @@ -147,17 +162,24 @@ void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width) if (PRVRANGEON) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); - + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); + /* only draw two separate 'curtains' if there's no overlap between them */ if (PSFRA < PEFRA + end_frame_width) { - glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax); - glRectf((float)(PEFRA + end_frame_width), v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax); + immRectf(pos, (float)(PEFRA + end_frame_width), v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); } else { - glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); } - + + immUnbindProgram(); + glDisable(GL_BLEND); } } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 2ac305dbc30..f5eadeab92a 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -74,6 +74,7 @@ #include "DNA_gpencil_types.h" #include "DNA_object_types.h" #include "DNA_userdef_types.h" +#include "DNA_layer_types.h" #include "MEM_guardedalloc.h" @@ -90,6 +91,7 @@ #include "BKE_global.h" #include "BKE_group.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_modifier.h" @@ -130,11 +132,11 @@ static void animedit_get_yscale_factor(bAnimContext *ac) /* Note: there's a similar function in key.c (BKE_key_from_object) */ static Key *actedit_get_shapekeys(bAnimContext *ac) { - Scene *scene = ac->scene; + SceneLayer *sl = ac->scene_layer; Object *ob; Key *key; - ob = OBACT; + ob = OBACT(sl); if (ob == NULL) return NULL; @@ -378,8 +380,9 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac) ac->scene = scene; if (scene) { ac->markers = ED_context_get_markers(C); - ac->obact = (scene->basact) ? scene->basact->object : NULL; } + ac->scene_layer = CTX_data_scene_layer(C); + ac->obact = (ac->scene_layer->basact) ? ac->scene_layer->basact->object : NULL; ac->sa = sa; ac->ar = ar; ac->sl = sl; @@ -1683,15 +1686,16 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi if (ads->filterflag & ADS_FILTER_GP_3DONLY) { Scene *scene = (Scene *)ads->source; + SceneLayer *sl = (SceneLayer *)ac->scene_layer; Base *base; - + /* Active scene's GPencil block first - No parent item needed... */ if (scene->gpd) { items += animdata_filter_gpencil_data(anim_data, ads, scene->gpd, filter_mode); } /* Objects in the scene */ - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { /* Only consider this object if it has got some GP data (saving on all the other tests) */ if (base->object && base->object->gpd) { Object *ob = base->object; @@ -1707,14 +1711,14 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi */ if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) { /* layer visibility - we check both object and base, since these may not be in sync yet */ - if ((scene->lay & (ob->lay | base->lay)) == 0) continue; + if ((base->flag & BASE_VISIBLED) == 0) continue; /* outliner restrict-flag */ if (ob->restrictflag & OB_RESTRICT_VIEW) continue; } /* check selection and object type filters */ - if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == scene->basact)*/) ) { + if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & BASE_SELECTED) /*|| (base == scene->basact)*/) ) { /* only selected should be shown */ continue; } @@ -1954,25 +1958,26 @@ static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data, static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode) { - SceneRenderLayer *srl; + SceneLayer *scene_layer; FreestyleLineSet *lineset; size_t items = 0; - for (srl = sce->r.layers.first; srl; srl = srl->next) { - for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { + for (scene_layer = sce->render_layers.first; scene_layer; scene_layer = scene_layer->next) { + for (lineset = scene_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) { if (lineset->linestyle) { lineset->linestyle->id.tag |= LIB_TAG_DOIT; } } } - for (srl = sce->r.layers.first; srl; srl = srl->next) { + for (scene_layer = sce->render_layers.first; scene_layer; scene_layer = scene_layer->next) { /* skip render layers without Freestyle enabled */ - if (!(srl->layflag & SCE_LAY_FRS)) + if ((scene_layer->flag & SCENE_LAYER_FREESTYLE) == 0) { continue; - + } + /* loop over linesets defined in the render layer */ - for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { + for (lineset = scene_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) { FreestyleLineStyle *linestyle = lineset->linestyle; ListBase tmp_data = {NULL, NULL}; size_t tmp_items = 0; @@ -2631,7 +2636,7 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data if (filter_mode & ANIMFILTER_LIST_CHANNELS) { /* check if filtering by selection */ // XXX: double-check on this - most of the time, a lot of tools need to filter out these channels! - if (ANIMCHANNEL_SELOK((base->flag & SELECT))) { + if (ANIMCHANNEL_SELOK((base->flag & BASE_SELECTED))) { /* check if filtering by active status */ if (ANIMCHANNEL_ACTIVEOK(ob)) { ANIMCHANNEL_NEW_CHANNEL(base, ANIMTYPE_OBJECT, ob); @@ -2855,7 +2860,7 @@ static size_t animdata_filter_dopesheet_movieclips(bAnimContext *ac, ListBase *a } /* Helper for animdata_filter_dopesheet() - For checking if an object should be included or not */ -static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base, int filter_mode) +static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_mode) { Object *ob = base->object; @@ -2873,7 +2878,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base */ if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) { /* layer visibility - we check both object and base, since these may not be in sync yet */ - if ((scene->lay & (ob->lay | base->lay)) == 0) + if ((base->flag & BASE_VISIBLED) == 0) return false; /* outliner restrict-flag */ @@ -2908,7 +2913,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base } /* check selection and object type filters */ - if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/)) { + if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & BASE_SELECTED) /*|| (base == sce->basact)*/)) { /* only selected should be shown */ return false; } @@ -2936,15 +2941,15 @@ static int ds_base_sorting_cmp(const void *base1_ptr, const void *base2_ptr) } /* Get a sorted list of all the bases - for inclusion in dopesheet (when drawing channels) */ -static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int filter_mode, size_t *r_usable_bases) +static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, SceneLayer *sl, int filter_mode, size_t *r_usable_bases) { /* Create an array with space for all the bases, but only containing the usable ones */ - size_t tot_bases = BLI_listbase_count(&scene->base); + size_t tot_bases = BLI_listbase_count(&sl->object_bases); size_t num_bases = 0; Base **sorted_bases = MEM_mallocN(sizeof(Base *) * tot_bases, "Dopesheet Usable Sorted Bases"); - for (Base *base = scene->base.first; base; base = base->next) { - if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if (animdata_filter_base_is_ok(ads, base, filter_mode)) { sorted_bases[num_bases++] = base; } } @@ -2962,8 +2967,9 @@ static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, int filter_mode) { Scene *scene = (Scene *)ads->source; + SceneLayer *sl = (SceneLayer *)ac->scene_layer; size_t items = 0; - + /* check that we do indeed have a scene */ if ((ads->source == NULL) || (GS(ads->source->name) != ID_SCE)) { printf("Dope Sheet Error: No scene!\n"); @@ -3000,14 +3006,14 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b * - Don't do this if there's just a single object */ if ((filter_mode & ANIMFILTER_LIST_CHANNELS) && !(ads->flag & ADS_FLAG_NO_DB_SORT) && - (scene->base.first != scene->base.last)) + (sl->object_bases.first != sl->object_bases.last)) { /* Filter list of bases (i.e. objects), sort them, then add their contents normally... */ // TODO: Cache the old sorted order - if the set of bases hasn't changed, don't re-sort... Base **sorted_bases; size_t num_bases; - sorted_bases = animdata_filter_ds_sorted_bases(ads, scene, filter_mode, &num_bases); + sorted_bases = animdata_filter_ds_sorted_bases(ads, sl, filter_mode, &num_bases); if (sorted_bases) { /* Add the necessary channels for these bases... */ for (size_t i = 0; i < num_bases; i++) { @@ -3024,8 +3030,8 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b /* Filter and add contents of each base (i.e. object) without them sorting first * NOTE: This saves performance in cases where order doesn't matter */ - for (Base *base = scene->base.first; base; base = base->next) { - if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if (animdata_filter_base_is_ok(ads, base, filter_mode)) { /* since we're still here, this object should be usable */ items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode); } diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 04398e88499..a5965336e12 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -36,13 +36,14 @@ #include "DNA_object_types.h" #include "BLI_blenlib.h" -#include "BLI_math_base.h" +#include "BLI_math.h" #include "BLI_utildefines.h" #include "BLT_translation.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_report.h" #include "BKE_scene.h" @@ -56,9 +57,11 @@ #include "WM_api.h" #include "WM_types.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" + #include "UI_interface.h" #include "UI_interface_icons.h" #include "UI_view2d.h" @@ -351,19 +354,30 @@ static void draw_marker( if (flag & DRAW_MARKERS_LINES) #endif { - setlinestyle(3); - - if (marker->flag & SELECT) - glColor4ub(255, 255, 255, 96); - else - glColor4ub(0, 0, 0, 96); - - glBegin(GL_LINES); - glVertex2f(xpos + 0.5f, 12.0f); - glVertex2f(xpos + 0.5f, (v2d->cur.ymax + 12.0f) * yscale); - glEnd(); - - setlinestyle(0); + Gwn_VertFormat *format = immVertexFormat(); + uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + if (marker->flag & SELECT) { + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.38f); + } + else { + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.38f); + } + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, xpos + 0.5f, 12.0f); + immVertex2f(pos, xpos + 0.5f, (v2d->cur.ymax + 12.0f) * yscale); + immEnd(); + + immUnbindProgram(); } /* 5 px to offset icon to align properly, space / pixels corrects for zoom */ @@ -383,19 +397,20 @@ static void draw_marker( /* and the marker name too, shifted slightly to the top-right */ if (marker->name[0]) { + unsigned char text_col[4]; float x, y; /* minimal y coordinate which wouldn't be occluded by scroll */ int min_y = 17.0f * UI_DPI_FAC; if (marker->flag & SELECT) { - UI_ThemeColor(TH_TEXT_HI); + UI_GetThemeColor4ubv(TH_TEXT_HI, text_col); x = xpos + 4.0f * UI_DPI_FAC; y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC; y = max_ii(y, min_y); } else { - UI_ThemeColor(TH_TEXT); + UI_GetThemeColor4ubv(TH_TEXT, text_col); if ((marker->frame <= cfra) && (marker->frame + 5 > cfra)) { x = xpos + 8.0f * UI_DPI_FAC; y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC; @@ -409,14 +424,11 @@ static void draw_marker( #ifdef DURIAN_CAMERA_SWITCH if (marker->camera && (marker->camera->restrictflag & OB_RESTRICT_RENDER)) { - float col[4]; - glGetFloatv(GL_CURRENT_COLOR, col); - col[3] = 0.4; - glColor4fv(col); + text_col[3] = 100; } #endif - UI_fontstyle_draw_simple(fstyle, x, y, marker->name); + UI_fontstyle_draw_simple(fstyle, x, y, marker->name, text_col); } } @@ -443,21 +455,27 @@ void ED_markers_draw(const bContext *C, int flag) v2d = UI_view2d_fromcontext(C); if (flag & DRAW_MARKERS_MARGIN) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + const unsigned char shade[4] = {0, 0, 0, 16}; - glColor4ubv(shade); + immUniformColor4ubv(shade); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glRectf(v2d->cur.xmin, 0, v2d->cur.xmax, UI_MARKER_MARGIN_Y); + immRectf(pos, v2d->cur.xmin, 0, v2d->cur.xmax, UI_MARKER_MARGIN_Y); glDisable(GL_BLEND); + + immUnbindProgram(); } /* no time correction for framelen! space is drawn with old values */ ypixels = BLI_rcti_size_y(&v2d->mask); UI_view2d_scale_get(v2d, &xscale, &yscale); - glScalef(1.0f / xscale, 1.0f, 1.0f); + gpuPushMatrix(); + gpuScale2f(1.0f / xscale, 1.0f); /* x-bounds with offset for text (adjust for long string, avoid checking string width) */ font_width_max = (10 * UI_DPI_FAC) / xscale; @@ -480,7 +498,7 @@ void ED_markers_draw(const bContext *C, int flag) } } - glScalef(xscale, 1.0f, 1.0f); + gpuPopMatrix(); } /* ************************ Marker Wrappers API ********************* */ @@ -844,7 +862,7 @@ static void ed_marker_move_apply(bContext *C, wmOperator *op) BKE_scene_camera_switch_update(scene); if (camera != scene->camera) { - BKE_screen_view3d_scene_sync(sc); + BKE_screen_view3d_scene_sync(sc, scene); WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene); } #endif @@ -1128,12 +1146,13 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool if (camera) { Scene *scene = CTX_data_scene(C); + SceneLayer *scene_layer = CTX_data_scene_layer(C); Base *base; TimeMarker *marker; int sel = 0; if (!extend) - BKE_scene_base_deselect_all(scene); + BKE_scene_layer_base_deselect_all(scene_layer); for (marker = markers->first; marker; marker = marker->next) { if (marker->frame == cfra) { @@ -1145,11 +1164,11 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool for (marker = markers->first; marker; marker = marker->next) { if (marker->camera) { if (marker->frame == cfra) { - base = BKE_scene_base_find(scene, marker->camera); + base = BKE_scene_layer_base_find(scene_layer, marker->camera); if (base) { - ED_base_object_select(base, sel); + ED_object_base_select(base, sel); if (sel) - ED_base_object_activate(C, base); + ED_object_base_activate(C, base); } } } @@ -1532,7 +1551,7 @@ static int ed_marker_camera_bind_exec(bContext *C, wmOperator *UNUSED(op)) /* camera may have changes */ BKE_scene_camera_switch_update(scene); - BKE_screen_view3d_scene_sync(sc); + BKE_screen_view3d_scene_sync(sc, scene); WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 24eb6451c5d..2d04f73c4ac 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -44,11 +44,13 @@ #include "DNA_texture_types.h" #include "BKE_animsys.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_context.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "ED_keyframing.h" #include "UI_interface.h" @@ -843,7 +845,7 @@ static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_typ if (success) { /* send updates */ UI_context_update_anim_flag(C); - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX return OPERATOR_FINISHED; @@ -941,7 +943,7 @@ static int remove_driver_button_exec(bContext *C, wmOperator *op) if (success) { /* send updates */ UI_context_update_anim_flag(C); - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX } @@ -1031,8 +1033,8 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op) UI_context_update_anim_flag(C); - DAG_relations_tag_update(CTX_data_main(C)); - DAG_id_tag_update(ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA); + DEG_relations_tag_update(CTX_data_main(C)); + DEG_id_tag_update(ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); // XXX diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index f25dbf2381c..12803854a42 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -52,7 +52,8 @@ #include "BKE_fcurve.h" -#include "BIF_gl.h" +#include "GPU_draw.h" +#include "GPU_immediate.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -463,49 +464,15 @@ bool actkeyblock_is_valid(ActKeyBlock *ab, DLRBT_Tree *keys) /* *************************** Keyframe Drawing *************************** */ -/* coordinates for diamond shape */ -static const float _unit_diamond_shape[4][2] = { - {0.0f, 1.0f}, /* top vert */ - {1.0f, 0.0f}, /* mid-right */ - {0.0f, -1.0f}, /* bottom vert */ - {-1.0f, 0.0f} /* mid-left */ -}; - -/* draw a simple diamond shape with OpenGL */ -void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha) +void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type, short mode, float alpha, + unsigned int pos_id, unsigned int size_id, unsigned int color_id, unsigned int outline_color_id) { - static GLuint displist1 = 0; - static GLuint displist2 = 0; - - /* initialize 2 display lists for diamond shape - one empty, one filled */ - if (displist1 == 0) { - displist1 = glGenLists(1); - glNewList(displist1, GL_COMPILE); - - glBegin(GL_LINE_LOOP); - glVertex2fv(_unit_diamond_shape[0]); - glVertex2fv(_unit_diamond_shape[1]); - glVertex2fv(_unit_diamond_shape[2]); - glVertex2fv(_unit_diamond_shape[3]); - glEnd(); - - glEndList(); - } - if (displist2 == 0) { - displist2 = glGenLists(1); - glNewList(displist2, GL_COMPILE); - - glBegin(GL_QUADS); - glVertex2fv(_unit_diamond_shape[0]); - glVertex2fv(_unit_diamond_shape[1]); - glVertex2fv(_unit_diamond_shape[2]); - glVertex2fv(_unit_diamond_shape[3]); - glEnd(); - - glEndList(); - } - - /* tweak size of keyframe shape according to type of keyframe + bool draw_fill = ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH); + bool draw_outline = ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH); + + BLI_assert(draw_fill || draw_outline); + + /* tweak size of keyframe shape according to type of keyframe * - 'proper' keyframes have key_type = 0, so get drawn at full size */ switch (key_type) { @@ -513,120 +480,93 @@ void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, break; case BEZT_KEYTYPE_BREAKDOWN: /* slightly smaller than normal keyframe */ - hsize *= 0.85f; + size *= 0.85f; break; case BEZT_KEYTYPE_MOVEHOLD: /* slightly smaller than normal keyframes (but by less than for breakdowns) */ - //hsize *= 0.72f; - hsize *= 0.95f; + size *= 0.925f; break; case BEZT_KEYTYPE_EXTREME: /* slightly larger */ - hsize *= 1.2f; + size *= 1.2f; break; default: - hsize -= 0.5f * key_type; - break; + size -= 0.8f * key_type; } - - /* adjust view transform before starting */ - glTranslatef(x, y, 0.0f); - glScalef(1.0f / xscale * hsize, hsize, 1.0f); - - /* anti-aliased lines for more consistent appearance */ - glEnable(GL_LINE_SMOOTH); - + + unsigned char fill_col[4]; + unsigned char outline_col[4]; + /* draw! */ - if (ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH)) { - float inner_col[4]; - + if (draw_fill) { /* get interior colors from theme (for selected and unselected only) */ switch (key_type) { case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames (default theme) */ - { - if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN_SELECT, inner_col); - else UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN, inner_col); + UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_BREAKDOWN_SELECT : TH_KEYTYPE_BREAKDOWN, fill_col); break; - } case BEZT_KEYTYPE_EXTREME: /* reddish frames (default theme) */ - { - if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME_SELECT, inner_col); - else UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME, inner_col); + UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_EXTREME_SELECT : TH_KEYTYPE_EXTREME, fill_col); break; - } case BEZT_KEYTYPE_JITTER: /* greenish frames (default theme) */ - { - if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_JITTER_SELECT, inner_col); - else UI_GetThemeColor4fv(TH_KEYTYPE_JITTER, inner_col); + UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_JITTER_SELECT : TH_KEYTYPE_JITTER, fill_col); break; - } case BEZT_KEYTYPE_MOVEHOLD: /* similar to traditional keyframes, but different... */ - { /* XXX: Should these get their own theme options instead? */ - if (sel) UI_GetThemeColorShade4fv(TH_STRIP_SELECT, 35, inner_col); - else UI_GetThemeColorShade4fv(TH_STRIP, 50, inner_col); - - inner_col[3] = 1.0f; /* full opacity, to avoid problems with visual glitches */ + if (sel) UI_GetThemeColorShade3ubv(TH_STRIP_SELECT, 35, fill_col); + else UI_GetThemeColorShade3ubv(TH_STRIP, 50, fill_col); + fill_col[3] = 255; /* full opacity, to avoid problems with visual glitches */ break; - } case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames (default theme) */ default: - { - if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME_SELECT, inner_col); - else UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME, inner_col); - break; - } + UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_KEYFRAME_SELECT : TH_KEYTYPE_KEYFRAME, fill_col); } /* NOTE: we don't use the straight alpha from the theme, or else effects such as * graying out protected/muted channels doesn't work correctly! */ - inner_col[3] *= alpha; - glColor4fv(inner_col); - - /* draw the "filled in" interior poly now */ - glCallList(displist2); + fill_col[3] *= alpha; + + if (!draw_outline) { + /* force outline color to match */ + outline_col[0] = fill_col[0]; + outline_col[1] = fill_col[1]; + outline_col[2] = fill_col[2]; + outline_col[3] = fill_col[3]; + } } - - if (ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH)) { - float border_col[4]; - + + if (draw_outline) { /* exterior - black frame */ - if (sel) UI_GetThemeColor4fv(TH_KEYBORDER_SELECT, border_col); - else UI_GetThemeColor4fv(TH_KEYBORDER, border_col); - - border_col[3] *= alpha; - glColor4fv(border_col); - - glCallList(displist1); + UI_GetThemeColor4ubv(sel ? TH_KEYBORDER_SELECT : TH_KEYBORDER, outline_col); + outline_col[3] *= alpha; + + if (!draw_fill) { + /* fill color needs to be (outline.rgb, 0) */ + fill_col[0] = outline_col[0]; + fill_col[1] = outline_col[1]; + fill_col[2] = outline_col[2]; + fill_col[3] = 0; + } } - - glDisable(GL_LINE_SMOOTH); - - /* restore view transform */ - glScalef(xscale / hsize, 1.0f / hsize, 1.0f); - glTranslatef(-x, -y, 0.0f); + + immAttrib1f(size_id, size); + immAttrib4ubv(color_id, fill_col); + immAttrib4ubv(outline_color_id, outline_col); + immVertex2f(pos_id, x, y); } static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, float yscale_fac, bool channelLocked) { - ActKeyColumn *ak; - ActKeyBlock *ab; - float alpha; - float xscale; - - const float iconsize = (U.widget_unit / 4.0f) * yscale_fac; - const float mhsize = iconsize * 0.7f; + const float icon_sz = U.widget_unit * 0.5f * yscale_fac; + const float half_icon_sz = 0.5f * icon_sz; + const float smaller_sz = 0.35f * icon_sz; glEnable(GL_BLEND); - /* get View2D scaling factor */ - UI_view2d_scale_get(v2d, &xscale, NULL); - /* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */ /* TODO: allow this opacity factor to be themed? */ - alpha = (channelLocked) ? 0.25f : 1.0f; + float alpha = channelLocked ? 0.25f : 1.0f; /* draw keyblocks */ if (blocks) { @@ -644,45 +584,59 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa sel_mhcol[3] *= 0.8f; copy_v4_v4(unsel_mhcol, unsel_color); unsel_mhcol[3] *= 0.8f; - + + unsigned int pos_id = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* NOTE: the tradeoff for changing colors between each draw is dwarfed by the cost of checking validity */ - for (ab = blocks->first; ab; ab = ab->next) { + for (ActKeyBlock *ab = blocks->first; ab; ab = ab->next) { if (actkeyblock_is_valid(ab, keys)) { if (ab->flag & ACTKEYBLOCK_FLAG_MOVING_HOLD) { /* draw "moving hold" long-keyframe block - slightly smaller */ - if (ab->sel) - glColor4fv(sel_mhcol); - else - glColor4fv(unsel_mhcol); - - glRectf(ab->start, ypos - mhsize, ab->end, ypos + mhsize); + immUniformColor4fv(ab->sel ? sel_mhcol : unsel_mhcol); + immRectf(pos_id, ab->start, ypos - smaller_sz, ab->end, ypos + smaller_sz); } else { /* draw standard long-keyframe block */ - if (ab->sel) - glColor4fv(sel_color); - else - glColor4fv(unsel_color); - - glRectf(ab->start, ypos - iconsize, ab->end, ypos + iconsize); + immUniformColor4fv(ab->sel ? sel_color : unsel_color); + immRectf(pos_id, ab->start, ypos - half_icon_sz, ab->end, ypos + half_icon_sz); } } } + immUnbindProgram(); } - /* draw keys */ if (keys) { - for (ak = keys->first; ak; ak = ak->next) { + /* count keys */ + unsigned int key_ct = 0; + for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) { /* optimization: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw * - this might give some improvements, since we current have to flip between view/region matrices */ - if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax) == 0) - continue; - - /* draw using OpenGL - uglier but faster */ - /* NOTE1: a previous version of this didn't work nice for some intel cards - * NOTE2: if we wanted to go back to icons, these are icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; */ - draw_keyframe_shape(ak->cfra, ypos, xscale, iconsize, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha); + if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) + key_ct++; + } + + if (key_ct > 0) { + /* draw keys */ + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + unsigned int outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + GPU_enable_program_point_size(); + immBegin(GWN_PRIM_POINTS, key_ct); + + for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) { + if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) { + draw_keyframe_shape(ak->cfra, ypos, icon_sz, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha, + pos_id, size_id, color_id, outline_color_id); + } + } + + immEnd(); + GPU_disable_program_point_size(); + immUnbindProgram(); } } diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index de0d19f7b05..afbd8e5bd41 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -56,7 +56,6 @@ #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_armature.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_idcode.h" #include "BKE_nla.h" @@ -66,6 +65,9 @@ #include "BKE_key.h" #include "BKE_material.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "ED_anim_api.h" #include "ED_keyframing.h" #include "ED_keyframes_edit.h" @@ -155,7 +157,7 @@ bAction *verify_adt_action(ID *id, short add) /* tag depsgraph to be rebuilt to include time dependency */ /* XXX: we probably should have bmain passed down, but that involves altering too many API's */ - DAG_relations_tag_update(G.main); + DEG_relations_tag_update(G.main); } /* return the action */ @@ -1618,7 +1620,7 @@ static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op)) /* delete F-Curve completely */ if (can_delete) { ANIM_fcurve_delete_from_animdata(NULL, adt, fcu); - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); changed = true; } } @@ -1725,7 +1727,7 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op) else BKE_reportf(op->reports, RPT_ERROR, "No keyframes removed from Object '%s'", id->name + 2); - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } CTX_DATA_END; diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index ad08caba799..da206ac9a64 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -48,9 +48,10 @@ #include "BKE_main.h" #include "BKE_animsys.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "ED_keyframing.h" #include "ED_screen.h" @@ -1049,7 +1050,7 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe Object *ob = (Object *)ksp->id; // XXX: only object transforms? - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); break; } default: diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt index b213aca478f..5348298f57e 100644 --- a/source/blender/editors/armature/CMakeLists.txt +++ b/source/blender/editors/armature/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../gpu ../../makesdna ../../makesrna diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index 2d7a83f20c1..0d114206c6b 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -48,11 +48,12 @@ #include "BKE_constraint.h" #include "BKE_context.h" #include "BKE_deform.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_modifier.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -375,7 +376,7 @@ static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op)) BLI_freelistN(&bones_names); /* since we renamed stuff... */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* copied from #rna_Bone_update_renamed */ /* redraw view */ @@ -425,7 +426,7 @@ static int armature_autoside_names_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* since we renamed stuff... */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 685f8227a47..0705d17882c 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -47,12 +47,15 @@ #include "BKE_animsys.h" #include "BKE_constraint.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -400,12 +403,12 @@ int join_armature_exec(bContext *C, wmOperator *op) } /* Free the old object data */ - ED_base_object_free_and_unlink(bmain, scene, base); + ED_object_base_free_and_unlink(bmain, scene, base->object); } } CTX_DATA_END; - DAG_relations_tag_update(bmain); /* because we removed object(s) */ + DEG_relations_tag_update(bmain); /* because we removed object(s) */ ED_armature_from_edit(arm); ED_armature_edit_free(arm); @@ -579,6 +582,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); Object *oldob, *newob; Base *oldbase, *newbase; @@ -602,14 +606,18 @@ static int separate_armature_exec(bContext *C, wmOperator *op) /* TODO: use context iterators for this? */ CTX_DATA_BEGIN(C, Base *, base, visible_bases) { - if (base->object == obedit) base->flag |= SELECT; - else base->flag &= ~SELECT; + if (base->object == obedit) { + ED_object_base_select(base, BA_SELECT); + } + else { + ED_object_base_select(base, BA_DESELECT); + } } CTX_DATA_END; /* 1) store starting settings and exit editmode */ oldob = obedit; - oldbase = BASACT; + oldbase = sl->basact; oldob->mode &= ~OB_MODE_POSE; //oldbase->flag &= ~OB_POSEMODE; @@ -617,13 +625,13 @@ static int separate_armature_exec(bContext *C, wmOperator *op) ED_armature_edit_free(obedit->data); /* 2) duplicate base */ - newbase = ED_object_add_duplicate(bmain, scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */ - DAG_relations_tag_update(bmain); + newbase = ED_object_add_duplicate(bmain, scene, sl, oldbase, USER_DUP_ARM); /* only duplicate linked armature */ + DEG_relations_tag_update(bmain); newob = newbase->object; - newbase->flag &= ~SELECT; - - + newbase->flag &= ~BASE_SELECTED; + + /* 3) remove bones that shouldn't still be around on both armatures */ separate_armature_bones(oldob, 1); separate_armature_bones(newob, 0); @@ -632,8 +640,8 @@ static int separate_armature_exec(bContext *C, wmOperator *op) /* 4) fix links before depsgraph flushes */ // err... or after? separated_armature_fix_links(oldob, newob); - DAG_id_tag_update(&oldob->id, OB_RECALC_DATA); /* this is the original one */ - DAG_id_tag_update(&newob->id, OB_RECALC_DATA); /* this is the separated one */ + DEG_id_tag_update(&oldob->id, OB_RECALC_DATA); /* this is the original one */ + DEG_id_tag_update(&newob->id, OB_RECALC_DATA); /* this is the separated one */ /* 5) restore original conditions */ diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 07ff7f15ce4..2c3c8ef4541 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -53,6 +53,8 @@ #include "ED_screen.h" #include "ED_view3d.h" +#include "DEG_depsgraph.h" + #include "armature_intern.h" /* utility macros for storing a temp int in the bone (selection flag) */ @@ -98,7 +100,7 @@ void *get_bone_from_selectbuffer( /* Determine what the current bone is */ if (obedit == NULL || base->object != obedit) { /* no singular posemode, so check for correct object */ - if (base->selcol == (hitresult & 0xFFFF)) { + if (base->object->select_color == (hitresult & 0xFFFF)) { bone = get_indexed_bone(base->object, hitresult); if (findunsel) @@ -166,21 +168,23 @@ void *get_bone_from_selectbuffer( /* x and y are mouse coords (area space) */ void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel) { + EvaluationContext eval_ctx; ViewContext vc; rcti rect; unsigned int buffer[MAXPICKBUF]; short hits; - + + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); // rect.xmin = ... mouseco! rect.xmin = rect.xmax = xy[0]; rect.ymin = rect.ymax = xy[1]; - hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); + hits = view3d_opengl_select(&eval_ctx, &vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); if (hits > 0) - return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel, true); + return get_bone_from_selectbuffer(vc.scene, vc.scene_layer->basact, buffer, hits, findunsel, true); return NULL; } @@ -291,7 +295,7 @@ static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits12, const /* does bones and points */ /* note that BONE ROOT only gets drawn for root bones (or without IK) */ static EditBone *get_nearest_editbonepoint( - ViewContext *vc, const int mval[2], + const EvaluationContext *eval_ctx, ViewContext *vc, const int mval[2], ListBase *edbo, bool findunsel, bool use_cycle, int *r_selmask) { bArmature *arm = (bArmature *)vc->obedit->data; @@ -344,7 +348,7 @@ static EditBone *get_nearest_editbonepoint( view3d_opengl_select_cache_begin(); BLI_rcti_init_pt_radius(&rect, mval, 12); - hits12 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode); + hits12 = view3d_opengl_select(eval_ctx, vc, buffer, MAXPICKBUF, &rect, select_mode); if (hits12 == 1) { hits = selectbuffer_ret_hits_12(buffer, hits12); goto cache_end; @@ -354,7 +358,7 @@ static EditBone *get_nearest_editbonepoint( offs = 4 * hits12; BLI_rcti_init_pt_radius(&rect, mval, 5); - hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); + hits5 = view3d_opengl_select(eval_ctx, vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); if (hits5 == 1) { hits = selectbuffer_ret_hits_5(buffer, hits12, hits5); @@ -482,17 +486,19 @@ bool ED_armature_select_pick(bContext *C, const int mval[2], bool extend, bool d { Object *obedit = CTX_data_edit_object(C); bArmature *arm = obedit->data; + EvaluationContext eval_ctx; ViewContext vc; EditBone *nearBone = NULL; int selmask; + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); - + if (BIF_sk_selectStroke(C, mval, extend)) { return true; } - nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, true, true, &selmask); + nearBone = get_nearest_editbonepoint(&eval_ctx, &vc, mval, arm->edbo, true, true, &selmask); if (nearBone) { if (!extend && !deselect && !toggle) { diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index e8d41f722d7..72b4837c1b8 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -43,12 +43,15 @@ #include "BKE_action.h" #include "BKE_armature.h" +#include "BKE_context.h" #include "BKE_deform.h" #include "BKE_object_deform.h" #include "BKE_report.h" #include "BKE_subsurf.h" #include "BKE_modifier.h" +#include "DEG_depsgraph.h" + #include "ED_armature.h" #include "ED_mesh.h" @@ -247,8 +250,9 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i } } -static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, Object *par, - int heat, const bool mirror) +static void add_verts_to_dgroups( + ReportList *reports, const EvaluationContext *eval_ctx, Scene *scene, Object *ob, Object *par, + int heat, const bool mirror) { /* This functions implements the automatic computation of vertex group * weights, either through envelopes or using a heat equilibrium. @@ -372,7 +376,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, if (wpmode) { /* if in weight paint mode, use final verts from derivedmesh */ - DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH); if (dm->foreachMappedVert) { mesh_get_mapped_verts_coords(dm, verts, mesh->totvert); @@ -424,8 +428,9 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, MEM_freeN(verts); } -void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob, Object *par, - const int mode, const bool mirror) +void create_vgroups_from_armature( + ReportList *reports, const EvaluationContext *eval_ctx, Scene *scene, Object *ob, Object *par, + const int mode, const bool mirror) { /* Lets try to create some vertex groups * based on the bones of the parent armature. @@ -451,6 +456,6 @@ void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob, * that are populated with the vertices for which the * bone is closest. */ - add_verts_to_dgroups(reports, scene, ob, par, (mode == ARM_GROUPS_AUTO), mirror); + add_verts_to_dgroups(reports, eval_ctx, scene, ob, par, (mode == ARM_GROUPS_AUTO), mirror); } } diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index a55264bd020..f27c4fdd96f 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -39,11 +39,12 @@ #include "BKE_armature.h" #include "BKE_context.h" #include "BKE_deform.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_main.h" +#include "DEG_depsgraph.h" + #include "ED_armature.h" #include "ED_util.h" @@ -674,7 +675,7 @@ void ED_armature_from_edit(bArmature *arm) } } - DAG_id_tag_update(&arm->id, 0); + DEG_id_tag_update(&arm->id, 0); } void ED_armature_edit_free(struct bArmature *arm) diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index bba486bc65c..1de7b99c6d2 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -33,6 +33,7 @@ #include "BKE_context.h" #include "BKE_sketch.h" +#include "BKE_layer.h" #include "RNA_define.h" #include "RNA_access.h" @@ -49,10 +50,16 @@ #include "ED_transform.h" #include "ED_transform_snap_object_context.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" #include "GPU_select.h" +#include "GPU_matrix.h" +#include "GPU_batch.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" typedef int (*GestureDetectFct)(bContext *, SK_Gesture *, SK_Sketch *); typedef void (*GestureApplyFct)(bContext *, SK_Gesture *, SK_Sketch *); @@ -140,9 +147,8 @@ static RigGraph *TEMPLATE_RIGG = NULL; void BIF_makeListTemplates(const bContext *C) { Object *obedit = CTX_data_edit_object(C); - Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); ToolSettings *ts = CTX_data_tool_settings(C); - Base *base; int index = 0; if (TEMPLATES_HASH != NULL) { @@ -152,9 +158,8 @@ void BIF_makeListTemplates(const bContext *C) TEMPLATES_HASH = BLI_ghash_int_new("makeListTemplates gh"); TEMPLATES_CURRENT = 0; - for (base = FIRSTBASE; base; base = base->next) { - Object *ob = base->object; - + FOREACH_OBJECT(sl, ob) + { if (ob != obedit && ob->type == OB_ARMATURE) { index++; BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob); @@ -164,6 +169,7 @@ void BIF_makeListTemplates(const bContext *C) } } } + FOREACH_OBJECT_END } #if 0 /* UNUSED */ @@ -420,7 +426,6 @@ static void sk_retargetStroke(bContext *C, SK_Stroke *stk) } /**************************************************************/ - static void sk_cancelStroke(SK_Sketch *sketch) { if (sketch->active_stroke != NULL) { @@ -435,17 +440,33 @@ static float sk_clampPointSize(SK_Point *pt, float size) return max_ff(size * pt->size, size / 2); } -static void sk_drawPoint(GLUquadric *quad, SK_Point *pt, float size) +static void sk_drawPoint(SK_Point *pt, float size, float color[4]) { - glTranslate3fv(pt->p); - gluSphere(quad, sk_clampPointSize(pt, size), 8, 8); + Gwn_Batch *batch = NULL; + + gpuTranslate3fv(pt->p); + + gpuPushMatrix(); + + gpuScaleUniform(sk_clampPointSize(pt, size)); + + batch = GPU_batch_preset_sphere(0); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + GWN_batch_uniform_4fv(batch, "color", color); + + GWN_batch_draw(batch); + + gpuPopMatrix(); } -static void sk_drawEdge(GLUquadric *quad, SK_Point *pt0, SK_Point *pt1, float size) +static void sk_drawEdge(SK_Point *pt0, SK_Point *pt1, float size, float color[4]) { - float vec1[3], vec2[3] = {0, 0, 1}, axis[3]; + float vec1[3], vec2[3] = { 0, 0, 1 }, axis[3]; float angle, length; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + sub_v3_v3v3(vec1, pt1->p, pt0->p); length = normalize_v3(vec1); cross_v3_v3v3(axis, vec2, vec1); @@ -454,19 +475,26 @@ static void sk_drawEdge(GLUquadric *quad, SK_Point *pt0, SK_Point *pt1, float si axis[1] = 1; } - angle = angle_normalized_v3v3(vec2, vec1); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(color); - glRotate3fv(angle * (float)(180.0 / M_PI) + 180.0f, axis); + angle = angle_normalized_v3v3(vec2, vec1); + gpuRotate3fv(angle * (float)(180.0 / M_PI) + 180.0f, axis); + imm_draw_cylinder_fill_3d(pos, sk_clampPointSize(pt1, size), sk_clampPointSize(pt0, size), length, 8, 8); - gluCylinder(quad, sk_clampPointSize(pt1, size), sk_clampPointSize(pt0, size), length, 8, 8); + immUnbindProgram(); } -static void sk_drawNormal(GLUquadric *quad, SK_Point *pt, float size, float height) +static void sk_drawNormal(SK_Point *pt, float size, float height) { - float vec2[3] = {0, 0, 1}, axis[3]; + float vec2[3] = { 0, 0, 1 }, axis[3]; float angle; - - glPushMatrix(); + float color[3] = { 0.0f, 1.0f, 1.0f }; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + gpuPushMatrix(); cross_v3_v3v3(axis, vec2, pt->no); @@ -474,41 +502,44 @@ static void sk_drawNormal(GLUquadric *quad, SK_Point *pt, float size, float heig axis[1] = 1; } + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(color); + angle = angle_normalized_v3v3(vec2, pt->no); + gpuRotate3fv(angle * (float)(180.0 / M_PI), axis); - glRotate3fv(angle * (float)(180.0 / M_PI), axis); + imm_draw_cylinder_fill_3d(pos, sk_clampPointSize(pt, size), 0, sk_clampPointSize(pt, height), 10, 2); - glColor3f(0, 1, 1); - gluCylinder(quad, sk_clampPointSize(pt, size), 0, sk_clampPointSize(pt, height), 10, 2); + immUnbindProgram(); - glPopMatrix(); + gpuPopMatrix(); } static void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end) { float rgb[3]; + float zero_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; int i; - GLUquadric *quad = gluNewQuadric(); - gluQuadricNormals(quad, GLU_SMOOTH); if (id != -1) { GPU_select_load_id(id); for (i = 0; i < stk->nb_points; i++) { - glPushMatrix(); + gpuPushMatrix(); - sk_drawPoint(quad, stk->points + i, 0.1); + sk_drawPoint(stk->points + i, 0.1, zero_color); if (i > 0) { - sk_drawEdge(quad, stk->points + i - 1, stk->points + i, 0.1); + sk_drawEdge(stk->points + i - 1, stk->points + i, 0.1, zero_color); } - glPopMatrix(); + gpuPopMatrix(); } } else { - float d_rgb[3] = {1, 1, 1}; + float d_rgb[3] = { 1, 1, 1 }; + float tmp_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; copy_v3_v3(rgb, color); sub_v3_v3(d_rgb, rgb); @@ -517,48 +548,44 @@ static void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int for (i = 0; i < stk->nb_points; i++) { SK_Point *pt = stk->points + i; - glPushMatrix(); + gpuPushMatrix(); if (pt->type == PT_EXACT) { - glColor3f(0, 0, 0); - sk_drawPoint(quad, pt, 0.15); - sk_drawNormal(quad, pt, 0.05, 0.9); + sk_drawPoint(pt, 0.15, zero_color); + sk_drawNormal(pt, 0.05, 0.9); } if (i >= start && i <= end) { - glColor3f(0.3, 0.3, 0.3); + copy_v4_fl4(tmp_color, 0.3f, 0.3f, 0.3f, 1.0f); } else { - glColor3fv(rgb); + copy_v4_fl4(tmp_color, rgb[0], rgb[1], rgb[2], 1.0f); } if (pt->type != PT_EXACT) { - - sk_drawPoint(quad, pt, 0.1); + sk_drawPoint(pt, 0.1, tmp_color); } if (i > 0) { - sk_drawEdge(quad, pt - 1, pt, 0.1); + sk_drawEdge(pt - 1, pt, 0.1, tmp_color); } - glPopMatrix(); + gpuPopMatrix(); add_v3_v3(rgb, d_rgb); } } - gluDeleteQuadric(quad); } static void drawSubdividedStrokeBy(ToolSettings *toolsettings, BArcIterator *iter, NextSubdivisionFunc next_subdividion) { SK_Stroke *stk = ((SK_StrokeIterator *)iter)->stroke; float head[3], tail[3]; + float color[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; int bone_start = 0; int end = iter->length; int index; - GLUquadric *quad = gluNewQuadric(); - gluQuadricNormals(quad, GLU_SMOOTH); iter->head(iter); copy_v3_v3(head, iter->p); @@ -567,22 +594,19 @@ static void drawSubdividedStrokeBy(ToolSettings *toolsettings, BArcIterator *ite while (index != -1) { SK_Point *pt = stk->points + index; - glPushMatrix(); + gpuPushMatrix(); - glColor3f(0, 1, 0); - sk_drawPoint(quad, pt, 0.15); + sk_drawPoint(pt, 0.15, color); - sk_drawNormal(quad, pt, 0.05, 0.9); + sk_drawNormal(pt, 0.05, 0.9); - glPopMatrix(); + gpuPopMatrix(); copy_v3_v3(head, tail); bone_start = index; // start next bone from current index index = next_subdividion(toolsettings, iter, bone_start, end, head, tail); } - - gluDeleteQuadric(quad); } static void sk_drawStrokeSubdivision(ToolSettings *toolsettings, SK_Stroke *stk) @@ -974,7 +998,7 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S * the ideal would be to call this function only at the beginning of the snap operation, * or at the beginning of the operator itself */ struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), 0, + CTX_data_main(C), CTX_data_scene(C), CTX_data_scene_layer(C), CTX_data_engine(C), 0, CTX_wm_region(C), CTX_wm_view3d(C)); float mvalf[2] = {UNPACK2(dd->mval)}; @@ -1900,16 +1924,18 @@ static void sk_applyGesture(bContext *C, SK_Sketch *sketch) static bool sk_selectStroke(bContext *C, SK_Sketch *sketch, const int mval[2], const bool extend) { + EvaluationContext eval_ctx; ViewContext vc; rcti rect; unsigned int buffer[MAXPICKBUF]; short hits; + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); BLI_rcti_init_pt_radius(&rect, mval, 5); - hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); + hits = view3d_opengl_select(&eval_ctx, &vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); if (hits > 0) { int besthitresult = -1; @@ -1975,9 +2001,9 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch, GPU_select_load_id(-1); } else { - float selected_rgb[3] = {1, 0, 0}; - float unselected_rgb[3] = {1, 0.5, 0}; - + float selected_rgb[3] = { 1, 0, 0 }; + float unselected_rgb[3] = { 1, 0.5, 0 }; + float tmp_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; for (stk = sketch->strokes.first; stk; stk = stk->next) { int start = -1; int end = -1; @@ -2001,75 +2027,37 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch, } if (last != NULL) { - GLUquadric *quad = gluNewQuadric(); - gluQuadricNormals(quad, GLU_SMOOTH); - - glPushMatrix(); + gpuPushMatrix(); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); switch (sketch->next_point.mode) { case PT_SNAP: - glColor3f(0, 1, 0); + copy_v4_fl4(tmp_color, 0.0f, 1.0f, 0.0f, 1.0f); break; case PT_PROJECT: - glColor3f(0, 0, 0); + copy_v4_fl4(tmp_color, 0.0f, 0.0f, 0.0f, 1.0f); break; } - sk_drawPoint(quad, &sketch->next_point, 0.1); + sk_drawPoint(&sketch->next_point, 0.1, tmp_color); - glColor4f(selected_rgb[0], selected_rgb[1], selected_rgb[2], 0.3); - - sk_drawEdge(quad, last, &sketch->next_point, 0.1); + copy_v4_fl4(tmp_color, selected_rgb[0], selected_rgb[1], selected_rgb[2], 0.3); + sk_drawEdge(last, &sketch->next_point, 0.1f, tmp_color); glDisable(GL_BLEND); - glPopMatrix(); - - gluDeleteQuadric(quad); + gpuPopMatrix(); } } } -#if 0 - if (BLI_listbase_is_empty(&sketch->depth_peels) == false) { - float colors[8][3] = { - {1, 0, 0}, - {0, 1, 0}, - {0, 0, 1}, - {1, 1, 0}, - {1, 0, 1}, - {0, 1, 1}, - {1, 1, 1}, - {0, 0, 0} - }; - DepthPeel *p; - GLUquadric *quad = gluNewQuadric(); - gluQuadricNormals(quad, GLU_SMOOTH); - - for (p = sketch->depth_peels.first; p; p = p->next) - { - int index = GET_INT_FROM_POINTER(p->ob); - index = (index >> 5) & 7; - - glColor3fv(colors[index]); - glPushMatrix(); - glTranslate3fv(p->p); - gluSphere(quad, 0.02, 8, 8); - glPopMatrix(); - } - - gluDeleteQuadric(quad); - } -#endif - glDisable(GL_DEPTH_TEST); /* only draw gesture in active area */ if (sketch->gesture != NULL /* && area_is_active_area(G.vd->area) */) { - float gesture_rgb[3] = {0, 0.5, 1}; + float gesture_rgb[3] = { 0, 0.5, 1 }; sk_drawStroke(sketch->gesture, -1, gesture_rgb, -1, -1); } } diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index acbf23ecf82..74e29b2e8da 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -43,10 +43,11 @@ #include "BKE_armature.h" #include "BKE_context.h" #include "BKE_deform.h" -#include "BKE_depsgraph.h" #include "BKE_object.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -95,7 +96,8 @@ void ED_armature_enter_posemode(bContext *C, Base *base) case OB_ARMATURE: ob->restore_mode = ob->mode; ob->mode |= OB_MODE_POSE; - + /* Inform all CoW versions that we changed the mode. */ + DEG_id_tag_update_ex(CTX_data_main(C), &ob->id, DEG_TAG_COPY_ON_WRITE); WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL); break; @@ -114,7 +116,10 @@ void ED_armature_exit_posemode(bContext *C, Base *base) ob->restore_mode = ob->mode; ob->mode &= ~OB_MODE_POSE; - + + /* Inform all CoW versions that we changed the mode. */ + DEG_id_tag_update_ex(CTX_data_main(C), &ob->id, DEG_TAG_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); } } @@ -154,8 +159,11 @@ static bool pose_has_protected_selected(Object *ob, short warn) * * To be called from various tools that do incremental updates */ -void ED_pose_recalculate_paths(Scene *scene, Object *ob) +void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob) { + struct Main *bmain = CTX_data_main(C); + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); ListBase targets = {NULL, NULL}; /* set flag to force recalc, then grab the relevant bones to target */ @@ -163,7 +171,7 @@ void ED_pose_recalculate_paths(Scene *scene, Object *ob) animviz_get_object_motionpaths(ob, &targets); /* recalculate paths, then free */ - animviz_calc_motionpaths(scene, &targets); + animviz_calc_motionpaths(&eval_ctx, bmain, scene, &targets); BLI_freelistN(&targets); } @@ -226,7 +234,7 @@ static int pose_calculate_paths_exec(bContext *C, wmOperator *op) /* calculate the bones that now have motionpaths... */ /* TODO: only make for the selected bones? */ - ED_pose_recalculate_paths(scene, ob); + ED_pose_recalculate_paths(C, scene, ob); /* notifiers for updates */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); @@ -282,7 +290,7 @@ static int pose_update_paths_exec(bContext *C, wmOperator *UNUSED(op)) /* calculate the bones that now have motionpaths... */ /* TODO: only make for the selected bones? */ - ED_pose_recalculate_paths(scene, ob); + ED_pose_recalculate_paths(C, scene, ob); /* notifiers for updates */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); @@ -580,7 +588,7 @@ static void pose_copy_menu(Scene *scene) BKE_pose_tag_recalc(bmain, ob->pose); } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations BIF_undo_push("Copy Pose Attributes"); @@ -613,7 +621,7 @@ static int pose_flip_names_exec(bContext *C, wmOperator *UNUSED(op)) BLI_freelistN(&bones_names); /* since we renamed stuff... */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); @@ -660,7 +668,7 @@ static int pose_autoside_names_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* since we renamed stuff... */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); @@ -709,7 +717,7 @@ static int pose_bone_rotmode_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* notifiers and updates */ - DAG_id_tag_update((ID *)ob, OB_RECALC_DATA); + DEG_id_tag_update((ID *)ob, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob); return OPERATOR_FINISHED; @@ -1171,7 +1179,7 @@ static int pose_flip_quats_exec(bContext *C, wmOperator *UNUSED(op)) CTX_DATA_END; /* notifiers and updates */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob); return OPERATOR_FINISHED; diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c index ac38500c841..0dbe3ddaa0a 100644 --- a/source/blender/editors/armature/pose_lib.c +++ b/source/blender/editors/armature/pose_lib.c @@ -46,7 +46,6 @@ #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_armature.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_library.h" @@ -55,6 +54,8 @@ #include "BKE_context.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -1067,6 +1068,9 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData static void poselib_preview_apply(bContext *C, wmOperator *op) { tPoseLib_PreviewData *pld = (tPoseLib_PreviewData *)op->customdata; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); /* only recalc pose (and its dependencies) if pose has changed */ if (pld->redraw == PL_PREVIEW_REDRAWALL) { @@ -1089,9 +1093,9 @@ static void poselib_preview_apply(bContext *C, wmOperator *op) */ // FIXME: shouldn't this use the builtin stuff? if ((pld->arm->flag & ARM_DELAYDEFORM) == 0) - DAG_id_tag_update(&pld->ob->id, OB_RECALC_DATA); /* sets recalc flags */ + DEG_id_tag_update(&pld->ob->id, OB_RECALC_DATA); /* sets recalc flags */ else - BKE_pose_where_is(pld->scene, pld->ob); + BKE_pose_where_is(&eval_ctx, pld->scene, pld->ob); } /* do header print - if interactively previewing */ @@ -1582,6 +1586,9 @@ static void poselib_preview_cleanup(bContext *C, wmOperator *op) bArmature *arm = pld->arm; bAction *act = pld->act; TimeMarker *marker = pld->marker; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); /* redraw the header so that it doesn't show any of our stuff anymore */ ED_area_headerprint(pld->sa, NULL); @@ -1597,9 +1604,9 @@ static void poselib_preview_cleanup(bContext *C, wmOperator *op) * - note: code copied from transform_generics.c -> recalcData() */ if ((arm->flag & ARM_DELAYDEFORM) == 0) - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */ + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */ else - BKE_pose_where_is(scene, ob); + BKE_pose_where_is(&eval_ctx, scene, ob); } else if (pld->state == PL_PREVIEW_CONFIRM) { /* tag poses as appropriate */ @@ -1610,14 +1617,14 @@ static void poselib_preview_cleanup(bContext *C, wmOperator *op) action_set_activemarker(act, marker, NULL); /* Update event for pose and deformation children */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* updates */ if (IS_AUTOKEY_MODE(scene, NORMAL)) { //remake_action_ipos(ob->action); } else - BKE_pose_where_is(scene, ob); + BKE_pose_where_is(&eval_ctx, scene, ob); } /* Request final redraw of the view. */ diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 401f180385d..ba01aab0d00 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -43,10 +43,11 @@ #include "BKE_armature.h" #include "BKE_constraint.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_object.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -122,7 +123,7 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select) * (see rna_Bone_select_update() in rna_armature.c for details) */ if (arm->flag & ARM_HAS_VIZ_DEPS) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } /* send necessary notifiers */ @@ -133,7 +134,7 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select) /* called from editview.c, for mode-less pose selection */ /* assumes scene obact and basact is still on old situation */ bool ED_do_pose_selectbuffer( - Scene *scene, Base *base, const unsigned int *buffer, short hits, + Scene *scene, SceneLayer *sl, Base *base, const unsigned int *buffer, short hits, bool extend, bool deselect, bool toggle, bool do_nearest) { Object *ob = base->object; @@ -145,7 +146,7 @@ bool ED_do_pose_selectbuffer( /* if the bone cannot be affected, don't do anything */ if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) { - Object *ob_act = OBACT; + Object *ob_act = OBACT(sl); bArmature *arm = ob->data; /* since we do unified select, we don't shift+select a bone if the @@ -197,7 +198,7 @@ bool ED_do_pose_selectbuffer( if (ob_act->mode & OB_MODE_WEIGHT_PAINT) { if (nearBone == arm->act_bone) { ED_vgroup_select_by_name(ob_act, nearBone->name); - DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob_act->id, OB_RECALC_DATA); } } /* if there are some dependencies for visualizing armature state @@ -207,7 +208,7 @@ bool ED_do_pose_selectbuffer( /* NOTE: ob not ob_act here is intentional - it's the source of the * bones being selected [T37247] */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } } @@ -314,7 +315,7 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve if (arm->flag & ARM_HAS_VIZ_DEPS) { /* mask modifier ('armature' mode), etc. */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } return OPERATOR_FINISHED; @@ -370,7 +371,7 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op) /* weightpaint or mask modifiers need depsgraph updates */ if (multipaint || (arm->flag & ARM_HAS_VIZ_DEPS)) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } return OPERATOR_FINISHED; @@ -422,7 +423,7 @@ static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op)) if (arm->flag & ARM_HAS_VIZ_DEPS) { /* mask modifier ('armature' mode), etc. */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } return OPERATOR_FINISHED; @@ -489,7 +490,7 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op if (arm->flag & ARM_HAS_VIZ_DEPS) { /* mask modifier ('armature' mode), etc. */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } return OPERATOR_FINISHED; @@ -583,7 +584,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) if (arm->flag & ARM_HAS_VIZ_DEPS) { /* mask modifier ('armature' mode), etc. */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } return OPERATOR_FINISHED; @@ -828,7 +829,7 @@ static int pose_select_grouped_exec(bContext *C, wmOperator *op) if (arm->flag & ARM_HAS_VIZ_DEPS) { /* mask modifier ('armature' mode), etc. */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } /* report done status */ @@ -921,7 +922,7 @@ static int pose_select_mirror_exec(bContext *C, wmOperator *op) /* in weightpaint we select the associated vertex group too */ if (ob_act->mode & OB_MODE_WEIGHT_PAINT) { ED_vgroup_select_by_name(ob_act, pchan_mirror_act->name); - DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob_act->id, OB_RECALC_DATA); } } diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 3707b914ecb..18d6408f026 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -45,13 +45,14 @@ #include "BKE_blender_copybuffer.h" #include "BKE_context.h" #include "BKE_deform.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -70,9 +71,12 @@ /* Pose Apply */ /* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */ -static void applyarmature_fix_boneparents(Scene *scene, Object *armob) +static void applyarmature_fix_boneparents(const bContext *C, Scene *scene, Object *armob) { Object workob, *ob; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); /* go through all objects in database */ for (ob = G.main->object.first; ob; ob = ob->id.next) { @@ -83,7 +87,7 @@ static void applyarmature_fix_boneparents(Scene *scene, Object *armob) */ BKE_object_apply_mat4(ob, ob->obmat, false, false); - BKE_object_workob_calc_parent(scene, ob, &workob); + BKE_object_workob_calc_parent(&eval_ctx, scene, ob, &workob); invert_m4_m4(ob->parentinv, workob.obmat); } } @@ -94,10 +98,13 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object + EvaluationContext eval_ctx; bArmature *arm = BKE_armature_from_object(ob); bPose *pose; bPoseChannel *pchan; EditBone *curbone; + + CTX_data_eval_ctx(C, &eval_ctx); /* don't check if editmode (should be done by caller) */ if (ob->type != OB_ARMATURE) @@ -167,10 +174,10 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op) ED_armature_edit_free(arm); /* flush positions of posebones */ - BKE_pose_where_is(scene, ob); + BKE_pose_where_is(&eval_ctx, scene, ob); /* fix parenting of objects which are bone-parented */ - applyarmature_fix_boneparents(scene, ob); + applyarmature_fix_boneparents(C, scene, ob); /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); @@ -225,7 +232,7 @@ static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op)) } CTX_DATA_END; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); @@ -543,11 +550,11 @@ static int pose_paste_exec(bContext *C, wmOperator *op) BKE_main_free(tmp_bmain); /* Update event for pose and deformation children. */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* Recalculate paths if any of the bones have paths... */ if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { - ED_pose_recalculate_paths(scene, ob); + ED_pose_recalculate_paths(C, scene, ob); } /* Notifiers for updates, */ @@ -774,10 +781,10 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op, /* now recalculate paths */ if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) - ED_pose_recalculate_paths(scene, ob); + ED_pose_recalculate_paths(C, scene, ob); } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob); @@ -924,7 +931,7 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op) } /* notifiers and updates */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob); return OPERATOR_FINISHED; diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c index f80afdd169e..acb9363cf10 100644 --- a/source/blender/editors/armature/pose_utils.c +++ b/source/blender/editors/armature/pose_utils.c @@ -39,11 +39,12 @@ #include "BKE_action.h" #include "BKE_armature.h" -#include "BKE_depsgraph.h" #include "BKE_idprop.h" #include "BKE_context.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "WM_api.h" @@ -183,15 +184,18 @@ void poseAnim_mapping_free(ListBase *pfLinks) void poseAnim_mapping_refresh(bContext *C, Scene *scene, Object *ob) { bArmature *arm = (bArmature *)ob->data; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); /* old optimize trick... this enforces to bypass the depgraph * - note: code copied from transform_generics.c -> recalcData() */ /* FIXME: shouldn't this use the builtin stuff? */ if ((arm->flag & ARM_DELAYDEFORM) == 0) - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */ + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */ else - BKE_pose_where_is(scene, ob); + BKE_pose_where_is(&eval_ctx, scene, ob); /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); @@ -266,7 +270,7 @@ void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, Object *ob, ListBa */ if (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) { //ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear - ED_pose_recalculate_paths(scene, ob); + ED_pose_recalculate_paths(C, scene, ob); } } } diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c index 2bcf3099104..0eb44085bae 100644 --- a/source/blender/editors/armature/reeb.c +++ b/source/blender/editors/armature/reeb.c @@ -3199,237 +3199,3 @@ ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C) return rg; #endif } - -#if 0 - -ReebGraph *BIF_ReebGraphFromEditMesh(void) -{ - EditMesh *em = G.editMesh; - EdgeIndex indexed_edges; - VertexData *data; - ReebGraph *rg = NULL; - - if (em == NULL) - return NULL; - - data = allocVertexData(em); - - buildIndexedEdges(em, &indexed_edges); - - if (weightFromDistance(em, &indexed_edges) == 0) - { - error("No selected vertex\n"); - freeEdgeIndex(&indexed_edges); - freeEdgeIndex(&indexed_edges); - return NULL; - } - - renormalizeWeight(em, 1.0f); - - if (G.scene->toolsettings->skgen_options & SKGEN_HARMONIC) - { - weightToHarmonic(em, &indexed_edges); - } - - freeEdgeIndex(&indexed_edges); - -#ifdef DEBUG_REEB -// weightToVCol(em, 1); -#endif - - rg = generateReebGraph(em, G.scene->toolsettings->skgen_resolution); - - - /* Remove arcs without embedding */ - filterNullReebGraph(rg); - - /* smart filter and loop filter on basic level */ - filterGraph(rg, SKGEN_FILTER_SMART, 0, 0); - - repositionNodes(rg); - - /* Filtering might have created degree 2 nodes, so remove them */ - removeNormalNodes(rg); - - joinSubgraphs(rg, 1.0); - - BLI_buildAdjacencyList((BGraph *)rg); - - /* calc length before copy, so we have same length on all levels */ - BLI_calcGraphLength((BGraph *)rg); - - filterGraph(rg, G.scene->toolsettings->skgen_options, G.scene->toolsettings->skgen_threshold_internal, G.scene->toolsettings->skgen_threshold_external); - - finalizeGraph(rg, G.scene->toolsettings->skgen_postpro_passes, G.scene->toolsettings->skgen_postpro); - -#ifdef DEBUG_REEB - REEB_exportGraph(rg, -1); - - arcToVCol(rg, em, 0); - //angleToVCol(em, 1); -#endif - - printf("DONE\n"); - printf("%i subgraphs\n", BLI_FlagSubgraphs((BGraph *)rg)); - - MEM_freeN(data); - - return rg; -} - -void BIF_GlobalReebFree() -{ - if (GLOBAL_RG != NULL) - { - REEB_freeGraph(GLOBAL_RG); - GLOBAL_RG = NULL; - } -} - -void BIF_GlobalReebGraphFromEditMesh(void) -{ - ReebGraph *rg; - - BIF_GlobalReebFree(); - - rg = BIF_ReebGraphMultiFromEditMesh(); - - GLOBAL_RG = rg; -} - -void REEB_draw() -{ - ReebGraph *rg; - ReebArc *arc; - int i = 0; - - if (GLOBAL_RG == NULL) - { - return; - } - - if (GLOBAL_RG->link_up && G.scene->toolsettings->skgen_options & SKGEN_DISP_ORIG) - { - for (rg = GLOBAL_RG; rg->link_up; rg = rg->link_up) ; - } - else { - i = G.scene->toolsettings->skgen_multi_level; - - for (rg = GLOBAL_RG; rg->multi_level != i && rg->link_up; rg = rg->link_up) ; - } - - glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE)); - - glDisable(GL_DEPTH_TEST); - for (arc = rg->arcs.first; arc; arc = arc->next, i++) - { - ReebArcIterator arc_iter; - BArcIterator *iter = (BArcIterator *)&arc_iter; - float vec[3]; - char text[128]; - char *s = text; - - glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE) + 2); - glColor3f(0, 0, 0); - glBegin(GL_LINE_STRIP); - glVertex3fv(arc->head->p); - - if (arc->bcount) - { - initArcIterator(iter, arc, arc->head); - for (IT_next(iter); IT_stopped(iter) == 0; IT_next(iter)) - { - glVertex3fv(iter->p); - } - } - - glVertex3fv(arc->tail->p); - glEnd(); - - glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE)); - - if (arc->symmetry_level == 1) - { - glColor3f(1, 0, 0); - } - else if (arc->symmetry_flag == SYM_SIDE_POSITIVE || arc->symmetry_flag == SYM_SIDE_NEGATIVE) - { - glColor3f(1, 0.5f, 0); - } - else if (arc->symmetry_flag >= SYM_SIDE_RADIAL) - { - glColor3f(0.5f, 1, 0); - } - else { - glColor3f(1, 1, 0); - } - glBegin(GL_LINE_STRIP); - glVertex3fv(arc->head->p); - - if (arc->bcount) - { - initArcIterator(iter, arc, arc->head); - for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter)) - { - glVertex3fv(iter->p); - } - } - - glVertex3fv(arc->tail->p); - glEnd(); - - - if (G.scene->toolsettings->skgen_options & SKGEN_DISP_EMBED) - { - glColor3f(1, 1, 1); - glBegin(GL_POINTS); - glVertex3fv(arc->head->p); - glVertex3fv(arc->tail->p); - - glColor3f(0.5f, 0.5f, 1); - if (arc->bcount) - { - initArcIterator(iter, arc, arc->head); - for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter)) - { - glVertex3fv(iter->p); - } - } - glEnd(); - } - - if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX) - { - mid_v3_v3v3(vec, arc->head->p, arc->tail->p); - s += sprintf(s, "%i (%i-%i-%i) ", i, arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group); - - if (G.scene->toolsettings->skgen_options & SKGEN_DISP_WEIGHT) - { - s += sprintf(s, "w:%0.3f ", arc->tail->weight - arc->head->weight); - } - - if (G.scene->toolsettings->skgen_options & SKGEN_DISP_LENGTH) - { - s += sprintf(s, "l:%0.3f", arc->length); - } - - glColor3f(0, 1, 0); - glRasterPos3fv(vec); - BMF_DrawString(G.fonts, text); - } - - if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX) - { - sprintf(text, " %i", arc->head->index); - glRasterPos3fv(arc->head->p); - BMF_DrawString(G.fonts, text); - - sprintf(text, " %i", arc->tail->index); - glRasterPos3fv(arc->tail->p); - BMF_DrawString(G.fonts, text); - } - } - glEnable(GL_DEPTH_TEST); -} - -#endif diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt index 2f5b2ab6e87..ae5c0a13ced 100644 --- a/source/blender/editors/curve/CMakeLists.txt +++ b/source/blender/editors/curve/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../gpu ../../makesdna ../../makesrna diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index fc363475608..7666fc15209 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -45,11 +45,11 @@ #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_report.h" @@ -57,6 +57,9 @@ #include "BKE_action.h" #include "BKE_modifier.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "WM_api.h" #include "WM_types.h" @@ -1285,6 +1288,7 @@ static int separate_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *oldob, *newob; Base *oldbase, *newbase; Curve *oldcu, *newcu; @@ -1312,8 +1316,8 @@ static int separate_exec(bContext *C, wmOperator *op) } /* 2. duplicate the object and data */ - newbase = ED_object_add_duplicate(bmain, scene, oldbase, 0); /* 0 = fully linked */ - DAG_relations_tag_update(bmain); + newbase = ED_object_add_duplicate(bmain, scene, sl, oldbase, 0); /* 0 = fully linked */ + DEG_relations_tag_update(bmain); newob = newbase->object; newcu = newob->data = BKE_curve_copy(bmain, oldcu); @@ -1332,8 +1336,8 @@ static int separate_exec(bContext *C, wmOperator *op) ED_curve_editnurb_free(newob); curve_delete_segments(oldob, true); - DAG_id_tag_update(&oldob->id, OB_RECALC_DATA); /* this is the original one */ - DAG_id_tag_update(&newob->id, OB_RECALC_DATA); /* this is the separated one */ + DEG_id_tag_update(&oldob->id, OB_RECALC_DATA); /* this is the original one */ + DEG_id_tag_update(&newob->id, OB_RECALC_DATA); /* this is the separated one */ WM_event_add_notifier(C, NC_GEOM | ND_DATA, oldob->data); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob); @@ -1381,7 +1385,7 @@ static int curve_split_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); } else { BKE_report(op->reports, RPT_ERROR, "Cannot split current selection"); @@ -2327,7 +2331,7 @@ static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) if (ED_curve_updateAnimPaths(obedit->data)) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -2375,7 +2379,7 @@ static int set_goal_weight_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -2428,7 +2432,7 @@ static int set_radius_exec(bContext *C, wmOperator *op) } WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -2580,7 +2584,7 @@ static int smooth_exec(bContext *C, wmOperator *UNUSED(op)) } WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -2771,7 +2775,7 @@ static int curve_smooth_weight_exec(bContext *C, wmOperator *UNUSED(op)) curve_smooth_value(editnurb, offsetof(BezTriple, weight), offsetof(BPoint, weight)); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -2799,7 +2803,7 @@ static int curve_smooth_radius_exec(bContext *C, wmOperator *UNUSED(op)) curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius)); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -2827,7 +2831,7 @@ static int curve_smooth_tilt_exec(bContext *C, wmOperator *UNUSED(op)) curve_smooth_value(editnurb, offsetof(BezTriple, alfa), offsetof(BPoint, alfa)); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -2899,7 +2903,7 @@ static int hide_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(obedit->data); @@ -2962,7 +2966,7 @@ static int reveal_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -3383,7 +3387,7 @@ static int subdivide_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -3578,7 +3582,7 @@ static int set_spline_type_exec(bContext *C, wmOperator *op) if (ED_curve_updateAnimPaths(obedit->data)) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); if (changed_size) { @@ -3632,7 +3636,7 @@ static int set_handle_type_exec(bContext *C, wmOperator *op) BKE_nurbList_handles_set(editnurb, RNA_enum_get(op->ptr, "type")); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -3677,7 +3681,7 @@ static int curve_normals_make_consistent_exec(bContext *C, wmOperator *op) BKE_nurbList_handles_recalculate(editnurb, calc_length, SELECT); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -4065,7 +4069,7 @@ static int merge_nurb(bContext *C, wmOperator *op) BKE_curve_nurb_active_set(obedit->data, NULL); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -4272,7 +4276,7 @@ static int make_segment_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -4516,7 +4520,7 @@ static int spin_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -4971,7 +4975,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) } WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -5016,7 +5020,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) const float mval[2] = {UNPACK2(event->mval)}; struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), vc.scene, 0, + CTX_data_main(C), vc.scene, vc.scene_layer, vc.engine, 0, vc.ar, vc.v3d); ED_transform_snap_object_project_view3d_mixed( @@ -5126,7 +5130,7 @@ static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op)) } WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); } return OPERATOR_FINISHED; @@ -5225,7 +5229,7 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op) } WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -5743,7 +5747,7 @@ static int curve_delete_exec(bContext *C, wmOperator *op) if (ED_curve_updateAnimPaths(obedit->data)) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return retval; } @@ -5887,7 +5891,7 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) if (ED_curve_updateAnimPaths(obedit->data)) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); } return OPERATOR_FINISHED; @@ -5963,7 +5967,7 @@ static int curve_decimate_exec(bContext *C, wmOperator *op) } WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); } return OPERATOR_FINISHED; @@ -6008,7 +6012,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) } WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -6122,7 +6126,7 @@ int join_curve_exec(bContext *C, wmOperator *op) } } - ED_base_object_free_and_unlink(bmain, scene, base); + ED_object_base_free_and_unlink(bmain, scene, base->object); } } } @@ -6134,9 +6138,9 @@ int join_curve_exec(bContext *C, wmOperator *op) /* Account for mixed 2D/3D curves when joining */ BKE_curve_curve_dimension_update(cu); - DAG_relations_tag_update(bmain); // because we removed object(s), call before editmode! + DEG_relations_tag_update(bmain); // because we removed object(s), call before editmode! - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); @@ -6176,7 +6180,7 @@ static int clear_tilt_exec(bContext *C, wmOperator *UNUSED(op)) } WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; } @@ -6354,12 +6358,15 @@ static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); Object *object = CTX_data_active_object(C); + EvaluationContext eval_ctx; Curve *curve = (Curve *) object->data; float min[3], max[3], size[3], loc[3]; int a; + CTX_data_eval_ctx(C, &eval_ctx); + if (object->curve_cache == NULL) { - BKE_displist_make_curveTypes(scene, object, false); + BKE_displist_make_curveTypes(&eval_ctx, scene, object, false); } INIT_MINMAX(min, max); diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index cc8e272d4f7..281f6c3c22e 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -42,9 +42,10 @@ #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_library.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "WM_api.h" @@ -502,7 +503,7 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) cu->flag |= CU_PATH | CU_3D; } else { - DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + DEG_id_tag_update(&obedit->id, OB_RECALC_DATA); } } else { /* adding surface */ @@ -512,7 +513,7 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) newob = true; } else { - DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + DEG_id_tag_update(&obedit->id, OB_RECALC_DATA); } } diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index 4602945d11c..a1b73a54e3d 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -33,10 +33,11 @@ #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -46,7 +47,11 @@ #include "ED_curve.h" #include "BIF_gl.h" -#include "BIF_glutil.h" + +#include "GPU_batch.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" #include "curve_intern.h" @@ -128,7 +133,6 @@ struct CurveDrawData { } prev; ViewContext vc; - bglMats mats; enum { CURVE_DRAW_IDLE = 0, CURVE_DRAW_PAINTING = 1, @@ -214,7 +218,7 @@ static bool stroke_elem_project( { const double depth = (double)ED_view3d_depth_read_cached(&cdd->vc, mval_i); if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) { - if (ED_view3d_depth_unproject(ar, &cdd->mats, mval_i, depth, r_location_world)) { + if (ED_view3d_depth_unproject(ar, mval_i, depth, r_location_world)) { is_location_world_set = true; if (r_normal_world) { zero_v3(r_normal_world); @@ -223,7 +227,7 @@ static bool stroke_elem_project( if (surface_offset != 0.0f) { const float offset = cdd->project.use_surface_offset_absolute ? 1.0f : radius; float normal[3]; - if (ED_view3d_depth_read_cached_normal(&cdd->vc, &cdd->mats, mval_i, normal)) { + if (ED_view3d_depth_read_cached_normal(&cdd->vc, mval_i, normal)) { madd_v3_v3fl(r_location_world, normal, offset * surface_offset); if (r_normal_world) { copy_v3_v3(r_normal_world, normal); @@ -369,39 +373,43 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS Object *obedit = cdd->vc.obedit; Curve *cu = obedit->data; - UI_ThemeColor(TH_WIRE); - if (cu->ext2 > 0.0f) { - GLUquadricObj *qobj = gluNewQuadric(); - - gluQuadricDrawStyle(qobj, GLU_FILL); - BLI_mempool_iter iter; const struct StrokeElem *selem; const float location_zero[3] = {0}; const float *location_prev = location_zero; + float color[3]; + UI_GetThemeColor3fv(TH_WIRE, color); + + Gwn_Batch *sphere = GPU_batch_preset_sphere(0); + GWN_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR); + GWN_batch_uniform_3fv(sphere, "color", color); + /* scale to edit-mode space */ - glPushMatrix(); - glMultMatrixf(obedit->obmat); + gpuPushMatrix(); + gpuMultMatrix(obedit->obmat); BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) { - glTranslatef( + gpuTranslate3f( selem->location_local[0] - location_prev[0], selem->location_local[1] - location_prev[1], selem->location_local[2] - location_prev[2]); location_prev = selem->location_local; + const float radius = stroke_elem_radius(cdd, selem); - gluSphere(qobj, radius, 12, 8); + + gpuPushMatrix(); + gpuScaleUniform(radius); + GWN_batch_draw(sphere); + gpuPopMatrix(); location_prev = selem->location_local; } - glPopMatrix(); - - gluDeleteQuadric(qobj); + gpuPopMatrix(); } if (stroke_len > 1) { @@ -418,30 +426,45 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS } { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, coord_array); - - cpack(0x0); + imm_cpack(0x0); + immBegin(GWN_PRIM_LINE_STRIP, stroke_len); glLineWidth(3.0f); - glDrawArrays(GL_LINE_STRIP, 0, stroke_len); - if (v3d->zbuf) + if (v3d->zbuf) { glDisable(GL_DEPTH_TEST); + } + + for (int i = 0; i < stroke_len; i++) { + immVertex3fv(pos, coord_array[i]); + } + + immEnd(); - cpack(0xffffffff); + imm_cpack(0xffffffff); + immBegin(GWN_PRIM_LINE_STRIP, stroke_len); glLineWidth(1.0f); - glDrawArrays(GL_LINE_STRIP, 0, stroke_len); - if (v3d->zbuf) - glEnable(GL_DEPTH_TEST); + for (int i = 0; i < stroke_len; i++) { + immVertex3fv(pos, coord_array[i]); + } - glDisableClientState(GL_VERTEX_ARRAY); + immEnd(); + + if (v3d->zbuf) { + glEnable(GL_DEPTH_TEST); + } glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); + + immUnbindProgram(); } MEM_freeN(coord_array); @@ -531,7 +554,7 @@ static void curve_draw_event_add_first(wmOperator *op, const wmEvent *event) CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW, CURVE_PAINT_SURFACE_PLANE_NORMAL_SURFACE)) { - if (ED_view3d_depth_read_cached_normal(&cdd->vc, &cdd->mats, event->mval, normal)) { + if (ED_view3d_depth_read_cached_normal(&cdd->vc, event->mval, normal)) { if (cps->surface_plane == CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW) { float cross_a[3], cross_b[3]; cross_v3_v3v3(cross_a, rv3d->viewinv[2], normal); @@ -589,7 +612,9 @@ static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke) } } else { + cdd->vc.depsgraph = CTX_data_depsgraph(C); cdd->vc.scene = CTX_data_scene(C); + cdd->vc.scene_layer = CTX_data_scene_layer(C); cdd->vc.obedit = CTX_data_edit_object(C); } @@ -1011,7 +1036,7 @@ static int curve_draw_exec(bContext *C, wmOperator *op) cu->actvert = nu->pntsu - 1; WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); curve_draw_exit(op); @@ -1066,12 +1091,13 @@ static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event) if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) && (v3d->drawtype > OB_WIRE)) { - view3d_get_transformation(cdd->vc.ar, cdd->vc.rv3d, NULL, &cdd->mats); + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); /* needed or else the draw matrix can be incorrect */ view3d_operator_needs_opengl(C); - ED_view3d_autodist_init(cdd->vc.scene, cdd->vc.ar, cdd->vc.v3d, 0); + ED_view3d_autodist_init(&eval_ctx, cdd->vc.depsgraph, cdd->vc.ar, cdd->vc.v3d, 0); if (cdd->vc.rv3d->depths) { cdd->vc.rv3d->depths->damaged = true; diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 4c5642493fa..f5a0b225974 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -49,13 +49,14 @@ #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_font.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -254,7 +255,7 @@ static void text_update_edited(bContext *C, Object *obedit, int mode) /* run update first since it can move the cursor */ if (mode == FO_EDIT) { /* re-tesselllate */ - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); } else { /* depsgraph runs above, but since we're not tagging for update, call direct */ @@ -273,6 +274,8 @@ static void text_update_edited(bContext *C, Object *obedit, int mode) } } + BKE_curve_batch_cache_dirty(cu, BKE_CURVE_BATCH_DIRTY_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); } @@ -420,6 +423,8 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + EvaluationContext eval_ctx; Curve *cu; Object *obedit; Base *base; @@ -429,13 +434,15 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const int a; float rot[3] = {0.f, 0.f, 0.f}; - obedit = BKE_object_add(bmain, scene, OB_FONT, NULL); - base = scene->basact; + CTX_data_eval_ctx(C, &eval_ctx); + + obedit = BKE_object_add(bmain, scene, sl, OB_FONT, NULL); + base = sl->basact; /* seems to assume view align ? TODO - look into this, could be an operator option */ ED_object_base_init_transform(C, base, NULL, rot); - BKE_object_where_is_calc(scene, obedit); + BKE_object_where_is_calc(&eval_ctx, scene, obedit); add_v3_v3(obedit->loc, offset); @@ -582,7 +589,7 @@ static int set_style(bContext *C, const int style, const bool clear) ef->textbufinfo[i].flag |= style; } - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt index 3d5317b2ebd..587c25031ab 100644 --- a/source/blender/editors/gpencil/CMakeLists.txt +++ b/source/blender/editors/gpencil/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../imbuf ../../gpu ../../makesdna diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 100e2dc8295..5d38ab2340a 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -60,9 +60,11 @@ #include "WM_api.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_immediate.h" +#include "GPU_draw.h" + #include "ED_gpencil.h" #include "ED_screen.h" #include "ED_view3d.h" @@ -92,99 +94,194 @@ typedef enum eDrawStrokeFlags { /* thickness above which we should use special drawing */ +#if 0 #define GP_DRAWTHICKNESS_SPECIAL 3 +#endif + +/* conversion utility (float --> normalized unsigned byte) */ +#define F2UB(x) (unsigned char)(255.0f * x) /* ----- Tool Buffer Drawing ------ */ -/* helper function to set color of buffer point */ -static void gp_set_tpoint_color(tGPspoint *pt, float ink[4]) +/* helper functions to set color of buffer point */ + +static void gp_set_tpoint_varying_color(const tGPspoint *pt, const float ink[4], unsigned attrib_id) { float alpha = ink[3] * pt->strength; CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f); - glColor4f(ink[0], ink[1], ink[2], alpha); + immAttrib4ub(attrib_id, F2UB(ink[0]), F2UB(ink[1]), F2UB(ink[2]), F2UB(alpha)); } -/* helper function to set color of point */ -static void gp_set_point_color(bGPDspoint *pt, float ink[4]) +static void gp_set_point_uniform_color(const bGPDspoint *pt, const float ink[4]) { float alpha = ink[3] * pt->strength; CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f); - glColor4f(ink[0], ink[1], ink[2], alpha); + immUniformColor3fvAlpha(ink, alpha); } -/* helper function to set color and point */ -static void gp_set_color_and_tpoint(tGPspoint *pt, float ink[4]) +static void gp_set_point_varying_color(const bGPDspoint *pt, const float ink[4], unsigned attrib_id) { - gp_set_tpoint_color(pt, ink); - glVertex2iv(&pt->x); + float alpha = ink[3] * pt->strength; + CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f); + immAttrib4ub(attrib_id, F2UB(ink[0]), F2UB(ink[1]), F2UB(ink[2]), F2UB(alpha)); +} + +/* draw fills for buffer stroke */ +static void gp_draw_stroke_buffer_fill(const tGPspoint *points, int totpoints, float ink[4]) +{ + if (totpoints < 3) { + return; + } + int tot_triangles = totpoints - 2; + /* allocate memory for temporary areas */ + unsigned int(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * tot_triangles, "GP Stroke buffer temp triangulation"); + float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * totpoints, "GP Stroke buffer temp 2d points"); + + /* Convert points to array and triangulate + * Here a cache is not used because while drawing the information changes all the time, so the cache + * would be recalculated constantly, so it is better to do direct calculation for each function call + */ + for (int i = 0; i < totpoints; i++) { + const tGPspoint *pt = &points[i]; + points2d[i][0] = pt->x; + points2d[i][1] = pt->y; + } + BLI_polyfill_calc((const float(*)[2])points2d, (unsigned int)totpoints, 0, (unsigned int(*)[3])tmp_triangles); + + /* draw triangulation data */ + if (tot_triangles > 0) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + + /* Draw all triangles for filling the polygon */ + immBegin(GWN_PRIM_TRIS, tot_triangles * 3); + /* TODO: use batch instead of immediate mode, to share vertices */ + + const tGPspoint *pt; + for (int i = 0; i < tot_triangles; i++) { + /* vertex 1 */ + pt = &points[tmp_triangles[i][0]]; + gp_set_tpoint_varying_color(pt, ink, color); + immVertex2iv(pos, &pt->x); + /* vertex 2 */ + pt = &points[tmp_triangles[i][1]]; + gp_set_tpoint_varying_color(pt, ink, color); + immVertex2iv(pos, &pt->x); + /* vertex 3 */ + pt = &points[tmp_triangles[i][2]]; + gp_set_tpoint_varying_color(pt, ink, color); + immVertex2iv(pos, &pt->x); + } + + immEnd(); + immUnbindProgram(); + } + + /* clear memory */ + if (tmp_triangles) { + MEM_freeN(tmp_triangles); + } + if (points2d) { + MEM_freeN(points2d); + } } /* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */ -static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickness, - short dflag, short sflag, float ink[4]) +static void gp_draw_stroke_buffer(const tGPspoint *points, int totpoints, short thickness, + short dflag, short sflag, float ink[4], float fill_ink[4]) { - tGPspoint *pt; - int i; - + int draw_points = 0; + /* error checking */ if ((points == NULL) || (totpoints <= 0)) return; - + /* check if buffer can be drawn */ if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D)) return; - + + if (sflag & GP_STROKE_ERASER) { + /* don't draw stroke at all! */ + return; + } + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + const tGPspoint *pt = points; + if (totpoints == 1) { /* if drawing a single point, draw it larger */ glPointSize((float)(thickness + 2) * points->pressure); - glBegin(GL_POINTS); - - gp_set_color_and_tpoint(points, ink); - glEnd(); - } - else if (sflag & GP_STROKE_ERASER) { - /* don't draw stroke at all! */ + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); + immBegin(GWN_PRIM_POINTS, 1); + gp_set_tpoint_varying_color(pt, ink, color); + immVertex2iv(pos, &pt->x); } else { float oldpressure = points[0].pressure; - + /* draw stroke curve */ - if (G.debug & G_DEBUG) setlinestyle(2); - glLineWidth(max_ff(oldpressure * thickness, 1.0)); - glBegin(GL_LINE_STRIP); - - for (i = 0, pt = points; i < totpoints && pt; i++, pt++) { + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints); + + /* TODO: implement this with a geometry shader to draw one continuous tapered stroke */ + + for (int i = 0; i < totpoints; i++, pt++) { /* if there was a significant pressure change, stop the curve, change the thickness of the stroke, * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP) */ if (fabsf(pt->pressure - oldpressure) > 0.2f) { - glEnd(); + /* need to have 2 points to avoid immEnd assert error */ + if (draw_points < 2) { + gp_set_tpoint_varying_color(pt - 1, ink, color); + immVertex2iv(pos, &(pt - 1)->x); + } + + immEnd(); + draw_points = 0; + glLineWidth(max_ff(pt->pressure * thickness, 1.0f)); - glBegin(GL_LINE_STRIP); - + immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints - i + 1); + /* need to roll-back one point to ensure that there are no gaps in the stroke */ if (i != 0) { - gp_set_color_and_tpoint((pt - 1), ink); + gp_set_tpoint_varying_color(pt - 1, ink, color); + immVertex2iv(pos, &(pt - 1)->x); + ++draw_points; } - - /* now the point we want... */ - gp_set_color_and_tpoint(pt, ink); - - oldpressure = pt->pressure; - } - else { - gp_set_color_and_tpoint(pt, ink); + + oldpressure = pt->pressure; /* reset our threshold */ } + + /* now the point we want */ + gp_set_tpoint_varying_color(pt, ink, color); + immVertex2iv(pos, &pt->x); + ++draw_points; + } + /* need to have 2 points to avoid immEnd assert error */ + if (draw_points < 2) { + gp_set_tpoint_varying_color(pt - 1, ink, color); + immVertex2iv(pos, &(pt - 1)->x); } - glEnd(); + } + + immEnd(); + immUnbindProgram(); - if (G.debug & G_DEBUG) setlinestyle(0); + // draw fill + if (fill_ink[3] > GPENCIL_ALPHA_OPACITY_THRESH) { + gp_draw_stroke_buffer_fill(points, totpoints, fill_ink); } } /* --------- 2D Stroke Drawing Helpers --------- */ /* change in parameter list */ -static void gp_calc_2d_stroke_fxy(float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2]) +static void gp_calc_2d_stroke_fxy(const float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2]) { if (sflag & GP_STROKE_2DSPACE) { r_co[0] = pt[0]; @@ -210,203 +307,141 @@ static void gp_calc_2d_stroke_fxy(float pt[3], short sflag, int offsx, int offsy /* draw a 2D buffer stroke in "volumetric" style * NOTE: the stroke buffer doesn't have any coordinate offsets/transforms */ -static void gp_draw_stroke_volumetric_buffer(tGPspoint *points, int totpoints, short thickness, - short dflag, short UNUSED(sflag), float ink[4]) +static void gp_draw_stroke_volumetric_buffer(const tGPspoint *points, int totpoints, short thickness, + short dflag, const float ink[4]) { - GLUquadricObj *qobj = gluNewQuadric(); - float modelview[4][4]; - - tGPspoint *pt; - int i; - /* error checking */ if ((points == NULL) || (totpoints <= 0)) return; - + /* check if buffer can be drawn */ if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D)) return; - - /* get basic matrix - should be camera space (i.e "identity") */ - glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview); - - /* draw points */ - glPushMatrix(); - - for (i = 0, pt = points; i < totpoints; i++, pt++) { - /* set the transformed position */ - // TODO: scale should change based on zoom level, which requires proper translation mult too! - modelview[3][0] = pt->x; - modelview[3][1] = pt->y; - - glLoadMatrixf((float *)modelview); - - /* draw the disk using the current state... */ - gp_set_tpoint_color(pt, ink); - gluDisk(qobj, 0.0, pt->pressure * thickness, 32, 1); - - - modelview[3][0] = modelview[3][1] = 0.0f; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int size = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR); + GPU_enable_program_point_size(); + immBegin(GWN_PRIM_POINTS, totpoints); + + const tGPspoint *pt = points; + for (int i = 0; i < totpoints; i++, pt++) { + gp_set_tpoint_varying_color(pt, ink, color); + immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform (zoom level) */ + immVertex2f(pos, pt->x, pt->y); } - glPopMatrix(); - gluDeleteQuadric(qobj); + immEnd(); + immUnbindProgram(); + GPU_disable_program_point_size(); } /* draw a 2D strokes in "volumetric" style */ -static void gp_draw_stroke_volumetric_2d(bGPDspoint *points, int totpoints, short thickness, - short dflag, short sflag, +static void gp_draw_stroke_volumetric_2d(const bGPDspoint *points, int totpoints, short thickness, + short UNUSED(dflag), short sflag, int offsx, int offsy, int winx, int winy, - float diff_mat[4][4], float ink[4]) + const float diff_mat[4][4], const float ink[4]) { - GLUquadricObj *qobj = gluNewQuadric(); - float modelview[4][4]; - float baseloc[3]; - float scalefac = 1.0f; - - bGPDspoint *pt; - int i; - float fpt[3]; - - /* HACK: We need a scale factor for the drawing in the image editor, - * which seems to use 1 unit as it's maximum size, whereas everything - * else assumes 1 unit = 1 pixel. Otherwise, we only get a massive blob. - */ - if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) { - scalefac = 0.001f; - } - - /* get basic matrix */ - glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview); - copy_v3_v3(baseloc, modelview[3]); - - /* draw points */ - glPushMatrix(); - - for (i = 0, pt = points; i < totpoints; i++, pt++) { - /* color of point */ - gp_set_point_color(pt, ink); - - /* set the transformed position */ + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int size = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR); + GPU_enable_program_point_size(); + immBegin(GWN_PRIM_POINTS, totpoints); + + const bGPDspoint *pt = points; + for (int i = 0; i < totpoints; i++, pt++) { + /* transform position to 2D */ float co[2]; - + float fpt[3]; + mul_v3_m4v3(fpt, diff_mat, &pt->x); gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co); - translate_m4(modelview, co[0], co[1], 0.0f); - - glLoadMatrixf((float *)modelview); - - /* draw the disk using the current state... */ - gluDisk(qobj, 0.0, pt->pressure * thickness * scalefac, 32, 1); - - /* restore matrix */ - copy_v3_v3(modelview[3], baseloc); + + gp_set_point_varying_color(pt, ink, color); + immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */ + immVertex2f(pos, co[0], co[1]); } - - glPopMatrix(); - gluDeleteQuadric(qobj); + + immEnd(); + immUnbindProgram(); + GPU_disable_program_point_size(); } /* draw a 3D stroke in "volumetric" style */ static void gp_draw_stroke_volumetric_3d( - bGPDspoint *points, int totpoints, short thickness, - short UNUSED(dflag), short UNUSED(sflag), float diff_mat[4][4], float ink[4]) + const bGPDspoint *points, int totpoints, short thickness, + const float ink[4]) { - GLUquadricObj *qobj = gluNewQuadric(); - - float base_modelview[4][4], modelview[4][4]; - float base_loc[3]; - - bGPDspoint *pt; - int i; - float fpt[3]; - - /* Get the basic modelview matrix we use for performing calculations */ - glGetFloatv(GL_MODELVIEW_MATRIX, (float *)base_modelview); - copy_v3_v3(base_loc, base_modelview[3]); - - /* Create the basic view-aligned billboard matrix we're going to actually draw qobj with: - * - We need to knock out the rotation so that we are - * simply left with a camera-facing billboard - * - The scale factors here are chosen so that the thickness - * is relatively reasonable. Otherwise, it gets far too - * large! - */ - scale_m4_fl(modelview, 0.1f); - - /* draw each point as a disk... */ - glPushMatrix(); - - for (i = 0, pt = points; i < totpoints && pt; i++, pt++) { - /* color of point */ - gp_set_point_color(pt, ink); - - mul_v3_m4v3(fpt, diff_mat, &pt->x); - - /* apply translation to base_modelview, so that the translated point is put in the right place */ - translate_m4(base_modelview, fpt[0], fpt[1], fpt[2]); - - /* copy the translation component to the billboard matrix we're going to use, - * then reset the base matrix to the original values so that we can do the same - * for the next point without accumulation/pollution effects - */ - copy_v3_v3(modelview[3], base_modelview[3]); /* copy offset value */ - copy_v3_v3(base_modelview[3], base_loc); /* restore */ - - /* apply our billboard matrix for drawing... */ - glLoadMatrixf((float *)modelview); - - /* draw the disk using the current state... */ - gluDisk(qobj, 0.0, pt->pressure * thickness, 32, 1); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int size = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR); + GPU_enable_program_point_size(); + immBegin(GWN_PRIM_POINTS, totpoints); + + const bGPDspoint *pt = points; + for (int i = 0; i < totpoints && pt; i++, pt++) { + gp_set_point_varying_color(pt, ink, color); + immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */ + immVertex3fv(pos, &pt->x); /* we can adjust size in vertex shader based on view/projection! */ } - - glPopMatrix(); - gluDeleteQuadric(qobj); + + immEnd(); + immUnbindProgram(); + GPU_disable_program_point_size(); } /* --------------- Stroke Fills ----------------- */ /* Get points of stroke always flat to view not affected by camera view or view position */ -static void gp_stroke_2d_flat(bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction) +static void gp_stroke_2d_flat(const bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction) { - bGPDspoint *pt0 = &points[0]; - bGPDspoint *pt1 = &points[1]; - bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)]; - + const bGPDspoint *pt0 = &points[0]; + const bGPDspoint *pt1 = &points[1]; + const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)]; + float locx[3]; float locy[3]; float loc3[3]; float normal[3]; - + /* local X axis (p0 -> p1) */ sub_v3_v3v3(locx, &pt1->x, &pt0->x); - + /* point vector at 3/4 */ sub_v3_v3v3(loc3, &pt3->x, &pt0->x); - + /* vector orthogonal to polygon plane */ cross_v3_v3v3(normal, locx, loc3); - + /* local Y axis (cross to normal/x axis) */ cross_v3_v3v3(locy, normal, locx); - + /* Normalize vectors */ normalize_v3(locx); normalize_v3(locy); - + /* Get all points in local space */ for (int i = 0; i < totpoints; i++) { - bGPDspoint *pt = &points[i]; + const bGPDspoint *pt = &points[i]; float loc[3]; - + /* Get local space using first point as origin */ sub_v3_v3v3(loc, &pt->x, &pt0->x); - + points2d[i][0] = dot_v3v3(loc, locx); points2d[i][1] = dot_v3v3(loc, locy); } - + /* Concave (-1), Convex (1), or Autodetect (0)? */ *r_direction = (int)locy[2]; } @@ -416,14 +451,14 @@ static void gp_stroke_2d_flat(bGPDspoint *points, int totpoints, float(*points2d static void gp_triangulate_stroke_fill(bGPDstroke *gps) { BLI_assert(gps->totpoints >= 3); - + /* allocate memory for temporary areas */ gps->tot_triangles = gps->totpoints - 2; unsigned int (*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation"); float (*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points"); - + int direction = 0; - + /* convert to 2d and triangulate */ gp_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction); BLI_polyfill_calc(points2d, (unsigned int)gps->totpoints, direction, tmp_triangles); @@ -438,25 +473,24 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps) else { gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles); } - + for (int i = 0; i < gps->tot_triangles; i++) { - bGPDtriangle *stroke_triangle = &gps->triangles[i]; - memcpy(stroke_triangle->verts, tmp_triangles[i], sizeof(uint[3])); + memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3])); } } else { /* No triangles needed - Free anything allocated previously */ if (gps->triangles) MEM_freeN(gps->triangles); - + gps->triangles = NULL; } - + /* disable recalculation flag */ if (gps->flag & GP_STROKE_RECALC_CACHES) { gps->flag &= ~GP_STROKE_RECALC_CACHES; } - + /* clear memory */ if (tmp_triangles) MEM_freeN(tmp_triangles); if (points2d) MEM_freeN(points2d); @@ -466,78 +500,64 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps) /* draw fills for shapes */ static void gp_draw_stroke_fill( bGPdata *gpd, bGPDstroke *gps, - int offsx, int offsy, int winx, int winy, float diff_mat[4][4]) + int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float color[4]) { - bGPDpalettecolor *palcolor; - int i; float fpt[3]; BLI_assert(gps->totpoints >= 3); - palcolor = ED_gpencil_stroke_getcolor(gpd, gps); + bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps); /* Triangulation fill if high quality flag is enabled */ if (palcolor->flag & PC_COLOR_HQ_FILL) { - bGPDtriangle *stroke_triangle; - bGPDspoint *pt; - /* Calculate triangles cache for filling area (must be done only after changes) */ if ((gps->flag & GP_STROKE_RECALC_CACHES) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) { gp_triangulate_stroke_fill(gps); } - /* Draw all triangles for filling the polygon (cache must be calculated before) */ BLI_assert(gps->tot_triangles >= 1); - glBegin(GL_TRIANGLES); + + unsigned int pos; if (gps->flag & GP_STROKE_3DSPACE) { - for (i = 0, stroke_triangle = gps->triangles; i < gps->tot_triangles; i++, stroke_triangle++) { + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + } + else { + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + } + + immUniformColor4fv(color); + + /* Draw all triangles for filling the polygon (cache must be calculated before) */ + immBegin(GWN_PRIM_TRIS, gps->tot_triangles * 3); + /* TODO: use batch instead of immediate mode, to share vertices */ + + bGPDtriangle *stroke_triangle = gps->triangles; + bGPDspoint *pt; + + if (gps->flag & GP_STROKE_3DSPACE) { + for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) { for (int j = 0; j < 3; j++) { pt = &gps->points[stroke_triangle->verts[j]]; mul_v3_m4v3(fpt, diff_mat, &pt->x); - glVertex3fv(fpt); + immVertex3fv(pos, fpt); } } } else { - for (i = 0, stroke_triangle = gps->triangles; i < gps->tot_triangles; i++, stroke_triangle++) { + for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) { for (int j = 0; j < 3; j++) { float co[2]; pt = &gps->points[stroke_triangle->verts[j]]; mul_v3_m4v3(fpt, diff_mat, &pt->x); gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co); - glVertex2fv(co); + immVertex3fv(pos, fpt); } } } - glEnd(); - } - else { - /* As an initial implementation, we use the OpenGL filled polygon drawing - * here since it's the easiest option to implement for this case. It does - * come with limitations (notably for concave shapes), though it shouldn't - * be much of an issue in most cases. - * - * We keep this legacy implementation around despite now having the high quality - * fills, as this is necessary for keeping everything working nicely for files - * created using old versions of Blender which may have depended on the artifacts - * the old fills created. - */ - bGPDspoint *pt; - - glBegin(GL_POLYGON); - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if (gps->flag & GP_STROKE_3DSPACE) { - mul_v3_m4v3(fpt, diff_mat, &pt->x); - glVertex3fv(fpt); - } - else { - float co[2]; - mul_v3_m4v3(fpt, diff_mat, &pt->x); - gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co); - glVertex2fv(co); - } - } - glEnd(); + immEnd(); + immUnbindProgram(); } } @@ -545,153 +565,162 @@ static void gp_draw_stroke_fill( /* draw a given stroke - just a single dot (only one point) */ static void gp_draw_stroke_point( - bGPDspoint *points, short thickness, short dflag, short sflag, - int offsx, int offsy, int winx, int winy, float diff_mat[4][4], float ink[4]) + const bGPDspoint *points, short thickness, short UNUSED(dflag), short sflag, + int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float ink[4]) { - float fpt[3]; - bGPDspoint *pt = &points[0]; - - /* color of point */ - gp_set_point_color(pt, ink); + const bGPDspoint *pt = points; - /* set point thickness (since there's only one of these) */ - glPointSize((float)(thickness + 2) * points->pressure); - /* get final position using parent matrix */ + float fpt[3]; mul_v3_m4v3(fpt, diff_mat, &pt->x); - /* draw point */ + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + if (sflag & GP_STROKE_3DSPACE) { - glBegin(GL_POINTS); - glVertex3fv(fpt); - glEnd(); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); } else { - float co[2]; - - /* get coordinates of point */ + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + + /* get 2D coordinates of point */ + float co[3] = { 0.0f }; gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co); - - /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple dot looks ok - * - also mandatory in if Image Editor 'image-based' dot - */ - if ((thickness < GP_DRAWTHICKNESS_SPECIAL) || - ((dflag & GP_DRAWDATA_IEDITHACK) && (sflag & GP_STROKE_2DSPACE))) - { - glBegin(GL_POINTS); - glVertex2fv(co); - glEnd(); - } - else { - /* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */ - GLUquadricObj *qobj = gluNewQuadric(); - - gluQuadricDrawStyle(qobj, GLU_FILL); - - /* need to translate drawing position, but must reset after too! */ - glTranslate2fv(co); - gluDisk(qobj, 0.0, thickness, 32, 1); - glTranslatef(-co[0], -co[1], 0.0); - - gluDeleteQuadric(qobj); - } + copy_v3_v3(fpt, co); } + + gp_set_point_uniform_color(pt, ink); + /* set point thickness (since there's only one of these) */ + immUniform1f("size", (float)(thickness + 2) * pt->pressure); + + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, fpt); + immEnd(); + + immUnbindProgram(); } /* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */ -static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness, bool debug, - short UNUSED(sflag), float diff_mat[4][4], float ink[4], bool cyclic) +static void gp_draw_stroke_3d(const bGPDspoint *points, int totpoints, short thickness, bool UNUSED(debug), + short UNUSED(sflag), const float diff_mat[4][4], const float ink[4], bool cyclic) { - bGPDspoint *pt, *pt2; float curpressure = points[0].pressure; - int i; float fpt[3]; float cyclic_fpt[3]; + int draw_points = 0; + + /* if cyclic needs one vertex more */ + int cyclic_add = 0; + if (cyclic) { + ++cyclic_add; + } + + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); + + /* TODO: implement this with a geometry shader to draw one continuous tapered stroke */ /* draw stroke curve */ glLineWidth(max_ff(curpressure * thickness, 1.0f)); - glBegin(GL_LINE_STRIP); - for (i = 0, pt = points; i < totpoints && pt; i++, pt++) { - gp_set_point_color(pt, ink); + immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints + cyclic_add); + const bGPDspoint *pt = points; + for (int i = 0; i < totpoints; i++, pt++) { + gp_set_point_varying_color(pt, ink, color); /* if there was a significant pressure change, stop the curve, change the thickness of the stroke, * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP) * Note: we want more visible levels of pressures when thickness is bigger. */ if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) { - glEnd(); + /* if the pressure changes before get at least 2 vertices, need to repeat last point to avoid assert in immEnd() */ + if (draw_points < 2) { + const bGPDspoint *pt2 = pt - 1; + mul_v3_m4v3(fpt, diff_mat, &pt2->x); + immVertex3fv(pos, fpt); + } + immEnd(); + draw_points = 0; + curpressure = pt->pressure; glLineWidth(max_ff(curpressure * thickness, 1.0f)); - glBegin(GL_LINE_STRIP); - + immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints - i + 1 + cyclic_add); + /* need to roll-back one point to ensure that there are no gaps in the stroke */ if (i != 0) { - pt2 = pt - 1; + const bGPDspoint *pt2 = pt - 1; mul_v3_m4v3(fpt, diff_mat, &pt2->x); - glVertex3fv(fpt); + gp_set_point_varying_color(pt2, ink, color); + immVertex3fv(pos, fpt); + ++draw_points; } - - /* now the point we want... */ - mul_v3_m4v3(fpt, diff_mat, &pt->x); - glVertex3fv(fpt); - } - else { - mul_v3_m4v3(fpt, diff_mat, &pt->x); - glVertex3fv(fpt); } - /* saves first point to use in cyclic */ - if (i == 0) { + + /* now the point we want */ + mul_v3_m4v3(fpt, diff_mat, &pt->x); + immVertex3fv(pos, fpt); + ++draw_points; + + if (cyclic && i == 0) { + /* save first point to use in cyclic */ copy_v3_v3(cyclic_fpt, fpt); } } - /* if cyclic draw line to first point */ + if (cyclic) { - glVertex3fv(cyclic_fpt); + /* draw line to first point to complete the cycle */ + immVertex3fv(pos, cyclic_fpt); + ++draw_points; } - glEnd(); - - /* draw debug points of curve on top? */ - /* XXX: for now, we represent "selected" strokes in the same way as debug, which isn't used anymore */ - if (debug) { - glPointSize((float)(thickness + 2)); - - glBegin(GL_POINTS); - for (i = 0, pt = points; i < totpoints && pt; i++, pt++) { - mul_v3_m4v3(fpt, diff_mat, &pt->x); - glVertex3fv(fpt); - } - glEnd(); + /* if less of two points, need to repeat last point to avoid assert in immEnd() */ + if (draw_points < 2) { + const bGPDspoint *pt2 = pt - 1; + mul_v3_m4v3(fpt, diff_mat, &pt2->x); + gp_set_point_varying_color(pt2, ink, color); + immVertex3fv(pos, fpt); } + + immEnd(); + immUnbindProgram(); } /* ----- Fancy 2D-Stroke Drawing ------ */ /* draw a given stroke in 2d */ -static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag, - bool debug, int offsx, int offsy, int winx, int winy, float diff_mat[4][4], float ink[4]) +static void gp_draw_stroke_2d(const bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag, + bool UNUSED(debug), int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float ink[4]) { /* otherwise thickness is twice that of the 3D view */ float thickness = (float)thickness_s * 0.5f; - + /* strokes in Image Editor need a scale factor, since units there are not pixels! */ float scalefac = 1.0f; if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) { scalefac = 0.001f; } - - /* tessellation code - draw stroke as series of connected quads with connection + + /* TODO: fancy++ with the magic of shaders */ + + /* tessellation code - draw stroke as series of connected quads (triangle strips in fact) with connection * edges rotated to minimize shrinking artifacts, and rounded endcaps */ { - bGPDspoint *pt1, *pt2; + const bGPDspoint *pt1, *pt2; float s0[2], s1[2]; /* segment 'center' points */ float pm[2]; /* normal from previous segment. */ int i; float fpt[3]; - - glShadeModel(GL_FLAT); - glBegin(GL_QUADS); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBegin(GWN_PRIM_TRI_STRIP, totpoints * 2 + 4); /* get x and y coordinates from first point */ mul_v3_m4v3(fpt, diff_mat, &points->x); @@ -706,19 +735,19 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness /* get x and y coordinates from point2 (point1 has already been computed in previous iteration). */ mul_v3_m4v3(fpt, diff_mat, &pt2->x); gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s1); - + /* calculate gradient and normal - 'angle'=(ny/nx) */ m1[1] = s1[1] - s0[1]; m1[0] = s1[0] - s0[0]; normalize_v2(m1); m2[1] = -m1[0]; m2[0] = m1[1]; - + /* always use pressure from first point here */ pthick = (pt1->pressure * thickness * scalefac); - + /* color of point */ - gp_set_point_color(pt1, ink); + gp_set_point_varying_color(pt1, ink, color); /* if the first segment, start of segment is segment's normal */ if (i == 0) { @@ -729,40 +758,39 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness mt[1] = m2[1] * pthick * 0.5f; sc[0] = s0[0] - (m1[0] * pthick * 0.75f); sc[1] = s0[1] - (m1[1] * pthick * 0.75f); - + t0[0] = sc[0] - mt[0]; t0[1] = sc[1] - mt[1]; t1[0] = sc[0] + mt[0]; t1[1] = sc[1] + mt[1]; - - glVertex2fv(t0); - glVertex2fv(t1); - + + /* First two points of cap. */ + immVertex2fv(pos, t0); + immVertex2fv(pos, t1); + /* calculate points for start of segment */ mt[0] = m2[0] * pthick; mt[1] = m2[1] * pthick; - + t0[0] = s0[0] - mt[0]; t0[1] = s0[1] - mt[1]; t1[0] = s0[0] + mt[0]; t1[1] = s0[1] + mt[1]; - - /* draw this line twice (first to finish off start cap, then for stroke) */ - glVertex2fv(t1); - glVertex2fv(t0); - glVertex2fv(t0); - glVertex2fv(t1); + + /* Last two points of start cap (and first two points of first segment). */ + immVertex2fv(pos, t0); + immVertex2fv(pos, t1); } /* if not the first segment, use bisector of angle between segments */ else { float mb[2]; /* bisector normal */ float athick, dfac; /* actual thickness, difference between thicknesses */ - + /* calculate gradient of bisector (as average of normals) */ mb[0] = (pm[0] + m2[0]) / 2; mb[1] = (pm[1] + m2[1]) / 2; normalize_v2(mb); - + /* calculate gradient to apply * - as basis, use just pthick * bisector gradient * - if cross-section not as thick as it should be, add extra padding to fix it @@ -771,49 +799,44 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness mt[1] = mb[1] * pthick; athick = len_v2(mt); dfac = pthick - (athick * 2); - + if (((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick) == 0)) { mt[0] += (mb[0] * dfac); mt[1] += (mb[1] * dfac); } - + /* calculate points for start of segment */ t0[0] = s0[0] - mt[0]; t0[1] = s0[1] - mt[1]; t1[0] = s0[0] + mt[0]; t1[1] = s0[1] + mt[1]; - - /* draw this line twice (once for end of current segment, and once for start of next) */ - glVertex2fv(t1); - glVertex2fv(t0); - glVertex2fv(t0); - glVertex2fv(t1); + + /* Last two points of previous segment, and first two points of current segment. */ + immVertex2fv(pos, t0); + immVertex2fv(pos, t1); } - + /* if last segment, also draw end of segment (defined as segment's normal) */ if (i == totpoints - 2) { /* for once, we use second point's pressure (otherwise it won't be drawn) */ pthick = (pt2->pressure * thickness * scalefac); - + /* color of point */ - gp_set_point_color(pt2, ink); + gp_set_point_varying_color(pt2, ink, color); /* calculate points for end of segment */ mt[0] = m2[0] * pthick; mt[1] = m2[1] * pthick; - + t0[0] = s1[0] - mt[0]; t0[1] = s1[1] - mt[1]; t1[0] = s1[0] + mt[0]; t1[1] = s1[1] + mt[1]; - - /* draw this line twice (once for end of stroke, and once for endcap)*/ - glVertex2fv(t1); - glVertex2fv(t0); - glVertex2fv(t0); - glVertex2fv(t1); - - + + /* Last two points of last segment (and first two points of end cap). */ + immVertex2fv(pos, t0); + immVertex2fv(pos, t1); + /* draw end cap as last step * - make points slightly closer to center (about halfway across) */ @@ -821,42 +844,25 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness mt[1] = m2[1] * pthick * 0.5f; sc[0] = s1[0] + (m1[0] * pthick * 0.75f); sc[1] = s1[1] + (m1[1] * pthick * 0.75f); - + t0[0] = sc[0] - mt[0]; t0[1] = sc[1] - mt[1]; t1[0] = sc[0] + mt[0]; t1[1] = sc[1] + mt[1]; - - glVertex2fv(t1); - glVertex2fv(t0); + + /* Last two points of end cap. */ + immVertex2fv(pos, t0); + immVertex2fv(pos, t1); } - + /* store computed point2 coordinates as point1 ones of next segment. */ copy_v2_v2(s0, s1); /* store stroke's 'natural' normal for next stroke to use */ copy_v2_v2(pm, m2); } - - glEnd(); - glShadeModel(GL_SMOOTH); - } - - /* draw debug points of curve on top? (original stroke points) */ - if (debug) { - bGPDspoint *pt; - int i; - float fpt[3]; - glPointSize((float)(thickness_s + 2)); - - glBegin(GL_POINTS); - for (i = 0, pt = points; i < totpoints && pt; i++, pt++) { - float co[2]; - mul_v3_m4v3(fpt, diff_mat, &pt->x); - gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co); - glVertex2fv(co); - } - glEnd(); + immEnd(); + immUnbindProgram(); } } @@ -871,41 +877,41 @@ static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag) return false; if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE)) return false; - + /* 2) Screen Space 2D Strokes */ if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE)) return false; if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE)) return false; - + /* 3) Image Space (2D) */ if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE)) return false; if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE)) return false; - - + /* skip stroke if it doesn't have any valid data */ if ((gps->points == NULL) || (gps->totpoints < 1)) return false; - + /* stroke can be drawn */ return true; } /* draw a set of strokes */ static void gp_draw_strokes( - bGPdata *gpd, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag, + bGPdata *gpd, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag, bool debug, short lthick, const float opacity, const float tintcolor[4], - const bool onion, const bool custonion, float diff_mat[4][4]) + const bool onion, const bool custonion, const float diff_mat[4][4]) { - bGPDstroke *gps; float tcolor[4]; float tfill[4]; short sthickness; float ink[4]; - for (gps = gpf->strokes.first; gps; gps = gps->next) { + GPU_enable_program_point_size(); + + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { /* check if stroke can be drawn */ if (gp_can_draw_stroke(gps, dflag) == false) { continue; @@ -923,6 +929,10 @@ static void gp_draw_strokes( /* calculate thickness */ sthickness = gps->thickness + lthick; + if (sthickness <= 0) { + continue; + } + /* check which stroke-drawer to use */ if (dflag & GP_DRAWDATA_ONLY3D) { const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY); @@ -936,10 +946,6 @@ static void gp_draw_strokes( /* first arg is normally rv3d->dist, but this isn't * available here and seems to work quite well without */ bglPolygonOffset(1.0f, 1.0f); -#if 0 - glEnable(GL_POLYGON_OFFSET_LINE); - glPolygonOffset(-1.0f, -1.0f); -#endif } /* 3D Fill */ @@ -949,19 +955,20 @@ static void gp_draw_strokes( interp_v3_v3v3(tfill, palcolor->fill, tintcolor, tintcolor[3]); tfill[3] = palcolor->fill[3] * opacity; if (tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) { + const float *color; if (!onion) { - glColor4fv(tfill); + color = tfill; } else { if (custonion) { - glColor4fv(tintcolor); + color = tintcolor; } else { ARRAY_SET_ITEMS(tfill, UNPACK3(palcolor->fill), tintcolor[3]); - glColor4fv(tfill); + color = tfill; } } - gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat); + gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat, color); } } @@ -983,7 +990,7 @@ static void gp_draw_strokes( } if (palcolor->flag & PC_COLOR_VOLUMETRIC) { /* volumetric stroke drawing */ - gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, dflag, gps->flag, diff_mat, ink); + gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, ink); } else { /* 3D Lines - OpenGL primitives-based */ @@ -1001,10 +1008,6 @@ static void gp_draw_strokes( glDisable(GL_DEPTH_TEST); bglPolygonOffset(0.0, 0.0); -#if 0 - glDisable(GL_POLYGON_OFFSET_LINE); - glPolygonOffset(0, 0); -#endif } } else { @@ -1014,20 +1017,21 @@ static void gp_draw_strokes( interp_v3_v3v3(tfill, palcolor->fill, tintcolor, tintcolor[3]); tfill[3] = palcolor->fill[3] * opacity; if (tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) { + const float *color; if (!onion) { - glColor4fv(tfill); + color = tfill; } else { if (custonion) { - glColor4fv(tintcolor); + color = tintcolor; } else { ARRAY_SET_ITEMS(tfill, palcolor->fill[0], palcolor->fill[1], palcolor->fill[2], tintcolor[3]); - glColor4fv(tfill); + color = tfill; } } - gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat); + gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat, color); } } @@ -1065,15 +1069,15 @@ static void gp_draw_strokes( } } } + + GPU_disable_program_point_size(); } /* Draw selected verts for strokes being edited */ static void gp_draw_strokes_edit( - bGPdata *gpd, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, short dflag, - short lflag, float diff_mat[4][4], float alpha) + bGPdata *gpd, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy, short dflag, + short lflag, const float diff_mat[4][4], float alpha) { - bGPDstroke *gps; - /* if alpha 0 do not draw */ if (alpha == 0.0f) return; @@ -1087,36 +1091,28 @@ static void gp_draw_strokes_edit( glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig); glDepthMask(0); glEnable(GL_DEPTH_TEST); - + /* first arg is normally rv3d->dist, but this isn't * available here and seems to work quite well without */ bglPolygonOffset(1.0f, 1.0f); -#if 0 - glEnable(GL_POLYGON_OFFSET_LINE); - glPolygonOffset(-1.0f, -1.0f); -#endif } } - - - /* draw stroke verts */ - for (gps = gpf->strokes.first; gps; gps = gps->next) { - bGPDspoint *pt; - float vsize, bsize; - int i; - float fpt[3]; + GPU_enable_program_point_size(); + + /* draw stroke verts */ + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { /* check if stroke can be drawn */ if (gp_can_draw_stroke(gps, dflag) == false) continue; - + /* Optimisation: only draw points for selected strokes * We assume that selected points can only occur in * strokes that are selected too. */ if ((gps->flag & GP_STROKE_SELECT) == 0) continue; - + /* verify palette color lock */ { bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps); @@ -1135,7 +1131,8 @@ static void gp_draw_strokes_edit( * they stand out more. * - We use the theme setting for size of the unselected verts */ - bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE); + float bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE); + float vsize; if ((int)bsize > 8) { vsize = 10.0f; bsize = 8.0f; @@ -1143,89 +1140,83 @@ static void gp_draw_strokes_edit( else { vsize = bsize + 2; } - - /* First Pass: Draw all the verts (i.e. these become the unselected state) */ + /* for now, we assume that the base color of the points is not too close to the real color */ /* set color using palette */ bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps); - glColor3fv(palcolor->color); - glPointSize(bsize); - - glBegin(GL_POINTS); - for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) { + float selectColor[4]; + UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor); + selectColor[3] = alpha; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos; /* specified later */ + unsigned int size = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + if (gps->flag & GP_STROKE_3DSPACE) { + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR); + } + else { + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR); + } + + immBegin(GWN_PRIM_POINTS, gps->totpoints); + + /* Draw start and end point differently if enabled stroke direction hint */ + bool show_direction_hint = (gpd->flag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1); + + /* Draw all the stroke points (selected or not) */ + bGPDspoint *pt = gps->points; + float fpt[3]; + for (int i = 0; i < gps->totpoints; i++, pt++) { + /* size and color first */ + if (show_direction_hint && i == 0) { + /* start point in green bigger */ + immAttrib3f(color, 0.0f, 1.0f, 0.0f); + immAttrib1f(size, vsize + 4); + } + else if (show_direction_hint && (i == gps->totpoints - 1)) { + /* end point in red smaller */ + immAttrib3f(color, 1.0f, 0.0f, 0.0f); + immAttrib1f(size, vsize + 1); + } + else if (pt->flag & GP_SPOINT_SELECT) { + immAttrib3fv(color, selectColor); + immAttrib1f(size, vsize); + } + else { + immAttrib3fv(color, palcolor->color); + immAttrib1f(size, bsize); + } + + /* then position */ if (gps->flag & GP_STROKE_3DSPACE) { mul_v3_m4v3(fpt, diff_mat, &pt->x); - glVertex3fv(fpt); + immVertex3fv(pos, fpt); } else { float co[2]; mul_v3_m4v3(fpt, diff_mat, &pt->x); gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co); - glVertex2fv(co); + immVertex2fv(pos, co); } } - glEnd(); - - - /* Second Pass: Draw only verts which are selected */ - float curColor[4]; - UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, curColor); - glColor4f(curColor[0], curColor[1], curColor[2], alpha); - glPointSize(vsize); - - glBegin(GL_POINTS); - for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) { - if (pt->flag & GP_SPOINT_SELECT) { - if (gps->flag & GP_STROKE_3DSPACE) { - mul_v3_m4v3(fpt, diff_mat, &pt->x); - glVertex3fv(fpt); - } - else { - float co[2]; - - mul_v3_m4v3(fpt, diff_mat, &pt->x); - gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co); - glVertex2fv(co); - } - } - } - glEnd(); - - /* Draw start and end point if enabled stroke direction hint */ - if ((gpd->flag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1)) { - bGPDspoint *p; - - glPointSize(vsize + 4); - glBegin(GL_POINTS); - - /* start point in green bigger */ - glColor3f(0.0f, 1.0f, 0.0f); - p = &gps->points[0]; - mul_v3_m4v3(fpt, diff_mat, &p->x); - glVertex3fv(fpt); - glEnd(); - - /* end point in red smaller */ - glPointSize(vsize + 1); - glBegin(GL_POINTS); - - glColor3f(1.0f, 0.0f, 0.0f); - p = &gps->points[gps->totpoints - 1]; - mul_v3_m4v3(fpt, diff_mat, &p->x); - glVertex3fv(fpt); - glEnd(); - } + immEnd(); + immUnbindProgram(); } - - + + GPU_disable_program_point_size(); + /* clear depth mask */ if (dflag & GP_DRAWDATA_ONLY3D) { if (no_xray) { glDepthMask(mask_orig); glDisable(GL_DEPTH_TEST); - + bglPolygonOffset(0.0, 0.0); #if 0 glDisable(GL_POLYGON_OFFSET_LINE); @@ -1239,8 +1230,8 @@ static void gp_draw_strokes_edit( /* draw onion-skinning for a layer */ static void gp_draw_onionskins( - bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, - int UNUSED(cfra), int dflag, bool debug, float diff_mat[4][4]) + bGPdata *gpd, const bGPDlayer *gpl, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy, + int UNUSED(cfra), int dflag, bool debug, const float diff_mat[4][4]) { const float default_color[3] = {UNPACK3(U.gpencil_new_layer_col)}; const float alpha = 1.0f; @@ -1253,17 +1244,14 @@ static void gp_draw_onionskins( else { copy_v3_v3(color, default_color); } - + if (gpl->gstep > 0) { - bGPDframe *gf; - float fac; - /* draw previous frames first */ - for (gf = gpf->prev; gf; gf = gf->prev) { + for (bGPDframe *gf = gpf->prev; gf; gf = gf->prev) { /* check if frame is drawable */ if ((gpf->framenum - gf->framenum) <= gpl->gstep) { /* alpha decreases with distance from curframe index */ - fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1)); + float fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1)); color[3] = alpha * fac * 0.66f; gp_draw_strokes(gpd, gf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, 1.0f, color, true, gpl->flag & GP_LAYER_GHOST_PREVCOL, diff_mat); @@ -1283,8 +1271,7 @@ static void gp_draw_onionskins( else { /* don't draw - disabled */ } - - + /* 2) Now draw next frames */ if (gpl->flag & GP_LAYER_GHOST_NEXTCOL) { copy_v3_v3(color, gpl->gcolor_next); @@ -1292,17 +1279,14 @@ static void gp_draw_onionskins( else { copy_v3_v3(color, default_color); } - + if (gpl->gstep_next > 0) { - bGPDframe *gf; - float fac; - /* now draw next frames */ - for (gf = gpf->next; gf; gf = gf->next) { + for (bGPDframe *gf = gpf->next; gf; gf = gf->next) { /* check if frame is drawable */ if ((gf->framenum - gpf->framenum) <= gpl->gstep_next) { /* alpha decreases with distance from curframe index */ - fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1)); + float fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1)); color[3] = alpha * fac * 0.66f; gp_draw_strokes(gpd, gf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, 1.0f, color, true, gpl->flag & GP_LAYER_GHOST_NEXTCOL, diff_mat); @@ -1322,7 +1306,6 @@ static void gp_draw_onionskins( else { /* don't draw - disabled */ } - } /* draw interpolate strokes (used only while operator is running) */ @@ -1360,29 +1343,27 @@ void ED_gp_draw_interpolation(tGPDinterpolate *tgpi, const int type) /* loop over gpencil data layers, drawing them */ static void gp_draw_data_layers( - bGPDbrush *brush, float alpha, bGPdata *gpd, + const bGPDbrush *brush, float alpha, bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag) { - bGPDlayer *gpl; float diff_mat[4][4]; - for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { - bGPDframe *gpf; + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* calculate parent position */ ED_gpencil_parent_location(gpl, diff_mat); - bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? true : false; + bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG); short lthick = brush->thickness + gpl->thickness; - + /* don't draw layer if hidden */ if (gpl->flag & GP_LAYER_HIDE) continue; - + /* get frame to draw */ - gpf = BKE_gpencil_layer_getframe(gpl, cfra, 0); + bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra, 0); if (gpf == NULL) continue; - + /* set basic stroke thickness */ glLineWidth(lthick); @@ -1394,10 +1375,10 @@ static void gp_draw_data_layers( if (condition) dflag |= (draw_flag_value); \ else dflag &= ~(draw_flag_value); \ } (void)0 - + /* xray... */ GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_NO_XRAY), GP_DRAWDATA_NO_XRAY); - + /* volumetric strokes... */ GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_VOLUMETRIC), GP_DRAWDATA_VOLUMETRIC); @@ -1421,11 +1402,11 @@ static void gp_draw_data_layers( */ gp_draw_onionskins(gpd, gpl, gpf, offsx, offsy, winx, winy, cfra, dflag, debug, diff_mat); } - + /* draw the strokes already in active frame */ gp_draw_strokes(gpd, gpf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, gpl->opacity, gpl->tintcolor, false, false, diff_mat); - + /* Draw verts of selected strokes * - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering * - locked layers can't be edited, so there's no point showing these verts @@ -1440,16 +1421,13 @@ static void gp_draw_data_layers( { gp_draw_strokes_edit(gpd, gpf, offsx, offsy, winx, winy, dflag, gpl->flag, diff_mat, alpha); } - + /* Check if may need to draw the active stroke cache, only if this layer is the active layer * that is being edited. (Stroke buffer is currently stored in gp-data) */ if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) && (gpf->flag & GP_FRAME_PAINT)) { - /* Set color for drawing buffer stroke - since this may not be set yet */ - // glColor4fv(gpl->color); - /* Buffer stroke needs to be drawn with a different linestyle * to help differentiate them from normal strokes. * @@ -1458,89 +1436,84 @@ static void gp_draw_data_layers( */ if (gpd->sflag & PC_COLOR_VOLUMETRIC) { gp_draw_stroke_volumetric_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, - dflag, gpd->sbuffer_sflag, gpd->scolor); + dflag, gpd->scolor); } else { - gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag, gpd->scolor); + gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag, gpd->scolor, gpd->sfill); } } } } /* draw a short status message in the top-right corner */ -static void gp_draw_status_text(bGPdata *gpd, ARegion *ar) +static void gp_draw_status_text(const bGPdata *gpd, ARegion *ar) { rcti rect; - + /* Cannot draw any status text when drawing OpenGL Renders */ if (G.f & G_RENDER_OGL) return; - + /* Get bounds of region - Necessary to avoid problems with region overlap */ ED_region_visible_rect(ar, &rect); - + /* for now, this should only be used to indicate when we are in stroke editmode */ if (gpd->flag & GP_DATA_STROKE_EDITMODE) { const char *printable = IFACE_("GPencil Stroke Editing"); float printable_size[2]; - int xco, yco; - - BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); - - xco = (rect.xmax - U.widget_unit) - (int)printable_size[0]; - yco = (rect.ymax - U.widget_unit); + + int font_id = BLF_default(); + + BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); + int xco = (rect.xmax - U.widget_unit) - (int)printable_size[0]; + int yco = (rect.ymax - U.widget_unit); + /* text label */ - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(font_id, TH_TEXT_HI); #ifdef WITH_INTERNATIONAL BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); #else BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); #endif - + /* grease pencil icon... */ // XXX: is this too intrusive? glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - + xco -= U.widget_unit; yco -= (int)printable_size[1] / 2; UI_icon_draw(xco, yco, ICON_GREASEPENCIL); - + glDisable(GL_BLEND); } } /* draw grease-pencil datablock */ static void gp_draw_data( - bGPDbrush *brush, float alpha, bGPdata *gpd, + const bGPDbrush *brush, float alpha, bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag) { - /* reset line drawing style (in case previous user didn't reset) */ - setlinestyle(0); - /* turn on smooth lines (i.e. anti-aliasing) */ glEnable(GL_LINE_SMOOTH); - + /* XXX: turn on some way of ensuring that the polygon edges get smoothed * GL_POLYGON_SMOOTH is nasty and shouldn't be used, as it ends up * creating internal white rays due to the ways it accumulates stuff */ - + /* turn on alpha-blending */ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - + /* draw! */ gp_draw_data_layers(brush, alpha, gpd, offsx, offsy, winx, winy, cfra, dflag); - + /* turn off alpha blending, then smooth lines */ glDisable(GL_BLEND); // alpha blending glDisable(GL_LINE_SMOOTH); // smooth lines - - /* restore initial gl conditions */ - glColor4f(0, 0, 0, 1); } /* if we have strokes for scenes (3d view)/clips (movie clip editor) @@ -1575,7 +1548,7 @@ static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, i } } } - + /* scene/clip data has already been drawn, only object/track data is drawn here * if gpd_source == gpd, we don't have any object/track data and we can skip */ if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) { @@ -1601,28 +1574,27 @@ void ED_gpencil_draw_2dimage(const bContext *C) ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); - bGPdata *gpd; + int offsx, offsy, sizex, sizey; int dflag = GP_DRAWDATA_NOSTATUS; - - gpd = ED_gpencil_data_get_active(C); // XXX + + bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX if (gpd == NULL) return; - + /* calculate rect */ switch (sa->spacetype) { case SPACE_IMAGE: /* image */ case SPACE_CLIP: /* clip */ { - /* just draw using standard scaling (settings here are currently ignored anyways) */ /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */ offsx = 0; offsy = 0; sizex = ar->winx; sizey = ar->winy; - + wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax); - + dflag |= GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_IEDITHACK; break; } @@ -1633,7 +1605,7 @@ void ED_gpencil_draw_2dimage(const bContext *C) offsy = 0; sizex = ar->winx; sizey = ar->winy; - + /* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated * and everything moved to standard View2d */ @@ -1645,77 +1617,79 @@ void ED_gpencil_draw_2dimage(const bContext *C) offsy = 0; sizex = ar->winx; sizey = ar->winy; - + dflag |= GP_DRAWDATA_ONLYI2D; break; } - + if (ED_screen_animation_playing(wm)) { /* don't show onionskins during animation playback/scrub (i.e. it obscures the poses) * OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes) */ dflag |= GP_DRAWDATA_NO_ONIONS; } - - + /* draw it! */ gp_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, sa->spacetype); } /* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly - * Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes, - * second time with onlyv2d=0 for screen-aligned strokes */ + * Note: this gets called twice - first time with onlyv2d=true to draw 'canvas' strokes, + * second time with onlyv2d=false for screen-aligned strokes */ void ED_gpencil_draw_view2d(const bContext *C, bool onlyv2d) { wmWindowManager *wm = CTX_wm_manager(C); ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); - bGPdata *gpd; int dflag = 0; /* check that we have grease-pencil stuff to draw */ if (sa == NULL) return; - gpd = ED_gpencil_data_get_active(C); // XXX + bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX if (gpd == NULL) return; - + /* special hack for Image Editor */ /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */ if (ELEM(sa->spacetype, SPACE_IMAGE, SPACE_CLIP)) dflag |= GP_DRAWDATA_IEDITHACK; - + /* draw it! */ if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_NOSTATUS); if (ED_screen_animation_playing(wm)) dflag |= GP_DRAWDATA_NO_ONIONS; - + gp_draw_data_all(scene, gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag, sa->spacetype); - + /* draw status text (if in screen/pixel-space) */ - if (onlyv2d == false) { + if (!onlyv2d) { gp_draw_status_text(gpd, ar); } } /* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly - * Note: this gets called twice - first time with only3d=1 to draw 3d-strokes, - * second time with only3d=0 for screen-aligned strokes */ -void ED_gpencil_draw_view3d(wmWindowManager *wm, Scene *scene, View3D *v3d, ARegion *ar, bool only3d) + * Note: this gets called twice - first time with only3d=true to draw 3d-strokes, + * second time with only3d=false for screen-aligned strokes */ +void ED_gpencil_draw_view3d(wmWindowManager *wm, + Scene *scene, + SceneLayer *scene_layer, + View3D *v3d, + ARegion *ar, + bool only3d) { - bGPdata *gpd; int dflag = 0; RegionView3D *rv3d = ar->regiondata; int offsx, offsy, winx, winy; - + /* check that we have grease-pencil stuff to draw */ - gpd = ED_gpencil_data_get_active_v3d(scene, v3d); + bGPdata *gpd = ED_gpencil_data_get_active_v3d(scene, scene_layer); if (gpd == NULL) return; - + /* when rendering to the offscreen buffer we don't want to * deal with the camera border, otherwise map the coords to the camera border. */ if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_RENDER_OGL)) { rctf rectf; ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &rectf, true); /* no shift */ - + offsx = round_fl_to_int(rectf.xmin); offsy = round_fl_to_int(rectf.ymin); winx = round_fl_to_int(rectf.xmax - rectf.xmin); @@ -1727,7 +1701,7 @@ void ED_gpencil_draw_view3d(wmWindowManager *wm, Scene *scene, View3D *v3d, AReg winx = ar->winx; winy = ar->winy; } - + /* set flags */ if (only3d) { /* 3D strokes/3D space: @@ -1736,28 +1710,27 @@ void ED_gpencil_draw_view3d(wmWindowManager *wm, Scene *scene, View3D *v3d, AReg */ dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS); } - + if (v3d->flag2 & V3D_RENDER_OVERRIDE) { /* don't draw status text when "only render" flag is set */ dflag |= GP_DRAWDATA_NOSTATUS; } - + if ((wm == NULL) || ED_screen_animation_playing(wm)) { /* don't show onionskins during animation playback/scrub (i.e. it obscures the poses) * OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes) */ dflag |= GP_DRAWDATA_NO_ONIONS; } - + /* draw it! */ - gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype); - + gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype); } void ED_gpencil_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype) { int dflag = GP_DRAWDATA_NOSTATUS | GP_DRAWDATA_ONLYV2D; - + gp_draw_data_all(scene, gpd, 0, 0, winx, winy, cfra, dflag, spacetype); } diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c index bb3800941ab..38927cf91e1 100644 --- a/source/blender/editors/gpencil/gpencil_brush.c +++ b/source/blender/editors/gpencil/gpencil_brush.c @@ -75,8 +75,8 @@ #include "ED_screen.h" #include "ED_view3d.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" #include "gpencil_intern.h" @@ -979,28 +979,28 @@ static bool gpsculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso) static void gp_brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)) { GP_EditBrush_Data *brush = gpsculpt_get_brush(CTX_data_scene(C)); - + if (brush) { - glPushMatrix(); - - glTranslatef((float)x, (float)y, 0.0f); - + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - + /* Inner Ring: Light color for action of the brush */ /* TODO: toggle between add and remove? */ - glColor4ub(255, 255, 255, 200); - glutil_draw_lined_arc(0.0, M_PI * 2.0, brush->size, 40); - + immUniformColor4ub(255, 255, 255, 200); + imm_draw_circle_wire_2d(pos, x, y, brush->size, 40); + /* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */ - glColor3ub(30, 30, 30); - glutil_draw_lined_arc(0.0, M_PI * 2.0, brush->size + 1, 40); - + immUniformColor3ub(30, 30, 30); + imm_draw_circle_wire_2d(pos, x, y, brush->size + 1, 40); + + immUnbindProgram(); + glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - - glPopMatrix(); } } diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 7d455f214db..5d014b5d49e 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -56,12 +56,13 @@ #include "DNA_view3d_types.h" #include "DNA_gpencil_types.h" +#include "BKE_collection.h" #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_gpencil.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_object.h" #include "BKE_report.h" @@ -69,6 +70,8 @@ #include "BKE_screen.h" #include "BKE_tracking.h" +#include "DEG_depsgraph.h" + #include "UI_interface.h" #include "WM_api.h" @@ -546,7 +549,7 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); /* send updates */ - DAG_id_tag_update(&cu->id, 0); + DEG_id_tag_update(&cu->id, 0); } #undef MIN_TIME_DELTA @@ -1121,14 +1124,15 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG const bool norm_weights, const float rad_fac, const bool link_strokes, tGpTimingData *gtd) { struct Main *bmain = CTX_data_main(C); - View3D *v3d = CTX_wm_view3d(C); /* may be NULL */ Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + SceneCollection *sc = CTX_data_scene_collection(C); bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0); bGPDstroke *gps, *prev_gps = NULL; Object *ob; Curve *cu; Nurb *nu = NULL; - Base *base_orig = BASACT, *base_new = NULL; + Base *base_new = NULL; float minmax_weights[2] = {1.0f, 0.0f}; /* camera framing */ @@ -1152,7 +1156,8 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG */ ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info); cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE); - base_new = BKE_scene_base_add(scene, ob); + BKE_collection_object_add(scene, sc, ob); + base_new = BKE_scene_layer_base_find(sl, ob); cu->flag |= CU_3D; @@ -1216,8 +1221,8 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG } /* set the layer and select */ - base_new->lay = ob->lay = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene); - base_new->flag = ob->flag = base_new->flag | SELECT; + base_new->flag |= SELECT; + BKE_scene_object_base_flag_sync_from_base(base_new); } /* --- */ diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index bd5a42df99a..a82148788c8 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -79,6 +79,8 @@ #include "ED_view3d.h" #include "ED_space_api.h" +#include "DEG_depsgraph.h" + #include "gpencil_intern.h" /* ************************************************ */ @@ -2106,8 +2108,12 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) /* init autodist for geometry projection */ if (mode == GP_REPROJECT_SURFACE) { + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + + struct Depsgraph *graph = CTX_data_depsgraph(C); view3d_region_operator_needs_opengl(CTX_wm_window(C), gsc.ar); - ED_view3d_autodist_init(scene, gsc.ar, CTX_wm_view3d(C), 0); + ED_view3d_autodist_init(&eval_ctx, graph, gsc.ar, CTX_wm_view3d(C), 0); } // TODO: For deforming geometry workflow, create new frames? diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index cff198db6c0..0b4bdb9914d 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -69,15 +69,19 @@ #include "ED_view3d.h" #include "ED_clip.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" + #include "RNA_access.h" #include "RNA_define.h" #include "WM_api.h" #include "WM_types.h" +#include "DEG_depsgraph.h" + #include "gpencil_intern.h" /* ******************************************* */ @@ -112,7 +116,9 @@ typedef enum eGPencil_PaintFlags { * "p" = op->customdata */ typedef struct tGPsdata { + EvaluationContext eval_ctx; Scene *scene; /* current scene from context */ + struct Depsgraph *graph; wmWindow *win; /* window where painting originated */ ScrArea *sa; /* area where painting originated */ @@ -481,7 +487,8 @@ static void gp_brush_angle(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const } /* add current stroke-point to buffer (returns whether point was successfully added) */ -static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, double curtime) +static short gp_stroke_addpoint( + tGPsdata *p, const int mval[2], float pressure, double curtime) { bGPdata *gpd = p->gpd; bGPDbrush *brush = p->brush; @@ -639,7 +646,8 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, View3D *v3d = p->sa->spacedata.first; view3d_region_operator_needs_opengl(p->win, p->ar); - ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0); + ED_view3d_autodist_init( + &p->eval_ctx, p->graph, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0); } /* convert screen-coordinates to appropriate coordinates (and store them) */ @@ -735,7 +743,7 @@ static void gp_stroke_simplify(tGPsdata *p) /* ignore return values on this... assume to be ok for now */ gp_stroke_addpoint(p, mco, pressure, p->inittime + (double)time); - + j += 2; } } @@ -1239,9 +1247,8 @@ static void gp_stroke_doeraser(tGPsdata *p) if (p->sa->spacetype == SPACE_VIEW3D) { if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) { View3D *v3d = p->sa->spacedata.first; - view3d_region_operator_needs_opengl(p->win, p->ar); - ED_view3d_autodist_init(p->scene, p->ar, v3d, 0); + ED_view3d_autodist_init(&p->eval_ctx, p->graph, p->ar, v3d, 0); } } @@ -1394,7 +1401,9 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) } /* pass on current scene and window */ + CTX_data_eval_ctx(C, &p->eval_ctx); p->scene = CTX_data_scene(C); + p->graph = CTX_data_depsgraph(C); p->win = CTX_wm_window(C); unit_m4(p->imat); @@ -1549,6 +1558,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) bGPDpalettecolor *palcolor = p->palettecolor; bGPdata *pdata = p->gpd; copy_v4_v4(pdata->scolor, palcolor->color); + copy_v4_v4(pdata->sfill, palcolor->fill); pdata->sflag = palcolor->flag; /* lock axis */ p->lock_axis = ts->gp_sculpt.lock_axis; @@ -1806,14 +1816,14 @@ static void gp_paint_strokeend(tGPsdata *p) /* need to restore the original projection settings before packing up */ view3d_region_operator_needs_opengl(p->win, p->ar); - ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0); + ED_view3d_autodist_init(&p->eval_ctx, p->graph, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0); } /* check if doing eraser or not */ if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) { /* simplify stroke before transferring? */ gp_stroke_simplify(p); - + /* transfer stroke to frame */ gp_stroke_newfrombuffer(p); } @@ -1844,28 +1854,41 @@ static void gp_paint_cleanup(tGPsdata *p) static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr) { tGPsdata *p = (tGPsdata *)p_ptr; - + if (p->paintmode == GP_PAINTMODE_ERASER) { - glPushMatrix(); - - glTranslatef((float)x, (float)y, 0.0f); - + Gwn_VertFormat *format = immVertexFormat(); + const uint shdr_pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - - glColor4ub(255, 100, 100, 20); - glutil_draw_filled_arc(0.0, M_PI * 2.0, p->radius, 40); - - setlinestyle(6); - - glColor4ub(255, 100, 100, 200); - glutil_draw_lined_arc(0.0, M_PI * 2.0, p->radius, 40); - - setlinestyle(0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + immUniformColor4ub(255, 100, 100, 20); + imm_draw_circle_fill_2d(shdr_pos, x, y, p->radius, 40); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f); + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniform1f("dash_width", 12.0f); + immUniform1f("dash_factor", 0.5f); + + imm_draw_circle_wire_2d(shdr_pos, x, y, p->radius, + /* XXX Dashed shader gives bad results with sets of small segments currently, + * temp hack around the issue. :( */ + max_ii(8, p->radius / 2)); /* was fixed 40 */ + + immUnbindProgram(); + glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - - glPopMatrix(); } } @@ -2039,7 +2062,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) if (p->paintmode == GP_PAINTMODE_ERASER) { /* do 'live' erasing now */ gp_stroke_doeraser(p); - + /* store used values */ p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; @@ -2049,7 +2072,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { /* try to add point */ short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); - + /* handle errors while adding point */ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { /* finish off old stroke */ @@ -2194,7 +2217,7 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event) /* apply the current latest drawing point */ gpencil_draw_apply(op, p); - + /* force refresh */ ED_region_tag_redraw(p->ar); /* just active area for now, since doing whole screen is too slow */ } @@ -2370,9 +2393,9 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) static void gpencil_stroke_end(wmOperator *op) { tGPsdata *p = op->customdata; - + gp_paint_cleanup(p); - + gpencil_undo_push(p->gpd); gp_session_cleanup(p); @@ -2506,7 +2529,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* end stroke only, and then wait to resume painting soon */ /* printf("\t\tGP - end stroke only\n"); */ gpencil_stroke_end(op); - + /* If eraser mode is on, turn it off after the stroke finishes * NOTE: This just makes it nicer to work with drawing sessions */ @@ -2649,7 +2672,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* handle drawing event */ /* printf("\t\tGP - add point\n"); */ gpencil_draw_apply_event(op, event); - + /* finish painting operation if anything went wrong just now */ if (p->status == GP_STATUS_ERROR) { printf("\t\t\t\tGP - add error done!\n"); diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 672c87ed6fd..96c929e9a92 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -65,6 +65,8 @@ #include "ED_clip.h" #include "ED_view3d.h" +#include "DEG_depsgraph.h" + #include "gpencil_intern.h" /* ******************************************************** */ @@ -202,15 +204,15 @@ bGPdata *ED_gpencil_data_get_active(const bContext *C) /* -------------------------------------------------------- */ // XXX: this should be removed... We really shouldn't duplicate logic like this! -bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, View3D *v3d) +bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, SceneLayer *scene_layer) { - Base *base = scene->basact; + Base *base = scene_layer->basact; bGPdata *gpd = NULL; /* We have to make sure active object is actually visible and selected, else we must use default scene gpd, * to be consistent with ED_gpencil_data_get_active's behavior. */ - if (base && TESTBASE(v3d, base)) { + if (base && TESTBASE(base)) { gpd = base->object->gpd; } return gpd ? gpd : scene->gpd; @@ -536,14 +538,18 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc) if (sa->spacetype == SPACE_VIEW3D) { wmWindow *win = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); + struct Depsgraph *graph = CTX_data_depsgraph(C); View3D *v3d = (View3D *)CTX_wm_space_data(C); RegionView3D *rv3d = ar->regiondata; + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + /* init 3d depth buffers */ view3d_operator_needs_opengl(C); view3d_region_operator_needs_opengl(win, ar); - ED_view3d_autodist_init(scene, ar, v3d, 0); + ED_view3d_autodist_init(&eval_ctx, graph, ar, v3d, 0); /* for camera view set the subrect */ if (rv3d->persp == RV3D_CAMOB) { @@ -912,8 +918,8 @@ bool gp_smooth_stroke_thickness(bGPDstroke *gps, int i, float inf) ptc = &gps->points[after]; /* the optimal value is the corresponding to the interpolation of the pressure - * at the distance of point b - */ + * at the distance of point b + */ float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x); float optimal = (1.0f - fac) * pta->pressure + fac * ptc->pressure; diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h index e264d9e16a3..f91e7d42bca 100644 --- a/source/blender/editors/include/BIF_gl.h +++ b/source/blender/editors/include/BIF_gl.h @@ -36,45 +36,6 @@ #include "GPU_glew.h" #include "BLI_utildefines.h" -/* - * these should be phased out. cpack should be replaced in - * code with calls to glColor3ub. - zr - */ -/* - * - * This define converts a numerical value to the equivalent 24-bit - * color, while not being endian-sensitive. On little-endians, this - * is the same as doing a 'naive' indexing, on big-endian, it is not! - * */ -void cpack(unsigned int x); - -#ifdef WITH_GL_PROFILE_COMPAT -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) -# define glMultMatrixf(x) \ - glMultMatrixf(_Generic((x), \ - float *: (float *)(x), \ - float [16]: (float *)(x), \ - float (*)[4]: (float *)(x), \ - float [4][4]: (float *)(x), \ - const float *: (float *)(x), \ - const float [16]: (float *)(x), \ - const float (*)[4]: (float *)(x), \ - const float [4][4]: (float *)(x)) \ -) -# define glLoadMatrixf(x) \ - glLoadMatrixf(_Generic((x), \ - float *: (float *)(x), \ - float [16]: (float *)(x), \ - float (*)[4]: (float *)(x), \ - float [4][4]: (float *)(x)) \ -) -#else -# define glMultMatrixf(x) glMultMatrixf((float *)(x)) -# define glLoadMatrixf(x) glLoadMatrixf((float *)(x)) -#endif /* C11 */ -#endif /* WITH_GL_PROFILE_COMPAT */ - - /* hacking pointsize and linewidth */ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) # define glPointSize(f) glPointSize(U.pixelsize * _Generic((f), double: (float)(f), default: (f))) @@ -86,19 +47,5 @@ void cpack(unsigned int x); #define GLA_PIXEL_OFS 0.375f - -BLI_INLINE void glTranslate3iv(const int vec[3]) { glTranslatef(UNPACK3_EX((const float), vec, )); } -BLI_INLINE void glTranslate2iv(const int vec[2]) { glTranslatef(UNPACK2_EX((const float), vec, ), 0.0f); } -BLI_INLINE void glTranslate3fv(const float vec[3]) { glTranslatef(UNPACK3(vec)); } -BLI_INLINE void glTranslate2fv(const float vec[2]) { glTranslatef(UNPACK2(vec), 0.0f); } - -BLI_INLINE void glScale3iv(const int vec[3]) { glTranslatef(UNPACK3_EX((const float), vec, )); } -BLI_INLINE void glScale2iv(const int vec[2]) { glTranslatef(UNPACK2_EX((const float), vec, ), 0.0f); } -BLI_INLINE void glScale3fv(const float vec[3]) { glScalef(UNPACK3(vec)); } -BLI_INLINE void glScale2fv(const float vec[2]) { glScalef(UNPACK2(vec), 0.0); } - -/* v2 versions don't make much sense for rotation */ -BLI_INLINE void glRotate3fv(const float angle, const float vec[3]) { glRotatef(angle, UNPACK3(vec)); } - #endif /* #ifdef __BIF_GL_H__ */ diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h index d3d2c465d46..3184ebee4d9 100644 --- a/source/blender/editors/include/BIF_glutil.h +++ b/source/blender/editors/include/BIF_glutil.h @@ -38,56 +38,14 @@ struct bContext; struct ColorManagedViewSettings; struct ColorManagedDisplaySettings; -void fdrawbezier(float vec[4][3]); -void fdrawline(float x1, float y1, float x2, float y2); -void fdrawbox(float x1, float y1, float x2, float y2); -void sdrawline(int x1, int y1, int x2, int y2); -#if 0 -void sdrawtri(int x1, int y1, int x2, int y2); -void sdrawtrifill(int x1, int y1, int x2, int y2); -#endif -void sdrawbox(int x1, int y1, int x2, int y2); - -void sdrawXORline(int x0, int y0, int x1, int y1); -void sdrawXORline4(int nr, int x0, int y0, int x1, int y1); - -void fdrawXORellipse(float xofs, float yofs, float hw, float hh); -void fdrawXORcirc(float xofs, float yofs, float rad); - -void fdrawcheckerboard(float x1, float y1, float x2, float y2); - -/* OpenGL stipple defines */ -extern const unsigned char stipple_halftone[128]; -extern const unsigned char stipple_quarttone[128]; -extern const unsigned char stipple_diag_stripes_pos[128]; -extern const unsigned char stipple_diag_stripes_neg[128]; -extern const unsigned char stipple_checker_8px[128]; - -/** - * Draw a lined (non-looping) arc with the given - * \a radius, starting at angle \a start and arcing - * through \a angle. The arc is centered at the origin - * and drawn in the XY plane. +/* A few functions defined here are being DEPRECATED for Blender 2.8 * - * \param start The initial angle (in radians). - * \param angle The length of the arc (in radians). - * \param radius The arc radius. - * \param nsegments The number of segments to use in drawing the arc. - */ -void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments); - -/** - * Draw a filled arc with the given \a radius, - * starting at angle \a start and arcing through - * \a angle. The arc is centered at the origin - * and drawn in the XY plane. + * Do not use them in new code, and you are encouraged to + * convert existing code to draw without these. * - * \param start The initial angle (in radians). - * \param angle The length of the arc (in radians). - * \param radius The arc radius. - * \param nsegments The number of segments to use in drawing the arc. + * These will be deleted before we ship 2.8! + * - merwin */ -void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments); /** * Returns a float value as obtained by glGetFloatv. @@ -109,58 +67,46 @@ int glaGetOneInt(int param); */ void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y); -/** - * Functions like a limited glDrawPixels, except ensures that - * the image is displayed onscreen even if the \a x and \a y - * coordinates for would be clipped. The routine respects the - * glPixelZoom values, pixel unpacking parameters are _not_ - * respected. - * - * \attention This routine makes many assumptions: the rect data - * is expected to be in RGBA unsigned byte format, the coordinate - * (GLA_PIXEL_OFS, GLA_PIXEL_OFS) is assumed to be within the view frustum, - * and the modelview and projection matrices are assumed to define a - * 1-to-1 mapping to screen space. - * \attention Furthermore, in the case of zoomed or unpixel aligned - * images extending outside the view frustum, but still within the - * window, some portion of the image may be visible left and/or - * below of the given \a x and \a y coordinates. It is recommended - * to use the glScissor functionality if images are to be drawn - * with an inset view matrix. - */ -void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect); +typedef struct IMMDrawPixelsTexState { + struct GPUShader *shader; + unsigned int pos; + unsigned int texco; + bool do_shader_unbind; +} IMMDrawPixelsTexState; + +/* To be used before calling immDrawPixelsTex + * Default shader is GPU_SHADER_2D_IMAGE_COLOR + * Returns a shader to be able to set uniforms */ +IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin); /** - * glaDrawPixelsTex - Functions like a limited glDrawPixels, but actually draws the + * immDrawPixelsTex - Functions like a limited glDrawPixels, but actually draws the * image using textures, which can be tremendously faster on low-end * cards, and also avoids problems with the raster position being - * clipped when offscreen. The routine respects the glPixelZoom values, - * pixel unpacking parameters are _not_ respected. + * clipped when offscreen. Pixel unpacking parameters and + * the glPixelZoom values are _not_ respected. + * + * \attention Use immDrawPixelsTexSetup before calling this function. * * \attention This routine makes many assumptions: the rect data * is expected to be in RGBA byte or float format, and the * modelview and projection matrices are assumed to define a * 1-to-1 mapping to screen space. */ - -void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect); -void glaDrawPixelsTex_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, - float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y); - -/** - * glaDrawPixelsAuto - Switches between texture or pixel drawing using UserDef. - * only RGBA - * needs glaDefine2DArea to be set. - */ -void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect); -void glaDrawPixelsAuto_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, - float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y); - - -void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY); -void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY, - float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y); - +void immDrawPixelsTex(IMMDrawPixelsTexState *state, + float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, + float xzoom, float yzoom, float color[4]); +void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state, + float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, + float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y, + float xzoom, float yzoom, float color[4]); +void immDrawPixelsTexScaled(IMMDrawPixelsTexState *state, + float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY, + float xzoom, float yzoom, float color[4]); +void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, + float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY, + float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y, + float xzoom, float yzoom, float color[4]); /* 2D Drawing Assistance */ /** Define a 2D area (viewport, scissor, matrices) for OpenGL rendering. @@ -176,12 +122,13 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, int */ void glaDefine2DArea(struct rcti *screen_rect); -typedef struct gla2DDrawInfo gla2DDrawInfo; +/* TODO(merwin): put the following 2D code to use, or build new 2D code inspired & informd by it */ + +#if 0 /* UNUSED */ -/* UNUSED */ -#if 0 +typedef struct gla2DDrawInfo gla2DDrawInfo; -gla2DDrawInfo *glaBegin2DDraw(struct rcti *screen_rect, struct rctf *world_rect); +gla2DDrawInfo *glaBegin2DDraw(struct rcti *screen_rect, struct rctf *world_rect); void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *r_sc_x, int *r_sc_y); void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int r_screen[2]); @@ -190,7 +137,8 @@ void glaEnd2DDraw(gla2DDrawInfo *di); /** Adjust the transformation mapping of a 2d area */ void gla2DGetMap(gla2DDrawInfo *di, struct rctf *rect); void gla2DSetMap(gla2DDrawInfo *di, struct rctf *rect); -#endif + +#endif /* UNUSED */ void set_inverted_drawing(int enable); void setlinestyle(int nr); @@ -198,37 +146,32 @@ void setlinestyle(int nr); /* own working polygon offset */ void bglPolygonOffset(float viewdist, float dist); -/* For caching opengl matrices (gluProject/gluUnProject) */ -typedef struct bglMats { - double modelview[16]; - double projection[16]; - int viewport[4]; -} bglMats; -void bgl_get_mats(bglMats *mats); - /* **** Color management helper functions for GLSL display/transform ***** */ /* Draw imbuf on a screen, preferably using GLSL display transform */ void glaDrawImBuf_glsl(struct ImBuf *ibuf, float x, float y, int zoomfilter, struct ColorManagedViewSettings *view_settings, - struct ColorManagedDisplaySettings *display_settings); + struct ColorManagedDisplaySettings *display_settings, + float zoom_x, float zoom_y); void glaDrawImBuf_glsl_clipping(struct ImBuf *ibuf, float x, float y, int zoomfilter, struct ColorManagedViewSettings *view_settings, struct ColorManagedDisplaySettings *display_settings, float clip_min_x, float clip_min_y, - float clip_max_x, float clip_max_y); + float clip_max_x, float clip_max_y, + float zoom_x, float zoom_y); /* Draw imbuf on a screen, preferably using GLSL display transform */ -void glaDrawImBuf_glsl_ctx(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter); +void glaDrawImBuf_glsl_ctx(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter, + float zoom_x, float zoom_y); void glaDrawImBuf_glsl_ctx_clipping(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter, float clip_min_x, float clip_min_y, - float clip_max_x, float clip_max_y); + float clip_max_x, float clip_max_y, + float zoom_x, float zoom_y); -void glaDrawBorderCorners(const struct rcti *border, float zoomx, float zoomy); +void immDrawBorderCorners(unsigned int pos, const struct rcti *border, float zoomx, float zoomy); #endif /* __BIF_GLUTIL_H__ */ - diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index ab02fd1ccc8..77b2ce435c2 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -82,6 +82,7 @@ typedef struct bAnimContext { struct bDopeSheet *ads; /* dopesheet data for editor (or which is being used) */ struct Scene *scene; /* active scene */ + struct SceneLayer *scene_layer; /* active scene layer */ struct Object *obact; /* active object */ ListBase *markers; /* active set of markers */ diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 00081b95c51..918e96d8408 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -39,6 +39,7 @@ struct Base; struct bContext; struct Bone; struct bPoseChannel; +struct EvaluationContext; struct IDProperty; struct ListBase; struct MeshDeformModifierData; @@ -46,9 +47,11 @@ struct DerivedMesh; struct Object; struct ReportList; struct Scene; +struct SceneLayer; struct ViewContext; struct wmKeyConfig; struct wmOperator; +struct Main; typedef struct EditBone { struct EditBone *next, *prev; @@ -85,6 +88,12 @@ typedef struct EditBone { short segments; + /* Used for display */ + float disp_mat[4][4]; /* in Armature space, rest pos matrix */ + float disp_tail_mat[4][4]; /* in Armature space, rest pos matrix */ + /* 32 == MAX_BBONE_SUBDIV */ + float disp_bbone_mat[32][4][4]; /* in Armature space, rest pos matrix */ + /* Used to store temporary data */ union { struct EditBone *ebone; @@ -134,7 +143,7 @@ void ED_armature_deselect_all(struct Object *obedit); void ED_armature_deselect_all_visible(struct Object *obedit); bool ED_do_pose_selectbuffer( - struct Scene *scene, struct Base *base, const unsigned int *buffer, short hits, + struct Scene *scene, struct SceneLayer *sl, struct Base *base, const unsigned int *buffer, short hits, bool extend, bool deselect, bool toggle, bool do_nearest); bool ED_armature_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); int join_armature_exec(struct bContext *C, struct wmOperator *op); @@ -169,8 +178,9 @@ void ED_armature_transform(struct bArmature *arm, float mat[4][4], const bool do #define ARM_GROUPS_ENVELOPE 2 #define ARM_GROUPS_AUTO 3 -void create_vgroups_from_armature(struct ReportList *reports, struct Scene *scene, struct Object *ob, - struct Object *par, const int mode, const bool mirror); +void create_vgroups_from_armature( + struct ReportList *reports, const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct Object *ob, struct Object *par, const int mode, const bool mirror); /* if bone is already in list, pass it as param to ignore it */ void unique_editbone_name(struct ListBase *ebones, char *name, EditBone *bone); @@ -191,7 +201,7 @@ void ED_armature_exit_posemode(struct bContext *C, struct Base *base); void ED_armature_enter_posemode(struct bContext *C, struct Base *base); void ED_pose_de_selectall(struct Object *ob, int select_mode, const bool ignore_visibility); void ED_pose_bone_select(struct Object *ob, struct bPoseChannel *pchan, bool select); -void ED_pose_recalculate_paths(struct Scene *scene, struct Object *ob); +void ED_pose_recalculate_paths(struct bContext *C, struct Scene *scene, struct Object *ob); struct Object *ED_pose_object_from_context(struct bContext *C); /* sketch */ diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 74d9ad0886d..926f31781e2 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -48,6 +48,8 @@ struct bGPDpalettecolor; struct bAnimContext; struct KeyframeEditData; struct PointerRNA; +struct Scene; +struct SceneLayer; struct wmWindowManager; struct wmKeyConfig; @@ -113,7 +115,7 @@ struct bGPdata *ED_gpencil_data_get_active_direct(struct ID *screen_id, struct S struct ScrArea *sa, struct Object *ob); /* 3D View */ -struct bGPdata *ED_gpencil_data_get_active_v3d(struct Scene *scene, struct View3D *v3d); +struct bGPdata *ED_gpencil_data_get_active_v3d(struct Scene *scene, struct SceneLayer *scene_layer); bool ED_gpencil_has_keyframe_v3d(struct Scene *scene, struct Object *ob, int cfra); @@ -147,7 +149,12 @@ void ED_gpencil_strokes_copybuf_free(void); void ED_gpencil_draw_2dimage(const struct bContext *C); void ED_gpencil_draw_view2d(const struct bContext *C, bool onlyv2d); -void ED_gpencil_draw_view3d(struct wmWindowManager *wm, struct Scene *scene, struct View3D *v3d, struct ARegion *ar, bool only3d); +void ED_gpencil_draw_view3d(struct wmWindowManager *wm, + struct Scene *scene, + struct SceneLayer *scene_layer, + struct View3D *v3d, + struct ARegion *ar, + bool only3d); void ED_gpencil_draw_ex(struct Scene *scene, struct bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype); void ED_gp_draw_interpolation(struct tGPDinterpolate *tgpi, const int type); diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index 9de550a20ce..00e58785373 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -39,6 +39,7 @@ struct ToolSettings; struct wmWindowManager; struct ARegion; struct Scene; +struct SceneLayer; /* image_edit.c, exported for transform */ struct Image *ED_space_image(struct SpaceImage *sima); @@ -74,7 +75,7 @@ bool ED_space_image_show_uvedit(struct SpaceImage *sima, struct Object *obedit); bool ED_space_image_paint_curve(const struct bContext *C); -bool ED_space_image_check_show_maskedit(struct Scene *scene, struct SpaceImage *sima); +bool ED_space_image_check_show_maskedit(struct SceneLayer *sl, struct SpaceImage *sima); int ED_space_image_maskedit_poll(struct bContext *C); int ED_space_image_maskedit_mask_poll(struct bContext *C); diff --git a/source/blender/editors/include/ED_info.h b/source/blender/editors/include/ED_info.h index 6970abaa633..fe570fef83d 100644 --- a/source/blender/editors/include/ED_info.h +++ b/source/blender/editors/include/ED_info.h @@ -28,7 +28,7 @@ #define __ED_INFO_H__ /* info_stats.c */ -void ED_info_stats_clear(struct Scene *scene); -const char *ED_info_stats_string(struct Scene *scene); +void ED_info_stats_clear(struct SceneLayer *sl); +const char *ED_info_stats_string(struct Scene *scene, struct SceneLayer *sl); #endif /* __ED_INFO_H__ */ diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index c478a8b17e5..62f1a617fcb 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -108,8 +108,10 @@ typedef enum eKeyframeShapeDrawOpts { KEYFRAME_SHAPE_BOTH } eKeyframeShapeDrawOpts; -/* draw simple diamond-shape keyframe (with OpenGL) */ -void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha); +/* draw simple diamond-shape keyframe */ +/* caller should set up vertex format, bind GPU_SHADER_KEYFRAME_DIAMOND, immBegin(GWN_PRIM_POINTS, n), then call this n times */ +void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type, short mode, float alpha, + unsigned int pos_id, unsigned int size_id, unsigned int color_id, unsigned int outline_color_id); /* ******************************* Methods ****************************** */ diff --git a/source/blender/editors/include/ED_manipulator_library.h b/source/blender/editors/include/ED_manipulator_library.h new file mode 100644 index 00000000000..80703321490 --- /dev/null +++ b/source/blender/editors/include/ED_manipulator_library.h @@ -0,0 +1,202 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ED_manipulator_library.h + * \ingroup wm + * + * \name Generic Manipulators. + * + * This is exposes pre-defined manipulators for re-use. + */ + + +#ifndef __ED_MANIPULATOR_LIBRARY_H__ +#define __ED_MANIPULATOR_LIBRARY_H__ + +/* initialize manipulators */ +void ED_manipulatortypes_arrow_2d(void); +void ED_manipulatortypes_arrow_3d(void); +void ED_manipulatortypes_cage_2d(void); +void ED_manipulatortypes_cage_3d(void); +void ED_manipulatortypes_dial_3d(void); +void ED_manipulatortypes_grab_3d(void); +void ED_manipulatortypes_facemap_3d(void); +void ED_manipulatortypes_primitive_3d(void); + +struct wmManipulator; +struct wmManipulatorGroup; + + +/* -------------------------------------------------------------------- */ +/* Shape Presets + * + * Intended to be called by custom draw functions. + */ + +/* manipulator_library_presets.c */ +void ED_manipulator_draw_preset_box( + const struct wmManipulator *mpr, float mat[4][4], int select_id); +void ED_manipulator_draw_preset_arrow( + const struct wmManipulator *mpr, float mat[4][4], int axis, int select_id); +void ED_manipulator_draw_preset_circle( + const struct wmManipulator *mpr, float mat[4][4], int axis, int select_id); +void ED_manipulator_draw_preset_facemap( + const struct bContext *C, const struct wmManipulator *mpr, struct Scene *scene, + struct Object *ob, const int facemap, int select_id); + + +/* -------------------------------------------------------------------- */ +/* 3D Arrow Manipulator */ + +enum { + ED_MANIPULATOR_ARROW_STYLE_NORMAL = 0, + ED_MANIPULATOR_ARROW_STYLE_CROSS = 1, + ED_MANIPULATOR_ARROW_STYLE_BOX = 2, + ED_MANIPULATOR_ARROW_STYLE_CONE = 3, +}; + +enum { + /* inverted offset during interaction - if set it also sets constrained below */ + ED_MANIPULATOR_ARROW_STYLE_INVERTED = (1 << 3), + /* clamp arrow interaction to property width */ + ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED = (1 << 4), +}; + +void ED_manipulator_arrow3d_set_ui_range(struct wmManipulator *mpr, const float min, const float max); +void ED_manipulator_arrow3d_set_range_fac(struct wmManipulator *mpr, const float range_fac); + +/* -------------------------------------------------------------------- */ +/* 2D Arrow Manipulator */ + +/* none */ + +/* -------------------------------------------------------------------- */ +/* Cage Manipulator */ + +enum { + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE = (1 << 0), /* Translates */ + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE = (1 << 1), /* Rotates */ + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE = (1 << 2), /* Scales */ + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM = (1 << 3), /* Scales uniformly */ + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_SIGNED = (1 << 4), /* Negative scale allowed */ +}; + +/* draw_style */ +enum { + ED_MANIPULATOR_CAGE2D_STYLE_BOX = 0, + ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE = 1, +}; + +/* draw_options */ +enum { + /** Draw a central handle (instead of having the entire area selectable) + * Needed for large rectangles that we don't want to swallow all events. */ + ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE = (1 << 0), +}; + +/** #wmManipulator.highlight_part */ +enum { + ED_MANIPULATOR_CAGE2D_PART_TRANSLATE = 0, + ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X = 1, + ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X = 2, + ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y = 3, + ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y = 4, + /* Corners */ + ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y = 5, + ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y = 6, + ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y = 7, + ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y = 8, + + ED_MANIPULATOR_CAGE2D_PART_ROTATE = 9, +}; + +/** #wmManipulator.highlight_part */ +enum { + /* ordered min/mid/max so we can loop over values (MIN/MID/MAX) on each axis. */ + ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z = 0, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MID_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MAX_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MID_Y_MIN_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MID_Y_MID_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MID_Y_MAX_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MIN_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MID_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MAX_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MIN_Y_MIN_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MIN_Y_MID_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MIN_Y_MAX_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MID_Y_MIN_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MID_Y_MID_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MID_Y_MAX_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MAX_Y_MIN_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MAX_Y_MID_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MAX_Y_MAX_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MIN_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MID_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MAX_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MID_Y_MIN_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MID_Y_MID_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MID_Y_MAX_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MIN_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MID_Z, + ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z, + + ED_MANIPULATOR_CAGE3D_PART_TRANSLATE, + + ED_MANIPULATOR_CAGE3D_PART_ROTATE, +}; + +/* -------------------------------------------------------------------- */ +/* Dial Manipulator */ + +/* draw_options */ +enum { + ED_MANIPULATOR_DIAL_DRAW_FLAG_NOP = 0, + ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP = (1 << 0), + ED_MANIPULATOR_DIAL_DRAW_FLAG_FILL = (1 << 1), + ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_MIRROR = (1 << 2), + ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_START_Y = (1 << 3), +}; + +/* -------------------------------------------------------------------- */ +/* Grab Manipulator */ + +/* draw_options */ +enum { + ED_MANIPULATOR_GRAB_DRAW_FLAG_NOP = 0, + /* only for solid shapes */ + ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL = (1 << 0), + ED_MANIPULATOR_GRAB_DRAW_FLAG_ALIGN_VIEW = (1 << 1), +}; + +enum { + ED_MANIPULATOR_GRAB_STYLE_RING_2D = 0, + ED_MANIPULATOR_GRAB_STYLE_CROSS_2D = 1, +}; + + +/* -------------------------------------------------------------------- */ +/* Primitive Manipulator */ + +enum { + ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE = 0, +}; + +#endif /* __ED_MANIPULATOR_LIBRARY_H__ */ diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index c2c00ad5635..1c8cf0665b3 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -36,6 +36,7 @@ extern "C" { #endif struct ID; +struct EvaluationContext; struct View3D; struct ARegion; struct bContext; @@ -113,8 +114,8 @@ struct UvElementMap *BM_uv_element_map_create( void BM_uv_element_map_free(struct UvElementMap *vmap); struct UvElement *BM_uv_element_get(struct UvElementMap *map, struct BMFace *efa, struct BMLoop *l); -bool EDBM_mtexpoly_check(struct BMEditMesh *em); -struct MTexPoly *EDBM_mtexpoly_active_get(struct BMEditMesh *em, struct BMFace **r_act_efa, const bool sloppy, const bool selected); +bool EDBM_uv_check(struct BMEditMesh *em); +struct BMFace *EDBM_uv_active_face_get(struct BMEditMesh *em, const bool sloppy, const bool selected); void BM_uv_vert_map_free(struct UvVertMap *vmap); struct UvMapVert *BM_uv_vert_map_at_index(struct UvVertMap *vmap, unsigned int v); @@ -134,35 +135,36 @@ void EDBM_select_mirrored( int *r_totmirr, int *r_totfail); void EDBM_automerge(struct Scene *scene, struct Object *ob, bool update, const char hflag); -bool EDBM_backbuf_border_init(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); +bool EDBM_backbuf_border_init(const struct EvaluationContext *eval_ctx, struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); bool EDBM_backbuf_check(unsigned int index); void EDBM_backbuf_free(void); -bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2], short tot, - short xmin, short ymin, short xmax, short ymax); -bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads); +bool EDBM_backbuf_border_mask_init( + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, const int mcords[][2], short tot, + short xmin, short ymin, short xmax, short ymax); +bool EDBM_backbuf_circle_init(const struct EvaluationContext *eval_ctx, struct ViewContext *vc, short xs, short ys, short rads); struct BMVert *EDBM_vert_find_nearest_ex( - struct ViewContext *vc, float *r_dist, + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, float *r_dist, const bool use_select_bias, bool use_cycle); struct BMVert *EDBM_vert_find_nearest( - struct ViewContext *vc, float *r_dist); + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, float *r_dist); struct BMEdge *EDBM_edge_find_nearest_ex( - struct ViewContext *vc, float *r_dist, + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, float *r_dist, float *r_dist_center, const bool use_select_bias, const bool use_cycle, struct BMEdge **r_eed_zbuf); struct BMEdge *EDBM_edge_find_nearest( - struct ViewContext *vc, float *r_dist); + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, float *r_dist); struct BMFace *EDBM_face_find_nearest_ex( - struct ViewContext *vc, float *r_dist, + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, float *r_dist, float *r_dist_center, const bool use_select_bias, const bool use_cycle, struct BMFace **r_efa_zbuf); struct BMFace *EDBM_face_find_nearest( - struct ViewContext *vc, float *r_dist); + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, float *r_dist); bool EDBM_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); @@ -199,7 +201,7 @@ void EMBM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct BMEd /* editface.c */ void paintface_flush_flags(struct Object *ob, short flag); bool paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], bool extend, bool deselect, bool toggle); -int do_paintface_box_select(struct ViewContext *vc, struct rcti *rect, bool select, bool extend); +int do_paintface_box_select(const struct EvaluationContext *eval_ctx, struct ViewContext *vc, struct rcti *rect, bool select, bool extend); void paintface_deselect_all_visible(struct Object *ob, int action, bool flush_flags); void paintface_select_linked(struct bContext *C, struct Object *ob, const int mval[2], const bool select); bool paintface_minmax(struct Object *ob, float r_min[3], float r_max[3]); @@ -259,7 +261,6 @@ void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGrou float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum); void ED_vgroup_vert_active_mirror(struct Object *ob, int def_nr); - /* mesh_data.c */ // void ED_mesh_geometry_add(struct Mesh *mesh, struct ReportList *reports, int verts, int edges, int faces); void ED_mesh_polys_add(struct Mesh *mesh, struct ReportList *reports, int count); diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index e3c382382a9..20363c69fa0 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -75,7 +75,7 @@ void ED_init_custom_node_socket_type(struct bNodeSocketType *stype); void ED_init_standard_node_socket_type(struct bNodeSocketType *stype); void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype); void ED_node_sample_set(const float col[4]); -void ED_node_draw_snap(struct View2D *v2d, const float cent[2], float size, NodeBorder border); +void ED_node_draw_snap(struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos); /* node_draw.c */ void ED_node_tree_update(const struct bContext *C); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index cdca848f213..1e5ba378d7d 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -35,6 +35,7 @@ extern "C" { #endif +struct bFaceMap; struct Base; struct EnumPropertyItem; struct ID; @@ -43,6 +44,7 @@ struct ModifierData; struct Object; struct ReportList; struct Scene; +struct SceneLayer; struct bConstraint; struct bContext; struct bPoseChannel; @@ -80,16 +82,21 @@ typedef enum eParentType { PAR_VERTEX_TRI, } eParentType; +typedef enum eObjectSelect_Mode{ + BA_DESELECT = 0, + BA_SELECT = 1, + BA_INVERT = 2, +} eObjectSelect_Mode; + #ifdef __RNA_TYPES_H__ extern struct EnumPropertyItem prop_clear_parent_types[]; extern struct EnumPropertyItem prop_make_parent_types[]; #endif -bool ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob, +bool ED_object_parent_set(struct ReportList *reports, const struct bContext *C, struct Scene *scene, struct Object *ob, struct Object *par, int partype, const bool xmirror, const bool keep_transform, const int vert_par[3]); void ED_object_parent_clear(struct Object *ob, const int type); -struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob); void ED_keymap_proportional_cycle(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap); void ED_keymap_proportional_obmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap); @@ -97,15 +104,12 @@ void ED_keymap_proportional_maskmode(struct wmKeyConfig *keyconf, struct wmKeyMa void ED_keymap_proportional_editmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap, const bool do_connected); -/* send your own notifier for select! */ -void ED_base_object_select(struct Base *base, short mode); -/* includes notifier */ -void ED_base_object_activate(struct bContext *C, struct Base *base); - -void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Base *base); +void ED_object_base_select(struct Base *base, eObjectSelect_Mode mode); +void ED_object_base_activate(struct bContext *C, struct Base *base); +void ED_object_base_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob); /* single object duplicate, if (dupflag == 0), fully linked, else it uses the flags given */ -struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct Base *base, int dupflag); +struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl, struct Base *base, int dupflag); void ED_object_parent(struct Object *ob, struct Object *parent, const int type, const char *substr); @@ -191,8 +195,8 @@ void ED_object_modifier_clear(struct Main *bmain, struct Object *ob); int ED_object_modifier_move_down(struct ReportList *reports, struct Object *ob, struct ModifierData *md); int ED_object_modifier_move_up(struct ReportList *reports, struct Object *ob, struct ModifierData *md); int ED_object_modifier_convert(struct ReportList *reports, struct Main *bmain, struct Scene *scene, - struct Object *ob, struct ModifierData *md); -int ED_object_modifier_apply(struct ReportList *reports, struct Scene *scene, + struct SceneLayer *sl, struct Object *ob, struct ModifierData *md); +int ED_object_modifier_apply(struct ReportList *reports, const struct bContext *C, struct Scene *scene, struct Object *ob, struct ModifierData *md, int mode); int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md); @@ -214,6 +218,10 @@ const struct EnumPropertyItem *ED_object_vgroup_selection_itemf_helper( void ED_object_check_force_modifiers(struct Main *bmain, struct Scene *scene, struct Object *object); +/* object_facemap_ops.c */ +void ED_object_facemap_face_add(struct Object *ob, struct bFaceMap *fmap, int facenum); +void ED_object_facemap_face_remove(struct Object *ob, struct bFaceMap *fmap, int facenum); + #ifdef __cplusplus } #endif diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h index 6cb8c0cfb19..f8bd8a22897 100644 --- a/source/blender/editors/include/ED_particle.h +++ b/source/blender/editors/include/ED_particle.h @@ -38,21 +38,24 @@ struct ParticleEditSettings; struct rcti; struct PTCacheEdit; struct Scene; +struct SceneLayer; /* particle edit mode */ void PE_free_ptcache_edit(struct PTCacheEdit *edit); int PE_start_edit(struct PTCacheEdit *edit); /* access */ -struct PTCacheEdit *PE_get_current(struct Scene *scene, struct Object *ob); -struct PTCacheEdit *PE_create_current(struct Scene *scene, struct Object *ob); -void PE_current_changed(struct Scene *scene, struct Object *ob); -int PE_minmax(struct Scene *scene, float min[3], float max[3]); +struct PTCacheEdit *PE_get_current(struct Scene *scene, struct SceneLayer *sl, struct Object *ob); +struct PTCacheEdit *PE_create_current(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); +void PE_current_changed(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); +int PE_minmax(struct Scene *scene, struct SceneLayer *sl, float min[3], float max[3]); struct ParticleEditSettings *PE_settings(struct Scene *scene); /* update calls */ void PE_hide_keys_time(struct Scene *scene, struct PTCacheEdit *edit, float cfra); -void PE_update_object(struct Scene *scene, struct Object *ob, int useflag); +void PE_update_object( + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct SceneLayer *sl, struct Object *ob, int useflag); /* selection tools */ int PE_mouse_particles(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); @@ -62,13 +65,13 @@ int PE_lasso_select(struct bContext *C, const int mcords[][2], const short moves void PE_deselect_all_visible(struct PTCacheEdit *edit); /* undo */ -void PE_undo_push(struct Scene *scene, const char *str); -void PE_undo_step(struct Scene *scene, int step); -void PE_undo(struct Scene *scene); -void PE_redo(struct Scene *scene); -bool PE_undo_is_valid(struct Scene *scene); -void PE_undo_number(struct Scene *scene, int nr); -const char *PE_undo_get_name(struct Scene *scene, int nr, bool *r_active); +void PE_undo_push(struct Scene *scene, struct SceneLayer *sl, const char *str); +void PE_undo_step(struct Scene *scene, struct SceneLayer *sl, int step); +void PE_undo(struct Scene *scene, struct SceneLayer *sl); +void PE_redo(struct Scene *scene, struct SceneLayer *sl); +bool PE_undo_is_valid(struct Scene *scene, struct SceneLayer *sl); +void PE_undo_number(struct Scene *scene, struct SceneLayer *sl, int nr); +const char *PE_undo_get_name(struct Scene *scene, struct SceneLayer *sl, int nr, bool *r_active); #endif /* __ED_PARTICLE_H__ */ diff --git a/source/blender/editors/include/ED_scene.h b/source/blender/editors/include/ED_scene.h new file mode 100644 index 00000000000..6a4ebf68d3d --- /dev/null +++ b/source/blender/editors/include/ED_scene.h @@ -0,0 +1,43 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ED_scene.h + * \ingroup editors + */ + +#ifndef __ED_SCENE_H__ +#define __ED_SCENE_H__ + +#include "BLI_compiler_attrs.h" + +enum eSceneCopyMethod; + +struct Scene *ED_scene_add(struct Main *bmain, struct bContext *C, struct wmWindow *win, enum eSceneCopyMethod method) ATTR_NONNULL(); +bool ED_scene_delete(struct bContext *C, struct Main *bmain, struct wmWindow *win, struct Scene *scene) ATTR_NONNULL(); +void ED_scene_exit(struct bContext *C) ATTR_NONNULL(); +void ED_scene_changed_update(struct Main *bmain, struct bContext *C, struct Scene *scene_new, + const struct bScreen *active_screen) ATTR_NONNULL(); +bool ED_scene_render_layer_delete( + struct Main *bmain, struct Scene *scene, struct SceneLayer *layer, + struct ReportList *reports) ATTR_NONNULL(1, 2, 3); + +void ED_operatortypes_scene(void); + +#endif /* __ED_SCENE_H__ */ diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 4253e214537..51f1f38a9e9 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -35,21 +35,31 @@ #include "DNA_space_types.h" #include "DNA_view2d_types.h" #include "DNA_view3d_types.h" +#include "DNA_workspace_types.h" +#include "BLI_compiler_attrs.h" + +struct Depsgraph; struct wmWindowManager; struct wmWindow; struct wmNotifier; struct wmEvent; struct wmKeyConfig; +struct WorkSpace; +struct WorkSpaceInstanceHook; struct bContext; struct Scene; +struct SceneLayer; struct bScreen; struct ARegion; struct uiBlock; struct rcti; +struct Main; /* regions */ -void ED_region_do_listen(struct bScreen *sc, struct ScrArea *sa, struct ARegion *ar, struct wmNotifier *note); +void ED_region_do_listen( + struct bScreen *sc, struct ScrArea *sa, struct ARegion *ar, + struct wmNotifier *note, const Scene *scene); void ED_region_do_draw(struct bContext *C, struct ARegion *ar); void ED_region_exit(struct bContext *C, struct ARegion *ar); void ED_region_pixelspace(struct ARegion *ar); @@ -70,6 +80,7 @@ void ED_region_header(const struct bContext *C, struct ARegion *ar); void ED_region_cursor_set(struct wmWindow *win, struct ScrArea *sa, struct ARegion *ar); void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar); void ED_region_info_draw(struct ARegion *ar, const char *text, float fill_color[4], const bool full_redraw); +void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float fill_color[4], const bool full_redraw); void ED_region_image_metadata_draw(int x, int y, struct ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy); void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy); float ED_region_blend_factor(struct ARegion *ar); @@ -84,7 +95,8 @@ int ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *bl void ED_area_initialize(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa); void ED_area_exit(struct bContext *C, struct ScrArea *sa); int ED_screen_area_active(const struct bContext *C); -void ED_area_do_listen(struct bScreen *sc, ScrArea *sa, struct wmNotifier *note); +void ED_area_do_listen(struct bScreen *sc, ScrArea *sa, struct wmNotifier *note, Scene *scene, + struct WorkSpace *workspace); void ED_area_tag_redraw(ScrArea *sa); void ED_area_tag_redraw_regiontype(ScrArea *sa, int type); void ED_area_tag_refresh(ScrArea *sa); @@ -101,12 +113,11 @@ void ED_screens_initialize(struct wmWindowManager *wm); void ED_screen_draw(struct wmWindow *win); void ED_screen_refresh(struct wmWindowManager *wm, struct wmWindow *win); void ED_screen_do_listen(struct bContext *C, struct wmNotifier *note); -bScreen *ED_screen_duplicate(struct wmWindow *win, struct bScreen *sc); -bScreen *ED_screen_add(struct wmWindow *win, struct Scene *scene, const char *name); -bool ED_screen_set(struct bContext *C, struct bScreen *sc); -bool ED_screen_delete(struct bContext *C, struct bScreen *sc); -void ED_screen_set_scene(struct bContext *C, struct bScreen *screen, struct Scene *scene); -bool ED_screen_delete_scene(struct bContext *C, struct Scene *scene); +bool ED_screen_change(struct bContext *C, struct bScreen *sc); +void ED_screen_update_after_scene_change( + const struct bScreen *screen, + struct Scene *scene_new, + struct SceneLayer *scene_layer); void ED_screen_set_subwinactive(struct bContext *C, const struct wmEvent *event); void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen); void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable); @@ -117,10 +128,47 @@ void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa); void ED_screen_full_restore(struct bContext *C, ScrArea *sa); struct ScrArea *ED_screen_state_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *sa, const short state); void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg); -bool ED_screen_stereo3d_required(struct bScreen *screen); +bool ED_screen_stereo3d_required(const struct bScreen *screen, const struct Scene *scene); +Scene *ED_screen_scene_find(const struct bScreen *screen, const struct wmWindowManager *wm); +void ED_screen_preview_render(const struct bScreen *screen, int size_x, int size_y, unsigned int *r_rect) ATTR_NONNULL(); + +/* workspaces */ +struct WorkSpace *ED_workspace_add( + struct Main *bmain, + const char *name, + SceneLayer *act_render_layer, + struct ViewRender *view_render) ATTR_NONNULL(); +bool ED_workspace_change( + struct WorkSpace *workspace_new, + struct bContext *C, + struct wmWindowManager *wm, struct wmWindow *win) ATTR_NONNULL(); +struct WorkSpace *ED_workspace_duplicate( + struct WorkSpace *workspace_old, + struct Main *bmain, struct wmWindow *win); +bool ED_workspace_delete( + struct WorkSpace *workspace, + struct Main *bmain, struct bContext *C, + struct wmWindowManager *wm) ATTR_NONNULL(); +void ED_workspace_scene_data_sync( + struct WorkSpaceInstanceHook *hook, Scene *scene) ATTR_NONNULL(); +void ED_workspace_render_layer_unset( + const struct Main *bmain, const SceneLayer *layer_unset, SceneLayer *layer_new) ATTR_NONNULL(1, 2); +struct WorkSpaceLayout *ED_workspace_layout_add( + struct WorkSpace *workspace, + struct wmWindow *win, + const char *name) ATTR_NONNULL(); +struct WorkSpaceLayout *ED_workspace_layout_duplicate( + struct WorkSpace *workspace, const struct WorkSpaceLayout *layout_old, + struct wmWindow *win) ATTR_NONNULL(); +bool ED_workspace_layout_delete( + struct WorkSpace *workspace, struct WorkSpaceLayout *layout_old, + struct bContext *C) ATTR_NONNULL(); +bool ED_workspace_layout_cycle( + struct WorkSpace *workspace, const short direction, + struct bContext *C) ATTR_NONNULL(); /* anim */ -void ED_update_for_newframe(struct Main *bmain, struct Scene *scene, int mute); +void ED_update_for_newframe(struct Main *bmain, struct Scene *scene, struct SceneLayer *scene_layer, struct Depsgraph *depsgraph); void ED_refresh_viewport_fps(struct bContext *C); int ED_screen_animation_play(struct bContext *C, int sync, int mode); @@ -130,6 +178,8 @@ bScreen *ED_screen_animation_no_scrub(const struct wmWindowManager *wm); /* screen keymaps */ void ED_operatortypes_screen(void); void ED_keymap_screen(struct wmKeyConfig *keyconf); +/* workspace keymaps */ +void ED_operatortypes_workspace(void); /* operators; context poll callbacks */ int ED_operator_screenactive(struct bContext *C); @@ -185,6 +235,7 @@ int ED_operator_posemode_context(struct bContext *C); int ED_operator_posemode(struct bContext *C); int ED_operator_posemode_local(struct bContext *C); int ED_operator_mask(struct bContext *C); +int ED_operator_camera(struct bContext *C); /* Cache display helpers */ diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h index 6daaac5bb42..a81d63d9f25 100644 --- a/source/blender/editors/include/ED_sculpt.h +++ b/source/blender/editors/include/ED_sculpt.h @@ -39,8 +39,7 @@ struct rcti; /* sculpt.c */ void ED_operatortypes_sculpt(void); -void ED_sculpt_redraw_planes_get(float planes[4][4], struct ARegion *ar, - struct RegionView3D *rv3d, struct Object *ob); +void ED_sculpt_redraw_planes_get(float planes[4][4], struct ARegion *ar, struct Object *ob); int ED_sculpt_mask_box_select(struct bContext *C, struct ViewContext *vc, const struct rcti *rect, bool select, bool extend); #endif /* __ED_SCULPT_H__ */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 9a0a7f8f1bb..536f9c22dcd 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -43,6 +43,7 @@ struct wmEvent; struct wmKeyConfig; struct wmKeyMap; struct wmOperatorType; +struct WorkSpace; struct Main; struct SnapObjectContext; struct SnapObjectParams; @@ -109,9 +110,10 @@ enum TfmMode { bool calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], float cent2d[2]); struct TransInfo; -struct Base; struct Scene; struct Object; +struct wmManipulatorGroup; +struct wmManipulatorGroupType; struct wmOperator; /* UNUSED */ @@ -128,7 +130,7 @@ void BIF_createTransformOrientation(struct bContext *C, struct ReportList *repor const char *name, const bool use_view, const bool activate, const bool overwrite); void BIF_selectTransformOrientation(struct bContext *C, struct TransformOrientation *ts); -void BIF_selectTransformOrientationValue(struct bContext *C, int orientation); +void BIF_selectTransformOrientationValue(struct View3D *v3d, int orientation); void ED_getTransformOrientationMatrix(const struct bContext *C, float orientation_mat[3][3], const short around); @@ -153,10 +155,16 @@ int BIF_countTransformOrientation(const struct bContext *C); void Transform_Properties(struct wmOperatorType *ot, int flags); -/* view3d manipulators */ +/* transform manipulators */ + +void TRANSFORM_WGT_manipulator(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_xform_cage(struct wmManipulatorGroupType *wgt); + +bool ED_widgetgroup_manipulator2d_poll(const struct bContext *C, struct wmManipulatorGroupType *wgt); +void ED_widgetgroup_manipulator2d_setup(const struct bContext *C, struct wmManipulatorGroup *mgroup); +void ED_widgetgroup_manipulator2d_refresh(const struct bContext *C, struct wmManipulatorGroup *mgroup); +void ED_widgetgroup_manipulator2d_draw_prepare(const struct bContext *C, struct wmManipulatorGroup *mgroup); -int BIF_do_manipulator(struct bContext *C, const struct wmEvent *event, struct wmOperator *op); -void BIF_draw_manipulator(const struct bContext *C); /* Snapping */ diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h index 156b0ab36b0..2639130acc0 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.h +++ b/source/blender/editors/include/ED_transform_snap_object_context.h @@ -30,11 +30,14 @@ struct BMEdge; struct BMFace; struct ListBase; +struct RenderEngineType; struct Scene; +struct SceneLayer; struct Main; struct Object; struct ARegion; struct View3D; +struct bContext; /* transform_snap_object.c */ @@ -73,9 +76,9 @@ struct SnapObjectParams { typedef struct SnapObjectContext SnapObjectContext; SnapObjectContext *ED_transform_snap_object_context_create( - struct Main *bmain, struct Scene *scene, int flag); + struct Main *bmain, struct Scene *scene, struct SceneLayer *sl, struct RenderEngineType *engine, int flag); SnapObjectContext *ED_transform_snap_object_context_create_view3d( - struct Main *bmain, struct Scene *scene, int flag, + struct Main *bmain, struct Scene *scene, struct SceneLayer *sl, struct RenderEngineType *engine, int flag, /* extra args for view3d */ const struct ARegion *ar, const struct View3D *v3d); void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx); diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 354a9655a48..641cc523873 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -35,12 +35,13 @@ struct BMesh; struct BMEditMesh; struct BMFace; struct BMLoop; +struct Depsgraph; struct Image; struct ImageUser; -struct MTexPoly; struct Main; struct Object; struct Scene; +struct SceneLayer; struct SpaceImage; struct bNode; struct wmKeyConfig; @@ -51,6 +52,7 @@ void ED_keymap_uvedit(struct wmKeyConfig *keyconf); void ED_uvedit_assign_image(struct Main *bmain, struct Scene *scene, struct Object *obedit, struct Image *ima, struct Image *previma); bool ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obedit, float min[2], float max[2]); +bool ED_uvedit_center(Scene *scene, Image *ima, struct Object *obedit, float cent[2], char mode); void ED_uvedit_select_all(struct BMesh *bm); bool ED_object_get_active_image(struct Object *ob, int mat_nr, @@ -60,7 +62,7 @@ void ED_object_assign_active_image(struct Main *bmain, struct Object *ob, int ma bool ED_uvedit_test(struct Object *obedit); /* visibility and selection */ -bool uvedit_face_visible_test(struct Scene *scene, struct Image *ima, struct BMFace *efa, struct MTexPoly *tf); +bool uvedit_face_visible_test(struct Scene *scene, struct Image *ima, struct BMFace *efa); bool uvedit_face_select_test(struct Scene *scene, struct BMFace *efa, const int cd_loop_uv_offset); bool uvedit_edge_select_test(struct Scene *scene, struct BMLoop *l, @@ -110,7 +112,7 @@ void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel) /* uvedit_draw.c */ void ED_image_draw_cursor(struct ARegion *ar, const float cursor[2]); -void ED_uvedit_draw_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct Object *obedit, struct Object *obact); +void ED_uvedit_draw_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct SceneLayer *sl, struct Object *obedit, struct Object *obact, struct Depsgraph *depsgraph); /* uvedit_buttons.c */ void ED_uvedit_buttons_register(struct ARegionType *art); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 85fb0ee4447..8116a1ba456 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -40,7 +40,10 @@ struct BPoint; struct Base; struct BezTriple; struct BoundBox; +struct Camera; +struct Depsgraph; struct EditBone; +struct EvaluationContext; struct ImBuf; struct MVert; struct Main; @@ -49,14 +52,15 @@ struct Nurb; struct Object; struct RV3DMatrixStore; struct RegionView3D; +struct RenderEngineType; struct Scene; +struct SceneLayer; struct ScrArea; struct View3D; struct ViewContext; struct bContext; struct bPoseChannel; struct bScreen; -struct bglMats; struct rctf; struct rcti; struct wmOperator; @@ -66,11 +70,15 @@ struct wmWindowManager; struct GPUFX; struct GPUOffScreen; struct GPUFXSettings; +struct WorkSpace; enum eGPUFXFlags; /* for derivedmesh drawing callbacks, for view3d_select, .... */ typedef struct ViewContext { + struct Depsgraph *depsgraph; struct Scene *scene; + struct SceneLayer *scene_layer; + struct RenderEngineType *engine; struct Object *obact; struct Object *obedit; struct ARegion *ar; @@ -108,10 +116,10 @@ void ED_view3d_lastview_store(struct RegionView3D *rv3d); void ED_view3d_depth_update(struct ARegion *ar); float ED_view3d_depth_read_cached(const struct ViewContext *vc, const int mval[2]); bool ED_view3d_depth_read_cached_normal( - const ViewContext *vc, const struct bglMats *mats, const int mval[2], + const ViewContext *vc, const int mval[2], float r_normal[3]); bool ED_view3d_depth_unproject( - const struct ARegion *ar, const struct bglMats *mats, + const struct ARegion *ar, const int mval[2], const double depth, float r_location_world[3]); void ED_view3d_depth_tag_update(struct RegionView3D *rv3d); @@ -148,20 +156,20 @@ typedef enum { /* foreach iterators */ void meshobject_foreachScreenVert( - struct ViewContext *vc, + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, void (*func)(void *userData, struct MVert *eve, const float screen_co[2], int index), void *userData, const eV3DProjTest clip_flag); void mesh_foreachScreenVert( - struct ViewContext *vc, + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, void (*func)(void *userData, struct BMVert *eve, const float screen_co[2], int index), void *userData, const eV3DProjTest clip_flag); void mesh_foreachScreenEdge( - struct ViewContext *vc, + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, void (*func)(void *userData, struct BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index), void *userData, const eV3DProjTest clip_flag); void mesh_foreachScreenFace( - struct ViewContext *vc, + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, void (*func)(void *userData, struct BMFace *efa, const float screen_co[2], int index), void *userData, const eV3DProjTest clip_flag); void nurbs_foreachScreenVert( @@ -239,7 +247,9 @@ bool ED_view3d_win_to_segment(const struct ARegion *ar, struct View3D *v3d, cons float r_ray_start[3], float r_ray_end[3], const bool do_clip); void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]); void ED_view3d_ob_project_mat_get_from_obmat(const struct RegionView3D *rv3d, float obmat[4][4], float pmat[4][4]); -void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z); + +void ED_view3d_project(const struct ARegion *ar, const float world[3], float region[3]); +bool ED_view3d_unproject(const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3]); /* end */ @@ -264,11 +274,13 @@ void ED_view3d_calc_camera_border_size( const struct Scene *scene, const struct ARegion *ar, const struct View3D *v3d, const struct RegionView3D *rv3d, float r_size[2]); -bool ED_view3d_calc_render_border(struct Scene *scene, struct View3D *v3d, - struct ARegion *ar, struct rcti *rect); +bool ED_view3d_calc_render_border( + const struct Scene *scene, struct View3D *v3d, + struct ARegion *ar, struct rcti *rect); void ED_view3d_clipping_calc_from_boundbox(float clip[6][4], const struct BoundBox *clipbb, const bool is_flip); -void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4], struct bglMats *mats, const struct rcti *rect); +void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4], + const struct ARegion *ar, const struct Object *ob, const struct rcti *rect); void ED_view3d_clipping_local(struct RegionView3D *rv3d, float mat[4][4]); bool ED_view3d_clipping_test(const struct RegionView3D *rv3d, const float co[3], const bool is_local); void ED_view3d_clipping_set(struct RegionView3D *rv3d); @@ -284,24 +296,26 @@ float ED_view3d_radius_to_dist( const char persp, const bool use_aspect, const float radius); -void drawcircball(int mode, const float cent[3], float rad, const float tmat[4][4]); +void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos); /* backbuffer select and draw support */ -void ED_view3d_backbuf_validate(struct ViewContext *vc); -struct ImBuf *ED_view3d_backbuf_read(struct ViewContext *vc, int xmin, int ymin, int xmax, int ymax); +void ED_view3d_backbuf_validate(const struct EvaluationContext *eval_ctx, struct ViewContext *vc); +struct ImBuf *ED_view3d_backbuf_read( + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, int xmin, int ymin, int xmax, int ymax); unsigned int ED_view3d_backbuf_sample_rect( - struct ViewContext *vc, const int mval[2], int size, + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, const int mval[2], int size, unsigned int min, unsigned int max, float *r_dist); int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist); -unsigned int ED_view3d_backbuf_sample(struct ViewContext *vc, int x, int y); +unsigned int ED_view3d_backbuf_sample( + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, int x, int y); bool ED_view3d_autodist( - struct Scene *scene, struct ARegion *ar, struct View3D *v3d, + const struct EvaluationContext *eval_ctx, struct Depsgraph *graph, struct ARegion *ar, struct View3D *v3d, const int mval[2], float mouse_worldloc[3], const bool alphaoverride, const float fallback_depth_pt[3]); /* only draw so ED_view3d_autodist_simple can be called many times after */ -void ED_view3d_autodist_init(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, int mode); +void ED_view3d_autodist_init(const struct EvaluationContext *eval_ctx, struct Depsgraph *graph, struct ARegion *ar, struct View3D *v3d, int mode); bool ED_view3d_autodist_simple(struct ARegion *ar, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth); bool ED_view3d_autodist_depth(struct ARegion *ar, const int mval[2], int margin, float *depth); bool ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], const int mval_end[2], int margin, float *depth); @@ -323,7 +337,7 @@ void view3d_opengl_select_cache_begin(void); void view3d_opengl_select_cache_end(void); int view3d_opengl_select( - struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input, + const struct EvaluationContext *eval_ctx, struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input, eV3DSelectMode select_mode); /* view3d_select.c */ @@ -332,7 +346,6 @@ void view3d_set_viewcontext(struct bContext *C, struct ViewContext *vc); void view3d_operator_needs_opengl(const struct bContext *C); void view3d_region_operator_needs_opengl(struct wmWindow *win, struct ARegion *ar); void view3d_opengl_read_pixels(struct ARegion *ar, int x, int y, int w, int h, int format, int type, void *data); -void view3d_get_transformation(const struct ARegion *ar, struct RegionView3D *rv3d, struct Object *ob, struct bglMats *mats); /* XXX should move to BLI_math */ bool edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2]); @@ -356,24 +369,31 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active); struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d); void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat); +void ED_draw_object_facemap(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, const float col[4], const int facemap); + bool ED_view3d_context_activate(struct bContext *C); -void ED_view3d_draw_offscreen_init(struct Scene *scene, struct View3D *v3d); +void ED_view3d_draw_offscreen_init( + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct SceneLayer *sl, struct View3D *v3d); void ED_view3d_draw_offscreen( - struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4], + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct SceneLayer *scene_layer, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4], float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, const char *viewname, struct GPUFX *fx, struct GPUFXSettings *fx_settings, struct GPUOffScreen *ofs); void ED_view3d_draw_setup_view( - struct wmWindow *win, struct Scene *scene, struct ARegion *ar, struct View3D *v3d, + struct wmWindow *win, const struct EvaluationContext *eval_ctx, struct Scene *scene, struct ARegion *ar, struct View3D *v3d, float viewmat[4][4], float winmat[4][4], const struct rcti *rect); struct ImBuf *ED_view3d_draw_offscreen_imbuf( - struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, - unsigned int flag, bool draw_background, + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct SceneLayer *scene_layer, struct View3D *v3d, struct ARegion *ar, + int sizex, int sizey, unsigned int flag, bool draw_background, int alpha_mode, int samples, bool full_samples, const char *viewname, struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]); struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple( - struct Scene *scene, struct Object *camera, int width, int height, + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct SceneLayer *scene_layer, struct Object *camera, int width, int height, unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, int samples, bool full_samples, const char *viewname, struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]); @@ -381,7 +401,7 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple( struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]); void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip); void ED_view3d_update_viewmat( - struct Scene *scene, struct View3D *v3d, struct ARegion *ar, + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4], const struct rcti *rect); bool ED_view3d_quat_from_axis_view(const char view, float quat[4]); char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon); @@ -390,7 +410,7 @@ char ED_view3d_axis_view_opposite(char view); bool ED_view3d_lock(struct RegionView3D *rv3d); uint64_t ED_view3d_datamask(const struct Scene *scene, const struct View3D *v3d); -uint64_t ED_view3d_screen_datamask(const struct bScreen *screen); +uint64_t ED_view3d_screen_datamask(const struct Scene *scene, const struct bScreen *screen); bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d); @@ -411,10 +431,6 @@ bool ED_view3d_camera_lock_autokey( void ED_view3D_lock_clear(struct View3D *v3d); -struct BGpic *ED_view3D_background_image_new(struct View3D *v3d); -void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic); -void ED_view3D_background_image_clear(struct View3D *v3d); - #define VIEW3D_MARGIN 1.4f #define VIEW3D_DIST_FALLBACK 1.0f diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 0e936fdd313..c955cd27cfc 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -261,6 +261,7 @@ typedef enum { UI_BTYPE_CHECKBOX = (13 << 9), /* similar to toggle, display a 'tick' */ UI_BTYPE_CHECKBOX_N = (14 << 9), UI_BTYPE_COLOR = (15 << 9), + UI_BTYPE_TAB = (16 << 9), UI_BTYPE_SCROLL = (18 << 9), UI_BTYPE_BLOCK = (19 << 9), UI_BTYPE_LABEL = (20 << 9), @@ -313,18 +314,22 @@ typedef enum { * Functions to draw various shapes, taking theme settings into account. * Used for code that draws its own UI style elements. */ -void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad); void UI_draw_roundbox_corner_set(int type); +void UI_draw_roundbox_aa(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4]); +void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4]); +void UI_draw_roundbox_3ubAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const unsigned char col[3], unsigned char alpha); +void UI_draw_roundbox_3fvAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[3], float alpha); +void UI_draw_roundbox_shade_x(bool filled, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown, const float col[4]); + +#if 0 /* unused */ int UI_draw_roundbox_corner_get(void); -void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad); +void UI_draw_roundbox_shade_y(bool filled, float minx, float miny, float maxx, float maxy, float rad, float shadeleft, float shaderight, const float col[4]); +#endif + void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy); -void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad); -void UI_draw_roundbox_shade_x(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown); -void UI_draw_roundbox_shade_y(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeLeft, float shadeRight); -void UI_draw_text_underline(int pos_x, int pos_y, int len, int height); +void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4]); -void UI_draw_safe_areas( - float x1, float x2, float y1, float y2, +void UI_draw_safe_areas(uint pos, float x1, float x2, float y1, float y2, const float title_aspect[2], const float action_aspect[2]); /* state for scrolldrawing */ @@ -800,7 +805,6 @@ void UI_popup_handlers_remove_all(struct bContext *C, struct ListBase *handlers) void UI_init(void); void UI_init_userdef(void); void UI_reinit_font(void); -void UI_reinit_gl_state(void); void UI_exit(void); /* Layout @@ -865,9 +869,6 @@ enum { UI_CNR_ALL = (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT) }; -/* not apart of the corner flags but mixed in some functions */ -#define UI_RB_ALPHA (UI_CNR_ALL + 1) - uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, struct uiStyle *style); void UI_block_layout_set_current(uiBlock *block, uiLayout *layout); void UI_block_layout_resolve(uiBlock *block, int *x, int *y); @@ -926,6 +927,17 @@ void uiTemplateIDPreview(uiLayout *layout, struct bContext *C, struct PointerRNA const char *newop, const char *openop, const char *unlinkop, int rows, int cols); void uiTemplateAnyID(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *proptypename, const char *text); +void uiTemplateSearch( + uiLayout *layout, struct bContext *C, + struct PointerRNA *ptr, const char *propname, + struct PointerRNA *searchptr, const char *searchpropname, + const char *newop, const char *unlinkop); +void uiTemplateSearchPreview( + uiLayout *layout, struct bContext *C, + struct PointerRNA *ptr, const char *propname, + struct PointerRNA *searchptr, const char *searchpropname, + const char *newop, const char *unlinkop, + const int rows, const int cols); void uiTemplatePathBuilder(uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *root_ptr, const char *text); uiLayout *uiTemplateModifier(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr); @@ -962,6 +974,11 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C); void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C); void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C); void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr); +void uiTemplateOverrideProperty( + uiLayout *layout, struct PointerRNA *collection_props_ptr, struct PointerRNA *scene_props_ptr, + const char *propname, + const char *name, const char *text_ctxt, int translate, int icon, + const char *custom_template); void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name); void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color); void uiTemplateCacheFile(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname); @@ -1071,20 +1088,22 @@ void UI_context_active_but_prop_get_templateID( /* Styled text draw */ void UI_fontstyle_set(const struct uiFontStyle *fs); -void UI_fontstyle_draw_ex( - const struct uiFontStyle *fs, const struct rcti *rect, const char *str, - size_t len, float *r_xofs, float *r_yofs); -void UI_fontstyle_draw(const struct uiFontStyle *fs, const struct rcti *rect, const char *str); -void UI_fontstyle_draw_rotated(const struct uiFontStyle *fs, const struct rcti *rect, const char *str); -void UI_fontstyle_draw_simple(const struct uiFontStyle *fs, float x, float y, const char *str); +void UI_fontstyle_draw_ex(const struct uiFontStyle *fs, const struct rcti *rect, const char *str, + const unsigned char col[4], size_t len, float *r_xofs, float *r_yofs); +void UI_fontstyle_draw(const struct uiFontStyle *fs, const struct rcti *rect, const char *str, + const unsigned char col[4]); +void UI_fontstyle_draw_rotated(const struct uiFontStyle *fs, const struct rcti *rect, const char *str, + const unsigned char col[4]); +void UI_fontstyle_draw_simple(const struct uiFontStyle *fs, float x, float y, const char *str, + const unsigned char col[4]); void UI_fontstyle_draw_simple_backdrop( const struct uiFontStyle *fs, float x, float y, const char *str, - const unsigned char fg[4], const unsigned char bg[4]); + const float col_fg[4], const float col_bg[4]); int UI_fontstyle_string_width(const struct uiFontStyle *fs, const char *str); int UI_fontstyle_height_max(const struct uiFontStyle *fs); -void UI_draw_icon_tri(float x, float y, char dir); +void UI_draw_icon_tri(float x, float y, char dir, const float[4]); struct uiStyle *UI_style_get(void); /* use for fonts etc */ struct uiStyle *UI_style_get_dpi(void); /* DPI scaled settings for drawing */ diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index 945ac1b6db9..cee68ed361c 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -66,6 +66,7 @@ void UI_id_icon_render( int UI_preview_render_size(enum eIconSizes size); void UI_icon_draw(float x, float y, int icon_id); +void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha); void UI_icon_draw_preview(float x, float y, int icon_id); void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect); void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, float alpha, int size); diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index a0efd586af5..7d2837ffe4e 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -279,6 +279,12 @@ enum { TH_AXIS_Y, TH_AXIS_Z, + TH_MANIPULATOR_HI, + TH_MANIPULATOR_PRIMARY, + TH_MANIPULATOR_SECONDARY, + TH_MANIPULATOR_A, + TH_MANIPULATOR_B, + TH_LOW_GRAD, TH_HIGH_GRAD, TH_SHOW_BACK_GRAD, @@ -319,13 +325,13 @@ struct bThemeState { void UI_ThemeColor(int colorid); // sets the color plus alpha -void UI_ThemeColor4(int colorid); +void UI_ThemeColor4(int colorid); // sets color plus offset for shade -void UI_ThemeColorShade(int colorid, int offset); +void UI_ThemeColorShade(int colorid, int offset); // sets color plus offset for alpha -void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset); +void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset); // sets color, which is blend between two theme colors void UI_ThemeColorBlend(int colorid1, int colorid2, float fac); @@ -343,14 +349,27 @@ int UI_GetThemeValueType(int colorid, int spacetype); // get three color values, scaled to 0.0-1.0 range void UI_GetThemeColor3fv(int colorid, float col[3]); void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned char col[3]); +void UI_GetThemeColorBlend3f(int colorid1, int colorid2, float fac, float r_col[3]); // get the color, range 0.0-1.0, complete with shading offset void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3]); void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3]); +void UI_GetThemeColorShade4ubv(int colorid, int offset, unsigned char col[4]); + +// get three color values, range 0-255, complete with shading offset for the RGB components and blending +void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int offset, unsigned char col[3]); // get four color values, scaled to 0.0-1.0 range void UI_GetThemeColor4fv(int colorid, float col[4]); // get four color values, range 0.0-1.0, complete with shading offset for the RGB components void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4]); +void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4]); + +// get four colour values ranged between 0 and 255; includes the alpha channel +void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset, unsigned char col[4]); + +// get four color values, range 0.0-1.0, complete with shading offset for the RGB components and blending +void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int offset, float col[3]); +void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4]); // get the 3 or 4 byte values void UI_GetThemeColor3ubv(int colorid, unsigned char col[3]); @@ -368,6 +387,10 @@ void UI_GetColorPtrShade3ubv(const unsigned char cp1[3], unsigned char col[3] // get a 3 byte color, blended and shaded between two other char color pointers void UI_GetColorPtrBlendShade3ubv(const unsigned char cp1[3], const unsigned char cp2[3], unsigned char col[3], float fac, int offset); +// sets the font color +// (for anything fancy use UI_GetThemeColor[Fancy] then BLF_color) +void UI_FontThemeColor(int fontid, int colorid); + // clear the openGL ClearColor using the input colorid void UI_ThemeClearColor(int colorid); diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index 7392db0c91b..03a2c1ec414 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../gpu ../../imbuf ../../makesdna diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 5f36c5e21bf..234355c8581 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -56,7 +56,8 @@ #include "BKE_screen.h" #include "BKE_idprop.h" -#include "BIF_gl.h" +#include "GPU_glew.h" +#include "GPU_matrix.h" #include "BLF_api.h" #include "BLT_translation.h" @@ -509,6 +510,7 @@ static int ui_but_calc_float_precision(uiBut *but, double value) static void ui_draw_linkline(uiLinkLine *line, int highlightActiveLines, int dashInactiveLines) { rcti rect; + float color[4] = {1.0f}; if (line->from == NULL || line->to == NULL) return; @@ -518,15 +520,15 @@ static void ui_draw_linkline(uiLinkLine *line, int highlightActiveLines, int das rect.ymax = BLI_rctf_cent_y(&line->to->rect); if (dashInactiveLines) - UI_ThemeColor(TH_GRID); + UI_GetThemeColor4fv(TH_GRID, color); else if (line->flag & UI_SELECT) - glColor3ub(100, 100, 100); + rgba_float_args_set_ch(color, 100, 100, 100, 255); else if (highlightActiveLines && ((line->from->flag & UI_ACTIVE) || (line->to->flag & UI_ACTIVE))) - UI_ThemeColor(TH_TEXT_HI); + UI_GetThemeColor4fv(TH_TEXT_HI, color); else - glColor3ub(0, 0, 0); + rgba_float_args_set_ch(color, 0, 0, 0, 255); - ui_draw_link_bezier(&rect); + ui_draw_link_bezier(&rect, color); } static void ui_draw_links(uiBlock *block) @@ -1400,11 +1402,9 @@ void UI_block_draw(const bContext *C, uiBlock *block) ui_but_to_pixelrect(&rect, ar, block, NULL); /* pixel space for AA widgets */ - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); + gpuPushProjectionMatrix(); + gpuPushMatrix(); + gpuLoadIdentity(); wmOrtho2_region_pixelspace(ar); @@ -1429,10 +1429,8 @@ void UI_block_draw(const bContext *C, uiBlock *block) } /* restore matrix */ - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + gpuPopProjectionMatrix(); + gpuPopMatrix(); if (multisample_enabled) glEnable(GL_MULTISAMPLE); @@ -1486,6 +1484,7 @@ int ui_but_is_pushed_ex(uiBut *but, double *value) break; case UI_BTYPE_ROW: case UI_BTYPE_LISTROW: + case UI_BTYPE_TAB: UI_GET_BUT_VALUE_INIT(but, *value); /* support for rna enum buts */ if (but->rnaprop && (RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG)) { @@ -2425,7 +2424,7 @@ static void ui_but_string_free_internal(uiBut *but) bool ui_but_string_set(bContext *C, uiBut *but, const char *str) { - if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { + if (but->rnaprop && but->rnapoin.data && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { if (RNA_property_editable(&but->rnapoin, but->rnaprop)) { PropertyType type; @@ -2472,8 +2471,15 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) } else if (but->type == UI_BTYPE_TEXT) { /* string */ - if (ui_but_is_utf8(but)) BLI_strncpy_utf8(but->poin, str, but->hardmax); - else BLI_strncpy(but->poin, str, but->hardmax); + if (!but->poin || (str[0] == '\0')) { + str = ""; + } + else if (ui_but_is_utf8(but)) { + BLI_strncpy_utf8(but->poin, str, but->hardmax); + } + else { + BLI_strncpy(but->poin, str, but->hardmax); + } return true; } @@ -2685,6 +2691,10 @@ static void ui_but_free(const bContext *C, uiBut *but) MEM_freeN(but->hold_argN); } + if (!but->editstr && but->free_search_arg) { + MEM_SAFE_FREE(but->search_arg); + } + if (but->active) { /* XXX solve later, buttons should be free-able without context ideally, * however they may have open tooltips or popup windows, which need to @@ -2837,11 +2847,13 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]); } else { + const bScreen *screen = WM_window_get_active_screen(window); + /* no subwindow created yet, for menus for example, so we * use the main window instead, since buttons are created * there anyway */ - wm_subwindow_matrix_get(window, window->screen->mainwin, block->winmat); - wm_subwindow_size_get(window, window->screen->mainwin, &getsizex, &getsizey); + wm_subwindow_matrix_get(window, screen->mainwin, block->winmat); + wm_subwindow_size_get(window, screen->mainwin, &getsizex, &getsizey); block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]); block->auto_open = true; @@ -3558,7 +3570,7 @@ static uiBut *ui_def_but_rna( } const char *info; - if (!RNA_property_editable_info(&but->rnapoin, prop, &info)) { + if (but->rnapoin.data && !RNA_property_editable_info(&but->rnapoin, prop, &info)) { ui_def_but_rna__disable(but, info); } @@ -4457,7 +4469,7 @@ static void operator_enum_search_cb(const struct bContext *C, void *but, const c for (item = item_array; item->identifier; item++) { /* note: need to give the index rather than the identifier because the enum can be freed */ if (BLI_strcasestr(item->name, str)) { - if (false == UI_search_item_add(items, item->name, SET_INT_IN_POINTER(item->value), 0)) + if (false == UI_search_item_add(items, item->name, SET_INT_IN_POINTER(item->value), item->icon)) break; } } @@ -4588,7 +4600,7 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) tmp = BLI_strdup(RNA_property_identifier(but->rnaprop)); } else if (type == BUT_GET_RNASTRUCT_IDENTIFIER) { - if (but->rnaprop) + if (but->rnaprop && but->rnapoin.data) tmp = BLI_strdup(RNA_struct_identifier(but->rnapoin.type)); else if (but->optype) tmp = BLI_strdup(but->optype->idname); @@ -4683,7 +4695,10 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) if (ptr && prop) { if (!item) { int i; - + + /* so the context is passed to itemf functions */ + WM_operator_properties_sanitize(ptr, false); + RNA_property_enum_items_gettexted(C, ptr, prop, &items, &totitems, &free_items); for (i = 0, item = items; i < totitems; i++, item++) { if (item->identifier[0] && item->value == value) diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c index 500744c366d..9aeb685a907 100644 --- a/source/blender/editors/interface/interface_align.c +++ b/source/blender/editors/interface/interface_align.c @@ -110,9 +110,9 @@ enum { bool ui_but_can_align(const uiBut *but) { - return ( - !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE) && - (BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f)); + const bool btype_can_align = !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, + UI_BTYPE_TAB, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE); + return (btype_can_align && (BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f)); } /** diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index a04360b3395..812f4ef0747 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -39,11 +39,12 @@ #include "BLI_utildefines.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_nla.h" +#include "DEG_depsgraph_build.h" + #include "ED_keyframing.h" #include "UI_interface.h" @@ -211,7 +212,7 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str) /* updates */ driver->flag |= DRIVER_FLAG_RECOMPILE; - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME, NULL); ok = true; } diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 01ea1e953fa..e46c6a0e267 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -50,13 +50,14 @@ #include "IMB_imbuf_types.h" #include "IMB_colormanagement.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "BLF_api.h" -#include "GPU_draw.h" -#include "GPU_basic_shader.h" +#include "GPU_batch.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" #include "UI_interface.h" @@ -71,336 +72,462 @@ void UI_draw_roundbox_corner_set(int type) * if this is undone, it's not that big a deal, only makes curves edges * square for the */ roundboxtype = type; - } +#if 0 /* unused */ int UI_draw_roundbox_corner_get(void) { return roundboxtype; } +#endif + +void UI_draw_roundbox_3ubAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const unsigned char col[3], unsigned char alpha) +{ + float colv[4]; + colv[0] = ((float)col[0]) / 255; + colv[1] = ((float)col[1]) / 255; + colv[2] = ((float)col[2]) / 255; + colv[3] = ((float)alpha) / 255; + UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv); +} + +void UI_draw_roundbox_3fvAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[3], float alpha) +{ + float colv[4]; + colv[0] = col[0]; + colv[1] = col[1]; + colv[2] = col[2]; + colv[3] = alpha; + UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv); +} -void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad) +void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4]) { float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293}, {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; int a; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + /* mult */ for (a = 0; a < 7; a++) { mul_v2_fl(vec[a], rad); } - glBegin(mode); + unsigned int vert_ct = 0; + vert_ct += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; + vert_ct += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; + vert_ct += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; + vert_ct += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv(col); + immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_ct); /* start with corner right-bottom */ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - glVertex2f(maxx - rad, miny); + immVertex2f(pos, maxx - rad, miny); for (a = 0; a < 7; a++) { - glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]); + immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); } - glVertex2f(maxx, miny + rad); + immVertex2f(pos, maxx, miny + rad); } else { - glVertex2f(maxx, miny); + immVertex2f(pos, maxx, miny); } /* corner right-top */ if (roundboxtype & UI_CNR_TOP_RIGHT) { - glVertex2f(maxx, maxy - rad); + immVertex2f(pos, maxx, maxy - rad); for (a = 0; a < 7; a++) { - glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]); + immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); } - glVertex2f(maxx - rad, maxy); + immVertex2f(pos, maxx - rad, maxy); } else { - glVertex2f(maxx, maxy); + immVertex2f(pos, maxx, maxy); } /* corner left-top */ if (roundboxtype & UI_CNR_TOP_LEFT) { - glVertex2f(minx + rad, maxy); + immVertex2f(pos, minx + rad, maxy); for (a = 0; a < 7; a++) { - glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]); + immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); } - glVertex2f(minx, maxy - rad); + immVertex2f(pos, minx, maxy - rad); } else { - glVertex2f(minx, maxy); + immVertex2f(pos, minx, maxy); } /* corner left-bottom */ if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - glVertex2f(minx, miny + rad); + immVertex2f(pos, minx, miny + rad); for (a = 0; a < 7; a++) { - glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]); + immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); } - glVertex2f(minx + rad, miny); + immVertex2f(pos, minx + rad, miny); } else { - glVertex2f(minx, miny); + immVertex2f(pos, minx, miny); } - glEnd(); + immEnd(); + immUnbindProgram(); } -static void round_box_shade_col(const float col1[3], float const col2[3], const float fac) +static void round_box_shade_col(unsigned attrib, const float col1[3], float const col2[3], const float fac) { - float col[3] = { + float col[4] = { fac * col1[0] + (1.0f - fac) * col2[0], fac * col1[1] + (1.0f - fac) * col2[1], - fac * col1[2] + (1.0f - fac) * col2[2] + fac * col1[2] + (1.0f - fac) * col2[2], + 1.0f }; - glColor3fv(col); + immAttrib4fv(attrib, col); } /* linear horizontal shade within button or in outline */ /* view2d scrollers use it */ void UI_draw_roundbox_shade_x( - int mode, float minx, float miny, float maxx, float maxy, - float rad, float shadetop, float shadedown) + bool filled, float minx, float miny, float maxx, float maxy, + float rad, float shadetop, float shadedown, const float col[4]) { float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293}, {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; const float div = maxy - miny; const float idiv = 1.0f / div; - float coltop[3], coldown[3], color[4]; + float coltop[3], coldown[3]; + int vert_count = 0; int a; - + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + /* mult */ for (a = 0; a < 7; a++) { mul_v2_fl(vec[a], rad); } - /* get current color, needs to be outside of glBegin/End */ - glGetFloatv(GL_CURRENT_COLOR, color); /* 'shade' defines strength of shading */ - coltop[0] = min_ff(1.0f, color[0] + shadetop); - coltop[1] = min_ff(1.0f, color[1] + shadetop); - coltop[2] = min_ff(1.0f, color[2] + shadetop); - coldown[0] = max_ff(0.0f, color[0] + shadedown); - coldown[1] = max_ff(0.0f, color[1] + shadedown); - coldown[2] = max_ff(0.0f, color[2] + shadedown); + coltop[0] = min_ff(1.0f, col[0] + shadetop); + coltop[1] = min_ff(1.0f, col[1] + shadetop); + coltop[2] = min_ff(1.0f, col[2] + shadetop); + coldown[0] = max_ff(0.0f, col[0] + shadedown); + coldown[1] = max_ff(0.0f, col[1] + shadedown); + coldown[2] = max_ff(0.0f, col[2] + shadedown); - glBegin(mode); + vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; + + immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_count); /* start with corner right-bottom */ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - round_box_shade_col(coltop, coldown, 0.0); - glVertex2f(maxx - rad, miny); + round_box_shade_col(color, coltop, coldown, 0.0); + immVertex2f(pos, maxx - rad, miny); for (a = 0; a < 7; a++) { - round_box_shade_col(coltop, coldown, vec[a][1] * idiv); - glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]); + round_box_shade_col(color, coltop, coldown, vec[a][1] * idiv); + immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); } - round_box_shade_col(coltop, coldown, rad * idiv); - glVertex2f(maxx, miny + rad); + round_box_shade_col(color, coltop, coldown, rad * idiv); + immVertex2f(pos, maxx, miny + rad); } else { - round_box_shade_col(coltop, coldown, 0.0); - glVertex2f(maxx, miny); + round_box_shade_col(color, coltop, coldown, 0.0); + immVertex2f(pos, maxx, miny); } /* corner right-top */ if (roundboxtype & UI_CNR_TOP_RIGHT) { - round_box_shade_col(coltop, coldown, (div - rad) * idiv); - glVertex2f(maxx, maxy - rad); + round_box_shade_col(color, coltop, coldown, (div - rad) * idiv); + immVertex2f(pos, maxx, maxy - rad); for (a = 0; a < 7; a++) { - round_box_shade_col(coltop, coldown, (div - rad + vec[a][1]) * idiv); - glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]); + round_box_shade_col(color, coltop, coldown, (div - rad + vec[a][1]) * idiv); + immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); } - round_box_shade_col(coltop, coldown, 1.0); - glVertex2f(maxx - rad, maxy); + round_box_shade_col(color, coltop, coldown, 1.0); + immVertex2f(pos, maxx - rad, maxy); } else { - round_box_shade_col(coltop, coldown, 1.0); - glVertex2f(maxx, maxy); + round_box_shade_col(color, coltop, coldown, 1.0); + immVertex2f(pos, maxx, maxy); } /* corner left-top */ if (roundboxtype & UI_CNR_TOP_LEFT) { - round_box_shade_col(coltop, coldown, 1.0); - glVertex2f(minx + rad, maxy); + round_box_shade_col(color, coltop, coldown, 1.0); + immVertex2f(pos, minx + rad, maxy); for (a = 0; a < 7; a++) { - round_box_shade_col(coltop, coldown, (div - vec[a][1]) * idiv); - glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]); + round_box_shade_col(color, coltop, coldown, (div - vec[a][1]) * idiv); + immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); } - round_box_shade_col(coltop, coldown, (div - rad) * idiv); - glVertex2f(minx, maxy - rad); + round_box_shade_col(color, coltop, coldown, (div - rad) * idiv); + immVertex2f(pos, minx, maxy - rad); } else { - round_box_shade_col(coltop, coldown, 1.0); - glVertex2f(minx, maxy); + round_box_shade_col(color, coltop, coldown, 1.0); + immVertex2f(pos, minx, maxy); } /* corner left-bottom */ if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - round_box_shade_col(coltop, coldown, rad * idiv); - glVertex2f(minx, miny + rad); + round_box_shade_col(color, coltop, coldown, rad * idiv); + immVertex2f(pos, minx, miny + rad); for (a = 0; a < 7; a++) { - round_box_shade_col(coltop, coldown, (rad - vec[a][1]) * idiv); - glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]); + round_box_shade_col(color, coltop, coldown, (rad - vec[a][1]) * idiv); + immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); } - round_box_shade_col(coltop, coldown, 0.0); - glVertex2f(minx + rad, miny); + round_box_shade_col(color, coltop, coldown, 0.0); + immVertex2f(pos, minx + rad, miny); } else { - round_box_shade_col(coltop, coldown, 0.0); - glVertex2f(minx, miny); + round_box_shade_col(color, coltop, coldown, 0.0); + immVertex2f(pos, minx, miny); } - - glEnd(); + + immEnd(); + immUnbindProgram(); } +#if 0 /* unused */ /* linear vertical shade within button or in outline */ /* view2d scrollers use it */ void UI_draw_roundbox_shade_y( - int mode, float minx, float miny, float maxx, float maxy, - float rad, float shadeLeft, float shadeRight) + bool filled, float minx, float miny, float maxx, float maxy, + float rad, float shadeleft, float shaderight, const float col[4]) { float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293}, {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; const float div = maxx - minx; const float idiv = 1.0f / div; - float colLeft[3], colRight[3], color[4]; + float colLeft[3], colRight[3]; + int vert_count = 0; int a; /* mult */ for (a = 0; a < 7; a++) { mul_v2_fl(vec[a], rad); } - /* get current color, needs to be outside of glBegin/End */ - glGetFloatv(GL_CURRENT_COLOR, color); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); /* 'shade' defines strength of shading */ - colLeft[0] = min_ff(1.0f, color[0] + shadeLeft); - colLeft[1] = min_ff(1.0f, color[1] + shadeLeft); - colLeft[2] = min_ff(1.0f, color[2] + shadeLeft); - colRight[0] = max_ff(0.0f, color[0] + shadeRight); - colRight[1] = max_ff(0.0f, color[1] + shadeRight); - colRight[2] = max_ff(0.0f, color[2] + shadeRight); + colLeft[0] = min_ff(1.0f, col[0] + shadeleft); + colLeft[1] = min_ff(1.0f, col[1] + shadeleft); + colLeft[2] = min_ff(1.0f, col[2] + shadeleft); + colRight[0] = max_ff(0.0f, col[0] + shaderight); + colRight[1] = max_ff(0.0f, col[1] + shaderight); + colRight[2] = max_ff(0.0f, col[2] + shaderight); + - glBegin(mode); + vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; + + immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_count); /* start with corner right-bottom */ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - round_box_shade_col(colLeft, colRight, 0.0); - glVertex2f(maxx - rad, miny); + round_box_shade_col(color, colLeft, colRight, 0.0); + immVertex2f(pos, maxx - rad, miny); for (a = 0; a < 7; a++) { - round_box_shade_col(colLeft, colRight, vec[a][0] * idiv); - glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]); + round_box_shade_col(color, colLeft, colRight, vec[a][0] * idiv); + immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); } - round_box_shade_col(colLeft, colRight, rad * idiv); - glVertex2f(maxx, miny + rad); + round_box_shade_col(color, colLeft, colRight, rad * idiv); + immVertex2f(pos, maxx, miny + rad); } else { - round_box_shade_col(colLeft, colRight, 0.0); - glVertex2f(maxx, miny); + round_box_shade_col(color, colLeft, colRight, 0.0); + immVertex2f(pos, maxx, miny); } /* corner right-top */ if (roundboxtype & UI_CNR_TOP_RIGHT) { - round_box_shade_col(colLeft, colRight, 0.0); - glVertex2f(maxx, maxy - rad); + round_box_shade_col(color, colLeft, colRight, 0.0); + immVertex2f(pos, maxx, maxy - rad); for (a = 0; a < 7; a++) { - round_box_shade_col(colLeft, colRight, (div - rad - vec[a][0]) * idiv); - glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]); + round_box_shade_col(color, colLeft, colRight, (div - rad - vec[a][0]) * idiv); + immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); } - round_box_shade_col(colLeft, colRight, (div - rad) * idiv); - glVertex2f(maxx - rad, maxy); + round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv); + immVertex2f(pos, maxx - rad, maxy); } else { - round_box_shade_col(colLeft, colRight, 0.0); - glVertex2f(maxx, maxy); + round_box_shade_col(color, colLeft, colRight, 0.0); + immVertex2f(pos, maxx, maxy); } /* corner left-top */ if (roundboxtype & UI_CNR_TOP_LEFT) { - round_box_shade_col(colLeft, colRight, (div - rad) * idiv); - glVertex2f(minx + rad, maxy); + round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv); + immVertex2f(pos, minx + rad, maxy); for (a = 0; a < 7; a++) { - round_box_shade_col(colLeft, colRight, (div - rad + vec[a][0]) * idiv); - glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]); + round_box_shade_col(color, colLeft, colRight, (div - rad + vec[a][0]) * idiv); + immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); } - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx, maxy - rad); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx, maxy - rad); } else { - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx, maxy); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx, maxy); } /* corner left-bottom */ if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx, miny + rad); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx, miny + rad); for (a = 0; a < 7; a++) { - round_box_shade_col(colLeft, colRight, (vec[a][0]) * idiv); - glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]); + round_box_shade_col(color, colLeft, colRight, (vec[a][0]) * idiv); + immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); } - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx + rad, miny); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx + rad, miny); } else { - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx, miny); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx, miny); } - - glEnd(); + + immEnd(); + immUnbindProgram(); } +#endif /* unused */ -/* plain antialiased unfilled rectangle */ -void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad) +void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4]) { - float color[4]; - - if (roundboxtype & UI_RB_ALPHA) { - glGetFloatv(GL_CURRENT_COLOR, color); - color[3] = 0.5; - glColor4fv(color); - glEnable(GL_BLEND); - } - - /* set antialias line */ - glEnable(GL_LINE_SMOOTH); - glEnable(GL_BLEND); + int ofs_y = 4 * U.pixelsize; - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, minx, miny, maxx, maxy, rad); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); - glDisable(GL_BLEND); - glDisable(GL_LINE_SMOOTH); -} + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv(color); -/* (old, used in outliner) plain antialiased filled box */ -void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad) -{ - ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA); + immRecti(pos, pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize)); + immUnbindProgram(); } -void UI_draw_text_underline(int pos_x, int pos_y, int len, int height) +/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */ + +/* based on UI_draw_roundbox_gl_mode, check on making a version which allows us to skip some sides */ +void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highlight[3], unsigned char highlight_fade[3]) { - int ofs_y = 4 * U.pixelsize; - glRecti(pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize)); -} + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + /* add a 1px offset, looks nicer */ + const int minx = rect->xmin + U.pixelsize, maxx = rect->xmax - U.pixelsize; + const int miny = rect->ymin + U.pixelsize, maxy = rect->ymax - U.pixelsize; + int a; + float vec[4][2] = { + {0.195, 0.02}, + {0.55, 0.169}, + {0.831, 0.45}, + {0.98, 0.805}, + }; -/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */ + + /* mult */ + for (a = 0; a < 4; a++) { + mul_v2_fl(vec[a], rad); + } + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + immBeginAtMost(GWN_PRIM_LINE_STRIP, 25); + + immAttrib3ubv(col, highlight); + + /* start with corner left-top */ + if (roundboxtype & UI_CNR_TOP_LEFT) { + immVertex2f(pos, minx, maxy - rad); + for (a = 0; a < 4; a++) { + immVertex2f(pos, minx + vec[a][1], maxy - rad + vec[a][0]); + } + immVertex2f(pos, minx + rad, maxy); + } + else { + immVertex2f(pos, minx, maxy); + } + + /* corner right-top */ + if (roundboxtype & UI_CNR_TOP_RIGHT) { + immVertex2f(pos, maxx - rad, maxy); + for (a = 0; a < 4; a++) { + immVertex2f(pos, maxx - rad + vec[a][0], maxy - vec[a][1]); + } + immVertex2f(pos, maxx, maxy - rad); + } + else { + immVertex2f(pos, maxx, maxy); + } + + immAttrib3ubv(col, highlight_fade); + + /* corner right-bottom */ + if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { + immVertex2f(pos, maxx, miny + rad); + for (a = 0; a < 4; a++) { + immVertex2f(pos, maxx - vec[a][1], miny + rad - vec[a][0]); + } + immVertex2f(pos, maxx - rad, miny); + } + else { + immVertex2f(pos, maxx, miny); + } + + /* corner left-bottom */ + if (roundboxtype & UI_CNR_BOTTOM_LEFT) { + immVertex2f(pos, minx + rad, miny); + for (a = 0; a < 4; a++) { + immVertex2f(pos, minx + rad - vec[a][0], miny + vec[a][1]); + } + immVertex2f(pos, minx, miny + rad); + } + else { + immVertex2f(pos, minx, miny); + } + + immAttrib3ubv(col, highlight); + + /* back to corner left-top */ + immVertex2f(pos, minx, roundboxtype & UI_CNR_TOP_LEFT ? maxy - rad : maxy); + + immEnd(); + immUnbindProgram(); +} void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect) { @@ -411,15 +538,15 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w ImBuf *ibuf = (ImBuf *)but->poin; if (!ibuf) return; + + float facx = 1.0f; + float facy = 1.0f; int w = BLI_rcti_size_x(rect); int h = BLI_rcti_size_y(rect); /* scissor doesn't seem to be doing the right thing...? */ #if 0 - //glColor4f(1.0, 0.f, 0.f, 1.f); - //fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax) - /* prevent drawing outside widget area */ GLint scissor[4]; glGetIntegerv(GL_SCISSOR_BOX, scissor); @@ -427,16 +554,15 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w #endif glEnable(GL_BLEND); - glColor4f(0.0, 0.0, 0.0, 0.0); if (w != ibuf->x || h != ibuf->y) { - float facx = (float)w / (float)ibuf->x; - float facy = (float)h / (float)ibuf->y; - glPixelZoom(facx, facy); + facx = (float)w / (float)ibuf->x; + facy = (float)h / (float)ibuf->y; } - glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect); - - glPixelZoom(1.0f, 1.0f); + + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, (float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect, + facx, facy, NULL); glDisable(GL_BLEND); @@ -451,43 +577,34 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w /** * Draw title and text safe areas. * - * The first 4 parameters are the offsets for the view, not the zones. + * \Note This functionn is to be used with the 2D dashed shader enabled. + * + * \param pos is a PRIM_FLOAT, 2, GWN_FETCH_FLOAT vertex attrib + * \param line_origin is a PRIM_FLOAT, 2, GWN_FETCH_FLOAT vertex attrib + * + * The next 4 parameters are the offsets for the view, not the zones. */ void UI_draw_safe_areas( - float x1, float x2, float y1, float y2, + uint pos, float x1, float x2, float y1, float y2, const float title_aspect[2], const float action_aspect[2]) { const float size_x_half = (x2 - x1) * 0.5f; const float size_y_half = (y2 - y1) * 0.5f; const float *safe_areas[] = {title_aspect, action_aspect}; - int safe_len = ARRAY_SIZE(safe_areas); - bool is_first = true; + const int safe_len = ARRAY_SIZE(safe_areas); for (int i = 0; i < safe_len; i++) { if (safe_areas[i][0] || safe_areas[i][1]) { - float margin_x, margin_y; - float minx, miny, maxx, maxy; + float margin_x = safe_areas[i][0] * size_x_half; + float margin_y = safe_areas[i][1] * size_y_half; - if (is_first) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0); - is_first = false; - } + float minx = x1 + margin_x; + float miny = y1 + margin_y; + float maxx = x2 - margin_x; + float maxy = y2 - margin_y; - margin_x = safe_areas[i][0] * size_x_half; - margin_y = safe_areas[i][1] * size_y_half; - - minx = x1 + margin_x; - miny = y1 + margin_y; - maxx = x2 - margin_x; - maxy = y2 - margin_y; - - glBegin(GL_LINE_LOOP); - glVertex2f(maxx, miny); - glVertex2f(maxx, maxy); - glVertex2f(minx, maxy); - glVertex2f(minx, miny); - glEnd(); + imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy); } } } @@ -501,52 +618,60 @@ static void draw_scope_end(const rctf *rect, GLint *scissor) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* outline */ - glColor4f(0.f, 0.f, 0.f, 0.5f); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f); + float color[4] = {0.0f, 0.0f, 0.0f, 0.5f}; + UI_draw_roundbox_4fv(false, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f, color); } static void histogram_draw_one( float r, float g, float b, float alpha, - float x, float y, float w, float h, const float *data, int res, const bool is_line) + float x, float y, float w, float h, const float *data, int res, const bool is_line, + unsigned int pos_attrib) { + float color[4] = {r, g, b, alpha}; + + /* that can happen */ + if (res == 0) + return; + glEnable(GL_LINE_SMOOTH); glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glColor4f(r, g, b, alpha); + + immUniformColor4fv(color); if (is_line) { /* curve outline */ glLineWidth(1.5); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, res); for (int i = 0; i < res; i++) { float x2 = x + i * (w / (float)res); - glVertex2f(x2, y + (data[i] * h)); + immVertex2f(pos_attrib, x2, y + (data[i] * h)); } - glEnd(); + immEnd(); } else { /* under the curve */ - glBegin(GL_TRIANGLE_STRIP); - glVertex2f(x, y); - glVertex2f(x, y + (data[0] * h)); + immBegin(GWN_PRIM_TRI_STRIP, res * 2); + immVertex2f(pos_attrib, x, y); + immVertex2f(pos_attrib, x, y + (data[0] * h)); for (int i = 1; i < res; i++) { float x2 = x + i * (w / (float)res); - glVertex2f(x2, y + (data[i] * h)); - glVertex2f(x2, y); + immVertex2f(pos_attrib, x2, y + (data[i] * h)); + immVertex2f(pos_attrib, x2, y); } - glEnd(); + immEnd(); /* curve outline */ - glColor4f(0.f, 0.f, 0.f, 0.25f); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.25f); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, res); for (int i = 0; i < res; i++) { float x2 = x + i * (w / (float)res); - glVertex2f(x2, y + (data[i] * h)); + immVertex2f(pos_attrib, x2, y + (data[i] * h)); } - glEnd(); + immEnd(); } glDisable(GL_LINE_SMOOTH); @@ -559,7 +684,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) Histogram *hist = (Histogram *)but->poin; int res = hist->x_resolution; const bool is_line = (hist->flag & HISTO_FLAG_LINE) != 0; - + rctf rect = { .xmin = (float)recti->xmin + 1, .xmax = (float)recti->xmax - 1, @@ -573,9 +698,10 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - UI_ThemeColor4(TH_PREVIEW_BACK); + float color[4]; + UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f); + UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); /* need scissor test, histogram can draw outside of boundary */ GLint scissor[4]; @@ -585,34 +711,48 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); - glColor4f(1.f, 1.f, 1.f, 0.08f); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f); /* draw grid lines here */ for (int i = 1; i <= HISTOGRAM_TOT_GRID_LINES; i++) { const float fac = (float)i / (float)HISTOGRAM_TOT_GRID_LINES; /* so we can tell the 1.0 color point */ if (i == HISTOGRAM_TOT_GRID_LINES) { - glColor4f(1.0f, 1.0f, 1.0f, 0.5f); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f); } - fdrawline(rect.xmin, rect.ymin + fac * h, rect.xmax, rect.ymin + fac * h); - fdrawline(rect.xmin + fac * w, rect.ymin, rect.xmin + fac * w, rect.ymax); + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, rect.xmin, rect.ymin + fac * h); + immVertex2f(pos, rect.xmax, rect.ymin + fac * h); + + immVertex2f(pos, rect.xmin + fac * w, rect.ymin); + immVertex2f(pos, rect.xmin + fac * w, rect.ymax); + + immEnd(); } - + if (hist->mode == HISTO_MODE_LUMA) { - histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line); + histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line, pos); } else if (hist->mode == HISTO_MODE_ALPHA) { - histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line); + histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line, pos); } else { if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_R) - histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line); + histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line, pos); if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_G) - histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line); + histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line, pos); if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_B) - histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line); + histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line, pos); } + + immUnbindProgram(); /* outline */ draw_scope_end(&rect, scissor); @@ -620,6 +760,25 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) #undef HISTOGRAM_TOT_GRID_LINES +static void waveform_draw_one(float *waveform, int nbr, const float col[3]) +{ + Gwn_VertFormat format = {0}; + unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, nbr); + + GWN_vertbuf_attr_fill(vbo, pos_id, waveform); + + /* TODO store the Gwn_Batch inside the scope */ + Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO); + GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR); + GWN_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f); + GWN_batch_draw(batch); + + GWN_batch_discard(batch); +} + void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) { Scopes *scopes = (Scopes *)but->poin; @@ -642,7 +801,7 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), scopes->wavefrm_yfac = 0.98f; float w = BLI_rctf_size_x(&rect) - 7; float h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac; - float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) / 2.0f; + float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) * 0.5f; float w3 = w / 3.0f; /* log scale for alpha */ @@ -660,9 +819,10 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - UI_ThemeColor4(TH_PREVIEW_BACK); + float color[4]; + UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f); + UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); /* need scissor test, waveform can draw outside of boundary */ glGetIntegerv(GL_VIEWPORT, scissor); @@ -671,94 +831,119 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); - glColor4f(1.f, 1.f, 1.f, 0.08f); - /* draw grid lines here */ + /* draw scale numbers first before binding any shader */ for (int i = 0; i < 6; i++) { char str[4]; BLI_snprintf(str, sizeof(str), "%-3d", i * 20); str[3] = '\0'; - fdrawline(rect.xmin + 22, yofs + (i / 5.f) * h, rect.xmax + 1, yofs + (i / 5.f) * h); - BLF_draw_default(rect.xmin + 1, yofs - 5 + (i / 5.f) * h, 0, str, sizeof(str) - 1); - /* in the loop because blf_draw reset it */ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + BLF_color4f(BLF_default(), 1.0f, 1.0f, 1.0f, 0.08f); + BLF_draw_default(rect.xmin + 1, yofs - 5 + (i * 0.2f) * h, 0, str, sizeof(str) - 1); + } + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f); + + /* draw grid lines here */ + immBegin(GWN_PRIM_LINES, 12); + + for (int i = 0; i < 6; i++) { + immVertex2f(pos, rect.xmin + 22, yofs + (i * 0.2f) * h); + immVertex2f(pos, rect.xmax + 1, yofs + (i * 0.2f) * h); } + + immEnd(); + /* 3 vertical separation */ if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) { + immBegin(GWN_PRIM_LINES, 4); + for (int i = 1; i < 3; i++) { - fdrawline(rect.xmin + i * w3, rect.ymin, rect.xmin + i * w3, rect.ymax); + immVertex2f(pos, rect.xmin + i * w3, rect.ymin); + immVertex2f(pos, rect.xmin + i * w3, rect.ymax); } + + immEnd(); } /* separate min max zone on the right */ - fdrawline(rect.xmin + w, rect.ymin, rect.xmin + w, rect.ymax); + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, rect.xmin + w, rect.ymin); + immVertex2f(pos, rect.xmin + w, rect.ymax); + immEnd(); + /* 16-235-240 level in case of ITU-R BT601/709 */ - glColor4f(1.f, 0.4f, 0.f, 0.2f); + immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f); if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)) { - fdrawline(rect.xmin + 22, yofs + h * 16.0f / 255.0f, rect.xmax + 1, yofs + h * 16.0f / 255.0f); - fdrawline(rect.xmin + 22, yofs + h * 235.0f / 255.0f, rect.xmin + w3, yofs + h * 235.0f / 255.0f); - fdrawline(rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f, rect.xmax + 1, yofs + h * 235.0f / 255.0f); - fdrawline(rect.xmin + w3, yofs + h * 240.0f / 255.0f, rect.xmax + 1, yofs + h * 240.0f / 255.0f); + immBegin(GWN_PRIM_LINES, 8); + + immVertex2f(pos, rect.xmin + 22, yofs + h * 16.0f / 255.0f); + immVertex2f(pos, rect.xmax + 1, yofs + h * 16.0f / 255.0f); + + immVertex2f(pos, rect.xmin + 22, yofs + h * 235.0f / 255.0f); + immVertex2f(pos, rect.xmin + w3, yofs + h * 235.0f / 255.0f); + + immVertex2f(pos, rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f); + immVertex2f(pos, rect.xmax + 1, yofs + h * 235.0f / 255.0f); + + immVertex2f(pos, rect.xmin + w3, yofs + h * 240.0f / 255.0f); + immVertex2f(pos, rect.xmax + 1, yofs + h * 240.0f / 255.0f); + + immEnd(); } /* 7.5 IRE black point level for NTSC */ - if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) - fdrawline(rect.xmin, yofs + h * 0.075f, rect.xmax + 1, yofs + h * 0.075f); + if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) { + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, rect.xmin, yofs + h * 0.075f); + immVertex2f(pos, rect.xmax + 1, yofs + h * 0.075f); + immEnd(); + } if (scopes->ok && scopes->waveform_1 != NULL) { - - /* LUMA (1 channel) */ glBlendFunc(GL_ONE, GL_ONE); - glColor3f(alpha, alpha, alpha); glPointSize(1.0); + /* LUMA (1 channel) */ if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) { + float col[3] = {alpha, alpha, alpha}; - glBlendFunc(GL_ONE, GL_ONE); - - glPushMatrix(); - glEnableClientState(GL_VERTEX_ARRAY); - - glTranslatef(rect.xmin, yofs, 0.f); - glScalef(w, h, 0.f); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + gpuPushMatrix(); + gpuTranslate2f(rect.xmin, yofs); + gpuScale2f(w, h); - glDisableClientState(GL_VERTEX_ARRAY); - glPopMatrix(); + waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, col); + + gpuPopMatrix(); /* min max */ - glColor3f(0.5f, 0.5f, 0.5f); + immUniformColor3f(0.5f, 0.5f, 0.5f); min = yofs + scopes->minmax[0][0] * h; max = yofs + scopes->minmax[0][1] * h; CLAMP(min, rect.ymin, rect.ymax); CLAMP(max, rect.ymin, rect.ymax); - fdrawline(rect.xmax - 3, min, rect.xmax - 3, max); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, rect.xmax - 3, min); + immVertex2f(pos, rect.xmax - 3, max); + immEnd(); } /* RGB (3 channel) */ else if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) { - glBlendFunc(GL_ONE, GL_ONE); - - glEnableClientState(GL_VERTEX_ARRAY); - - glPushMatrix(); + gpuPushMatrix(); + gpuTranslate2f(rect.xmin, yofs); + gpuScale2f(w, h); - glTranslatef(rect.xmin, yofs, 0.f); - glScalef(w, h, 0.f); + waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, colors_alpha[0]); + waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, colors_alpha[1]); + waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, colors_alpha[2]); - glColor3fv( colors_alpha[0] ); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - - glColor3fv( colors_alpha[1] ); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - - glColor3fv( colors_alpha[2] ); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - - glDisableClientState(GL_VERTEX_ARRAY); - glPopMatrix(); + gpuPopMatrix(); } /* PARADE / YCC (3 channels) */ else if (ELEM(scopes->wavefrm_mode, @@ -770,49 +955,47 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), { int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE); - glBlendFunc(GL_ONE, GL_ONE); - - glPushMatrix(); - glEnableClientState(GL_VERTEX_ARRAY); + gpuPushMatrix(); + gpuTranslate2f(rect.xmin, yofs); + gpuScale2f(w3, h); - glTranslatef(rect.xmin, yofs, 0.f); - glScalef(w3, h, 0.f); + waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, (rgb) ? colors_alpha[0] : colorsycc_alpha[0]); - glColor3fv((rgb) ? colors_alpha[0] : colorsycc_alpha[0]); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + gpuTranslate2f(1.0f, 0.0f); + waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, (rgb) ? colors_alpha[1] : colorsycc_alpha[1]); - glTranslatef(1.f, 0.f, 0.f); - glColor3fv((rgb) ? colors_alpha[1] : colorsycc_alpha[1]); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + gpuTranslate2f(1.0f, 0.0f); + waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, (rgb) ? colors_alpha[2] : colorsycc_alpha[2]); - glTranslatef(1.f, 0.f, 0.f); - glColor3fv((rgb) ? colors_alpha[2] : colorsycc_alpha[2]); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - - glDisableClientState(GL_VERTEX_ARRAY); - glPopMatrix(); + gpuPopMatrix(); } + /* min max */ if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA ) { for (int c = 0; c < 3; c++) { if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_RGB_PARADE, SCOPES_WAVEFRM_RGB)) - glColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f); + immUniformColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f); else - glColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f); + immUniformColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f); min = yofs + scopes->minmax[c][0] * h; max = yofs + scopes->minmax[c][1] * h; CLAMP(min, rect.ymin, rect.ymax); CLAMP(max, rect.ymin, rect.ymax); - fdrawline(rect.xmin + w + 2 + c * 2, min, rect.xmin + w + 2 + c * 2, max); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, rect.xmin + w + 2 + c * 2, min); + immVertex2f(pos, rect.xmin + w + 2 + c * 2, max); + immEnd(); } } } - + + immUnbindProgram(); + /* outline */ draw_scope_end(&rect, scissor); + + glDisable(GL_BLEND); } static float polar_to_x(float center, float diam, float ampli, float angle) @@ -825,10 +1008,10 @@ static float polar_to_y(float center, float diam, float ampli, float angle) return center + diam * ampli * sinf(angle); } -static void vectorscope_draw_target(float centerx, float centery, float diam, const float colf[3]) +static void vectorscope_draw_target(unsigned int pos, float centerx, float centery, float diam, const float colf[3]) { float y, u, v; - float tangle = 0.f, tampli; + float tangle = 0.0f, tampli; float dangle, dampli, dangle2, dampli2; rgb_to_yuv(colf[0], colf[1], colf[2], &y, &u, &v); @@ -840,41 +1023,41 @@ static void vectorscope_draw_target(float centerx, float centery, float diam, co tampli = sqrtf(u * u + v * v); /* small target vary by 2.5 degree and 2.5 IRE unit */ - glColor4f(1.0f, 1.0f, 1.0, 0.12f); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f); dangle = DEG2RADF(2.5f); dampli = 2.5f / 200.0f; - glBegin(GL_LINE_LOOP); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle)); - glEnd(); + immBegin(GWN_PRIM_LINE_LOOP, 4); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle)); + immEnd(); /* big target vary by 10 degree and 20% amplitude */ - glColor4f(1.0f, 1.0f, 1.0, 0.12f); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f); dangle = DEG2RADF(10.0f); dampli = 0.2f * tampli; dangle2 = DEG2RADF(5.0f); dampli2 = 0.5f * dampli; - glBegin(GL_LINE_STRIP); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2)); - glEnd(); - glBegin(GL_LINE_STRIP); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2)); - glEnd(); - glBegin(GL_LINE_STRIP); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2)); - glEnd(); - glBegin(GL_LINE_STRIP); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2)); - glEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2)); + immEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2)); + immEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2)); + immEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2)); + immEnd(); } void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) @@ -895,8 +1078,8 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco float w = BLI_rctf_size_x(&rect); float h = BLI_rctf_size_y(&rect); - float centerx = rect.xmin + w / 2; - float centery = rect.ymin + h / 2; + float centerx = rect.xmin + w * 0.5f; + float centery = rect.ymin + h * 0.5f; float diam = (w < h) ? w : h; float alpha = scopes->vecscope_alpha * scopes->vecscope_alpha * scopes->vecscope_alpha; @@ -904,9 +1087,10 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - UI_ThemeColor4(TH_PREVIEW_BACK); + float color[4]; + UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f); + UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); /* need scissor test, hvectorscope can draw outside of boundary */ GLint scissor[4]; @@ -916,93 +1100,109 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); - glColor4f(1.f, 1.f, 1.f, 0.08f); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f); /* draw grid elements */ /* cross */ - fdrawline(centerx - (diam / 2) - 5, centery, centerx + (diam / 2) + 5, centery); - fdrawline(centerx, centery - (diam / 2) - 5, centerx, centery + (diam / 2) + 5); + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, centerx - (diam * 0.5f) - 5, centery); + immVertex2f(pos, centerx + (diam * 0.5f) + 5, centery); + + immVertex2f(pos, centerx, centery - (diam * 0.5f) - 5); + immVertex2f(pos, centerx, centery + (diam * 0.5f) + 5); + + immEnd(); + /* circles */ for (int j = 0; j < 5; j++) { - glBegin(GL_LINE_LOOP); const int increment = 15; + immBegin(GWN_PRIM_LINE_LOOP, (int)(360 / increment)); for (int i = 0; i <= 360 - increment; i += increment) { const float a = DEG2RADF((float)i); - const float r = (j + 1) / 10.0f; - glVertex2f(polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a)); + const float r = (j + 1) * 0.1f; + immVertex2f(pos, polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a)); } - glEnd(); + immEnd(); } /* skin tone line */ - glColor4f(1.f, 0.4f, 0.f, 0.2f); - fdrawline(polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5, skin_rad), - polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1, skin_rad)); + immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5f, skin_rad)); + immVertex2f(pos, polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1f, skin_rad)); + immEnd(); + /* saturation points */ for (int i = 0; i < 6; i++) - vectorscope_draw_target(centerx, centery, diam, colors[i]); + vectorscope_draw_target(pos, centerx, centery, diam, colors[i]); if (scopes->ok && scopes->vecscope != NULL) { /* pixel point cloud */ + float col[3] = {alpha, alpha, alpha}; + glBlendFunc(GL_ONE, GL_ONE); - glColor3f(alpha, alpha, alpha); + glPointSize(1.0); - glPushMatrix(); - glEnableClientState(GL_VERTEX_ARRAY); + gpuPushMatrix(); + gpuTranslate2f(centerx, centery); + gpuScaleUniform(diam); - glTranslatef(centerx, centery, 0.f); - glScalef(diam, diam, 0.f); + waveform_draw_one(scopes->vecscope, scopes->waveform_tot, col); - glVertexPointer(2, GL_FLOAT, 0, scopes->vecscope); - glPointSize(1.0); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - - glDisableClientState(GL_VERTEX_ARRAY); - glPopMatrix(); + gpuPopMatrix(); } + immUnbindProgram(); + /* outline */ draw_scope_end(&rect, scissor); glDisable(GL_BLEND); } -static void ui_draw_colorband_handle_tri_hlight(float x1, float y1, float halfwidth, float height) +static void ui_draw_colorband_handle_tri_hlight(unsigned int pos, float x1, float y1, float halfwidth, float height) { glEnable(GL_LINE_SMOOTH); - glBegin(GL_LINE_STRIP); - glVertex2f(x1 + halfwidth, y1); - glVertex2f(x1, y1 + height); - glVertex2f(x1 - halfwidth, y1); - glEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, x1 + halfwidth, y1); + immVertex2f(pos, x1, y1 + height); + immVertex2f(pos, x1 - halfwidth, y1); + immEnd(); glDisable(GL_LINE_SMOOTH); } -static void ui_draw_colorband_handle_tri(float x1, float y1, float halfwidth, float height, bool fill) +static void ui_draw_colorband_handle_tri(unsigned int pos, float x1, float y1, float halfwidth, float height, bool fill) { glEnable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH); - glBegin(fill ? GL_TRIANGLES : GL_LINE_LOOP); - glVertex2f(x1 + halfwidth, y1); - glVertex2f(x1, y1 + height); - glVertex2f(x1 - halfwidth, y1); - glEnd(); + immBegin(fill ? GWN_PRIM_TRIS : GWN_PRIM_LINE_LOOP, 3); + immVertex2f(pos, x1 + halfwidth, y1); + immVertex2f(pos, x1, y1 + height); + immVertex2f(pos, x1 - halfwidth, y1); + immEnd(); glDisable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH); } -static void ui_draw_colorband_handle_box(float x1, float y1, float x2, float y2, bool fill) +static void ui_draw_colorband_handle_box(unsigned int pos, float x1, float y1, float x2, float y2, bool fill) { - glBegin(fill ? GL_QUADS : GL_LINE_LOOP); - glVertex2f(x1, y1); - glVertex2f(x1, y2); - glVertex2f(x2, y2); - glVertex2f(x2, y1); - glEnd(); + immBegin(fill ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, 4); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x1, y2); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x2, y1); + immEnd(); } static void ui_draw_colorband_handle( - const rcti *rect, float x, + uint shdr_pos, const rcti *rect, float x, const float rgb[3], struct ColorManagedDisplay *display, bool active) { @@ -1021,18 +1221,26 @@ static void ui_draw_colorband_handle( y1 = floorf(y1 + 0.5f); if (active || half_width < min_width) { - glBegin(GL_LINES); - glColor3ub(0, 0, 0); - glVertex2f(x, y1); - glVertex2f(x, y2); - glEnd(); - setlinestyle(active ? 2 : 1); - glBegin(GL_LINES); - glColor3ub(200, 200, 200); - glVertex2f(x, y1); - glVertex2f(x, y2); - glEnd(); - setlinestyle(0); + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 2); /* "advanced" mode */ + immUniformArray4fv("colors", (float *)(float[][4]){{0.8f, 0.8f, 0.8f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2); + immUniform1f("dash_width", active ? 4.0f : 2.0f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(shdr_pos, x, y1); + immVertex2f(shdr_pos, x, y2); + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* hide handles when zoomed out too far */ if (half_width < min_width) { @@ -1043,45 +1251,46 @@ static void ui_draw_colorband_handle( /* shift handle down */ y1 -= half_width; - glColor3ub(0, 0, 0); - ui_draw_colorband_handle_box(x - half_width, y1 - 1, x + half_width, y1 + height, false); + immUniformColor3ub(0, 0, 0); + ui_draw_colorband_handle_box(shdr_pos, x - half_width, y1 - 1, x + half_width, y1 + height, false); /* draw all triangles blended */ glEnable(GL_BLEND); - ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true); + ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true); if (active) - glColor3ub(196, 196, 196); + immUniformColor3ub(196, 196, 196); else - glColor3ub(96, 96, 96); - ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true); + immUniformColor3ub(96, 96, 96); + ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true); if (active) - glColor3ub(255, 255, 255); + immUniformColor3ub(255, 255, 255); else - glColor3ub(128, 128, 128); - ui_draw_colorband_handle_tri_hlight(x, y1 + height - 1, (half_width - 1), (half_width - 1)); + immUniformColor3ub(128, 128, 128); + ui_draw_colorband_handle_tri_hlight(shdr_pos, x, y1 + height - 1, (half_width - 1), (half_width - 1)); - glColor3ub(0, 0, 0); - ui_draw_colorband_handle_tri_hlight(x, y1 + height, half_width, half_width); + immUniformColor3ub(0, 0, 0); + ui_draw_colorband_handle_tri_hlight(shdr_pos, x, y1 + height, half_width, half_width); glDisable(GL_BLEND); - glColor3ub(128, 128, 128); - ui_draw_colorband_handle_box(x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true); + immUniformColor3ub(128, 128, 128); + ui_draw_colorband_handle_box(shdr_pos, x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true); if (display) { IMB_colormanagement_scene_linear_to_display_v3(colf, display); } - glColor3fv(colf); - ui_draw_colorband_handle_box(x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true); + immUniformColor3fv(colf); + ui_draw_colorband_handle_box(shdr_pos, x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true); } void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect) { struct ColorManagedDisplay *display = NULL; + unsigned int position, color; ColorBand *coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin); if (coba == NULL) return; @@ -1092,20 +1301,25 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti float x1 = rect->xmin; float sizex = rect->xmax - x1; float sizey = BLI_rcti_size_y(rect); - float sizey_solid = sizey / 4; + float sizey_solid = sizey * 0.25f; float y1 = rect->ymin; - /* Drawing the checkerboard. - * This could be optimized with a single checkerboard shader, - * instead of drawing twice and using stippling the second time. */ - /* layer: background, to show tranparency */ - glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255); - glRectf(x1, y1, x1 + sizex, rect->ymax); - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_CHECKER_8PX); - glRectf(x1, y1, x1 + sizex, rect->ymax); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + Gwn_VertFormat *format = immVertexFormat(); + position = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_CHECKER); + + /* Drawing the checkerboard. */ + immUniform4f("color1", UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, 1.0f); + immUniform4f("color2", UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 1.0f); + immUniform1i("size", 8); + immRectf(position, x1, y1, x1 + sizex, rect->ymax); + immUnbindProgram(); + + /* New format */ + format = immVertexFormat(); + position = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); /* layer: color ramp */ glEnable(GL_BLEND); @@ -1118,7 +1332,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti v1[1] = y1 + sizey_solid; v2[1] = rect->ymax; - glBegin(GL_TRIANGLE_STRIP); + immBegin(GWN_PRIM_TRI_STRIP, (sizex + 1) * 2); for (int a = 0; a <= sizex; a++) { float pos = ((float)a) / sizex; do_colorband(coba, pos, colf); @@ -1127,17 +1341,17 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti v1[0] = v2[0] = x1 + a; - glColor4fv(colf); - glVertex2fv(v1); - glVertex2fv(v2); + immAttrib4fv(color, colf); + immVertex2fv(position, v1); + immVertex2fv(position, v2); } - glEnd(); + immEnd(); /* layer: color ramp without alpha for reference when manipulating ramp properties */ v1[1] = y1; v2[1] = y1 + sizey_solid; - glBegin(GL_TRIANGLE_STRIP); + immBegin(GWN_PRIM_TRI_STRIP, (sizex + 1) * 2); for (int a = 0; a <= sizex; a++) { float pos = ((float)a) / sizex; do_colorband(coba, pos, colf); @@ -1146,31 +1360,48 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti v1[0] = v2[0] = x1 + a; - glColor4f(colf[0], colf[1], colf[2], 1.0f); - glVertex2fv(v1); - glVertex2fv(v2); + immAttrib4f(color, colf[0], colf[1], colf[2], 1.0f); + immVertex2fv(position, v1); + immVertex2fv(position, v2); } - glEnd(); + immEnd(); + + immUnbindProgram(); glDisable(GL_BLEND); + /* New format */ + format = immVertexFormat(); + position = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* layer: box outline */ - glColor4f(0.0, 0.0, 0.0, 1.0); - fdrawbox(x1, y1, x1 + sizex, rect->ymax); - + immUniformColor4f(0.0f, 0.0f, 0.0f, 1.0f); + imm_draw_box_wire_2d(position, x1, y1, x1 + sizex, rect->ymax); + /* layer: box outline */ glEnable(GL_BLEND); - glColor4f(0.0f, 0.0f, 0.0f, 0.5f); - fdrawline(x1, y1, x1 + sizex, y1); - glColor4f(1.0f, 1.0f, 1.0f, 0.25f); - fdrawline(x1, y1 - 1, x1 + sizex, y1 - 1); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(position, x1, y1); + immVertex2f(position, x1 + sizex, y1); + immEnd(); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(position, x1, y1 - 1); + immVertex2f(position, x1 + sizex, y1 - 1); + immEnd(); + glDisable(GL_BLEND); /* layer: draw handles */ for (int a = 0; a < coba->tot; a++, cbd++) { if (a != coba->cur) { float pos = x1 + cbd->pos * (sizex - 1) + 1; - ui_draw_colorband_handle(rect, pos, &cbd->r, display, false); + ui_draw_colorband_handle(position, rect, pos, &cbd->r, display, false); } } @@ -1178,117 +1409,100 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti if (coba->tot != 0) { cbd = &coba->data[coba->cur]; float pos = x1 + cbd->pos * (sizex - 1) + 1; - ui_draw_colorband_handle(rect, pos, &cbd->r, display, true); + ui_draw_colorband_handle(position, rect, pos, &cbd->r, display, true); } + + immUnbindProgram(); } void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect) { - static GLuint displist = 0; + /* sphere color */ float diffuse[3] = {1.0f, 1.0f, 1.0f}; + float light[3]; float size; /* backdrop */ - glColor3ubv((unsigned char *)wcol->inner); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f); + UI_draw_roundbox_3ubAlpha(true, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, (unsigned char *)wcol->inner, 255); - /* sphere color */ glCullFace(GL_BACK); glEnable(GL_CULL_FACE); /* setup lights */ - GPULightData light = {0}; - light.type = GPU_LIGHT_SUN; - copy_v3_v3(light.diffuse, diffuse); - zero_v3(light.specular); - ui_but_v3_get(but, light.direction); - - GPU_basic_shader_light_set(0, &light); - for (int a = 1; a < 8; a++) - GPU_basic_shader_light_set(a, NULL); - - /* setup shader */ - GPU_basic_shader_colors(diffuse, NULL, 0, 1.0f); - GPU_basic_shader_bind(GPU_SHADER_LIGHTING); + ui_but_v3_get(but, light); /* transform to button */ - glPushMatrix(); - glTranslatef(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect), 0.0f); + gpuPushMatrix(); if (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect)) - size = BLI_rcti_size_x(rect) / 200.f; + size = 0.5f * BLI_rcti_size_x(rect); else - size = BLI_rcti_size_y(rect) / 200.f; - - glScalef(size, size, MIN2(size, 1.0f)); + size = 0.5f * BLI_rcti_size_y(rect); - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_FILL); - GPU_basic_shader_bind(GPU_basic_shader_bound_options()); - gluSphere(qobj, 100.0, 32, 24); - gluDeleteQuadric(qobj); - - glEndList(); - } + gpuTranslate2f(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect)); + gpuScaleUniform(size); - glCallList(displist); + Gwn_Batch *sphere = GPU_batch_preset_sphere(2); + GWN_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_4f(sphere, "color", diffuse[0], diffuse[1], diffuse[2], 1.0f); + GWN_batch_uniform_3fv(sphere, "light", light); + GWN_batch_draw(sphere); /* restore */ - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - GPU_default_lights(); glDisable(GL_CULL_FACE); /* AA circle */ + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3ubv((unsigned char *)wcol->inner); + glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - glColor3ubv((unsigned char *)wcol->inner); - glutil_draw_lined_arc(0.0f, M_PI * 2.0, 100.0f, 32); + imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, 1.0f, 32); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); /* matrix after circle */ - glPopMatrix(); + gpuPopMatrix(); - /* We disabled all blender lights above, so restore them here. */ - GPU_default_lights(); + immUnbindProgram(); } -static void ui_draw_but_curve_grid(const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step) +static void ui_draw_but_curve_grid(unsigned int pos, const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step) { - glBegin(GL_LINES); float dx = step * zoomx; float fx = rect->xmin + zoomx * (-offsx); if (fx > rect->xmin) fx -= dx * (floorf(fx - rect->xmin)); - while (fx < rect->xmax) { - glVertex2f(fx, rect->ymin); - glVertex2f(fx, rect->ymax); - fx += dx; - } float dy = step * zoomy; float fy = rect->ymin + zoomy * (-offsy); if (fy > rect->ymin) fy -= dy * (floorf(fy - rect->ymin)); + + float line_count = floorf((rect->xmax - fx) / dx) + 1.0f + + floorf((rect->ymax - fy) / dy) + 1.0f; + + immBegin(GWN_PRIM_LINES, (int)line_count * 2); + while (fx < rect->xmax) { + immVertex2f(pos, fx, rect->ymin); + immVertex2f(pos, fx, rect->ymax); + fx += dx; + } while (fy < rect->ymax) { - glVertex2f(rect->xmin, fy); - glVertex2f(rect->xmax, fy); + immVertex2f(pos, rect->xmin, fy); + immVertex2f(pos, rect->xmax, fy); fy += dy; } - glEnd(); + immEnd(); } static void gl_shaded_color(unsigned char *col, int shade) { - glColor3ub(col[0] - shade > 0 ? col[0] - shade : 0, - col[1] - shade > 0 ? col[1] - shade : 0, - col[2] - shade > 0 ? col[2] - shade : 0); + immUniformColor3ub(col[0] - shade > 0 ? col[0] - shade : 0, + col[1] - shade > 0 ? col[1] - shade : 0, + col[2] - shade > 0 ? col[2] - shade : 0); } void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti *rect) @@ -1324,10 +1538,8 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti float zoomy = (BLI_rcti_size_y(rect) - 2.0f) / BLI_rctf_size_y(&cumap->curr); float offsx = cumap->curr.xmin - (1.0f / zoomx); float offsy = cumap->curr.ymin - (1.0f / zoomy); - - glLineWidth(1.0f); - /* backdrop */ + /* Do this first to not mess imm context */ if (but->a1 == UI_GRAD_H) { /* magic trigger for curve backgrounds */ float col[3] = {0.0f, 0.0f, 0.0f}; /* dummy arg */ @@ -1340,96 +1552,105 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti }; ui_draw_gradient(&grid, col, UI_GRAD_H, 1.0f); + } + glLineWidth(1.0f); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* backdrop */ + if (but->a1 == UI_GRAD_H) { /* grid, hsv uses different grid */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4ub(0, 0, 0, 48); - ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.1666666f); + immUniformColor4ub(0, 0, 0, 48); + ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.1666666f); glDisable(GL_BLEND); } else { if (cumap->flag & CUMA_DO_CLIP) { gl_shaded_color((unsigned char *)wcol->inner, -20); - glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax); - glColor3ubv((unsigned char *)wcol->inner); - glRectf(rect->xmin + zoomx * (cumap->clipr.xmin - offsx), - rect->ymin + zoomy * (cumap->clipr.ymin - offsy), - rect->xmin + zoomx * (cumap->clipr.xmax - offsx), - rect->ymin + zoomy * (cumap->clipr.ymax - offsy)); + immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + immUniformColor3ubv((unsigned char *)wcol->inner); + immRectf(pos, rect->xmin + zoomx * (cumap->clipr.xmin - offsx), + rect->ymin + zoomy * (cumap->clipr.ymin - offsy), + rect->xmin + zoomx * (cumap->clipr.xmax - offsx), + rect->ymin + zoomy * (cumap->clipr.ymax - offsy)); } else { - glColor3ubv((unsigned char *)wcol->inner); - glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax); + immUniformColor3ubv((unsigned char *)wcol->inner); + immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); } /* grid, every 0.25 step */ gl_shaded_color((unsigned char *)wcol->inner, -16); - ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.25f); + ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.25f); /* grid, every 1.0 step */ gl_shaded_color((unsigned char *)wcol->inner, -24); - ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 1.0f); + ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f); /* axes */ gl_shaded_color((unsigned char *)wcol->inner, -50); - glBegin(GL_LINES); - glVertex2f(rect->xmin, rect->ymin + zoomy * (-offsy)); - glVertex2f(rect->xmax, rect->ymin + zoomy * (-offsy)); - glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymax); - glEnd(); + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (-offsy)); + immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (-offsy)); + immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymax); + immEnd(); } /* cfra option */ /* XXX 2.48 */ #if 0 if (cumap->flag & CUMA_DRAW_CFRA) { - glColor3ub(0x60, 0xc0, 0x40); - glBegin(GL_LINES); - glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax); - glEnd(); + immUniformColor3ub(0x60, 0xc0, 0x40); + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax); + immEnd(); } #endif /* sample option */ if (cumap->flag & CUMA_DRAW_SAMPLE) { - glBegin(GL_LINES); /* will draw one of the following 3 lines */ + immBegin(GWN_PRIM_LINES, 2); /* will draw one of the following 3 lines */ if (but->a1 == UI_GRAD_H) { float tsample[3]; float hsv[3]; linearrgb_to_srgb_v3_v3(tsample, cumap->sample); rgb_to_hsv_v(tsample, hsv); - glColor3ub(240, 240, 240); + immUniformColor3ub(240, 240, 240); - glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax); + immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax); } else if (cumap->cur == 3) { float lum = IMB_colormanagement_get_luminance(cumap->sample); - glColor3ub(240, 240, 240); + immUniformColor3ub(240, 240, 240); - glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymax); + immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymax); } else { if (cumap->cur == 0) - glColor3ub(240, 100, 100); + immUniformColor3ub(240, 100, 100); else if (cumap->cur == 1) - glColor3ub(100, 240, 100); + immUniformColor3ub(100, 240, 100); else - glColor3ub(100, 100, 240); + immUniformColor3ub(100, 100, 240); - glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax); + immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax); } - glEnd(); + immEnd(); } /* the curve */ - glColor3ubv((unsigned char *)wcol->item); + immUniformColor3ubv((unsigned char *)wcol->item); glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, (CM_TABLE + 1) + 2); if (cuma->table == NULL) curvemapping_changed(cumap, false); @@ -1438,52 +1659,67 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti /* first point */ if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { - glVertex2f(rect->xmin, rect->ymin + zoomy * (cmp[0].y - offsy)); + immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (cmp[0].y - offsy)); } else { float fx = rect->xmin + zoomx * (cmp[0].x - offsx + cuma->ext_in[0]); float fy = rect->ymin + zoomy * (cmp[0].y - offsy + cuma->ext_in[1]); - glVertex2f(fx, fy); + immVertex2f(pos, fx, fy); } for (int a = 0; a <= CM_TABLE; a++) { float fx = rect->xmin + zoomx * (cmp[a].x - offsx); float fy = rect->ymin + zoomy * (cmp[a].y - offsy); - glVertex2f(fx, fy); + immVertex2f(pos, fx, fy); } /* last point */ if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { - glVertex2f(rect->xmax, rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy)); + immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy)); } else { float fx = rect->xmin + zoomx * (cmp[CM_TABLE].x - offsx - cuma->ext_out[0]); float fy = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy - cuma->ext_out[1]); - glVertex2f(fx, fy); + immVertex2f(pos, fx, fy); } - glEnd(); + immEnd(); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); + immUnbindProgram(); /* the points, use aspect to make them visible on edges */ + format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + cmp = cuma->curve; glPointSize(3.0f); - glBegin(GL_POINTS); + immBegin(GWN_PRIM_POINTS, cuma->totpoint); for (int a = 0; a < cuma->totpoint; a++) { + float color[4]; if (cmp[a].flag & CUMA_SELECT) - UI_ThemeColor(TH_TEXT_HI); + UI_GetThemeColor4fv(TH_TEXT_HI, color); else - UI_ThemeColor(TH_TEXT); + UI_GetThemeColor4fv(TH_TEXT, color); float fx = rect->xmin + zoomx * (cmp[a].x - offsx); float fy = rect->ymin + zoomy * (cmp[a].y - offsy); - glVertex2f(fx, fy); + immAttrib4fv(col, color); + immVertex2f(pos, fx, fy); } - glEnd(); + immEnd(); + immUnbindProgram(); /* restore scissortest */ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); /* outline */ - glColor3ubv((unsigned char *)wcol->outline); - fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax); + format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3ubv((unsigned char *)wcol->outline); + imm_draw_box_wire_2d(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + + immUnbindProgram(); } void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) @@ -1513,9 +1749,9 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc (rect.ymax + 1) - (rect.ymin - 1)); if (scopes->track_disabled) { - glColor4f(0.7f, 0.3f, 0.3f, 0.3f); + float color[4] = {0.7f, 0.3f, 0.3f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f); + UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); ok = true; } @@ -1542,62 +1778,72 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc } if (!ok && scopes->track_preview) { - glPushMatrix(); + gpuPushMatrix(); /* draw content of pattern area */ glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, scissor[2], scissor[3]); if (width > 0 && height > 0) { ImBuf *drawibuf = scopes->track_preview; + float col_sel[4], col_outline[4]; if (scopes->use_track_mask) { - glColor4f(0.0f, 0.0f, 0.0f, 0.3f); + float color[4] = {0.0f, 0.0f, 0.0f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f); + UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); } - glaDrawPixelsSafe(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, - drawibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, drawibuf->rect); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, drawibuf->rect, 1.0f, 1.0f, NULL); /* draw cross for pixel position */ - glTranslatef(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1], 0.f); + gpuTranslate2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]); glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect)); - GPU_basic_shader_bind_enable(GPU_SHADER_LINE); - - for (int a = 0; a < 2; a++) { - if (a == 1) { - GPU_basic_shader_bind_enable(GPU_SHADER_STIPPLE); - GPU_basic_shader_line_stipple(3, 0xAAAA); - UI_ThemeColor(TH_SEL_MARKER); - } - else { - UI_ThemeColor(TH_MARKER_OUTLINE); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + + UI_GetThemeColor4fv(TH_SEL_MARKER, col_sel); + UI_GetThemeColor4fv(TH_MARKER_OUTLINE, col_outline); + + /* Do stipple cross with geometry */ + immBegin(GWN_PRIM_LINES, 7 * 2 * 2); + float pos_sel[8] = {-10.0f, -7.0f, -4.0f, -1.0f, 2.0f, 5.0f, 8.0f, 11.0f}; + for (int axe = 0; axe < 2; ++axe) { + for (int i = 0; i < 7; ++i) { + float x1 = pos_sel[i] * (1 - axe); + float y1 = pos_sel[i] * axe; + float x2 = pos_sel[i + 1] * (1 - axe); + float y2 = pos_sel[i + 1] * axe; + + if (i % 2 == 1) + immAttrib4fv(col, col_sel); + else + immAttrib4fv(col, col_outline); + + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y2); } - - glBegin(GL_LINES); - glVertex2f(-10.0f, 0.0f); - glVertex2f(10.0f, 0.0f); - glVertex2f(0.0f, -10.0f); - glVertex2f(0.0f, 10.0f); - glEnd(); } + immEnd(); - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); + immUnbindProgram(); } - glPopMatrix(); + gpuPopMatrix(); ok = true; } if (!ok) { - glColor4f(0.f, 0.f, 0.f, 0.3f); + float color[4] = {0.0f, 0.0f, 0.0f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f); + UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); } /* outline */ @@ -1643,26 +1889,31 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol BLI_rcti_size_x(&scissor_new), BLI_rcti_size_y(&scissor_new)); - glColor4ubv(but->col); - float x = 0.5f * (recti->xmin + recti->xmax); float y = 0.5f * (recti->ymin + recti->ymax); - + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv(but->col); + glEnable(GL_BLEND); - glBegin(GL_POLYGON); + immBegin(GWN_PRIM_TRI_FAN, 16); for (int a = 0; a < 16; a++) - glVertex2f(x + size * si[a], y + size * co[a]); - glEnd(); + immVertex2f(pos, x + size * si[a], y + size * co[a]); + immEnd(); - glColor4ub(0, 0, 0, 150); + immUniformColor4ub(0, 0, 0, 150); glLineWidth(1); glEnable(GL_LINE_SMOOTH); - glBegin(GL_LINE_LOOP); + immBegin(GWN_PRIM_LINE_LOOP, 16); for (int a = 0; a < 16; a++) - glVertex2f(x + size * si[a], y + size * co[a]); - glEnd(); + immVertex2f(pos, x + size * si[a], y + size * co[a]); + immEnd(); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); + + immUnbindProgram(); /* restore scissortest */ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); @@ -1670,47 +1921,91 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol /* ****************************************************** */ +/* TODO: high quality UI drop shadows using GLSL shader and single draw call + * would replace / modify the following 3 functions - merwin + */ -static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha) +static void ui_shadowbox(unsigned pos, unsigned color, float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha) { + /* v1-_ + * | -_v2 + * | | + * | | + * | | + * v7_______v3____v4 + * \ | / + * \ | _v5 + * v8______v6_- + */ + const float v1[2] = {maxx, maxy - 0.3f * shadsize}; + const float v2[2] = {maxx + shadsize, maxy - 0.75f * shadsize}; + const float v3[2] = {maxx, miny}; + const float v4[2] = {maxx + shadsize, miny}; + + const float v5[2] = {maxx + 0.7f * shadsize, miny - 0.7f * shadsize}; + + const float v6[2] = {maxx, miny - shadsize}; + const float v7[2] = {minx + 0.3f * shadsize, miny}; + const float v8[2] = {minx + 0.5f * shadsize, miny - shadsize}; + /* right quad */ - glColor4ub(0, 0, 0, alpha); - glVertex2f(maxx, miny); - glVertex2f(maxx, maxy - 0.3f * shadsize); - glColor4ub(0, 0, 0, 0); - glVertex2f(maxx + shadsize, maxy - 0.75f * shadsize); - glVertex2f(maxx + shadsize, miny); - + immAttrib4ub(color, 0, 0, 0, alpha); + immVertex2fv(pos, v3); + immVertex2fv(pos, v1); + immAttrib4ub(color, 0, 0, 0, 0); + immVertex2fv(pos, v2); + + immVertex2fv(pos, v2); + immVertex2fv(pos, v4); + immAttrib4ub(color, 0, 0, 0, alpha); + immVertex2fv(pos, v3); + /* corner shape */ - glColor4ub(0, 0, 0, alpha); - glVertex2f(maxx, miny); - glColor4ub(0, 0, 0, 0); - glVertex2f(maxx + shadsize, miny); - glVertex2f(maxx + 0.7f * shadsize, miny - 0.7f * shadsize); - glVertex2f(maxx, miny - shadsize); - + /* immAttrib4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */ + immVertex2fv(pos, v3); + immAttrib4ub(color, 0, 0, 0, 0); + immVertex2fv(pos, v4); + immVertex2fv(pos, v5); + + immVertex2fv(pos, v5); + immVertex2fv(pos, v6); + immAttrib4ub(color, 0, 0, 0, alpha); + immVertex2fv(pos, v3); + /* bottom quad */ - glColor4ub(0, 0, 0, alpha); - glVertex2f(minx + 0.3f * shadsize, miny); - glVertex2f(maxx, miny); - glColor4ub(0, 0, 0, 0); - glVertex2f(maxx, miny - shadsize); - glVertex2f(minx + 0.5f * shadsize, miny - shadsize); + /* immAttrib4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */ + immVertex2fv(pos, v3); + immAttrib4ub(color, 0, 0, 0, 0); + immVertex2fv(pos, v6); + immVertex2fv(pos, v8); + + immVertex2fv(pos, v8); + immAttrib4ub(color, 0, 0, 0, alpha); + immVertex2fv(pos, v7); + immVertex2fv(pos, v3); } void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy) { glEnable(GL_BLEND); - - glBegin(GL_QUADS); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + + immBegin(GWN_PRIM_TRIS, 54); /* accumulated outline boxes to make shade not linear, is more pleasant */ - ui_shadowbox(minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8); - ui_shadowbox(minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8); - ui_shadowbox(minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8); - - glEnd(); + ui_shadowbox(pos, color, minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8); + ui_shadowbox(pos, color, minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8); + ui_shadowbox(pos, color, minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8); + immEnd(); + + immUnbindProgram(); + glDisable(GL_BLEND); } @@ -1719,8 +2014,8 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha { float rad; - if (radius > (BLI_rctf_size_y(rct) - 10.0f) / 2.0f) - rad = (BLI_rctf_size_y(rct) - 10.0f) / 2.0f; + if (radius > (BLI_rctf_size_y(rct) - 10.0f) * 0.5f) + rad = (BLI_rctf_size_y(rct) - 10.0f) * 0.5f; else rad = radius; @@ -1741,29 +2036,16 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha float calpha = dalpha; for (; i--; a -= aspect) { /* alpha ranges from 2 to 20 or so */ - glColor4f(0.0f, 0.0f, 0.0f, calpha); + float color[4] = {0.0f, 0.0f, 0.0f, calpha}; + UI_draw_roundbox_4fv(true, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color); calpha += dalpha; - - UI_draw_roundbox_gl_mode(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a); } /* outline emphasis */ glEnable(GL_LINE_SMOOTH); - glColor4ub(0, 0, 0, 100); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f); + float color[4] = {0.0f, 0.0f, 0.0f, 0.4f}; + UI_draw_roundbox_4fv(false, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f, color); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); } - -/** - * Reset GL state (keep minimal). - * - * \note Blender's internal code doesn't assume these are reset, - * but external callbacks may depend on their state. - */ -void UI_reinit_gl_state(void) -{ - glLineWidth(1.0f); - glPointSize(1.0f); -} diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index 564b29d3343..e92139ada0c 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -43,10 +43,12 @@ #include "BKE_screen.h" #include "BKE_report.h" #include "BKE_animsys.h" -#include "BKE_depsgraph.h" #include "BKE_idcode.h" #include "BKE_unit.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -139,8 +141,8 @@ static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, c wmWindow *win = CTX_wm_window(C); int x = win->eventstate->x; int y = win->eventstate->y; - const unsigned char fg[4] = {255, 255, 255, 255}; - const unsigned char bg[4] = {0, 0, 0, 50}; + const float col_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const float col_bg[4] = {0.0f, 0.0f, 0.0f, 0.2f}; if ((name[0] == '\0') || @@ -154,7 +156,7 @@ static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, c y += U.widget_unit; - UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, fg, bg); + UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg); } @@ -169,8 +171,8 @@ static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, c */ static uiBut *eyedropper_get_property_button_under_mouse(bContext *C, const wmEvent *event) { - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, event->x, event->y); + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->x, event->y); ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_ANY, event->x, event->y); uiBut *but = ui_but_find_mouse_over(ar, event); @@ -262,10 +264,9 @@ static void eyedropper_exit(bContext *C, wmOperator *op) */ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int mx, int my, float r_col[3]) { - /* we could use some clever */ - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my); + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my); const char *display_device = CTX_data_scene(C)->display_settings.display_device; struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); @@ -586,8 +587,8 @@ static void datadropper_exit(bContext *C, wmOperator *op) static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int my, ID **r_id) { /* we could use some clever */ - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = BKE_screen_find_area_xy(win->screen, -1, mx, my); + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = BKE_screen_find_area_xy(screen, -1, mx, my); ScrArea *area_prev = CTX_wm_area(C); ARegion *ar_prev = CTX_wm_region(C); @@ -887,9 +888,9 @@ static void depthdropper_exit(bContext *C, wmOperator *op) static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth) { /* we could use some clever */ - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my); - Scene *scene = win->screen->scene; + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my); + Scene *scene = CTX_data_scene(C); UnitSettings *unit = &scene->unit; const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0; @@ -902,6 +903,7 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, if (sa->spacetype == SPACE_VIEW3D) { ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); if (ar) { + struct Depsgraph *graph = CTX_data_depsgraph(C); View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; /* weak, we could pass in some reference point */ @@ -911,6 +913,9 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, my - ar->winrct.ymin}; float co[3]; + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + CTX_wm_area_set(C, sa); CTX_wm_region_set(C, ar); @@ -919,7 +924,7 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, view3d_operator_needs_opengl(C); - if (ED_view3d_autodist(scene, ar, v3d, mval, co, true, NULL)) { + if (ED_view3d_autodist(&eval_ctx, graph, ar, v3d, mval, co, true, NULL)) { const float mval_center_fl[2] = { (float)ar->winx / 2, (float)ar->winy / 2}; @@ -1205,8 +1210,8 @@ static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *eve if (success) { /* send updates */ UI_context_update_anim_flag(C); - DAG_relations_tag_update(CTX_data_main(C)); - DAG_id_tag_update(ddr->ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA); + DEG_relations_tag_update(CTX_data_main(C)); + DEG_id_tag_update(ddr->ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA); WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX } } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 4dfb1a92bf6..2947365fc5d 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -186,7 +186,6 @@ typedef struct uiSelectContextStore { uiSelectContextElem *elems; int elems_len; bool do_free; - bool is_enabled; /* When set, simply copy values (don't apply difference). * Rules are: * - dragging numbers uses delta. @@ -202,7 +201,9 @@ static void ui_selectcontext_apply( bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data, const double value, const double value_orig); +#if 0 #define IS_ALLSELECT_EVENT(event) ((event)->alt != 0) +#endif /** just show a tinted color so users know its activated */ #define UI_BUT_IS_SELECT_CONTEXT UI_BUT_NODE_ACTIVE @@ -1182,14 +1183,11 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl ui_but_execute_begin(C, ar, but, &active_back); #ifdef USE_ALLSELECT - if (data->select_others.is_enabled) { - /* init once! */ - if (mbut_state->select_others.elems_len == 0) { - ui_selectcontext_begin(C, but, &mbut_state->select_others); - } - if (mbut_state->select_others.elems_len == 0) { - mbut_state->select_others.elems_len = -1; - } + if (mbut_state->select_others.elems_len == 0) { + ui_selectcontext_begin(C, but, &mbut_state->select_others); + } + if (mbut_state->select_others.elems_len == 0) { + mbut_state->select_others.elems_len = -1; } /* needed so we apply the right deltas */ @@ -2072,12 +2070,7 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton else # endif if (data->select_others.elems_len == 0) { - wmWindow *win = CTX_wm_window(C); - /* may have been enabled before activating */ - if (data->select_others.is_enabled || IS_ALLSELECT_EVENT(win->eventstate)) { - ui_selectcontext_begin(C, but, &data->select_others); - data->select_others.is_enabled = true; - } + ui_selectcontext_begin(C, but, &data->select_others); } if (data->select_others.elems_len == 0) { /* dont check again */ @@ -2118,6 +2111,7 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton break; case UI_BTYPE_ROW: case UI_BTYPE_LISTROW: + case UI_BTYPE_TAB: ui_apply_but_ROW(C, block, but, data); break; case UI_BTYPE_SCROLL: @@ -3079,11 +3073,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) #ifdef USE_ALLSELECT if (is_num_but) { - if (IS_ALLSELECT_EVENT(win->eventstate)) { - data->select_others.is_enabled = true; - data->select_others.is_copy = true; - - } + data->select_others.is_copy = true; } #endif @@ -3170,6 +3160,9 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data) ui_searchbox_free(C, data->searchbox); data->searchbox = NULL; + if (but->free_search_arg) { + MEM_SAFE_FREE(but->search_arg); + } } but->editstr = NULL; @@ -3685,15 +3678,6 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat data->menu->popup = but->block->handle->popup; } -#ifdef USE_ALLSELECT - { - wmWindow *win = CTX_wm_window(C); - if (IS_ALLSELECT_EVENT(win->eventstate)) { - data->select_others.is_enabled = true; - } - } -#endif - /* this makes adjacent blocks auto open from now on */ //if (but->block->auto_open == 0) but->block->auto_open = 1; } @@ -3875,6 +3859,18 @@ static int ui_do_but_KEYEVT( return WM_UI_HANDLER_CONTINUE; } +static int ui_do_but_TAB(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +{ + if (data->state == BUTTON_STATE_HIGHLIGHT) { + if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_RELEASE) { + button_activate_state(C, but, BUTTON_STATE_EXIT); + return WM_UI_HANDLER_CONTINUE; + } + } + + return WM_UI_HANDLER_CONTINUE; +} + static bool ui_but_is_mouse_over_icon_extra(const ARegion *region, uiBut *but, const int mouse_xy[2]) { int x = mouse_xy[0], y = mouse_xy[1]; @@ -5219,7 +5215,8 @@ static int ui_do_but_COLOR( if (!event->ctrl) { float color[3]; Scene *scene = CTX_data_scene(C); - Paint *paint = BKE_paint_get_active(scene); + SceneLayer *sl = CTX_data_scene_layer(C); + Paint *paint = BKE_paint_get_active(scene, sl); Brush *brush = BKE_paint_brush(paint); if (brush->flag & BRUSH_USE_GRADIENT) { @@ -6127,6 +6124,7 @@ static int ui_do_but_CURVE( int mx, my, a; bool changed = false; Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); mx = event->x; my = event->y; @@ -6255,7 +6253,7 @@ static int ui_do_but_CURVE( } else { curvemapping_changed(cumap, true); /* remove doubles */ - BKE_paint_invalidate_cursor_overlay(scene, cumap); + BKE_paint_invalidate_cursor_overlay(scene, sl, cumap); } } @@ -7129,6 +7127,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * case UI_BTYPE_HOTKEY_EVENT: retval = ui_do_but_HOTKEYEVT(C, but, data, event); break; + case UI_BTYPE_TAB: + retval = ui_do_but_TAB(C, but, data, event); + break; case UI_BTYPE_BUT_TOGGLE: case UI_BTYPE_TOGGLE: case UI_BTYPE_ICON_TOGGLE: diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 0357fc8ff01..d048324d35e 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -33,8 +33,8 @@ #include "MEM_guardedalloc.h" -#include "GPU_extensions.h" -#include "GPU_basic_shader.h" +#include "GPU_draw.h" +#include "GPU_immediate.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" @@ -59,7 +59,6 @@ #include "IMB_imbuf_types.h" #include "IMB_thumbs.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "ED_datafiles.h" @@ -224,13 +223,17 @@ static void vicon_small_tri_right_draw(int x, int y, int w, int UNUSED(h), float viconutil_set_point(pts[1], cx - d2, cy - d); viconutil_set_point(pts[2], cx + d2, cy); - glColor4f(0.2f, 0.2f, 0.2f, alpha); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4f(0.2f, 0.2f, 0.2f, alpha); - glBegin(GL_TRIANGLES); - glVertex2iv(pts[0]); - glVertex2iv(pts[1]); - glVertex2iv(pts[2]); - glEnd(); + immBegin(GWN_PRIM_TRIS, 3); + immVertex2iv(pos, pts[0]); + immVertex2iv(pos, pts[1]); + immVertex2iv(pos, pts[2]); + immEnd(); + + immUnbindProgram(); } static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha, short key_type) @@ -239,7 +242,6 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha, * (since we're doing this offscreen, free from any particular space_id) */ struct bThemeState theme_state; - int xco, yco; UI_Theme_Store(&theme_state); UI_SetTheme(SPACE_ACTION, RGN_TYPE_WINDOW); @@ -248,16 +250,30 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha, * while the draw_keyframe_shape() function needs the midpoint for * the keyframe */ - xco = x + w / 2; - yco = y + h / 2; - + int xco = x + w / 2; + int yco = y + h / 2; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + unsigned int outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + GPU_enable_program_point_size(); + immBegin(GWN_PRIM_POINTS, 1); + /* draw keyframe - * - xscale: 1.0 (since there's no timeline scaling to compensate for) - * - yscale: 0.3 * h (found out experimentally... dunno why!) + * - size: 0.6 * h (found out experimentally... dunno why!) * - sel: true (so that "keyframe" state shows the iconic yellow icon) */ - draw_keyframe_shape(xco, yco, 1.0f, 0.3f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha); - + draw_keyframe_shape(xco, yco, 0.6f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha, + pos_id, size_id, color_id, outline_color_id); + + immEnd(); + GPU_disable_program_point_size(); + immUnbindProgram(); + UI_Theme_Restore(&theme_state); } @@ -290,7 +306,7 @@ static void vicon_colorset_draw(int index, int x, int y, int w, int h, float UNU { bTheme *btheme = UI_GetTheme(); ThemeWireColor *cs = &btheme->tarm[index]; - + /* Draw three bands of color: One per color * x-----a-----b-----c * | N | S | A | @@ -299,19 +315,24 @@ static void vicon_colorset_draw(int index, int x, int y, int w, int h, float UNU const int a = x + w / 3; const int b = x + w / 3 * 2; const int c = x + w; - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* XXX: Include alpha into this... */ /* normal */ - glColor3ubv((unsigned char *)cs->solid); - glRecti(x, y, a, y + h); - + immUniformColor3ubv((unsigned char *)cs->solid); + immRecti(pos, x, y, a, y + h); + /* selected */ - glColor3ubv((unsigned char *)cs->select); - glRecti(a, y, b, y + h); - + immUniformColor3ubv((unsigned char *)cs->select); + immRecti(pos, a, y, b, y + h); + /* active */ - glColor3ubv((unsigned char *)cs->active); - glRecti(b, y, c, y + h); + immUniformColor3ubv((unsigned char *)cs->active); + immRecti(pos, b, y, c, y + h); + + immUnbindProgram(); } #define DEF_VICON_COLORSET_DRAW_NTH(prefix, index) \ @@ -504,8 +525,12 @@ static void init_internal_icons(void) icongltex.id = 0; } +#if 0 /* should be a compile-time check (if needed at all) */ /* we only use a texture for cards with non-power of two */ if (GPU_full_non_power_of_two_support()) { +#else + { +#endif glGenTextures(1, &icongltex.id); if (icongltex.id) { @@ -533,11 +558,6 @@ static void init_internal_icons(void) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); - - if (glGetError() == GL_OUT_OF_MEMORY) { - glDeleteTextures(1, &icongltex.id); - icongltex.id = 0; - } } } } @@ -851,12 +871,15 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi { ID *id = (icon->type != 0) ? icon->obj : NULL; PreviewImage *prv = id ? BKE_previewimg_id_ensure(id) : icon->obj; + /* Using jobs for screen previews crashes due to offscreen rendering. + * XXX would be nicer if PreviewImage could store if it supports jobs */ + const bool use_jobs = !id || (GS(id->name) != ID_SCR); if (prv) { const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON; if (id || (prv->tag & PRV_TAG_DEFFERED) != 0) { - ui_id_preview_image_render_size(C, NULL, id, prv, size, true); + ui_id_preview_image_render_size(C, NULL, id, prv, size, use_jobs); } } break; @@ -936,7 +959,7 @@ PreviewImage *UI_icon_to_preview(int icon_id) } static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh, - unsigned int *rect, float alpha, const float rgb[3], const bool is_preview) + unsigned int *rect, float alpha, const float rgb[3], const bool UNUSED(is_preview)) { ImBuf *ima = NULL; int draw_w = w; @@ -950,15 +973,13 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), BLI_assert(!"invalid icon size"); return; } - /* modulate color */ - if (alpha != 1.0f) - glPixelTransferf(GL_ALPHA_SCALE, alpha); + float col[4] = {1.0f, 1.0f, 1.0f, alpha}; if (rgb) { - glPixelTransferf(GL_RED_SCALE, rgb[0]); - glPixelTransferf(GL_GREEN_SCALE, rgb[1]); - glPixelTransferf(GL_BLUE_SCALE, rgb[2]); + col[0] = rgb[0]; + col[1] = rgb[1]; + col[2] = rgb[2]; } /* rect contains image in 'rendersize', we only scale if needed */ @@ -984,31 +1005,12 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), } /* draw */ - if (is_preview) { - glaDrawPixelsSafe(draw_x, draw_y, draw_w, draw_h, draw_w, GL_RGBA, GL_UNSIGNED_BYTE, rect); - } - else { - int bound_options; - GPU_BASIC_SHADER_DISABLE_AND_STORE(bound_options); - - glRasterPos2f(draw_x, draw_y); - glDrawPixels(draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, rect); - - GPU_BASIC_SHADER_ENABLE_AND_RESTORE(bound_options); - } + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, draw_x, draw_y, draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect, + 1.0f, 1.0f, col); if (ima) IMB_freeImBuf(ima); - - /* restore color */ - if (alpha != 0.0f) - glPixelTransferf(GL_ALPHA_SCALE, 1.0f); - - if (rgb) { - glPixelTransferf(GL_RED_SCALE, 1.0f); - glPixelTransferf(GL_GREEN_SCALE, 1.0f); - glPixelTransferf(GL_BLUE_SCALE, 1.0f); - } } static void icon_draw_texture( @@ -1017,38 +1019,39 @@ static void icon_draw_texture( { float x1, x2, y1, y2; - if (rgb) glColor4f(rgb[0], rgb[1], rgb[2], alpha); - else glColor4f(alpha, alpha, alpha, alpha); - x1 = ix * icongltex.invw; x2 = (ix + ih) * icongltex.invw; y1 = iy * icongltex.invh; y2 = (iy + ih) * icongltex.invh; - GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR); glBindTexture(GL_TEXTURE_2D, icongltex.id); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - /* sharper downscaling, has no effect when scale matches with a mip level */ - glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -0.5f); + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); + if (rgb) immUniformColor3fvAlpha(rgb, alpha); + else immUniformColor4f(alpha, alpha, alpha, alpha); - glBegin(GL_QUADS); - glTexCoord2f(x1, y1); - glVertex2f(x, y); + immUniform1i("image", 0); - glTexCoord2f(x2, y1); - glVertex2f(x + w, y); + immBegin(GWN_PRIM_TRI_STRIP, 4); + immAttrib2f(texCoord, x1, y2); + immVertex2f(pos, x, y + h); - glTexCoord2f(x2, y2); - glVertex2f(x + w, y + h); + immAttrib2f(texCoord, x1, y1); + immVertex2f(pos, x, y); - glTexCoord2f(x1, y2); - glVertex2f(x, y + h); - glEnd(); + immAttrib2f(texCoord, x2, y2); + immVertex2f(pos, x + w, y + h); - glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.0f); + immAttrib2f(texCoord, x2, y1); + immVertex2f(pos, x + w, y); + immEnd(); + + immUnbindProgram(); glBindTexture(GL_TEXTURE_2D, 0); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); } /* Drawing size for preview images */ @@ -1162,7 +1165,7 @@ void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big, } } -static void ui_id_brush_render(const bContext *C, ID *id) +static void ui_id_icon_render(const bContext *C, ID *id, bool use_jobs) { PreviewImage *pi = BKE_previewimg_id_ensure(id); enum eIconSizes i; @@ -1174,7 +1177,7 @@ static void ui_id_brush_render(const bContext *C, ID *id) /* check if rect needs to be created; changed * only set by dynamic icons */ if (((pi->flag[i] & PRV_CHANGED) || !pi->rect[i])) { - icon_set_image(C, NULL, id, pi, i, true); + icon_set_image(C, NULL, id, pi, i, use_jobs); pi->flag[i] &= ~PRV_CHANGED; } } @@ -1187,7 +1190,7 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id) if (br->flag & BRUSH_CUSTOM_ICON) { BKE_icon_id_ensure(id); - ui_id_brush_render(C, id); + ui_id_icon_render(C, id, true); } else { Object *ob = CTX_data_active_object(C); @@ -1234,6 +1237,15 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id) return id->icon_id; } +static int ui_id_screen_get_icon(const bContext *C, ID *id) +{ + BKE_icon_id_ensure(id); + /* Don't use jobs here, offscreen rendering doesn't like this and crashes. */ + ui_id_icon_render(C, id, false); + + return id->icon_id; +} + int ui_id_icon_get(const bContext *C, ID *id, const bool big) { int iconid = 0; @@ -1252,6 +1264,9 @@ int ui_id_icon_get(const bContext *C, ID *id, const bool big) /* checks if not exists, or changed */ UI_id_icon_render(C, NULL, id, big, true); break; + case ID_SCR: + iconid = ui_id_screen_get_icon(C, id); + break; default: break; } @@ -1344,6 +1359,8 @@ int UI_idcode_icon_get(const int idcode) return ICON_COLOR; /* TODO! this would need its own icon! */ case ID_PC: return ICON_CURVE_BEZCURVE; /* TODO! this would need its own icon! */ + case ID_LP: + return ICON_RADIO; case ID_SCE: return ICON_SCENE_DATA; case ID_SPK: @@ -1388,6 +1405,11 @@ void UI_icon_draw(float x, float y, int icon_id) UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, 1.0f); } +void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha) +{ + UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, alpha); +} + void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha) { icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, true, false); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 638ab01f8ba..39927699d6d 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -72,6 +72,7 @@ typedef enum { UI_WTYPE_NUMBER, UI_WTYPE_SLIDER, UI_WTYPE_EXEC, + UI_WTYPE_TAB, UI_WTYPE_TOOLTIP, /* strings */ @@ -258,6 +259,7 @@ struct uiBut { uiButSearchCreateFunc search_create_func; uiButSearchFunc search_func; + bool free_search_arg; void *search_arg; uiButHandleRenameFunc rename_func; @@ -281,7 +283,7 @@ struct uiBut { BIFIconID icon; char dt; /* drawtype: UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied from the block */ signed char pie_dir; /* direction in a pie menu, used for collision detection (RadialDirection) */ - char changed; /* could be made into a single flag */ + bool changed; /* could be made into a single flag */ unsigned char unit_type; /* so buttons can support unit systems which are not RNA */ short modifier_key; short iconadd; @@ -654,6 +656,8 @@ extern void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, floa void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha); + +void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highlight[3], unsigned char highlight_fade[3]); void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect); void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect); void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect); @@ -696,15 +700,16 @@ struct wmIMEData *ui_but_ime_data_get(uiBut *but); #endif /* interface_widgets.c */ -void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); -void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha); +void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3, const float color[4]); +void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, + float rad, bool use_alpha, const float color[4]); void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect); void ui_draw_pie_center(uiBlock *block); uiWidgetColors *ui_tooltip_get_theme(void); void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *block, rcti *rect); void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect); bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol); -void ui_draw_link_bezier(const rcti *rect); +void ui_draw_link_bezier(const rcti *rect, const float color[4]); extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect); /* theme color init */ @@ -758,4 +763,20 @@ void UI_OT_eyedropper_id(struct wmOperatorType *ot); void UI_OT_eyedropper_depth(struct wmOperatorType *ot); void UI_OT_eyedropper_driver(struct wmOperatorType *ot); +/* interface_util.c */ + +/** + * For use with #ui_rna_collection_search_cb. + */ +typedef struct uiRNACollectionSearch { + PointerRNA target_ptr; + PropertyRNA *target_prop; + + PointerRNA search_ptr; + PropertyRNA *search_prop; + + bool *but_changed; /* pointer to uiBut.changed */ +} uiRNACollectionSearch; +void ui_rna_collection_search_cb(const struct bContext *C, void *arg, const char *str, uiSearchItems *items); + #endif /* __INTERFACE_INTERN_H__ */ diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index fa27c6fc07b..d43b7511977 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -870,7 +870,7 @@ static uiBut *uiItemFullO_ptr_ex( return but; } -static void ui_item_hold_menu(struct bContext *C, ARegion *butregion, uiBut *but) +static void ui_item_menu_hold(struct bContext *C, ARegion *butregion, uiBut *but) { uiPopupMenu *pup = UI_popup_menu_begin(C, "", ICON_NONE); uiLayout *layout = UI_popup_menu_layout(pup); @@ -878,6 +878,8 @@ static void ui_item_hold_menu(struct bContext *C, ARegion *butregion, uiBut *but UI_popup_menu_but_set(pup, butregion, but); block->flag |= UI_BLOCK_POPUP_HOLD; + block->flag |= UI_BLOCK_IS_FLIP; + UI_block_direction_set(block, UI_DIR_DOWN); const char *menu_id = but->hold_argN; MenuType *mt = WM_menutype_find(menu_id, true); @@ -907,7 +909,7 @@ void uiItemFullOMenuHold_ptr( PointerRNA *r_opptr) { uiBut *but = uiItemFullO_ptr_ex(layout, ot, name, icon, properties, context, flag, r_opptr); - UI_but_func_hold_set(but, ui_item_hold_menu, BLI_strdup(menu_id)); + UI_but_func_hold_set(but, ui_item_menu_hold, BLI_strdup(menu_id)); } void uiItemFullO( @@ -1639,95 +1641,6 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname /* Pointer RNA button with search */ -typedef struct CollItemSearch { - struct CollItemSearch *next, *prev; - char *name; - int index; - int iconid; -} CollItemSearch; - -static int sort_search_items_list(const void *a, const void *b) -{ - const CollItemSearch *cis1 = a; - const CollItemSearch *cis2 = b; - - if (BLI_strcasecmp(cis1->name, cis2->name) > 0) - return 1; - else - return 0; -} - -static void rna_search_cb(const struct bContext *C, void *arg_but, const char *str, uiSearchItems *items) -{ - uiBut *but = arg_but; - char *name; - int i = 0, iconid = 0, flag = RNA_property_flag(but->rnaprop); - ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list"); - CollItemSearch *cis; - const bool skip_filter = !but->changed; - - /* build a temporary list of relevant items first */ - RNA_PROP_BEGIN (&but->rnasearchpoin, itemptr, but->rnasearchprop) - { - if (flag & PROP_ID_SELF_CHECK) - if (itemptr.data == but->rnapoin.id.data) - continue; - - /* use filter */ - if (RNA_property_type(but->rnaprop) == PROP_POINTER) { - if (RNA_property_pointer_poll(&but->rnapoin, but->rnaprop, &itemptr) == 0) - continue; - } - - if (itemptr.type && RNA_struct_is_ID(itemptr.type)) { - ID *id = itemptr.data; - char name_ui[MAX_ID_NAME]; - -#if 0 /* this name is used for a string comparison and can't be modified, TODO */ - /* if ever enabled, make name_ui be MAX_ID_NAME+1 */ - BKE_id_ui_prefix(name_ui, id); -#else - BLI_strncpy(name_ui, id->name + 2, sizeof(name_ui)); -#endif - name = BLI_strdup(name_ui); - iconid = ui_id_icon_get(C, id, false); - } - else { - name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */ - iconid = 0; - } - - if (name) { - if (skip_filter || BLI_strcasestr(name, str)) { - cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch"); - cis->name = MEM_dupallocN(name); - cis->index = i; - cis->iconid = iconid; - BLI_addtail(items_list, cis); - } - MEM_freeN(name); - } - - i++; - } - RNA_PROP_END; - - BLI_listbase_sort(items_list, sort_search_items_list); - - /* add search items from temporary list */ - for (cis = items_list->first; cis; cis = cis->next) { - if (false == UI_search_item_add(items, cis->name, SET_INT_IN_POINTER(cis->index), cis->iconid)) { - break; - } - } - - for (cis = items_list->first; cis; cis = cis->next) { - MEM_freeN(cis->name); - } - BLI_freelistN(items_list); - MEM_freeN(items_list); -} - static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA **prop) { StructRNA *srna; @@ -1768,6 +1681,8 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN /* turn button into search button */ if (searchprop) { + uiRNACollectionSearch *coll_search = MEM_mallocN(sizeof(*coll_search), __func__); + but->type = UI_BTYPE_SEARCH_MENU; but->hardmax = MAX2(but->hardmax, 256.0f); but->rnasearchpoin = *searchptr; @@ -1777,13 +1692,22 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN but->flag |= UI_BUT_VALUE_CLEAR; } + coll_search->target_ptr = *ptr; + coll_search->target_prop = prop; + coll_search->search_ptr = *searchptr; + coll_search->search_prop = searchprop; + coll_search->but_changed = &but->changed; + if (RNA_property_type(prop) == PROP_ENUM) { /* XXX, this will have a menu string, * but in this case we just want the text */ but->str[0] = 0; } - UI_but_func_search_set(but, ui_searchbox_create_generic, rna_search_cb, but, NULL, NULL); + UI_but_func_search_set( + but, ui_searchbox_create_generic, ui_rna_collection_search_cb, + coll_search, NULL, NULL); + but->free_search_arg = true; } else if (but->type == UI_BTYPE_SEARCH_MENU) { /* In case we fail to find proper searchprop, so other code might have already set but->type to search menu... */ diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 47b7e9aa085..5913f1c48f5 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -42,14 +42,19 @@ #include "BLT_lang.h" #include "BKE_context.h" +#include "BKE_idprop.h" +#include "BKE_layer.h" #include "BKE_screen.h" #include "BKE_global.h" #include "BKE_node.h" #include "BKE_text.h" /* for UI_OT_reports_to_text */ #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" +#include "RNA_types.h" #include "UI_interface.h" @@ -328,6 +333,125 @@ static void UI_OT_unset_property_button(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; } +/* Use/Unuse Property Button Operator ------------------------ */ + +static int use_property_button_exec(bContext *C, wmOperator *UNUSED(op)) +{ + PointerRNA ptr, scene_props_ptr; + PropertyRNA *prop; + IDProperty *props; + + uiBut *but = UI_context_active_but_get(C); + + prop = but->rnaprop; + ptr = but->rnapoin; + props = (IDProperty *)ptr.data; + /* XXX Using existing data struct to pass another RNAPointer */ + scene_props_ptr = but->rnasearchpoin; + + const char *identifier = RNA_property_identifier(prop); + if (IDP_GetPropertyFromGroup(props, identifier)) { + return OPERATOR_CANCELLED; + } + + int array_len = RNA_property_array_length(&scene_props_ptr, prop); + bool is_array = array_len != 0; + + switch (RNA_property_type(prop)) { + case PROP_FLOAT: + { + if (is_array) { + float values[RNA_MAX_ARRAY_LENGTH]; + RNA_property_float_get_array(&scene_props_ptr, prop, values); + BKE_collection_engine_property_add_float_array(props, identifier, values, array_len); + } + else { + float value = RNA_property_float_get(&scene_props_ptr, prop); + BKE_collection_engine_property_add_float(props, identifier, value); + } + break; + } + case PROP_ENUM: + { + int value = RNA_enum_get(&scene_props_ptr, identifier); + BKE_collection_engine_property_add_int(props, identifier, value); + break; + } + case PROP_INT: + { + int value = RNA_int_get(&scene_props_ptr, identifier); + BKE_collection_engine_property_add_int(props, identifier, value); + break; + } + case PROP_BOOLEAN: + { + int value = RNA_boolean_get(&scene_props_ptr, identifier); + BKE_collection_engine_property_add_bool(props, identifier, value); + break; + } + case PROP_STRING: + case PROP_POINTER: + case PROP_COLLECTION: + default: + break; + } + + /* TODO(sergey): Use proper flag for tagging here. */ + DEG_id_tag_update((ID *)CTX_data_scene(C), 0); + + return OPERATOR_FINISHED; +} + +static void UI_OT_use_property_button(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Use property"; + ot->idname = "UI_OT_use_property_button"; + ot->description = "Create a property"; + + /* callbacks */ + ot->poll = ED_operator_regionactive; + ot->exec = use_property_button_exec; + + /* flags */ + ot->flag = OPTYPE_UNDO; +} + +static int unuse_property_button_exec(bContext *C, wmOperator *UNUSED(op)) +{ + PointerRNA ptr; + PropertyRNA *prop; + int index; + + /* try to unset the nominated property */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + const char *identifier = RNA_property_identifier(prop); + + IDProperty *props = (IDProperty *)ptr.data; + IDProperty *prop_to_remove = IDP_GetPropertyFromGroup(props, identifier); + IDP_FreeFromGroup(props, prop_to_remove); + + /* TODO(sergey): Use proper flag for tagging here. */ + DEG_id_tag_update((ID *)CTX_data_scene(C), 0); + + return OPERATOR_FINISHED; +} + +static void UI_OT_unuse_property_button(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Unuse property"; + ot->idname = "UI_OT_unuse_property_button"; + ot->description = "Remove a property"; + + /* callbacks */ + ot->poll = ED_operator_regionactive; + ot->exec = unuse_property_button_exec; + + /* flags */ + ot->flag = OPTYPE_UNDO; +} + /* Copy To Selected Operator ------------------------ */ bool UI_context_copy_to_selected_list( @@ -1117,6 +1241,8 @@ void ED_operatortypes_ui(void) WM_operatortype_append(UI_OT_copy_python_command_button); WM_operatortype_append(UI_OT_reset_default_button); WM_operatortype_append(UI_OT_unset_property_button); + WM_operatortype_append(UI_OT_use_property_button); + WM_operatortype_append(UI_OT_unuse_property_button); WM_operatortype_append(UI_OT_copy_to_selected_button); WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */ WM_operatortype_append(UI_OT_drop_color); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index d9685d7281b..c3759e232b0 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -50,9 +50,6 @@ #include "BKE_context.h" #include "BKE_screen.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" - #include "BLF_api.h" #include "WM_api.h" @@ -65,6 +62,8 @@ #include "UI_interface_icons.h" #include "UI_resources.h" +#include "GPU_immediate.h" + #include "interface_intern.h" /*********************** defines and structs ************************/ @@ -393,54 +392,42 @@ static void ui_offset_panel_block(uiBlock *block) /**************************** drawing *******************************/ -/* extern used by previewrender */ -#if 0 /*UNUSED 2.5*/ -static void uiPanelPush(uiBlock *block) -{ - glPushMatrix(); - - if (block->panel) - glTranslatef((float)block->panel->ofsx, (float)block->panel->ofsy, 0.0); -} - -static void uiPanelPop(uiBlock *UNUSED(block)) -{ - glPopMatrix(); -} -#endif - /* triangle 'icon' for panel header */ -void UI_draw_icon_tri(float x, float y, char dir) +void UI_draw_icon_tri(float x, float y, char dir, const float color[4]) { float f3 = 0.15 * U.widget_unit; float f5 = 0.25 * U.widget_unit; float f7 = 0.35 * U.widget_unit; if (dir == 'h') { - ui_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y); + ui_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y, color); } else if (dir == 't') { - ui_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3); + ui_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3, color); } else { /* 'v' = vertical, down */ - ui_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7); + ui_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7, color); } } /* triangle 'icon' inside rect */ static void ui_draw_tria_rect(const rctf *rect, char dir) { + float color[4]; + UI_GetThemeColor3fv(TH_TITLE, color); + color[3] = 1.0f; + if (dir == 'h') { float half = 0.5f * BLI_rctf_size_y(rect); - ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half); + ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half, color); } else { float half = 0.5f * BLI_rctf_size_x(rect); - ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin); + ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin, color); } } -static void ui_draw_anti_x(float x1, float y1, float x2, float y2) +static void ui_draw_anti_x(unsigned int pos, float x1, float y1, float x2, float y2) { /* set antialias line */ @@ -448,9 +435,16 @@ static void ui_draw_anti_x(float x1, float y1, float x2, float y2) glEnable(GL_BLEND); glLineWidth(2.0); - - fdrawline(x1, y1, x2, y2); - fdrawline(x1, y2, x2, y1); + + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y2); + + immVertex2f(pos, x1, y2); + immVertex2f(pos, x2, y1); + + immEnd(); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); @@ -458,16 +452,16 @@ static void ui_draw_anti_x(float x1, float y1, float x2, float y2) } /* x 'icon' for panel header */ -static void ui_draw_x_icon(float x, float y) +static void ui_draw_x_icon(unsigned int pos, float x, float y) { - ui_draw_anti_x(x, y, x + 9.375f, y + 9.375f); + ui_draw_anti_x(pos, x, y, x + 9.375f, y + 9.375f); } #define PNL_ICON UI_UNIT_X /* could be UI_UNIT_Y too */ -static void ui_draw_panel_scalewidget(const rcti *rect) +static void ui_draw_panel_scalewidget(unsigned int pos, const rcti *rect) { float xmin, xmax, dx; float ymin, ymax, dy; @@ -481,16 +475,33 @@ static void ui_draw_panel_scalewidget(const rcti *rect) dy = 0.5f * (ymax - ymin); glEnable(GL_BLEND); - glColor4ub(255, 255, 255, 50); - fdrawline(xmin, ymin, xmax, ymax); - fdrawline(xmin + dx, ymin, xmax, ymax - dy); + immUniformColor4ub(255, 255, 255, 50); + + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, xmin, ymin); + immVertex2f(pos, xmax, ymax); + + immVertex2f(pos, xmin + dx, ymin); + immVertex2f(pos, xmax, ymax - dy); + + immEnd(); - glColor4ub(0, 0, 0, 50); - fdrawline(xmin, ymin + 1, xmax, ymax + 1); - fdrawline(xmin + dx, ymin + 1, xmax, ymax - dy + 1); + immUniformColor4ub(0, 0, 0, 50); + + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, xmin, ymin + 1); + immVertex2f(pos, xmax, ymax + 1); + + immVertex2f(pos, xmin + dx, ymin + 1); + immVertex2f(pos, xmax, ymax - dy + 1); + + immEnd(); + glDisable(GL_BLEND); } -static void ui_draw_panel_dragwidget(const rctf *rect) +static void ui_draw_panel_dragwidget(unsigned int pos, const rctf *rect) { unsigned char col_back[3], col_high[3], col_dark[3]; const int col_tint = 84; @@ -519,10 +530,10 @@ static void ui_draw_panel_dragwidget(const rctf *rect) const int x_co = (x_min + x_ofs) + (i_x * (box_size + box_margin)); const int y_co = (y_min + y_ofs) + (i_y * (box_size + box_margin)); - glColor3ubv(col_dark); - glRectf(x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom); - glColor3ubv(col_high); - glRectf(x_co - box_size, y_co, x_co, y_co + box_size); + immUniformColor3ubv(col_dark); + immRectf(pos, x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom); + immUniformColor3ubv(col_high); + immRectf(pos, x_co - box_size, y_co, x_co, y_co + box_size); } } } @@ -534,29 +545,30 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const r rcti hrect; int pnl_icons; const char *activename = panel->drawname[0] ? panel->drawname : panel->panelname; + unsigned char col_title[4]; /* + 0.001f to avoid flirting with float inaccuracy */ if (panel->control & UI_PNL_CLOSE) pnl_icons = (panel->labelofs + 2 * PNL_ICON + 5) / block->aspect + 0.001f; else pnl_icons = (panel->labelofs + PNL_ICON + 5) / block->aspect + 0.001f; - - /* active tab */ + /* draw text label */ - UI_ThemeColor(TH_TITLE); - + UI_GetThemeColor3ubv(TH_TITLE, col_title); + col_title[3] = 255; + hrect = *rect; if (dir == 'h') { hrect.xmin = rect->xmin + pnl_icons; hrect.ymin += 2.0f / block->aspect; - UI_fontstyle_draw(&style->paneltitle, &hrect, activename); + UI_fontstyle_draw(&style->paneltitle, &hrect, activename, col_title); } else { /* ignore 'pnl_icons', otherwise the text gets offset horizontally * + 0.001f to avoid flirting with float inaccuracy */ hrect.xmin = rect->xmin + (PNL_ICON + 5) / block->aspect + 0.001f; - UI_fontstyle_draw_rotated(&style->paneltitle, &hrect, activename); + UI_fontstyle_draw_rotated(&style->paneltitle, &hrect, activename, col_title); } } @@ -566,7 +578,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con Panel *panel = block->panel; rcti headrect; rctf itemrect; - int ofsx; + float color[4]; const bool is_closed_x = (panel->flag & PNL_CLOSEDX) ? true : false; const bool is_closed_y = (panel->flag & PNL_CLOSEDY) ? true : false; @@ -579,6 +591,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con headrect.ymin = headrect.ymax; headrect.ymax = headrect.ymin + floor(PNL_HEADER / block->aspect + 0.001f); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + { float minx = rect->xmin; float maxx = is_closed_x ? (minx + PNL_HEADER / block->aspect) : rect->xmax; @@ -588,11 +603,18 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con if (UI_GetThemeValue(TH_PANEL_SHOW_HEADER)) { /* draw with background color */ - UI_ThemeColor4(TH_PANEL_HEADER); - glRectf(minx, headrect.ymin + 1, maxx, y); + immUniformThemeColor(TH_PANEL_HEADER); + immRectf(pos, minx, headrect.ymin + 1, maxx, y); + + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, minx, y); + immVertex2f(pos, maxx, y); + + immVertex2f(pos, minx, y); + immVertex2f(pos, maxx, y); - fdrawline(minx, y, maxx, y); - fdrawline(minx, y, maxx, y); + immEnd(); } else if (!(panel->runtime_flag & PNL_FIRST)) { /* draw embossed separator */ @@ -602,15 +624,26 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con maxx -= 5.0f / block->aspect; } - glColor4f(0.0f, 0.0f, 0.0f, 0.5f); - fdrawline(minx, y, maxx, y); - glColor4f(1.0f, 1.0f, 1.0f, 0.25f); - fdrawline(minx, y - 1, maxx, y - 1); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, minx, y); + immVertex2f(pos, maxx, y); + immEnd(); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, minx, y - 1); + immVertex2f(pos, maxx, y - 1); + immEnd(); } glDisable(GL_BLEND); } + immUnbindProgram(); + /* draw optional pin icon */ #ifdef USE_PIN_HIDDEN @@ -626,9 +659,11 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con glDisable(GL_BLEND); } + /* horizontal title */ if (is_closed_x == false) { ui_draw_aligned_panel_header(style, block, &headrect, 'h'); + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); /* itemrect smaller */ itemrect.xmax = headrect.xmax - 5.0f / block->aspect; @@ -637,7 +672,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con itemrect.ymax = headrect.ymax; BLI_rctf_scale(&itemrect, 0.7f); - ui_draw_panel_dragwidget(&itemrect); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + ui_draw_panel_dragwidget(pos, &itemrect); + immUnbindProgram(); } /* if the panel is minimized vertically: @@ -649,6 +686,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con else if (is_closed_x) { /* draw vertical title */ ui_draw_aligned_panel_header(style, block, &headrect, 'v'); + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); } /* an open panel */ else { @@ -657,33 +695,37 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con if (panel->control & UI_PNL_SOLID) UI_draw_roundbox_corner_set(UI_CNR_ALL); else UI_draw_roundbox_corner_set(UI_CNR_NONE); - UI_ThemeColorShade(TH_BACK, -120); - UI_draw_roundbox_unfilled(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8); + UI_GetThemeColorShade4fv(TH_BACK, -120, color); + UI_draw_roundbox_aa(false, 0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8, color); } + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* panel backdrop */ if (UI_GetThemeValue(TH_PANEL_SHOW_BACK)) { /* draw with background color */ glEnable(GL_BLEND); - UI_ThemeColor4(TH_PANEL_BACK); - glRecti(rect->xmin, rect->ymin, rect->xmax, rect->ymax); + immUniformThemeColor(TH_PANEL_BACK); + immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); } if (panel->control & UI_PNL_SCALE) - ui_draw_panel_scalewidget(rect); + ui_draw_panel_scalewidget(pos, rect); + + immUnbindProgram(); } /* draw optional close icon */ - ofsx = 6; if (panel->control & UI_PNL_CLOSE) { - UI_ThemeColor(TH_TITLE); - ui_draw_x_icon(rect->xmin + 2 + ofsx, rect->ymax + 2); - ofsx = 22; + const int ofsx = 6; + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor3(TH_TITLE); + ui_draw_x_icon(pos, rect->xmin + 2 + ofsx, rect->ymax + 2); + immUnbindProgram(); } /* draw collapse icon */ - UI_ThemeColor(TH_TITLE); /* itemrect smaller */ itemrect.xmin = headrect.xmin + 5.0f / block->aspect; @@ -699,8 +741,6 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con ui_draw_tria_rect(&itemrect, 'h'); else ui_draw_tria_rect(&itemrect, 'v'); - - (void)ofsx; } /************************** panel alignment *************************/ @@ -1513,12 +1553,13 @@ void UI_panel_category_clear_all(ARegion *ar) BLI_freelistN(&ar->panels_category); } -/* based on UI_draw_roundbox_gl_mode, check on making a version which allows us to skip some sides */ +/* based on UI_draw_roundbox, check on making a version which allows us to skip some sides */ static void ui_panel_category_draw_tab( - int mode, float minx, float miny, float maxx, float maxy, float rad, + bool filled, float minx, float miny, float maxx, float maxy, float rad, int roundboxtype, - const bool use_highlight, const bool use_shadow, - const unsigned char highlight_fade[3]) + bool use_highlight, bool use_shadow, + const unsigned char highlight_fade[3], + const unsigned char col[3]) { float vec[4][2] = { {0.195, 0.02}, @@ -1527,74 +1568,96 @@ static void ui_panel_category_draw_tab( {0.98, 0.805}}; int a; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + /* mult */ for (a = 0; a < 4; a++) { mul_v2_fl(vec[a], rad); } - glBegin(mode); + unsigned int vert_ct = 0; + if (use_highlight) { + vert_ct += (roundboxtype & UI_CNR_TOP_RIGHT) ? 6 : 1; + vert_ct += (roundboxtype & UI_CNR_TOP_LEFT) ? 6 : 1; + } + if (use_highlight && !use_shadow) { + vert_ct++; + } + else { + vert_ct += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 6 : 1; + vert_ct += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 6 : 1; + } + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + + immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_STRIP, vert_ct); + + immAttrib3ubv(color, col); /* start with corner right-top */ if (use_highlight) { if (roundboxtype & UI_CNR_TOP_RIGHT) { - glVertex2f(maxx, maxy - rad); + immVertex2f(pos, maxx, maxy - rad); for (a = 0; a < 4; a++) { - glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]); + immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); } - glVertex2f(maxx - rad, maxy); + immVertex2f(pos, maxx - rad, maxy); } else { - glVertex2f(maxx, maxy); + immVertex2f(pos, maxx, maxy); } /* corner left-top */ if (roundboxtype & UI_CNR_TOP_LEFT) { - glVertex2f(minx + rad, maxy); + immVertex2f(pos, minx + rad, maxy); for (a = 0; a < 4; a++) { - glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]); + immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); } - glVertex2f(minx, maxy - rad); + immVertex2f(pos, minx, maxy - rad); } else { - glVertex2f(minx, maxy); + immVertex2f(pos, minx, maxy); } } if (use_highlight && !use_shadow) { if (highlight_fade) { - glColor3ubv(highlight_fade); + immAttrib3ubv(color, highlight_fade); } - glVertex2f(minx, miny + rad); - glEnd(); + immVertex2f(pos, minx, miny + rad); + immEnd(); + immUnbindProgram(); return; } /* corner left-bottom */ if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - glVertex2f(minx, miny + rad); + immVertex2f(pos, minx, miny + rad); for (a = 0; a < 4; a++) { - glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]); + immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); } - glVertex2f(minx + rad, miny); + immVertex2f(pos, minx + rad, miny); } else { - glVertex2f(minx, miny); + immVertex2f(pos, minx, miny); } /* corner right-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - glVertex2f(maxx - rad, miny); + immVertex2f(pos, maxx - rad, miny); for (a = 0; a < 4; a++) { - glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]); + immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); } - glVertex2f(maxx, miny + rad); + immVertex2f(pos, maxx, miny + rad); } else { - glVertex2f(maxx, miny); + immVertex2f(pos, maxx, miny); } - glEnd(); + immEnd(); + immUnbindProgram(); } @@ -1717,21 +1780,26 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active) /* begin drawing */ glEnable(GL_LINE_SMOOTH); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* draw the background */ if (is_alpha) { glEnable(GL_BLEND); - glColor4ubv(theme_col_tab_bg); + immUniformColor4ubv(theme_col_tab_bg); } else { - glColor3ubv(theme_col_tab_bg); + immUniformColor3ubv(theme_col_tab_bg); } - glRecti(v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax); + immRecti(pos, v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax); if (is_alpha) { glDisable(GL_BLEND); } + immUnbindProgram(); + for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) { const rcti *rct = &pc_dyn->rect; const char *category_id = pc_dyn->idname; @@ -1754,28 +1822,33 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active) if (is_active) #endif { - glColor3ubv(is_active ? theme_col_tab_active : theme_col_tab_inactive); - ui_panel_category_draw_tab(GL_POLYGON, rct->xmin, rct->ymin, rct->xmax, rct->ymax, - tab_curve_radius - px, roundboxtype, true, true, NULL); + ui_panel_category_draw_tab(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, + tab_curve_radius - px, roundboxtype, true, true, NULL, + is_active ? theme_col_tab_active : theme_col_tab_inactive); /* tab outline */ - glColor3ubv(theme_col_tab_outline); - ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin - px, rct->ymin - px, rct->xmax - px, rct->ymax + px, - tab_curve_radius, roundboxtype, true, true, NULL); + ui_panel_category_draw_tab(false, rct->xmin - px, rct->ymin - px, rct->xmax - px, rct->ymax + px, + tab_curve_radius, roundboxtype, true, true, NULL, theme_col_tab_outline); + /* tab highlight (3d look) */ - glColor3ubv(is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive); - ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, + ui_panel_category_draw_tab(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, tab_curve_radius, roundboxtype, true, false, - is_active ? theme_col_back : theme_col_tab_inactive); + is_active ? theme_col_back : theme_col_tab_inactive, + is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive); } /* tab blackline */ if (!is_active) { - glColor3ubv(theme_col_tab_divider); - glRecti(v2d->mask.xmin + category_tabs_width - px, - rct->ymin - tab_v_pad, - v2d->mask.xmin + category_tabs_width, - rct->ymax + tab_v_pad); + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3ubv(theme_col_tab_divider); + immRecti(pos, v2d->mask.xmin + category_tabs_width - px, + rct->ymin - tab_v_pad, + v2d->mask.xmin + category_tabs_width, + rct->ymax + tab_v_pad); + + immUnbindProgram(); } if (do_scaletabs) { @@ -1788,7 +1861,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active) /* tab titles */ /* draw white shadow to give text more depth */ - glColor3ubv(theme_col_text); + BLF_color3ubv(fontid, theme_col_text); /* main tab title */ BLF_draw(fontid, category_id_draw, category_draw_len); @@ -1796,33 +1869,36 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active) glDisable(GL_BLEND); /* tab blackline remaining (last tab) */ + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); if (pc_dyn->prev == NULL) { - glColor3ubv(theme_col_tab_divider); - glRecti(v2d->mask.xmin + category_tabs_width - px, - rct->ymax + px, - v2d->mask.xmin + category_tabs_width, - v2d->mask.ymax); + immUniformColor3ubv(theme_col_tab_divider); + immRecti(pos, v2d->mask.xmin + category_tabs_width - px, + rct->ymax + px, + v2d->mask.xmin + category_tabs_width, + v2d->mask.ymax); } if (pc_dyn->next == NULL) { - glColor3ubv(theme_col_tab_divider); - glRecti(v2d->mask.xmin + category_tabs_width - px, - 0, - v2d->mask.xmin + category_tabs_width, - rct->ymin); + immUniformColor3ubv(theme_col_tab_divider); + immRecti(pos, v2d->mask.xmin + category_tabs_width - px, + 0, + v2d->mask.xmin + category_tabs_width, + rct->ymin); } #ifdef USE_FLAT_INACTIVE /* draw line between inactive tabs */ if (is_active == false && is_active_prev == false && pc_dyn->prev) { - glColor3ubv(theme_col_tab_divider); - glRecti(v2d->mask.xmin + (category_tabs_width / 5), - rct->ymax + px, - (v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5), - rct->ymax + (px * 3)); + immUniformColor3ubv(theme_col_tab_divider); + immRecti(pos, v2d->mask.xmin + (category_tabs_width / 5), + rct->ymax + px, + (v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5), + rct->ymax + (px * 3)); } is_active_prev = is_active; #endif + immUnbindProgram(); /* not essential, but allows events to be handled right up until the region edge [#38171] */ pc_dyn->rect.xmin = v2d->mask.xmin; diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c index aa3e2464237..a0aecb12b84 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.c +++ b/source/blender/editors/interface/interface_region_menu_popup.c @@ -603,11 +603,13 @@ void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block) /* if loading new .blend while popup is open, window will be NULL */ if (block->handle) { if (win) { + const bScreen *screen = WM_window_get_active_screen(win); + UI_popup_handlers_remove(&win->modalhandlers, block->handle); ui_popup_block_free(C, block->handle); /* In the case we have nested popups, closing one may need to redraw another, see: T48874 */ - for (ARegion *ar = win->screen->regionbase.first; ar; ar = ar->next) { + for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) { ED_region_tag_refresh_ui(ar); } } diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index 15053f0d8ca..24990c593ac 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -324,7 +324,7 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar) * Use to refresh centered popups on screen resizing (for splash). */ static void ui_block_region_popup_window_listener( - bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene)) { switch (wmn->category) { case NC_WINDOW: diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index c9d313a4bab..f14f9af8785 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -397,7 +397,7 @@ int ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str) return match; } -static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) +static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar) { uiSearchboxData *data = ar->regiondata; @@ -415,6 +415,9 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) if (data->preview) { /* draw items */ for (a = 0; a < data->items.totitem; a++) { + /* ensure icon is up-to-date */ + ui_icon_ensure_deferred(C, data->items.icons[a], data->preview); + ui_searchbox_butrect(&rect, data, a); /* widget itself */ diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index 7d10087dcd9..f71b71fce43 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -157,6 +157,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) uiWidgetColors *theme = ui_tooltip_get_theme(); rcti bbox = data->bbox; float tip_colors[UI_TIP_LC_MAX][3]; + unsigned char drawcol[4] = {0, 0, 0, 255}; /* to store color in while drawing (alpha is always 255) */ float *main_color = tip_colors[UI_TIP_LC_MAIN]; /* the color from the theme */ float *value_color = tip_colors[UI_TIP_LC_VALUE]; @@ -225,9 +226,9 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) fstyle_header.shadowalpha = 1.0f; fstyle_header.word_wrap = true; + rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_MAIN]); UI_fontstyle_set(&fstyle_header); - glColor3fv(tip_colors[UI_TIP_LC_MAIN]); - UI_fontstyle_draw(&fstyle_header, &bbox, field->text); + UI_fontstyle_draw(&fstyle_header, &bbox, field->text, drawcol); fstyle_header.shadow = 0; @@ -238,8 +239,8 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) bbox.xmin += xofs; bbox.ymax -= yofs; - glColor3fv(tip_colors[UI_TIP_LC_ACTIVE]); - UI_fontstyle_draw(&fstyle_header, &bbox, field->text_suffix); + rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_ACTIVE]); + UI_fontstyle_draw(&fstyle_header, &bbox, field->text_suffix, drawcol); /* undo offset */ bbox.xmin -= xofs; @@ -254,8 +255,8 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) UI_fontstyle_set(&fstyle_mono); /* XXX, needed because we dont have mono in 'U.uifonts' */ BLF_size(fstyle_mono.uifont_id, fstyle_mono.points * U.pixelsize, U.dpi); - glColor3fv(tip_colors[field->format.color_id]); - UI_fontstyle_draw(&fstyle_mono, &bbox, field->text); + rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]); + UI_fontstyle_draw(&fstyle_mono, &bbox, field->text, drawcol); } else { uiFontStyle fstyle_normal = data->fstyle; @@ -263,9 +264,9 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) fstyle_normal.word_wrap = true; /* draw remaining data */ + rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]); UI_fontstyle_set(&fstyle_normal); - glColor3fv(tip_colors[field->format.color_id]); - UI_fontstyle_draw(&fstyle_normal, &bbox, field->text); + UI_fontstyle_draw(&fstyle_normal, &bbox, field->text, drawcol); } bbox.ymax -= data->lineh * field->geom.lines; @@ -306,6 +307,65 @@ static void ui_tooltip_region_free_cb(ARegion *ar) /** \name ToolTip Creation * \{ */ +static uiTooltipData *ui_tooltip_data_from_keymap(bContext *C, wmKeyMap *keymap) +{ + char buf[512]; + + /* create tooltip data */ + uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData"); + + BLI_assert(data->fields_len < MAX_TOOLTIP_LINES); + + for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { + wmOperatorType *ot = WM_operatortype_find(kmi->idname, true); + if (ot != NULL) { + /* Tip */ + { + uiTooltipField *field = text_field_add( + data, &(uiTooltipFormat){ + .style = UI_TIP_STYLE_NORMAL, + .color_id = UI_TIP_LC_MAIN, + .is_pad = true, + }); + field->text = BLI_strdup(ot->description[0] ? ot->description : ot->name); + } + /* Shortcut */ + { + uiTooltipField *field = text_field_add( + data, &(uiTooltipFormat){ + .style = UI_TIP_STYLE_NORMAL, + .color_id = UI_TIP_LC_NORMAL, + }); + bool found = false; + if (WM_keymap_item_to_string(kmi, false, buf, sizeof(buf))) { + found = true; + } + field->text = BLI_sprintfN(TIP_("Shortcut: %s"), found ? buf : "None"); + } + + /* Python */ + { + uiTooltipField *field = text_field_add( + data, &(uiTooltipFormat){ + .style = UI_TIP_STYLE_NORMAL, + .color_id = UI_TIP_LC_PYTHON, + }); + char *str = WM_operator_pystring_ex(C, NULL, false, false, ot, kmi->ptr); + WM_operator_pystring_abbreviate(str, 32); + field->text = BLI_sprintfN(TIP_("Python: %s"), str); + MEM_freeN(str); + } + } + } + if (data->fields_len == 0) { + MEM_freeN(data); + return NULL; + } + else { + return data; + } +} + static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but) { uiStringInfo but_tip = {BUT_GET_TIP, NULL}; @@ -586,8 +646,27 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) if (but->drawflag & UI_BUT_NO_TOOLTIP) { return NULL; } + uiTooltipData *data = NULL; + + /* custom tips for pre-defined operators */ + if (but->optype) { + if (STREQ(but->optype->idname, "WM_OT_tool_set")) { + char keymap[64] = ""; + RNA_string_get(but->opptr, "keymap", keymap); + if (keymap[0]) { + ScrArea *sa = CTX_wm_area(C); + wmKeyMap *km = WM_keymap_find_all(C, keymap, sa->spacetype, RGN_TYPE_WINDOW); + if (km != NULL) { + data = ui_tooltip_data_from_keymap(C, km); + } + } + } + } + /* toolsystem exception */ - uiTooltipData *data = ui_tooltip_data_from_button(C, but); + if (data == NULL) { + data = ui_tooltip_data_from_button(C, but); + } if (data == NULL) { return NULL; } diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index dd1d38bbe2e..fa25a119ada 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -61,6 +61,9 @@ ARegion *ui_region_temp_add(bScreen *sc) void ui_region_temp_remove(bContext *C, bScreen *sc, ARegion *ar) { wmWindow *win = CTX_wm_window(C); + + BLI_assert(ar->regiontype == RGN_TYPE_TEMPORARY); + BLI_assert(BLI_findindex(&sc->regionbase, ar) != -1); if (win) wm_draw_region_clear(win, ar); diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index 8b41302b5bb..01456e2e122 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -149,7 +149,7 @@ static uiFont *uifont_to_blfont(int id) void UI_fontstyle_draw_ex( - const uiFontStyle *fs, const rcti *rect, const char *str, + const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4], size_t len, float *r_xofs, float *r_yofs) { int xofs = 0, yofs; @@ -196,6 +196,7 @@ void UI_fontstyle_draw_ex( /* clip is very strict, so we give it some space */ BLF_clipping(fs->uifont_id, rect->xmin - 2, rect->ymin - 4, rect->xmax + 1, rect->ymax + 4); BLF_position(fs->uifont_id, rect->xmin + xofs, rect->ymin + yofs, 0.0f); + BLF_color4ubv(fs->uifont_id, col); BLF_draw(fs->uifont_id, str, len); @@ -205,17 +206,17 @@ void UI_fontstyle_draw_ex( *r_yofs = yofs; } -void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str) +void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4]) { float xofs, yofs; UI_fontstyle_draw_ex( - fs, rect, str, + fs, rect, str, col, BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs); } /* drawn same as above, but at 90 degree angle */ -void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str) +void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4]) { float height; int xofs, yofs; @@ -249,6 +250,7 @@ void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const ch BLF_enable(fs->uifont_id, BLF_ROTATION); BLF_rotation(fs->uifont_id, angle); + BLF_color4ubv(fs->uifont_id, col); if (fs->shadow) { BLF_enable(fs->uifont_id, BLF_SHADOW); @@ -275,13 +277,14 @@ void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const ch * * For drawing on-screen labels. */ -void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str) +void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str, const unsigned char col[4]) { if (fs->kerning == 1) BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT); UI_fontstyle_set(fs); BLF_position(fs->uifont_id, x, y, 0.0f); + BLF_color4ubv(fs->uifont_id, col); BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX); if (fs->kerning == 1) @@ -293,7 +296,7 @@ void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const cha */ void UI_fontstyle_draw_simple_backdrop( const uiFontStyle *fs, float x, float y, const char *str, - const unsigned char fg[4], const unsigned char bg[4]) + const float col_fg[4], const float col_bg[4]) { if (fs->kerning == 1) BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT); @@ -307,21 +310,19 @@ void UI_fontstyle_draw_simple_backdrop( const float margin = height / 4.0f; /* backdrop */ - glColor4ubv(bg); + float color[4] = { col_bg[0], col_bg[1], col_bg[2], 0.5f }; - UI_draw_roundbox_corner_set(UI_CNR_ALL | UI_RB_ALPHA); - UI_draw_roundbox( + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_aa(true, x - margin, (y + decent) - margin, x + width + margin, (y + decent) + height + margin, - margin); - - glColor4ubv(fg); + margin, color); } - BLF_position(fs->uifont_id, x, y, 0.0f); + BLF_color4fv(fs->uifont_id, col_fg); BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX); if (fs->kerning == 1) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index e1e18b1f102..9cc0136ebdd 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -55,10 +55,10 @@ #include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idcode.h" #include "BKE_idprop.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_linestyle.h" #include "BKE_main.h" @@ -72,6 +72,9 @@ #include "BKE_screen.h" #include "BKE_texture.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "ED_screen.h" #include "ED_object.h" #include "ED_render.h" @@ -91,11 +94,126 @@ // #define USE_OP_RESET_BUT // we may want to make this optional, disable for now. +/* defines for templateID/TemplateSearch */ +#define TEMPLATE_SEARCH_TEXTBUT_WIDTH (UI_UNIT_X * 6) +#define TEMPLATE_SEARCH_TEXTBUT_HEIGHT UI_UNIT_Y + void UI_template_fix_linking(void) { } +/** + * Add a block button for the search menu for templateID and templateSearch. + */ +static void template_add_button_search_menu( + const bContext *C, uiLayout *layout, uiBlock *block, + PointerRNA *ptr, PropertyRNA *prop, + uiBlockCreateFunc block_func, void *block_argN, const char * const tip, + const bool use_previews, const bool editable) +{ + PointerRNA active_ptr = RNA_property_pointer_get(ptr, prop); + ID *id = (active_ptr.data && RNA_struct_is_ID(active_ptr.type)) ? active_ptr.data : NULL; + const ID *idfrom = ptr->id.data; + const StructRNA *type = active_ptr.type ? active_ptr.type : RNA_property_pointer_type(ptr, prop); + uiBut *but; + + if (use_previews) { + ARegion *region = CTX_wm_region(C); + const bool use_big_size = (region->regiontype != RGN_TYPE_HEADER); /* silly check, could be more generic */ + /* Ugly exception for screens here, drawing their preview in icon size looks ugly/useless */ + const bool use_preview_icon = use_big_size || (id && (GS(id->name) != ID_SCR)); + const short width = UI_UNIT_X * (use_big_size ? 6 : 1.6f); + const short height = UI_UNIT_Y * (use_big_size ? 6 : 1); + + but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, width, height, tip); + if (use_preview_icon) { + int icon = id ? ui_id_icon_get(C, id, use_big_size) : RNA_struct_ui_icon(type); + ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); + } + else { + ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON); + UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); + } + + if ((idfrom && idfrom->lib) || !editable) + UI_but_flag_enable(but, UI_BUT_DISABLED); + if (use_big_size) { + uiLayoutRow(layout, true); + } + } + else { + but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, tip); + ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON); + if (id) { + /* default dragging of icon for id browse buttons */ + UI_but_drag_set_id(but, id); + } + UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); + + if ((idfrom && idfrom->lib) || !editable) + UI_but_flag_enable(but, UI_BUT_DISABLED); + } +} + +static uiBlock *template_common_search_menu( + const bContext *C, ARegion *region, + uiButSearchFunc search_func, void *search_arg, + uiButHandleFunc handle_func, void *active_item, + const int preview_rows, const int preview_cols) +{ + static char search[256]; + wmWindow *win = CTX_wm_window(C); + uiBlock *block; + uiBut *but; + + /* clear initial search string, then all items show */ + search[0] = 0; + + block = UI_block_begin(C, region, "_popup", UI_EMBOSS); + UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU); + + /* preview thumbnails */ + if (preview_rows > 0 && preview_cols > 0) { + const int w = 4 * U.widget_unit * preview_cols; + const int h = 5 * U.widget_unit * preview_rows; + + /* fake button, it holds space for search items */ + uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL); + + but = uiDefSearchBut( + block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y, + preview_rows, preview_cols, ""); + } + /* list view */ + else { + const int searchbox_width = UI_searchbox_size_x(); + const int searchbox_height = UI_searchbox_size_y(); + + /* fake button, it holds space for search items */ + uiDefBut( + block, UI_BTYPE_LABEL, 0, "", 10, 15, searchbox_width, searchbox_height, + NULL, 0, 0, 0, 0, NULL); + but = uiDefSearchBut( + block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, + searchbox_width, UI_UNIT_Y - 1, 0, 0, ""); + } + UI_but_func_search_set( + but, ui_searchbox_create_generic, search_func, + search_arg, handle_func, active_item); + + + UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); + UI_block_direction_set(block, UI_DIR_DOWN); + + /* give search-field focus */ + UI_but_focus_on_enter_event(win, but); + /* this type of search menu requires undo */ + but->flag |= UI_BUT_UNDO; + + return block; +} + /********************** Header Template *************************/ void uiTemplateHeader(uiLayout *layout, bContext *C) @@ -177,61 +295,16 @@ static void id_search_cb(const bContext *C, void *arg_template, const char *str, /* ID Search browse menu, open */ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) { - static char search[256]; static TemplateID template; - PointerRNA idptr; - wmWindow *win = CTX_wm_window(C); - uiBlock *block; - uiBut *but; - - /* clear initial search string, then all items show */ - search[0] = 0; + PointerRNA active_item_ptr; + /* arg_litem is malloced, can be freed by parent button */ template = *((TemplateID *)arg_litem); - - /* get active id for showing first item */ - idptr = RNA_property_pointer_get(&template.ptr, template.prop); + active_item_ptr = RNA_property_pointer_get(&template.ptr, template.prop); - block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); - UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU); - - /* preview thumbnails */ - if (template.prv_rows > 0 && template.prv_cols > 0) { - int w = 4 * U.widget_unit * template.prv_cols; - int h = 5 * U.widget_unit * template.prv_rows; - - /* fake button, it holds space for search items */ - uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL); - - but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y, - template.prv_rows, template.prv_cols, ""); - UI_but_func_search_set( - but, ui_searchbox_create_generic, id_search_cb, - &template, id_search_call_cb, idptr.data); - } - /* list view */ - else { - const int searchbox_width = UI_searchbox_size_x(); - const int searchbox_height = UI_searchbox_size_y(); - - /* fake button, it holds space for search items */ - uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 15, searchbox_width, searchbox_height, NULL, 0, 0, 0, 0, NULL); - but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, searchbox_width, UI_UNIT_Y - 1, 0, 0, ""); - UI_but_func_search_set( - but, ui_searchbox_create_generic, id_search_cb, - &template, id_search_call_cb, idptr.data); - } - - - UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); - UI_block_direction_set(block, UI_DIR_DOWN); - - /* give search-field focus */ - UI_but_focus_on_enter_event(win, but); - /* this type of search menu requires undo */ - but->flag |= UI_BUT_UNDO; - - return block; + return template_common_search_menu( + C, ar, id_search_cb, &template, id_search_call_cb, active_item_ptr.data, + template.prv_rows, template.prv_cols); } /************************ ID Template ***************************/ @@ -330,13 +403,13 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) Scene *scene = CTX_data_scene(C); ED_object_single_user(bmain, scene, (struct Object *)id); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } else { if (id) { Main *bmain = CTX_data_main(C); id_single_user(C, id, &template->ptr, template->prop); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } } } @@ -348,7 +421,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) } } -static const char *template_id_browse_tip(StructRNA *type) +static const char *template_id_browse_tip(const StructRNA *type) { if (type) { switch (RNA_type_to_ID_code(type)) { @@ -380,6 +453,8 @@ static const char *template_id_browse_tip(StructRNA *type) case ID_PAL: return N_("Browse Palette Data to be linked"); case ID_PC: return N_("Browse Paint Curve Data to be linked"); case ID_CF: return N_("Browse Cache Files to be linked"); + case ID_WS: return N_("Browse Workspace to be linked"); + case ID_LP: return N_("Browse LightProbe to be linked"); } } return N_("Browse ID data to be linked"); @@ -409,6 +484,7 @@ static void template_ID( // ListBase *lb; // UNUSED ID *id, *idfrom; const bool editable = RNA_property_editable(&template->ptr, template->prop); + const bool use_previews = template->preview = (flag & UI_ID_PREVIEWS) != 0; idptr = RNA_property_pointer_get(&template->ptr, template->prop); id = idptr.data; @@ -421,29 +497,11 @@ static void template_ID( if (idptr.type) type = idptr.type; - if (flag & UI_ID_PREVIEWS) { - template->preview = true; - - but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, - TIP_(template_id_browse_tip(type))); - ui_def_but_icon(but, id ? ui_id_icon_get(C, id, true) : RNA_struct_ui_icon(type), - UI_HAS_ICON | UI_BUT_ICON_PREVIEW); - - if ((idfrom && idfrom->lib) || !editable) - UI_but_flag_enable(but, UI_BUT_DISABLED); - - uiLayoutRow(layout, true); - } - else if (flag & UI_ID_BROWSE) { - but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, - TIP_(template_id_browse_tip(type))); - ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON); - /* default dragging of icon for id browse buttons */ - UI_but_drag_set_id(but, id); - UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); - - if ((idfrom && idfrom->lib) || !editable) - UI_but_flag_enable(but, UI_BUT_DISABLED); + if (flag & UI_ID_BROWSE) { + template_add_button_search_menu( + C, layout, block, &template->ptr, template->prop, + id_search_menu, MEM_dupallocN(template), TIP_(template_id_browse_tip(type)), + use_previews, editable); } /* text button with name */ @@ -453,8 +511,9 @@ static void template_ID( //text_idbutton(id, name); name[0] = '\0'; - but = uiDefButR(block, UI_BTYPE_TEXT, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, - &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); + but = uiDefButR( + block, UI_BTYPE_TEXT, 0, name, 0, 0, TEMPLATE_SEARCH_TEXTBUT_WIDTH, TEMPLATE_SEARCH_TEXTBUT_HEIGHT, + &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME)); if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT); @@ -499,7 +558,7 @@ static void template_ID( if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT); - if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) { + if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { uiDefButR(block, UI_BTYPE_TOGGLE, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL); } } @@ -533,6 +592,8 @@ static void template_ID( BLT_I18NCONTEXT_ID_PARTICLESETTINGS, BLT_I18NCONTEXT_ID_GPENCIL, BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE, + BLT_I18NCONTEXT_ID_WORKSPACE, + BLT_I18NCONTEXT_ID_LIGHTPROBE, ); if (newop) { @@ -740,6 +801,204 @@ void uiTemplateAnyID( uiItemFullR(sub, ptr, propID, 0, 0, 0, "", ICON_NONE); } +/********************* Search Template ********************/ + +typedef struct TemplateSearch { + uiRNACollectionSearch search_data; + + bool use_previews; + int preview_rows, preview_cols; +} TemplateSearch; + +static void template_search_handle_cb(bContext *C, void *arg_template, void *item) +{ + TemplateSearch *template_search = arg_template; + uiRNACollectionSearch *coll_search = &template_search->search_data; + StructRNA *type = RNA_property_pointer_type(&coll_search->target_ptr, coll_search->target_prop); + PointerRNA item_ptr; + + RNA_pointer_create(NULL, type, item, &item_ptr); + RNA_property_pointer_set(&coll_search->target_ptr, coll_search->target_prop, item_ptr); + RNA_property_update(C, &coll_search->target_ptr, coll_search->target_prop); +} + +static uiBlock *template_search_menu(bContext *C, ARegion *region, void *arg_template) +{ + static TemplateSearch template_search; + PointerRNA active_ptr; + + /* arg_template is malloced, can be freed by parent button */ + template_search = *((TemplateSearch *)arg_template); + active_ptr = RNA_property_pointer_get(&template_search.search_data.target_ptr, + template_search.search_data.target_prop); + + return template_common_search_menu( + C, region, ui_rna_collection_search_cb, &template_search, + template_search_handle_cb, active_ptr.data, + template_search.preview_rows, template_search.preview_cols); +} + +static void template_search_add_button_searchmenu( + const bContext *C, uiLayout *layout, uiBlock *block, + TemplateSearch *template_search, const bool editable) +{ + const char *ui_description = RNA_property_ui_description(template_search->search_data.target_prop); + + template_add_button_search_menu( + C, layout, block, + &template_search->search_data.target_ptr, template_search->search_data.target_prop, + template_search_menu, MEM_dupallocN(template_search), ui_description, + template_search->use_previews, editable); +} + +static void template_search_add_button_name( + uiBlock *block, PointerRNA *active_ptr, const StructRNA *type) +{ + uiDefAutoButR( + block, active_ptr, RNA_struct_name_property(type), 0, "", ICON_NONE, + 0, 0, TEMPLATE_SEARCH_TEXTBUT_WIDTH, TEMPLATE_SEARCH_TEXTBUT_HEIGHT); +} + +static void template_search_add_button_operator( + uiBlock *block, const char * const operator_name, + const int opcontext, const int icon, const bool editable) +{ + if (!operator_name) { + return; + } + + uiBut *but = uiDefIconButO( + block, UI_BTYPE_BUT, operator_name, opcontext, icon, + 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); + + if (!editable) { + UI_but_drawflag_enable(but, UI_BUT_DISABLED); + } +} + +static void template_search_buttons( + const bContext *C, uiLayout *layout, TemplateSearch *template_search, + const char *newop, const char *unlinkop) +{ + uiBlock *block = uiLayoutGetBlock(layout); + uiRNACollectionSearch *search_data = &template_search->search_data; + StructRNA *type = RNA_property_pointer_type(&search_data->target_ptr, search_data->target_prop); + const bool editable = RNA_property_editable(&search_data->target_ptr, search_data->target_prop); + PointerRNA active_ptr = RNA_property_pointer_get(&search_data->target_ptr, search_data->target_prop); + + if (active_ptr.type) { + /* can only get correct type when there is an active item */ + type = active_ptr.type; + } + + uiLayoutRow(layout, true); + UI_block_align_begin(block); + + template_search_add_button_searchmenu(C, layout, block, template_search, editable); + template_search_add_button_name(block, &active_ptr, type); + template_search_add_button_operator(block, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, editable); + template_search_add_button_operator(block, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, editable); + + UI_block_align_end(block); +} + +static PropertyRNA *template_search_get_searchprop( + PointerRNA *targetptr, PropertyRNA *targetprop, + PointerRNA *searchptr, const char * const searchpropname) +{ + PropertyRNA *searchprop; + + if (searchptr && !searchptr->data) { + searchptr = NULL; + } + + if (!searchptr && !searchpropname) { + /* both NULL means we don't use a custom rna collection to search in */ + } + else if (!searchptr && searchpropname) { + RNA_warning("searchpropname defined (%s) but searchptr is missing", searchpropname); + } + else if (searchptr && !searchpropname) { + RNA_warning("searchptr defined (%s) but searchpropname is missing", RNA_struct_identifier(searchptr->type)); + } + else if (!(searchprop = RNA_struct_find_property(searchptr, searchpropname))) { + RNA_warning("search collection property not found: %s.%s", + RNA_struct_identifier(searchptr->type), searchpropname); + } + else if (RNA_property_type(searchprop) != PROP_COLLECTION) { + RNA_warning("search collection property is not a collection type: %s.%s", + RNA_struct_identifier(searchptr->type), searchpropname); + } + /* check if searchprop has same type as targetprop */ + else if (RNA_property_pointer_type(searchptr, searchprop) != RNA_property_pointer_type(targetptr, targetprop)) { + RNA_warning("search collection items from %s.%s are not of type %s", + RNA_struct_identifier(searchptr->type), searchpropname, + RNA_struct_identifier(RNA_property_pointer_type(targetptr, targetprop))); + } + else { + return searchprop; + } + + return NULL; +} + +static TemplateSearch *template_search_setup( + PointerRNA *ptr, const char * const propname, + PointerRNA *searchptr, const char * const searchpropname) +{ + TemplateSearch *template_search; + PropertyRNA *prop, *searchprop; + + prop = RNA_struct_find_property(ptr, propname); + + if (!prop || RNA_property_type(prop) != PROP_POINTER) { + RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); + return NULL; + } + searchprop = template_search_get_searchprop(ptr, prop, searchptr, searchpropname); + + template_search = MEM_callocN(sizeof(*template_search), __func__); + template_search->search_data.target_ptr = *ptr; + template_search->search_data.target_prop = prop; + template_search->search_data.search_ptr = *searchptr; + template_search->search_data.search_prop = searchprop; + + return template_search; +} + +/** + * Search menu to pick an item from a collection. + * A version of uiTemplateID that works for non-ID types. + */ +void uiTemplateSearch( + uiLayout *layout, bContext *C, + PointerRNA *ptr, const char *propname, + PointerRNA *searchptr, const char *searchpropname, + const char *newop, const char *unlinkop) +{ + TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname); + template_search_buttons(C, layout, template_search, newop, unlinkop); + MEM_freeN(template_search); +} + +void uiTemplateSearchPreview( + uiLayout *layout, bContext *C, + PointerRNA *ptr, const char *propname, + PointerRNA *searchptr, const char *searchpropname, + const char *newop, const char *unlinkop, + const int rows, const int cols) +{ + TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname); + + template_search->use_previews = true; + template_search->preview_rows = rows; + template_search->preview_cols = cols; + + template_search_buttons(C, layout, template_search, newop, unlinkop); + + MEM_freeN(template_search); +} + /********************* RNA Path Builder Template ********************/ /* ---------- */ @@ -793,7 +1052,7 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v) ob->partype = PAROBJECT; WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); ED_undo_push(C, "Modifier convert to real"); } @@ -937,7 +1196,7 @@ static uiLayout *draw_modifier( /* When Modifier is a simulation, show button to switch to context rather than the delete button. */ if (modifier_can_delete(md) && (!modifier_is_simulation(md) || - STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME))) + STREQ(scene->view_render.engine_id, RE_engine_id_BLENDER_GAME))) { uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove"); } @@ -1074,7 +1333,7 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event) Main *bmain = CTX_data_main(C); if (ob->pose) BKE_pose_tag_recalc(bmain, ob->pose); /* checks & sorts pose channels */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); break; } #endif @@ -1088,8 +1347,8 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event) * object_test_constraints(ob); * if (ob->pose) BKE_pose_update_constraint_flags(ob->pose); */ - if (ob->type == OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); - else DAG_id_tag_update(&ob->id, OB_RECALC_OB); + if (ob->type == OB_ARMATURE) DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); + else DEG_id_tag_update(&ob->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); } @@ -3849,6 +4108,7 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr) if (propptr.data) { uiBut *but = uiLayoutGetBlock(layout)->buttons.last; + WM_operator_properties_sanitize(&propptr, false); template_keymap_item_properties(layout, NULL, &propptr); /* attach callbacks to compensate for missing properties update, @@ -3865,6 +4125,66 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr) } } +/********************************* Overrides *************************************/ + +void uiTemplateOverrideProperty( + uiLayout *layout, PointerRNA *collection_props_ptr, PointerRNA *scene_props_ptr, const char *propname, + const char *name, const char *text_ctxt, int translate, int icon, + const char *custom_template) +{ + bool is_set = false; + uiLayout *row, *col; + + PointerRNA *ptr; + PropertyRNA *prop; + + IDProperty *collection_props = collection_props_ptr->data; + + if (IDP_GetPropertyFromGroup(collection_props, propname)) { + prop = RNA_struct_find_property(collection_props_ptr, propname); + ptr = collection_props_ptr; + is_set = RNA_property_is_set(ptr, prop); + } + else { + /* property doesn't exist yet */ + prop = RNA_struct_find_property(scene_props_ptr, propname); + ptr = scene_props_ptr; + } + + /* Get translated name (label). */ + name = RNA_translate_ui_text(name, text_ctxt, NULL, prop, translate); + + row = uiLayoutRow(layout, false); + col = uiLayoutColumn(row, false); + + uiLayoutSetEnabled(col, is_set); + + if (custom_template && STREQ(custom_template, "icon_view")) { + uiTemplateIconView(col, ptr, propname, false, 5.0f); + } + else { + uiItemFullR(col, ptr, prop, -1, 0, 0, name, icon); + } + + col = uiLayoutColumn(row, false); + uiBut *but; + uiBlock *block = uiLayoutGetBlock(col); + UI_block_emboss_set(block, UI_EMBOSS_NONE); + + if (is_set) { + but = uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_unuse_property_button", WM_OP_EXEC_DEFAULT, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); + } + else { + but = uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_use_property_button", WM_OP_EXEC_DEFAULT, ICON_ZOOMIN, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); + /* XXX - Using existing data struct to pass another RNAPointer */ + but->rnasearchpoin = *scene_props_ptr; + } + + but->rnapoin = *collection_props_ptr; + but->rnaprop = prop; + UI_block_emboss_set(block, UI_EMBOSS); +} + /********************************* Color management *************************************/ void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char *propname) diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 1927d7280f3..f0317087ddc 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -215,8 +215,90 @@ int uiDefAutoButsRNA( return tot; } -/***************************** ID Utilities *******************************/ +/* *** RNA collection search menu *** */ +typedef struct CollItemSearch { + struct CollItemSearch *next, *prev; + void *data; + char *name; + int index; + int iconid; +} CollItemSearch; + +static int sort_search_items_list(const void *a, const void *b) +{ + const CollItemSearch *cis1 = a; + const CollItemSearch *cis2 = b; + + if (BLI_strcasecmp(cis1->name, cis2->name) > 0) + return 1; + else + return 0; +} + +void ui_rna_collection_search_cb(const struct bContext *C, void *arg, const char *str, uiSearchItems *items) +{ + uiRNACollectionSearch *data = arg; + char *name; + int i = 0, iconid = 0, flag = RNA_property_flag(data->target_prop); + ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list"); + CollItemSearch *cis; + const bool skip_filter = !(data->but_changed && *data->but_changed); + + /* build a temporary list of relevant items first */ + RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop) + { + + if (flag & PROP_ID_SELF_CHECK) + if (itemptr.data == data->target_ptr.id.data) + continue; + + /* use filter */ + if (RNA_property_type(data->target_prop) == PROP_POINTER) { + if (RNA_property_pointer_poll(&data->target_ptr, data->target_prop, &itemptr) == 0) + continue; + } + + name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */ + iconid = 0; + if (itemptr.type && RNA_struct_is_ID(itemptr.type)) { + iconid = ui_id_icon_get(C, itemptr.data, false); + } + + if (name) { + if (skip_filter || BLI_strcasestr(name, str)) { + cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch"); + cis->data = itemptr.data; + cis->name = MEM_dupallocN(name); + cis->index = i; + cis->iconid = iconid; + BLI_addtail(items_list, cis); + } + MEM_freeN(name); + } + + i++; + } + RNA_PROP_END; + + BLI_listbase_sort(items_list, sort_search_items_list); + + /* add search items from temporary list */ + for (cis = items_list->first; cis; cis = cis->next) { + if (UI_search_item_add(items, cis->name, cis->data, cis->iconid) == false) { + break; + } + } + + for (cis = items_list->first; cis; cis = cis->next) { + MEM_freeN(cis->name); + } + BLI_freelistN(items_list); + MEM_freeN(items_list); +} + + +/***************************** ID Utilities *******************************/ int UI_icon_from_id(ID *id) { Object *ob; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 39ee8e2885d..2f996eb7e39 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -47,9 +47,6 @@ #include "RNA_access.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" - #include "BLF_api.h" #include "UI_interface.h" @@ -58,6 +55,9 @@ #include "interface_intern.h" #include "GPU_basic_shader.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" #ifdef WITH_INPUT_IME # include "WM_types.h" @@ -208,48 +208,58 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}} /* ************************************************* */ -void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3) +void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3, + const float color[4]) { float tri_arr[3][2] = {{x1, y1}, {x2, y2}, {x3, y3}}; - float color[4]; - int j; - + float draw_color[4]; + + copy_v4_v4(draw_color, color); + draw_color[3] *= 0.125f; + glEnable(GL_BLEND); - glGetFloatv(GL_CURRENT_COLOR, color); - color[3] *= 0.125f; - glColor4fv(color); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, tri_arr); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4fv(draw_color); + immBegin(GWN_PRIM_TRIS, 3 * WIDGET_AA_JITTER); /* for each AA step */ - for (j = 0; j < WIDGET_AA_JITTER; j++) { - glTranslate2fv(jit[j]); - glDrawArrays(GL_TRIANGLES, 0, 3); - glTranslatef(-jit[j][0], -jit[j][1], 0.0f); + for (int j = 0; j < WIDGET_AA_JITTER; j++) { + immVertex2f(pos, tri_arr[0][0] + jit[j][0], tri_arr[0][1] + jit[j][1]); + immVertex2f(pos, tri_arr[1][0] + jit[j][0], tri_arr[1][1] + jit[j][1]); + immVertex2f(pos, tri_arr[2][0] + jit[j][0], tri_arr[2][1] + jit[j][1]); } - glDisableClientState(GL_VERTEX_ARRAY); + immEnd(); + + immUnbindProgram(); + glDisable(GL_BLEND); } -void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha) +/* belongs in interface_draw.c, but needs WIDGET_AA_JITTER from this file */ +void UI_draw_roundbox_aa(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4]) { - float color[4]; - int j; - glEnable(GL_BLEND); - glGetFloatv(GL_CURRENT_COLOR, color); - if (use_alpha) { - color[3] = 0.5f; + + if (filled) { + /* plain antialiased filled box */ + const float alpha = color[3] * 0.125f; + + for (int j = 0; j < WIDGET_AA_JITTER; j++) { + gpuPushMatrix(); + gpuTranslate2fv(jit[j]); + UI_draw_roundbox_3fvAlpha(true, minx, miny, maxx, maxy, rad, color, alpha); + gpuPopMatrix(); + } } - color[3] *= 0.125f; - glColor4fv(color); - - for (j = 0; j < WIDGET_AA_JITTER; j++) { - glTranslate2fv(jit[j]); - UI_draw_roundbox_gl_mode(mode, minx, miny, maxx, maxy, rad); - glTranslatef(-jit[j][0], -jit[j][1], 0.0f); + else { + /* plain antialiased unfilled box */ + glEnable(GL_LINE_SMOOTH); + UI_draw_roundbox_4fv(false, minx, miny, maxx, maxy, rad, color); + glDisable(GL_LINE_SMOOTH); } glDisable(GL_BLEND); @@ -570,12 +580,27 @@ static void shape_preset_init_scroll_circle(uiWidgetTrias *tria, const rcti *rec g_shape_preset_scroll_circle_face, ARRAY_SIZE(g_shape_preset_scroll_circle_face)); } -static void shape_preset_draw_trias(uiWidgetTrias *tria) +static void shape_preset_draw_trias(uiWidgetTrias *tria, uint pos) +{ + immBegin(GWN_PRIM_TRIS, tria->tot * 3); + for (int i = 0; i < tria->tot; ++i) + for (int j = 0; j < 3; ++j) + immVertex2fv(pos, tria->vec[tria->index[i][j]]); + immEnd(); +} + +static void widget_draw_vertex_buffer(unsigned int pos, unsigned int col, int mode, + const float quads_pos[WIDGET_SIZE_MAX][2], + const unsigned char quads_col[WIDGET_SIZE_MAX][4], + unsigned int totvert) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, tria->vec); - glDrawElements(GL_TRIANGLES, tria->tot * 3, GL_UNSIGNED_INT, tria->index); - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(mode, totvert); + for (int i = 0; i < totvert; ++i) { + if (quads_col) + immAttrib4ubv(col, quads_col[i]); + immVertex2fv(pos, quads_pos[i]); + } + immEnd(); } static void shape_preset_trias_from_rect_menu(uiWidgetTrias *tria, const rcti *rect) @@ -666,21 +691,18 @@ static void widget_verts_to_triangle_strip_open(uiWidgetBase *wtb, const int tot } } -static void widgetbase_outline(uiWidgetBase *wtb) +static void widgetbase_outline(uiWidgetBase *wtb, unsigned int pos) { float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */ widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, triangle_strip); - glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2); - glDisableClientState(GL_VERTEX_ARRAY); + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2); } static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) { int j, a; - + glEnable(GL_BLEND); /* backdrop non AA */ @@ -690,78 +712,76 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) float inner_v_half[WIDGET_SIZE_MAX][2]; float x_mid = 0.0f; /* used for dumb clamping of values */ - /* dark checkers */ - glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_CHECKER); - /* light checkers */ - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_CHECKER_8PX); + /* checkers */ + immUniform4f("color1", UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, 1.0f); + immUniform4f("color2", UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 1.0f); + immUniform1i("size", 8); - glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + immUnbindProgram(); /* alpha fill */ - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv((unsigned char *)wcol->inner); - glColor4ubv((unsigned char *)wcol->inner); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); for (a = 0; a < wtb->totvert; a++) { x_mid += wtb->inner_v[a][0]; } x_mid /= wtb->totvert; - glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert); /* 1/2 solid color */ - glColor4ub(wcol->inner[0], wcol->inner[1], wcol->inner[2], 255); + immUniformColor3ubv((unsigned char *)wcol->inner); for (a = 0; a < wtb->totvert; a++) { inner_v_half[a][0] = MIN2(wtb->inner_v[a][0], x_mid); inner_v_half[a][1] = wtb->inner_v[a][1]; } - glVertexPointer(2, GL_FLOAT, 0, inner_v_half); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); - glDisableClientState(GL_VERTEX_ARRAY); + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, inner_v_half, NULL, wtb->totvert); + + immUnbindProgram(); } else { /* simple fill */ - glColor4ubv((unsigned char *)wcol->inner); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv((unsigned char *)wcol->inner); + + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); - glDisableClientState(GL_VERTEX_ARRAY); + immUnbindProgram(); } } else { char col1[4], col2[4]; - unsigned char col_array[WIDGET_SIZE_MAX * 4]; - unsigned char *col_pt = col_array; - + unsigned char col_array[WIDGET_SIZE_MAX][4]; + unsigned char *col_pt = &col_array[0][0]; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown); for (a = 0; a < wtb->totvert; a++, col_pt += 4) { round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->draw_shadedir ? 1 : 0]); } - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glColorPointer(4, GL_UNSIGNED_BYTE, 0, col_array); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); + widget_draw_vertex_buffer(pos, col, GL_TRIANGLE_FAN, wtb->inner_v, col_array, wtb->totvert); + immUnbindProgram(); } } - + /* for each AA step */ if (wtb->draw_outline) { float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */ @@ -780,53 +800,55 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss); } - glEnableClientState(GL_VERTEX_ARRAY); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); for (j = 0; j < WIDGET_AA_JITTER; j++) { - glTranslate2fv(jit[j]); + gpuTranslate2fv(jit[j]); /* outline */ - glColor4ubv(tcol); + immUniformColor4ubv(tcol); - glVertexPointer(2, GL_FLOAT, 0, triangle_strip); - glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2); + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2); /* emboss bottom shadow */ if (wtb->draw_emboss) { if (emboss[3]) { - glColor4ubv(emboss); - glVertexPointer(2, GL_FLOAT, 0, triangle_strip_emboss); - glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->halfwayvert * 2); + immUniformColor4ubv(emboss); + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip_emboss, NULL, wtb->halfwayvert * 2); } } - glTranslatef(-jit[j][0], -jit[j][1], 0.0f); + gpuTranslate2f(-jit[j][0], -jit[j][1]); } - - glDisableClientState(GL_VERTEX_ARRAY); + immUnbindProgram(); } - + /* decoration */ if (wtb->tria1.tot || wtb->tria2.tot) { const unsigned char tcol[4] = {wcol->item[0], wcol->item[1], wcol->item[2], (unsigned char)((float)wcol->item[3] / WIDGET_AA_JITTER)}; - glColor4ubv(tcol); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv(tcol); /* for each AA step */ for (j = 0; j < WIDGET_AA_JITTER; j++) { - glTranslate2fv(jit[j]); + gpuTranslate2fv(jit[j]); - if (wtb->tria1.tot) { - shape_preset_draw_trias(&wtb->tria1); - } - if (wtb->tria2.tot) { - shape_preset_draw_trias(&wtb->tria2); - } + if (wtb->tria1.tot) + shape_preset_draw_trias(&wtb->tria1, pos); + + if (wtb->tria2.tot) + shape_preset_draw_trias(&wtb->tria2, pos); - glTranslatef(-jit[j][0], -jit[j][1], 0.0f); + gpuTranslate2f(-jit[j][0], -jit[j][1]); } + + immUnbindProgram(); } glDisable(GL_BLEND); @@ -1282,6 +1304,7 @@ static void widget_draw_text_ime_underline( int ofs_x, width; int rect_x = BLI_rcti_size_x(rect); int sel_start = ime_data->sel_start, sel_end = ime_data->sel_end; + float fcol[4]; if (drawstr[0] != 0) { if (but->pos >= but->ofs) { @@ -1294,8 +1317,8 @@ static void widget_draw_text_ime_underline( width = BLF_width(fstyle->uifont_id, drawstr + but->ofs, ime_data->composite_len + but->pos - but->ofs); - glColor4ubv((unsigned char *)wcol->text); - UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1); + rgba_uchar_to_float(fcol, wcol->text); + UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1, fcol); /* draw the thick line */ if (sel_start != -1 && sel_end != -1) { @@ -1312,7 +1335,7 @@ static void widget_draw_text_ime_underline( width = BLF_width(fstyle->uifont_id, drawstr + but->ofs, sel_end + sel_start - but->ofs); - UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2); + UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2, fcol); } } } @@ -1396,11 +1419,16 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b selwidth_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selend - but->ofs); - glColor4ubv((unsigned char *)wcol->item); - glRecti(rect->xmin + selsta_draw, - rect->ymin + 2, - min_ii(rect->xmin + selwidth_draw, rect->xmax - 2), - rect->ymax - 2); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4ubv((unsigned char *)wcol->item); + immRecti(pos, rect->xmin + selsta_draw, + rect->ymin + 2, + min_ii(rect->xmin + selwidth_draw, rect->xmax - 2), + rect->ymax - 2); + + immUnbindProgram(); } } @@ -1423,13 +1451,18 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b t = 0; } - glColor3f(0.2, 0.6, 0.9); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3f(0.2f, 0.6f, 0.9f); tx = rect->xmin + t + 2; ty = rect->ymin + 2; /* draw cursor */ - glRecti(rect->xmin + t, ty, tx, rect->ymax - 2); + immRecti(pos, rect->xmin + t, ty, tx, rect->ymax - 2); + + immUnbindProgram(); } #ifdef WITH_INPUT_IME @@ -1488,43 +1521,46 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b } #endif - glColor4ubv((unsigned char *)wcol->text); - if (!use_right_only) { /* for underline drawing */ float font_xofs, font_yofs; - UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs, - drawstr_left_len - but->ofs, &font_xofs, &font_yofs); + int drawlen = (drawstr_left_len == INT_MAX) ? strlen(drawstr + but->ofs) : (drawstr_left_len - but->ofs); - if (but->menu_key != '\0') { - char fixedbuf[128]; - const char *str; + if (drawlen > 0) { + UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs, (unsigned char *)wcol->text, + drawlen, &font_xofs, &font_yofs); - BLI_strncpy(fixedbuf, drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawstr_left_len)); + if (but->menu_key != '\0') { + char fixedbuf[128]; + const char *str; - str = strchr(fixedbuf, but->menu_key - 32); /* upper case */ - if (str == NULL) - str = strchr(fixedbuf, but->menu_key); + BLI_strncpy(fixedbuf, drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawlen)); - if (str) { - int ul_index = -1; - float ul_advance; + str = strchr(fixedbuf, but->menu_key - 32); /* upper case */ + if (str == NULL) + str = strchr(fixedbuf, but->menu_key); - ul_index = (int)(str - fixedbuf); + if (str) { + int ul_index = -1; + float ul_advance; - if (fstyle->kerning == 1) { - BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); - } + ul_index = (int)(str - fixedbuf); - fixedbuf[ul_index] = '\0'; - ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index); + if (fstyle->kerning == 1) { + BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + } + + fixedbuf[ul_index] = '\0'; + ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index); - BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f); - BLF_draw(fstyle->uifont_id, "_", 2); + BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f); + BLF_color4ubv(fstyle->uifont_id, (unsigned char *)wcol->text); + BLF_draw(fstyle->uifont_id, "_", 2); - if (fstyle->kerning == 1) { - BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + if (fstyle->kerning == 1) { + BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + } } } } @@ -1534,7 +1570,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b if (drawstr_right) { fstyle->align = UI_STYLE_TEXT_RIGHT; rect->xmax -= UI_TEXT_CLIP_MARGIN; - UI_fontstyle_draw(fstyle, rect, drawstr_right); + UI_fontstyle_draw(fstyle, rect, drawstr_right, (unsigned char *)wcol->text); } } @@ -1657,6 +1693,9 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB widget_draw_text(fstyle, wcol, but, rect); ui_but_text_password_hide(password_str, but, true); + + /* if a widget uses font shadow it has to be deactivated now */ + BLF_disable(fstyle->uifont_id, BLF_SHADOW); } #undef UI_TEXT_CLIP_MARGIN @@ -1915,6 +1954,19 @@ static struct uiWidgetColors wcol_list_item = { 0, 0 }; +struct uiWidgetColors wcol_tab = { + {255, 255, 255, 255}, + {83, 83, 83, 255}, + {114, 114, 114, 255}, + {90, 90, 90, 255}, + + {0, 0, 0, 255}, + {0, 0, 0, 255}, + + 0, + 0, 0 +}; + /* free wcol struct to play with */ static struct uiWidgetColors wcol_tmp = { {0, 0, 0, 255}, @@ -1937,6 +1989,7 @@ void ui_widget_color_init(ThemeUI *tui) tui->wcol_tool = wcol_tool; tui->wcol_text = wcol_text; tui->wcol_radio = wcol_radio; + tui->wcol_tab = wcol_tab; tui->wcol_option = wcol_option; tui->wcol_toggle = wcol_toggle; tui->wcol_num = wcol_num; @@ -2195,23 +2248,24 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r /* we draw a number of increasing size alpha quad strips */ alphastep = 3.0f * btheme->tui.menu_shadow_fac / radout; - - glEnableClientState(GL_VERTEX_ARRAY); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); for (step = 1; step <= (int)radout; step++) { float expfac = sqrtf(step / radout); round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step); - glColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac)); + immUniformColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac)); widget_verts_to_triangle_strip(&wtb, totvert, triangle_strip); - glVertexPointer(2, GL_FLOAT, 0, triangle_strip); - glDrawArrays(GL_TRIANGLE_STRIP, 0, totvert * 2); /* add + 2 for getting a complete soft rect. Now it skips top edge to allow transparent menus */ + widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, totvert * 2); } - glDisableClientState(GL_VERTEX_ARRAY); + immUnbindProgram(); } static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction) @@ -2248,20 +2302,21 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir static void ui_hsv_cursor(float x, float y) { - glPushMatrix(); - glTranslatef(x, y, 0.0f); - - glColor3f(1.0f, 1.0f, 1.0f); - glutil_draw_filled_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 8); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3f(1.0f, 1.0f, 1.0f); + imm_draw_circle_fill_2d(pos, x, y, 3.0f * U.pixelsize, 8); glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - glColor3f(0.0f, 0.0f, 0.0f); - glutil_draw_lined_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 12); + immUniformColor3f(0.0f, 0.0f, 0.0f); + imm_draw_circle_wire_2d(pos, x, y, 3.0f * U.pixelsize, 12); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - - glPopMatrix(); + + immUnbindProgram(); } void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect, @@ -2301,18 +2356,17 @@ void ui_hsvcircle_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *rect) { + /* TODO(merwin): reimplement as shader for pixel-perfect colors */ + const int tot = 64; const float radstep = 2.0f * (float)M_PI / (float)tot; const float centx = BLI_rcti_cent_x_fl(rect); const float centy = BLI_rcti_cent_y_fl(rect); float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f; - /* gouraud triangle fan */ ColorPicker *cpicker = but->custom_data; const float *hsv_ptr = cpicker->color_data; - float xpos, ypos, ang = 0.0f; float rgb[3], hsvo[3], hsv[3], col[3], colcent[3]; - int a; bool color_profile = ui_but_is_colorpicker_display_space(but); /* color */ @@ -2343,11 +2397,18 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * ui_color_picker_to_rgb(0.0f, 0.0f, hsv[2], colcent, colcent + 1, colcent + 2); - glBegin(GL_TRIANGLE_FAN); - glColor3fv(colcent); - glVertex2f(centx, centy); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + + immBegin(GWN_PRIM_TRI_FAN, tot + 2); + immAttrib3fv(color, colcent); + immVertex2f(pos, centx, centy); - for (a = 0; a <= tot; a++, ang += radstep) { + float ang = 0.0f; + for (int a = 0; a <= tot; a++, ang += radstep) { float si = sinf(ang); float co = cosf(ang); @@ -2355,25 +2416,32 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * ui_color_picker_to_rgb_v(hsv, col); - glColor3fv(col); - glVertex2f(centx + co * radius, centy + si * radius); + immAttrib3fv(color, col); + immVertex2f(pos, centx + co * radius, centy + si * radius); } - glEnd(); - + immEnd(); + immUnbindProgram(); + /* fully rounded outline */ - glPushMatrix(); - glTranslatef(centx, centy, 0.0f); + format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - glColor3ubv((unsigned char *)wcol->outline); - glutil_draw_lined_arc(0.0f, M_PI * 2.0, radius, tot + 1); + + immUniformColor3ubv((unsigned char *)wcol->outline); + imm_draw_circle_wire_2d(pos, centx, centy, radius, tot); + + immUnbindProgram(); + glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - glPopMatrix(); /* cursor */ + float xpos, ypos; ui_hsvcircle_pos_from_vals(but, rect, hsvo, &xpos, &ypos); - ui_hsv_cursor(xpos, ypos); } @@ -2383,7 +2451,8 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha) { /* allows for 4 steps (red->yellow) */ - const float color_step = 1.0f / 48.0f; + const int steps = 48; + const float color_step = 1.0f / steps; int a; float h = hsv[0], s = hsv[1], v = hsv[2]; float dx, dy, sx1, sx2, sy; @@ -2437,9 +2506,14 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons copy_v3_v3(col1[3], col1[2]); break; } - + /* old below */ + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + immBegin(GWN_PRIM_TRIS, steps * 3 * 6); for (dx = 0.0f; dx < 0.999f; dx += color_step) { /* 0.999 = prevent float inaccuracy for steps */ const float dx_next = dx + color_step; @@ -2497,22 +2571,29 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons sy = rect->ymin; dy = (float)BLI_rcti_size_y(rect) / 3.0f; - glBegin(GL_QUADS); for (a = 0; a < 3; a++, sy += dy) { - glColor4f(col0[a][0], col0[a][1], col0[a][2], alpha); - glVertex2f(sx1, sy); + immAttrib4f(col, col0[a][0], col0[a][1], col0[a][2], alpha); + immVertex2f(pos, sx1, sy); - glColor4f(col1[a][0], col1[a][1], col1[a][2], alpha); - glVertex2f(sx2, sy); + immAttrib4f(col, col1[a][0], col1[a][1], col1[a][2], alpha); + immVertex2f(pos, sx2, sy); - glColor4f(col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha); - glVertex2f(sx2, sy + dy); + immAttrib4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha); + immVertex2f(pos, sx2, sy + dy); + + immAttrib4f(col, col0[a][0], col0[a][1], col0[a][2], alpha); + immVertex2f(pos, sx1, sy); + + immAttrib4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha); + immVertex2f(pos, sx2, sy + dy); - glColor4f(col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha); - glVertex2f(sx1, sy + dy); + immAttrib4f(col, col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha); + immVertex2f(pos, sx1, sy + dy); } - glEnd(); } + immEnd(); + + immUnbindProgram(); } bool ui_but_is_colorpicker_display_space(uiBut *but) @@ -2588,8 +2669,11 @@ static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect) ui_hsv_cursor(x, y); /* outline */ - glColor3ub(0, 0, 0); - fdrawbox((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax)); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3ub(0, 0, 0); + imm_draw_box_wire_2d(pos, (rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax)); + immUnbindProgram(); } /* vertical 'value' slider, using new widget code */ @@ -2657,12 +2741,22 @@ static void ui_draw_separator(const rcti *rect, uiWidgetColors *wcol) wcol->text[2], 30 }; - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + glEnable(GL_BLEND); - glColor4ubv(col); + immUniformColor4ubv(col); glLineWidth(1.0f); - sdrawline(rect->xmin, y, rect->xmax, y); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, rect->xmin, y); + immVertex2f(pos, rect->xmax, y); + immEnd(); + glDisable(GL_BLEND); + + immUnbindProgram(); } /* ************ button callbacks, draw ***************** */ @@ -2734,11 +2828,14 @@ bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol) } #define LINK_RESOL 24 -void ui_draw_link_bezier(const rcti *rect) +void ui_draw_link_bezier(const rcti *rect, const float color[4]) { float coord_array[LINK_RESOL + 1][2]; if (ui_link_bezier_points(rect, coord_array, LINK_RESOL)) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + #if 0 /* unused */ /* we can reuse the dist variable here to increment the GL curve eval amount*/ const float dist = 1.0f / (float)LINK_RESOL; @@ -2746,13 +2843,17 @@ void ui_draw_link_bezier(const rcti *rect) glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, coord_array); - glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL + 1); - glDisableClientState(GL_VERTEX_ARRAY); + immUniformColor4fv(color); + + immBegin(GWN_PRIM_LINE_STRIP, LINK_RESOL + 1); + for (int i = 0; i <= LINK_RESOL; ++i) + immVertex2fv(pos, coord_array[i]); + immEnd(); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); + + immUnbindProgram(); } } @@ -2934,15 +3035,16 @@ static void widget_link(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect, in if (but->flag & UI_SELECT) { rcti rectlink; + float color[4]; - UI_ThemeColor(TH_TEXT_HI); + UI_GetThemeColor4fv(TH_TEXT_HI, color); rectlink.xmin = BLI_rcti_cent_x(rect); rectlink.ymin = BLI_rcti_cent_y(rect); rectlink.xmax = but->linkto[0]; rectlink.ymax = but->linkto[1]; - ui_draw_link_bezier(&rectlink); + ui_draw_link_bezier(&rectlink, color); } } @@ -3094,13 +3196,18 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat float bw = rgb_to_grayscale(col); bw += (bw < 0.5f) ? 0.5f : -0.5f; - - glColor4f(bw, bw, bw, 1.0); - glBegin(GL_TRIANGLES); - glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.9f * height); - glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.5f * height); - glVertex2f(rect->xmin + 0.5f * width, rect->ymin + 0.9f * height); - glEnd(); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3f(bw, bw, bw); + immBegin(GWN_PRIM_TRIS, 3); + immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.9f * height); + immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.5f * height); + immVertex2f(pos, rect->xmin + 0.5f * width, rect->ymin + 0.9f * height); + immEnd(); + + immUnbindProgram(); } } @@ -3416,12 +3523,50 @@ static void widget_roundbut_exec(uiWidgetColors *wcol, rcti *rect, int state, in widgetbase_draw(&wtb, wcol); } +static void widget_tab(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign) +{ + const uiStyle *style = UI_style_get(); + const float rad = 0.15f * U.widget_unit; + const int fontid = style->widget.uifont_id; + const bool is_active = (but->flag & UI_SELECT); + + uiWidgetBase wtb; + unsigned char theme_col_tab_highlight[3]; + + /* create outline highlight colors */ + if (is_active) { + interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner_sel, + (unsigned char *)wcol->outline, 0.2f); + } + else { + interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner, + (unsigned char *)wcol->outline, 0.12f); + } + + widget_init(&wtb); + + /* half rounded */ + round_box_edges(&wtb, roundboxalign, rect, rad); + + /* draw inner */ + wtb.draw_outline = 0; + widgetbase_draw(&wtb, wcol); + + /* draw outline (3d look) */ + ui_draw_but_TAB_outline(rect, rad, theme_col_tab_highlight, (unsigned char *)wcol->inner); + + /* text shadow */ + BLF_enable(fontid, BLF_SHADOW); + BLF_shadow(fontid, 3, (const float[4]){1.0f, 1.0f, 1.0f, 0.25f}); + BLF_shadow_offset(fontid, 0, -1); +} + static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect) { uiWidgetBase wtb; const float rad = 0.25f * U.widget_unit; unsigned char col[4]; - + /* state copy! */ wt->wcol = *(wt->wcol_theme); @@ -3431,12 +3576,17 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType * /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */ but->block->drawextra(C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* make mask to draw over image */ UI_GetThemeColor3ubv(TH_BACK, col); - glColor3ubv(col); - + immUniformColor3ubv(col); + round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, rad); - widgetbase_outline(&wtb); + widgetbase_outline(&wtb, pos); + + immUnbindProgram(); } /* outline */ @@ -3498,6 +3648,11 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) wt.draw = widget_roundbut_exec; break; + case UI_WTYPE_TAB: + wt.custom = widget_tab; + wt.wcol_theme = &btheme->tui.wcol_tab; + break; + case UI_WTYPE_TOOLTIP: wt.wcol_theme = &btheme->tui.wcol_tooltip; wt.draw = widget_menu_back; @@ -3760,7 +3915,11 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct if (but->block->flag & UI_BLOCK_LOOP) wt->wcol_theme = &btheme->tui.wcol_menu_back; break; - + + case UI_BTYPE_TAB: + wt = widget_type(UI_WTYPE_TAB); + break; + case UI_BTYPE_BUT_TOGGLE: case UI_BTYPE_TOGGLE: case UI_BTYPE_TOGGLE_N: @@ -3962,15 +4121,21 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect) wt->draw(&wt->wcol, rect, 0, 0); if (block) { + float draw_color[4]; + unsigned char *color = (unsigned char *)wt->wcol.text; + + draw_color[0] = ((float)color[0]) / 255.0f; + draw_color[1] = ((float)color[1]) / 255.0f; + draw_color[2] = ((float)color[2]) / 255.0f; + draw_color[3] = 1.0f; + if (block->flag & UI_BLOCK_CLIPTOP) { /* XXX no scaling for UI here yet */ - glColor3ubv((unsigned char *)wt->wcol.text); - UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't'); + UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't', draw_color); } if (block->flag & UI_BLOCK_CLIPBOTTOM) { /* XXX no scaling for UI here yet */ - glColor3ubv((unsigned char *)wt->wcol.text); - UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v'); + UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v', draw_color); } } } @@ -3988,33 +4153,21 @@ static void draw_disk_shaded( float y1, y2; float fac; unsigned char r_col[4]; + unsigned int pos, col; - glBegin(GL_TRIANGLE_STRIP); - - s = sinf(start); - c = cosf(start); - - y1 = s * radius_int; - y2 = s * radius_ext; - + Gwn_VertFormat *format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); if (shaded) { - fac = (y1 + radius_ext) * radius_ext_scale; - round_box_shade_col4_r(r_col, col1, col2, fac); - - glColor4ubv(r_col); + col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); } - - glVertex2f(c * radius_int, s * radius_int); - - if (shaded) { - fac = (y2 + radius_ext) * radius_ext_scale; - round_box_shade_col4_r(r_col, col1, col2, fac); - - glColor4ubv(r_col); + else { + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv((unsigned char *)col1); } - glVertex2f(c * radius_ext, s * radius_ext); - for (i = 1; i < subd; i++) { + immBegin(GWN_PRIM_TRI_STRIP, subd * 2); + for (i = 0; i < subd; i++) { float a; a = start + ((i) / (float)(subd - 1)) * angle; @@ -4026,20 +4179,20 @@ static void draw_disk_shaded( if (shaded) { fac = (y1 + radius_ext) * radius_ext_scale; round_box_shade_col4_r(r_col, col1, col2, fac); - - glColor4ubv(r_col); + immAttrib4ubv(col, r_col); } - glVertex2f(c * radius_int, s * radius_int); + immVertex2f(pos, c * radius_int, s * radius_int); if (shaded) { fac = (y2 + radius_ext) * radius_ext_scale; round_box_shade_col4_r(r_col, col1, col2, fac); - - glColor4ubv(r_col); + immAttrib4ubv(col, r_col); } - glVertex2f(c * radius_ext, s * radius_ext); + immVertex2f(pos, c * radius_ext, s * radius_ext); } - glEnd(); + immEnd(); + + immUnbindProgram(); } void ui_draw_pie_center(uiBlock *block) @@ -4058,8 +4211,8 @@ void ui_draw_pie_center(uiBlock *block) float angle = atan2f(pie_dir[1], pie_dir[0]); float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_2 : M_PI_4; - glPushMatrix(); - glTranslatef(cx, cy, 0.0f); + gpuPushMatrix(); + gpuTranslate2f(cx, cy); glEnable(GL_BLEND); if (btheme->tui.wcol_pie_menu.shaded) { @@ -4068,8 +4221,7 @@ void ui_draw_pie_center(uiBlock *block) draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, col1, col2, true); } else { - glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner); - draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, NULL, NULL, false); + draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, btheme->tui.wcol_pie_menu.inner, NULL, false); } if (!(block->pie_data.flags & UI_PIE_INVALID_DIR)) { @@ -4079,25 +4231,34 @@ void ui_draw_pie_center(uiBlock *block) draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, col1, col2, true); } else { - glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner_sel); - draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, NULL, NULL, false); + draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, btheme->tui.wcol_pie_menu.inner_sel, NULL, false); } } - glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.outline); - glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_internal, subd); - glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_external, subd); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv((unsigned char *)btheme->tui.wcol_pie_menu.outline); + + imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_internal, subd); + imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_external, subd); + + immUnbindProgram(); if (U.pie_menu_confirm > 0 && !(block->pie_data.flags & (UI_PIE_INVALID_DIR | UI_PIE_CLICK_STYLE))) { float pie_confirm_radius = U.pixelsize * (pie_radius_internal + U.pie_menu_confirm); float pie_confirm_external = U.pixelsize * (pie_radius_internal + U.pie_menu_confirm + 7.0f); - glColor4ub(btheme->tui.wcol_pie_menu.text_sel[0], btheme->tui.wcol_pie_menu.text_sel[1], btheme->tui.wcol_pie_menu.text_sel[2], 64); - draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, NULL, NULL, false); + const char col[4] = {btheme->tui.wcol_pie_menu.text_sel[0], + btheme->tui.wcol_pie_menu.text_sel[1], + btheme->tui.wcol_pie_menu.text_sel[2], + 64}; + + draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, col, NULL, false); } glDisable(GL_BLEND); - glPopMatrix(); + gpuPopMatrix(); } @@ -4181,8 +4342,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0'); } - glColor4ubv((unsigned char *)wt->wcol.text); - UI_fontstyle_draw(fstyle, rect, drawstr); + UI_fontstyle_draw(fstyle, rect, drawstr, (unsigned char *)wt->wcol.text); } /* part text right aligned */ @@ -4190,7 +4350,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic if (cpoin) { fstyle->align = UI_STYLE_TEXT_RIGHT; rect->xmax = _rect.xmax - 5; - UI_fontstyle_draw(fstyle, rect, cpoin + 1); + UI_fontstyle_draw(fstyle, rect, cpoin + 1, (unsigned char *)wt->wcol.text); *cpoin = UI_SEP_CHAR; } } @@ -4248,8 +4408,7 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int BLI_strncpy(drawstr, name, sizeof(drawstr)); UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0'); - glColor4ubv((unsigned char *)wt->wcol.text); - UI_fontstyle_draw(fstyle, &trect, drawstr); + UI_fontstyle_draw(fstyle, &trect, drawstr, (unsigned char *)wt->wcol.text); } } diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 4b47d0da13e..bf42316289f 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -53,6 +53,8 @@ #include "BIF_gl.h" +#include "BLF_api.h" + #include "UI_interface.h" #include "UI_interface_icons.h" @@ -665,6 +667,17 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo case TH_AXIS_Z: cp = btheme->tui.zaxis; break; + case TH_MANIPULATOR_HI: + cp = btheme->tui.manipulator_hi; break; + case TH_MANIPULATOR_PRIMARY: + cp = btheme->tui.manipulator_primary; break; + case TH_MANIPULATOR_SECONDARY: + cp = btheme->tui.manipulator_secondary; break; + case TH_MANIPULATOR_A: + cp = btheme->tui.manipulator_a; break; + case TH_MANIPULATOR_B: + cp = btheme->tui.manipulator_b; break; + case TH_INFO_SELECTED: cp = ts->info_selected; break; @@ -835,6 +848,15 @@ static void ui_theme_space_init_handles_color(ThemeSpace *theme_space) rgba_char_args_set(theme_space->act_spline, 0xdb, 0x25, 0x12, 255); } +static void ui_theme_space_init_manipulator_colors(bTheme *btheme) +{ + rgba_char_args_set(btheme->tui.manipulator_hi, 255, 255, 255, 255); + rgba_char_args_set(btheme->tui.manipulator_primary, 222, 255, 13, 255); + rgba_char_args_set(btheme->tui.manipulator_secondary, 0, 255, 255, 255); + rgba_char_args_set(btheme->tui.manipulator_a, 23, 127, 23, 255); + rgba_char_args_set(btheme->tui.manipulator_b, 127, 23, 23, 255); +} + /** * initialize default theme * \note: when you add new colors, created & saved themes need initialized @@ -875,6 +897,9 @@ void ui_theme_init_default(void) /* common (new) variables */ ui_theme_init_new(btheme); + /* Manipulator. */ + ui_theme_space_init_manipulator_colors(btheme); + /* space view3d */ rgba_char_args_set_fl(btheme->tv3d.back, 0.225, 0.225, 0.225, 1.0); rgba_char_args_set(btheme->tv3d.text, 0, 0, 0, 255); @@ -1272,25 +1297,35 @@ void UI_ThemeColor4(int colorid) cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); glColor4ubv(cp); - } /* set the color with offset for shades */ void UI_ThemeColorShade(int colorid, int offset) { - int r, g, b; + unsigned char col[4]; + UI_GetThemeColorShade4ubv(colorid, offset, col); + glColor4ubv(col); +} + +void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset) +{ + int r, g, b, a; const unsigned char *cp; cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); - r = offset + (int) cp[0]; + r = coloffset + (int) cp[0]; CLAMP(r, 0, 255); - g = offset + (int) cp[1]; + g = coloffset + (int) cp[1]; CLAMP(g, 0, 255); - b = offset + (int) cp[2]; + b = coloffset + (int) cp[2]; CLAMP(b, 0, 255); - glColor4ub(r, g, b, cp[3]); + a = alphaoffset + (int) cp[3]; + CLAMP(a, 0, 255); + + glColor4ub(r, g, b, a); } -void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset) + +void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset, unsigned char col[4]) { int r, g, b, a; const unsigned char *cp; @@ -1304,7 +1339,11 @@ void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset) CLAMP(b, 0, 255); a = alphaoffset + (int) cp[3]; CLAMP(a, 0, 255); - glColor4ub(r, g, b, a); + + col[0] = r; + col[1] = g; + col[2] = b; + col[3] = a; } void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned char col[3]) @@ -1320,6 +1359,19 @@ void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned c col[2] = floorf((1.0f - fac) * cp1[2] + fac * cp2[2]); } +void UI_GetThemeColorBlend3f(int colorid1, int colorid2, float fac, float r_col[3]) +{ + const unsigned char *cp1, *cp2; + + cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1); + cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2); + + CLAMP(fac, 0.0f, 1.0f); + r_col[0] = ((1.0f - fac) * cp1[0] + fac * cp2[0]) / 255.0f; + r_col[1] = ((1.0f - fac) * cp1[1] + fac * cp2[1]) / 255.0f; + r_col[2] = ((1.0f - fac) * cp1[2] + fac * cp2[2]) / 255.0f; +} + /* blend between to theme colors, and set it */ void UI_ThemeColorBlend(int colorid1, int colorid2, float fac) { @@ -1372,6 +1424,12 @@ void UI_ThemeColorBlendShadeAlpha(int colorid1, int colorid2, float fac, int off glColor4ub(r, g, b, a); } +void UI_FontThemeColor(int fontid, int colorid) +{ + unsigned char color[4]; + UI_GetThemeColor4ubv(colorid, color); + BLF_color4ubv(fontid, color); +} /* get individual values, not scaled */ float UI_GetThemeValuef(int colorid) @@ -1470,6 +1528,111 @@ void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3]) col[2] = b; } +void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int offset, unsigned char col[3]) +{ + const unsigned char *cp1, *cp2; + + cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1); + cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2); + + CLAMP(fac, 0.0f, 1.0f); + + float blend[3]; + blend[0] = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]); + blend[1] = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]); + blend[2] = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]); + + F3TOCHAR3(blend, col); +} + +void UI_GetThemeColorShade4ubv(int colorid, int offset, unsigned char col[4]) +{ + int r, g, b; + const unsigned char *cp; + + cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + r = offset + (int) cp[0]; + CLAMP(r, 0, 255); + g = offset + (int) cp[1]; + CLAMP(g, 0, 255); + b = offset + (int) cp[2]; + CLAMP(b, 0, 255); + + col[0] = r; + col[1] = g; + col[2] = b; + col[3] = cp[3]; +} + +void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4]) +{ + int r, g, b, a; + const unsigned char *cp; + + cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + + r = coloffset + (int) cp[0]; + CLAMP(r, 0, 255); + g = coloffset + (int) cp[1]; + CLAMP(g, 0, 255); + b = coloffset + (int) cp[2]; + CLAMP(b, 0, 255); + a = alphaoffset + (int) cp[3]; + CLAMP(b, 0, 255); + + col[0] = ((float)r) / 255.0f; + col[1] = ((float)g) / 255.0f; + col[2] = ((float)b) / 255.0f; + col[3] = ((float)a) / 255.0f; +} + +void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int offset, float col[3]) +{ + int r, g, b; + const unsigned char *cp1, *cp2; + + cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1); + cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2); + + CLAMP(fac, 0.0f, 1.0f); + + r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]); + CLAMP(r, 0, 255); + g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]); + CLAMP(g, 0, 255); + b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]); + CLAMP(b, 0, 255); + + col[0] = ((float)r) / 255.0f; + col[1] = ((float)g) / 255.0f; + col[2] = ((float)b) / 255.0f; +} + +void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4]) +{ + int r, g, b, a; + const unsigned char *cp1, *cp2; + + cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1); + cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2); + + CLAMP(fac, 0.0f, 1.0f); + + r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]); + CLAMP(r, 0, 255); + g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]); + CLAMP(g, 0, 255); + b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]); + CLAMP(b, 0, 255); + a = offset + floorf((1.0f - fac) * cp1[3] + fac * cp2[3]); + CLAMP(a, 0, 255); + + col[0] = ((float)r) / 255.0f; + col[1] = ((float)g) / 255.0f; + col[2] = ((float)b) / 255.0f; + col[3] = ((float)a) / 255.0f; +} + /* get the color, in char pointer */ void UI_GetThemeColor3ubv(int colorid, unsigned char col[3]) { @@ -1658,11 +1821,9 @@ void init_userdef_do_versions(void) U.savetime = 1; // XXX error(STRINGIFY(BLENDER_STARTUP_FILE)" is buggy, please consider removing it.\n"); } - /* transform widget settings */ - if (U.tw_hotspot == 0) { - U.tw_hotspot = 14; - U.tw_size = 25; /* percentage of window size */ - U.tw_handlesize = 16; /* percentage of widget radius */ + if (U.manipulator_size == 0) { + U.manipulator_size = 75; + U.manipulator_flag |= USER_MANIPULATOR_DRAW; } if (U.pad_rot_angle == 0.0f) U.pad_rot_angle = 15.0f; @@ -2500,9 +2661,6 @@ void init_userdef_do_versions(void) if (!USER_VERSION_ATLEAST(269, 9)) { bTheme *btheme; - - U.tw_size = U.tw_size * 5.0f; - /* Action Editor (and NLA Editor) - Keyframe Colors */ /* Graph Editor - larger vertex size defaults */ for (btheme = U.themes.first; btheme; btheme = btheme->next) { @@ -2776,13 +2934,35 @@ void init_userdef_do_versions(void) U.uiflag |= USER_LOCK_CURSOR_ADJUST; } + if (!USER_VERSION_ATLEAST(280, 1)) { + /* interface_widgets.c */ + struct uiWidgetColors wcol_tab = { + {255, 255, 255, 255}, + {83, 83, 83, 255}, + {114, 114, 114, 255}, + {90, 90, 90, 255}, + + {0, 0, 0, 255}, + {0, 0, 0, 255}, + + 0, + 0, 0 + }; + + for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) { + btheme->tui.wcol_tab = wcol_tab; + } + } + /** * Include next version bump. * * (keep this block even if it becomes empty). */ - { - + if (((bTheme *)U.themes.first)->tui.manipulator_hi[3] == 0) { + for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) { + ui_theme_space_init_manipulator_colors(btheme); + } } if (U.pixelsize == 0.0f) @@ -2791,11 +2971,8 @@ void init_userdef_do_versions(void) if (U.image_draw_method == 0) U.image_draw_method = IMAGE_DRAW_METHOD_2DTEXTURE; - // keep the following until the new audaspace is default to be built with -#ifdef WITH_SYSTEM_AUDASPACE // we default to the first audio device U.audiodevice = 0; -#endif /* funny name, but it is GE stuff, moves userdef stuff to engine */ // XXX space_set_commmandline_options(); diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index 38432395a17..a94ef0d1d5b 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -49,11 +49,11 @@ #include "BKE_screen.h" #include "BKE_global.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" #include "WM_api.h" -#include "BIF_gl.h" - #include "BLF_api.h" #include "ED_screen.h" @@ -1100,9 +1100,6 @@ void UI_view2d_view_ortho(View2D *v2d) /* set matrix on all appropriate axes */ wmOrtho2(curmasked.xmin, curmasked.xmax, curmasked.ymin, curmasked.ymax); - - /* XXX is this necessary? */ - glLoadIdentity(); } /** @@ -1130,9 +1127,6 @@ void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, const bool xaxis) wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, ar->winy - yofs); else wmOrtho2(-xofs, ar->winx - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs); - - /* XXX is this necessary? */ - glLoadIdentity(); } @@ -1144,7 +1138,7 @@ void UI_view2d_view_restore(const bContext *C) int height = BLI_rcti_size_y(&ar->winrct) + 1; wmOrtho2(0.0f, (float)width, 0.0f, (float)height); - glLoadIdentity(); + gpuLoadIdentity(); // ED_region_pixelspace(CTX_wm_region(C)); } @@ -1298,12 +1292,45 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) { float vec1[2], vec2[2]; int a, step; + int vertical_minor_step = (BLI_rcti_size_x(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC), + horizontal_major_step = (BLI_rcti_size_y(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC); + unsigned char grid_line_color[3]; /* check for grid first, as it may not exist */ if (grid == NULL) return; - glBegin(GL_LINES); + /* Count the needed vertices for the gridlines */ + unsigned vertex_count = 0; + if (flag & V2D_VERTICAL_LINES) { + /* vertical lines */ + vertex_count += 2 * vertical_minor_step; /* minor gridlines */ + vertex_count += 2 * (vertical_minor_step + 2); /* major gridlines */ + } + if (flag & V2D_HORIZONTAL_LINES) { + /* horizontal lines */ + vertex_count += 2 * (horizontal_major_step + 1); /* major gridlines */ + + /* fine lines */ + if (flag & V2D_HORIZONTAL_FINELINES) + vertex_count += 2 * (horizontal_major_step + 1); + } + /* axes */ + if (flag & V2D_HORIZONTAL_AXIS) + vertex_count += 2; + if (flag & V2D_VERTICAL_AXIS) + vertex_count += 2; + + /* If there is nothing to render, exit early */ + if (vertex_count == 0) + return; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBegin(GWN_PRIM_LINES, vertex_count); /* vertical lines */ if (flag & V2D_VERTICAL_LINES) { @@ -1313,24 +1340,31 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) vec2[1] = v2d->cur.ymax; /* minor gridlines */ - step = (BLI_rcti_size_x(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC); - UI_ThemeColor(TH_GRID); - - for (a = 0; a < step; a++) { - glVertex2fv(vec1); - glVertex2fv(vec2); - - vec2[0] = vec1[0] += grid->dx; + step = vertical_minor_step; + if (step != 0) { + UI_GetThemeColor3ubv(TH_GRID, grid_line_color); + + for (a = 0; a < step; a++) { + immSkipAttrib(color); + immVertex2fv(pos, vec1); + immAttrib3ubv(color, grid_line_color); + immVertex2fv(pos, vec2); + + vec2[0] = vec1[0] += grid->dx; + } } /* major gridlines */ vec2[0] = vec1[0] -= 0.5f * grid->dx; - UI_ThemeColorShade(TH_GRID, 16); + + UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color); step++; for (a = 0; a <= step; a++) { - glVertex2fv(vec1); - glVertex2fv(vec2); + immSkipAttrib(color); + immVertex2fv(pos, vec1); + immAttrib3ubv(color, grid_line_color); + immVertex2fv(pos, vec2); vec2[0] = vec1[0] -= grid->dx; } @@ -1343,12 +1377,15 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) vec1[0] = grid->startx; vec2[0] = v2d->cur.xmax; - step = (BLI_rcti_size_y(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC); - - UI_ThemeColor(TH_GRID); + step = horizontal_major_step; + + UI_GetThemeColor3ubv(TH_GRID, grid_line_color); + for (a = 0; a <= step; a++) { - glVertex2fv(vec1); - glVertex2fv(vec2); + immSkipAttrib(color); + immVertex2fv(pos, vec1); + immAttrib3ubv(color, grid_line_color); + immVertex2fv(pos, vec2); vec2[1] = vec1[1] += grid->dy; } @@ -1358,10 +1395,12 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) step++; if (flag & V2D_HORIZONTAL_FINELINES) { - UI_ThemeColorShade(TH_GRID, 16); + UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color); for (a = 0; a < step; a++) { - glVertex2fv(vec1); - glVertex2fv(vec2); + immSkipAttrib(color); + immVertex2fv(pos, vec1); + immAttrib3ubv(color, grid_line_color); + immVertex2fv(pos, vec2); vec2[1] = vec1[1] -= grid->dy; } @@ -1369,7 +1408,7 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) } /* Axes are drawn as darker lines */ - UI_ThemeColorShade(TH_GRID, -50); + UI_GetThemeColorShade3ubv(TH_GRID, -50, grid_line_color); /* horizontal axis */ if (flag & V2D_HORIZONTAL_AXIS) { @@ -1377,8 +1416,10 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) vec2[0] = v2d->cur.xmax; vec1[1] = vec2[1] = 0.0f; - glVertex2fv(vec1); - glVertex2fv(vec2); + immSkipAttrib(color); + immVertex2fv(pos, vec1); + immAttrib3ubv(color, grid_line_color); + immVertex2fv(pos, vec2); } /* vertical axis */ @@ -1387,91 +1428,157 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) vec2[1] = v2d->cur.ymax; vec1[0] = vec2[0] = 0.0f; - glVertex2fv(vec1); - glVertex2fv(vec2); + immSkipAttrib(color); + immVertex2fv(pos, vec1); + immAttrib3ubv(color, grid_line_color); + immVertex2fv(pos, vec2); } - glEnd(); + immEnd(); + immUnbindProgram(); } /* Draw a constant grid in given 2d-region */ void UI_view2d_constant_grid_draw(View2D *v2d, float step) { - float start; - - UI_ThemeColorShade(TH_BACK, -10); + float start_x, start_y; + int count_x, count_y; - start = v2d->cur.xmin - (float)fmod(v2d->cur.xmin, step); + start_x = v2d->cur.xmin; + if (start_x < 0.0) + start_x += -(float)fmod(v2d->cur.xmin, step); + else + start_x += (step - (float)fmod(v2d->cur.xmin, step)); + + if (start_x > v2d->cur.xmax) + count_x = 0; + else + count_x = (v2d->cur.xmax - start_x) / step + 1; + + start_y = v2d->cur.ymin; + if (start_y < 0.0) + start_y += -(float)fmod(v2d->cur.ymin, step); + else + start_y += (step - (float)fabs(fmod(v2d->cur.ymin, step))); + + if (start_y > v2d->cur.ymax) + count_y = 0; + else + count_y = (v2d->cur.ymax - start_y) / step + 1; - glBegin(GL_LINES); - for (; start < v2d->cur.xmax; start += step) { - glVertex2f(start, v2d->cur.ymin); - glVertex2f(start, v2d->cur.ymax); - } + if (count_x > 0 || count_y > 0) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + float theme_color[3]; - start = v2d->cur.ymin - (float)fmod(v2d->cur.ymin, step); - for (; start < v2d->cur.ymax; start += step) { - glVertex2f(v2d->cur.xmin, start); - glVertex2f(v2d->cur.xmax, start); - } + UI_GetThemeColorShade3fv(TH_BACK, -10, theme_color); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBegin(GWN_PRIM_LINES, count_x * 2 + count_y * 2 + 4); + + immAttrib3fv(color, theme_color); + for (int i = 0; i < count_x ; start_x += step, i++) { + immVertex2f(pos, start_x, v2d->cur.ymin); + immVertex2f(pos, start_x, v2d->cur.ymax); + } + + for (int i = 0; i < count_y; start_y += step, i++) { + immVertex2f(pos, v2d->cur.xmin, start_y); + immVertex2f(pos, v2d->cur.xmax, start_y); + } - /* X and Y axis */ - UI_ThemeColorShade(TH_BACK, -18); - glVertex2f(0.0f, v2d->cur.ymin); - glVertex2f(0.0f, v2d->cur.ymax); - glVertex2f(v2d->cur.xmin, 0.0f); - glVertex2f(v2d->cur.xmax, 0.0f); + /* X and Y axis */ + UI_GetThemeColorShade3fv(TH_BACK, -18, theme_color); + + immAttrib3fv(color, theme_color); + immVertex2f(pos, 0.0f, v2d->cur.ymin); + immVertex2f(pos, 0.0f, v2d->cur.ymax); + immVertex2f(pos, v2d->cur.xmin, 0.0f); + immVertex2f(pos, v2d->cur.xmax, 0.0f); - glEnd(); + immEnd(); + immUnbindProgram(); + } } /* Draw a multi-level grid in given 2d-region */ void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_size, int totlevels) { + /* Exit if there is nothing to draw */ + if (totlevels == 0) + return; + int offset = -10; float lstep = step; - int level; + unsigned char grid_line_color[3]; + + /* Make an estimate of at least how many vertices will be needed */ + unsigned vertex_count = 4; + vertex_count += 2 * ((int)((v2d->cur.xmax - v2d->cur.xmin) / lstep) + 1); + vertex_count += 2 * ((int)((v2d->cur.ymax - v2d->cur.ymin) / lstep) + 1); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); glLineWidth(1.0f); - for (level = 0; level < totlevels; ++level) { - int i; - float start; - - UI_ThemeColorShade(colorid, offset); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBeginAtMost(GWN_PRIM_LINES, vertex_count); + + for (int level = 0; level < totlevels; ++level) { + UI_GetThemeColorShade3ubv(colorid, offset, grid_line_color); - i = (v2d->cur.xmin >= 0.0f ? -(int)(-v2d->cur.xmin / lstep) : (int)(v2d->cur.xmin / lstep)); - start = i * lstep; + int i = (int)(v2d->cur.xmin / lstep); + if (v2d->cur.xmin > 0.0f) + i++; + float start = i * lstep; - glBegin(GL_LINES); for (; start < v2d->cur.xmax; start += lstep, ++i) { if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) continue; - glVertex2f(start, v2d->cur.ymin); - glVertex2f(start, v2d->cur.ymax); + + immSkipAttrib(color); + immVertex2f(pos, start, v2d->cur.ymin); + immAttrib3ubv(color, grid_line_color); + immVertex2f(pos, start, v2d->cur.ymax); } - i = (v2d->cur.ymin >= 0.0f ? -(int)(-v2d->cur.ymin / lstep) : (int)(v2d->cur.ymin / lstep)); + i = (int)(v2d->cur.ymin / lstep); + if (v2d->cur.ymin > 0.0f) + i++; start = i * lstep; for (; start < v2d->cur.ymax; start += lstep, ++i) { if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) continue; - glVertex2f(v2d->cur.xmin, start); - glVertex2f(v2d->cur.xmax, start); + + immSkipAttrib(color); + immVertex2f(pos, v2d->cur.xmin, start); + immAttrib3ubv(color, grid_line_color); + immVertex2f(pos, v2d->cur.xmax, start); } - /* X and Y axis */ - UI_ThemeColorShade(colorid, offset - 8); - glVertex2f(0.0f, v2d->cur.ymin); - glVertex2f(0.0f, v2d->cur.ymax); - glVertex2f(v2d->cur.xmin, 0.0f); - glVertex2f(v2d->cur.xmax, 0.0f); - - glEnd(); - lstep *= level_size; offset -= 6; } + + /* X and Y axis */ + UI_GetThemeColorShade3ubv(colorid, -18 + ((totlevels - 1) * -6), grid_line_color); + + immSkipAttrib(color); + immVertex2f(pos, 0.0f, v2d->cur.ymin); + immAttrib3ubv(color, grid_line_color); + immVertex2f(pos, 0.0f, v2d->cur.ymax); + + immSkipAttrib(color); + immVertex2f(pos, v2d->cur.xmin, 0.0f); + immAttrib3ubv(color, grid_line_color); + immVertex2f(pos, v2d->cur.xmax, 0.0f); + + immEnd(); + immUnbindProgram(); } /* the price we pay for not exposting structs :( */ @@ -1693,6 +1800,10 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v Scene *scene = CTX_data_scene(C); rcti vert, hor; int scroll = view2d_scroll_mapped(v2d->scroll); + unsigned char scrollers_back_color[4]; + + /* Color for scrollbar backs */ + UI_GetThemeColor4ubv(TH_BACK, scrollers_back_color); /* make copies of rects for less typing */ vert = vs->vert; @@ -1704,7 +1815,6 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v uiWidgetColors wcol = btheme->tui.wcol_scroll; rcti slider; int state; - unsigned char col[4]; slider.xmin = vs->hor_min; slider.xmax = vs->hor_max; @@ -1728,16 +1838,23 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v } /* clean rect behind slider, but not with transparent background */ - UI_GetThemeColor4ubv(TH_BACK, col); - if (col[3] == 255) { - glColor3ub(col[0], col[1], col[2]); - glRecti(v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax); + if (scrollers_back_color[3] == 255) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3ubv(scrollers_back_color); + immRecti(pos, v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax); + + immUnbindProgram(); } UI_draw_widget_scroll(&wcol, &hor, &slider, state); /* scale indicators */ if ((scroll & V2D_SCROLL_SCALE_HORIZONTAL) && (vs->grid)) { + const int font_id = BLF_default(); View2DGrid *grid = vs->grid; float fac, dfac, fac2, val; @@ -1752,7 +1869,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v dfac = dfac * BLI_rcti_size_x(&hor); /* set starting value, and text color */ - UI_ThemeColor(TH_TEXT); + UI_FontThemeColor(font_id, TH_TEXT); val = grid->startx; /* if we're clamping to whole numbers only, make sure entries won't be repeated */ @@ -1764,7 +1881,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v } if (vs->xunits == V2D_UNIT_FRAMES) grid->powerx = 1; - + /* draw numbers in the appropriate range */ if (dfac > 0.0f) { float h = 0.1f * UI_UNIT_Y + (float)(hor.ymin); @@ -1805,7 +1922,6 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v uiWidgetColors wcol = btheme->tui.wcol_scroll; rcti slider; int state; - unsigned char col[4]; slider.xmin = vert.xmin; slider.xmax = vert.xmax; @@ -1829,10 +1945,16 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v } /* clean rect behind slider, but not with transparent background */ - UI_GetThemeColor4ubv(TH_BACK, col); - if (col[3] == 255) { - glColor3ub(col[0], col[1], col[2]); - glRecti(v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax); + if (scrollers_back_color[3] == 255) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3ubv(scrollers_back_color); + immRecti(pos, v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax); + + immUnbindProgram(); } UI_draw_widget_scroll(&wcol, &vert, &slider, state); @@ -1856,7 +1978,8 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v dfac = dfac * BLI_rcti_size_y(&vert); /* set starting value, and text color */ - UI_ThemeColor(TH_TEXT); + const int font_id = BLF_default(); + UI_FontThemeColor(font_id, TH_TEXT); val = grid->starty; /* if vertical clamping (to whole numbers) is used (i.e. in Sequencer), apply correction */ @@ -1865,9 +1988,8 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v /* draw vertical steps */ if (dfac > 0.0f) { - - BLF_rotation_default(M_PI_2); - BLF_enable_default(BLF_ROTATION); + BLF_rotation(font_id, M_PI_2); + BLF_enable(font_id, BLF_ROTATION); for (; fac < vert.ymax - 10; fac += dfac, val += grid->dy) { @@ -1878,7 +2000,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v scroll_printstr(scene, (float)(vert.xmax) - 2.0f, fac, val, grid->powery, vs->yunits, 'v'); } - BLF_disable_default(BLF_ROTATION); + BLF_disable(font_id, BLF_ROTATION); } } } @@ -2400,7 +2522,8 @@ void UI_view2d_text_cache_draw(ARegion *ar) int col_pack_prev = 0; /* investigate using BLF_ascender() */ - const float default_height = g_v2d_strings ? BLF_height_default("28", 3) : 0.0f; + const int font_id = BLF_default(); + const float default_height = g_v2d_strings ? BLF_height(font_id, "28", 3) : 0.0f; wmOrtho2_region_pixelspace(ar); @@ -2411,7 +2534,7 @@ void UI_view2d_text_cache_draw(ARegion *ar) if (yofs < 1) yofs = 1; if (col_pack_prev != v2s->col.pack) { - glColor3ubv(v2s->col.ub); + BLF_color3ubv(font_id, v2s->col.ub); col_pack_prev = v2s->col.pack; } @@ -2419,11 +2542,11 @@ void UI_view2d_text_cache_draw(ARegion *ar) BLF_draw_default((float)(v2s->mval[0] + xofs), (float)(v2s->mval[1] + yofs), 0.0, v2s->str, BLF_DRAW_STR_DUMMY_MAX); else { - BLF_clipping_default(v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4); - BLF_enable_default(BLF_CLIPPING); + BLF_enable(font_id, BLF_CLIPPING); + BLF_clipping(font_id, v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4); BLF_draw_default(v2s->rect.xmin + xofs, v2s->rect.ymin + yofs, 0.0f, v2s->str, BLF_DRAW_STR_DUMMY_MAX); - BLF_disable_default(BLF_CLIPPING); + BLF_disable(font_id, BLF_CLIPPING); } } g_v2d_strings = NULL; @@ -2432,11 +2555,6 @@ void UI_view2d_text_cache_draw(ARegion *ar) BLI_memarena_free(g_v2d_strings_arena); g_v2d_strings_arena = NULL; } - - // glMatrixMode(GL_PROJECTION); - // glPopMatrix(); - // glMatrixMode(GL_MODELVIEW); - // glPopMatrix(); } diff --git a/source/blender/editors/io/CMakeLists.txt b/source/blender/editors/io/CMakeLists.txt index b3bbce939a5..4d3f106a5d6 100644 --- a/source/blender/editors/io/CMakeLists.txt +++ b/source/blender/editors/io/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blenlib ../../blentranslation ../../bmesh + ../../depsgraph ../../makesdna ../../makesrna ../../windowmanager diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index 39065606201..9e79ca5b0e3 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -56,6 +56,8 @@ #include "io_collada.h" +#include "DEG_depsgraph.h" + static int wm_collada_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (!RNA_struct_property_is_set(op->ptr, "filepath")) { @@ -78,6 +80,7 @@ static int wm_collada_export_invoke(bContext *C, wmOperator *op, const wmEvent * /* function used for WM_OT_save_mainfile too */ static int wm_collada_export_exec(bContext *C, wmOperator *op) { + EvaluationContext eval_ctx; char filepath[FILE_MAX]; int apply_modifiers; int export_mesh_type; @@ -87,7 +90,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int include_shapekeys; int deform_bones_only; - int export_texture_type; + int include_material_textures; int use_texture_copies; int active_uv_only; @@ -103,6 +106,8 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int export_count; + CTX_data_eval_ctx(C, &eval_ctx); + if (!RNA_struct_property_is_set(op->ptr, "filepath")) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; @@ -138,7 +143,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys"); deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only"); - export_texture_type = RNA_enum_get(op->ptr, "export_texture_type_selection"); + include_material_textures = RNA_boolean_get(op->ptr, "include_material_textures"); use_texture_copies = RNA_boolean_get(op->ptr, "use_texture_copies"); active_uv_only = RNA_boolean_get(op->ptr, "active_uv_only"); @@ -156,7 +161,9 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) ED_object_editmode_load(CTX_data_edit_object(C)); - export_count = collada_export(CTX_data_scene(C), + export_count = collada_export(&eval_ctx, + CTX_data_scene(C), + CTX_data_scene_layer(C), filepath, apply_modifiers, export_mesh_type, @@ -167,7 +174,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) deform_bones_only, active_uv_only, - export_texture_type, + include_material_textures, use_texture_copies, triangulate, @@ -238,7 +245,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) uiItemR(row, imfptr, "active_uv_only", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); - uiItemR(row, imfptr, "export_texture_type_selection", 0, "", ICON_NONE); + uiItemR(row, imfptr, "include_material_textures", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "use_texture_copies", 1, NULL, ICON_NONE); @@ -315,15 +322,9 @@ void WM_OT_collada_export(wmOperatorType *ot) }; static const EnumPropertyItem prop_bc_export_transformation_type[] = { - { BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations" }, - { BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations" }, - { 0, NULL, 0, NULL, NULL } - }; - - static const EnumPropertyItem prop_bc_export_texture_type[] = { - { BC_TEXTURE_TYPE_MAT, "mat", 0, "Materials", "Export Materials" }, - { BC_TEXTURE_TYPE_UV, "uv", 0, "UV Textures", "Export UV Textures (Face textures) as materials" }, - { 0, NULL, 0, NULL, NULL } + {BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations"}, + {BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations"}, + {0, NULL, 0, NULL, NULL} }; ot->name = "Export COLLADA"; @@ -368,9 +369,13 @@ void WM_OT_collada_export(wmOperatorType *ot) RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only", "Only export deforming bones with armatures"); + RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map", "Export only the selected UV Map"); + RNA_def_boolean(func, "include_material_textures", 0, "Include Material Textures", + "Export textures assigned to the object Materials"); + RNA_def_boolean(func, "use_texture_copies", 1, "Copy", "Copy textures to same folder where the .dae file is exported"); @@ -387,20 +392,11 @@ void WM_OT_collada_export(wmOperatorType *ot) RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name"); - RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX, - "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX); + "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX); RNA_def_enum(func, "export_transformation_type_selection", prop_bc_export_transformation_type, 0, - "Transform", "Transformation type for translation, scale and rotation"); - - - RNA_def_int(func, "export_texture_type", 0, INT_MIN, INT_MAX, - "Texture Type", "Type for exported Textures (UV or MAT)", INT_MIN, INT_MAX); - - RNA_def_enum(func, "export_texture_type_selection", prop_bc_export_texture_type, 0, - "Texture Type", "Type for exported Textures (UV or MAT)"); - + "Transform", "Transformation type for translation, scale and rotation"); RNA_def_boolean(func, "open_sim", 0, "Export to SL/OpenSim", "Compatibility mode for SL, OpenSim and other compatible online worlds"); diff --git a/source/blender/editors/manipulator_library/CMakeLists.txt b/source/blender/editors/manipulator_library/CMakeLists.txt new file mode 100644 index 00000000000..9f7df8c6425 --- /dev/null +++ b/source/blender/editors/manipulator_library/CMakeLists.txt @@ -0,0 +1,59 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + ../include + ../../blenkernel + ../../blenlib + ../../blentranslation + ../../bmesh + ../../depsgraph + ../../gpu + ../../makesdna + ../../makesrna + ../../windowmanager + ../../../../intern/guardedalloc + ../../../../intern/eigen + ../../../../intern/glew-mx +) + +set(INC_SYS + ${GLEW_INCLUDE_PATH} +) + +set(SRC + manipulator_draw_utils.c + manipulator_geometry.h + manipulator_library_intern.h + manipulator_library_presets.c + manipulator_library_utils.c + geometry/geom_arrow_manipulator.c + geometry/geom_cube_manipulator.c + geometry/geom_dial_manipulator.c + manipulator_types/arrow2d_manipulator.c + manipulator_types/arrow3d_manipulator.c + manipulator_types/cage2d_manipulator.c + manipulator_types/cage3d_manipulator.c + manipulator_types/dial3d_manipulator.c + manipulator_types/grab3d_manipulator.c + manipulator_types/primitive3d_manipulator.c +) + +add_definitions(${GL_DEFINITIONS}) + +blender_add_lib(bf_editor_manipulator_library "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/manipulator_library/geometry/geom_arrow_manipulator.c b/source/blender/editors/manipulator_library/geometry/geom_arrow_manipulator.c new file mode 100644 index 00000000000..34f7d73589c --- /dev/null +++ b/source/blender/editors/manipulator_library/geometry/geom_arrow_manipulator.c @@ -0,0 +1,141 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file geom_arrow_manipulator.c + * \ingroup wm + */ + +#include "../manipulator_geometry.h" + +static float verts[][3] = { + {-0.000000, 0.012320, 0.000000}, + {-0.000000, 0.012320, 0.974306}, + {0.008711, 0.008711, 0.000000}, + {0.008711, 0.008711, 0.974306}, + {0.012320, -0.000000, 0.000000}, + {0.012320, -0.000000, 0.974306}, + {0.008711, -0.008711, 0.000000}, + {0.008711, -0.008711, 0.974306}, + {-0.000000, -0.012320, 0.000000}, + {-0.000000, -0.012320, 0.974306}, + {-0.008711, -0.008711, 0.000000}, + {-0.008711, -0.008711, 0.974306}, + {-0.012320, 0.000000, 0.000000}, + {-0.012320, 0.000000, 0.974306}, + {-0.008711, 0.008711, 0.000000}, + {-0.008711, 0.008711, 0.974306}, + {0.000000, 0.072555, 0.974306}, + {0.051304, 0.051304, 0.974306}, + {0.072555, -0.000000, 0.974306}, + {0.051304, -0.051304, 0.974306}, + {-0.000000, -0.072555, 0.974306}, + {-0.051304, -0.051304, 0.974306}, + {-0.072555, 0.000000, 0.974306}, + {-0.051304, 0.051304, 0.974306}, + {0.000000, -0.000000, 1.268098}, +}; + +static float normals[][3] = { + {0.000000, 0.776360, -0.630238}, + {0.000000, 0.594348, -0.804163}, + {0.548967, 0.548967, -0.630238}, + {0.420270, 0.420270, -0.804163}, + {0.776360, 0.000000, -0.630238}, + {0.594378, 0.000000, -0.804163}, + {0.548967, -0.548967, -0.630238}, + {0.420270, -0.420270, -0.804163}, + {0.000000, -0.776360, -0.630238}, + {0.000000, -0.594378, -0.804163}, + {-0.548967, -0.548967, -0.630238}, + {-0.420270, -0.420270, -0.804163}, + {-0.776360, 0.000000, -0.630238}, + {-0.594378, 0.000000, -0.804163}, + {-0.548967, 0.548967, -0.630238}, + {-0.420270, 0.420270, -0.804163}, + {0.000000, 0.843226, -0.537492}, + {0.596271, 0.596271, -0.537492}, + {0.843226, 0.000000, -0.537492}, + {0.596271, -0.596271, -0.537492}, + {0.000000, -0.843226, -0.537492}, + {-0.596271, -0.596271, -0.537492}, + {-0.843226, 0.000000, -0.537492}, + {-0.596271, 0.596271, -0.537492}, + {0.000000, 0.000000, 1.000000}, +}; + +static unsigned short indices[] = { + 1, 3, 2, + 3, 5, 4, + 5, 7, 6, + 7, 9, 8, + 9, 11, 10, + 11, 13, 12, + 5, 18, 19, + 15, 1, 0, + 13, 15, 14, + 6, 10, 14, + 11, 21, 22, + 7, 19, 20, + 13, 22, 23, + 3, 17, 18, + 9, 20, 21, + 15, 23, 16, + 1, 16, 17, + 23, 22, 24, + 21, 20, 24, + 19, 18, 24, + 17, 16, 24, + 16, 23, 24, + 22, 21, 24, + 20, 19, 24, + 18, 17, 24, + 0, 1, 2, + 2, 3, 4, + 4, 5, 6, + 6, 7, 8, + 8, 9, 10, + 10, 11, 12, + 7, 5, 19, + 14, 15, 0, + 12, 13, 14, + 14, 0, 2, + 2, 4, 6, + 6, 8, 10, + 10, 12, 14, + 14, 2, 6, + 13, 11, 22, + 9, 7, 20, + 15, 13, 23, + 5, 3, 18, + 11, 9, 21, + 1, 15, 16, + 3, 1, 17, +}; + +ManipulatorGeomInfo wm_manipulator_geom_data_arrow = { + .nverts = 25, + .ntris = 46, + .verts = verts, + .normals = normals, + .indices = indices, +}; diff --git a/source/blender/editors/manipulator_library/geometry/geom_cube_manipulator.c b/source/blender/editors/manipulator_library/geometry/geom_cube_manipulator.c new file mode 100644 index 00000000000..cee8e1e22ee --- /dev/null +++ b/source/blender/editors/manipulator_library/geometry/geom_cube_manipulator.c @@ -0,0 +1,75 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 Blender Foundation. + * All rights reserved. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file geom_cube_manipulator.c + * \ingroup wm + */ + +#include "../manipulator_geometry.h" + +static const float verts[][3] = { + {1.000000, 1.000000, -1.000000}, + {1.000000, -1.000000, -1.000000}, + {-1.000000, -1.000000, -1.000000}, + {-1.000000, 1.000000, -1.000000}, + {1.000000, 1.000000, 1.000000}, + {0.999999, -1.000001, 1.000000}, + {-1.000000, -1.000000, 1.000000}, + {-1.000000, 1.000000, 1.000000}, +}; + +static const float normals[][3] = { + {0.577349, 0.577349, -0.577349}, + {0.577349, -0.577349, -0.577349}, + {-0.577349, -0.577349, -0.577349}, + {-0.577349, 0.577349, -0.577349}, + {0.577349, 0.577349, 0.577349}, + {0.577349, -0.577349, 0.577349}, + {-0.577349, -0.577349, 0.577349}, + {-0.577349, 0.577349, 0.577349}, +}; + +static const unsigned short indices[] = { + 1, 2, 3, + 7, 6, 5, + 4, 5, 1, + 5, 6, 2, + 2, 6, 7, + 0, 3, 7, + 0, 1, 3, + 4, 7, 5, + 0, 4, 1, + 1, 5, 2, + 3, 2, 7, + 4, 0, 7, +}; + +ManipulatorGeomInfo wm_manipulator_geom_data_cube = { + .nverts = 8, + .ntris = 12, + .verts = verts, + .normals = normals, + .indices = indices, +}; diff --git a/source/blender/editors/manipulator_library/geometry/geom_dial_manipulator.c b/source/blender/editors/manipulator_library/geometry/geom_dial_manipulator.c new file mode 100644 index 00000000000..811fc872a81 --- /dev/null +++ b/source/blender/editors/manipulator_library/geometry/geom_dial_manipulator.c @@ -0,0 +1,813 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file geom_dial_manipulator.c + * \ingroup wm + */ + +#include "../manipulator_geometry.h" + +static const float verts[][3] = { + {1.034000, 0.000000, 0.000000}, + {1.017000, 0.000000, 0.029445}, + {0.983000, 0.000000, 0.029445}, + {0.966000, 0.000000, 0.000000}, + {0.983000, 0.000000, -0.029445}, + {1.017000, 0.000000, -0.029445}, + {1.014132, 0.201723, 0.000000}, + {0.997459, 0.198407, 0.029445}, + {0.964112, 0.191774, 0.029445}, + {0.947439, 0.188457, 0.000000}, + {0.964112, 0.191774, -0.029445}, + {0.997459, 0.198407, -0.029445}, + {0.955292, 0.395695, 0.000000}, + {0.939586, 0.389189, 0.029445}, + {0.908174, 0.376178, 0.029445}, + {0.892468, 0.369672, 0.000000}, + {0.908174, 0.376178, -0.029445}, + {0.939586, 0.389189, -0.029445}, + {0.859740, 0.574460, 0.000000}, + {0.845605, 0.565015, 0.029445}, + {0.817335, 0.546126, 0.029445}, + {0.803200, 0.536681, 0.000000}, + {0.817335, 0.546126, -0.029445}, + {0.845605, 0.565015, -0.029445}, + {0.731148, 0.731148, 0.000000}, + {0.719128, 0.719128, 0.029445}, + {0.695086, 0.695086, 0.029445}, + {0.683065, 0.683065, 0.000000}, + {0.695086, 0.695086, -0.029445}, + {0.719128, 0.719128, -0.029445}, + {0.574460, 0.859740, 0.000000}, + {0.565015, 0.845605, 0.029445}, + {0.546125, 0.817335, 0.029445}, + {0.536681, 0.803200, 0.000000}, + {0.546125, 0.817335, -0.029445}, + {0.565015, 0.845605, -0.029445}, + {0.395695, 0.955291, 0.000000}, + {0.389189, 0.939585, 0.029445}, + {0.376178, 0.908173, 0.029445}, + {0.369672, 0.892467, 0.000000}, + {0.376178, 0.908173, -0.029445}, + {0.389189, 0.939585, -0.029445}, + {0.201724, 1.014132, 0.000000}, + {0.198407, 0.997459, 0.029445}, + {0.191774, 0.964112, 0.029445}, + {0.188457, 0.947439, 0.000000}, + {0.191774, 0.964112, -0.029445}, + {0.198407, 0.997459, -0.029445}, + {0.000000, 1.034000, 0.000000}, + {0.000000, 1.017000, 0.029445}, + {0.000000, 0.983000, 0.029445}, + {0.000000, 0.966000, 0.000000}, + {0.000000, 0.983000, -0.029445}, + {0.000000, 1.017000, -0.029445}, + {-0.201723, 1.014132, 0.000000}, + {-0.198407, 0.997459, 0.029445}, + {-0.191774, 0.964112, 0.029445}, + {-0.188457, 0.947439, 0.000000}, + {-0.191774, 0.964112, -0.029445}, + {-0.198407, 0.997459, -0.029445}, + {-0.395695, 0.955291, 0.000000}, + {-0.389189, 0.939585, 0.029445}, + {-0.376178, 0.908174, 0.029445}, + {-0.369672, 0.892468, 0.000000}, + {-0.376178, 0.908174, -0.029445}, + {-0.389189, 0.939585, -0.029445}, + {-0.574459, 0.859740, 0.000000}, + {-0.565015, 0.845605, 0.029445}, + {-0.546125, 0.817335, 0.029445}, + {-0.536681, 0.803200, 0.000000}, + {-0.546125, 0.817335, -0.029445}, + {-0.565015, 0.845605, -0.029445}, + {-0.731149, 0.731148, 0.000000}, + {-0.719128, 0.719127, 0.029445}, + {-0.695086, 0.695086, 0.029445}, + {-0.683065, 0.683065, 0.000000}, + {-0.695086, 0.695086, -0.029445}, + {-0.719128, 0.719127, -0.029445}, + {-0.859740, 0.574460, 0.000000}, + {-0.845604, 0.565015, 0.029445}, + {-0.817335, 0.546126, 0.029445}, + {-0.803200, 0.536681, 0.000000}, + {-0.817335, 0.546126, -0.029445}, + {-0.845604, 0.565015, -0.029445}, + {-0.955291, 0.395695, 0.000000}, + {-0.939585, 0.389189, 0.029445}, + {-0.908173, 0.376178, 0.029445}, + {-0.892468, 0.369672, 0.000000}, + {-0.908173, 0.376178, -0.029445}, + {-0.939585, 0.389189, -0.029445}, + {-1.014132, 0.201723, 0.000000}, + {-0.997459, 0.198407, 0.029445}, + {-0.964112, 0.191774, 0.029445}, + {-0.947439, 0.188457, 0.000000}, + {-0.964112, 0.191774, -0.029445}, + {-0.997459, 0.198407, -0.029445}, + {-1.034000, 0.000000, 0.000000}, + {-1.017000, 0.000000, 0.029445}, + {-0.983000, 0.000000, 0.029445}, + {-0.966000, 0.000000, 0.000000}, + {-0.983000, 0.000000, -0.029445}, + {-1.017000, 0.000000, -0.029445}, + {-1.014132, -0.201723, 0.000000}, + {-0.997459, -0.198407, 0.029445}, + {-0.964112, -0.191774, 0.029445}, + {-0.947439, -0.188457, 0.000000}, + {-0.964112, -0.191774, -0.029445}, + {-0.997459, -0.198407, -0.029445}, + {-0.955292, -0.395694, 0.000000}, + {-0.939586, -0.389189, 0.029445}, + {-0.908174, -0.376177, 0.029445}, + {-0.892468, -0.369672, 0.000000}, + {-0.908174, -0.376177, -0.029445}, + {-0.939586, -0.389189, -0.029445}, + {-0.859740, -0.574460, 0.000000}, + {-0.845604, -0.565015, 0.029445}, + {-0.817335, -0.546126, 0.029445}, + {-0.803200, -0.536681, 0.000000}, + {-0.817335, -0.546126, -0.029445}, + {-0.845604, -0.565015, -0.029445}, + {-0.731149, -0.731148, 0.000000}, + {-0.719128, -0.719127, 0.029445}, + {-0.695086, -0.695086, 0.029445}, + {-0.683065, -0.683065, 0.000000}, + {-0.695086, -0.695086, -0.029445}, + {-0.719128, -0.719127, -0.029445}, + {-0.574460, -0.859739, 0.000000}, + {-0.565015, -0.845604, 0.029445}, + {-0.546126, -0.817334, 0.029445}, + {-0.536681, -0.803199, 0.000000}, + {-0.546126, -0.817334, -0.029445}, + {-0.565015, -0.845604, -0.029445}, + {-0.395695, -0.955291, 0.000000}, + {-0.389189, -0.939585, 0.029445}, + {-0.376178, -0.908174, 0.029445}, + {-0.369672, -0.892468, 0.000000}, + {-0.376178, -0.908174, -0.029445}, + {-0.389189, -0.939585, -0.029445}, + {-0.201724, -1.014132, 0.000000}, + {-0.198407, -0.997459, 0.029445}, + {-0.191774, -0.964112, 0.029445}, + {-0.188458, -0.947438, 0.000000}, + {-0.191774, -0.964112, -0.029445}, + {-0.198407, -0.997459, -0.029445}, + {0.000000, -1.034000, 0.000000}, + {0.000000, -1.017000, 0.029445}, + {0.000000, -0.983000, 0.029445}, + {0.000000, -0.966000, 0.000000}, + {0.000000, -0.983000, -0.029445}, + {0.000000, -1.017000, -0.029445}, + {0.201723, -1.014132, 0.000000}, + {0.198407, -0.997459, 0.029445}, + {0.191773, -0.964112, 0.029445}, + {0.188457, -0.947439, 0.000000}, + {0.191773, -0.964112, -0.029445}, + {0.198407, -0.997459, -0.029445}, + {0.395695, -0.955291, 0.000000}, + {0.389189, -0.939585, 0.029445}, + {0.376178, -0.908173, 0.029445}, + {0.369672, -0.892467, 0.000000}, + {0.376178, -0.908173, -0.029445}, + {0.389189, -0.939585, -0.029445}, + {0.574460, -0.859740, 0.000000}, + {0.565015, -0.845605, 0.029445}, + {0.546125, -0.817335, 0.029445}, + {0.536681, -0.803200, 0.000000}, + {0.546125, -0.817335, -0.029445}, + {0.565015, -0.845605, -0.029445}, + {0.731148, -0.731149, 0.000000}, + {0.719127, -0.719128, 0.029445}, + {0.695086, -0.695086, 0.029445}, + {0.683065, -0.683066, 0.000000}, + {0.695086, -0.695086, -0.029445}, + {0.719127, -0.719128, -0.029445}, + {0.859740, -0.574460, 0.000000}, + {0.845605, -0.565015, 0.029445}, + {0.817335, -0.546126, 0.029445}, + {0.803200, -0.536681, 0.000000}, + {0.817335, -0.546126, -0.029445}, + {0.845605, -0.565015, -0.029445}, + {0.955291, -0.395695, 0.000000}, + {0.939585, -0.389189, 0.029445}, + {0.908173, -0.376178, 0.029445}, + {0.892467, -0.369673, 0.000000}, + {0.908173, -0.376178, -0.029445}, + {0.939585, -0.389189, -0.029445}, + {1.014132, -0.201723, 0.000000}, + {0.997459, -0.198407, 0.029445}, + {0.964112, -0.191774, 0.029445}, + {0.947439, -0.188457, 0.000000}, + {0.964112, -0.191774, -0.029445}, + {0.997459, -0.198407, -0.029445}, +}; + +static const float normals[][3] = { + {1.000000, 0.000000, 0.000000}, + {0.522691, 0.000000, 0.852504}, + {-0.475845, 0.000000, 0.879513}, + {-1.000000, 0.000000, 0.000000}, + {-0.475845, 0.000000, -0.879513}, + {0.522691, 0.000000, -0.852504}, + {0.980773, 0.195074, 0.000000}, + {0.512650, 0.101962, 0.852504}, + {-0.466689, -0.092807, 0.879513}, + {-0.980773, -0.195074, 0.000000}, + {-0.466689, -0.092807, -0.879513}, + {0.512650, 0.101962, -0.852504}, + {0.923856, 0.382672, 0.000000}, + {0.482894, 0.200018, 0.852504}, + {-0.439619, -0.182073, 0.879513}, + {-0.923856, -0.382672, 0.000000}, + {-0.439619, -0.182073, -0.879513}, + {0.482894, 0.200018, -0.852504}, + {0.831446, 0.555559, 0.000000}, + {0.434614, 0.290384, 0.852504}, + {-0.395642, -0.264351, 0.879513}, + {-0.831446, -0.555559, 0.000000}, + {-0.395642, -0.264351, -0.879513}, + {0.434614, 0.290384, -0.852504}, + {0.707083, 0.707083, 0.000000}, + {0.369610, 0.369610, 0.852504}, + {-0.336467, -0.336467, 0.879513}, + {-0.707083, -0.707083, 0.000000}, + {-0.336467, -0.336467, -0.879513}, + {0.369610, 0.369610, -0.852504}, + {0.555559, 0.831446, 0.000000}, + {0.290384, 0.434614, 0.852504}, + {-0.264351, -0.395642, 0.879513}, + {-0.555559, -0.831446, 0.000000}, + {-0.264351, -0.395642, -0.879513}, + {0.290384, 0.434614, -0.852504}, + {0.382672, 0.923856, 0.000000}, + {0.200018, 0.482894, 0.852504}, + {-0.182073, -0.439619, 0.879513}, + {-0.382672, -0.923856, 0.000000}, + {-0.182073, -0.439619, -0.879513}, + {0.200018, 0.482894, -0.852504}, + {0.195074, 0.980773, 0.000000}, + {0.101962, 0.512650, 0.852504}, + {-0.092807, -0.466689, 0.879513}, + {-0.195074, -0.980773, 0.000000}, + {-0.092807, -0.466689, -0.879513}, + {0.101962, 0.512650, -0.852504}, + {0.000000, 1.000000, 0.000000}, + {0.000000, 0.522691, 0.852504}, + {0.000000, -0.475845, 0.879513}, + {0.000000, -1.000000, 0.000000}, + {0.000000, -0.475845, -0.879513}, + {0.000000, 0.522691, -0.852504}, + {-0.195074, 0.980773, 0.000000}, + {-0.101962, 0.512650, 0.852504}, + {0.092807, -0.466689, 0.879513}, + {0.195074, -0.980773, 0.000000}, + {0.092807, -0.466689, -0.879513}, + {-0.101962, 0.512650, -0.852504}, + {-0.382672, 0.923856, 0.000000}, + {-0.200018, 0.482894, 0.852504}, + {0.182073, -0.439619, 0.879513}, + {0.382672, -0.923856, 0.000000}, + {0.182073, -0.439619, -0.879513}, + {-0.200018, 0.482894, -0.852504}, + {-0.555559, 0.831446, 0.000000}, + {-0.290384, 0.434614, 0.852504}, + {0.264351, -0.395642, 0.879513}, + {0.555559, -0.831446, 0.000000}, + {0.264351, -0.395642, -0.879513}, + {-0.290384, 0.434614, -0.852504}, + {-0.707083, 0.707083, 0.000000}, + {-0.369610, 0.369610, 0.852504}, + {0.336467, -0.336467, 0.879513}, + {0.707083, -0.707083, 0.000000}, + {0.336467, -0.336467, -0.879513}, + {-0.369610, 0.369610, -0.852504}, + {-0.831446, 0.555559, 0.000000}, + {-0.434614, 0.290384, 0.852504}, + {0.395642, -0.264351, 0.879513}, + {0.831446, -0.555559, 0.000000}, + {0.395642, -0.264351, -0.879513}, + {-0.434614, 0.290384, -0.852504}, + {-0.923856, 0.382672, 0.000000}, + {-0.482894, 0.200018, 0.852504}, + {0.439619, -0.182073, 0.879513}, + {0.923856, -0.382672, 0.000000}, + {0.439619, -0.182073, -0.879513}, + {-0.482894, 0.200018, -0.852504}, + {-0.980773, 0.195074, 0.000000}, + {-0.512650, 0.101962, 0.852504}, + {0.466689, -0.092807, 0.879513}, + {0.980773, -0.195074, 0.000000}, + {0.466689, -0.092807, -0.879513}, + {-0.512650, 0.101962, -0.852504}, + {-1.000000, 0.000000, 0.000000}, + {-0.522691, 0.000000, 0.852504}, + {0.475845, 0.000000, 0.879513}, + {1.000000, 0.000000, 0.000000}, + {0.475845, 0.000000, -0.879513}, + {-0.522691, 0.000000, -0.852504}, + {-0.980773, -0.195074, 0.000000}, + {-0.512650, -0.101962, 0.852504}, + {0.466689, 0.092807, 0.879513}, + {0.980773, 0.195074, 0.000000}, + {0.466689, 0.092807, -0.879513}, + {-0.512650, -0.101962, -0.852504}, + {-0.923856, -0.382672, 0.000000}, + {-0.482894, -0.200018, 0.852504}, + {0.439619, 0.182073, 0.879513}, + {0.923856, 0.382672, 0.000000}, + {0.439619, 0.182073, -0.879513}, + {-0.482894, -0.200018, -0.852504}, + {-0.831446, -0.555559, 0.000000}, + {-0.434614, -0.290384, 0.852504}, + {0.395642, 0.264351, 0.879513}, + {0.831446, 0.555559, 0.000000}, + {0.395642, 0.264351, -0.879513}, + {-0.434614, -0.290384, -0.852504}, + {-0.707083, -0.707083, 0.000000}, + {-0.369610, -0.369610, 0.852504}, + {0.336467, 0.336467, 0.879513}, + {0.707083, 0.707083, 0.000000}, + {0.336467, 0.336467, -0.879513}, + {-0.369610, -0.369610, -0.852504}, + {-0.555559, -0.831446, 0.000000}, + {-0.290384, -0.434614, 0.852504}, + {0.264351, 0.395642, 0.879513}, + {0.555559, 0.831446, 0.000000}, + {0.264351, 0.395642, -0.879513}, + {-0.290384, -0.434614, -0.852504}, + {-0.382672, -0.923856, 0.000000}, + {-0.200018, -0.482894, 0.852504}, + {0.182073, 0.439619, 0.879513}, + {0.382672, 0.923856, 0.000000}, + {0.182073, 0.439619, -0.879513}, + {-0.200018, -0.482894, -0.852504}, + {-0.195074, -0.980773, 0.000000}, + {-0.101962, -0.512650, 0.852504}, + {0.092807, 0.466689, 0.879513}, + {0.195074, 0.980773, 0.000000}, + {0.092807, 0.466689, -0.879513}, + {-0.101962, -0.512650, -0.852504}, + {0.000000, -1.000000, 0.000000}, + {0.000000, -0.522691, 0.852504}, + {0.000000, 0.475845, 0.879513}, + {0.000000, 1.000000, 0.000000}, + {0.000000, 0.475845, -0.879513}, + {0.000000, -0.522691, -0.852504}, + {0.195074, -0.980773, 0.000000}, + {0.101962, -0.512650, 0.852504}, + {-0.092807, 0.466689, 0.879513}, + {-0.195074, 0.980773, 0.000000}, + {-0.092807, 0.466689, -0.879513}, + {0.101962, -0.512650, -0.852504}, + {0.382672, -0.923856, 0.000000}, + {0.200018, -0.482894, 0.852504}, + {-0.182073, 0.439619, 0.879513}, + {-0.382672, 0.923856, 0.000000}, + {-0.182073, 0.439619, -0.879513}, + {0.200018, -0.482894, -0.852504}, + {0.555559, -0.831446, 0.000000}, + {0.290384, -0.434614, 0.852504}, + {-0.264351, 0.395642, 0.879513}, + {-0.555559, 0.831446, 0.000000}, + {-0.264351, 0.395642, -0.879513}, + {0.290384, -0.434614, -0.852504}, + {0.707083, -0.707083, 0.000000}, + {0.369610, -0.369610, 0.852504}, + {-0.336467, 0.336467, 0.879513}, + {-0.707083, 0.707083, 0.000000}, + {-0.336467, 0.336467, -0.879513}, + {0.369610, -0.369610, -0.852504}, + {0.831446, -0.555559, 0.000000}, + {0.434614, -0.290384, 0.852504}, + {-0.395642, 0.264351, 0.879513}, + {-0.831446, 0.555559, 0.000000}, + {-0.395642, 0.264351, -0.879513}, + {0.434614, -0.290384, -0.852504}, + {0.923856, -0.382672, 0.000000}, + {0.482894, -0.200018, 0.852504}, + {-0.439619, 0.182073, 0.879513}, + {-0.923856, 0.382672, 0.000000}, + {-0.439619, 0.182073, -0.879513}, + {0.482894, -0.200018, -0.852504}, + {0.980773, -0.195074, 0.000000}, + {0.512650, -0.101962, 0.852504}, + {-0.466689, 0.092807, 0.879513}, + {-0.980773, 0.195074, 0.000000}, + {-0.466689, 0.092807, -0.879513}, + {0.512650, -0.101962, -0.852504}, +}; + +static const unsigned short indices[] = { + 6, 7, 1, + 7, 8, 2, + 8, 9, 3, + 9, 10, 4, + 10, 11, 5, + 5, 11, 6, + 12, 13, 7, + 13, 14, 8, + 14, 15, 9, + 15, 16, 10, + 16, 17, 11, + 11, 17, 12, + 18, 19, 13, + 13, 19, 20, + 20, 21, 15, + 15, 21, 22, + 22, 23, 17, + 17, 23, 18, + 24, 25, 19, + 19, 25, 26, + 26, 27, 21, + 21, 27, 28, + 28, 29, 23, + 23, 29, 24, + 30, 31, 25, + 25, 31, 32, + 26, 32, 33, + 27, 33, 34, + 34, 35, 29, + 29, 35, 30, + 36, 37, 31, + 31, 37, 38, + 38, 39, 33, + 39, 40, 34, + 40, 41, 35, + 35, 41, 36, + 36, 42, 43, + 43, 44, 38, + 44, 45, 39, + 45, 46, 40, + 46, 47, 41, + 47, 42, 36, + 48, 49, 43, + 49, 50, 44, + 50, 51, 45, + 51, 52, 46, + 52, 53, 47, + 47, 53, 48, + 54, 55, 49, + 49, 55, 56, + 50, 56, 57, + 57, 58, 52, + 58, 59, 53, + 53, 59, 54, + 60, 61, 55, + 55, 61, 62, + 56, 62, 63, + 63, 64, 58, + 64, 65, 59, + 59, 65, 60, + 66, 67, 61, + 61, 67, 68, + 68, 69, 63, + 69, 70, 64, + 70, 71, 65, + 71, 66, 60, + 72, 73, 67, + 73, 74, 68, + 68, 74, 75, + 75, 76, 70, + 76, 77, 71, + 71, 77, 72, + 78, 79, 73, + 79, 80, 74, + 74, 80, 81, + 81, 82, 76, + 82, 83, 77, + 83, 78, 72, + 78, 84, 85, + 85, 86, 80, + 80, 86, 87, + 87, 88, 82, + 82, 88, 89, + 89, 84, 78, + 90, 91, 85, + 91, 92, 86, + 86, 92, 93, + 93, 94, 88, + 88, 94, 95, + 95, 90, 84, + 96, 97, 91, + 97, 98, 92, + 98, 99, 93, + 99, 100, 94, + 100, 101, 95, + 101, 96, 90, + 102, 103, 97, + 103, 104, 98, + 104, 105, 99, + 99, 105, 106, + 106, 107, 101, + 101, 107, 102, + 108, 109, 103, + 103, 109, 110, + 110, 111, 105, + 105, 111, 112, + 112, 113, 107, + 107, 113, 108, + 114, 115, 109, + 115, 116, 110, + 116, 117, 111, + 111, 117, 118, + 112, 118, 119, + 113, 119, 114, + 114, 120, 121, + 121, 122, 116, + 122, 123, 117, + 117, 123, 124, + 124, 125, 119, + 125, 120, 114, + 126, 127, 121, + 121, 127, 128, + 128, 129, 123, + 123, 129, 130, + 130, 131, 125, + 125, 131, 126, + 132, 133, 127, + 133, 134, 128, + 128, 134, 135, + 135, 136, 130, + 136, 137, 131, + 131, 137, 132, + 132, 138, 139, + 133, 139, 140, + 134, 140, 141, + 141, 142, 136, + 142, 143, 137, + 143, 138, 132, + 138, 144, 145, + 139, 145, 146, + 146, 147, 141, + 141, 147, 148, + 148, 149, 143, + 149, 144, 138, + 144, 150, 151, + 151, 152, 146, + 146, 152, 153, + 153, 154, 148, + 154, 155, 149, + 155, 150, 144, + 156, 157, 151, + 151, 157, 158, + 158, 159, 153, + 159, 160, 154, + 160, 161, 155, + 155, 161, 156, + 156, 162, 163, + 163, 164, 158, + 158, 164, 165, + 165, 166, 160, + 160, 166, 167, + 167, 162, 156, + 162, 168, 169, + 169, 170, 164, + 164, 170, 171, + 165, 171, 172, + 166, 172, 173, + 173, 168, 162, + 174, 175, 169, + 175, 176, 170, + 170, 176, 177, + 177, 178, 172, + 172, 178, 179, + 173, 179, 174, + 174, 180, 181, + 181, 182, 176, + 176, 182, 183, + 183, 184, 178, + 178, 184, 185, + 179, 185, 180, + 186, 187, 181, + 187, 188, 182, + 188, 189, 183, + 183, 189, 190, + 190, 191, 185, + 191, 186, 180, + 0, 1, 187, + 1, 2, 188, + 2, 3, 189, + 3, 4, 190, + 190, 4, 5, + 191, 5, 0, + 0, 6, 1, + 1, 7, 2, + 2, 8, 3, + 3, 9, 4, + 4, 10, 5, + 0, 5, 6, + 6, 12, 7, + 7, 13, 8, + 8, 14, 9, + 9, 15, 10, + 10, 16, 11, + 6, 11, 12, + 12, 18, 13, + 14, 13, 20, + 14, 20, 15, + 16, 15, 22, + 16, 22, 17, + 12, 17, 18, + 18, 24, 19, + 20, 19, 26, + 20, 26, 21, + 22, 21, 28, + 22, 28, 23, + 18, 23, 24, + 24, 30, 25, + 26, 25, 32, + 27, 26, 33, + 28, 27, 34, + 28, 34, 29, + 24, 29, 30, + 30, 36, 31, + 32, 31, 38, + 32, 38, 33, + 33, 39, 34, + 34, 40, 35, + 30, 35, 36, + 37, 36, 43, + 37, 43, 38, + 38, 44, 39, + 39, 45, 40, + 40, 46, 41, + 41, 47, 36, + 42, 48, 43, + 43, 49, 44, + 44, 50, 45, + 45, 51, 46, + 46, 52, 47, + 42, 47, 48, + 48, 54, 49, + 50, 49, 56, + 51, 50, 57, + 51, 57, 52, + 52, 58, 53, + 48, 53, 54, + 54, 60, 55, + 56, 55, 62, + 57, 56, 63, + 57, 63, 58, + 58, 64, 59, + 54, 59, 60, + 60, 66, 61, + 62, 61, 68, + 62, 68, 63, + 63, 69, 64, + 64, 70, 65, + 65, 71, 60, + 66, 72, 67, + 67, 73, 68, + 69, 68, 75, + 69, 75, 70, + 70, 76, 71, + 66, 71, 72, + 72, 78, 73, + 73, 79, 74, + 75, 74, 81, + 75, 81, 76, + 76, 82, 77, + 77, 83, 72, + 79, 78, 85, + 79, 85, 80, + 81, 80, 87, + 81, 87, 82, + 83, 82, 89, + 83, 89, 78, + 84, 90, 85, + 85, 91, 86, + 87, 86, 93, + 87, 93, 88, + 89, 88, 95, + 89, 95, 84, + 90, 96, 91, + 91, 97, 92, + 92, 98, 93, + 93, 99, 94, + 94, 100, 95, + 95, 101, 90, + 96, 102, 97, + 97, 103, 98, + 98, 104, 99, + 100, 99, 106, + 100, 106, 101, + 96, 101, 102, + 102, 108, 103, + 104, 103, 110, + 104, 110, 105, + 106, 105, 112, + 106, 112, 107, + 102, 107, 108, + 108, 114, 109, + 109, 115, 110, + 110, 116, 111, + 112, 111, 118, + 113, 112, 119, + 108, 113, 114, + 115, 114, 121, + 115, 121, 116, + 116, 122, 117, + 118, 117, 124, + 118, 124, 119, + 119, 125, 114, + 120, 126, 121, + 122, 121, 128, + 122, 128, 123, + 124, 123, 130, + 124, 130, 125, + 120, 125, 126, + 126, 132, 127, + 127, 133, 128, + 129, 128, 135, + 129, 135, 130, + 130, 136, 131, + 126, 131, 132, + 133, 132, 139, + 134, 133, 140, + 135, 134, 141, + 135, 141, 136, + 136, 142, 137, + 137, 143, 132, + 139, 138, 145, + 140, 139, 146, + 140, 146, 141, + 142, 141, 148, + 142, 148, 143, + 143, 149, 138, + 145, 144, 151, + 145, 151, 146, + 147, 146, 153, + 147, 153, 148, + 148, 154, 149, + 149, 155, 144, + 150, 156, 151, + 152, 151, 158, + 152, 158, 153, + 153, 159, 154, + 154, 160, 155, + 150, 155, 156, + 157, 156, 163, + 157, 163, 158, + 159, 158, 165, + 159, 165, 160, + 161, 160, 167, + 161, 167, 156, + 163, 162, 169, + 163, 169, 164, + 165, 164, 171, + 166, 165, 172, + 167, 166, 173, + 167, 173, 162, + 168, 174, 169, + 169, 175, 170, + 171, 170, 177, + 171, 177, 172, + 173, 172, 179, + 168, 173, 174, + 175, 174, 181, + 175, 181, 176, + 177, 176, 183, + 177, 183, 178, + 179, 178, 185, + 174, 179, 180, + 180, 186, 181, + 181, 187, 182, + 182, 188, 183, + 184, 183, 190, + 184, 190, 185, + 185, 191, 180, + 186, 0, 187, + 187, 1, 188, + 188, 2, 189, + 189, 3, 190, + 191, 190, 5, + 186, 191, 0, +}; + +ManipulatorGeomInfo wm_manipulator_geom_data_dial = { + .nverts = 192, + .ntris = 384, + .verts = verts, + .normals = normals, + .indices = indices, +}; diff --git a/source/blender/editors/manipulator_library/manipulator_draw_utils.c b/source/blender/editors/manipulator_library/manipulator_draw_utils.c new file mode 100644 index 00000000000..430841311aa --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_draw_utils.c @@ -0,0 +1,131 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file manipulator_draw_utils.c + * \ingroup wm + */ + +#include "BLI_listbase.h" +#include "BLI_ghash.h" +#include "BLI_math.h" +#include "BLI_string.h" +#include "BLI_string_utils.h" + +#include "BKE_context.h" + +#include "ED_screen.h" +#include "ED_view3d.h" + +#include "GPU_batch.h" +#include "GPU_glew.h" +#include "GPU_immediate.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +/* only for own init/exit calls (wm_manipulatortype_init/wm_manipulatortype_free) */ +#include "wm.h" + +/* own includes */ +#include "manipulator_library_intern.h" + +/** + * Main draw call for ManipulatorGeomInfo data + */ +void wm_manipulator_geometryinfo_draw(const ManipulatorGeomInfo *info, const bool select, const float color[4]) +{ + /* TODO store the Batches inside the ManipulatorGeomInfo and updated it when geom changes + * So we don't need to re-created and discard it every time */ + + const bool use_lighting = true || (!select && ((U.manipulator_flag & USER_MANIPULATOR_SHADED) != 0)); + Gwn_VertBuf *vbo; + Gwn_IndexBuf *el; + Gwn_Batch *batch; + Gwn_IndexBufBuilder elb = {0}; + + Gwn_VertFormat format = {0}; + uint pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + uint nor_id; + + if (use_lighting) { + nor_id = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + } + + /* Elements */ + GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, info->ntris, info->nverts); + for (int i = 0; i < info->ntris; ++i) { + const unsigned short *idx = &info->indices[i * 3]; + GWN_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]); + } + el = GWN_indexbuf_build(&elb); + + vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, info->nverts); + + GWN_vertbuf_attr_fill(vbo, pos_id, info->verts); + + if (use_lighting) { + /* Normals are expected to be smooth. */ + GWN_vertbuf_attr_fill(vbo, nor_id, info->normals); + } + + batch = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, el, GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + + GWN_batch_uniform_4fv(batch, "color", color); + + /* We may want to re-visit this, for now disable + * since it causes issues leaving the GL state modified. */ +#if 0 + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); +#endif + + GWN_batch_draw(batch); + +#if 0 + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); +#endif + + + GWN_batch_discard(batch); +} + +void wm_manipulator_vec_draw( + const float color[4], const float (*verts)[3], uint vert_count, + uint pos, uint primitive_type) +{ + immUniformColor4fv(color); + immBegin(primitive_type, vert_count); + for (int i = 0; i < vert_count; i++) { + immVertex3fv(pos, verts[i]); + } + immEnd(); +} diff --git a/source/blender/editors/manipulator_library/manipulator_geometry.h b/source/blender/editors/manipulator_library/manipulator_geometry.h new file mode 100644 index 00000000000..2083f9d4d31 --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_geometry.h @@ -0,0 +1,54 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file manipulator_geometry.h + * \ingroup wm + * + * \name Manipulator Geometry + * + * \brief Prototypes for arrays defining the manipulator geometry. The actual definitions can be found in files usually + * called geom_xxx_manipulator.c + */ + + +#ifndef __MANIPULATOR_GEOMETRY_H__ +#define __MANIPULATOR_GEOMETRY_H__ + +typedef struct ManipulatorGeomInfo { + int nverts; + int ntris; + const float (*verts)[3]; + const float (*normals)[3]; + const unsigned short *indices; +} ManipulatorGeomInfo; + +/* arrow manipulator */ +extern ManipulatorGeomInfo wm_manipulator_geom_data_arrow; + +/* cube manipulator */ +extern ManipulatorGeomInfo wm_manipulator_geom_data_cube; + +/* dial manipulator */ +extern ManipulatorGeomInfo wm_manipulator_geom_data_dial; + +#endif /* __MANIPULATOR_GEOMETRY_H__ */ diff --git a/source/blender/editors/manipulator_library/manipulator_library_intern.h b/source/blender/editors/manipulator_library/manipulator_library_intern.h new file mode 100644 index 00000000000..92ca195f21d --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_library_intern.h @@ -0,0 +1,108 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 Blender Foundation. + * All rights reserved. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file manipulator_library_intern.h + * \ingroup wm + */ + +#ifndef __MANIPULATOR_LIBRARY_INTERN_H__ +#define __MANIPULATOR_LIBRARY_INTERN_H__ + +/* distance around which manipulators respond to input (and get highlighted) */ +#define MANIPULATOR_HOTSPOT 14.0f + +/** + * Data for common interactions. Used in manipulator_library_utils.c functions. + */ +typedef struct ManipulatorCommonData { + int flag; + + float range_fac; /* factor for arrow min/max distance */ + float offset; + + /* property range for constrained manipulators */ + float range; + /* min/max value for constrained manipulators */ + float min, max; +} ManipulatorCommonData; + +typedef struct ManipulatorInteraction { + float init_value; /* initial property value */ + float init_mval[2]; + float init_offset; + float init_matrix_final[4][4]; + float init_matrix_basis[4][4]; + + /* offset of last handling step */ + float prev_offset; + /* Total offset added by precision tweaking. + * Needed to allow toggling precision on/off without causing jumps */ + float precision_offset; +} ManipulatorInteraction; + +/* ManipulatorCommonData->flag */ +enum { + MANIPULATOR_CUSTOM_RANGE_SET = (1 << 0), +}; + + +float manipulator_offset_from_value( + ManipulatorCommonData *data, const float value, + const bool constrained, const bool inverted); +float manipulator_value_from_offset( + ManipulatorCommonData *data, ManipulatorInteraction *inter, const float offset, + const bool constrained, const bool inverted, const bool use_precision); + +void manipulator_property_data_update( + struct wmManipulator *mpr, ManipulatorCommonData *data, wmManipulatorProperty *mpr_prop, + const bool constrained, const bool inverted); + +void manipulator_property_value_reset( + bContext *C, const struct wmManipulator *mpr, ManipulatorInteraction *inter, wmManipulatorProperty *mpr_prop); + + +/* -------------------------------------------------------------------- */ + +void manipulator_color_get( + const struct wmManipulator *mpr, const bool highlight, + float r_color[4]); + +bool manipulator_window_project_2d( + bContext *C, const struct wmManipulator *mpr, const float mval[2], int axis, bool use_offset, + float r_co[2]); + +/* -------------------------------------------------------------------- */ +/* Manipulator drawing */ + +#include "manipulator_geometry.h" + +void wm_manipulator_geometryinfo_draw(const struct ManipulatorGeomInfo *info, const bool select, const float color[4]); +void wm_manipulator_vec_draw( + const float color[4], const float (*verts)[3], uint vert_count, + uint pos, uint primitive_type); + + +#endif /* __MANIPULATOR_LIBRARY_INTERN_H__ */ + diff --git a/source/blender/editors/manipulator_library/manipulator_library_presets.c b/source/blender/editors/manipulator_library/manipulator_library_presets.c new file mode 100644 index 00000000000..7b8d2104992 --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_library_presets.c @@ -0,0 +1,154 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/manipulator_library/manipulator_library_presets.c + * \ingroup wm + * + * \name Manipulator Lib Presets + * + * \brief Preset shapes that can be drawn from any manipulator type. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "DNA_view3d_types.h" +#include "DNA_object_types.h" + +#include "BKE_context.h" + +#include "BIF_gl.h" + +#include "GPU_draw.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" +#include "GPU_select.h" + +#include "DEG_depsgraph.h" + +#include "RNA_access.h" + +#include "WM_types.h" +#include "WM_api.h" + +#include "ED_view3d.h" +#include "ED_screen.h" + +/* own includes */ +#include "ED_manipulator_library.h" /* own include */ +#include "manipulator_library_intern.h" /* own include */ + +/* TODO, this is to be used by RNA. might move to ED_manipulator_library */ + +/** + * Given a single axis, orient the matrix to a different direction. + */ +static void single_axis_convert( + int src_axis, float src_mat[4][4], + int dst_axis, float dst_mat[4][4]) +{ + copy_m4_m4(dst_mat, src_mat); + if (src_axis == dst_axis) { + return; + } + + float rotmat[3][3]; + mat3_from_axis_conversion_single(src_axis, dst_axis, rotmat); + transpose_m3(rotmat); + mul_m4_m4m3(dst_mat, src_mat, rotmat); +} + +/** + * Use for all geometry. + */ +static void ed_manipulator_draw_preset_geometry( + const struct wmManipulator *mpr, float mat[4][4], int select_id, + const ManipulatorGeomInfo *info) +{ + const bool is_select = (select_id != -1); + const bool is_highlight = is_select && (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0; + + float color[4]; + manipulator_color_get(mpr, is_highlight, color); + + if (is_select) { + GPU_select_load_id(select_id); + } + + gpuPushMatrix(); + gpuMultMatrix(mat); + wm_manipulator_geometryinfo_draw(info, is_select, color); + gpuPopMatrix(); + + if (is_select) { + GPU_select_load_id(-1); + } +} + +void ED_manipulator_draw_preset_box( + const struct wmManipulator *mpr, float mat[4][4], int select_id) +{ + ed_manipulator_draw_preset_geometry(mpr, mat, select_id, &wm_manipulator_geom_data_cube); +} + +void ED_manipulator_draw_preset_arrow( + const struct wmManipulator *mpr, float mat[4][4], int axis, int select_id) +{ + float mat_rotate[4][4]; + single_axis_convert(OB_POSZ, mat, axis, mat_rotate); + ed_manipulator_draw_preset_geometry(mpr, mat_rotate, select_id, &wm_manipulator_geom_data_arrow); +} + +void ED_manipulator_draw_preset_circle( + const struct wmManipulator *mpr, float mat[4][4], int axis, int select_id) +{ + float mat_rotate[4][4]; + single_axis_convert(OB_POSZ, mat, axis, mat_rotate); + ed_manipulator_draw_preset_geometry(mpr, mat_rotate, select_id, &wm_manipulator_geom_data_dial); +} + +void ED_manipulator_draw_preset_facemap( + const bContext *C, const struct wmManipulator *mpr, struct Scene *scene, Object *ob, const int facemap, int select_id) +{ + const bool is_select = (select_id != -1); + const bool is_highlight = is_select && (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0; + + float color[4]; + manipulator_color_get(mpr, is_highlight, color); + + if (is_select) { + GPU_select_load_id(select_id); + } + + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + + gpuPushMatrix(); + gpuMultMatrix(ob->obmat); + ED_draw_object_facemap(&eval_ctx, scene, ob, color, facemap); + gpuPopMatrix(); + + if (is_select) { + GPU_select_load_id(-1); + } +} + diff --git a/source/blender/editors/manipulator_library/manipulator_library_utils.c b/source/blender/editors/manipulator_library/manipulator_library_utils.c new file mode 100644 index 00000000000..38b518b1992 --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_library_utils.c @@ -0,0 +1,221 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 Blender Foundation. + * All rights reserved. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file manipulator_library_utils.c + * \ingroup wm + * + * \name Manipulator Library Utilities + * + * \brief This file contains functions for common behaviors of manipulators. + */ + +#include "BLI_math.h" +#include "BLI_listbase.h" + +#include "DNA_view3d_types.h" +#include "DNA_screen_types.h" + +#include "BKE_context.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_view3d.h" + +/* own includes */ +#include "manipulator_library_intern.h" + +/* factor for precision tweaking */ +#define MANIPULATOR_PRECISION_FAC 0.05f + + +BLI_INLINE float manipulator_offset_from_value_constr( + const float range_fac, const float min, const float range, const float value, + const bool inverted) +{ + return inverted ? (range_fac * (min + range - value) / range) : (range_fac * (value / range)); +} + +BLI_INLINE float manipulator_value_from_offset_constr( + const float range_fac, const float min, const float range, const float value, + const bool inverted) +{ + return inverted ? (min + range - (value * range / range_fac)) : (value * range / range_fac); +} + +float manipulator_offset_from_value( + ManipulatorCommonData *data, const float value, const bool constrained, const bool inverted) +{ + if (constrained) + return manipulator_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted); + + return value; +} + +float manipulator_value_from_offset( + ManipulatorCommonData *data, ManipulatorInteraction *inter, const float offset, + const bool constrained, const bool inverted, const bool use_precision) +{ + const float max = data->min + data->range; + + if (use_precision) { + /* add delta offset of this step to total precision_offset */ + inter->precision_offset += offset - inter->prev_offset; + } + inter->prev_offset = offset; + + float ofs_new = inter->init_offset + offset - inter->precision_offset * (1.0f - MANIPULATOR_PRECISION_FAC); + float value; + + if (constrained) { + value = manipulator_value_from_offset_constr(data->range_fac, data->min, data->range, ofs_new, inverted); + } + else { + value = ofs_new; + } + + /* clamp to custom range */ + if (data->flag & MANIPULATOR_CUSTOM_RANGE_SET) { + CLAMP(value, data->min, max); + } + + return value; +} + +void manipulator_property_data_update( + wmManipulator *mpr, ManipulatorCommonData *data, wmManipulatorProperty *mpr_prop, + const bool constrained, const bool inverted) +{ + if (mpr_prop->custom_func.value_get_fn != NULL) { + /* pass */ + } + else if (mpr_prop->prop != NULL) { + /* pass */ + } + else { + data->offset = 0.0f; + return; + } + + float value = WM_manipulator_target_property_value_get(mpr, mpr_prop); + + if (constrained) { + if ((data->flag & MANIPULATOR_CUSTOM_RANGE_SET) == 0) { + float range[2]; + if (WM_manipulator_target_property_range_get(mpr, mpr_prop, range)) { + data->range = range[1] - range[0]; + data->min = range[0]; + } + else { + BLI_assert(0); + } + } + data->offset = manipulator_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted); + } + else { + data->offset = value; + } +} + +void manipulator_property_value_reset( + bContext *C, const wmManipulator *mpr, ManipulatorInteraction *inter, + wmManipulatorProperty *mpr_prop) +{ + WM_manipulator_target_property_value_set(C, mpr, mpr_prop, inter->init_value); +} + +/* -------------------------------------------------------------------- */ + +void manipulator_color_get( + const wmManipulator *mpr, const bool highlight, + float r_col[4]) +{ + if (highlight && !(mpr->flag & WM_MANIPULATOR_DRAW_HOVER)) { + copy_v4_v4(r_col, mpr->color_hi); + } + else { + copy_v4_v4(r_col, mpr->color); + } +} + +/* -------------------------------------------------------------------- */ + +/** + * Takes mouse coordinates and returns them in relation to the manipulator. + * Both 2D & 3D supported, use so we can use 2D manipulators in the 3D view. + */ +bool manipulator_window_project_2d( + bContext *C, const struct wmManipulator *mpr, const float mval[2], int axis, bool use_offset, + float r_co[2]) +{ + float mat[4][4]; + { + float mat_identity[4][4]; + struct WM_ManipulatorMatrixParams params = {NULL}; + if (use_offset == false) { + unit_m4(mat_identity); + params.matrix_offset = mat_identity; + } + WM_manipulator_calc_matrix_final_params(mpr, ¶ms, mat); + } + + /* rotate mouse in relation to the center and relocate it */ + if (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) { + /* For 3d views, transform 2D mouse pos onto plane. */ + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + + float plane[4]; + + plane_from_point_normal_v3(plane, mat[3], mat[2]); + + float ray_origin[3], ray_direction[3]; + + if (ED_view3d_win_to_ray(ar, v3d, mval, ray_origin, ray_direction, false)) { + float lambda; + if (isect_ray_plane_v3(ray_origin, ray_direction, plane, &lambda, true)) { + float co[3]; + madd_v3_v3v3fl(co, ray_origin, ray_direction, lambda); + float imat[4][4]; + invert_m4_m4(imat, mat); + mul_m4_v3(imat, co); + r_co[0] = co[(axis + 1) % 3]; + r_co[1] = co[(axis + 2) % 3]; + return true; + } + } + return false; + } + else { + float co[3] = {mval[0], mval[1], 0.0f}; + float imat[4][4]; + invert_m4_m4(imat, mat); + mul_m4_v3(imat, co); + copy_v2_v2(r_co, co); + return true; + } +} diff --git a/source/blender/editors/manipulator_library/manipulator_types/arrow2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/arrow2d_manipulator.c new file mode 100644 index 00000000000..749e92e25fb --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_types/arrow2d_manipulator.c @@ -0,0 +1,224 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 Blender Foundation. + * All rights reserved. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file arrow2d_manipulator.c + * \ingroup wm + * + * \name 2D Arrow Manipulator + * + * \brief Simple arrow manipulator which is dragged into a certain direction. + */ + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_rect.h" + +#include "DNA_windowmanager_types.h" + +#include "BKE_context.h" + +#include "BIF_gl.h" + +#include "GPU_draw.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +/* own includes */ +#include "WM_api.h" + +#include "../manipulator_library_intern.h" + +static void arrow2d_draw_geom(wmManipulator *mpr, const float matrix[4][4], const float color[4]) +{ + const float size = 0.11f; + const float size_breadth = size / 2.0f; + const float size_length = size * 1.7f; + /* Subtract the length so the arrow fits in the hotspot. */ + const float arrow_length = RNA_float_get(mpr->ptr, "length") - size_length; + const float arrow_angle = RNA_float_get(mpr->ptr, "angle"); + + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + gpuPushMatrix(); + gpuMultMatrix(matrix); + gpuRotate2D(RAD2DEGF(arrow_angle)); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4fv(color); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, 0.0f, 0.0f); + immVertex2f(pos, 0.0f, arrow_length); + immEnd(); + + immBegin(GWN_PRIM_TRIS, 3); + immVertex2f(pos, size_breadth, arrow_length); + immVertex2f(pos, -size_breadth, arrow_length); + immVertex2f(pos, 0.0f, arrow_length + size_length); + immEnd(); + + immUnbindProgram(); + + gpuPopMatrix(); +} + +static void manipulator_arrow2d_draw(const bContext *UNUSED(C), wmManipulator *mpr) +{ + float color[4]; + + float matrix_final[4][4]; + + manipulator_color_get(mpr, mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT, color); + + glLineWidth(mpr->line_width); + + WM_manipulator_calc_matrix_final(mpr, matrix_final); + + glEnable(GL_BLEND); + arrow2d_draw_geom(mpr, matrix_final, color); + glDisable(GL_BLEND); + + if (mpr->interaction_data) { + ManipulatorInteraction *inter = mpr->interaction_data; + + glEnable(GL_BLEND); + arrow2d_draw_geom(mpr, inter->init_matrix_final, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f}); + glDisable(GL_BLEND); + } +} + +static void manipulator_arrow2d_setup(wmManipulator *mpr) +{ + mpr->flag |= WM_MANIPULATOR_DRAW_MODAL; +} + +static int manipulator_arrow2d_invoke( + bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *UNUSED(event)) +{ + ManipulatorInteraction *inter = MEM_callocN(sizeof(ManipulatorInteraction), __func__); + + copy_m4_m4(inter->init_matrix_basis, mpr->matrix_basis); + WM_manipulator_calc_matrix_final(mpr, inter->init_matrix_final); + + mpr->interaction_data = inter; + + return OPERATOR_RUNNING_MODAL; +} + +static int manipulator_arrow2d_test_select( + bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event) +{ + const float mval[2] = {event->mval[0], event->mval[1]}; + const float arrow_length = RNA_float_get(mpr->ptr, "length"); + const float arrow_angle = RNA_float_get(mpr->ptr, "angle"); + const float line_len = arrow_length * mpr->scale_final; + float mval_local[2]; + + copy_v2_v2(mval_local, mval); + sub_v2_v2(mval_local, mpr->matrix_basis[3]); + + float line[2][2]; + line[0][0] = line[0][1] = line[1][0] = 0.0f; + line[1][1] = line_len; + + /* rotate only if needed */ + if (arrow_angle != 0.0f) { + float rot_point[2]; + copy_v2_v2(rot_point, line[1]); + rotate_v2_v2fl(line[1], rot_point, arrow_angle); + } + + /* arrow line intersection check */ + float isect_1[2], isect_2[2]; + const int isect = isect_line_sphere_v2( + line[0], line[1], mval_local, MANIPULATOR_HOTSPOT + mpr->line_width * 0.5f, + isect_1, isect_2); + + if (isect > 0) { + float line_ext[2][2]; /* extended line for segment check including hotspot */ + copy_v2_v2(line_ext[0], line[0]); + line_ext[1][0] = line[1][0] + MANIPULATOR_HOTSPOT * ((line[1][0] - line[0][0]) / line_len); + line_ext[1][1] = line[1][1] + MANIPULATOR_HOTSPOT * ((line[1][1] - line[0][1]) / line_len); + + const float lambda_1 = line_point_factor_v2(isect_1, line_ext[0], line_ext[1]); + if (isect == 1) { + if (IN_RANGE_INCL(lambda_1, 0.0f, 1.0f)) { + return 0; + } + } + else { + BLI_assert(isect == 2); + const float lambda_2 = line_point_factor_v2(isect_2, line_ext[0], line_ext[1]); + if (IN_RANGE_INCL(lambda_1, 0.0f, 1.0f) && IN_RANGE_INCL(lambda_2, 0.0f, 1.0f)) { + return 0; + } + } + } + + return -1; +} + +/* -------------------------------------------------------------------- */ +/** \name 2D Arrow Manipulator API + * + * \{ */ + +static void MANIPULATOR_WT_arrow_2d(wmManipulatorType *wt) +{ + /* identifiers */ + wt->idname = "MANIPULATOR_WT_arrow_2d"; + + /* api callbacks */ + wt->draw = manipulator_arrow2d_draw; + wt->setup = manipulator_arrow2d_setup; + wt->invoke = manipulator_arrow2d_invoke; + wt->test_select = manipulator_arrow2d_test_select; + + wt->struct_size = sizeof(wmManipulator); + + /* rna */ + RNA_def_float(wt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX); + RNA_def_float_rotation( + wt->srna, "angle", 0, NULL, DEG2RADF(-360.0f), DEG2RADF(360.0f), + "Roll", "", DEG2RADF(-360.0f), DEG2RADF(360.0f)); +} + +void ED_manipulatortypes_arrow_2d(void) +{ + WM_manipulatortype_append(MANIPULATOR_WT_arrow_2d); +} + +/** \} */ diff --git a/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c new file mode 100644 index 00000000000..e9760e3e270 --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c @@ -0,0 +1,503 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file arrow3d_manipulator.c + * \ingroup wm + * + * \name Arrow Manipulator + * + * 3D Manipulator + * + * \brief Simple arrow manipulator which is dragged into a certain direction. + * The arrow head can have varying shapes, e.g. cone, box, etc. + * + * - `matrix[0]` is derived from Y and Z. + * - `matrix[1]` is 'up' for manipulator types that have an up. + * - `matrix[2]` is the arrow direction (for all arrowes). + */ + +#include "BIF_gl.h" + +#include "BLI_math.h" + +#include "DNA_view3d_types.h" + +#include "BKE_context.h" + +#include "GPU_draw.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" +#include "GPU_select.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_types.h" +#include "WM_api.h" + +#include "ED_view3d.h" +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +/* own includes */ +#include "../manipulator_geometry.h" +#include "../manipulator_library_intern.h" + +/* to use custom arrows exported to geom_arrow_manipulator.c */ +//#define USE_MANIPULATOR_CUSTOM_ARROWS + +typedef struct ArrowManipulator3D { + wmManipulator manipulator; + ManipulatorCommonData data; +} ArrowManipulator3D; + + +/* -------------------------------------------------------------------- */ + +static void manipulator_arrow_matrix_basis_get(const wmManipulator *mpr, float r_matrix[4][4]) +{ + ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr; + + copy_m4_m4(r_matrix, arrow->manipulator.matrix_basis); + madd_v3_v3fl(r_matrix[3], arrow->manipulator.matrix_basis[2], arrow->data.offset); +} + +static void arrow_draw_geom(const ArrowManipulator3D *arrow, const bool select, const float color[4]) +{ + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + bool unbind_shader = true; + const int draw_style = RNA_enum_get(arrow->manipulator.ptr, "draw_style"); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + if (draw_style == ED_MANIPULATOR_ARROW_STYLE_CROSS) { + immUniformColor4fv(color); + + immBegin(GWN_PRIM_LINES, 4); + immVertex3f(pos, -1.0f, 0.0f, 0.0f); + immVertex3f(pos, 1.0f, 0.0f, 0.0f); + immVertex3f(pos, 0.0f, -1.0f, 0.0f); + immVertex3f(pos, 0.0f, 1.0f, 0.0f); + immEnd(); + } + else if (draw_style == ED_MANIPULATOR_ARROW_STYLE_CONE) { + float aspect[2]; + RNA_float_get_array(arrow->manipulator.ptr, "aspect", aspect); + const float unitx = aspect[0]; + const float unity = aspect[1]; + const float vec[4][3] = { + {-unitx, -unity, 0}, + { unitx, -unity, 0}, + { unitx, unity, 0}, + {-unitx, unity, 0}, + }; + + glLineWidth(arrow->manipulator.line_width); + wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_LOOP); + } + else { +#ifdef USE_MANIPULATOR_CUSTOM_ARROWS + wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_arrow, select, color); +#else + const float arrow_length = RNA_float_get(arrow->manipulator.ptr, "length"); + + const float vec[2][3] = { + {0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, arrow_length}, + }; + + glLineWidth(arrow->manipulator.line_width); + wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_STRIP); + + + /* *** draw arrow head *** */ + + gpuPushMatrix(); + + if (draw_style == ED_MANIPULATOR_ARROW_STYLE_BOX) { + const float size = 0.05f; + + /* translate to line end with some extra offset so box starts exactly where line ends */ + gpuTranslate3f(0.0f, 0.0f, arrow_length + size); + /* scale down to box size */ + gpuScale3f(size, size, size); + + /* draw cube */ + immUnbindProgram(); + unbind_shader = false; + wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_cube, select, color); + } + else { + BLI_assert(draw_style == ED_MANIPULATOR_ARROW_STYLE_NORMAL); + + const float len = 0.25f; + const float width = 0.06f; + const bool use_lighting = (!select && ((U.manipulator_flag & USER_MANIPULATOR_SHADED) != 0)); + + /* translate to line end */ + gpuTranslate3f(0.0f, 0.0f, arrow_length); + + if (use_lighting) { + immUnbindProgram(); + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); + } + + imm_draw_circle_fill_3d(pos, 0.0, 0.0, width, 8); + imm_draw_cylinder_fill_3d(pos, width, 0.0, len, 8, 1); + } + + gpuPopMatrix(); +#endif /* USE_MANIPULATOR_CUSTOM_ARROWS */ + } + + if (unbind_shader) { + immUnbindProgram(); + } +} + +static void arrow_draw_intern(ArrowManipulator3D *arrow, const bool select, const bool highlight) +{ + wmManipulator *mpr = &arrow->manipulator; + float color[4]; + float matrix_final[4][4]; + + manipulator_color_get(mpr, highlight, color); + + WM_manipulator_calc_matrix_final(mpr, matrix_final); + + gpuPushMatrix(); + gpuMultMatrix(matrix_final); + glEnable(GL_BLEND); + arrow_draw_geom(arrow, select, color); + glDisable(GL_BLEND); + + gpuPopMatrix(); + + if (mpr->interaction_data) { + ManipulatorInteraction *inter = mpr->interaction_data; + + gpuPushMatrix(); + gpuMultMatrix(inter->init_matrix_final); + + + glEnable(GL_BLEND); + arrow_draw_geom(arrow, select, (const float [4]){0.5f, 0.5f, 0.5f, 0.5f}); + glDisable(GL_BLEND); + + gpuPopMatrix(); + } +} + +static void manipulator_arrow_draw_select( + const bContext *UNUSED(C), wmManipulator *mpr, + int select_id) +{ + GPU_select_load_id(select_id); + arrow_draw_intern((ArrowManipulator3D *)mpr, true, false); +} + +static void manipulator_arrow_draw(const bContext *UNUSED(C), wmManipulator *mpr) +{ + arrow_draw_intern((ArrowManipulator3D *)mpr, false, (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0); +} + +/** + * Calculate arrow offset independent from prop min value, + * meaning the range will not be offset by min value first. + */ +static int manipulator_arrow_modal( + bContext *C, wmManipulator *mpr, const wmEvent *event, + eWM_ManipulatorTweak tweak_flag) +{ + ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr; + ManipulatorInteraction *inter = mpr->interaction_data; + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + + float orig_origin[4]; + float viewvec[3], tangent[3], plane[3]; + float offset[4]; + float m_diff[2]; + float dir_2d[2], dir2d_final[2]; + float facdir = 1.0f; + bool use_vertical = false; + + + copy_v3_v3(orig_origin, inter->init_matrix_basis[3]); + orig_origin[3] = 1.0f; + add_v3_v3v3(offset, orig_origin, arrow->manipulator.matrix_basis[2]); + offset[3] = 1.0f; + + /* calculate view vector */ + if (rv3d->is_persp) { + sub_v3_v3v3(viewvec, orig_origin, rv3d->viewinv[3]); + } + else { + copy_v3_v3(viewvec, rv3d->viewinv[2]); + } + normalize_v3(viewvec); + + /* first determine if view vector is really close to the direction. If it is, we use + * vertical movement to determine offset, just like transform system does */ + if (RAD2DEGF(acosf(dot_v3v3(viewvec, arrow->manipulator.matrix_basis[2]))) > 5.0f) { + /* multiply to projection space */ + mul_m4_v4(rv3d->persmat, orig_origin); + mul_v4_fl(orig_origin, 1.0f / orig_origin[3]); + mul_m4_v4(rv3d->persmat, offset); + mul_v4_fl(offset, 1.0f / offset[3]); + + sub_v2_v2v2(dir_2d, offset, orig_origin); + dir_2d[0] *= ar->winx; + dir_2d[1] *= ar->winy; + normalize_v2(dir_2d); + } + else { + dir_2d[0] = 0.0f; + dir_2d[1] = 1.0f; + use_vertical = true; + } + + /* find mouse difference */ + m_diff[0] = event->mval[0] - inter->init_mval[0]; + m_diff[1] = event->mval[1] - inter->init_mval[1]; + + /* project the displacement on the screen space arrow direction */ + project_v2_v2v2(dir2d_final, m_diff, dir_2d); + + float zfac = ED_view3d_calc_zfac(rv3d, orig_origin, NULL); + ED_view3d_win_to_delta(ar, dir2d_final, offset, zfac); + + add_v3_v3v3(orig_origin, offset, inter->init_matrix_basis[3]); + + /* calculate view vector for the new position */ + if (rv3d->is_persp) { + sub_v3_v3v3(viewvec, orig_origin, rv3d->viewinv[3]); + } + else { + copy_v3_v3(viewvec, rv3d->viewinv[2]); + } + + normalize_v3(viewvec); + if (!use_vertical) { + /* now find a plane parallel to the view vector so we can intersect with the arrow direction */ + cross_v3_v3v3(tangent, viewvec, offset); + cross_v3_v3v3(plane, tangent, viewvec); + + const float plane_offset = dot_v3v3(plane, offset); + const float plane_dir = dot_v3v3(plane, arrow->manipulator.matrix_basis[2]); + const float fac = (plane_dir != 0.0f) ? (plane_offset / plane_dir) : 0.0f; + facdir = (fac < 0.0f) ? -1.0f : 1.0f; + if (isfinite(fac)) { + mul_v3_v3fl(offset, arrow->manipulator.matrix_basis[2], fac); + } + } + else { + facdir = (m_diff[1] < 0.0f) ? -1.0f : 1.0f; + } + + + ManipulatorCommonData *data = &arrow->data; + const float ofs_new = facdir * len_v3(offset); + + wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset"); + + /* set the property for the operator and call its modal function */ + if (WM_manipulator_target_property_is_valid(mpr_prop)) { + const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options"); + const bool constrained = (draw_options & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED) != 0; + const bool inverted = (draw_options & ED_MANIPULATOR_ARROW_STYLE_INVERTED) != 0; + const bool use_precision = (tweak_flag & WM_MANIPULATOR_TWEAK_PRECISE) != 0; + float value = manipulator_value_from_offset(data, inter, ofs_new, constrained, inverted, use_precision); + + WM_manipulator_target_property_value_set(C, mpr, mpr_prop, value); + /* get clamped value */ + value = WM_manipulator_target_property_value_get(mpr, mpr_prop); + + data->offset = manipulator_offset_from_value(data, value, constrained, inverted); + } + else { + data->offset = ofs_new; + } + + /* tag the region for redraw */ + ED_region_tag_redraw(ar); + WM_event_add_mousemove(C); + + return OPERATOR_RUNNING_MODAL; +} + +static void manipulator_arrow_setup(wmManipulator *mpr) +{ + ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr; + + arrow->manipulator.flag |= WM_MANIPULATOR_DRAW_MODAL; + + arrow->data.range_fac = 1.0f; +} + +static int manipulator_arrow_invoke( + bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event) +{ + ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr; + ManipulatorInteraction *inter = MEM_callocN(sizeof(ManipulatorInteraction), __func__); + wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset"); + + /* Some manipulators don't use properties. */ + if (WM_manipulator_target_property_is_valid(mpr_prop)) { + inter->init_value = WM_manipulator_target_property_value_get(mpr, mpr_prop); + } + + inter->init_offset = arrow->data.offset; + + inter->init_mval[0] = event->mval[0]; + inter->init_mval[1] = event->mval[1]; + + manipulator_arrow_matrix_basis_get(mpr, inter->init_matrix_basis); + WM_manipulator_calc_matrix_final(mpr, inter->init_matrix_final); + + mpr->interaction_data = inter; + + return OPERATOR_RUNNING_MODAL; +} + +static void manipulator_arrow_property_update(wmManipulator *mpr, wmManipulatorProperty *mpr_prop) +{ + ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr; + const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options"); + const bool constrained = (draw_options & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED) != 0; + const bool inverted = (draw_options & ED_MANIPULATOR_ARROW_STYLE_INVERTED) != 0; + manipulator_property_data_update(mpr, &arrow->data, mpr_prop, constrained, inverted); +} + +static void manipulator_arrow_exit(bContext *C, wmManipulator *mpr, const bool cancel) +{ + ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr; + ManipulatorCommonData *data = &arrow->data; + wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset"); + const bool is_prop_valid = WM_manipulator_target_property_is_valid(mpr_prop); + + if (!cancel) { + /* Assign incase applying the opetration needs an updated offset + * editmesh bisect needs this. */ + if (is_prop_valid) { + data->offset = WM_manipulator_target_property_value_get(mpr, mpr_prop); + } + return; + } + + ManipulatorInteraction *inter = mpr->interaction_data; + if (is_prop_valid) { + manipulator_property_value_reset(C, mpr, inter, mpr_prop); + } + data->offset = inter->init_offset; +} + + +/* -------------------------------------------------------------------- */ +/** \name Arrow Manipulator API + * + * \{ */ + +/** + * Define a custom property UI range + * + * \note Needs to be called before WM_manipulator_target_property_def_rna! + */ +void ED_manipulator_arrow3d_set_ui_range(wmManipulator *mpr, const float min, const float max) +{ + ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr; + + BLI_assert(min < max); + BLI_assert(!(WM_manipulator_target_property_is_valid(WM_manipulator_target_property_find(mpr, "offset")) && + "Make sure this function is called before WM_manipulator_target_property_def_rna")); + + arrow->data.range = max - min; + arrow->data.min = min; + arrow->data.flag |= MANIPULATOR_CUSTOM_RANGE_SET; +} + +/** + * Define a custom factor for arrow min/max distance + * + * \note Needs to be called before WM_manipulator_target_property_def_rna! + */ +void ED_manipulator_arrow3d_set_range_fac(wmManipulator *mpr, const float range_fac) +{ + ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr; + BLI_assert(!(WM_manipulator_target_property_is_valid(WM_manipulator_target_property_find(mpr, "offset")) && + "Make sure this function is called before WM_manipulator_target_property_def_rna")); + + arrow->data.range_fac = range_fac; +} + +static void MANIPULATOR_WT_arrow_3d(wmManipulatorType *wt) +{ + /* identifiers */ + wt->idname = "MANIPULATOR_WT_arrow_3d"; + + /* api callbacks */ + wt->draw = manipulator_arrow_draw; + wt->draw_select = manipulator_arrow_draw_select; + wt->matrix_basis_get = manipulator_arrow_matrix_basis_get; + wt->modal = manipulator_arrow_modal; + wt->setup = manipulator_arrow_setup; + wt->invoke = manipulator_arrow_invoke; + wt->property_update = manipulator_arrow_property_update; + wt->exit = manipulator_arrow_exit; + + wt->struct_size = sizeof(ArrowManipulator3D); + + /* rna */ + static EnumPropertyItem rna_enum_draw_style[] = { + {ED_MANIPULATOR_ARROW_STYLE_NORMAL, "NORMAL", 0, "Normal", ""}, + {ED_MANIPULATOR_ARROW_STYLE_CROSS, "CROSS", 0, "Cross", ""}, + {ED_MANIPULATOR_ARROW_STYLE_BOX, "BOX", 0, "Box", ""}, + {ED_MANIPULATOR_ARROW_STYLE_CONE, "CONE", 0, "Cone", ""}, + {0, NULL, 0, NULL, NULL} + }; + static EnumPropertyItem rna_enum_draw_options[] = { + {ED_MANIPULATOR_ARROW_STYLE_INVERTED, "INVERT", 0, "Inverted", ""}, + {ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED, "CONSTRAIN", 0, "Constrained", ""}, + {0, NULL, 0, NULL, NULL} + }; + + RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_ARROW_STYLE_NORMAL, "Draw Style", ""); + RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", ""); + + RNA_def_float(wt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX); + RNA_def_float_vector(wt->srna, "aspect", 2, NULL, 0, FLT_MAX, "Aspect", "Cone/box style only", 0.0f, FLT_MAX); + + WM_manipulatortype_target_property_def(wt, "offset", PROP_FLOAT, 1); +} + +void ED_manipulatortypes_arrow_3d(void) +{ + WM_manipulatortype_append(MANIPULATOR_WT_arrow_3d); +} + +/** \} */ diff --git a/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c new file mode 100644 index 00000000000..0299a33d0fe --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c @@ -0,0 +1,1109 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file cage2d_manipulator.c + * \ingroup wm + * + * \name Cage Manipulator + * + * 2D Manipulator + * + * \brief Rectangular manipulator acting as a 'cage' around its content. + * Interacting scales or translates the manipulator. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_dial.h" +#include "BLI_rect.h" + +#include "BKE_context.h" + +#include "BIF_gl.h" + +#include "GPU_matrix.h" +#include "GPU_shader.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_select.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_view3d.h" +#include "ED_manipulator_library.h" + +/* own includes */ +#include "../manipulator_library_intern.h" + +#define MANIPULATOR_RESIZER_SIZE 10.0f +#define MANIPULATOR_MARGIN_OFFSET_SCALE 1.5f + +static void manipulator_calc_matrix_final_no_offset( + const wmManipulator *mpr, float orig_matrix_final_no_offset[4][4]) +{ + float mat_identity[4][4]; + struct WM_ManipulatorMatrixParams params = {NULL}; + unit_m4(mat_identity); + params.matrix_offset = mat_identity; + WM_manipulator_calc_matrix_final_params(mpr, ¶ms, orig_matrix_final_no_offset); +} + +static void manipulator_calc_rect_view_scale( + const wmManipulator *mpr, const float dims[2], float scale[2]) +{ + float matrix_final_no_offset[4][4]; + float asp[2] = {1.0f, 1.0f}; + if (dims[0] > dims[1]) { + asp[0] = dims[1] / dims[0]; + } + else { + asp[1] = dims[0] / dims[1]; + } + float x_axis[3], y_axis[3]; + manipulator_calc_matrix_final_no_offset(mpr, matrix_final_no_offset); + mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, mpr->matrix_offset[0]); + mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, mpr->matrix_offset[1]); + + mul_v2_v2(x_axis, asp); + mul_v2_v2(y_axis, asp); + + scale[0] = 1.0f / len_v3(x_axis); + scale[1] = 1.0f / len_v3(y_axis); +} + +static void manipulator_calc_rect_view_margin( + const wmManipulator *mpr, const float dims[2], float margin[2]) +{ + float handle_size; + if (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) { + handle_size = 0.15f; + } + else { + handle_size = MANIPULATOR_RESIZER_SIZE; + } + handle_size *= mpr->scale_final; + float scale_xy[2]; + manipulator_calc_rect_view_scale(mpr, dims, scale_xy); + margin[0] = ((handle_size * scale_xy[0])); + margin[1] = ((handle_size * scale_xy[1])); +} + +/* -------------------------------------------------------------------- */ + +static void manipulator_rect_pivot_from_scale_part(int part, float r_pt[2], bool r_constrain_axis[2]) +{ + bool x = true, y = true; + switch (part) { + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X: { ARRAY_SET_ITEMS(r_pt, 0.5, 0.0); x = false; break; } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X: { ARRAY_SET_ITEMS(r_pt, -0.5, 0.0); x = false; break; } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y: { ARRAY_SET_ITEMS(r_pt, 0.0, 0.5); y = false; break; } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y: { ARRAY_SET_ITEMS(r_pt, 0.0, -0.5); y = false; break; } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y: { ARRAY_SET_ITEMS(r_pt, 0.5, 0.5); x = y = false; break; } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y: { ARRAY_SET_ITEMS(r_pt, 0.5, -0.5); x = y = false; break; } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y: { ARRAY_SET_ITEMS(r_pt, -0.5, 0.5); x = y = false; break; } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y: { ARRAY_SET_ITEMS(r_pt, -0.5, -0.5); x = y = false; break; } + default: BLI_assert(0); + } + r_constrain_axis[0] = x; + r_constrain_axis[1] = y; +} + +/* -------------------------------------------------------------------- */ +/** \name Box Draw Style + * + * Useful for 3D views, see: #ED_MANIPULATOR_CAGE2D_STYLE_BOX + * \{ */ + +static void cage2d_draw_box_corners( + const rctf *r, const float margin[2], const float color[3]) +{ + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3fv(color); + + immBegin(GWN_PRIM_LINES, 16); + + immVertex2f(pos, r->xmin, r->ymin + margin[1]); + immVertex2f(pos, r->xmin, r->ymin); + immVertex2f(pos, r->xmin, r->ymin); + immVertex2f(pos, r->xmin + margin[0], r->ymin); + + immVertex2f(pos, r->xmax, r->ymin + margin[1]); + immVertex2f(pos, r->xmax, r->ymin); + immVertex2f(pos, r->xmax, r->ymin); + immVertex2f(pos, r->xmax - margin[0], r->ymin); + + immVertex2f(pos, r->xmax, r->ymax - margin[1]); + immVertex2f(pos, r->xmax, r->ymax); + immVertex2f(pos, r->xmax, r->ymax); + immVertex2f(pos, r->xmax - margin[0], r->ymax); + + immVertex2f(pos, r->xmin, r->ymax - margin[1]); + immVertex2f(pos, r->xmin, r->ymax); + immVertex2f(pos, r->xmin, r->ymax); + immVertex2f(pos, r->xmin + margin[0], r->ymax); + + immEnd(); + + immUnbindProgram(); +} + +static void cage2d_draw_box_interaction( + const float color[4], const int highlighted, + const float size[2], const float margin[2], + const float line_width, const bool is_solid, const int draw_options) +{ + /* 4 verts for translate, otherwise only 3 are used. */ + float verts[4][2]; + uint verts_len = 0; + Gwn_PrimType prim_type = GWN_PRIM_NONE; + + switch (highlighted) { + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X: + { + rctf r = { + .xmin = -size[0], .xmax = -size[0] + margin[0], + .ymin = -size[1] + margin[1], .ymax = size[1] - margin[1], + }; + ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin); + ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymax); + verts_len = 2; + if (is_solid) { + ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax); + ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin); + verts_len += 2; + prim_type = GWN_PRIM_TRI_FAN; + } + else { + prim_type = GWN_PRIM_LINE_STRIP; + } + break; + } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X: + { + rctf r = { + .xmin = size[0] - margin[0], .xmax = size[0], + .ymin = -size[1] + margin[1], .ymax = size[1] - margin[1], + }; + ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymin); + ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax); + verts_len = 2; + if (is_solid) { + ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymax); + ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin); + verts_len += 2; + prim_type = GWN_PRIM_TRI_FAN; + } + else { + prim_type = GWN_PRIM_LINE_STRIP; + } + break; + } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y: + { + rctf r = { + .xmin = -size[0] + margin[0], .xmax = size[0] - margin[0], + .ymin = -size[1], .ymax = -size[1] + margin[1], + }; + ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin); + ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymin); + verts_len = 2; + if (is_solid) { + ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax); + ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax); + verts_len += 2; + prim_type = GWN_PRIM_TRI_FAN; + } + else { + prim_type = GWN_PRIM_LINE_STRIP; + } + break; + } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y: + { + rctf r = { + .xmin = -size[0] + margin[0], .xmax = size[0] - margin[0], + .ymin = size[1] - margin[1], .ymax = size[1], + }; + ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymax); + ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax); + verts_len = 2; + if (is_solid) { + ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymin); + ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin); + verts_len += 2; + prim_type = GWN_PRIM_TRI_FAN; + } + else { + prim_type = GWN_PRIM_LINE_STRIP; + } + break; + } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y: + { + rctf r = { + .xmin = -size[0], .xmax = -size[0] + margin[0], + .ymin = -size[1], .ymax = -size[1] + margin[1], + }; + ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymin); + ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax); + ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymax); + verts_len = 3; + if (is_solid) { + ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin); + verts_len += 1; + prim_type = GWN_PRIM_TRI_FAN; + } + else { + prim_type = GWN_PRIM_LINE_STRIP; + } + break; + } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y: + { + rctf r = { + .xmin = -size[0], .xmax = -size[0] + margin[0], + .ymin = size[1] - margin[1], .ymax = size[1], + }; + ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymax); + ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymin); + ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymin); + verts_len = 3; + if (is_solid) { + ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax); + verts_len += 1; + prim_type = GWN_PRIM_TRI_FAN; + } + else { + prim_type = GWN_PRIM_LINE_STRIP; + } + break; + } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y: + { + rctf r = { + .xmin = size[0] - margin[0], .xmax = size[0], + .ymin = -size[1], .ymax = -size[1] + margin[1], + }; + ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin); + ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymax); + ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax); + verts_len = 3; + if (is_solid) { + ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin); + verts_len += 1; + prim_type = GWN_PRIM_TRI_FAN; + } + else { + prim_type = GWN_PRIM_LINE_STRIP; + } + break; + } + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y: + { + rctf r = { + .xmin = size[0] - margin[0], .xmax = size[0], + .ymin = size[1] - margin[1], .ymax = size[1], + }; + ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymax); + ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymin); + ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymin); + verts_len = 3; + if (is_solid) { + ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymax); + verts_len += 1; + prim_type = GWN_PRIM_TRI_FAN; + } + else { + prim_type = GWN_PRIM_LINE_STRIP; + } + break; + } + case ED_MANIPULATOR_CAGE2D_PART_ROTATE: + { + const float rotate_pt[2] = {0.0f, size[1] + margin[1]}; + const rctf r_rotate = { + .xmin = rotate_pt[0] - margin[0] / 2.0f, + .xmax = rotate_pt[0] + margin[0] / 2.0f, + .ymin = rotate_pt[1] - margin[1] / 2.0f, + .ymax = rotate_pt[1] + margin[1] / 2.0f, + }; + + ARRAY_SET_ITEMS(verts[0], r_rotate.xmin, r_rotate.ymin); + ARRAY_SET_ITEMS(verts[1], r_rotate.xmin, r_rotate.ymax); + ARRAY_SET_ITEMS(verts[2], r_rotate.xmax, r_rotate.ymax); + ARRAY_SET_ITEMS(verts[3], r_rotate.xmax, r_rotate.ymin); + verts_len = 4; + if (is_solid) { + prim_type = GWN_PRIM_TRI_FAN; + } + else { + prim_type = GWN_PRIM_LINE_STRIP; + } + break; + } + + case ED_MANIPULATOR_CAGE2D_PART_TRANSLATE: + if (draw_options & ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) { + ARRAY_SET_ITEMS(verts[0], -margin[0] / 2, -margin[1] / 2); + ARRAY_SET_ITEMS(verts[1], margin[0] / 2, margin[1] / 2); + ARRAY_SET_ITEMS(verts[2], -margin[0] / 2, margin[1] / 2); + ARRAY_SET_ITEMS(verts[3], margin[0] / 2, -margin[1] / 2); + verts_len = 4; + if (is_solid) { + prim_type = GWN_PRIM_TRI_FAN; + } + else { + prim_type = GWN_PRIM_LINES; + } + } + else { + /* Only used for 3D view selection, never displayed to the user. */ + ARRAY_SET_ITEMS(verts[0], -size[0], -size[1]); + ARRAY_SET_ITEMS(verts[1], -size[0], size[1]); + ARRAY_SET_ITEMS(verts[2], size[0], size[1]); + ARRAY_SET_ITEMS(verts[3], size[0], -size[1]); + verts_len = 4; + if (is_solid) { + prim_type = GWN_PRIM_TRI_FAN; + } + else { + /* unreachable */ + BLI_assert(0); + prim_type = GWN_PRIM_LINE_STRIP; + } + } + break; + default: + return; + } + + BLI_assert(prim_type != GWN_PRIM_NONE); + + Gwn_VertFormat *format = immVertexFormat(); + struct { + uint pos, col; + } attr_id = { + .pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT), + .col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT), + }; + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + + { + if (is_solid) { + BLI_assert(ELEM(prim_type, GWN_PRIM_TRI_FAN)); + immBegin(prim_type, verts_len); + immAttrib3f(attr_id.col, 0.0f, 0.0f, 0.0f); + for (uint i = 0; i < verts_len; i++) { + immVertex2fv(attr_id.pos, verts[i]); + } + immEnd(); + } + else { + BLI_assert(ELEM(prim_type, GWN_PRIM_LINE_STRIP, GWN_PRIM_LINES)); + glLineWidth(line_width + 3.0f); + + immBegin(prim_type, verts_len); + immAttrib3f(attr_id.col, 0.0f, 0.0f, 0.0f); + for (uint i = 0; i < verts_len; i++) { + immVertex2fv(attr_id.pos, verts[i]); + } + immEnd(); + + glLineWidth(line_width); + + immBegin(prim_type, verts_len); + immAttrib3fv(attr_id.col, color); + for (uint i = 0; i < verts_len; i++) { + immVertex2fv(attr_id.pos, verts[i]); + } + immEnd(); + } + } + + immUnbindProgram(); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Circle Draw Style + * + * Useful for 2D views, see: #ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE + * \{ */ + +static void imm_draw_point_aspect_2d( + uint pos, float x, float y, float rad_x, float rad_y, bool solid) +{ + immBegin(solid ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, 4); + immVertex2f(pos, x - rad_x, y - rad_y); + immVertex2f(pos, x - rad_x, y + rad_y); + immVertex2f(pos, x + rad_x, y + rad_y); + immVertex2f(pos, x + rad_x, y - rad_y); + immEnd(); +} + +static void cage2d_draw_circle_wire( + const rctf *r, const float margin[2], const float color[3], + const int transform_flag, const int draw_options) +{ + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3fv(color); + + immBegin(GWN_PRIM_LINE_LOOP, 4); + immVertex2f(pos, r->xmin, r->ymin); + immVertex2f(pos, r->xmax, r->ymin); + immVertex2f(pos, r->xmax, r->ymax); + immVertex2f(pos, r->xmin, r->ymax); + immEnd(); + + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE) { + immBegin(GWN_PRIM_LINE_LOOP, 2); + immVertex2f(pos, BLI_rctf_cent_x(r), r->ymax); + immVertex2f(pos, BLI_rctf_cent_x(r), r->ymax + margin[1]); + immEnd(); + } + + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) { + if (draw_options & ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) { + const float rad[2] = {margin[0] / 2, margin[1] / 2}; + const float center[2] = {BLI_rctf_cent_x(r), BLI_rctf_cent_y(r)}; + + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, center[0] - rad[0], center[1] - rad[1]); + immVertex2f(pos, center[0] + rad[0], center[1] + rad[1]); + immVertex2f(pos, center[0] + rad[0], center[1] - rad[1]); + immVertex2f(pos, center[0] - rad[0], center[1] + rad[1]); + immEnd(); + } + } + + immUnbindProgram(); +} + +static void cage2d_draw_circle_handles( + const rctf *r, const float margin[2], const float color[3], + const int transform_flag, + bool solid) +{ + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + void (*circle_fn)(uint, float, float, float, float, int) = + (solid) ? imm_draw_circle_fill_aspect_2d : imm_draw_circle_wire_aspect_2d; + const int resolu = 12; + const float rad[2] = {margin[0] / 3, margin[1] / 3}; + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3fv(color); + + /* should really divide by two, but looks too bulky. */ + { + imm_draw_point_aspect_2d(pos, r->xmin, r->ymin, rad[0], rad[1], solid); + imm_draw_point_aspect_2d(pos, r->xmax, r->ymin, rad[0], rad[1], solid); + imm_draw_point_aspect_2d(pos, r->xmax, r->ymax, rad[0], rad[1], solid); + imm_draw_point_aspect_2d(pos, r->xmin, r->ymax, rad[0], rad[1], solid); + } + + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE) { + const float handle[2] = {BLI_rctf_cent_x(r), r->ymax + (margin[1] * MANIPULATOR_MARGIN_OFFSET_SCALE)}; + circle_fn(pos, handle[0], handle[1], rad[0], rad[1], resolu); + } + + immUnbindProgram(); +} + +/** \} */ + +static void manipulator_cage2d_draw_intern( + wmManipulator *mpr, const bool select, const bool highlight, const int select_id) +{ + // const bool use_clamp = (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) == 0; + float dims[2]; + RNA_float_get_array(mpr->ptr, "dimensions", dims); + float matrix_final[4][4]; + + const int transform_flag = RNA_enum_get(mpr->ptr, "transform"); + const int draw_style = RNA_enum_get(mpr->ptr, "draw_style"); + const int draw_options = RNA_enum_get(mpr->ptr, "draw_options"); + + const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f}; + + WM_manipulator_calc_matrix_final(mpr, matrix_final); + + gpuPushMatrix(); + gpuMultMatrix(matrix_final); + + float margin[2]; + manipulator_calc_rect_view_margin(mpr, dims, margin); + + /* Handy for quick testing draw (if it's outside bounds). */ + if (false) { + glEnable(GL_BLEND); + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv((const float[4]){1, 1, 1, 0.5f}); + float s = 0.5f; + immRectf(pos, -s, -s, s, s); + immUnbindProgram(); + glDisable(GL_BLEND); + } + + if (select) { + /* expand for hotspot */ + const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2}; + + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE) { + int scale_parts[] = { + ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X, + ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X, + ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y, + ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y, + + ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y, + ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y, + ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y, + ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y, + }; + for (int i = 0; i < ARRAY_SIZE(scale_parts); i++) { + GPU_select_load_id(select_id | scale_parts[i]); + cage2d_draw_box_interaction( + mpr->color, scale_parts[i], size, margin, mpr->line_width, true, draw_options); + } + } + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) { + const int transform_part = ED_MANIPULATOR_CAGE2D_PART_TRANSLATE; + GPU_select_load_id(select_id | transform_part); + cage2d_draw_box_interaction( + mpr->color, transform_part, size, margin, mpr->line_width, true, draw_options); + } + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE) { + cage2d_draw_box_interaction( + mpr->color, ED_MANIPULATOR_CAGE2D_PART_ROTATE, size_real, margin, mpr->line_width, true, draw_options); + } + } + else { + const rctf r = { + .xmin = -size_real[0], + .ymin = -size_real[1], + .xmax = size_real[0], + .ymax = size_real[1], + }; + if (draw_style == ED_MANIPULATOR_CAGE2D_STYLE_BOX) { + /* corner manipulators */ + glLineWidth(mpr->line_width + 3.0f); + cage2d_draw_box_corners(&r, margin, (const float[3]){0, 0, 0}); + + /* corner manipulators */ + float color[4]; + manipulator_color_get(mpr, highlight, color); + glLineWidth(mpr->line_width); + cage2d_draw_box_corners(&r, margin, color); + + bool show = false; + if (mpr->highlight_part == ED_MANIPULATOR_CAGE2D_PART_TRANSLATE) { + /* Only show if we're drawing the center handle + * otherwise the entire rectangle is the hotspot. */ + if (draw_options & ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) { + show = true; + } + } + else { + show = true; + } + + if (show) { + cage2d_draw_box_interaction( + mpr->color, mpr->highlight_part, size_real, margin, mpr->line_width, false, draw_options); + } + + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE) { + cage2d_draw_box_interaction( + mpr->color, ED_MANIPULATOR_CAGE2D_PART_ROTATE, size_real, margin, mpr->line_width, false, draw_options); + } + } + else if (draw_style == ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE) { + float color[4]; + manipulator_color_get(mpr, highlight, color); + + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + + glLineWidth(mpr->line_width + 3.0f); + cage2d_draw_circle_wire(&r, margin, (const float[3]){0, 0, 0}, transform_flag, draw_options); + glLineWidth(mpr->line_width); + cage2d_draw_circle_wire(&r, margin, color, transform_flag, draw_options); + + + /* corner manipulators */ + cage2d_draw_circle_handles(&r, margin, color, transform_flag, true); + cage2d_draw_circle_handles(&r, margin, (const float[3]){0, 0, 0}, transform_flag, false); + + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); + } + else { + BLI_assert(0); + } + } + + glLineWidth(1.0); + gpuPopMatrix(); +} + +/** + * For when we want to draw 2d cage in 3d views. + */ +static void manipulator_cage2d_draw_select(const bContext *UNUSED(C), wmManipulator *mpr, int select_id) +{ + manipulator_cage2d_draw_intern(mpr, true, false, select_id); +} + +static void manipulator_cage2d_draw(const bContext *UNUSED(C), wmManipulator *mpr) +{ + const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0; + manipulator_cage2d_draw_intern(mpr, false, is_highlight, -1); +} + +static int manipulator_cage2d_get_cursor(wmManipulator *mpr) +{ + int highlight_part = mpr->highlight_part; + + if (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) { + return BC_NSEW_SCROLLCURSOR; + } + + switch (highlight_part) { + case ED_MANIPULATOR_CAGE2D_PART_TRANSLATE: + return BC_HANDCURSOR; + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X: + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X: + return CURSOR_X_MOVE; + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y: + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y: + return CURSOR_Y_MOVE; + + /* TODO diagonal cursor */ + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y: + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y: + return BC_NSEW_SCROLLCURSOR; + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y: + case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y: + return BC_NSEW_SCROLLCURSOR; + case ED_MANIPULATOR_CAGE2D_PART_ROTATE: + return BC_CROSSCURSOR; + default: + return CURSOR_STD; + } +} + +static int manipulator_cage2d_test_select( + bContext *C, wmManipulator *mpr, const wmEvent *event) +{ + float point_local[2]; + float dims[2]; + RNA_float_get_array(mpr->ptr, "dimensions", dims); + const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f}; + + if (manipulator_window_project_2d( + C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, true, point_local) == false) + { + return -1; + } + + float margin[2]; + manipulator_calc_rect_view_margin(mpr, dims, margin); + /* expand for hotspot */ + const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2}; + + const int transform_flag = RNA_enum_get(mpr->ptr, "transform"); + const int draw_options = RNA_enum_get(mpr->ptr, "draw_options"); + + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) { + rctf r; + if (draw_options & ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) { + r.xmin = -margin[0] / 2; + r.ymin = -margin[1] / 2; + r.xmax = margin[0] / 2; + r.ymax = margin[1] / 2; + } + else { + r.xmin = -size[0] + margin[0]; + r.ymin = -size[1] + margin[1]; + r.xmax = size[0] - margin[0]; + r.ymax = size[1] - margin[1]; + }; + bool isect = BLI_rctf_isect_pt_v(&r, point_local); + if (isect) { + return ED_MANIPULATOR_CAGE2D_PART_TRANSLATE; + } + } + + /* if manipulator does not have a scale intersection, don't do it */ + if (transform_flag & (ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM)) { + const rctf r_xmin = {.xmin = -size[0], .ymin = -size[1], .xmax = -size[0] + margin[0], .ymax = size[1]}; + const rctf r_xmax = {.xmin = size[0] - margin[0], .ymin = -size[1], .xmax = size[0], .ymax = size[1]}; + const rctf r_ymin = {.xmin = -size[0], .ymin = -size[1], .xmax = size[0], .ymax = -size[1] + margin[1]}; + const rctf r_ymax = {.xmin = -size[0], .ymin = size[1] - margin[1], .xmax = size[0], .ymax = size[1]}; + + if (BLI_rctf_isect_pt_v(&r_xmin, point_local)) { + if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) { + return ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y; + } + if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) { + return ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y; + } + return ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X; + } + if (BLI_rctf_isect_pt_v(&r_xmax, point_local)) { + if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) { + return ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y; + } + if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) { + return ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y; + } + return ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X; + } + if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) { + return ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y; + } + if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) { + return ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y; + } + } + + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE) { + /* Rotate: + * (*) <-- hot spot is here! + * +---+ + * | | + * +---+ */ + const float r_rotate_pt[2] = {0.0f, size_real[1] + (margin[1] * MANIPULATOR_MARGIN_OFFSET_SCALE)}; + const rctf r_rotate = { + .xmin = r_rotate_pt[0] - margin[0] / 2.0f, + .xmax = r_rotate_pt[0] + margin[0] / 2.0f, + .ymin = r_rotate_pt[1] - margin[1] / 2.0f, + .ymax = r_rotate_pt[1] + margin[1] / 2.0f, + }; + + if (BLI_rctf_isect_pt_v(&r_rotate, point_local)) { + return ED_MANIPULATOR_CAGE2D_PART_ROTATE; + } + } + + return -1; +} + +typedef struct RectTransformInteraction { + float orig_mouse[2]; + float orig_matrix_offset[4][4]; + float orig_matrix_final_no_offset[4][4]; + Dial *dial; +} RectTransformInteraction; + +static void manipulator_cage2d_setup(wmManipulator *mpr) +{ + mpr->flag |= WM_MANIPULATOR_DRAW_MODAL | WM_MANIPULATOR_DRAW_NO_SCALE; +} + +static int manipulator_cage2d_invoke( + bContext *C, wmManipulator *mpr, const wmEvent *event) +{ + RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction), "cage_interaction"); + + copy_m4_m4(data->orig_matrix_offset, mpr->matrix_offset); + manipulator_calc_matrix_final_no_offset(mpr, data->orig_matrix_final_no_offset); + + if (manipulator_window_project_2d( + C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, data->orig_mouse) == 0) + { + zero_v2(data->orig_mouse); + } + + mpr->interaction_data = data; + + return OPERATOR_RUNNING_MODAL; +} + +static int manipulator_cage2d_modal( + bContext *C, wmManipulator *mpr, const wmEvent *event, + eWM_ManipulatorTweak UNUSED(tweak_flag)) +{ + /* For transform logic to be managable we operate in -0.5..0.5 2D space, + * no matter the size of the rectangle, mouse coorts are scaled to unit space. + * The mouse coords have been projected into the matrix so we don't need to worry about axis alignment. + * + * - The cursor offset are multiplied by 'dims'. + * - Matrix translation is also multiplied by 'dims'. + */ + RectTransformInteraction *data = mpr->interaction_data; + float point_local[2]; + + float dims[2]; + RNA_float_get_array(mpr->ptr, "dimensions", dims); + + { + float matrix_back[4][4]; + copy_m4_m4(matrix_back, mpr->matrix_offset); + copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset); + + bool ok = manipulator_window_project_2d( + C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, point_local); + copy_m4_m4(mpr->matrix_offset, matrix_back); + if (!ok) { + return OPERATOR_RUNNING_MODAL; + } + } + + const int transform_flag = RNA_enum_get(mpr->ptr, "transform"); + wmManipulatorProperty *mpr_prop; + + mpr_prop = WM_manipulator_target_property_find(mpr, "matrix"); + if (mpr_prop->type != NULL) { + WM_manipulator_target_property_value_get_array(mpr, mpr_prop, &mpr->matrix_offset[0][0]); + } + + if (mpr->highlight_part == ED_MANIPULATOR_CAGE2D_PART_TRANSLATE) { + /* do this to prevent clamping from changing size */ + copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset); + mpr->matrix_offset[3][0] = data->orig_matrix_offset[3][0] + (point_local[0] - data->orig_mouse[0]); + mpr->matrix_offset[3][1] = data->orig_matrix_offset[3][1] + (point_local[1] - data->orig_mouse[1]); + } + else if (mpr->highlight_part == ED_MANIPULATOR_CAGE2D_PART_ROTATE) { + +#define MUL_V2_V3_M4_FINAL(test_co, mouse_co) \ + mul_v3_m4v3(test_co, data->orig_matrix_final_no_offset, ((const float[3]){UNPACK2(mouse_co), 0.0})) + + float test_co[3]; + + if (data->dial == NULL) { + MUL_V2_V3_M4_FINAL(test_co, data->orig_matrix_offset[3]); + + data->dial = BLI_dial_initialize(test_co, FLT_EPSILON); + + MUL_V2_V3_M4_FINAL(test_co, data->orig_mouse); + BLI_dial_angle(data->dial, test_co); + } + + /* rotate */ + MUL_V2_V3_M4_FINAL(test_co, point_local); + const float angle = BLI_dial_angle(data->dial, test_co); + + float matrix_space_inv[4][4]; + float matrix_rotate[4][4]; + float pivot[3]; + + copy_v3_v3(pivot, data->orig_matrix_offset[3]); + + invert_m4_m4(matrix_space_inv, mpr->matrix_space); + + unit_m4(matrix_rotate); + mul_m4_m4m4(matrix_rotate, matrix_rotate, matrix_space_inv); + rotate_m4(matrix_rotate, 'Z', -angle); + mul_m4_m4m4(matrix_rotate, matrix_rotate, mpr->matrix_space); + + zero_v3(matrix_rotate[3]); + transform_pivot_set_m4(matrix_rotate, pivot); + + mul_m4_m4m4(mpr->matrix_offset, matrix_rotate, data->orig_matrix_offset); + +#undef MUL_V2_V3_M4_FINAL + } + else { + /* scale */ + copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset); + float pivot[2]; + bool constrain_axis[2] = {false}; + + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) { + manipulator_rect_pivot_from_scale_part(mpr->highlight_part, pivot, constrain_axis); + } + else { + zero_v2(pivot); + } + + /* Cursor deltas scaled to (-0.5..0.5). */ + float delta_orig[2], delta_curr[2]; + for (int i = 0; i < 2; i++) { + delta_orig[i] = ((data->orig_mouse[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i]; + delta_curr[i] = ((point_local[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i]; + } + + float scale[2] = {1.0f, 1.0f}; + for (int i = 0; i < 2; i++) { + if (constrain_axis[i] == false) { + if (delta_orig[i] < 0.0f) { + delta_orig[i] *= -1.0f; + delta_curr[i] *= -1.0f; + } + const int sign = signum_i(scale[i]); + + scale[i] = 1.0f + ((delta_curr[i] - delta_orig[i]) / len_v3(data->orig_matrix_offset[i])); + + if ((transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_SIGNED) == 0) { + if (sign != signum_i(scale[i])) { + scale[i] = 0.0f; + } + } + } + } + + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM) { + if (constrain_axis[0] == false && constrain_axis[1] == false) { + scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f; + } + else if (constrain_axis[0] == false) { + scale[1] = scale[0]; + } + else if (constrain_axis[1] == false) { + scale[0] = scale[1]; + } + else { + BLI_assert(0); + } + } + + /* scale around pivot */ + float matrix_scale[4][4]; + unit_m4(matrix_scale); + + mul_v3_fl(matrix_scale[0], scale[0]); + mul_v3_fl(matrix_scale[1], scale[1]); + + transform_pivot_set_m4(matrix_scale, (const float [3]){pivot[0] * dims[0], pivot[1] * dims[1], 0.0f}); + mul_m4_m4m4(mpr->matrix_offset, data->orig_matrix_offset, matrix_scale); + } + + if (mpr_prop->type != NULL) { + WM_manipulator_target_property_value_set_array(C, mpr, mpr_prop, &mpr->matrix_offset[0][0]); + } + + /* tag the region for redraw */ + ED_region_tag_redraw(CTX_wm_region(C)); + WM_event_add_mousemove(C); + + return OPERATOR_RUNNING_MODAL; +} + +static void manipulator_cage2d_property_update(wmManipulator *mpr, wmManipulatorProperty *mpr_prop) +{ + if (STREQ(mpr_prop->type->idname, "matrix")) { + if (WM_manipulator_target_property_array_length(mpr, mpr_prop) == 16) { + WM_manipulator_target_property_value_get_array(mpr, mpr_prop, &mpr->matrix_offset[0][0]); + } + else { + BLI_assert(0); + } + } + else { + BLI_assert(0); + } +} + +static void manipulator_cage2d_exit(bContext *C, wmManipulator *mpr, const bool cancel) +{ + RectTransformInteraction *data = mpr->interaction_data; + + MEM_SAFE_FREE(data->dial); + + if (!cancel) + return; + + wmManipulatorProperty *mpr_prop; + + /* reset properties */ + mpr_prop = WM_manipulator_target_property_find(mpr, "matrix"); + if (mpr_prop->type != NULL) { + WM_manipulator_target_property_value_set_array(C, mpr, mpr_prop, &data->orig_matrix_offset[0][0]); + } + + copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset); +} + + +/* -------------------------------------------------------------------- */ +/** \name Cage Manipulator API + * + * \{ */ + +static void MANIPULATOR_WT_cage_2d(wmManipulatorType *wt) +{ + /* identifiers */ + wt->idname = "MANIPULATOR_WT_cage_2d"; + + /* api callbacks */ + wt->draw = manipulator_cage2d_draw; + wt->draw_select = manipulator_cage2d_draw_select; + wt->test_select = manipulator_cage2d_test_select; + wt->setup = manipulator_cage2d_setup; + wt->invoke = manipulator_cage2d_invoke; + wt->property_update = manipulator_cage2d_property_update; + wt->modal = manipulator_cage2d_modal; + wt->exit = manipulator_cage2d_exit; + wt->cursor_get = manipulator_cage2d_get_cursor; + + wt->struct_size = sizeof(wmManipulator); + + /* rna */ + static EnumPropertyItem rna_enum_draw_style[] = { + {ED_MANIPULATOR_CAGE2D_STYLE_BOX, "BOX", 0, "Box", ""}, + {ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""}, + {0, NULL, 0, NULL, NULL} + }; + static EnumPropertyItem rna_enum_transform[] = { + {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Translate", ""}, + {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE, "ROTATE", 0, "Rotate", ""}, + {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""}, + {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""}, + {0, NULL, 0, NULL, NULL} + }; + static EnumPropertyItem rna_enum_draw_options[] = { + {ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "XFORM_CENTER_HANDLE", 0, "Center Handle", ""}, + {0, NULL, 0, NULL, NULL} + }; + static float unit_v2[2] = {1.0f, 1.0f}; + RNA_def_float_vector(wt->srna, "dimensions", 2, unit_v2, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX); + RNA_def_enum_flag(wt->srna, "transform", rna_enum_transform, 0, "Transform Options", ""); + RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE, "Draw Style", ""); + RNA_def_enum_flag( + wt->srna, "draw_options", rna_enum_draw_options, + ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "Draw Options", ""); + + WM_manipulatortype_target_property_def(wt, "matrix", PROP_FLOAT, 16); +} + +void ED_manipulatortypes_cage_2d(void) +{ + WM_manipulatortype_append(MANIPULATOR_WT_cage_2d); +} + +/** \} */ diff --git a/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c new file mode 100644 index 00000000000..d58cdb4b187 --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c @@ -0,0 +1,735 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file cage3d_manipulator.c + * \ingroup wm + * + * \name Cage Manipulator + * + * 2D Manipulator + * + * \brief Rectangular manipulator acting as a 'cage' around its content. + * Interacting scales or translates the manipulator. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_dial.h" +#include "BLI_rect.h" + +#include "BKE_context.h" + +#include "BIF_gl.h" + +#include "GPU_matrix.h" +#include "GPU_shader.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_select.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_view3d.h" +#include "ED_manipulator_library.h" + +/* own includes */ +#include "../manipulator_library_intern.h" + +#define MANIPULATOR_RESIZER_SIZE 10.0f +#define MANIPULATOR_MARGIN_OFFSET_SCALE 1.5f + +static void manipulator_calc_matrix_final_no_offset( + const wmManipulator *mpr, float orig_matrix_final_no_offset[4][4], bool use_space) +{ + float mat_identity[4][4]; + struct WM_ManipulatorMatrixParams params = {NULL}; + unit_m4(mat_identity); + if (use_space == false) { + params.matrix_basis = mat_identity; + } + params.matrix_offset = mat_identity; + WM_manipulator_calc_matrix_final_params(mpr, ¶ms, orig_matrix_final_no_offset); +} + +static void manipulator_calc_rect_view_scale( + const wmManipulator *mpr, const float dims[3], float scale[3]) +{ + UNUSED_VARS(dims); + + /* Unlike cage2d, no need to correct for aspect. */ + float matrix_final_no_offset[4][4]; + + float x_axis[3], y_axis[3], z_axis[3]; + manipulator_calc_matrix_final_no_offset(mpr, matrix_final_no_offset, false); + mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, mpr->matrix_offset[0]); + mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, mpr->matrix_offset[1]); + mul_v3_mat3_m4v3(z_axis, matrix_final_no_offset, mpr->matrix_offset[2]); + + scale[0] = 1.0f / len_v3(x_axis); + scale[1] = 1.0f / len_v3(y_axis); + scale[2] = 1.0f / len_v3(z_axis); +} + +static void manipulator_calc_rect_view_margin( + const wmManipulator *mpr, const float dims[3], float margin[3]) +{ + float handle_size; + if (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) { + handle_size = 0.15f; + } + else { + handle_size = MANIPULATOR_RESIZER_SIZE; + } + // XXX, the scale isn't taking offset into account, we need to calculate scale per handle! + // handle_size *= mpr->scale_final; + + float scale_xyz[3]; + manipulator_calc_rect_view_scale(mpr, dims, scale_xyz); + margin[0] = ((handle_size * scale_xyz[0])); + margin[1] = ((handle_size * scale_xyz[1])); + margin[2] = ((handle_size * scale_xyz[2])); +} + +/* -------------------------------------------------------------------- */ + +static void manipulator_rect_pivot_from_scale_part(int part, float r_pt[3], bool r_constrain_axis[3]) +{ + if (part >= ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z && + part <= ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z) + { + int index = (part - ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z); + int range[3]; + range[2] = index % 3; + index = index / 3; + range[1] = index % 3; + index = index / 3; + range[0] = index % 3; + + const float sign[3] = {-0.5f, 0.0f, 0.5f}; + for (int i = 0; i < 3; i++) { + r_pt[i] = 0.5 * sign[range[i]]; + r_constrain_axis[i] = (range[i] == 1); + } + } +} + +/* -------------------------------------------------------------------- */ +/** \name Box Draw Style + * + * Useful for 3D views, see: #ED_MANIPULATOR_CAGE2D_STYLE_BOX + * \{ */ + +static void cage3d_draw_box_corners( + const float r[3], const float margin[3], const float color[3]) +{ + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + UNUSED_VARS(margin); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3fv(color); + + imm_draw_cube_wire_3d(pos, (float[3]){0}, r); + + immUnbindProgram(); +} + +static void cage3d_draw_box_interaction( + const float color[4], const int highlighted, + const float size[3], const float margin[3]) +{ + if (highlighted >= ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z && + highlighted <= ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z) + { + int index = (highlighted - ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z); + int range[3]; + range[2] = index % 3; + index = index / 3; + range[1] = index % 3; + index = index / 3; + range[0] = index % 3; + + const float sign[3] = {-1.0f, 0.0f, 1.0f}; + float co[3]; + + for (int i = 0; i < 3; i++) { + co[i] = size[i] * sign[range[i]]; + } + const float rad[3] = {margin[0] / 3, margin[1] / 3, margin[2] / 3}; + + { + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3fv(color); + imm_draw_cube_fill_3d(pos, co, rad); + immUnbindProgram(); + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Circle Draw Style + * + * Useful for 2D views, see: #ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE + * \{ */ + +static void imm_draw_point_aspect_3d( + uint pos, const float co[3], const float rad[3], bool solid) +{ + if (solid) { + imm_draw_cube_fill_3d(pos, co, rad); + } + else { + imm_draw_cube_wire_3d(pos, co, rad); + } +} + +static void cage3d_draw_circle_wire( + const float r[3], const float margin[3], const float color[3], + const int transform_flag, const int draw_options) +{ + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3fv(color); + + imm_draw_cube_wire_3d(pos, (float[3]){0}, r); + +#if 0 + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) { + if (draw_options & ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) { + const float rad[2] = {margin[0] / 2, margin[1] / 2}; + const float center[2] = {0.0f, 0.0f}; + + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, center[0] - rad[0], center[1] - rad[1]); + immVertex2f(pos, center[0] + rad[0], center[1] + rad[1]); + immVertex2f(pos, center[0] + rad[0], center[1] - rad[1]); + immVertex2f(pos, center[0] - rad[0], center[1] + rad[1]); + immEnd(); + } + } +#else + UNUSED_VARS(margin, transform_flag, draw_options); +#endif + + + immUnbindProgram(); +} + +static void cage3d_draw_circle_handles( + const RegionView3D *rv3d, const float matrix_final[4][4], + const float r[3], const float margin[3], const float color[3], + bool solid, float scale) +{ + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + const float rad[3] = {margin[0] / 3, margin[1] / 3, margin[2] / 3}; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3fv(color); + + float sign[3] = {-1.0f, 0.0f, 1.0f}; + for (int x = 0; x < 3; x++) { + for (int y = 0; y < 3; y++) { + for (int z = 0; z < 3; z++) { + if (x == 1 && y == 1 && z == 1) { + continue; + } + const float co[3] = {r[0] * sign[x], r[1] * sign[y], r[2] * sign[z]}; + float co_test[3]; + mul_v3_m4v3(co_test, matrix_final, co); + float rad_scale[3]; + mul_v3_v3fl(rad_scale, rad, ED_view3d_pixel_size(rv3d, co_test) * scale); + imm_draw_point_aspect_3d(pos, co, rad_scale, solid); + } + } + } + + immUnbindProgram(); +} + +/** \} */ + +static void manipulator_cage3d_draw_intern( + RegionView3D *rv3d, + wmManipulator *mpr, const bool select, const bool highlight, const int select_id) +{ + // const bool use_clamp = (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) == 0; + float dims[3]; + RNA_float_get_array(mpr->ptr, "dimensions", dims); + float matrix_final[4][4]; + + const int transform_flag = RNA_enum_get(mpr->ptr, "transform"); + const int draw_style = RNA_enum_get(mpr->ptr, "draw_style"); + const int draw_options = RNA_enum_get(mpr->ptr, "draw_options"); + + const float size_real[3] = {dims[0] / 2.0f, dims[1] / 2.0f, dims[2] / 2.0f}; + + WM_manipulator_calc_matrix_final(mpr, matrix_final); + + gpuPushMatrix(); + gpuMultMatrix(matrix_final); + + float margin[3]; + manipulator_calc_rect_view_margin(mpr, dims, margin); + + /* Handy for quick testing draw (if it's outside bounds). */ + if (false) { + glEnable(GL_BLEND); + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv((const float[4]){1, 1, 1, 0.5f}); + float s = 0.5f; + immRectf(pos, -s, -s, s, s); + immUnbindProgram(); + glDisable(GL_BLEND); + } + + if (select) { + /* expand for hotspot */ +#if 0 + const float size[3] = { + size_real[0] + margin[0] / 2, + size_real[1] + margin[1] / 2, + size_real[2] + margin[2] / 2, + }; +#else + /* just use same value for now. */ + const float size[3] = {UNPACK3(size_real)}; +#endif + + + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE) { + for (int i = ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z; + i <= ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z; + i++) + { + if (i == ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MID_Y_MID_Z) { + continue; + } + GPU_select_load_id(select_id | i); + cage3d_draw_box_interaction( + mpr->color, i, size, margin); + } + } + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) { + const int transform_part = ED_MANIPULATOR_CAGE3D_PART_TRANSLATE; + GPU_select_load_id(select_id | transform_part); + cage3d_draw_box_interaction( + mpr->color, transform_part, size, margin); + } + } + else { +#if 0 + const rctf _r = { + .xmin = -size_real[0], + .ymin = -size_real[1], + .xmax = size_real[0], + .ymax = size_real[1], + }; +#endif + if (draw_style == ED_MANIPULATOR_CAGE2D_STYLE_BOX) { + /* corner manipulators */ + glLineWidth(mpr->line_width + 3.0f); + cage3d_draw_box_corners(size_real, margin, (const float[3]){0, 0, 0}); + + /* corner manipulators */ + float color[4]; + manipulator_color_get(mpr, highlight, color); + glLineWidth(mpr->line_width); + cage3d_draw_box_corners(size_real, margin, color); + + bool show = false; + if (mpr->highlight_part == ED_MANIPULATOR_CAGE3D_PART_TRANSLATE) { + /* Only show if we're drawing the center handle + * otherwise the entire rectangle is the hotspot. */ + if (draw_options & ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) { + show = true; + } + } + else { + show = true; + } + + if (show) { + cage3d_draw_box_interaction( + mpr->color, mpr->highlight_part, size_real, margin); + } + } + else if (draw_style == ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE) { + float color[4]; + manipulator_color_get(mpr, highlight, color); + + glEnable(GL_LINE_SMOOTH); + glEnable(GL_POLYGON_SMOOTH); + glEnable(GL_BLEND); + + glLineWidth(mpr->line_width + 3.0f); + cage3d_draw_circle_wire(size_real, margin, (const float[3]){0, 0, 0}, transform_flag, draw_options); + glLineWidth(mpr->line_width); + cage3d_draw_circle_wire(size_real, margin, color, transform_flag, draw_options); + + /* corner manipulators */ + cage3d_draw_circle_handles(rv3d, matrix_final, size_real, margin, (const float[3]){0, 0, 0}, true, 60); + cage3d_draw_circle_handles(rv3d, matrix_final, size_real, margin, color, true, 40); + + glDisable(GL_BLEND); + glDisable(GL_POLYGON_SMOOTH); + glDisable(GL_LINE_SMOOTH); + } + else { + BLI_assert(0); + } + } + + glLineWidth(1.0); + gpuPopMatrix(); +} + +/** + * For when we want to draw 3d cage in 3d views. + */ +static void manipulator_cage3d_draw_select(const bContext *C, wmManipulator *mpr, int select_id) +{ + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + manipulator_cage3d_draw_intern(rv3d, mpr, true, false, select_id); +} + +static void manipulator_cage3d_draw(const bContext *C, wmManipulator *mpr) +{ + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0; + manipulator_cage3d_draw_intern(rv3d, mpr, false, is_highlight, -1); +} + +static int manipulator_cage3d_get_cursor(wmManipulator *mpr) +{ + if (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) { + return BC_NSEW_SCROLLCURSOR; + } + + return CURSOR_STD; +} + +typedef struct RectTransformInteraction { + float orig_mouse[2]; + float orig_matrix_offset[4][4]; + float orig_matrix_final_no_offset[4][4]; + Dial *dial; +} RectTransformInteraction; + +static void manipulator_cage3d_setup(wmManipulator *mpr) +{ + mpr->flag |= /* WM_MANIPULATOR_DRAW_MODAL | */ /* TODO */ + WM_MANIPULATOR_DRAW_NO_SCALE; +} + +static int manipulator_cage3d_invoke( + bContext *C, wmManipulator *mpr, const wmEvent *event) +{ + RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction), "cage_interaction"); + + copy_m4_m4(data->orig_matrix_offset, mpr->matrix_offset); + manipulator_calc_matrix_final_no_offset(mpr, data->orig_matrix_final_no_offset, true); + + if (manipulator_window_project_2d( + C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, data->orig_mouse) == 0) + { + zero_v2(data->orig_mouse); + } + + mpr->interaction_data = data; + + return OPERATOR_RUNNING_MODAL; +} + +/* XXX. this isn't working properly, for now rely on the modal operators. */ +static int manipulator_cage3d_modal( + bContext *C, wmManipulator *mpr, const wmEvent *event, + eWM_ManipulatorTweak UNUSED(tweak_flag)) +{ + /* For transform logic to be managable we operate in -0.5..0.5 2D space, + * no matter the size of the rectangle, mouse coorts are scaled to unit space. + * The mouse coords have been projected into the matrix so we don't need to worry about axis alignment. + * + * - The cursor offset are multiplied by 'dims'. + * - Matrix translation is also multiplied by 'dims'. + */ + RectTransformInteraction *data = mpr->interaction_data; + float point_local[2]; + + float dims[3]; + RNA_float_get_array(mpr->ptr, "dimensions", dims); + + { + float matrix_back[4][4]; + copy_m4_m4(matrix_back, mpr->matrix_offset); + copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset); + + bool ok = manipulator_window_project_2d( + C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, point_local); + copy_m4_m4(mpr->matrix_offset, matrix_back); + if (!ok) { + return OPERATOR_RUNNING_MODAL; + } + } + + const int transform_flag = RNA_enum_get(mpr->ptr, "transform"); + wmManipulatorProperty *mpr_prop; + + mpr_prop = WM_manipulator_target_property_find(mpr, "matrix"); + if (mpr_prop->type != NULL) { + WM_manipulator_target_property_value_get_array(mpr, mpr_prop, &mpr->matrix_offset[0][0]); + } + + if (mpr->highlight_part == ED_MANIPULATOR_CAGE3D_PART_TRANSLATE) { + /* do this to prevent clamping from changing size */ + copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset); + mpr->matrix_offset[3][0] = data->orig_matrix_offset[3][0] + (point_local[0] - data->orig_mouse[0]); + mpr->matrix_offset[3][1] = data->orig_matrix_offset[3][1] + (point_local[1] - data->orig_mouse[1]); + } + else if (mpr->highlight_part == ED_MANIPULATOR_CAGE3D_PART_ROTATE) { + +#define MUL_V2_V3_M4_FINAL(test_co, mouse_co) \ + mul_v3_m4v3(test_co, data->orig_matrix_final_no_offset, ((const float[3]){UNPACK2(mouse_co), 0.0})) + + float test_co[3]; + + if (data->dial == NULL) { + MUL_V2_V3_M4_FINAL(test_co, data->orig_matrix_offset[3]); + + data->dial = BLI_dial_initialize(test_co, FLT_EPSILON); + + MUL_V2_V3_M4_FINAL(test_co, data->orig_mouse); + BLI_dial_angle(data->dial, test_co); + } + + /* rotate */ + MUL_V2_V3_M4_FINAL(test_co, point_local); + const float angle = BLI_dial_angle(data->dial, test_co); + + float matrix_space_inv[4][4]; + float matrix_rotate[4][4]; + float pivot[3]; + + copy_v3_v3(pivot, data->orig_matrix_offset[3]); + + invert_m4_m4(matrix_space_inv, mpr->matrix_space); + + unit_m4(matrix_rotate); + mul_m4_m4m4(matrix_rotate, matrix_rotate, matrix_space_inv); + rotate_m4(matrix_rotate, 'Z', -angle); + mul_m4_m4m4(matrix_rotate, matrix_rotate, mpr->matrix_space); + + zero_v3(matrix_rotate[3]); + transform_pivot_set_m4(matrix_rotate, pivot); + + mul_m4_m4m4(mpr->matrix_offset, matrix_rotate, data->orig_matrix_offset); + +#undef MUL_V2_V3_M4_FINAL + } + else { + /* scale */ + copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset); + float pivot[3]; + bool constrain_axis[3] = {false}; + + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) { + manipulator_rect_pivot_from_scale_part(mpr->highlight_part, pivot, constrain_axis); + } + else { + zero_v3(pivot); + } + + /* Cursor deltas scaled to (-0.5..0.5). */ + float delta_orig[3], delta_curr[3]; + + delta_orig[2] = 0.0; + delta_curr[2] = 0.0; + + for (int i = 0; i < 2; i++) { + delta_orig[i] = ((data->orig_mouse[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i]; + delta_curr[i] = ((point_local[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i]; + } + + float scale[3] = {1.0f, 1.0f, 1.0f}; + for (int i = 0; i < 3; i++) { + if (constrain_axis[i] == false) { + if (delta_orig[i] < 0.0f) { + delta_orig[i] *= -1.0f; + delta_curr[i] *= -1.0f; + } + const int sign = signum_i(scale[i]); + + scale[i] = 1.0f + ((delta_curr[i] - delta_orig[i]) / len_v3(data->orig_matrix_offset[i])); + + if ((transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_SIGNED) == 0) { + if (sign != signum_i(scale[i])) { + scale[i] = 0.0f; + } + } + } + } + + if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM) { + if (constrain_axis[0] == false && constrain_axis[1] == false) { + scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f; + } + else if (constrain_axis[0] == false) { + scale[1] = scale[0]; + } + else if (constrain_axis[1] == false) { + scale[0] = scale[1]; + } + else { + BLI_assert(0); + } + } + + /* scale around pivot */ + float matrix_scale[4][4]; + unit_m4(matrix_scale); + + mul_v3_fl(matrix_scale[0], scale[0]); + mul_v3_fl(matrix_scale[1], scale[1]); + mul_v3_fl(matrix_scale[2], scale[2]); + + transform_pivot_set_m4( + matrix_scale, + (const float [3]){pivot[0] * dims[0], pivot[1] * dims[1], pivot[2] * dims[2]}); + mul_m4_m4m4(mpr->matrix_offset, data->orig_matrix_offset, matrix_scale); + } + + if (mpr_prop->type != NULL) { + WM_manipulator_target_property_value_set_array(C, mpr, mpr_prop, &mpr->matrix_offset[0][0]); + } + + /* tag the region for redraw */ + ED_region_tag_redraw(CTX_wm_region(C)); + WM_event_add_mousemove(C); + + return OPERATOR_RUNNING_MODAL; +} + +static void manipulator_cage3d_property_update(wmManipulator *mpr, wmManipulatorProperty *mpr_prop) +{ + if (STREQ(mpr_prop->type->idname, "matrix")) { + if (WM_manipulator_target_property_array_length(mpr, mpr_prop) == 16) { + WM_manipulator_target_property_value_get_array(mpr, mpr_prop, &mpr->matrix_offset[0][0]); + } + else { + BLI_assert(0); + } + } + else { + BLI_assert(0); + } +} + +static void manipulator_cage3d_exit(bContext *C, wmManipulator *mpr, const bool cancel) +{ + RectTransformInteraction *data = mpr->interaction_data; + + MEM_SAFE_FREE(data->dial); + + if (!cancel) + return; + + wmManipulatorProperty *mpr_prop; + + /* reset properties */ + mpr_prop = WM_manipulator_target_property_find(mpr, "matrix"); + if (mpr_prop->type != NULL) { + WM_manipulator_target_property_value_set_array(C, mpr, mpr_prop, &data->orig_matrix_offset[0][0]); + } + + copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset); +} + + +/* -------------------------------------------------------------------- */ +/** \name Cage Manipulator API + * + * \{ */ + +static void MANIPULATOR_WT_cage_3d(wmManipulatorType *wt) +{ + /* identifiers */ + wt->idname = "MANIPULATOR_WT_cage_3d"; + + /* api callbacks */ + wt->draw = manipulator_cage3d_draw; + wt->draw_select = manipulator_cage3d_draw_select; + wt->setup = manipulator_cage3d_setup; + wt->invoke = manipulator_cage3d_invoke; + wt->property_update = manipulator_cage3d_property_update; + wt->modal = manipulator_cage3d_modal; + wt->exit = manipulator_cage3d_exit; + wt->cursor_get = manipulator_cage3d_get_cursor; + + wt->struct_size = sizeof(wmManipulator); + + /* rna */ + static EnumPropertyItem rna_enum_draw_style[] = { + {ED_MANIPULATOR_CAGE2D_STYLE_BOX, "BOX", 0, "Box", ""}, + {ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""}, + {0, NULL, 0, NULL, NULL} + }; + static EnumPropertyItem rna_enum_transform[] = { + {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Translate", ""}, + {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""}, + {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""}, + {0, NULL, 0, NULL, NULL} + }; + static EnumPropertyItem rna_enum_draw_options[] = { + {ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "XFORM_CENTER_HANDLE", 0, "Center Handle", ""}, + {0, NULL, 0, NULL, NULL} + }; + static float unit_v3[3] = {1.0f, 1.0f, 1.0f}; + RNA_def_float_vector(wt->srna, "dimensions", 3, unit_v3, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX); + RNA_def_enum_flag(wt->srna, "transform", rna_enum_transform, 0, "Transform Options", ""); + RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE, "Draw Style", ""); + RNA_def_enum_flag( + wt->srna, "draw_options", rna_enum_draw_options, + ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "Draw Options", ""); + + WM_manipulatortype_target_property_def(wt, "matrix", PROP_FLOAT, 16); +} + +void ED_manipulatortypes_cage_3d(void) +{ + WM_manipulatortype_append(MANIPULATOR_WT_cage_3d); +} + +/** \} */ diff --git a/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c new file mode 100644 index 00000000000..f2f5851ff0c --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c @@ -0,0 +1,478 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file dial3d_manipulator.c + * \ingroup wm + * + * \name Dial Manipulator + * + * 3D Manipulator + * + * \brief Circle shaped manipulator for circular interaction. + * Currently no own handling, use with operator only. + * + * - `matrix[0]` is derived from Y and Z. + * - `matrix[1]` is 'up' when DialManipulator.use_start_y_axis is set. + * - `matrix[2]` is the axis the dial rotates around (all dials). + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "BKE_context.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" +#include "GPU_select.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_view3d.h" +#include "ED_manipulator_library.h" + +/* own includes */ +#include "../manipulator_geometry.h" +#include "../manipulator_library_intern.h" + +/* to use custom dials exported to geom_dial_manipulator.c */ +// #define USE_MANIPULATOR_CUSTOM_DIAL + +static int manipulator_dial_modal( + bContext *C, wmManipulator *mpr, const wmEvent *event, + eWM_ManipulatorTweak tweak_flag); + +typedef struct DialInteraction { + float init_mval[2]; + + /* only for when using properties */ + float init_prop_angle; + + /* cache the last angle to detect rotations bigger than -/+ PI */ + float last_angle; + /* number of full rotations */ + int rotations; + + /* final output values, used for drawing */ + struct { + float angle_ofs; + float angle_delta; + } output; +} DialInteraction; + +#define DIAL_WIDTH 1.0f +#define DIAL_RESOLUTION 32 + +/** + * We can't use this for the #wmManipulatorType.matrix_basis_get callback, it conflicts with depth picking. + */ +static void dial_calc_matrix(const wmManipulator *mpr, float mat[4][4]) +{ + float rot[3][3]; + const float up[3] = {0.0f, 0.0f, 1.0f}; + + rotation_between_vecs_to_mat3(rot, up, mpr->matrix_basis[2]); + copy_m4_m3(mat, rot); + copy_v3_v3(mat[3], mpr->matrix_basis[3]); +} + +/* -------------------------------------------------------------------- */ + +static void dial_geom_draw( + const wmManipulator *mpr, const float color[4], const bool select, + float axis_modal_mat[4][4], float clip_plane[4]) +{ +#ifdef USE_MANIPULATOR_CUSTOM_DIAL + UNUSED_VARS(dial, col, axis_modal_mat, clip_plane); + wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_dial, select); +#else + const int draw_options = RNA_enum_get(mpr->ptr, "draw_options"); + const bool filled = (draw_options & ED_MANIPULATOR_DIAL_DRAW_FLAG_FILL) != 0; + + glLineWidth(mpr->line_width); + + Gwn_VertFormat *format = immVertexFormat(); + uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + if (clip_plane) { + immBindBuiltinProgram(GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR); + float clip_plane_f[4] = {clip_plane[0], clip_plane[1], clip_plane[2], clip_plane[3]}; + immUniform4fv("ClipPlane", clip_plane_f); + immUniformMatrix4fv("ModelMatrix", axis_modal_mat); + } + else { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + } + + immUniformColor4fv(color); + + if (filled) { + imm_draw_circle_fill_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION); + } + else { + imm_draw_circle_wire_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION); + } + + immUnbindProgram(); + + UNUSED_VARS(select); +#endif +} + +/** + * Draws a line from (0, 0, 0) to \a co_outer, at \a angle. + */ +static void dial_ghostarc_draw_helpline(const float angle, const float co_outer[3], const float color[4]) +{ + glLineWidth(1.0f); + + gpuPushMatrix(); + gpuRotate3f(RAD2DEGF(angle), 0.0f, 0.0f, -1.0f); + + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + immUniformColor4fv(color); + + immBegin(GWN_PRIM_LINE_STRIP, 2); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immVertex3fv(pos, co_outer); + immEnd(); + + immUnbindProgram(); + + gpuPopMatrix(); +} + +static void dial_ghostarc_draw( + const wmManipulator *mpr, const float angle_ofs, const float angle_delta, const float color[4]) +{ + const float width_inner = DIAL_WIDTH - mpr->line_width * 0.5f / U.manipulator_size; + + Gwn_VertFormat *format = immVertexFormat(); + uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(color); + imm_draw_disk_partial_fill_2d( + pos, 0, 0, 0.0, width_inner, DIAL_RESOLUTION, RAD2DEGF(angle_ofs), RAD2DEGF(angle_delta)); + immUnbindProgram(); +} + +static void dial_ghostarc_get_angles( + const wmManipulator *mpr, + const wmEvent *event, + const ARegion *ar, const View3D *v3d, + float mat[4][4], const float co_outer[3], + float *r_start, float *r_delta) +{ + DialInteraction *inter = mpr->interaction_data; + const RegionView3D *rv3d = ar->regiondata; + const float mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin}; + + /* we might need to invert the direction of the angles */ + float view_vec[3], axis_vec[3]; + ED_view3d_global_to_vector(rv3d, mpr->matrix_basis[3], view_vec); + normalize_v3_v3(axis_vec, mpr->matrix_basis[2]); + + float proj_outer_rel[3]; + mul_v3_project_m4_v3(proj_outer_rel, mat, co_outer); + sub_v3_v3(proj_outer_rel, mpr->matrix_basis[3]); + + float proj_mval_new_rel[3]; + float proj_mval_init_rel[3]; + float dial_plane[4]; + float ray_co[3], ray_no[3]; + float ray_lambda; + + plane_from_point_normal_v3(dial_plane, mpr->matrix_basis[3], axis_vec); + + if (!ED_view3d_win_to_ray(ar, v3d, inter->init_mval, ray_co, ray_no, false) || + !isect_ray_plane_v3(ray_co, ray_no, dial_plane, &ray_lambda, false)) + { + goto fail; + } + madd_v3_v3v3fl(proj_mval_init_rel, ray_co, ray_no, ray_lambda); + sub_v3_v3(proj_mval_init_rel, mpr->matrix_basis[3]); + + if (!ED_view3d_win_to_ray(ar, v3d, mval, ray_co, ray_no, false) || + !isect_ray_plane_v3(ray_co, ray_no, dial_plane, &ray_lambda, false)) + { + goto fail; + } + madd_v3_v3v3fl(proj_mval_new_rel, ray_co, ray_no, ray_lambda); + sub_v3_v3(proj_mval_new_rel, mpr->matrix_basis[3]); + + const int draw_options = RNA_enum_get(mpr->ptr, "draw_options"); + + /* Start direction from mouse or set by user */ + const float *proj_init_rel = + (draw_options & ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_START_Y) ? + mpr->matrix_basis[1] : proj_mval_init_rel; + + /* return angles */ + const float start = angle_wrap_rad(angle_signed_on_axis_v3v3_v3(proj_outer_rel, proj_init_rel, axis_vec)); + const float delta = angle_wrap_rad(angle_signed_on_axis_v3v3_v3(proj_mval_init_rel, proj_mval_new_rel, axis_vec)); + + /* Change of sign, we passed the 180 degree threshold. This means we need to add a turn + * to distinguish between transition from 0 to -1 and -PI to +PI, use comparison with PI/2. + * Logic taken from BLI_dial_angle */ + if ((delta * inter->last_angle < 0.0f) && + (fabsf(inter->last_angle) > (float)M_PI_2)) + { + if (inter->last_angle < 0.0f) + inter->rotations--; + else + inter->rotations++; + } + inter->last_angle = delta; + + *r_start = start; + *r_delta = fmod(delta + 2.0f * (float)M_PI * inter->rotations, 2 * (float)M_PI); + return; + + /* If we can't project (unlikely). */ +fail: + *r_start = 0.0; + *r_delta = 0.0; +} + +static void dial_draw_intern( + const bContext *C, wmManipulator *mpr, + const bool select, const bool highlight, float clip_plane[4]) +{ + float matrix_basis_adjust[4][4]; + float matrix_final[4][4]; + float color[4]; + + BLI_assert(CTX_wm_area(C)->spacetype == SPACE_VIEW3D); + + manipulator_color_get(mpr, highlight, color); + + dial_calc_matrix(mpr, matrix_basis_adjust); + + WM_manipulator_calc_matrix_final_params( + mpr, &((struct WM_ManipulatorMatrixParams) { + .matrix_basis = (void *)matrix_basis_adjust, + }), matrix_final); + + gpuPushMatrix(); + gpuMultMatrix(matrix_final); + + /* draw rotation indicator arc first */ + if ((mpr->flag & WM_MANIPULATOR_DRAW_VALUE) && + (mpr->state & WM_MANIPULATOR_STATE_MODAL)) + { + const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f}; /* coordinate at which the arc drawing will be started */ + + DialInteraction *inter = mpr->interaction_data; + + /* XXX, View3D rotation manipulator doesn't call modal. */ + if (!WM_manipulator_target_property_is_valid_any(mpr)) { + wmWindow *win = CTX_wm_window(C); + manipulator_dial_modal((bContext *)C, mpr, win->eventstate, 0); + } + + float angle_ofs = inter->output.angle_ofs; + float angle_delta = inter->output.angle_delta; + + /* draw! */ + for (int i = 0; i < 2; i++) { + dial_ghostarc_draw(mpr, angle_ofs, angle_delta, (const float [4]){0.8f, 0.8f, 0.8f, 0.4f}); + + dial_ghostarc_draw_helpline(angle_ofs, co_outer, color); /* starting position */ + dial_ghostarc_draw_helpline(angle_ofs + angle_delta, co_outer, color); /* starting position + current value */ + + if (i == 0) { + const int draw_options = RNA_enum_get(mpr->ptr, "draw_options"); + if ((draw_options & ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_MIRROR) == 0) { + break; + } + } + + angle_ofs += (float)M_PI; + } + } + + /* draw actual dial manipulator */ + dial_geom_draw(mpr, color, select, matrix_basis_adjust, clip_plane); + + gpuPopMatrix(); +} + +static void manipulator_dial_draw_select(const bContext *C, wmManipulator *mpr, int select_id) +{ + float clip_plane_buf[4]; + const int draw_options = RNA_enum_get(mpr->ptr, "draw_options"); + float *clip_plane = (draw_options & ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP) ? clip_plane_buf : NULL; + + /* enable clipping if needed */ + if (clip_plane) { + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + + copy_v3_v3(clip_plane, rv3d->viewinv[2]); + clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]); + glEnable(GL_CLIP_DISTANCE0); + } + + GPU_select_load_id(select_id); + dial_draw_intern(C, mpr, true, false, clip_plane); + + if (clip_plane) { + glDisable(GL_CLIP_DISTANCE0); + } +} + +static void manipulator_dial_draw(const bContext *C, wmManipulator *mpr) +{ + const bool is_modal = mpr->state & WM_MANIPULATOR_STATE_MODAL; + const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0; + float clip_plane_buf[4]; + const int draw_options = RNA_enum_get(mpr->ptr, "draw_options"); + float *clip_plane = (!is_modal && (draw_options & ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP)) ? clip_plane_buf : NULL; + + /* enable clipping if needed */ + if (clip_plane) { + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + + copy_v3_v3(clip_plane, rv3d->viewinv[2]); + clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]); + clip_plane[3] -= 0.02f * mpr->scale_final; + + glEnable(GL_CLIP_DISTANCE0); + } + + glEnable(GL_BLEND); + dial_draw_intern(C, mpr, false, is_highlight, clip_plane); + glDisable(GL_BLEND); + + if (clip_plane) { + glDisable(GL_CLIP_DISTANCE0); + } +} + +static int manipulator_dial_modal( + bContext *C, wmManipulator *mpr, const wmEvent *event, + eWM_ManipulatorTweak UNUSED(tweak_flag)) +{ + const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f}; /* coordinate at which the arc drawing will be started */ + float angle_ofs, angle_delta; + + float matrix[4][4]; + + dial_calc_matrix(mpr, matrix); + + dial_ghostarc_get_angles( + mpr, event, CTX_wm_region(C), CTX_wm_view3d(C), matrix, co_outer, &angle_ofs, &angle_delta); + + DialInteraction *inter = mpr->interaction_data; + + inter->output.angle_delta = angle_delta; + inter->output.angle_ofs = angle_ofs; + + /* set the property for the operator and call its modal function */ + wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset"); + if (WM_manipulator_target_property_is_valid(mpr_prop)) { + WM_manipulator_target_property_value_set(C, mpr, mpr_prop, inter->init_prop_angle + angle_delta); + } + return OPERATOR_RUNNING_MODAL; +} + + +static void manipulator_dial_setup(wmManipulator *mpr) +{ + const float dir_default[3] = {0.0f, 0.0f, 1.0f}; + + /* defaults */ + copy_v3_v3(mpr->matrix_basis[2], dir_default); +} + +static int manipulator_dial_invoke( + bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event) +{ + DialInteraction *inter = MEM_callocN(sizeof(DialInteraction), __func__); + + inter->init_mval[0] = event->mval[0]; + inter->init_mval[1] = event->mval[1]; + + wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset"); + if (WM_manipulator_target_property_is_valid(mpr_prop)) { + inter->init_prop_angle = WM_manipulator_target_property_value_get(mpr, mpr_prop); + } + + mpr->interaction_data = inter; + + return OPERATOR_RUNNING_MODAL; +} + +/* -------------------------------------------------------------------- */ +/** \name Dial Manipulator API + * + * \{ */ + +static void MANIPULATOR_WT_dial_3d(wmManipulatorType *wt) +{ + /* identifiers */ + wt->idname = "MANIPULATOR_WT_dial_3d"; + + /* api callbacks */ + wt->draw = manipulator_dial_draw; + wt->draw_select = manipulator_dial_draw_select; + wt->setup = manipulator_dial_setup; + wt->invoke = manipulator_dial_invoke; + wt->modal = manipulator_dial_modal; + + wt->struct_size = sizeof(wmManipulator); + + /* rna */ + static EnumPropertyItem rna_enum_draw_options[] = { + {ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP, "CLIP", 0, "Clipped", ""}, + {ED_MANIPULATOR_DIAL_DRAW_FLAG_FILL, "FILL", 0, "Filled", ""}, + {ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_MIRROR, "ANGLE_MIRROR", 0, "Angle Mirror", ""}, + {ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_START_Y, "ANGLE_START_Y", 0, "Angle Start Y", ""}, + {0, NULL, 0, NULL, NULL} + }; + RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", ""); + + WM_manipulatortype_target_property_def(wt, "offset", PROP_FLOAT, 1); +} + +void ED_manipulatortypes_dial_3d(void) +{ + WM_manipulatortype_append(MANIPULATOR_WT_dial_3d); +} + +/** \} */ diff --git a/source/blender/editors/manipulator_library/manipulator_types/grab3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/grab3d_manipulator.c new file mode 100644 index 00000000000..151e173e5e6 --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_types/grab3d_manipulator.c @@ -0,0 +1,373 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file grab3d_manipulator.c + * \ingroup wm + * + * \name Grab Manipulator + * + * 3D Manipulator, also works in 2D views. + * + * \brief Simple manipulator to grab and translate. + * + * - `matrix[0]` is derived from Y and Z. + * - `matrix[1]` currently not used. + * - `matrix[2]` is the widget direction (for all manipulators). + * + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "BKE_context.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" +#include "GPU_select.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_view3d.h" +#include "ED_manipulator_library.h" + +/* own includes */ +#include "../manipulator_geometry.h" +#include "../manipulator_library_intern.h" + +typedef struct GrabManipulator3D { + wmManipulator manipulator; + /* Added to 'matrix_basis' when calculating the matrix. */ + float prop_co[3]; +} GrabManipulator3D; + +static void manipulator_grab_matrix_basis_get(const wmManipulator *mpr, float r_matrix[4][4]) +{ + GrabManipulator3D *grab = (GrabManipulator3D *)mpr; + + copy_m4_m4(r_matrix, grab->manipulator.matrix_basis); + add_v3_v3(r_matrix[3], grab->prop_co); +} + +static int manipulator_grab_modal( + bContext *C, wmManipulator *mpr, const wmEvent *event, + eWM_ManipulatorTweak tweak_flag); + +typedef struct GrabInteraction { + float init_mval[2]; + + /* only for when using properties */ + float init_prop_co[3]; + + float init_matrix_final[4][4]; +} GrabInteraction; + +#define DIAL_RESOLUTION 32 + +/* -------------------------------------------------------------------- */ + +static void grab_geom_draw( + const wmManipulator *mpr, const float color[4], const bool select, const int draw_options) +{ +#ifdef USE_MANIPULATOR_CUSTOM_DIAL + UNUSED_VARS(grab3d, col, axis_modal_mat); + wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_grab3d, select); +#else + const int draw_style = RNA_enum_get(mpr->ptr, "draw_style"); + const bool filled = (draw_options & ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL) != 0; + + glLineWidth(mpr->line_width); + + Gwn_VertFormat *format = immVertexFormat(); + uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + immUniformColor4fv(color); + + if (draw_style == ED_MANIPULATOR_GRAB_STYLE_RING_2D) { + if (filled) { + imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, DIAL_RESOLUTION); + } + else { + imm_draw_circle_wire_2d(pos, 0, 0, 1.0f, DIAL_RESOLUTION); + } + } + else if (draw_style == ED_MANIPULATOR_GRAB_STYLE_CROSS_2D) { + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, 1.0f, 1.0f); + immVertex2f(pos, -1.0f, -1.0f); + + immVertex2f(pos, -1.0f, 1.0f); + immVertex2f(pos, 1.0f, -1.0f); + immEnd(); + } + else { + BLI_assert(0); + } + + immUnbindProgram(); + + UNUSED_VARS(select); +#endif +} + +static void grab3d_get_translate( + const wmManipulator *mpr, const wmEvent *event, const ARegion *ar, + float co_delta[3]) +{ + GrabInteraction *inter = mpr->interaction_data; + const float mval_delta[2] = { + event->mval[0] - inter->init_mval[0], + event->mval[1] - inter->init_mval[1], + }; + + RegionView3D *rv3d = ar->regiondata; + float co_ref[3]; + mul_v3_mat3_m4v3(co_ref, mpr->matrix_space, inter->init_prop_co); + const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL); + + ED_view3d_win_to_delta(ar, mval_delta, co_delta, zfac); + + float matrix_space_inv[3][3]; + copy_m3_m4(matrix_space_inv, mpr->matrix_space); + invert_m3(matrix_space_inv); + mul_m3_v3(matrix_space_inv, co_delta); +} + +static void grab3d_draw_intern( + const bContext *C, wmManipulator *mpr, + const bool select, const bool highlight) +{ + GrabInteraction *inter = mpr->interaction_data; + const int draw_options = RNA_enum_get(mpr->ptr, "draw_options"); + const bool align_view = (draw_options & ED_MANIPULATOR_GRAB_DRAW_FLAG_ALIGN_VIEW) != 0; + float color[4]; + float matrix_final[4][4]; + float matrix_align[4][4]; + + manipulator_color_get(mpr, highlight, color); + WM_manipulator_calc_matrix_final(mpr, matrix_final); + + gpuPushMatrix(); + gpuMultMatrix(matrix_final); + + if (align_view) { + float matrix_final_unit[4][4]; + RegionView3D *rv3d = CTX_wm_region_view3d(C); + normalize_m4_m4(matrix_final_unit, matrix_final); + mul_m4_m4m4(matrix_align, rv3d->viewmat, matrix_final_unit); + zero_v3(matrix_align[3]); + transpose_m4(matrix_align); + gpuMultMatrix(matrix_align); + } + + glEnable(GL_BLEND); + grab_geom_draw(mpr, color, select, draw_options); + glDisable(GL_BLEND); + gpuPopMatrix(); + + if (mpr->interaction_data) { + gpuPushMatrix(); + gpuMultMatrix(inter->init_matrix_final); + + if (align_view) { + gpuMultMatrix(matrix_align); + } + + glEnable(GL_BLEND); + grab_geom_draw(mpr, (const float [4]){0.5f, 0.5f, 0.5f, 0.5f}, select, draw_options); + glDisable(GL_BLEND); + gpuPopMatrix(); + } +} + +static void manipulator_grab_draw_select(const bContext *C, wmManipulator *mpr, int select_id) +{ + GPU_select_load_id(select_id); + grab3d_draw_intern(C, mpr, true, false); +} + +static void manipulator_grab_draw(const bContext *C, wmManipulator *mpr) +{ + const bool is_modal = mpr->state & WM_MANIPULATOR_STATE_MODAL; + const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0; + + (void)is_modal; + + glEnable(GL_BLEND); + grab3d_draw_intern(C, mpr, false, is_highlight); + glDisable(GL_BLEND); +} + +static int manipulator_grab_modal( + bContext *C, wmManipulator *mpr, const wmEvent *event, + eWM_ManipulatorTweak UNUSED(tweak_flag)) +{ + GrabManipulator3D *grab = (GrabManipulator3D *)mpr; + GrabInteraction *inter = mpr->interaction_data; + ARegion *ar = CTX_wm_region(C); + + float prop_delta[3]; + if (CTX_wm_area(C)->spacetype == SPACE_VIEW3D) { + grab3d_get_translate(mpr, event, ar, prop_delta); + } + else { + float mval_proj_init[2], mval_proj_curr[2]; + if ((manipulator_window_project_2d( + C, mpr, inter->init_mval, 2, false, mval_proj_init) == false) || + (manipulator_window_project_2d( + C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, mval_proj_curr) == false)) + { + return OPERATOR_RUNNING_MODAL; + } + sub_v2_v2v2(prop_delta, mval_proj_curr, mval_proj_init); + prop_delta[2] = 0.0f; + } + add_v3_v3v3(grab->prop_co, inter->init_prop_co, prop_delta); + + /* set the property for the operator and call its modal function */ + wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset"); + if (WM_manipulator_target_property_is_valid(mpr_prop)) { + WM_manipulator_target_property_value_set_array(C, mpr, mpr_prop, grab->prop_co); + } + else { + zero_v3(grab->prop_co); + } + + ED_region_tag_redraw(ar); + + return OPERATOR_RUNNING_MODAL; +} + +static int manipulator_grab_invoke( + bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event) +{ + GrabInteraction *inter = MEM_callocN(sizeof(GrabInteraction), __func__); + + inter->init_mval[0] = event->mval[0]; + inter->init_mval[1] = event->mval[1]; + +#if 0 + copy_v3_v3(inter->init_prop_co, grab->prop_co); +#else + wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset"); + if (WM_manipulator_target_property_is_valid(mpr_prop)) { + WM_manipulator_target_property_value_get_array(mpr, mpr_prop, inter->init_prop_co); + } +#endif + + WM_manipulator_calc_matrix_final(mpr, inter->init_matrix_final); + + mpr->interaction_data = inter; + + return OPERATOR_RUNNING_MODAL; +} + + +static int manipulator_grab_test_select( + bContext *C, wmManipulator *mpr, const wmEvent *event) +{ + float point_local[2]; + + if (manipulator_window_project_2d( + C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, true, point_local) == false) + { + return -1; + } + + if (len_squared_v2(point_local) < SQUARE(mpr->scale_final)) { + return 0; + } + + return -1; +} + +static void manipulator_grab_property_update(wmManipulator *mpr, wmManipulatorProperty *mpr_prop) +{ + GrabManipulator3D *grab = (GrabManipulator3D *)mpr; + if (WM_manipulator_target_property_is_valid(mpr_prop)) { + WM_manipulator_target_property_value_get_array(mpr, mpr_prop, grab->prop_co); + } + else { + zero_v3(grab->prop_co); + } +} + +static int manipulator_grab_cursor_get(wmManipulator *UNUSED(mpr)) +{ + return BC_HANDCURSOR; +} + +/* -------------------------------------------------------------------- */ +/** \name Grab Manipulator API + * + * \{ */ + +static void MANIPULATOR_WT_grab_3d(wmManipulatorType *wt) +{ + /* identifiers */ + wt->idname = "MANIPULATOR_WT_grab_3d"; + + /* api callbacks */ + wt->draw = manipulator_grab_draw; + wt->draw_select = manipulator_grab_draw_select; + wt->test_select = manipulator_grab_test_select; + wt->matrix_basis_get = manipulator_grab_matrix_basis_get; + wt->invoke = manipulator_grab_invoke; + wt->property_update = manipulator_grab_property_update; + wt->modal = manipulator_grab_modal; + wt->cursor_get = manipulator_grab_cursor_get; + + wt->struct_size = sizeof(GrabManipulator3D); + + /* rna */ + static EnumPropertyItem rna_enum_draw_style[] = { + {ED_MANIPULATOR_GRAB_STYLE_RING_2D, "RING_2D", 0, "Ring", ""}, + {ED_MANIPULATOR_GRAB_STYLE_CROSS_2D, "CROSS_2D", 0, "Ring", ""}, + {0, NULL, 0, NULL, NULL} + }; + static EnumPropertyItem rna_enum_draw_options[] = { + {ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL, "FILL", 0, "Filled", ""}, + {ED_MANIPULATOR_GRAB_DRAW_FLAG_ALIGN_VIEW, "ALIGN_VIEW", 0, "Align View", ""}, + {0, NULL, 0, NULL, NULL} + }; + + RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_GRAB_STYLE_RING_2D, "Draw Style", ""); + RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", ""); + + WM_manipulatortype_target_property_def(wt, "offset", PROP_FLOAT, 3); +} + +void ED_manipulatortypes_grab_3d(void) +{ + WM_manipulatortype_append(MANIPULATOR_WT_grab_3d); +} + +/** \} */ // Grab Manipulator API diff --git a/source/blender/editors/manipulator_library/manipulator_types/primitive3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/primitive3d_manipulator.c new file mode 100644 index 00000000000..531cf742e6f --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_types/primitive3d_manipulator.c @@ -0,0 +1,190 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file primitive3d_manipulator.c + * \ingroup wm + * + * \name Primitive Manipulator + * + * 3D Manipulator + * + * \brief Manipulator with primitive drawing type (plane, cube, etc.). + * Currently only plane primitive supported without own handling, use with operator only. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "DNA_view3d_types.h" + +#include "BKE_context.h" + +#include "BIF_gl.h" + +#include "GPU_immediate.h" +#include "GPU_matrix.h" +#include "GPU_select.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_manipulator_library.h" + +/* own includes */ +#include "../manipulator_library_intern.h" + +static float verts_plane[4][3] = { + {-1, -1, 0}, + { 1, -1, 0}, + { 1, 1, 0}, + {-1, 1, 0}, +}; + + +/* -------------------------------------------------------------------- */ + +static void manipulator_primitive_draw_geom( + const float col_inner[4], const float col_outer[4], const int draw_style) +{ + float (*verts)[3]; + uint vert_count = 0; + + if (draw_style == ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE) { + verts = verts_plane; + vert_count = ARRAY_SIZE(verts_plane); + } + + if (vert_count > 0) { + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + wm_manipulator_vec_draw(col_inner, verts, vert_count, pos, GWN_PRIM_TRI_FAN); + wm_manipulator_vec_draw(col_outer, verts, vert_count, pos, GWN_PRIM_LINE_LOOP); + immUnbindProgram(); + } +} + +static void manipulator_primitive_draw_intern( + wmManipulator *mpr, const bool UNUSED(select), + const bool highlight) +{ + float color_inner[4], color_outer[4]; + float matrix_final[4][4]; + const int draw_style = RNA_enum_get(mpr->ptr, "draw_style"); + + manipulator_color_get(mpr, highlight, color_outer); + copy_v4_v4(color_inner, color_outer); + color_inner[3] *= 0.5f; + + WM_manipulator_calc_matrix_final(mpr, matrix_final); + + gpuPushMatrix(); + gpuMultMatrix(matrix_final); + + glEnable(GL_BLEND); + manipulator_primitive_draw_geom(color_inner, color_outer, draw_style); + glDisable(GL_BLEND); + + gpuPopMatrix(); + + if (mpr->interaction_data) { + ManipulatorInteraction *inter = mpr->interaction_data; + + copy_v4_fl(color_inner, 0.5f); + copy_v3_fl(color_outer, 0.5f); + color_outer[3] = 0.8f; + + gpuPushMatrix(); + gpuMultMatrix(inter->init_matrix_final); + + glEnable(GL_BLEND); + manipulator_primitive_draw_geom(color_inner, color_outer, draw_style); + glDisable(GL_BLEND); + + gpuPopMatrix(); + } +} + +static void manipulator_primitive_draw_select( + const bContext *UNUSED(C), wmManipulator *mpr, + int select_id) +{ + GPU_select_load_id(select_id); + manipulator_primitive_draw_intern(mpr, true, false); +} + +static void manipulator_primitive_draw(const bContext *UNUSED(C), wmManipulator *mpr) +{ + manipulator_primitive_draw_intern( + mpr, false, + (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT)); +} + +static void manipulator_primitive_setup(wmManipulator *mpr) +{ + mpr->flag |= WM_MANIPULATOR_DRAW_MODAL; +} + +static int manipulator_primitive_invoke( + bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *UNUSED(event)) +{ + ManipulatorInteraction *inter = MEM_callocN(sizeof(ManipulatorInteraction), __func__); + + WM_manipulator_calc_matrix_final(mpr, inter->init_matrix_final); + + mpr->interaction_data = inter; + + return OPERATOR_RUNNING_MODAL; +} + +/* -------------------------------------------------------------------- */ +/** \name Primitive Manipulator API + * + * \{ */ + +static void MANIPULATOR_WT_primitive_3d(wmManipulatorType *wt) +{ + /* identifiers */ + wt->idname = "MANIPULATOR_WT_primitive_3d"; + + /* api callbacks */ + wt->draw = manipulator_primitive_draw; + wt->draw_select = manipulator_primitive_draw_select; + wt->setup = manipulator_primitive_setup; + wt->invoke = manipulator_primitive_invoke; + + wt->struct_size = sizeof(wmManipulator); + + static EnumPropertyItem rna_enum_draw_style[] = { + {ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE, "PLANE", 0, "Plane", ""}, + {0, NULL, 0, NULL, NULL} + }; + RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE, "Draw Style", ""); +} + +void ED_manipulatortypes_primitive_3d(void) +{ + WM_manipulatortype_append(MANIPULATOR_WT_primitive_3d); +} + +/** \} */ diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt index 033d034cf4e..d17df344dc9 100644 --- a/source/blender/editors/mask/CMakeLists.txt +++ b/source/blender/editors/mask/CMakeLists.txt @@ -25,6 +25,7 @@ set(INC ../include ../../blenkernel ../../blenlib + ../../depsgraph ../../gpu ../../makesdna ../../makesrna diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 69335195b96..ad1a567f843 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -34,9 +34,10 @@ #include "BLI_math.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_mask.h" +#include "DEG_depsgraph.h" + #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_mask_types.h" @@ -692,7 +693,7 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); - DAG_id_tag_update(&mask->id, 0); + DEG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index be7eb2bf9ed..6ed1c021c6c 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -36,6 +36,7 @@ #include "BLI_math.h" #include "BLI_rect.h" #include "BLI_task.h" +#include "BLI_listbase.h" #include "BKE_context.h" #include "BKE_mask.h" @@ -48,10 +49,13 @@ #include "ED_clip.h" #include "ED_mask.h" /* own include */ #include "ED_space_api.h" -#include "BIF_gl.h" + #include "BIF_glutil.h" -#include "GPU_basic_shader.h" +#include "GPU_immediate.h" +#include "GPU_draw.h" +#include "GPU_shader.h" +#include "GPU_matrix.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -93,40 +97,6 @@ static void mask_spline_feather_color_get(MaskLayer *UNUSED(masklay), MaskSpline r_rgb[3] = 255; } -#if 0 -static void draw_spline_parents(MaskLayer *UNUSED(masklay), MaskSpline *spline) -{ - int i; - MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); - - if (!spline->tot_point) - return; - - GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); - GPU_basic_shader_line_stipple(1, 0xAAAA); - - glColor3ub(0, 0, 0); - glBegin(GL_LINES); - - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &points_array[i]; - BezTriple *bezt = &point->bezt; - - if (point->parent.id) { - glVertex2f(bezt->vec[1][0], - bezt->vec[1][1]); - - glVertex2f(bezt->vec[1][0] - point->parent.offset[0], - bezt->vec[1][1] - point->parent.offset[1]); - } - } - - glEnd(); - - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); -} -#endif - static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float co[2]) { BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co); @@ -134,46 +104,9 @@ static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float c BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co); } -static void draw_circle(const float x, const float y, - const float size, const bool fill, - const float xscale, const float yscale) -{ - static GLuint wire_displist = 0; - static GLuint fill_displist = 0; - GLuint displist = fill ? fill_displist : wire_displist; - - /* Initialize round circle shape. */ - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, fill ? GLU_FILL : GLU_SILHOUETTE); - gluDisk(qobj, 0, 0.7, 8, 1); - gluDeleteQuadric(qobj); - - glEndList(); - - if (fill) { - fill_displist = displist; - } - else { - wire_displist = displist; - } - } - - glPushMatrix(); - glTranslatef(x, y, 0.0f); - glScalef(1.0f / xscale * size, 1.0f / yscale * size, 1.0f); - glCallList(displist); - glPopMatrix(); -} - static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoint *point, const eMaskWhichHandle which_handle, const int draw_type, - const float handle_size, const float xscale, const float yscale, + const float handle_size, const float point_pos[2], const float handle_pos[2]) { const BezTriple *bezt = &point->bezt; @@ -190,54 +123,70 @@ static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoin return; } + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff}; + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3ubv(rgb_gray); + /* this could be split into its own loop */ if (draw_type == MASK_DT_OUTLINE) { - const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff}; - glLineWidth(3); - glColor4ubv(rgb_gray); - glBegin(GL_LINES); - glVertex2fv(point_pos); - glVertex2fv(handle_pos); - glEnd(); + glLineWidth(3.0f); + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(pos, point_pos); + immVertex2fv(pos, handle_pos); + immEnd(); } switch (handle_type) { case HD_FREE: - UI_ThemeColor(TH_HANDLE_FREE); + immUniformThemeColor(TH_HANDLE_FREE); break; case HD_AUTO: - UI_ThemeColor(TH_HANDLE_AUTO); + immUniformThemeColor(TH_HANDLE_AUTO); break; case HD_ALIGN: case HD_ALIGN_DOUBLESIDE: - UI_ThemeColor(TH_HANDLE_ALIGN); + immUniformThemeColor(TH_HANDLE_ALIGN); break; } - glLineWidth(1); - glBegin(GL_LINES); - glVertex2fv(point_pos); - glVertex2fv(handle_pos); - glEnd(); + glLineWidth(1.0f); + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(pos, point_pos); + immVertex2fv(pos, handle_pos); + immEnd(); + immUnbindProgram(); /* draw handle points */ + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); + immUniform1f("size", handle_size); + immUniform1f("outlineWidth", 1.5f); + + float point_color[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; /* active color by default */ if (MASKPOINT_ISSEL_HANDLE(point, which_handle)) { - if (point == mask_layer->act_point) - glColor3f(1.0f, 1.0f, 1.0f); - else - UI_ThemeColor(TH_HANDLE_VERTEX_SELECT); + if (point != mask_layer->act_point) { + UI_GetThemeColor3fv(TH_HANDLE_VERTEX_SELECT, point_color); + } } else { - UI_ThemeColor(TH_HANDLE_VERTEX); + UI_GetThemeColor3fv(TH_HANDLE_VERTEX, point_color); } - draw_circle(handle_pos[0], handle_pos[1], handle_size, false, xscale, yscale); + immUniform4fv("outlineColor", point_color); + immUniformColor3fvAlpha(point_color, 0.25f); + + immBegin(GWN_PRIM_POINTS, 1); + immVertex2fv(pos, handle_pos); + immEnd(); + + immUnbindProgram(); } /* return non-zero if spline is selected */ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline *spline, - const char draw_flag, const char draw_type, - const float xscale, const float yscale) + const char draw_flag, const char draw_type) { const bool is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0; const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0; @@ -247,7 +196,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline SpaceClip *sc = CTX_wm_space_clip(C); bool undistort = false; - int i, handle_size, tot_feather_point; + int tot_feather_point; float (*feather_points)[2], (*fp)[2]; float min[2], max[2]; @@ -258,22 +207,24 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT); /* TODO, add this to sequence editor */ - handle_size = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize; - - glPointSize(handle_size); + float handle_size = 2.0f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize; mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + immUniform1f("size", 0.7f * handle_size); + /* feather points */ feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); - for (i = 0; i < spline->tot_point; i++) { + for (int i = 0; i < spline->tot_point; i++) { /* watch it! this is intentionally not the deform array, only check for sel */ MaskSplinePoint *point = &spline->points[i]; - int j; - - for (j = 0; j <= point->tot_uw; j++) { + for (int j = 0; j <= point->tot_uw; j++) { float feather_point[2]; bool sel = false; @@ -291,32 +242,32 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline if (sel) { if (point == masklay->act_point) - glColor3f(1.0f, 1.0f, 1.0f); + immUniformColor3f(1.0f, 1.0f, 1.0f); else - UI_ThemeColor(TH_HANDLE_VERTEX_SELECT); + immUniformThemeColor(TH_HANDLE_VERTEX_SELECT); } else { - UI_ThemeColor(TH_HANDLE_VERTEX); + immUniformThemeColor(TH_HANDLE_VERTEX); } - glBegin(GL_POINTS); - glVertex2fv(feather_point); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex2fv(pos, feather_point); + immEnd(); fp++; } } MEM_freeN(feather_points); + immUnbindProgram(); + if (is_smooth) { glEnable(GL_LINE_SMOOTH); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } /* control points */ INIT_MINMAX2(min, max); - for (i = 0; i < spline->tot_point; i++) { + for (int i = 0; i < spline->tot_point; i++) { /* watch it! this is intentionally not the deform array, only check for sel */ MaskSplinePoint *point = &spline->points[i]; @@ -339,7 +290,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline mask_point_undistort_pos(sc, handle, handle); } draw_single_handle(masklay, point, MASK_WHICH_HANDLE_STICK, - draw_type, handle_size, xscale, yscale, vert, handle); + draw_type, handle_size, vert, handle); } else { float handle_left[2], handle_right[2]; @@ -350,53 +301,62 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline mask_point_undistort_pos(sc, handle_left, handle_left); } draw_single_handle(masklay, point, MASK_WHICH_HANDLE_LEFT, - draw_type, handle_size, xscale, yscale, vert, handle_left); + draw_type, handle_size, vert, handle_left); draw_single_handle(masklay, point, MASK_WHICH_HANDLE_RIGHT, - draw_type, handle_size, xscale, yscale, vert, handle_right); + draw_type, handle_size, vert, handle_right); } + /* bind program in loop so it does not interfere with draw_single_handle */ + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + /* draw CV point */ if (MASKPOINT_ISSEL_KNOT(point)) { if (point == masklay->act_point) - glColor3f(1.0f, 1.0f, 1.0f); + immUniformColor3f(1.0f, 1.0f, 1.0f); else - UI_ThemeColor(TH_HANDLE_VERTEX_SELECT); + immUniformThemeColor(TH_HANDLE_VERTEX_SELECT); } else - UI_ThemeColor(TH_HANDLE_VERTEX); + immUniformThemeColor(TH_HANDLE_VERTEX); + + immBegin(GWN_PRIM_POINTS, 1); + immVertex2fv(pos, vert); + immEnd(); - glBegin(GL_POINTS); - glVertex2fv(vert); - glEnd(); + immUnbindProgram(); minmax_v2v2_v2(min, max, vert); } + if (is_smooth) { + glDisable(GL_LINE_SMOOTH); + } + if (is_spline_sel) { - float x = (min[0] + max[0]) / 2.0f; - float y = (min[1] + max[1]) / 2.0f; - /* TODO(sergey): Remove hardcoded colors. */ + float x = (min[0] + max[0]) * 0.5f; + float y = (min[1] + max[1]) * 0.5f; + + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); + immUniform1f("outlineWidth", 1.5f); + if (masklay->act_spline == spline) { - glColor3ub(255, 255, 255); + immUniformColor3f(1.0f, 1.0f, 1.0f); } else { - glColor3ub(255, 255, 0); + immUniformColor3f(1.0f, 1.0f, 0.0f); } - draw_circle(x, y, 6.0f, true, xscale, yscale); + immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 1.0f); + immUniform1f("size", 12.0f); - glColor3ub(0, 0, 0); - draw_circle(x, y, 6.0f, false, xscale, yscale); - } + immBegin(GWN_PRIM_POINTS, 1); + immVertex2f(pos, x, y); + immEnd(); - if (is_smooth) { - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); + immUnbindProgram(); } } -/* #define USE_XOR */ - static void mask_color_active_tint(unsigned char r_rgb[4], const unsigned char rgb[4], const bool is_active) { if (!is_active) { @@ -410,13 +370,21 @@ static void mask_color_active_tint(unsigned char r_rgb[4], const unsigned char r } } +static void mask_draw_array(unsigned int pos, Gwn_PrimType prim_type, const float (*points)[2], unsigned int vertex_ct) +{ + immBegin(prim_type, vertex_ct); + for (unsigned int i = 0; i < vertex_ct; ++i) { + immVertex2fv(pos, points[i]); + } + immEnd(); +} + static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*orig_points)[2], int tot_point, - const bool is_feather, const bool is_smooth, const bool is_active, + const bool is_feather, const bool is_active, const unsigned char rgb_spline[4], const char draw_type) { - const int draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GL_LINE_LOOP : GL_LINE_STRIP; + const Gwn_PrimType draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GWN_PRIM_LINE_LOOP : GWN_PRIM_LINE_STRIP; const unsigned char rgb_black[4] = {0x00, 0x00, 0x00, 0xff}; -// const unsigned char rgb_white[4] = {0xff, 0xff, 0xff, 0xff}; unsigned char rgb_tmp[4]; SpaceClip *sc = CTX_wm_space_clip(C); float (*points)[2] = orig_points; @@ -425,65 +393,45 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (* const bool undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT); if (undistort) { - int i; - points = MEM_callocN(2 * tot_point * sizeof(float), "undistorthed mask curve"); - for (i = 0; i < tot_point; i++) { + for (int i = 0; i < tot_point; i++) { mask_point_undistort_pos(sc, points[i], orig_points[i]); } } } - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, points); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); switch (draw_type) { case MASK_DT_OUTLINE: - glLineWidth(3); - - mask_color_active_tint(rgb_tmp, rgb_black, is_active); - glColor4ubv(rgb_tmp); - - glDrawArrays(draw_method, 0, tot_point); + /* TODO(merwin): use fancy line shader here + * probably better with geometry shader (after core profile switch) + */ + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - glLineWidth(1); - mask_color_active_tint(rgb_tmp, rgb_spline, is_active); - glColor4ubv(rgb_tmp); - glDrawArrays(draw_method, 0, tot_point); + glLineWidth(3.0f); - break; + mask_color_active_tint(rgb_tmp, rgb_black, is_active); + immUniformColor4ubv(rgb_tmp); + mask_draw_array(pos, draw_method, points, tot_point); - case MASK_DT_DASH: - default: - GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); - GPU_basic_shader_line_stipple(3, 0xAAAA); + glLineWidth(1.0f); -#ifdef USE_XOR - glEnable(GL_COLOR_LOGIC_OP); - glLogicOp(GL_OR); -#endif mask_color_active_tint(rgb_tmp, rgb_spline, is_active); - glColor4ubv(rgb_tmp); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, points); - glDrawArrays(draw_method, 0, tot_point); - -#ifdef USE_XOR - glDisable(GL_COLOR_LOGIC_OP); -#endif - mask_color_active_tint(rgb_tmp, rgb_black, is_active); - glColor4ubv(rgb_tmp); - GPU_basic_shader_line_stipple(3, 0x5555); - glDrawArrays(draw_method, 0, tot_point); + immUniformColor4ubv(rgb_tmp); + mask_draw_array(pos, draw_method, points, tot_point); - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); + immUnbindProgram(); break; - case MASK_DT_BLACK: case MASK_DT_WHITE: + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + glLineWidth(1.0f); + if (draw_type == MASK_DT_BLACK) { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 0; } else { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 255; } /* alpha values seem too low but gl draws many points that compensate for it */ @@ -496,26 +444,39 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (* rgb_tmp[2] = (unsigned char)(((short)rgb_tmp[2] + (short)rgb_spline[2]) / 2); } - if (is_smooth == false && is_feather) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - mask_color_active_tint(rgb_tmp, rgb_tmp, is_active); - glColor4ubv(rgb_tmp); + immUniformColor4ubv(rgb_tmp); + mask_draw_array(pos, draw_method, points, tot_point); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, points); - glDrawArrays(draw_method, 0, tot_point); + immUnbindProgram(); + break; - if (is_smooth == false && is_feather) { - glDisable(GL_BLEND); - } + case MASK_DT_DASH: + /* TODO(merwin): use dashed line shader here + * probably better with geometry shader (after core profile switch) + */ +#if 0 + glLineWidth(1.0f); + + GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); + GPU_basic_shader_line_stipple(3, 0xAAAA); + mask_color_active_tint(rgb_tmp, rgb_spline, is_active); + immUniformColor4ubv(rgb_tmp); + mask_draw_array(pos, draw_method, points, tot_point); + + mask_color_active_tint(rgb_tmp, rgb_black, is_active); + immUniformColor4ubv(rgb_tmp); + GPU_basic_shader_line_stipple(3, 0x5555); + mask_draw_array(pos, draw_method, points, tot_point); + + GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); +#endif break; - } - glDisableClientState(GL_VERTEX_ARRAY); + default: + BLI_assert(false); + } if (points != orig_points) MEM_freeN(points); @@ -548,8 +509,6 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline if (is_smooth) { glEnable(GL_LINE_SMOOTH); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution(spline, &tot_feather_point, resol, (is_fill != false)); @@ -557,26 +516,24 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline /* draw feather */ mask_spline_feather_color_get(masklay, spline, is_spline_sel, rgb_tmp); mask_draw_curve_type(C, spline, feather_points, tot_feather_point, - true, is_smooth, is_active, + true, is_active, rgb_tmp, draw_type); if (!is_fill) { - const float *fp = &diff_points[0][0]; float *fp_feather = &feather_points[0][0]; - float tvec[2]; - int i; BLI_assert(tot_diff_point == tot_feather_point); - for (i = 0; i < tot_diff_point; i++, fp += 2, fp_feather += 2) { + for (int i = 0; i < tot_diff_point; i++, fp += 2, fp_feather += 2) { + float tvec[2]; sub_v2_v2v2(tvec, fp, fp_feather); add_v2_v2v2(fp_feather, fp, tvec); } /* same as above */ mask_draw_curve_type(C, spline, feather_points, tot_feather_point, - true, is_smooth, is_active, + true, is_active, rgb_tmp, draw_type); } @@ -585,21 +542,22 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline /* draw main curve */ mask_spline_color_get(masklay, spline, is_spline_sel, rgb_tmp); mask_draw_curve_type(C, spline, diff_points, tot_diff_point, - false, is_smooth, is_active, + false, is_active, rgb_tmp, draw_type); MEM_freeN(diff_points); - if (draw_flag & MASK_DRAWFLAG_SMOOTH) { + if (is_smooth) { glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); } - - (void)draw_type; } static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, const char draw_type, - const int width, const int height, const float xscale, const float yscale) + const int width, const int height) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GPU_enable_program_point_size(); + MaskLayer *masklay; int i; @@ -616,11 +574,9 @@ static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, c /* draw curve itself first... */ draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height); -// draw_spline_parents(masklay, spline); - if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) { /* ...and then handles over the curve so they're nicely visible */ - draw_spline_points(C, masklay, spline, draw_flag, draw_type, xscale, yscale); + draw_spline_points(C, masklay, spline, draw_flag, draw_type); } /* show undeform for testing */ @@ -629,33 +585,29 @@ static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, c spline->points_deform = NULL; draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height); -// draw_spline_parents(masklay, spline); - draw_spline_points(C, masklay, spline, draw_flag, draw_type, xscale, yscale); + draw_spline_points(C, masklay, spline, draw_flag, draw_type); spline->points_deform = back; } } } + + GPU_disable_program_point_size(); + glDisable(GL_BLEND); } void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type) { ScrArea *sa = CTX_wm_area(C); - ARegion *ar = CTX_wm_region(C); - Mask *mask = CTX_data_edit_mask(C); int width, height; - float aspx, aspy; - float xscale, yscale; if (!mask) return; ED_mask_get_size(sa, &width, &height); - ED_mask_get_aspect(sa, ar, &aspx, &aspy); - UI_view2d_scale_get(&ar->v2d, &xscale, &yscale); - draw_masklays(C, mask, draw_flag, draw_type, width, height, xscale * aspx, yscale * aspy); + draw_masklays(C, mask, draw_flag, draw_type, width, height); } typedef struct ThreadedMaskRasterizeState { @@ -802,28 +754,26 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar, } if (draw_flag & MASK_DRAWFLAG_OVERLAY) { + float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; float *buffer = threaded_mask_rasterize(mask, width, height); - int format; - if (overlay_mode == MASK_OVERLAY_ALPHACHANNEL) { - glColor3f(1.0f, 1.0f, 1.0f); - format = GL_LUMINANCE; - } - else { + if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) { /* More blending types could be supported in the future. */ glEnable(GL_BLEND); - glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA); - format = GL_ALPHA; + glBlendFunc(GL_DST_COLOR, GL_ZERO); } - glPushMatrix(); - glTranslatef(x, y, 0); - glScalef(zoomx, zoomy, 0); + gpuPushMatrix(); + gpuTranslate2f(x, y); + gpuScale2f(zoomx, zoomy); if (stabmat) { - glMultMatrixf(stabmat); + gpuMultMatrix(stabmat); } - glaDrawPixelsTex(0.0f, 0.0f, width, height, format, GL_FLOAT, GL_NEAREST, buffer); - glPopMatrix(); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); + GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); + immDrawPixelsTex(&state, 0.0f, 0.0f, width, height, GL_RED, GL_FLOAT, GL_NEAREST, buffer, 1.0f, 1.0f, NULL); + + gpuPopMatrix(); if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) { glDisable(GL_BLEND); @@ -833,26 +783,26 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar, } /* apply transformation so mask editing tools will assume drawing from the origin in normalized space */ - glPushMatrix(); - glTranslatef(x + xofs, y + yofs, 0); - glScalef(zoomx, zoomy, 0); + gpuPushMatrix(); + gpuTranslate2f(x + xofs, y + yofs); + gpuScale2f(zoomx, zoomy); if (stabmat) { - glMultMatrixf(stabmat); + gpuMultMatrix(stabmat); } - glScalef(maxdim, maxdim, 0); + gpuScale2f(maxdim, maxdim); if (do_draw_cb) { ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); } /* draw! */ - draw_masklays(C, mask, draw_flag, draw_type, width, height, maxdim * zoomx, maxdim * zoomy); + draw_masklays(C, mask, draw_flag, draw_type, width, height); if (do_draw_cb) { ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); } - glPopMatrix(); + gpuPopMatrix(); } void ED_mask_draw_frames(Mask *mask, ARegion *ar, const int cfra, const int sfra, const int efra) @@ -861,25 +811,31 @@ void ED_mask_draw_frames(Mask *mask, ARegion *ar, const int cfra, const int sfra MaskLayer *masklay = BKE_mask_layer_active(mask); - glBegin(GL_LINES); - glColor4ub(255, 175, 0, 255); - if (masklay) { - MaskLayerShape *masklay_shape; - - for (masklay_shape = masklay->splines_shapes.first; - masklay_shape; - masklay_shape = masklay_shape->next) - { - int frame = masklay_shape->frame; - - /* draw_keyframe(i, CFRA, sfra, framelen, 1); */ - int height = (frame == cfra) ? 22 : 10; - int x = (frame - sfra) * framelen; - glVertex2i(x, 0); - glVertex2i(x, height); + unsigned int num_lines = BLI_listbase_count(&masklay->splines_shapes); + + if (num_lines > 0) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ub(255, 175, 0, 255); + + immBegin(GWN_PRIM_LINES, 2 * num_lines); + + for (MaskLayerShape *masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) + { + int frame = masklay_shape->frame; + + /* draw_keyframe(i, CFRA, sfra, framelen, 1); */ + int height = (frame == cfra) ? 22 : 10; + int x = (frame - sfra) * framelen; + immVertex2i(pos, x, 0); + immVertex2i(pos, x, height); + } + immEnd(); + immUnbindProgram(); } } - - glEnd(); } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 97d5ee1eff0..b6ac23a37e8 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -35,10 +35,11 @@ #include "BLI_math.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_mask.h" +#include "DEG_depsgraph.h" + #include "DNA_scene_types.h" #include "DNA_mask_types.h" #include "DNA_object_types.h" /* SELECT */ @@ -1062,7 +1063,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event) } WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); - DAG_id_tag_update(&data->mask->id, 0); + DEG_id_tag_update(&data->mask->id, 0); break; } @@ -1089,7 +1090,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event) } WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); - DAG_id_tag_update(&data->mask->id, 0); + DEG_id_tag_update(&data->mask->id, 0); free_slide_point_data(op->customdata); /* keep this last! */ return OPERATOR_FINISHED; @@ -1105,7 +1106,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event) cancel_slide_point(op->customdata); WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); - DAG_id_tag_update(&data->mask->id, 0); + DEG_id_tag_update(&data->mask->id, 0); free_slide_point_data(op->customdata); /* keep this last! */ return OPERATOR_CANCELLED; @@ -1469,7 +1470,7 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve } WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask); - DAG_id_tag_update(&slide_data->mask->id, 0); + DEG_id_tag_update(&slide_data->mask->id, 0); break; } @@ -1483,7 +1484,7 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve } WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask); - DAG_id_tag_update(&slide_data->mask->id, 0); + DEG_id_tag_update(&slide_data->mask->id, 0); free_slide_spline_curvature_data(slide_data); /* keep this last! */ return OPERATOR_FINISHED; @@ -1495,7 +1496,7 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve cancel_slide_spline_curvature(slide_data); WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask); - DAG_id_tag_update(&slide_data->mask->id, 0); + DEG_id_tag_update(&slide_data->mask->id, 0); free_slide_spline_curvature_data(op->customdata); /* keep this last! */ return OPERATOR_CANCELLED; @@ -1541,7 +1542,7 @@ static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) } } - DAG_id_tag_update(&mask->id, 0); + DEG_id_tag_update(&mask->id, 0); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; @@ -1900,7 +1901,7 @@ static int set_handle_type_exec(bContext *C, wmOperator *op) if (changed) { WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); - DAG_id_tag_update(&mask->id, 0); + DEG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } @@ -1955,7 +1956,7 @@ static int mask_hide_view_clear_exec(bContext *C, wmOperator *op) if (changed) { WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask); - DAG_id_tag_update(&mask->id, 0); + DEG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } @@ -2019,7 +2020,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op) if (changed) { WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask); - DAG_id_tag_update(&mask->id, 0); + DEG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } @@ -2079,7 +2080,7 @@ static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op)) BKE_mask_update_display(mask, CFRA); WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask); - DAG_id_tag_update(&mask->id, 0); + DEG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 4e0aa8f84ae..c500ec75aee 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -34,10 +34,11 @@ #include "BLI_string.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_mask.h" #include "BKE_tracking.h" +#include "DEG_depsgraph.h" + #include "DNA_mask_types.h" #include "WM_api.h" @@ -73,7 +74,7 @@ static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op)) } WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); - DAG_id_tag_update(&mask->id, 0); + DEG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } @@ -176,7 +177,7 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) } WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); - DAG_id_tag_update(&mask->id, 0); + DEG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index 99ffc9cd7d2..3fb1cc87dbd 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -36,13 +36,14 @@ #include "BLI_math.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_mask.h" #include "DNA_object_types.h" #include "DNA_mask_types.h" #include "DNA_scene_types.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -75,7 +76,7 @@ static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op)) if (changed) { WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); - DAG_id_tag_update(&mask->id, 0); + DEG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } @@ -124,7 +125,7 @@ static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) if (changed) { WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); - DAG_id_tag_update(&mask->id, OB_RECALC_DATA); + DEG_id_tag_update(&mask->id, OB_RECALC_DATA); return OPERATOR_FINISHED; } @@ -216,7 +217,7 @@ static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op) if (changed) { WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); - DAG_id_tag_update(&mask->id, 0); + DEG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } @@ -386,7 +387,7 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op) if (changed) { WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); - DAG_id_tag_update(&mask->id, 0); + DEG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index 8783367ef7e..80e1187609c 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../bmesh ../../gpu ../../imbuf @@ -51,6 +52,7 @@ set(SRC editmesh_knife_project.c editmesh_loopcut.c editmesh_path.c + editmesh_polybuild.c editmesh_rip.c editmesh_rip_edge.c editmesh_select.c diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 87c8c55b0a1..992d0fada5e 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -105,6 +105,8 @@ void paintface_flush_flags(Object *ob, short flag) /* draw-object caches hidden faces, force re-generation T46867 */ GPU_drawobject_free(dm); } + + BKE_mesh_batch_cache_dirty(me, BKE_MESH_BATCH_DIRTY_ALL); } void paintface_hide(Object *ob, const bool unselected) @@ -386,14 +388,14 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b } /* image window redraw */ - + paintface_flush_flags(ob, SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views return true; } -int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) +int do_paintface_box_select(const struct EvaluationContext *eval_ctx, ViewContext *vc, rcti *rect, bool select, bool extend) { Object *ob = vc->obact; Mesh *me; @@ -424,7 +426,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten } } - ED_view3d_backbuf_validate(vc); + ED_view3d_backbuf_validate(eval_ctx, vc); ibuf = IMB_allocImBuf(size[0], size[1], 32, IB_rect); rt = ibuf->rect; @@ -514,6 +516,8 @@ void paintvert_flush_flags(Object *ob) dm_mv->flag = me->mvert[i].flag; } } + + BKE_mesh_batch_cache_dirty(me, BKE_MESH_BATCH_DIRTY_ALL); } /* note: if the caller passes false to flush_flags, then they will need to run paintvert_flush_flags(ob) themselves */ void paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index 3a9e278f039..1937a9f6891 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -50,9 +50,17 @@ #include "ED_screen.h" #include "ED_view3d.h" +#include "UI_resources.h" #include "mesh_intern.h" /* own include */ +#define USE_MANIPULATOR + +#ifdef USE_MANIPULATOR +#include "ED_manipulator_library.h" +#include "ED_util.h" +#endif + static int mesh_bisect_exec(bContext *C, wmOperator *op); /* -------------------------------------------------------------------- */ @@ -186,6 +194,16 @@ static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event) if (ret & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) { edbm_bisect_exit(C, &opdata_back); + +#ifdef USE_MANIPULATOR + /* Setup manipulators */ + { + View3D *v3d = CTX_wm_view3d(C); + if (v3d && (v3d->twtype & V3D_MANIPULATOR_DRAW)) { + WM_manipulator_group_type_ensure("MESH_WGT_bisect"); + } + } +#endif } return ret; @@ -315,6 +333,9 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) } } +#ifdef USE_MANIPULATOR +static void MESH_WGT_bisect(struct wmManipulatorGroupType *wgt); +#endif void MESH_OT_bisect(struct wmOperatorType *ot) { @@ -350,4 +371,331 @@ void MESH_OT_bisect(struct wmOperatorType *ot) RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Axis Threshold", "", 0.00001, 0.1); WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT); + +#ifdef USE_MANIPULATOR + WM_manipulatorgrouptype_append(MESH_WGT_bisect); +#endif +} + + +#ifdef USE_MANIPULATOR + +/* -------------------------------------------------------------------- */ + +/** \name Bisect Manipulator + * \{ */ + +typedef struct ManipulatorGroup { + /* Arrow to change plane depth. */ + struct wmManipulator *translate_z; + /* Translate XYZ */ + struct wmManipulator *translate_c; + /* For grabbing the manipulator and moving freely. */ + struct wmManipulator *rotate_c; + + /* We could store more vars here! */ + struct { + bContext *context; + wmOperator *op; + PropertyRNA *prop_plane_co; + PropertyRNA *prop_plane_no; + + float rotate_axis[3]; + float rotate_up[3]; + } data; +} ManipulatorGroup; + +/** + * XXX. calling redo from property updates is not great. + * This is needed because changing the RNA doesn't cause a redo + * and we're not using operator UI which does just this. + */ +static void manipulator_bisect_exec(ManipulatorGroup *man) +{ + wmOperator *op = man->data.op; + if (op == WM_operator_last_redo((bContext *)man->data.context)) { + ED_undo_operator_repeat((bContext *)man->data.context, op); + } +} + +static void manipulator_mesh_bisect_update_from_op(ManipulatorGroup *man) +{ + wmOperator *op = man->data.op; + + float plane_co[3], plane_no[3]; + + RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, plane_co); + RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no); + + WM_manipulator_set_matrix_location(man->translate_z, plane_co); + WM_manipulator_set_matrix_location(man->rotate_c, plane_co); + /* translate_c location comes from the property. */ + + WM_manipulator_set_matrix_rotation_from_z_axis(man->translate_z, plane_no); + + WM_manipulator_set_scale(man->translate_c, 0.2); + + RegionView3D *rv3d = ED_view3d_context_rv3d(man->data.context); + if (rv3d) { + normalize_v3_v3(man->data.rotate_axis, rv3d->viewinv[2]); + normalize_v3_v3(man->data.rotate_up, rv3d->viewinv[1]); + + /* ensure its orthogonal */ + project_plane_normalized_v3_v3v3(man->data.rotate_up, man->data.rotate_up, man->data.rotate_axis); + normalize_v3(man->data.rotate_up); + + WM_manipulator_set_matrix_rotation_from_z_axis(man->translate_c, plane_no); + + float plane_no_cross[3]; + cross_v3_v3v3(plane_no_cross, plane_no, man->data.rotate_axis); + + WM_manipulator_set_matrix_offset_rotation_from_yz_axis(man->rotate_c, plane_no_cross, man->data.rotate_axis); + RNA_enum_set(man->rotate_c->ptr, "draw_options", + ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_MIRROR | + ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_START_Y); + } +} + +/* depth callbacks */ +static void manipulator_bisect_prop_depth_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_co[3], plane_no[3]; + RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, plane_co); + RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no); + + value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, mpr->matrix_basis[3]); +} + +static void manipulator_bisect_prop_depth_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + const float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_co[3], plane[4]; + RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, plane_co); + RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane); + normalize_v3(plane); + + plane[3] = -value[0] - dot_v3v3(plane, mpr->matrix_basis[3]); + + /* Keep our location, may be offset simply to be inside the viewport. */ + closest_to_plane_normalized_v3(plane_co, plane, plane_co); + + RNA_property_float_set_array(op->ptr, man->data.prop_plane_co, plane_co); + + manipulator_bisect_exec(man); +} + +/* translate callbacks */ +static void manipulator_bisect_prop_translate_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + + BLI_assert(mpr_prop->type->array_length == 3); + UNUSED_VARS_NDEBUG(mpr_prop); + + RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, value_p); +} + +static void manipulator_bisect_prop_translate_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + + BLI_assert(mpr_prop->type->array_length == 3); + UNUSED_VARS_NDEBUG(mpr_prop); + + RNA_property_float_set_array(op->ptr, man->data.prop_plane_co, value_p); + + manipulator_bisect_exec(man); +} + +/* angle callbacks */ +static void manipulator_bisect_prop_angle_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_no[4]; + RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no); + normalize_v3(plane_no); + + float plane_no_proj[3]; + project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, man->data.rotate_axis); + + if (!is_zero_v3(plane_no_proj)) { + const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, man->data.rotate_up, man->data.rotate_axis); + value[0] = angle; + } + else { + value[0] = 0.0f; + } +} + +static void manipulator_bisect_prop_angle_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + const float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_no[4]; + RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no); + normalize_v3(plane_no); + + float plane_no_proj[3]; + project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, man->data.rotate_axis); + + if (!is_zero_v3(plane_no_proj)) { + const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, man->data.rotate_up, man->data.rotate_axis); + const float angle_delta = angle - angle_compat_rad(value[0], angle); + if (angle_delta != 0.0f) { + float mat[3][3]; + axis_angle_normalized_to_mat3(mat, man->data.rotate_axis, angle_delta); + mul_m3_v3(mat, plane_no); + + /* re-normalize - seems acceptable */ + RNA_property_float_set_array(op->ptr, man->data.prop_plane_no, plane_no); + + manipulator_bisect_exec(man); + } + } +} + +static bool manipulator_mesh_bisect_poll(const bContext *C, wmManipulatorGroupType *wgt) +{ + wmOperator *op = WM_operator_last_redo(C); + if (op == NULL || !STREQ(op->type->idname, "MESH_OT_bisect")) { + WM_manipulator_group_type_unlink_delayed_ptr(wgt); + return false; + } + return true; } + +static void manipulator_mesh_bisect_setup(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmOperator *op = WM_operator_last_redo(C); + + if (op == NULL || !STREQ(op->type->idname, "MESH_OT_bisect")) { + return; + } + + struct ManipulatorGroup *man = MEM_callocN(sizeof(ManipulatorGroup), __func__); + mgroup->customdata = man; + + const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true); + const wmManipulatorType *wt_grab = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", true); + const wmManipulatorType *wt_dial = WM_manipulatortype_find("MANIPULATOR_WT_dial_3d", true); + + man->translate_z = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); + man->translate_c = WM_manipulator_new_ptr(wt_grab, mgroup, NULL); + man->rotate_c = WM_manipulator_new_ptr(wt_dial, mgroup, NULL); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->translate_z->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->translate_c->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_SECONDARY, man->rotate_c->color); + + RNA_enum_set(man->translate_z->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_NORMAL); + RNA_enum_set(man->translate_c->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_RING_2D); + + WM_manipulator_set_flag(man->translate_c, WM_MANIPULATOR_DRAW_VALUE, true); + WM_manipulator_set_flag(man->rotate_c, WM_MANIPULATOR_DRAW_VALUE, true); + + { + man->data.context = (bContext *)C; + man->data.op = op; + man->data.prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co"); + man->data.prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no"); + } + + manipulator_mesh_bisect_update_from_op(man); + + /* Setup property callbacks */ + { + WM_manipulator_target_property_def_func( + man->translate_z, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_bisect_prop_depth_get, + .value_set_fn = manipulator_bisect_prop_depth_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + + WM_manipulator_target_property_def_func( + man->translate_c, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_bisect_prop_translate_get, + .value_set_fn = manipulator_bisect_prop_translate_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + + WM_manipulator_target_property_def_func( + man->rotate_c, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_bisect_prop_angle_get, + .value_set_fn = manipulator_bisect_prop_angle_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + } +} + +static void manipulator_mesh_bisect_draw_prepare( + const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + ManipulatorGroup *man = mgroup->customdata; + if (man->data.op->next) { + man->data.op = WM_operator_last_redo((bContext *)man->data.context); + } + manipulator_mesh_bisect_update_from_op(man); +} + +static void MESH_WGT_bisect(struct wmManipulatorGroupType *wgt) +{ + wgt->name = "Mesh Bisect"; + wgt->idname = "MESH_WGT_bisect"; + + wgt->flag = WM_MANIPULATORGROUPTYPE_3D; + + wgt->mmap_params.spaceid = SPACE_VIEW3D; + wgt->mmap_params.regionid = RGN_TYPE_WINDOW; + + wgt->poll = manipulator_mesh_bisect_poll; + wgt->setup = manipulator_mesh_bisect_setup; + wgt->draw_prepare = manipulator_mesh_bisect_draw_prepare; +} + +/** \} */ + +#endif /* USE_MANIPULATOR */ diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 5ac90ec29e6..18320ec65f5 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -45,6 +45,7 @@ #include "RNA_define.h" #include "RNA_access.h" +#include "WM_api.h" #include "WM_types.h" #include "ED_mesh.h" @@ -52,8 +53,19 @@ #include "ED_transform.h" #include "ED_view3d.h" +#include "UI_resources.h" + +#include "MEM_guardedalloc.h" + #include "mesh_intern.h" /* own include */ +#define USE_MANIPULATOR + +#ifdef USE_MANIPULATOR +#include "ED_manipulator_library.h" +#include "ED_util.h" +#endif + static void edbm_extrude_edge_exclude_mirror( Object *obedit, BMEditMesh *em, const char hflag, @@ -747,9 +759,25 @@ static int edbm_spin_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e } } - return edbm_spin_exec(C, op); + int ret = edbm_spin_exec(C, op); + +#ifdef USE_MANIPULATOR + if (ret & OPERATOR_FINISHED) { + /* Setup manipulators */ + if (v3d && (v3d->twtype & V3D_MANIPULATOR_DRAW)) { + WM_manipulator_group_type_ensure("MESH_WGT_spin"); + } + } +#endif + + return ret; + } +#ifdef USE_MANIPULATOR +static void MESH_WGT_spin(struct wmManipulatorGroupType *wgt); +#endif + void MESH_OT_spin(wmOperatorType *ot) { PropertyRNA *prop; @@ -778,8 +806,385 @@ void MESH_OT_spin(wmOperatorType *ot) "Center", "Center in global view space", -1e4f, 1e4f); RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f); +#ifdef USE_MANIPULATOR + WM_manipulatorgrouptype_append(MESH_WGT_spin); +#endif +} + + +#ifdef USE_MANIPULATOR + +/* -------------------------------------------------------------------- */ + +/** \name Spin Manipulator + * \{ */ + +typedef struct ManipulatorSpinGroup { + /* Arrow to change plane depth. */ + struct wmManipulator *translate_z; + /* Translate XYZ */ + struct wmManipulator *translate_c; + /* For grabbing the manipulator and moving freely. */ + struct wmManipulator *rotate_c; + /* Spin angle */ + struct wmManipulator *angle_z; + + /* We could store more vars here! */ + struct { + bContext *context; + wmOperator *op; + PropertyRNA *prop_axis_co; + PropertyRNA *prop_axis_no; + PropertyRNA *prop_angle; + + float rotate_axis[3]; + float rotate_up[3]; + } data; +} ManipulatorSpinGroup; + +/** + * XXX. calling redo from property updates is not great. + * This is needed because changing the RNA doesn't cause a redo + * and we're not using operator UI which does just this. + */ +static void manipulator_spin_exec(ManipulatorSpinGroup *man) +{ + wmOperator *op = man->data.op; + if (op == WM_operator_last_redo((bContext *)man->data.context)) { + ED_undo_operator_repeat((bContext *)man->data.context, op); + } +} + +static void manipulator_mesh_spin_update_from_op(ManipulatorSpinGroup *man) +{ + wmOperator *op = man->data.op; + + float plane_co[3], plane_no[3]; + + RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, plane_co); + RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no); + + WM_manipulator_set_matrix_location(man->translate_z, plane_co); + WM_manipulator_set_matrix_location(man->rotate_c, plane_co); + WM_manipulator_set_matrix_location(man->angle_z, plane_co); + /* translate_c location comes from the property. */ + + WM_manipulator_set_matrix_rotation_from_z_axis(man->translate_z, plane_no); + WM_manipulator_set_matrix_rotation_from_z_axis(man->angle_z, plane_no); + + WM_manipulator_set_scale(man->translate_c, 0.2); + + RegionView3D *rv3d = ED_view3d_context_rv3d(man->data.context); + if (rv3d) { + normalize_v3_v3(man->data.rotate_axis, rv3d->viewinv[2]); + normalize_v3_v3(man->data.rotate_up, rv3d->viewinv[1]); + + /* ensure its orthogonal */ + project_plane_normalized_v3_v3v3(man->data.rotate_up, man->data.rotate_up, man->data.rotate_axis); + normalize_v3(man->data.rotate_up); + + WM_manipulator_set_matrix_rotation_from_z_axis(man->translate_c, plane_no); + WM_manipulator_set_matrix_rotation_from_yz_axis(man->rotate_c, plane_no, man->data.rotate_axis); + + /* show the axis instead of mouse cursor */ + RNA_enum_set(man->rotate_c->ptr, "draw_options", + ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_MIRROR | + ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_START_Y); + + } } +/* depth callbacks */ +static void manipulator_spin_prop_depth_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_co[3], plane_no[3]; + RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, plane_co); + RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no); + + value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, mpr->matrix_basis[3]); +} + +static void manipulator_spin_prop_depth_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + const float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_co[3], plane[4]; + RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, plane_co); + RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane); + normalize_v3(plane); + + plane[3] = -value[0] - dot_v3v3(plane, mpr->matrix_basis[3]); + + /* Keep our location, may be offset simply to be inside the viewport. */ + closest_to_plane_normalized_v3(plane_co, plane, plane_co); + + RNA_property_float_set_array(op->ptr, man->data.prop_axis_co, plane_co); + + manipulator_spin_exec(man); +} + +/* translate callbacks */ +static void manipulator_spin_prop_translate_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 3); + UNUSED_VARS_NDEBUG(mpr_prop); + + RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, value); +} + +static void manipulator_spin_prop_translate_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + + BLI_assert(mpr_prop->type->array_length == 3); + UNUSED_VARS_NDEBUG(mpr_prop); + + RNA_property_float_set_array(op->ptr, man->data.prop_axis_co, value); + + manipulator_spin_exec(man); +} + +/* angle callbacks */ +static void manipulator_spin_prop_axis_angle_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_no[4]; + RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no); + normalize_v3(plane_no); + + float plane_no_proj[3]; + project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, man->data.rotate_axis); + + if (!is_zero_v3(plane_no_proj)) { + const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, man->data.rotate_up, man->data.rotate_axis); + value[0] = angle; + } + else { + value[0] = 0.0f; + } +} + +static void manipulator_spin_prop_axis_angle_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + const float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_no[4]; + RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no); + normalize_v3(plane_no); + + float plane_no_proj[3]; + project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, man->data.rotate_axis); + + if (!is_zero_v3(plane_no_proj)) { + const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, man->data.rotate_up, man->data.rotate_axis); + const float angle_delta = angle - angle_compat_rad(value[0], angle); + if (angle_delta != 0.0f) { + float mat[3][3]; + axis_angle_normalized_to_mat3(mat, man->data.rotate_axis, angle_delta); + mul_m3_v3(mat, plane_no); + + /* re-normalize - seems acceptable */ + RNA_property_float_set_array(op->ptr, man->data.prop_axis_no, plane_no); + + manipulator_spin_exec(man); + } + } +} + +/* angle callbacks */ +static void manipulator_spin_prop_angle_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + value[0] = RNA_property_float_get(op->ptr, man->data.prop_angle); +} + +static void manipulator_spin_prop_angle_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + const float *value = value_p; + RNA_property_float_set(op->ptr, man->data.prop_angle, value[0]); + + manipulator_spin_exec(man); +} + +static bool manipulator_mesh_spin_poll(const bContext *C, wmManipulatorGroupType *wgt) +{ + wmOperator *op = WM_operator_last_redo(C); + if (op == NULL || !STREQ(op->type->idname, "MESH_OT_spin")) { + WM_manipulator_group_type_unlink_delayed_ptr(wgt); + return false; + } + return true; +} + +static void manipulator_mesh_spin_setup(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmOperator *op = WM_operator_last_redo(C); + + if (op == NULL || !STREQ(op->type->idname, "MESH_OT_spin")) { + return; + } + + struct ManipulatorSpinGroup *man = MEM_callocN(sizeof(ManipulatorSpinGroup), __func__); + mgroup->customdata = man; + + const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true); + const wmManipulatorType *wt_grab = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", true); + const wmManipulatorType *wt_dial = WM_manipulatortype_find("MANIPULATOR_WT_dial_3d", true); + + man->translate_z = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); + man->translate_c = WM_manipulator_new_ptr(wt_grab, mgroup, NULL); + man->rotate_c = WM_manipulator_new_ptr(wt_dial, mgroup, NULL); + man->angle_z = WM_manipulator_new_ptr(wt_dial, mgroup, NULL); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->translate_z->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->translate_c->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_SECONDARY, man->rotate_c->color); + UI_GetThemeColor3fv(TH_AXIS_Z, man->angle_z->color); + + + RNA_enum_set(man->translate_z->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_NORMAL); + RNA_enum_set(man->translate_c->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_RING_2D); + + WM_manipulator_set_flag(man->translate_c, WM_MANIPULATOR_DRAW_VALUE, true); + WM_manipulator_set_flag(man->rotate_c, WM_MANIPULATOR_DRAW_VALUE, true); + WM_manipulator_set_flag(man->angle_z, WM_MANIPULATOR_DRAW_VALUE, true); + + WM_manipulator_set_scale(man->angle_z, 0.5f); + + { + man->data.context = (bContext *)C; + man->data.op = op; + man->data.prop_axis_co = RNA_struct_find_property(op->ptr, "center"); + man->data.prop_axis_no = RNA_struct_find_property(op->ptr, "axis"); + man->data.prop_angle = RNA_struct_find_property(op->ptr, "angle"); + } + + manipulator_mesh_spin_update_from_op(man); + + /* Setup property callbacks */ + { + WM_manipulator_target_property_def_func( + man->translate_z, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_spin_prop_depth_get, + .value_set_fn = manipulator_spin_prop_depth_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + + WM_manipulator_target_property_def_func( + man->translate_c, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_spin_prop_translate_get, + .value_set_fn = manipulator_spin_prop_translate_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + + WM_manipulator_target_property_def_func( + man->rotate_c, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_spin_prop_axis_angle_get, + .value_set_fn = manipulator_spin_prop_axis_angle_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + + WM_manipulator_target_property_def_func( + man->angle_z, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_spin_prop_angle_get, + .value_set_fn = manipulator_spin_prop_angle_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + + } +} + +static void manipulator_mesh_spin_draw_prepare( + const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + ManipulatorSpinGroup *man = mgroup->customdata; + if (man->data.op->next) { + man->data.op = WM_operator_last_redo((bContext *)man->data.context); + } + manipulator_mesh_spin_update_from_op(man); +} + +static void MESH_WGT_spin(struct wmManipulatorGroupType *wgt) +{ + wgt->name = "Mesh Spin"; + wgt->idname = "MESH_WGT_spin"; + + wgt->flag = WM_MANIPULATORGROUPTYPE_3D; + + wgt->mmap_params.spaceid = SPACE_VIEW3D; + wgt->mmap_params.regionid = RGN_TYPE_WINDOW; + + wgt->poll = manipulator_mesh_spin_poll; + wgt->setup = manipulator_mesh_spin_setup; + wgt->draw_prepare = manipulator_mesh_spin_draw_prepare; +} + +/** \} */ + +#endif /* USE_MANIPULATOR */ + + static int edbm_screw_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 658f8b3958b..c0501078424 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -54,8 +54,10 @@ #include "BKE_editmesh_bvh.h" #include "BKE_report.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" /* for paint cursor */ +#include "DEG_depsgraph.h" + +#include "GPU_immediate.h" +#include "GPU_matrix.h" #include "ED_screen.h" #include "ED_space_api.h" @@ -159,6 +161,7 @@ typedef struct KnifePosData { typedef struct KnifeTool_OpData { ARegion *ar; /* region that knifetool was activated in */ void *draw_handle; /* for drawing preview loop */ + EvaluationContext eval_ctx; ViewContext vc; /* note: _don't_ use 'mval', instead use the one we define below */ float mval[2]; /* mouse value with snapping applied */ //bContext *C; @@ -1004,12 +1007,18 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd) copy_v3_v3(v2, ray_hit_best[1]); } - UI_ThemeColor(TH_TRANSFORM); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_TRANSFORM); glLineWidth(2.0); - glBegin(GL_LINES); - glVertex3fv(v1); - glVertex3fv(v2); - glEnd(); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + immEnd(); + + immUnbindProgram(); } static void knife_init_colors(KnifeColors *colors) @@ -1037,66 +1046,69 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) glPolygonOffset(1.0f, 1.0f); - glPushMatrix(); - glMultMatrixf(kcd->ob->obmat); + gpuPushMatrix(); + gpuMultMatrix(kcd->ob->obmat); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); if (kcd->mode == MODE_DRAGGING) { if (kcd->is_angle_snapping) knifetool_draw_angle_snapping(kcd); - glColor3ubv(kcd->colors.line); - + immUniformColor3ubv(kcd->colors.line); glLineWidth(2.0); - glBegin(GL_LINES); - glVertex3fv(kcd->prev.cage); - glVertex3fv(kcd->curr.cage); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, kcd->prev.cage); + immVertex3fv(pos, kcd->curr.cage); + immEnd(); } if (kcd->prev.vert) { - glColor3ubv(kcd->colors.point); + immUniformColor3ubv(kcd->colors.point); glPointSize(11); - glBegin(GL_POINTS); - glVertex3fv(kcd->prev.cage); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, kcd->prev.cage); + immEnd(); } if (kcd->prev.bmface) { - glColor3ubv(kcd->colors.curpoint); + immUniformColor3ubv(kcd->colors.curpoint); glPointSize(9); - glBegin(GL_POINTS); - glVertex3fv(kcd->prev.cage); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, kcd->prev.cage); + immEnd(); } if (kcd->curr.edge) { - glColor3ubv(kcd->colors.edge); + immUniformColor3ubv(kcd->colors.edge); glLineWidth(2.0); - glBegin(GL_LINES); - glVertex3fv(kcd->curr.edge->v1->cageco); - glVertex3fv(kcd->curr.edge->v2->cageco); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, kcd->curr.edge->v1->cageco); + immVertex3fv(pos, kcd->curr.edge->v2->cageco); + immEnd(); } else if (kcd->curr.vert) { - glColor3ubv(kcd->colors.point); + immUniformColor3ubv(kcd->colors.point); glPointSize(11); - glBegin(GL_POINTS); - glVertex3fv(kcd->curr.cage); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, kcd->curr.cage); + immEnd(); } if (kcd->curr.bmface) { - glColor3ubv(kcd->colors.curpoint); + immUniformColor3ubv(kcd->colors.curpoint); glPointSize(9); - glBegin(GL_POINTS); - glVertex3fv(kcd->curr.cage); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, kcd->curr.cage); + immEnd(); } if (kcd->totlinehit > 0) { @@ -1107,26 +1119,35 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* draw any snapped verts first */ - glColor4ubv(kcd->colors.point_a); + immUniformColor4ubv(kcd->colors.point_a); glPointSize(11); - glBegin(GL_POINTS); + + immBeginAtMost(GWN_PRIM_POINTS, kcd->totlinehit); + lh = kcd->linehits; for (i = 0; i < kcd->totlinehit; i++, lh++) { - if (lh->v) - glVertex3fv(lh->cagehit); + if (lh->v) { + immVertex3fv(pos, lh->cagehit); + } } - glEnd(); + + immEnd(); /* now draw the rest */ - glColor4ubv(kcd->colors.curpoint_a); + immUniformColor4ubv(kcd->colors.curpoint_a); glPointSize(7); - glBegin(GL_POINTS); + + immBeginAtMost(GWN_PRIM_POINTS, kcd->totlinehit); + lh = kcd->linehits; for (i = 0; i < kcd->totlinehit; i++, lh++) { - if (!lh->v) - glVertex3fv(lh->cagehit); + if (!lh->v) { + immVertex3fv(pos, lh->cagehit); + } } - glEnd(); + + immEnd(); + glDisable(GL_BLEND); } @@ -1134,44 +1155,46 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) BLI_mempool_iter iter; KnifeEdge *kfe; + immUniformColor3ubv(kcd->colors.line); glLineWidth(1.0); - glBegin(GL_LINES); + + immBeginAtMost(GWN_PRIM_LINES, BLI_mempool_count(kcd->kedges) * 2); BLI_mempool_iternew(kcd->kedges, &iter); for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) { if (!kfe->is_cut) continue; - glColor3ubv(kcd->colors.line); - - glVertex3fv(kfe->v1->cageco); - glVertex3fv(kfe->v2->cageco); + immVertex3fv(pos, kfe->v1->cageco); + immVertex3fv(pos, kfe->v2->cageco); } - glEnd(); + immEnd(); } if (kcd->totkvert > 0) { BLI_mempool_iter iter; KnifeVert *kfv; + immUniformColor3ubv(kcd->colors.point); glPointSize(5.0); - glBegin(GL_POINTS); + immBeginAtMost(GWN_PRIM_POINTS, BLI_mempool_count(kcd->kverts)); + BLI_mempool_iternew(kcd->kverts, &iter); for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) { if (!kfv->is_cut) continue; - glColor3ubv(kcd->colors.point); - - glVertex3fv(kfv->cageco); + immVertex3fv(pos, kfv->cageco); } - glEnd(); + immEnd(); } - glPopMatrix(); + immUnbindProgram(); + + gpuPopMatrix(); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } @@ -1394,7 +1417,7 @@ static bool bm_ray_cast_cb_elem_not_in_face_check(BMFace *f, void *user_data) * intersecting faces matching this face (or connected when an vert/edge) will be ignored. */ static bool point_is_visible( - KnifeTool_OpData *kcd, const float p[3], const float s[2], bglMats *mats, + KnifeTool_OpData *kcd, const float p[3], const float s[2], BMElem *ele_test) { BMFace *f_hit; @@ -1412,7 +1435,7 @@ static bool point_is_visible( float view[3], p_ofs[3]; /* TODO: I think there's a simpler way to get the required raycast ray */ - ED_view3d_unproject(mats, view, s[0], s[1], 0.0f); + ED_view3d_unproject(kcd->vc.ar, s[0], s[1], 0.0f, view); mul_m4_v3(kcd->ob->imat, view); @@ -1485,7 +1508,6 @@ static void set_linehit_depth(KnifeTool_OpData *kcd, KnifeLineHit *lh) /* Finds visible (or all, if cutting through) edges that intersects the current screen drag line */ static void knife_find_line_hits(KnifeTool_OpData *kcd) { - bglMats mats; SmallHash faces, kfes, kfvs; float v1[3], v2[3], v3[3], v4[3], s1[2], s2[2]; BVHTree *planetree, *tree; @@ -1515,8 +1537,6 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) const bool use_hit_prev = true; const bool use_hit_curr = (kcd->is_drag_hold == false); - bgl_get_mats(&mats); - if (kcd->linehits) { MEM_freeN(kcd->linehits); kcd->linehits = NULL; @@ -1645,7 +1665,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) knife_project_v2(kcd, v->cageco, s); d = dist_squared_to_line_segment_v2(s, s1, s2); if ((d <= vert_tol_sq) && - (point_is_visible(kcd, v->cageco, s, &mats, bm_elem_from_knife_vert(v, &kfe_hit)))) + (point_is_visible(kcd, v->cageco, s, bm_elem_from_knife_vert(v, &kfe_hit)))) { memset(&hit, 0, sizeof(hit)); hit.v = v; @@ -1708,7 +1728,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) * Need to find 3d intersection of ray through sint */ knife_input_ray_segment(kcd, sint, 1.0f, r1, r2); isect_kind = isect_line_line_v3(kfe->v1->cageco, kfe->v2->cageco, r1, r2, p_cage, p_cage_tmp); - if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, &mats, bm_elem_from_knife_edge(kfe))) { + if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, bm_elem_from_knife_edge(kfe))) { memset(&hit, 0, sizeof(hit)); if (kcd->snap_midpoints) { /* choose intermediate point snap too */ @@ -1737,7 +1757,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) float p[3], p_cage[3]; if (use_hit_prev && knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) { - if (point_is_visible(kcd, p_cage, s1, &mats, (BMElem *)f)) { + if (point_is_visible(kcd, p_cage, s1, (BMElem *)f)) { memset(&hit, 0, sizeof(hit)); hit.f = f; copy_v3_v3(hit.hit, p); @@ -1749,7 +1769,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) } if (use_hit_curr && knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) { - if (point_is_visible(kcd, p_cage, s2, &mats, (BMElem *)f)) { + if (point_is_visible(kcd, p_cage, s2, (BMElem *)f)) { memset(&hit, 0, sizeof(hit)); hit.f = f; copy_v3_v3(hit.hit, p); @@ -1782,13 +1802,9 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs, float r_origin[3], float r_origin_ofs[3]) { - bglMats mats; - - bgl_get_mats(&mats); - /* unproject to find view ray */ - ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f); - ED_view3d_unproject(&mats, r_origin_ofs, mval[0], mval[1], ofs); + ED_view3d_unproject(kcd->vc.ar, mval[0], mval[1], 0.0f, r_origin); + ED_view3d_unproject(kcd->vc.ar, mval[0], mval[1], ofs, r_origin_ofs); /* transform into object space */ invert_m4_m4(kcd->ob->imat, kcd->ob->obmat); @@ -1822,7 +1838,7 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float if (!f) { if (kcd->is_interactive) { /* try to use backbuffer selection method if ray casting failed */ - f = EDBM_face_find_nearest(&kcd->vc, &dist); + f = EDBM_face_find_nearest(&kcd->eval_ctx, &kcd->vc, &dist); /* cheat for now; just put in the origin instead * of a true coordinate on the face. @@ -2574,7 +2590,7 @@ static void knifetool_init_bmbvh(KnifeTool_OpData *kcd) { BM_mesh_elem_index_ensure(kcd->em->bm, BM_VERT); - kcd->cagecos = (const float (*)[3])BKE_editmesh_vertexCos_get(kcd->em, kcd->scene, NULL); + kcd->cagecos = (const float (*)[3])BKE_editmesh_vertexCos_get(&kcd->eval_ctx, kcd->em, kcd->scene, NULL); kcd->bmbvh = BKE_bmbvh_new_from_editmesh( kcd->em, @@ -2608,6 +2624,7 @@ static void knifetool_init(bContext *C, KnifeTool_OpData *kcd, kcd->ob = obedit; kcd->ar = CTX_wm_region(C); + CTX_data_eval_ctx(C, &kcd->eval_ctx); em_setup_viewcontext(C, &kcd->vc); kcd->em = BKE_editmesh_from_object(kcd->ob); @@ -2775,6 +2792,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_FINISHED; } + CTX_data_eval_ctx(C, &kcd->eval_ctx); em_setup_viewcontext(C, &kcd->vc); kcd->ar = kcd->vc.ar; @@ -3008,7 +3026,6 @@ static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2]) void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_through) { KnifeTool_OpData *kcd; - bglMats mats; view3d_operator_needs_opengl(C); @@ -3027,10 +3044,6 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug if (use_tag) { BM_mesh_elem_hflag_enable_all(kcd->em->bm, BM_EDGE, BM_ELEM_TAG, false); } - - if (kcd->cut_through == false) { - bgl_get_mats(&mats); - } } /* execute */ @@ -3139,7 +3152,7 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug float cent[3], cent_ss[2]; BM_face_calc_point_in_face(f, cent); knife_project_v2(kcd, cent, cent_ss); - if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, &mats, (BMElem *)f)) && + if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, (BMElem *)f)) && edbm_mesh_knife_point_isect(polys, cent_ss)) { BM_elem_flag_enable(f, BM_ELEM_TAG); diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index 0d3cc07589b..c98d22503e1 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -42,6 +42,8 @@ #include "BKE_editmesh.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "RNA_define.h" #include "RNA_access.h" @@ -56,13 +58,17 @@ #include "mesh_intern.h" /* own include */ -static LinkNode *knifeproject_poly_from_object(ARegion *ar, Scene *scene, Object *ob, LinkNode *polys) +static LinkNode *knifeproject_poly_from_object(const bContext *C, Scene *scene, Object *ob, LinkNode *polys) { + ARegion *ar = CTX_wm_region(C); + EvaluationContext eval_ctx; DerivedMesh *dm; bool dm_needsFree; + CTX_data_eval_ctx(C, &eval_ctx); + if (ob->type == OB_MESH || ob->derivedFinal) { - dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(&eval_ctx, scene, ob, CD_MASK_BAREMESH); dm_needsFree = false; } else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { @@ -116,7 +122,6 @@ static LinkNode *knifeproject_poly_from_object(ARegion *ar, Scene *scene, Object static int knifeproject_exec(bContext *C, wmOperator *op) { - ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -127,7 +132,7 @@ static int knifeproject_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { if (ob != obedit) { - polys = knifeproject_poly_from_object(ar, scene, ob, polys); + polys = knifeproject_poly_from_object(C, scene, ob, polys); } } CTX_DATA_END; diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index f1c1e4105d0..a4a6ad82dfb 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -45,7 +45,8 @@ #include "BKE_DerivedMesh.h" #include "BKE_unit.h" -#include "BIF_gl.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" #include "UI_interface.h" @@ -62,6 +63,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "DEG_depsgraph.h" + #include "mesh_intern.h" /* own include */ #define SUBD_SMOOTH_MAX 4.0f @@ -104,27 +107,41 @@ static void ringsel_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) if (v3d && v3d->zbuf) glDisable(GL_DEPTH_TEST); - glPushMatrix(); - glMultMatrixf(lcd->ob->obmat); + gpuPushMatrix(); + gpuMultMatrix(lcd->ob->obmat); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ub(255, 0, 255); - glColor3ub(255, 0, 255); if (lcd->totedge > 0) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, lcd->edges); - glDrawArrays(GL_LINES, 0, lcd->totedge * 2); - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(GWN_PRIM_LINES, lcd->totedge * 2); + + for (int i = 0; i < lcd->totedge; i++) { + immVertex3fv(pos, lcd->edges[i][0]); + immVertex3fv(pos, lcd->edges[i][1]); + } + + immEnd(); } if (lcd->totpoint > 0) { glPointSize(3.0f); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, lcd->points); - glDrawArrays(GL_POINTS, 0, lcd->totpoint); - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(GWN_PRIM_POINTS, lcd->totpoint); + + for (int i = 0; i < lcd->totpoint; i++) { + immVertex3fv(pos, lcd->points[i]); + } + + immEnd(); } - glPopMatrix(); + immUnbindProgram(); + + gpuPopMatrix(); + if (v3d && v3d->zbuf) glEnable(GL_DEPTH_TEST); } @@ -541,20 +558,23 @@ static void loopcut_update_edge(RingSelOpData *lcd, BMEdge *e, const int preview } } -static void loopcut_mouse_move(RingSelOpData *lcd, const int previewlines) +static void loopcut_mouse_move(const struct EvaluationContext *eval_ctx, RingSelOpData *lcd, const int previewlines) { float dist = ED_view3d_select_dist_px(); - BMEdge *e = EDBM_edge_find_nearest(&lcd->vc, &dist); + BMEdge *e = EDBM_edge_find_nearest(eval_ctx, &lcd->vc, &dist); loopcut_update_edge(lcd, e, previewlines); } /* called by both init() and exec() */ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) { + EvaluationContext eval_ctx; const bool is_interactive = (event != NULL); Object *obedit = CTX_data_edit_object(C); RingSelOpData *lcd; + CTX_data_eval_ctx(C, &eval_ctx); + if (modifiers_isDeformedByLattice(obedit) || modifiers_isDeformedByArmature(obedit)) BKE_report(op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display"); @@ -582,7 +602,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) if (is_interactive) { copy_v2_v2_int(lcd->vc.mval, event->mval); - loopcut_mouse_move(lcd, is_interactive ? 1 : 0); + loopcut_mouse_move(&eval_ctx, lcd, is_interactive ? 1 : 0); } else { const int e_index = RNA_int_get(op->ptr, "edge_index"); @@ -655,12 +675,14 @@ static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op) static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) { + EvaluationContext eval_ctx; RingSelOpData *lcd = op->customdata; float cuts = lcd->cuts; float smoothness = lcd->smoothness; bool show_cuts = false; const bool has_numinput = hasNumInput(&lcd->num); + CTX_data_eval_ctx(C, &eval_ctx); em_setup_viewcontext(C, &lcd->vc); lcd->ar = lcd->vc.ar; @@ -746,7 +768,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) if (!has_numinput) { lcd->vc.mval[0] = event->mval[0]; lcd->vc.mval[1] = event->mval[1]; - loopcut_mouse_move(lcd, (int)lcd->cuts); + loopcut_mouse_move(&eval_ctx, lcd, (int)lcd->cuts); ED_region_tag_redraw(lcd->ar); handled = true; diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index a85d2425b3c..b71dd029bf2 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -59,6 +59,8 @@ #include "bmesh.h" #include "bmesh_tools.h" +#include "DEG_depsgraph.h" + #include "mesh_intern.h" /* own include */ struct PathSelectParams { @@ -570,19 +572,19 @@ static bool edbm_shortest_path_pick_ex( static int edbm_shortest_path_pick_exec(bContext *C, wmOperator *op); -static BMElem *edbm_elem_find_nearest(ViewContext *vc, const char htype) +static BMElem *edbm_elem_find_nearest(const struct EvaluationContext *eval_ctx, ViewContext *vc, const char htype) { BMEditMesh *em = vc->em; float dist = ED_view3d_select_dist_px(); if ((em->selectmode & SCE_SELECT_VERTEX) && (htype == BM_VERT)) { - return (BMElem *)EDBM_vert_find_nearest(vc, &dist); + return (BMElem *)EDBM_vert_find_nearest(eval_ctx, vc, &dist); } else if ((em->selectmode & SCE_SELECT_EDGE) && (htype == BM_EDGE)) { - return (BMElem *)EDBM_edge_find_nearest(vc, &dist); + return (BMElem *)EDBM_edge_find_nearest(eval_ctx, vc, &dist); } else if ((em->selectmode & SCE_SELECT_FACE) && (htype == BM_FACE)) { - return (BMElem *)EDBM_face_find_nearest(vc, &dist); + return (BMElem *)EDBM_face_find_nearest(eval_ctx, vc, &dist); } return NULL; @@ -605,10 +607,12 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE return edbm_shortest_path_pick_exec(C, op); } + EvaluationContext eval_ctx; ViewContext vc; BMEditMesh *em; bool track_active = true; + CTX_data_eval_ctx(C, &eval_ctx); em_setup_viewcontext(C, &vc); copy_v2_v2_int(vc.mval, event->mval); em = vc.em; @@ -617,14 +621,14 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE BMElem *ele_src, *ele_dst; if (!(ele_src = edbm_elem_active_elem_or_face_get(em->bm)) || - !(ele_dst = edbm_elem_find_nearest(&vc, ele_src->head.htype))) + !(ele_dst = edbm_elem_find_nearest(&eval_ctx, &vc, ele_src->head.htype))) { /* special case, toggle edge tags even when we don't have a path */ if (((em->selectmode & SCE_SELECT_EDGE) && (vc.scene->toolsettings->edge_mode != EDGE_MODE_SELECT)) && /* check if we only have a destination edge */ ((ele_src == NULL) && - (ele_dst = edbm_elem_find_nearest(&vc, BM_EDGE)))) + (ele_dst = edbm_elem_find_nearest(&eval_ctx, &vc, BM_EDGE)))) { ele_src = ele_dst; track_active = false; diff --git a/source/blender/editors/mesh/editmesh_polybuild.c b/source/blender/editors/mesh/editmesh_polybuild.c new file mode 100644 index 00000000000..bfabd64396f --- /dev/null +++ b/source/blender/editors/mesh/editmesh_polybuild.c @@ -0,0 +1,541 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mesh/editmesh_polybuild.c + * \ingroup edmesh + * + * Tools to implement polygon building tool, + * an experimental tool for quickly constructing/manipulating faces. + */ + +#include "DNA_object_types.h" + +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_report.h" +#include "BKE_editmesh.h" +#include "BKE_mesh.h" + +#include "WM_types.h" + +#include "ED_mesh.h" +#include "ED_screen.h" +#include "ED_transform.h" +#include "ED_view3d.h" + +#include "bmesh.h" + +#include "mesh_intern.h" /* own include */ + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" + +/* -------------------------------------------------------------------- */ +/** \name Local Utilities + * \{ */ + +static void edbm_selectmode_ensure(Scene *scene, BMEditMesh *em, short selectmode) +{ + if ((scene->toolsettings->selectmode & selectmode) == 0) { + scene->toolsettings->selectmode |= selectmode; + em->selectmode = scene->toolsettings->selectmode; + EDBM_selectmode_set(em); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Face At Cursor + * \{ */ + +static int edbm_polybuild_face_at_cursor_invoke( + bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + ViewContext vc; + float center[3]; + bool changed = false; + + em_setup_viewcontext(C, &vc); + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + BMElem *ele_act = BM_mesh_active_elem_get(bm); + + invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); + + edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX); + + if (ele_act == NULL || ele_act->head.htype == BM_FACE) { + /* Just add vert */ + copy_v3_v3(center, ED_view3d_cursor3d_get(vc.scene, vc.v3d)); + mul_v3_m4v3(center, vc.obedit->obmat, center); + ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center); + mul_m4_v3(vc.obedit->imat, center); + + BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP); + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_vert_select_set(bm, v_new, true); + changed = true; + } + else if (ele_act->head.htype == BM_EDGE) { + BMEdge *e_act = (BMEdge *)ele_act; + BMFace *f_reference = e_act->l ? e_act->l->f : NULL; + + mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co); + mul_m4_v3(vc.obedit->obmat, center); + ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center); + mul_m4_v3(vc.obedit->imat, center); + + BMVert *v_tri[3]; + v_tri[0] = e_act->v1; + v_tri[1] = e_act->v2; + v_tri[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP); + if (e_act->l && e_act->l->v == v_tri[0]) { + SWAP(BMVert *, v_tri[0], v_tri[1]); + } + // BMFace *f_new = + BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true); + + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_vert_select_set(bm, v_tri[2], true); + changed = true; + } + else if (ele_act->head.htype == BM_VERT) { + BMVert *v_act = (BMVert *)ele_act; + BMEdge *e_pair[2] = {NULL}; + + if (v_act->e != NULL) { + for (uint allow_wire = 0; allow_wire < 2 && (e_pair[1] == NULL); allow_wire++) { + int i = 0; + BMEdge *e_iter = v_act->e; + do { + if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) && + (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter))) + { + if (i == 2) { + e_pair[0] = e_pair[1] = NULL; + break; + } + e_pair[i++] = e_iter; + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_act)) != v_act->e); + } + } + + if (e_pair[1] != NULL) { + /* Quad from edge pair. */ + if (BM_edge_calc_length_squared(e_pair[0]) < + BM_edge_calc_length_squared(e_pair[1])) + { + SWAP(BMEdge *, e_pair[0], e_pair[1]); + } + + BMFace *f_reference = e_pair[0]->l ? e_pair[0]->l->f : NULL; + + mul_v3_m4v3(center, vc.obedit->obmat, v_act->co); + ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center); + mul_m4_v3(vc.obedit->imat, center); + + BMVert *v_quad[4]; + v_quad[0] = v_act; + v_quad[1] = BM_edge_other_vert(e_pair[0], v_act); + v_quad[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP); + v_quad[3] = BM_edge_other_vert(e_pair[1], v_act); + if (e_pair[0]->l && e_pair[0]->l->v == v_quad[0]) { + SWAP(BMVert *, v_quad[1], v_quad[3]); + } + // BMFace *f_new = + BM_face_create_verts(bm, v_quad, 4, f_reference, BM_CREATE_NOP, true); + + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_vert_select_set(bm, v_quad[2], true); + changed = true; + } + else { + /* Just add edge */ + mul_m4_v3(vc.obedit->obmat, center); + ED_view3d_win_to_3d_int(vc.v3d, vc.ar, v_act->co, event->mval, center); + mul_m4_v3(vc.obedit->imat, center); + + BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP); + + BM_edge_create(bm, v_act, v_new, NULL, BM_CREATE_NOP); + + BM_vert_select_set(bm, v_new, true); + } + } + + if (changed) { + BM_select_history_clear(bm); + + EDBM_mesh_normals_update(em); + EDBM_update_generic(em, true, true); + + WM_event_add_mousemove(C); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MESH_OT_polybuild_face_at_cursor(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Poly Build Face At Cursor"; + ot->idname = "MESH_OT_polybuild_face_at_cursor"; + ot->description = ""; + + /* api callbacks */ + ot->invoke = edbm_polybuild_face_at_cursor_invoke; + ot->poll = EDBM_view3d_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* to give to transform */ + Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Split At Cursor + * \{ */ + +static int edbm_polybuild_split_at_cursor_invoke( + bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + ViewContext vc; + float center[3]; + bool changed = false; + + em_setup_viewcontext(C, &vc); + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + + invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); + + edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX); + + BMElem *ele_act = BM_mesh_active_elem_get(bm); + + if (ele_act == NULL || ele_act->head.hflag == BM_FACE) { + return OPERATOR_PASS_THROUGH; + } + else if (ele_act->head.htype == BM_EDGE) { + BMEdge *e_act = (BMEdge *)ele_act; + mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co); + mul_m4_v3(vc.obedit->obmat, center); + ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center); + mul_m4_v3(vc.obedit->imat, center); + + const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co); + BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, NULL, CLAMPIS(fac, 0.0f, 1.0f)); + copy_v3_v3(v_new->co, center); + + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_vert_select_set(bm, v_new, true); + changed = true; + } + else if (ele_act->head.htype == BM_VERT) { + /* Just do nothing, allow dragging. */ + return OPERATOR_FINISHED; + } + + if (changed) { + BM_select_history_clear(bm); + + EDBM_mesh_normals_update(em); + EDBM_update_generic(em, true, true); + + WM_event_add_mousemove(C); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MESH_OT_polybuild_split_at_cursor(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Poly Build Split At Cursor"; + ot->idname = "MESH_OT_polybuild_split_at_cursor"; + ot->description = ""; + + /* api callbacks */ + ot->invoke = edbm_polybuild_split_at_cursor_invoke; + ot->poll = EDBM_view3d_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* to give to transform */ + Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ +/** \name Dissolve At Cursor + * + * \{ */ + +static int edbm_polybuild_dissolve_at_cursor_invoke( + bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + ViewContext vc; + em_setup_viewcontext(C, &vc); + bool changed = false; + + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + BMVert *v_act = BM_mesh_active_vert_get(bm); + BMEdge *e_act = BM_mesh_active_edge_get(bm); + + invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); + + edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX); + + + if (e_act) { + BMLoop *l_a, *l_b; + if (BM_edge_loop_pair(e_act, &l_a, &l_b)) { + BMFace *f_new = BM_faces_join_pair(bm, l_a, l_b, true); + if (f_new) { + changed = true; + } + } + } + else if (v_act) { + if (BM_vert_is_edge_pair(v_act)) { + BM_edge_collapse( + bm, v_act->e, v_act, + true, true); + } + else { + /* too involved to do inline */ + if (!EDBM_op_callf(em, op, + "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b", + BM_ELEM_SELECT, false, true)) + { + return OPERATOR_CANCELLED; + } + } + changed = true; + } + + if (changed) { + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + + BM_select_history_clear(bm); + + EDBM_mesh_normals_update(em); + EDBM_update_generic(em, true, true); + + WM_event_add_mousemove(C); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MESH_OT_polybuild_dissolve_at_cursor(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Poly Build Dissolve At Cursor"; + ot->idname = "MESH_OT_polybuild_dissolve_at_cursor"; + ot->description = ""; + + /* api callbacks */ + ot->invoke = edbm_polybuild_dissolve_at_cursor_invoke; + ot->poll = EDBM_view3d_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Cursor Manipulator + * + * \note This may need its own file, for now not. + * \{ */ + +static BMElem *edbm_hover_preselect( + bContext *C, + const int mval[2], + bool use_boundary) +{ + ViewContext vc; + + em_setup_viewcontext(C, &vc); + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + + invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); + + const float mval_fl[2] = {UNPACK2(mval)}; + float ray_origin[3], ray_direction[3]; + + BMElem *ele_best = NULL; + + if (ED_view3d_win_to_ray( + vc.ar, vc.v3d, mval_fl, + ray_origin, ray_direction, true)) + { + BMEdge *e; + + BMIter eiter; + float dist_sq_best = FLT_MAX; + + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if ((BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) && + (!use_boundary || BM_edge_is_boundary(e))) + { + float dist_sq_test; + float point[3]; + float depth; +#if 0 + dist_sq_test = dist_squared_ray_to_seg_v3( + ray_origin, ray_direction, + e->v1->co, e->v2->co, + point, &depth); +#else + mid_v3_v3v3(point, e->v1->co, e->v2->co); + dist_sq_test = dist_squared_to_ray_v3( + ray_origin, ray_direction, + point, &depth); +#endif + + if (dist_sq_test < dist_sq_best) { + dist_sq_best = dist_sq_test; + ele_best = (BMElem *)e; + } + + dist_sq_test = dist_squared_to_ray_v3( + ray_origin, ray_direction, + e->v1->co, &depth); + if (dist_sq_test < dist_sq_best) { + dist_sq_best = dist_sq_test; + ele_best = (BMElem *)e->v1; + } + dist_sq_test = dist_squared_to_ray_v3( + ray_origin, ray_direction, + e->v2->co, &depth); + if (dist_sq_test < dist_sq_best) { + dist_sq_best = dist_sq_test; + ele_best = (BMElem *)e->v2; + } + } + } + } + return ele_best; +} + +/* + * Developer note: this is not advocating pre-selection highlighting. + * This is just a quick way to test how a tool for interactively editing polygons may work. */ +static int edbm_polybuild_hover_invoke( + bContext *C, wmOperator *op, const wmEvent *event) +{ + const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary"); + ViewContext vc; + + em_setup_viewcontext(C, &vc); + + /* Vertex selection is needed */ + if ((vc.scene->toolsettings->selectmode & SCE_SELECT_VERTEX) == 0) { + return OPERATOR_PASS_THROUGH; + } + + /* Don't overwrite click-drag events. */ + if (use_boundary == false) { + /* pass */ + } + else if (vc.win->tweak || + (vc.win->eventstate->check_click && + vc.win->eventstate->prevval == KM_PRESS && + ISMOUSE(vc.win->eventstate->prevtype))) + { + return OPERATOR_PASS_THROUGH; + } + + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + BMElem *ele_active = BM_mesh_active_elem_get(bm); + BMElem *ele_hover = edbm_hover_preselect(C, event->mval, use_boundary); + + if (ele_hover && (ele_hover != ele_active)) { + if (event->shift == 0) { + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_select_history_clear(bm); + } + BM_elem_select_set(bm, ele_hover, true); + BM_select_history_store(em->bm, ele_hover); + BKE_mesh_batch_cache_dirty(obedit->data, BKE_MESH_BATCH_DIRTY_SELECT); + + ED_region_tag_redraw(vc.ar); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MESH_OT_polybuild_hover(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Poly Build Hover"; + ot->idname = "MESH_OT_polybuild_hover"; + ot->description = ""; + + /* api callbacks */ + ot->invoke = edbm_polybuild_hover_invoke; + ot->poll = EDBM_view3d_poll; + + /* flags */ + ot->flag = OPTYPE_INTERNAL; + + /* properties */ + RNA_def_boolean(ot->srna, "use_boundary", false, "Boundary", "Select only boundary geometry"); +} + +/** \} */ diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 3f443b49a5e..0a0a8ff2de3 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -68,6 +68,8 @@ #include "bmesh_tools.h" +#include "DEG_depsgraph.h" + #include "mesh_intern.h" /* own include */ /* use bmesh operator flags for a few operators */ @@ -194,7 +196,9 @@ static BLI_bitmap *edbm_backbuf_alloc(const int size) /* reads rect, and builds selection array for quick lookup */ /* returns if all is OK */ -bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) +bool EDBM_backbuf_border_init( + const struct EvaluationContext *eval_ctx, ViewContext *vc, short xmin, + short ymin, short xmax, short ymax) { struct ImBuf *buf; unsigned int *dr; @@ -204,7 +208,7 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma return false; } - buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_backbuf_read(eval_ctx, vc, xmin, ymin, xmax, ymax); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; } @@ -267,7 +271,7 @@ static void edbm_mask_lasso_px_cb(int x, int x_end, int y, void *user_data) * - grab again and compare * returns 'OK' */ -bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax) +bool EDBM_backbuf_border_mask_init(const struct EvaluationContext *eval_ctx, ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax) { unsigned int *dr, *dr_mask, *dr_mask_arr; struct ImBuf *buf; @@ -284,7 +288,7 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short return false; } - buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_backbuf_read(eval_ctx, vc, xmin, ymin, xmax, ymax); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; } @@ -317,7 +321,9 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short } /* circle shaped sample area */ -bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) +bool EDBM_backbuf_circle_init( + const struct EvaluationContext *eval_ctx, ViewContext *vc, + short xs, short ys, short rads) { struct ImBuf *buf; unsigned int *dr; @@ -336,7 +342,7 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) xmin = xs - rads; xmax = xs + rads; ymin = ys - rads; ymax = ys + rads; - buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_backbuf_read(eval_ctx, vc, xmin, ymin, xmax, ymax); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; } @@ -435,7 +441,7 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float * \param use_cycle Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index. */ BMVert *EDBM_vert_find_nearest_ex( - ViewContext *vc, float *r_dist, + const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist, const bool use_select_bias, bool use_cycle) { BMesh *bm = vc->em->bm; @@ -447,10 +453,10 @@ BMVert *EDBM_vert_find_nearest_ex( BMVert *eve; /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ - ED_view3d_backbuf_validate(vc); + ED_view3d_backbuf_validate(eval_ctx, vc); index = ED_view3d_backbuf_sample_rect( - vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); + eval_ctx, vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; if (eve) { @@ -485,7 +491,7 @@ BMVert *EDBM_vert_find_nearest_ex( data.cycle_index_prev = prev_select_index; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag); + mesh_foreachScreenVert(eval_ctx, vc, findnearestvert__doClosest, &data, clip_flag); hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit; *r_dist = hit->dist; @@ -497,9 +503,9 @@ BMVert *EDBM_vert_find_nearest_ex( } } -BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist) +BMVert *EDBM_vert_find_nearest(const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist) { - return EDBM_vert_find_nearest_ex(vc, r_dist, false, false); + return EDBM_vert_find_nearest_ex(eval_ctx, vc, r_dist, false, false); } /* find the distance to the edge we already have */ @@ -621,7 +627,7 @@ static void find_nearest_edge__doClosest( } BMEdge *EDBM_edge_find_nearest_ex( - ViewContext *vc, float *r_dist, + const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist, float *r_dist_center, const bool use_select_bias, const bool use_cycle, BMEdge **r_eed_zbuf) @@ -635,9 +641,9 @@ BMEdge *EDBM_edge_find_nearest_ex( BMEdge *eed; /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ - ED_view3d_backbuf_validate(vc); + ED_view3d_backbuf_validate(eval_ctx, vc); - index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); + index = ED_view3d_backbuf_sample_rect(eval_ctx, vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; if (r_eed_zbuf) { @@ -655,7 +661,7 @@ BMEdge *EDBM_edge_find_nearest_ex( ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenEdge(vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenEdge(eval_ctx, vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); *r_dist_center = data.dist; } @@ -695,7 +701,7 @@ BMEdge *EDBM_edge_find_nearest_ex( data.cycle_index_prev = prev_select_index; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag); + mesh_foreachScreenEdge(eval_ctx, vc, find_nearest_edge__doClosest, &data, clip_flag); hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit; *r_dist = hit->dist; @@ -711,9 +717,9 @@ BMEdge *EDBM_edge_find_nearest_ex( } BMEdge *EDBM_edge_find_nearest( - ViewContext *vc, float *r_dist) + const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist) { - return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL); + return EDBM_edge_find_nearest_ex(eval_ctx, vc, r_dist, NULL, false, false, NULL); } /* find the distance to the face we already have */ @@ -787,7 +793,7 @@ static void findnearestface__doClosest(void *userData, BMFace *efa, const float BMFace *EDBM_face_find_nearest_ex( - ViewContext *vc, float *r_dist, + const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist, float *r_dist_center, const bool use_select_bias, const bool use_cycle, BMFace **r_efa_zbuf) @@ -799,9 +805,9 @@ BMFace *EDBM_face_find_nearest_ex( unsigned int index; BMFace *efa; - ED_view3d_backbuf_validate(vc); + ED_view3d_backbuf_validate(eval_ctx, vc); - index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]); + index = ED_view3d_backbuf_sample(eval_ctx, vc, vc->mval[0], vc->mval[1]); efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; if (r_efa_zbuf) { @@ -819,7 +825,7 @@ BMFace *EDBM_face_find_nearest_ex( ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenFace(vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenFace(eval_ctx, vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); *r_dist_center = data.dist; } @@ -857,7 +863,7 @@ BMFace *EDBM_face_find_nearest_ex( data.cycle_index_prev = prev_select_index; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag); + mesh_foreachScreenFace(eval_ctx, vc, findnearestface__doClosest, &data, clip_flag); hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit; *r_dist = hit->dist; @@ -872,9 +878,9 @@ BMFace *EDBM_face_find_nearest_ex( } } -BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) +BMFace *EDBM_face_find_nearest(const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist) { - return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL); + return EDBM_face_find_nearest_ex(eval_ctx, vc, r_dist, NULL, false, false, NULL); } #undef FIND_NEAR_SELECT_BIAS @@ -886,7 +892,9 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) * selected vertices and edges get disadvantage * return 1 if found one */ -static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa) +static int unified_findnearest( + const struct EvaluationContext *eval_ctx, ViewContext *vc, + BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa) { BMEditMesh *em = vc->em; static short mval_prev[2] = {-1, -1}; @@ -905,12 +913,12 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ - ED_view3d_backbuf_validate(vc); + ED_view3d_backbuf_validate(eval_ctx, vc); if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) { float dist_center = 0.0f; float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL; - efa = EDBM_face_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf); + efa = EDBM_face_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf); if (efa && dist_center_p) { dist = min_ff(dist_margin, dist_center); } @@ -919,14 +927,14 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { float dist_center = 0.0f; float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL; - eed = EDBM_edge_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf); + eed = EDBM_edge_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf); if (eed && dist_center_p) { dist = min_ff(dist_margin, dist_center); } } if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) { - eve = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle); + eve = EDBM_vert_find_nearest_ex(eval_ctx, vc, &dist, true, use_cycle); } /* return only one of 3 pointers, for frontbuffer redraws */ @@ -989,13 +997,13 @@ static const EnumPropertyItem prop_similar_types[] = { #endif {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""}, - {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""}, {SIMFACE_AREA, "AREA", 0, "Area", ""}, {SIMFACE_SIDES, "SIDES", 0, "Polygon Sides", ""}, {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""}, {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""}, {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""}, {SIMFACE_SMOOTH, "SMOOTH", 0, "Flat/Smooth", ""}, + {SIMFACE_FACEMAP, "FACE_MAP", 0, "Face-Map", ""}, #ifdef WITH_FREESTYLE {SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""}, #endif @@ -1173,7 +1181,7 @@ static const EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA #ifdef WITH_FREESTYLE const int a_end = SIMFACE_FREESTYLE; #else - const int a_end = SIMFACE_SMOOTH; + const int a_end = SIMFACE_FACEMAP; #endif for (a = SIMFACE_MATERIAL; a <= a_end; a++) { RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a); @@ -1559,6 +1567,7 @@ static void mouse_mesh_loop_edge(BMEditMesh *em, BMEdge *eed, bool select, bool static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool ring) { + EvaluationContext eval_ctx; ViewContext vc; BMEditMesh *em; BMEdge *eed; @@ -1568,15 +1577,16 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de float dist = ED_view3d_select_dist_px() * 0.6666f; float mvalf[2]; + CTX_data_eval_ctx(C, &eval_ctx); em_setup_viewcontext(C, &vc); mvalf[0] = (float)(vc.mval[0] = mval[0]); mvalf[1] = (float)(vc.mval[1] = mval[1]); em = vc.em; /* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */ - ED_view3d_backbuf_validate(&vc); + ED_view3d_backbuf_validate(&eval_ctx, &vc); - eed = EDBM_edge_find_nearest_ex(&vc, &dist, NULL, true, true, NULL); + eed = EDBM_edge_find_nearest_ex(&eval_ctx, &vc, &dist, NULL, true, true, NULL); if (eed == NULL) { return false; } @@ -1819,17 +1829,19 @@ void MESH_OT_select_interior_faces(wmOperatorType *ot) /* gets called via generic mouse select operator */ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) { + EvaluationContext eval_ctx; ViewContext vc; BMVert *eve = NULL; BMEdge *eed = NULL; BMFace *efa = NULL; /* setup view context for argument to callbacks */ + CTX_data_eval_ctx(C, &eval_ctx); em_setup_viewcontext(C, &vc); vc.mval[0] = mval[0]; vc.mval[1] = mval[1]; - if (unified_findnearest(&vc, &eve, &eed, &efa)) { + if (unified_findnearest(&eval_ctx, &vc, &eve, &eed, &efa)) { /* Deselect everything */ if (extend == false && deselect == false && toggle == false) @@ -1916,12 +1928,30 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect EDBM_selectmode_flush(vc.em); - /* change active material on object */ - if (efa && efa->mat_nr != vc.obedit->actcol - 1) { - vc.obedit->actcol = efa->mat_nr + 1; - vc.em->mat_nr = efa->mat_nr; + if (efa) { + /* Change active material on object. */ + if (efa->mat_nr != vc.obedit->actcol - 1) { + vc.obedit->actcol = efa->mat_nr + 1; + vc.em->mat_nr = efa->mat_nr; + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL); + } - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL); + /* Change active face-map on object. */ + if (!BLI_listbase_is_empty(&vc.obedit->fmaps)) { + const int cd_fmap_offset = CustomData_get_offset(&vc.em->bm->pdata, CD_FACEMAP); + if (cd_fmap_offset != -1) { + int map = *((int *)BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset)); + if ((map < -1) || (map > BLI_listbase_count_ex(&vc.obedit->fmaps, map))) { + map = -1; + } + map += 1; + if (map != vc.obedit->actfmap) { + /* We may want to add notifiers later, + * currently select update handles redraw. */ + vc.obedit->actfmap = map; + } + } + } } @@ -2775,6 +2805,7 @@ static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, in static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *obedit = CTX_data_edit_object(C); + EvaluationContext eval_ctx; ViewContext vc; BMEditMesh *em; BMesh *bm; @@ -2792,6 +2823,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE view3d_operator_needs_opengl(C); /* setup view context for argument to callbacks */ + CTX_data_eval_ctx(C, &eval_ctx); em_setup_viewcontext(C, &vc); em = vc.em; bm = em->bm; @@ -2804,7 +2836,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE vc.mval[1] = event->mval[1]; /* return warning! */ - if (unified_findnearest(&vc, &eve, &eed, &efa) == 0) { + if (unified_findnearest(&eval_ctx, &vc, &eve, &eed, &efa) == 0) { WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit); return OPERATOR_CANCELLED; diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index bc251869e3d..cee9ee90b24 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -47,15 +47,18 @@ #include "BLI_rand.h" #include "BLI_sort_utils.h" +#include "BKE_layer.h" #include "BKE_material.h" #include "BKE_context.h" #include "BKE_deform.h" -#include "BKE_depsgraph.h" #include "BKE_report.h" #include "BKE_texture.h" #include "BKE_main.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "BLT_translation.h" #include "RNA_define.h" @@ -306,7 +309,7 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em) ED_view3d_init_mats_rv3d(obedit, ar->regiondata); struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), 0, + CTX_data_main(C), CTX_data_scene(C), CTX_data_scene_layer(C), CTX_data_engine(C), 0, ar, CTX_wm_view3d(C)); BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { @@ -2451,7 +2454,7 @@ static void shape_propagate(BMEditMesh *em, wmOperator *op) //TAG Mesh Objects that share this data for (base = scene->base.first; base; base = base->next) { if (base->object && base->object->data == me) { - DAG_id_tag_update(&base->object->id, OB_RECALC_DATA); + DEG_id_tag_update(&base->object->id, OB_RECALC_DATA); } } #endif @@ -3014,7 +3017,7 @@ enum { MESH_SEPARATE_LOOSE = 2, }; -static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) +static Base *mesh_separate_tagged(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old) { Base *base_new; Object *obedit = base_old->object; @@ -3035,11 +3038,11 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe CustomData_bmesh_init_pool(&bm_new->ldata, bm_mesh_allocsize_default.totloop, BM_LOOP); CustomData_bmesh_init_pool(&bm_new->pdata, bm_mesh_allocsize_default.totface, BM_FACE); - base_new = ED_object_add_duplicate(bmain, scene, base_old, USER_DUP_MESH); + base_new = ED_object_add_duplicate(bmain, scene, sl, base_old, USER_DUP_MESH); /* DAG_relations_tag_update(bmain); */ /* normally would call directly after but in this case delay recalc */ assign_matarar(base_new->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */ - ED_base_object_select(base_new, BA_SELECT); + ED_object_base_select(base_new, BA_SELECT); BMO_op_callf(bm_old, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "duplicate geom=%hvef dest=%p", BM_ELEM_TAG, bm_new); @@ -3061,7 +3064,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe return base_new; } -static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) +static bool mesh_separate_selected(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old) { /* we may have tags from previous operators */ BM_mesh_elem_hflag_disable_all(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, false); @@ -3069,7 +3072,7 @@ static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BM /* sel -> tag */ BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, true, false, BM_ELEM_SELECT); - return (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL); + return (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL); } /* flush a hflag to from verts to edges/faces */ @@ -3168,7 +3171,7 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const } } -static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) +static bool mesh_separate_material(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old) { BMFace *f_cmp, *f; BMIter iter; @@ -3209,7 +3212,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM } /* Move selection into a separate object */ - base_new = mesh_separate_tagged(bmain, scene, base_old, bm_old); + base_new = mesh_separate_tagged(bmain, scene, sl, base_old, bm_old); if (base_new) { mesh_separate_material_assign_mat_nr(bmain, base_new->object, mat_nr); } @@ -3220,7 +3223,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM return result; } -static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) +static bool mesh_separate_loose(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old) { int i; BMEdge *e; @@ -3273,7 +3276,7 @@ static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh bm_mesh_hflag_flush_vert(bm_old, BM_ELEM_TAG); /* Move selection into a separate object */ - result |= (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL); + result |= (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL); } return result; @@ -3283,6 +3286,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); const int type = RNA_enum_get(op->ptr, "type"); int retval = 0; @@ -3303,13 +3307,13 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) /* editmode separate */ switch (type) { case MESH_SEPARATE_SELECTED: - retval = mesh_separate_selected(bmain, scene, base, em->bm); + retval = mesh_separate_selected(bmain, scene, sl, base, em->bm); break; case MESH_SEPARATE_MATERIAL: - retval = mesh_separate_material(bmain, scene, base, em->bm); + retval = mesh_separate_material(bmain, scene, sl, base, em->bm); break; case MESH_SEPARATE_LOOSE: - retval = mesh_separate_loose(bmain, scene, base, em->bm); + retval = mesh_separate_loose(bmain, scene, sl, base, em->bm); break; default: BLI_assert(0); @@ -3344,10 +3348,10 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) switch (type) { case MESH_SEPARATE_MATERIAL: - retval_iter = mesh_separate_material(bmain, scene, base_iter, bm_old); + retval_iter = mesh_separate_material(bmain, scene, sl, base_iter, bm_old); break; case MESH_SEPARATE_LOOSE: - retval_iter = mesh_separate_loose(bmain, scene, base_iter, bm_old); + retval_iter = mesh_separate_loose(bmain, scene, sl, base_iter, bm_old); break; default: BLI_assert(0); @@ -3357,7 +3361,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) if (retval_iter) { BM_mesh_bm_to_me(bm_old, me, (&(struct BMeshToMeshParams){0})); - DAG_id_tag_update(&me->id, OB_RECALC_DATA); + DEG_id_tag_update(&me->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); } @@ -3372,7 +3376,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) if (retval) { /* delay depsgraph recalc until all objects are duplicated */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); return OPERATOR_FINISHED; @@ -5063,7 +5067,7 @@ static void sort_bmelem_flag(Scene *scene, Object *ob, } BM_mesh_remap(em->bm, map[0], map[1], map[2]); -/* DAG_id_tag_update(ob->data, 0);*/ +/* DEG_id_tag_update(ob->data, 0);*/ for (j = 3; j--; ) { if (map[j]) @@ -5890,7 +5894,7 @@ static int edbm_mark_freestyle_edge_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(obedit->data, OB_RECALC_DATA); + DEG_id_tag_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -5954,7 +5958,7 @@ static int edbm_mark_freestyle_face_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(obedit->data, OB_RECALC_DATA); + DEG_id_tag_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 8baf5d05fe9..230f46abad1 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -44,7 +44,6 @@ #include "BKE_DerivedMesh.h" #include "BKE_context.h" #include "BKE_global.h" -#include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" @@ -52,6 +51,8 @@ #include "BKE_editmesh.h" #include "BKE_editmesh_bvh.h" +#include "DEG_depsgraph.h" + #include "BKE_object.h" /* XXX. only for EDBM_mesh_ensure_valid_dm_hack() which will be removed */ #include "WM_api.h" @@ -116,7 +117,7 @@ void EDBM_mesh_ensure_valid_dm_hack(Scene *scene, BMEditMesh *em) { /* since we may not have done selection flushing */ if ((em->ob->recalc & OB_RECALC_DATA) == 0) { - DAG_id_tag_update(&em->ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&em->ob->id, OB_RECALC_DATA); } BKE_object_handle_update(G.main->eval_ctx, scene, em->ob); } @@ -382,7 +383,7 @@ void EDBM_mesh_make(ToolSettings *ts, Object *ob, const bool add_key_index) /** * \warning This can invalidate the #DerivedMesh cache of other objects (for linked duplicates). - * Most callers should run #DAG_id_tag_update on \a ob->data, see: T46738, T46913 + * Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913 */ void EDBM_mesh_load(Object *ob) { @@ -520,7 +521,6 @@ UvVertMap *BM_uv_vert_map_create( /* vars from original func */ UvVertMap *vmap; UvMapVert *buf; - /* MTexPoly *tf; */ /* UNUSED */ MLoopUV *luv; unsigned int a; int totverts, i, totuv, totfaces; @@ -602,7 +602,6 @@ UvVertMap *BM_uv_vert_map_create( newvlist = v; efa = BM_face_at_index(bm, v->f); - /* tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->tfindex); luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); @@ -614,7 +613,6 @@ UvVertMap *BM_uv_vert_map_create( while (iterv) { next = iterv->next; efa = BM_face_at_index(bm, iterv->f); - /* tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex); luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); @@ -929,29 +927,27 @@ UvElement *BM_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l) /* last_sel, use em->act_face otherwise get the last selected face in the editselections * at the moment, last_sel is mainly useful for making sure the space image dosnt flicker */ -MTexPoly *EDBM_mtexpoly_active_get(BMEditMesh *em, BMFace **r_act_efa, const bool sloppy, const bool selected) +BMFace *EDBM_uv_active_face_get(BMEditMesh *em, const bool sloppy, const bool selected) { BMFace *efa = NULL; - if (!EDBM_mtexpoly_check(em)) + if (!EDBM_uv_check(em)) return NULL; efa = BM_mesh_active_face_get(em->bm, sloppy, selected); if (efa) { - if (r_act_efa) *r_act_efa = efa; - return CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + return efa; } - if (r_act_efa) *r_act_efa = NULL; return NULL; } /* can we edit UV's for this mesh?*/ -bool EDBM_mtexpoly_check(BMEditMesh *em) +bool EDBM_uv_check(BMEditMesh *em) { /* some of these checks could be a touch overkill */ - return em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY) && + return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV); } @@ -1280,7 +1276,7 @@ void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_d { Object *ob = em->ob; /* order of calling isn't important */ - DAG_id_tag_update(ob->data, OB_RECALC_DATA); + DEG_id_tag_update(ob->data, OB_RECALC_DATA); WM_main_add_notifier(NC_GEOM | ND_DATA, ob->data); if (do_tessface) { diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index bd7aaec075b..218b97d3ede 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -42,7 +42,6 @@ #include "BLI_math.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -50,6 +49,8 @@ #include "BKE_report.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" + #include "RNA_define.h" #include "WM_api.h" @@ -245,14 +246,14 @@ void ED_mesh_uv_loop_reset_ex(struct Mesh *me, const int layernum) } } - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); } void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me) { /* could be ldata or pdata */ - CustomData *pdata = GET_CD_DATA(me, pdata); - const int layernum = CustomData_get_active_layer(pdata, CD_MTEXPOLY); + CustomData *ldata = GET_CD_DATA(me, ldata); + const int layernum = CustomData_get_active_layer(ldata, CD_MLOOPUV); ED_mesh_uv_loop_reset_ex(me, layernum); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); @@ -269,21 +270,10 @@ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set) if (me->edit_btmesh) { em = me->edit_btmesh; - layernum_dst = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY); + layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV); if (layernum_dst >= MAX_MTFACE) return -1; - /* CD_MTEXPOLY */ - BM_data_layer_add_named(em->bm, &em->bm->pdata, CD_MTEXPOLY, name); - /* copy data from active UV */ - if (layernum_dst) { - const int layernum_src = CustomData_get_active_layer(&em->bm->pdata, CD_MTEXPOLY); - BM_data_layer_copy(em->bm, &em->bm->pdata, CD_MTEXPOLY, layernum_src, layernum_dst); - } - if (active_set || layernum_dst == 0) { - CustomData_set_layer_active(&em->bm->pdata, CD_MTEXPOLY, layernum_dst); - } - /* CD_MLOOPUV */ BM_data_layer_add_named(em->bm, &em->bm->ldata, CD_MLOOPUV, name); /* copy data from active UV */ @@ -298,26 +288,22 @@ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set) } } else { - layernum_dst = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); + layernum_dst = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); if (layernum_dst >= MAX_MTFACE) return -1; - if (me->mtpoly) { - CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DUPLICATE, me->mtpoly, me->totpoly, name); + if (me->mloopuv) { CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DUPLICATE, me->mloopuv, me->totloop, name); CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name); is_init = true; } else { - CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, name); CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, name); CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface, name); } if (active_set || layernum_dst == 0) { - CustomData_set_layer_active(&me->pdata, CD_MTEXPOLY, layernum_dst); CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, layernum_dst); - CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum_dst); } @@ -329,7 +315,7 @@ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set) ED_mesh_uv_loop_reset_ex(me, layernum_dst); } - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, me); return layernum_dst; @@ -343,12 +329,12 @@ void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name) if (me->edit_btmesh) { em = me->edit_btmesh; - layernum_dst = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY); + layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV); if (layernum_dst == 0) ED_mesh_uv_texture_add(me, name, true); } else { - layernum_dst = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); + layernum_dst = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); if (layernum_dst == 0) ED_mesh_uv_texture_add(me, name, true); } @@ -357,23 +343,19 @@ void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name) bool ED_mesh_uv_texture_remove_index(Mesh *me, const int n) { - CustomData *pdata = GET_CD_DATA(me, pdata), *ldata = GET_CD_DATA(me, ldata); - CustomDataLayer *cdlp, *cdlu; + CustomData *ldata = GET_CD_DATA(me, ldata); + CustomDataLayer *cdlu; int index; - index = CustomData_get_layer_index_n(pdata, CD_MTEXPOLY, n); - cdlp = (index == -1) ? NULL : &pdata->layers[index]; - index = CustomData_get_layer_index_n(ldata, CD_MLOOPUV, n); cdlu = (index == -1) ? NULL : &ldata->layers[index]; - if (!cdlp || !cdlu) + if (!cdlu) return false; - delete_customdata_layer(me, cdlp); delete_customdata_layer(me, cdlu); - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, me); return true; @@ -381,14 +363,8 @@ bool ED_mesh_uv_texture_remove_index(Mesh *me, const int n) bool ED_mesh_uv_texture_remove_active(Mesh *me) { /* texpoly/uv are assumed to be in sync */ - CustomData *pdata = GET_CD_DATA(me, pdata); - const int n = CustomData_get_active_layer(pdata, CD_MTEXPOLY); - - /* double check active layers align! */ -#ifdef DEBUG CustomData *ldata = GET_CD_DATA(me, ldata); - BLI_assert(CustomData_get_active_layer(ldata, CD_MLOOPUV) == n); -#endif + const int n = CustomData_get_active_layer(ldata, CD_MLOOPUV); if (n != -1) { return ED_mesh_uv_texture_remove_index(me, n); @@ -400,8 +376,8 @@ bool ED_mesh_uv_texture_remove_active(Mesh *me) bool ED_mesh_uv_texture_remove_named(Mesh *me, const char *name) { /* texpoly/uv are assumed to be in sync */ - CustomData *pdata = GET_CD_DATA(me, pdata); - const int n = CustomData_get_named_layer(pdata, CD_MTEXPOLY, name); + CustomData *ldata = GET_CD_DATA(me, ldata); + const int n = CustomData_get_named_layer(ldata, CD_MLOOPUV, name); if (n != -1) { return ED_mesh_uv_texture_remove_index(me, n); } @@ -458,7 +434,7 @@ int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set) BKE_mesh_update_customdata_pointers(me, true); } - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, me); return layernum; @@ -473,7 +449,7 @@ bool ED_mesh_color_ensure(struct Mesh *me, const char *name) BKE_mesh_update_customdata_pointers(me, true); } - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); return (me->mloopcol != NULL); } @@ -491,7 +467,7 @@ bool ED_mesh_color_remove_index(Mesh *me, const int n) return false; delete_customdata_layer(me, cdl); - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, me); return true; @@ -612,7 +588,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e /* load_editMesh free's pointers used by CustomData layers which might be used by DerivedMesh too, * so signal to re-create DerivedMesh here (sergey) */ - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); } /* dummie drop support; ensure view shows a result :) */ @@ -751,7 +727,7 @@ static int mesh_customdata_clear_exec__internal(bContext *C, CustomData_free_layers(data, type, tot); } - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); return OPERATOR_FINISHED; @@ -847,7 +823,7 @@ static int mesh_customdata_skin_add_exec(bContext *C, wmOperator *UNUSED(op)) BKE_mesh_ensure_skin_customdata(me); - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); return OPERATOR_FINISHED; @@ -909,7 +885,7 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator CustomData_add_layer(data, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, me->totloop); } - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); return OPERATOR_FINISHED; @@ -986,7 +962,7 @@ void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges, int calc_tessface) BKE_mesh_calc_normals(mesh); - DAG_id_tag_update(&mesh->id, 0); + DEG_id_tag_update(&mesh->id, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, mesh); } @@ -1306,7 +1282,6 @@ void ED_mesh_calc_tessface(Mesh *mesh, bool free_mpoly) mesh->mloopcol = NULL; mesh->mloopuv = NULL; mesh->mpoly = NULL; - mesh->mtpoly = NULL; } } diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 300b21a052d..99342222d52 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -109,6 +109,11 @@ void MESH_OT_dupli_extrude_cursor(struct wmOperatorType *ot); void MESH_OT_spin(struct wmOperatorType *ot); void MESH_OT_screw(struct wmOperatorType *ot); +/* *** editmesh_polybuild.c *** */ +void MESH_OT_polybuild_face_at_cursor(struct wmOperatorType *ot); +void MESH_OT_polybuild_split_at_cursor(struct wmOperatorType *ot); +void MESH_OT_polybuild_dissolve_at_cursor(struct wmOperatorType *ot); +void MESH_OT_polybuild_hover(struct wmOperatorType *ot); /* *** editmesh_inset.c *** */ void MESH_OT_inset(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c index b95921964eb..a340e23efc5 100644 --- a/source/blender/editors/mesh/mesh_navmesh.c +++ b/source/blender/editors/mesh/mesh_navmesh.c @@ -40,8 +40,8 @@ #include "BLI_math_vector.h" #include "BLI_linklist.h" +#include "BKE_layer.h" #include "BKE_library.h" -#include "BKE_depsgraph.h" #include "BKE_context.h" #include "BKE_mesh.h" #include "BKE_scene.h" @@ -58,6 +58,8 @@ #include "recast-capi.h" +#include "DEG_depsgraph.h" + #include "mesh_intern.h" /* own include */ @@ -72,18 +74,21 @@ static void createVertsTrisData(bContext *C, LinkNode *obs, LinkNode *oblink, *dmlink; DerivedMesh *dm; Scene *scene = CTX_data_scene(C); + EvaluationContext eval_ctx; LinkNode *dms = NULL; int nverts, ntris, *tris; float *verts; + CTX_data_eval_ctx(C, &eval_ctx); + nverts = 0; ntris = 0; /* calculate number of verts and tris */ for (oblink = obs; oblink; oblink = oblink->next) { ob = (Object *) oblink->link; - dm = mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH); + dm = mesh_create_derived_no_virtual(&eval_ctx, scene, ob, NULL, CD_MASK_MESH); DM_ensure_tessface(dm); BLI_linklist_prepend(&dms, dm); @@ -333,7 +338,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, int i, j, k; unsigned short *v; int face[3]; - Scene *scene = CTX_data_scene(C); + SceneLayer *scene_layer = CTX_data_scene_layer(C); Object *obedit; int createob = base == NULL; int nverts, nmeshes, nvp; @@ -351,8 +356,8 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, } else { obedit = base->object; - BKE_scene_base_deselect_all(scene); - BKE_scene_base_select(scene, base); + BKE_scene_layer_base_deselect_all(scene_layer); + BKE_scene_layer_base_select(scene_layer, base); copy_v3_v3(obedit->loc, co); copy_v3_v3(obedit->rot, rot); } @@ -440,7 +445,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, recast_destroyPolyMesh(pmesh); recast_destroyPolyMeshDetail(dmesh); - DAG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); + DEG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); @@ -461,6 +466,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, static int navmesh_create_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); + SceneLayer *scene_layer = CTX_data_scene_layer(C); LinkNode *obs = NULL; Base *navmeshBase = NULL; @@ -468,7 +474,7 @@ static int navmesh_create_exec(bContext *C, wmOperator *op) { if (base->object->type == OB_MESH) { if (base->object->body_type == OB_BODY_TYPE_NAVMESH) { - if (!navmeshBase || base == scene->basact) { + if (!navmeshBase || base == scene_layer->basact) { navmeshBase = base; } } @@ -551,7 +557,7 @@ static int navmesh_face_copy_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); + DEG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -632,7 +638,7 @@ static int navmesh_face_add_exec(bContext *C, wmOperator *UNUSED(op)) } } - DAG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); + DEG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -681,7 +687,7 @@ static int navmesh_reset_exec(bContext *C, wmOperator *UNUSED(op)) BKE_mesh_ensure_navmesh(me); - DAG_id_tag_update(&me->id, OB_RECALC_DATA); + DEG_id_tag_update(&me->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, &me->id); return OPERATOR_FINISHED; @@ -709,7 +715,7 @@ static int navmesh_clear_exec(bContext *C, wmOperator *UNUSED(op)) CustomData_free_layers(&me->pdata, CD_RECAST, me->totpoly); - DAG_id_tag_update(&me->id, OB_RECALC_DATA); + DEG_id_tag_update(&me->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, &me->id); return OPERATOR_FINISHED; diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 697a92f36d1..b9920f9deca 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -147,7 +147,13 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_rip_edge); WM_operatortype_append(MESH_OT_blend_from_shape); WM_operatortype_append(MESH_OT_shape_propagate_to_all); - + + /* editmesh_polybuild */ + WM_operatortype_append(MESH_OT_polybuild_face_at_cursor); + WM_operatortype_append(MESH_OT_polybuild_split_at_cursor); + WM_operatortype_append(MESH_OT_polybuild_dissolve_at_cursor); + WM_operatortype_append(MESH_OT_polybuild_hover); + WM_operatortype_append(MESH_OT_uv_texture_add); WM_operatortype_append(MESH_OT_uv_texture_remove); WM_operatortype_append(MESH_OT_vertex_color_add); @@ -298,6 +304,23 @@ void ED_operatormacros_mesh(void) otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); RNA_enum_set(otmacro->ptr, "proportional", 0); RNA_boolean_set(otmacro->ptr, "mirror", false); + + + ot = WM_operatortype_append_macro( + "MESH_OT_polybuild_face_at_cursor_move", "Face At Cursor Move", "", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "MESH_OT_polybuild_face_at_cursor"); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_enum_set(otmacro->ptr, "proportional", 0); + RNA_boolean_set(otmacro->ptr, "mirror", false); + + ot = WM_operatortype_append_macro( + "MESH_OT_polybuild_split_at_cursor_move", "Split At Cursor Move", "", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "MESH_OT_polybuild_split_at_cursor"); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_enum_set(otmacro->ptr, "proportional", 0); + RNA_boolean_set(otmacro->ptr, "mirror", false); } /* note mesh keymap also for other space? */ diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index c900373a59c..dd1fbc36d8a 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -49,7 +49,6 @@ #include "BLI_kdtree.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_deform.h" #include "BKE_DerivedMesh.h" #include "BKE_key.h" @@ -62,6 +61,9 @@ #include "BKE_editmesh.h" #include "BKE_multires.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "ED_mesh.h" #include "ED_object.h" #include "ED_view3d.h" @@ -77,7 +79,7 @@ * return 0 if no join is made (error) and 1 if the join is done */ static void join_mesh_single( - Main *bmain, Scene *scene, + bContext *C, Main *bmain, Scene *scene, Object *ob_dst, Object *ob_src, float imat[4][4], MVert **mvert_pp, MEdge **medge_pp, MLoop **mloop_pp, MPoly **mpoly_pp, CustomData *vdata, CustomData *edata, CustomData *ldata, CustomData *pdata, @@ -86,6 +88,7 @@ static void join_mesh_single( Material **matar, int *matmap, int totcol, int *vertofs, int *edgeofs, int *loopofs, int *polyofs) { + EvaluationContext eval_ctx; int a, b; Mesh *me = ob_src->data; @@ -94,6 +97,8 @@ static void join_mesh_single( MLoop *mloop = *mloop_pp; MPoly *mpoly = *mpoly_pp; + CTX_data_eval_ctx(C, &eval_ctx); + if (me->totvert) { /* merge customdata flag */ ((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag; @@ -214,7 +219,7 @@ static void join_mesh_single( if (ob_src != ob_dst) { MultiresModifierData *mmd; - multiresModifier_prepare_join(scene, ob_src, ob_dst); + multiresModifier_prepare_join(&eval_ctx, scene, ob_src, ob_dst); if ((mmd = get_multires_modifier(scene, ob_src, true))) { ED_object_iter_other(bmain, ob_src, true, @@ -493,7 +498,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) * active mesh will remain first ones in new result of the merge, in same order for CD layers, etc. See also T50084. */ join_mesh_single( - bmain, scene, + C, bmain, scene, ob, ob, imat, &mvert, &medge, &mloop, &mpoly, &vdata, &edata, &ldata, &pdata, @@ -510,7 +515,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) /* only join if this is a mesh */ if (base->object->type == OB_MESH) { join_mesh_single( - bmain, scene, + C, bmain, scene, ob, base->object, imat, &mvert, &medge, &mloop, &mpoly, &vdata, &edata, &ldata, &pdata, @@ -521,7 +526,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) /* free base, now that data is merged */ if (base->object != ob) { - ED_base_object_free_and_unlink(bmain, scene, base); + ED_object_base_free_and_unlink(bmain, scene, base->object); } } } @@ -594,9 +599,9 @@ int join_mesh_exec(bContext *C, wmOperator *op) /* Due to dependnecy cycle some other object might access old derived data. */ BKE_object_free_derived_caches(ob); - DAG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */ + DEG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */ - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); @@ -612,6 +617,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); + EvaluationContext eval_ctx; Mesh *me = (Mesh *)ob->data; Mesh *selme = NULL; DerivedMesh *dm = NULL; @@ -619,6 +625,8 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) KeyBlock *kb; bool ok = false, nonequal_verts = false; + CTX_data_eval_ctx(C, &eval_ctx); + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { if (base->object == ob) continue; @@ -660,7 +668,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) selme = (Mesh *)base->object->data; if (selme->totvert == me->totvert) { - dm = mesh_get_derived_deform(scene, base->object, CD_MASK_BAREMESH); + dm = mesh_get_derived_deform(&eval_ctx, scene, base->object, CD_MASK_BAREMESH); if (!dm) continue; @@ -1088,6 +1096,7 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, DerivedMesh *dm) */ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size) { + EvaluationContext eval_ctx; ViewContext vc; Mesh *me = ob->data; @@ -1096,6 +1105,7 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int if (!me || me->totpoly == 0) return false; + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); if (size) { @@ -1103,11 +1113,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int * on an edge in the backbuf, we can still select a face */ float dummy_dist; - *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist); + *index = ED_view3d_backbuf_sample_rect(&eval_ctx, &vc, mval, size, 1, me->totpoly + 1, &dummy_dist); } else { /* sample only on the exact position */ - *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]); + *index = ED_view3d_backbuf_sample(&eval_ctx, &vc, mval[0], mval[1]); } if ((*index) == 0 || (*index) > (unsigned int)me->totpoly) @@ -1146,9 +1156,12 @@ static void ed_mesh_pick_face_vert__mpoly_find( */ bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size) { + EvaluationContext eval_ctx; unsigned int poly_index; Mesh *me = ob->data; + CTX_data_eval_ctx(C, &eval_ctx); + BLI_assert(me && GS(me->id.name) == ID_ME); if (ED_mesh_pick_face(C, ob, mval, &poly_index, size)) { @@ -1156,7 +1169,7 @@ bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned struct ARegion *ar = CTX_wm_region(C); /* derived mesh to find deformed locations */ - DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); + DerivedMesh *dm = mesh_get_derived_final(&eval_ctx, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); int v_idx_best = ORIGINDEX_NONE; @@ -1253,9 +1266,12 @@ static void ed_mesh_pick_vert__mapFunc(void *userData, int index, const float co } bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size, bool use_zbuf) { + EvaluationContext eval_ctx; ViewContext vc; Mesh *me = ob->data; + CTX_data_eval_ctx(C, &eval_ctx); + BLI_assert(me && GS(me->id.name) == ID_ME); if (!me || me->totvert == 0) @@ -1269,11 +1285,11 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int * on an face in the backbuf, we can still select a vert */ float dummy_dist; - *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist); + *index = ED_view3d_backbuf_sample_rect(&eval_ctx, &vc, mval, size, 1, me->totvert + 1, &dummy_dist); } else { /* sample only on the exact position */ - *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]); + *index = ED_view3d_backbuf_sample(&eval_ctx, &vc, mval[0], mval[1]); } if ((*index) == 0 || (*index) > (unsigned int)me->totvert) @@ -1283,7 +1299,7 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int } else { /* derived mesh to find deformed locations */ - DerivedMesh *dm = mesh_get_derived_final(vc.scene, ob, CD_MASK_BAREMESH); + DerivedMesh *dm = mesh_get_derived_final(&eval_ctx, vc.scene, ob, CD_MASK_BAREMESH); ARegion *ar = vc.ar; RegionView3D *rv3d = ar->regiondata; diff --git a/source/blender/editors/metaball/CMakeLists.txt b/source/blender/editors/metaball/CMakeLists.txt index 0f9de8dbf87..89ba942ac36 100644 --- a/source/blender/editors/metaball/CMakeLists.txt +++ b/source/blender/editors/metaball/CMakeLists.txt @@ -22,6 +22,7 @@ set(INC ../include ../../blenkernel ../../blenlib + ../../depsgraph ../../makesdna ../../makesrna ../../render/extern/include diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index 5b4078b98b7..935f1a5ea4a 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -48,10 +48,11 @@ #include "RNA_define.h" #include "RNA_access.h" -#include "BKE_depsgraph.h" #include "BKE_context.h" #include "BKE_mball.h" +#include "DEG_depsgraph.h" + #include "ED_mball.h" #include "ED_screen.h" #include "ED_view3d.h" @@ -433,7 +434,7 @@ static int duplicate_metaelems_exec(bContext *C, wmOperator *UNUSED(op)) ml = ml->prev; } WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); } return OPERATOR_FINISHED; @@ -475,7 +476,7 @@ static int delete_metaelems_exec(bContext *C, wmOperator *UNUSED(op)) ml = next; } WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); } return OPERATOR_FINISHED; @@ -515,7 +516,7 @@ static int hide_metaelems_exec(bContext *C, wmOperator *op) ml = ml->next; } WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); } return OPERATOR_FINISHED; @@ -558,7 +559,7 @@ static int reveal_metaelems_exec(bContext *C, wmOperator *op) } if (changed) { WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); } return OPERATOR_FINISHED; @@ -588,6 +589,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese { static MetaElem *startelem = NULL; Object *obedit = CTX_data_edit_object(C); + EvaluationContext eval_ctx; ViewContext vc; MetaBall *mb = (MetaBall *)obedit->data; MetaElem *ml, *ml_act = NULL; @@ -595,11 +597,12 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese unsigned int buffer[MAXPICKBUF]; rcti rect; + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); BLI_rcti_init_pt_radius(&rect, mval, 12); - hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); + hits = view3d_opengl_select(&eval_ctx, &vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); /* does startelem exist? */ ml = mb->editelems->first; diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index b3d02d45e13..8050508983b 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blenlib ../../blentranslation ../../bmesh + ../../depsgraph ../../gpu ../../ikplugin ../../imbuf @@ -46,6 +47,7 @@ set(SRC object_bake_api.c object_constraint.c object_edit.c + object_facemap_ops.c object_group.c object_hook.c object_lattice.c diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 3f82298f5b3..ea2c688daa3 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -45,6 +45,7 @@ #include "DNA_object_fluidsim.h" #include "DNA_object_force.h" #include "DNA_object_types.h" +#include "DNA_lightprobe_types.h" #include "DNA_scene_types.h" #include "DNA_vfont_types.h" #include "DNA_actuator_types.h" @@ -63,10 +64,10 @@ #include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_camera.h" +#include "BKE_collection.h" #include "BKE_context.h" #include "BKE_constraint.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_displist.h" #include "BKE_effect.h" @@ -74,6 +75,7 @@ #include "BKE_group.h" #include "BKE_lamp.h" #include "BKE_lattice.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" @@ -92,6 +94,9 @@ #include "BKE_speaker.h" #include "BKE_texture.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -113,7 +118,7 @@ #include "UI_resources.h" -#include "GPU_material.h" +#include "GPU_lamp.h" #include "object_intern.h" @@ -147,6 +152,16 @@ static const EnumPropertyItem field_type_items[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem lightprobe_type_items[] = { + {LIGHTPROBE_TYPE_CUBE, "SPHERE", ICON_MESH_UVSPHERE, "Reflection Cubemap", + "Reflection probe with spherical or cubic attenuation"}, + {LIGHTPROBE_TYPE_PLANAR, "PLANAR", ICON_MESH_PLANE, "Reflection Plane", + "Planar reflection probe"}, + {LIGHTPROBE_TYPE_GRID, "GRID", ICON_MESH_GRID, "Irradiance Volume", + "Irradiance probe to capture diffuse indirect lighting"}, + {0, NULL, 0, NULL, NULL} +}; + /************************** Exported *****************************/ void ED_object_location_from_view(bContext *C, float loc[3]) @@ -209,16 +224,19 @@ void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3], { Object *ob = base->object; Scene *scene = CTX_data_scene(C); + EvaluationContext eval_ctx; if (!scene) return; + CTX_data_eval_ctx(C, &eval_ctx); + if (loc) copy_v3_v3(ob->loc, loc); if (rot) copy_v3_v3(ob->rot, rot); - BKE_object_where_is_calc(scene, ob); + BKE_object_where_is_calc(&eval_ctx, scene, ob); } /* Uses context to figure out transform for primitive. @@ -406,10 +424,11 @@ Object *ED_object_add_type( bContext *C, int type, const char *name, const float loc[3], const float rot[3], - bool enter_editmode, unsigned int layer) + bool enter_editmode, unsigned int UNUSED(layer)) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob; /* for as long scene has editmode... */ @@ -417,13 +436,12 @@ Object *ED_object_add_type( ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */ /* deselects all, sets scene->basact */ - ob = BKE_object_add(bmain, scene, type, name); - BASACT->lay = ob->lay = layer; + ob = BKE_object_add(bmain, scene, sl, type, name); /* editor level activate, notifiers */ - ED_base_object_activate(C, BASACT); + ED_object_base_activate(C, sl->basact); /* more editor stuff */ - ED_object_base_init_transform(C, BASACT, loc, rot); + ED_object_base_init_transform(C, sl->basact, loc, rot); /* Ignore collisions by default for non-mesh objects */ if (type != OB_MESH) { @@ -431,8 +449,8 @@ Object *ED_object_add_type( ob->gameflag &= ~(OB_SENSOR | OB_RIGID_BODY | OB_SOFT_BODY | OB_COLLISION | OB_CHARACTER | OB_OCCLUDER | OB_DYNAMIC | OB_NAVMESH); /* copied from rna_object.c */ } - DAG_id_type_tag(bmain, ID_OB); - DAG_relations_tag_update(bmain); + DEG_id_type_tag(bmain, ID_OB); + DEG_relations_tag_update(bmain); if (ob->data) { ED_render_id_flush_update(bmain, ob->data); } @@ -442,6 +460,9 @@ Object *ED_object_add_type( WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); + /* TODO(sergey): Use proper flag for tagging here. */ + DEG_id_tag_update(&scene->id, 0); + return ob; } @@ -493,6 +514,79 @@ void OBJECT_OT_add(wmOperatorType *ot) ED_object_add_generic_props(ot, true); } +/********************** Add Probe Operator **********************/ + +/* for object add operator */ +static int lightprobe_add_exec(bContext *C, wmOperator *op) +{ + Object *ob; + LightProbe *probe; + int type; + bool enter_editmode; + unsigned int layer; + float loc[3], rot[3]; + float radius; + + WM_operator_view3d_unit_defaults(C, op); + if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL)) + return OPERATOR_CANCELLED; + + type = RNA_enum_get(op->ptr, "type"); + radius = RNA_float_get(op->ptr, "radius"); + + const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Light Probe"); + ob = ED_object_add_type(C, OB_LIGHTPROBE, name, loc, rot, false, layer); + BKE_object_obdata_size_init(ob, radius); + + probe = (LightProbe *)ob->data; + probe->type = type; + + switch (type) { + case LIGHTPROBE_TYPE_GRID: + probe->distinf = 0.3f; + probe->falloff = 1.0f; + probe->clipsta = 0.01f; + break; + case LIGHTPROBE_TYPE_PLANAR: + probe->distinf = 0.1f; + probe->falloff = 0.5f; + probe->clipsta = 0.001f; + ob->empty_drawsize = 0.5f; + break; + case LIGHTPROBE_TYPE_CUBE: + probe->attenuation_type = LIGHTPROBE_SHAPE_ELIPSOID; + break; + default: + BLI_assert(!"Lightprobe type not configured."); + break; + } + + DEG_relations_tag_update(CTX_data_main(C)); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_lightprobe_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Light Probe"; + ot->description = "Add a light probe object"; + ot->idname = "OBJECT_OT_lightprobe_add"; + + /* api callbacks */ + ot->exec = lightprobe_add_exec; + ot->poll = ED_operator_objectmode; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", lightprobe_type_items, 0, "Type", ""); + + ED_object_add_unit_props(ot); + ED_object_add_generic_props(ot, true); +} + /********************* Add Effector Operator ********************/ /* for object add operator */ @@ -536,7 +630,7 @@ static int effector_add_exec(bContext *C, wmOperator *op) ob->pd = object_add_collision_fields(type); - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); return OPERATOR_FINISHED; } @@ -641,7 +735,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) newob = true; } else { - DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + DEG_id_tag_update(&obedit->id, OB_RECALC_DATA); } ED_object_new_primitive_matrix(C, obedit, loc, rot, mat); @@ -745,7 +839,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) newob = true; } else { - DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + DEG_id_tag_update(&obedit->id, OB_RECALC_DATA); } if (obedit == NULL) { @@ -1003,7 +1097,7 @@ static int group_instance_add_exec(bContext *C, wmOperator *op) id_us_plus(&group->id); /* works without this except if you try render right after, see: 22027 */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); @@ -1110,22 +1204,20 @@ static void object_delete_check_glsl_update(Object *ob) /* remove base from a specific scene */ /* note: now unlinks constraints as well */ -void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base) +void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob) { - if (BKE_library_ID_is_indirectly_used(bmain, base->object) && - ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) + if (BKE_library_ID_is_indirectly_used(bmain, ob) && + ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) { /* We cannot delete indirectly used object... */ printf("WARNING, undeletable object '%s', should have been catched before reaching this function!", - base->object->id.name + 2); + ob->id.name + 2); return; } - BKE_scene_base_unlink(scene, base); - object_delete_check_glsl_update(base->object); - BKE_libblock_free_us(bmain, base->object); - MEM_freeN(base); - DAG_id_type_tag(bmain, ID_OB); + object_delete_check_glsl_update(ob); + BKE_collections_object_remove(bmain, scene, ob, true); + DEG_id_type_tag(bmain, ID_OB); } static int object_delete_exec(bContext *C, wmOperator *op) @@ -1140,18 +1232,18 @@ static int object_delete_exec(bContext *C, wmOperator *op) if (CTX_data_edit_object(C)) return OPERATOR_CANCELLED; - CTX_DATA_BEGIN (C, Base *, base, selected_bases) + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { - const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, base->object); - if (base->object->id.tag & LIB_TAG_INDIRECT) { + const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, ob); + if (ob->id.tag & LIB_TAG_INDIRECT) { /* Can this case ever happen? */ - BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2); + BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2); continue; } - else if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) { + else if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) { BKE_reportf(op->reports, RPT_WARNING, "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user", - base->object->id.name + 2, scene->id.name + 2); + ob->id.name + 2, scene->id.name + 2); continue; } @@ -1159,9 +1251,9 @@ static int object_delete_exec(bContext *C, wmOperator *op) * custom scene/object/base handling, and use generic lib remap/query for that. * But this is for later (aka 2.8, once layers & co are settled and working). */ - if (use_global && base->object->id.lib == NULL) { + if (use_global && ob->id.lib == NULL) { /* We want to nuke the object, let's nuke it the easy way (not for linked data though)... */ - BKE_libblock_delete(bmain, &base->object->id); + BKE_libblock_delete(bmain, &ob->id); changed = true; continue; } @@ -1172,38 +1264,28 @@ static int object_delete_exec(bContext *C, wmOperator *op) for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) { for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { if (gpl->parent != NULL) { - Object *ob = gpl->parent; - Object *curob = base->object; - if (ob == curob) { + if (gpl->parent == ob) { gpl->parent = NULL; } } } } - /* deselect object -- it could be used in other scenes */ - base->object->flag &= ~SELECT; - /* remove from current scene only */ - ED_base_object_free_and_unlink(bmain, scene, base); + ED_object_base_free_and_unlink(bmain, scene, ob); changed = true; if (use_global) { Scene *scene_iter; - Base *base_other; - for (scene_iter = bmain->scene.first; scene_iter; scene_iter = scene_iter->id.next) { if (scene_iter != scene && !ID_IS_LINKED(scene_iter)) { - base_other = BKE_scene_base_find(scene_iter, base->object); - if (base_other) { - if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) { - BKE_reportf(op->reports, RPT_WARNING, - "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user", - base->object->id.name + 2, scene_iter->id.name + 2); - break; - } - ED_base_object_free_and_unlink(bmain, scene_iter, base_other); + if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) { + BKE_reportf(op->reports, RPT_WARNING, + "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user", + ob->id.name + 2, scene_iter->id.name + 2); + break; } + ED_object_base_free_and_unlink(bmain, scene_iter, ob); } } } @@ -1217,12 +1299,12 @@ static int object_delete_exec(bContext *C, wmOperator *op) /* delete has to handle all open scenes */ BKE_main_id_tag_listbase(&bmain->scene, LIB_TAG_DOIT, true); for (win = wm->windows.first; win; win = win->next) { - scene = win->screen->scene; - + scene = WM_window_get_active_scene(win); + if (scene->id.tag & LIB_TAG_DOIT) { scene->id.tag &= ~LIB_TAG_DOIT; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); @@ -1344,6 +1426,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, const bool use_hierarchy) { Main *bmain = CTX_data_main(C); + SceneLayer *sl = CTX_data_scene_layer(C); ListBase *lb_duplis; DupliObject *dob; GHash *dupli_gh, *parent_gh = NULL; @@ -1376,12 +1459,11 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, ob_dst->totcol = 0; } - base_dst = MEM_dupallocN(base); - base_dst->flag &= ~(OB_FROMDUPLI | OB_FROMGROUP); - ob_dst->flag = base_dst->flag; - base_dst->lay = base->lay; - BLI_addhead(&scene->base, base_dst); /* addhead: othwise eternal loop */ - base_dst->object = ob_dst; + BKE_collection_object_add_from(scene, base->object, ob_dst); + base_dst = BKE_scene_layer_base_find(sl, ob_dst); + BLI_assert(base_dst != NULL); + + BKE_scene_object_base_flag_sync_from_base(base_dst); /* make sure apply works */ BKE_animdata_free(&ob_dst->id, true); @@ -1396,7 +1478,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, BKE_constraints_free(&ob_dst->constraints); ob_dst->curve_cache = NULL; ob_dst->transflag &= ~OB_DUPLI; - ob_dst->lay = base->lay; copy_m4_m4(ob_dst->obmat, dob->mat); BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false); @@ -1420,7 +1501,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, BKE_libblock_relink_to_newid(&ob_dst->id); set_sca_new_poins_ob(ob_dst); - DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); if (use_hierarchy) { /* original parents */ @@ -1474,7 +1555,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, BKE_object_apply_mat4(ob_dst, dob->mat, false, true); /* to set ob_dst->orig and in case theres any other discrepicies */ - DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB); + DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB); } } @@ -1483,7 +1564,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, if (ob->proxy_group == base->object) { ob->proxy = NULL; ob->proxy_from = NULL; - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } } } @@ -1519,7 +1600,7 @@ static int object_duplicates_make_real_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_SCENE, scene); WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); @@ -1553,14 +1634,14 @@ static const EnumPropertyItem convert_target_items[] = { {0, NULL, 0, NULL, NULL} }; -static void convert_ensure_curve_cache(Main *bmain, Scene *scene, Object *ob) +static void convert_ensure_curve_cache(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Object *ob) { if (ob->curve_cache == NULL) { /* Force creation. This is normally not needed but on operator * redo we might end up with an object which isn't evaluated yet. */ if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { - BKE_displist_make_curveTypes(scene, ob, false); + BKE_displist_make_curveTypes(eval_ctx, scene, ob, false); } else if (ob->type == OB_MBALL) { BKE_displist_make_mball(bmain->eval_ctx, scene, ob); @@ -1568,9 +1649,9 @@ static void convert_ensure_curve_cache(Main *bmain, Scene *scene, Object *ob) } } -static void curvetomesh(Main *bmain, Scene *scene, Object *ob) +static void curvetomesh(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Object *ob) { - convert_ensure_curve_cache(bmain, scene, ob); + convert_ensure_curve_cache(eval_ctx, bmain, scene, ob); BKE_mesh_from_nurbs(ob); /* also does users */ if (ob->type == OB_MESH) { @@ -1584,15 +1665,16 @@ static void curvetomesh(Main *bmain, Scene *scene, Object *ob) static int convert_poll(bContext *C) { - Object *obact = CTX_data_active_object(C); Scene *scene = CTX_data_scene(C); + Base *base_act = CTX_data_active_base(C); + Object *obact = base_act ? base_act->object : NULL; return (!ID_IS_LINKED(scene) && obact && scene->obedit != obact && - (obact->flag & SELECT) && !ID_IS_LINKED(obact)); + (base_act->flag & BASE_SELECTED) && !ID_IS_LINKED(obact)); } /* Helper for convert_exec */ -static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object *ob) +static Base *duplibase_for_convert(Main *bmain, Scene *scene, SceneLayer *sl, Base *base, Object *ob) { Object *obn; Base *basen; @@ -1602,17 +1684,12 @@ static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object } obn = BKE_object_copy(bmain, ob); - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); - - basen = MEM_mallocN(sizeof(Base), "duplibase"); - *basen = *base; - BLI_addhead(&scene->base, basen); /* addhead: otherwise eternal loop */ - basen->object = obn; - basen->flag |= SELECT; - obn->flag |= SELECT; - base->flag &= ~SELECT; - ob->flag &= ~SELECT; + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + BKE_collection_object_add_from(scene, ob, obn); + basen = BKE_scene_layer_base_find(sl, obn); + ED_object_base_select(basen, BA_SELECT); + ED_object_base_select(basen, BA_DESELECT); return basen; } @@ -1620,8 +1697,10 @@ static int convert_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + EvaluationContext eval_ctx; Base *basen = NULL, *basact = NULL; - Object *ob, *ob1, *newob, *obact = CTX_data_active_object(C); + Object *ob1, *newob, *obact = CTX_data_active_object(C); DerivedMesh *dm; Curve *cu; Nurb *nu; @@ -1631,13 +1710,13 @@ static int convert_exec(bContext *C, wmOperator *op) bool keep_original = RNA_boolean_get(op->ptr, "keep_original"); int a, mballConverted = 0; + CTX_data_eval_ctx(C, &eval_ctx); + /* don't forget multiple users! */ { - Base *base; - - for (base = scene->base.first; base; base = base->next) { - ob = base->object; + FOREACH_SCENE_OBJECT(scene, ob) + { ob->flag &= ~OB_DONE; /* flag data thats not been edited (only needed for !keep_original) */ @@ -1656,6 +1735,7 @@ static int convert_exec(bContext *C, wmOperator *op) } } } + FOREACH_SCENE_OBJECT_END } ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases"); @@ -1666,7 +1746,7 @@ static int convert_exec(bContext *C, wmOperator *op) { for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) { Base *base = link->ptr.data; - ob = base->object; + Object *ob = base->object; /* The way object type conversion works currently (enforcing conversion of *all* objetcs using converted * obdata, even some un-selected/hidden/inother scene ones, sounds totally bad to me. @@ -1679,18 +1759,19 @@ static int convert_exec(bContext *C, wmOperator *op) "Converting some linked object/object data, enforcing 'Keep Original' option to True"); } - DAG_id_tag_update(&base->object->id, OB_RECALC_DATA); + DEG_id_tag_update(&base->object->id, OB_RECALC_DATA); } + Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, sl, true); uint64_t customdata_mask_prev = scene->customdata_mask; scene->customdata_mask |= CD_MASK_MESH; - BKE_scene_update_tagged(bmain->eval_ctx, bmain, scene); + BKE_scene_graph_update_tagged(bmain->eval_ctx, depsgraph, bmain, scene, sl); scene->customdata_mask = customdata_mask_prev; } for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) { Base *base = link->ptr.data; - ob = base->object; + Object *ob = base->object; if (ob->flag & OB_DONE || !IS_TAGGED(ob->data)) { if (ob->type != target) { @@ -1711,7 +1792,7 @@ static int convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, scene, base, NULL); + basen = duplibase_for_convert(bmain, scene, sl, base, NULL); newob = basen->object; /* decrement original mesh's usage count */ @@ -1725,7 +1806,7 @@ static int convert_exec(bContext *C, wmOperator *op) newob = ob; } - BKE_mesh_to_curve(scene, newob); + BKE_mesh_to_curve(&eval_ctx, scene, newob); if (newob->type == OB_CURVE) { BKE_object_free_modifiers(newob); /* after derivedmesh calls! */ @@ -1736,7 +1817,7 @@ static int convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, scene, base, NULL); + basen = duplibase_for_convert(bmain, scene, sl, base, NULL); newob = basen->object; /* decrement original mesh's usage count */ @@ -1748,14 +1829,14 @@ static int convert_exec(bContext *C, wmOperator *op) } else { newob = ob; - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } /* make new mesh data from the original copy */ /* note: get the mesh from the original, not from the copy in some * cases this doesnt give correct results (when MDEF is used for eg) */ - dm = mesh_get_derived_final(scene, newob, CD_MASK_MESH); + dm = mesh_get_derived_final(&eval_ctx, scene, newob, CD_MASK_MESH); DM_to_mesh(dm, newob->data, newob, CD_MASK_MESH, true); @@ -1767,7 +1848,7 @@ static int convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, scene, base, NULL); + basen = duplibase_for_convert(bmain, scene, sl, base, NULL); newob = basen->object; /* decrement original curve's usage count */ @@ -1814,7 +1895,7 @@ static int convert_exec(bContext *C, wmOperator *op) for (ob1 = bmain->object.first; ob1; ob1 = ob1->id.next) { if (ob1->data == ob->data) { ob1->type = OB_CURVE; - DAG_id_tag_update(&ob1->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob1->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } } } @@ -1827,7 +1908,7 @@ static int convert_exec(bContext *C, wmOperator *op) BKE_curve_curve_dimension_update(cu); if (target == OB_MESH) { - curvetomesh(bmain, scene, newob); + curvetomesh(&eval_ctx, bmain, scene, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); @@ -1838,7 +1919,7 @@ static int convert_exec(bContext *C, wmOperator *op) if (target == OB_MESH) { if (keep_original) { - basen = duplibase_for_convert(bmain, scene, base, NULL); + basen = duplibase_for_convert(bmain, scene, sl, base, NULL); newob = basen->object; /* decrement original curve's usage count */ @@ -1851,7 +1932,7 @@ static int convert_exec(bContext *C, wmOperator *op) newob = ob; } - curvetomesh(bmain, scene, newob); + curvetomesh(&eval_ctx, bmain, scene, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); @@ -1860,8 +1941,8 @@ static int convert_exec(bContext *C, wmOperator *op) else if (ob->type == OB_MBALL && target == OB_MESH) { Object *baseob; - base->flag &= ~SELECT; - ob->flag &= ~SELECT; + base->flag &= ~BASE_SELECTED; + ob->base_flag &= ~BASE_SELECTED; baseob = BKE_mball_basis_find(scene, ob); @@ -1873,7 +1954,7 @@ static int convert_exec(bContext *C, wmOperator *op) if (!(baseob->flag & OB_DONE)) { baseob->flag |= OB_DONE; - basen = duplibase_for_convert(bmain, scene, base, baseob); + basen = duplibase_for_convert(bmain, scene, sl, base, baseob); newob = basen->object; mb = newob->data; @@ -1889,7 +1970,7 @@ static int convert_exec(bContext *C, wmOperator *op) for (a = 0; a < newob->totcol; a++) id_us_plus((ID *)me->mat[a]); } - convert_ensure_curve_cache(bmain, scene, baseob); + convert_ensure_curve_cache(&eval_ctx, bmain, scene, baseob); BKE_mesh_from_metaball(&baseob->curve_cache->disp, newob->data); if (obact->type == OB_MBALL) { @@ -1916,7 +1997,7 @@ static int convert_exec(bContext *C, wmOperator *op) } if (!keep_original && (ob->flag & OB_DONE)) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); ((ID *)ob->data)->tag &= ~LIB_TAG_DOIT; /* flag not to convert this datablock again */ } } @@ -1924,27 +2005,24 @@ static int convert_exec(bContext *C, wmOperator *op) if (!keep_original) { if (mballConverted) { - Base *base, *base_next; - - for (base = scene->base.first; base; base = base_next) { - base_next = base->next; - - ob = base->object; - if (ob->type == OB_MBALL) { - if (ob->flag & OB_DONE) { + FOREACH_SCENE_OBJECT(scene, ob_mball) + { + if (ob_mball->type == OB_MBALL) { + if (ob_mball->flag & OB_DONE) { Object *ob_basis = NULL; - if (BKE_mball_is_basis(ob) || - ((ob_basis = BKE_mball_basis_find(scene, ob)) && (ob_basis->flag & OB_DONE))) + if (BKE_mball_is_basis(ob_mball) || + ((ob_basis = BKE_mball_basis_find(scene, ob_mball)) && (ob_basis->flag & OB_DONE))) { - ED_base_object_free_and_unlink(bmain, scene, base); + ED_object_base_free_and_unlink(bmain, scene, ob_mball); } } } } + FOREACH_SCENE_OBJECT_END } /* delete object should renew depsgraph */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } // XXX ED_object_editmode_enter(C, 0); @@ -1952,15 +2030,15 @@ static int convert_exec(bContext *C, wmOperator *op) if (basact) { /* active base was changed */ - ED_base_object_activate(C, basact); - BASACT = basact; + ED_object_base_activate(C, basact); + BASACT(sl) = basact; } - else if (BASACT->object->flag & OB_DONE) { - WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT->object); - WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT->object); + else if (BASACT(sl)->object->flag & OB_DONE) { + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT(sl)->object); + WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT(sl)->object); } - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -1999,39 +2077,36 @@ void OBJECT_OT_convert(wmOperatorType *ot) /* used below, assumes id.new is correct */ /* leaves selection of base/object unaltered */ /* Does set ID->newid pointers. */ -static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base, int dupflag) +static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, SceneLayer *sl, Object *ob, int dupflag) { #define ID_NEW_REMAP_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; } #define ID_NEW_REMAP_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; } Base *basen = NULL; Material ***matarar; - Object *ob, *obn; + Object *obn; ID *id; int a, didit; - ob = base->object; if (ob->mode & OB_MODE_POSE) { ; /* nothing? */ } else { obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob)); - DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); - basen = MEM_mallocN(sizeof(Base), "duplibase"); - *basen = *base; - BLI_addhead(&scene->base, basen); /* addhead: prevent eternal loop */ - basen->object = obn; + BKE_collection_object_add_from(scene, ob, obn); + basen = BKE_scene_layer_base_find(sl, obn); /* 1) duplis should end up in same group as the original * 2) Rigid Body sim participants MUST always be part of a group... */ // XXX: is 2) really a good measure here? - if ((basen->flag & OB_FROMGROUP) || ob->rigidbody_object || ob->rigidbody_constraint) { + if ((ob->flag & OB_FROMGROUP) != 0 || ob->rigidbody_object || ob->rigidbody_constraint) { Group *group; for (group = bmain->group.first; group; group = group->id.next) { if (BKE_group_object_exists(group, ob)) - BKE_group_object_add(group, obn, scene, basen); + BKE_group_object_add(group, obn); } } @@ -2140,7 +2215,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base } break; case OB_ARMATURE: - DAG_id_tag_update(&obn->id, OB_RECALC_DATA); + DEG_id_tag_update(&obn->id, OB_RECALC_DATA); if (obn->pose) BKE_pose_tag_recalc(bmain, obn->pose); if (dupflag & USER_DUP_ARM) { @@ -2244,14 +2319,14 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base * note: don't call this within a loop since clear_* funcs loop over the entire database. * note: caller must do DAG_relations_tag_update(bmain); * this is not done automatic since we may duplicate many objects in a batch */ -Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag) +Base *ED_object_add_duplicate(Main *bmain, Scene *scene, SceneLayer *sl, Base *base, int dupflag) { Base *basen; Object *ob; clear_sca_new_poins(); /* BGE logic */ - basen = object_add_duplicate_internal(bmain, scene, base, dupflag); + basen = object_add_duplicate_internal(bmain, scene, sl, base->object, dupflag); if (basen == NULL) { return NULL; } @@ -2278,6 +2353,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); const bool linked = RNA_boolean_get(op->ptr, "linked"); int dupflag = (linked) ? 0 : U.dupflag; @@ -2285,22 +2361,23 @@ static int duplicate_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - Base *basen = object_add_duplicate_internal(bmain, scene, base, dupflag); + Base *basen = object_add_duplicate_internal(bmain, scene, sl, base->object, dupflag); /* note that this is safe to do with this context iterator, * the list is made in advance */ - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); + ED_object_base_select(basen, BA_SELECT); if (basen == NULL) { continue; } /* new object becomes active */ - if (BASACT == base) - ED_base_object_activate(C, basen); + if (BASACT(sl) == base) + ED_object_base_activate(C, basen); if (basen->object->data) { - DAG_id_tag_update(basen->object->data, 0); + DEG_id_tag_update(basen->object->data, 0); } } CTX_DATA_END; @@ -2309,7 +2386,9 @@ static int duplicate_exec(bContext *C, wmOperator *op) BKE_main_id_clear_newpoins(bmain); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); + /* TODO(sergey): Use proper flag for tagging here. */ + DEG_id_tag_update(&CTX_data_scene(C)->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -2345,9 +2424,9 @@ static int add_named_exec(bContext *C, wmOperator *op) wmWindow *win = CTX_wm_window(C); const wmEvent *event = win ? win->eventstate : NULL; Main *bmain = CTX_data_main(C); - View3D *v3d = CTX_wm_view3d(C); /* may be NULL */ Scene *scene = CTX_data_scene(C); - Base *basen, *base; + SceneLayer *sl = CTX_data_scene_layer(C); + Base *basen; Object *ob; const bool linked = RNA_boolean_get(op->ptr, "linked"); int dupflag = (linked) ? 0 : U.dupflag; @@ -2362,22 +2441,17 @@ static int add_named_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - base = MEM_callocN(sizeof(Base), "duplibase"); - base->object = ob; - base->flag = ob->flag; - /* prepare dupli */ clear_sca_new_poins(); /* BGE logic */ - basen = object_add_duplicate_internal(bmain, scene, base, dupflag); + basen = object_add_duplicate_internal(bmain, scene, sl, ob, dupflag); + BKE_scene_object_base_flag_sync_from_object(basen); if (basen == NULL) { - MEM_freeN(base); BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated"); return OPERATOR_CANCELLED; } - basen->lay = basen->object->lay = BKE_screen_view3d_layer_active(v3d, scene); basen->object->restrictflag &= ~OB_RESTRICT_VIEW; if (event) { @@ -2388,16 +2462,14 @@ static int add_named_exec(bContext *C, wmOperator *op) ED_view3d_cursor3d_position(C, basen->object->loc, mval); } - ED_base_object_select(basen, BA_SELECT); - ED_base_object_activate(C, basen); + ED_object_base_select(basen, BA_SELECT); + ED_object_base_activate(C, basen); copy_object_set_idnew(C); BKE_main_id_clear_newpoins(bmain); - DAG_relations_tag_update(bmain); - - MEM_freeN(base); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT | ND_OB_ACTIVE, scene); diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index 11d96da5786..0fd1d32c8b8 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -52,15 +52,17 @@ #include "BKE_global.h" #include "BKE_image.h" #include "BKE_main.h" +#include "BKE_material.h" #include "BKE_multires.h" #include "BKE_report.h" #include "BKE_cdderivedmesh.h" #include "BKE_modifier.h" #include "BKE_DerivedMesh.h" -#include "BKE_depsgraph.h" #include "BKE_mesh.h" #include "BKE_scene.h" +#include "DEG_depsgraph.h" + #include "RE_pipeline.h" #include "RE_shader_ext.h" #include "RE_multires_bake.h" @@ -86,6 +88,11 @@ * needed to make job totally thread-safe */ typedef struct MultiresBakerJobData { struct MultiresBakerJobData *next, *prev; + /* material aligned image array (for per-face bake image) */ + struct { + Image **array; + int len; + } ob_image; DerivedMesh *lores_dm, *hires_dm; bool simple; int lvl, tot_lvl; @@ -152,7 +159,7 @@ static bool multiresbake_check(bContext *C, wmOperator *op) break; } - if (!me->mtpoly) { + if (!me->mloopuv) { BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking"); ok = false; @@ -160,7 +167,7 @@ static bool multiresbake_check(bContext *C, wmOperator *op) else { a = me->totpoly; while (ok && a--) { - Image *ima = me->mtpoly[a].tpage; + Image *ima = BKE_object_material_edit_image_get(ob, me->mpoly[a].mat_nr); if (!ima) { BKE_report(op->reports, RPT_ERROR, "You should have active texture to use multires baker"); @@ -283,20 +290,27 @@ static void clear_single_image(Image *image, ClearFlag flag) } } -static void clear_images_poly(MTexPoly *mtpoly, int totpoly, ClearFlag flag) +static void clear_images_poly(Image **ob_image_array, int ob_image_array_len, ClearFlag flag) { - int a; - - for (a = 0; a < totpoly; a++) { - mtpoly[a].tpage->id.tag &= ~LIB_TAG_DOIT; + for (int i = 0; i < ob_image_array_len; i++) { + Image *image = ob_image_array[i]; + if (image) { + image->id.tag &= ~LIB_TAG_DOIT; + } } - for (a = 0; a < totpoly; a++) { - clear_single_image(mtpoly[a].tpage, flag); + for (int i = 0; i < ob_image_array_len; i++) { + Image *image = ob_image_array[i]; + if (image) { + clear_single_image(image, flag); + } } - for (a = 0; a < totpoly; a++) { - mtpoly[a].tpage->id.tag &= ~LIB_TAG_DOIT; + for (int i = 0; i < ob_image_array_len; i++) { + Image *image = ob_image_array[i]; + if (image) { + image->id.tag &= ~LIB_TAG_DOIT; + } } } @@ -312,11 +326,10 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op) if (scene->r.bake_flag & R_BAKE_CLEAR) { /* clear images */ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { - Mesh *me; ClearFlag clear_flag = 0; ob = base->object; - me = (Mesh *)ob->data; + // me = (Mesh *)ob->data; if (scene->r.bake_mode == RE_BAKE_NORMALS) { clear_flag = CLEAR_TANGENT_NORMAL; @@ -325,7 +338,11 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op) clear_flag = CLEAR_DISPLACEMENT; } - clear_images_poly(me->mtpoly, me->totpoly, clear_flag); + { + Image **ob_image_array = BKE_object_material_edit_image_get_array(ob); + clear_images_poly(ob_image_array, ob->totcol, clear_flag); + MEM_freeN(ob_image_array); + } } CTX_DATA_END; } @@ -351,11 +368,16 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op) //bkr.reports= op->reports; /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */ + bkr.ob_image.array = BKE_object_material_edit_image_get_array(ob); + bkr.ob_image.len = ob->totcol; + bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple); bkr.lores_dm = multiresbake_create_loresdm(scene, ob, &bkr.lvl); RE_multires_bake_images(&bkr); + MEM_freeN(bkr.ob_image.array); + BLI_freelistN(&bkr.image); bkr.lores_dm->release(bkr.lores_dm); @@ -401,6 +423,9 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj) data = MEM_callocN(sizeof(MultiresBakerJobData), "multiresBaker derivedMesh_data"); + data->ob_image.array = BKE_object_material_edit_image_get_array(ob); + data->ob_image.len = ob->totcol; + /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */ data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl, &data->simple); data->lores_dm = multiresbake_create_loresdm(scene, ob, &lvl); @@ -421,8 +446,6 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa if (bkj->bake_clear) { /* clear images */ for (data = bkj->data.first; data; data = data->next) { - DerivedMesh *dm = data->lores_dm; - MTexPoly *mtexpoly = CustomData_get_layer(&dm->polyData, CD_MTEXPOLY); ClearFlag clear_flag = 0; if (bkj->mode == RE_BAKE_NORMALS) { @@ -432,7 +455,7 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa clear_flag = CLEAR_DISPLACEMENT; } - clear_images_poly(mtexpoly, dm->getNumPolys(dm), clear_flag); + clear_images_poly(data->ob_image.array, data->ob_image.len, clear_flag); } } @@ -445,6 +468,8 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa bkr.use_lores_mesh = bkj->use_lores_mesh; bkr.user_scale = bkj->user_scale; //bkr.reports = bkj->reports; + bkr.ob_image.array = data->ob_image.array; + bkr.ob_image.len = data->ob_image.len; /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */ bkr.lores_dm = data->lores_dm; @@ -493,6 +518,8 @@ static void multiresbake_freejob(void *bkv) GPU_free_image(ima); } + MEM_freeN(data->ob_image.array); + BLI_freelistN(&data->images); MEM_freeN(data); @@ -589,6 +616,7 @@ static int test_bake_internal(bContext *C, ReportList *reports) static void init_bake_internal(BakeRender *bkr, bContext *C) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); bScreen *sc = CTX_wm_screen(C); /* get editmode results */ @@ -597,7 +625,7 @@ static void init_bake_internal(BakeRender *bkr, bContext *C) bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL; /* can be NULL */ bkr->main = CTX_data_main(C); bkr->scene = scene; - bkr->actob = (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT : NULL; + bkr->actob = (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT(sl) : NULL; bkr->re = RE_NewRender("_Bake View_"); if (scene->r.bake_mode == RE_BAKE_AO) { @@ -661,7 +689,7 @@ static void finish_bake_internal(BakeRender *bkr) } BKE_image_release_ibuf(ima, ibuf, NULL); - DAG_id_tag_update(&ima->id, 0); + DEG_id_tag_update(&ima->id, 0); } } @@ -671,7 +699,7 @@ static void finish_bake_internal(BakeRender *bkr) BLI_assert(BLI_thread_is_main()); for (me = G.main->mesh.first; me; me = me->id.next) { if (me->id.tag & LIB_TAG_DOIT) { - DAG_id_tag_update(&me->id, OB_RECALC_DATA); + DEG_id_tag_update(&me->id, OB_RECALC_DATA); BKE_mesh_tessface_clear(me); } } @@ -810,6 +838,7 @@ static int bake_image_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); int result = OPERATOR_CANCELLED; if (is_multires_bake(scene)) { @@ -829,7 +858,7 @@ static int bake_image_exec(bContext *C, wmOperator *op) RE_test_break_cb(bkr.re, NULL, thread_break); G.is_break = false; /* BKE_blender_test_break uses this global */ - RE_Database_Baking(bkr.re, bmain, scene, scene->lay, scene->r.bake_mode, (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT : NULL); + RE_Database_Baking(bkr.re, bmain, scene, scene->lay, scene->r.bake_mode, (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT(sl) : NULL); /* baking itself is threaded, cannot use test_break in threads */ BLI_init_threads(&threads, do_bake_render, 1); diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 4825271876c..0174a307c16 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -57,7 +57,8 @@ #include "BKE_modifier.h" #include "BKE_mesh.h" #include "BKE_screen.h" -#include "BKE_depsgraph.h" + +#include "DEG_depsgraph.h" #include "RE_engine.h" #include "RE_pipeline.h" @@ -83,6 +84,7 @@ static void bake_set_props(wmOperator *op, Scene *scene); typedef struct BakeAPIRender { Object *ob; Main *main; + Depsgraph *depsgraph; Scene *scene; ReportList *reports; ListBase selected_objects; @@ -272,7 +274,7 @@ static void refresh_images(BakeImages *bake_images) Image *ima = bake_images->data[i].image; if (ima->ok == IMA_OK_LOADED) { GPU_free_image(ima); - DAG_id_tag_update(&ima->id, 0); + DEG_id_tag_update(&ima->id, 0); } } } @@ -619,12 +621,12 @@ static size_t initialize_internal_images(BakeImages *bake_images, ReportList *re } /* create new mesh with edit mode changes and modifiers applied */ -static Mesh *bake_mesh_new_from_object(Main *bmain, Scene *scene, Object *ob) +static Mesh *bake_mesh_new_from_object(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Object *ob) { if (ob->mode & OB_MODE_EDIT) ED_object_editmode_load(ob); - Mesh *me = BKE_mesh_new_from_object(bmain, scene, ob, 1, 2, 0, 0); + Mesh *me = BKE_mesh_new_from_object(eval_ctx, bmain, scene, ob, 1, 2, 0, 0); if (me->flag & ME_AUTOSMOOTH) { BKE_mesh_split_faces(me, true); } @@ -633,7 +635,7 @@ static Mesh *bake_mesh_new_from_object(Main *bmain, Scene *scene, Object *ob) } static int bake( - Render *re, Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports, + Render *re, Main *bmain, Depsgraph *graph, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports, const eScenePassType pass_type, const int pass_filter, const int margin, const eBakeSaveMode save_mode, const bool is_clear, const bool is_split_materials, const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage, @@ -672,7 +674,7 @@ static int bake( size_t num_pixels; int tot_materials; - RE_bake_engine_set_engine_parameters(re, bmain, scene); + RE_bake_engine_set_engine_parameters(re, bmain, graph, scene); if (!RE_bake_has_engine(re)) { BKE_report(reports, RPT_ERROR, "Current render engine does not support baking"); @@ -783,7 +785,7 @@ static int bake( } /* get the mesh as it arrives in the renderer */ - me_low = bake_mesh_new_from_object(bmain, scene, ob_low); + me_low = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, ob_low); /* populate the pixel array with the face data */ if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false) @@ -798,7 +800,7 @@ static int bake( /* prepare cage mesh */ if (ob_cage) { - me_cage = bake_mesh_new_from_object(bmain, scene, ob_cage); + me_cage = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, ob_cage); if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) { BKE_report(reports, RPT_ERROR, "Invalid cage object, the cage mesh must have the same number " @@ -830,7 +832,7 @@ static int bake( ob_low->modifiers = modifiers_tmp; /* get the cage mesh as it arrives in the renderer */ - me_cage = bake_mesh_new_from_object(bmain, scene, ob_low); + me_cage = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, ob_low); RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer); } @@ -856,7 +858,7 @@ static int bake( tmd->quad_method = MOD_TRIANGULATE_QUAD_FIXED; tmd->ngon_method = MOD_TRIANGULATE_NGON_EARCLIP; - highpoly[i].me = bake_mesh_new_from_object(bmain, scene, highpoly[i].ob); + highpoly[i].me = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, highpoly[i].ob); highpoly[i].ob->restrictflag &= ~OB_RESTRICT_RENDER; /* lowpoly to highpoly transformation matrix */ @@ -959,7 +961,7 @@ cage_cleanup: md->mode &= ~eModifierMode_Render; } - me_nores = bake_mesh_new_from_object(bmain, scene, ob_low); + me_nores = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, ob_low); RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer); RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat); @@ -1120,6 +1122,7 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr) bkr->ob = CTX_data_active_object(C); bkr->main = CTX_data_main(C); + bkr->depsgraph = CTX_data_depsgraph(C); bkr->scene = CTX_data_scene(C); bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL; @@ -1203,7 +1206,7 @@ static int bake_exec(bContext *C, wmOperator *op) if (bkr.is_selected_to_active) { result = bake( - bkr.render, bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports, + bkr.render, bkr.main, bkr.depsgraph, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode, bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true, bkr.is_cage, bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle, @@ -1216,7 +1219,7 @@ static int bake_exec(bContext *C, wmOperator *op) for (link = bkr.selected_objects.first; link; link = link->next) { Object *ob_iter = link->ptr.data; result = bake( - bkr.render, bkr.main, bkr.scene, ob_iter, NULL, bkr.reports, + bkr.render, bkr.main, bkr.depsgraph, bkr.scene, ob_iter, NULL, bkr.reports, bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode, is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage, bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle, @@ -1261,7 +1264,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa if (bkr->is_selected_to_active) { bkr->result = bake( - bkr->render, bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports, + bkr->render, bkr->main, bkr->depsgraph, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode, bkr->is_clear, bkr->is_split_materials, bkr->is_automatic_name, true, bkr->is_cage, bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle, @@ -1274,7 +1277,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa for (link = bkr->selected_objects.first; link; link = link->next) { Object *ob_iter = link->ptr.data; bkr->result = bake( - bkr->render, bkr->main, bkr->scene, ob_iter, NULL, bkr->reports, + bkr->render, bkr->main, bkr->depsgraph, bkr->scene, ob_iter, NULL, bkr->reports, bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode, is_clear, bkr->is_split_materials, bkr->is_automatic_name, false, bkr->is_cage, bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle, diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 94caaedec19..80fd44be364 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -53,7 +53,6 @@ #include "BKE_armature.h" #include "BKE_constraint.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_main.h" @@ -62,6 +61,9 @@ #include "BKE_tracking.h" #include "BIK_api.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #ifdef WITH_PYTHON #include "BPY_extern.h" #endif @@ -773,8 +775,12 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot) /* ------------- Child-Of Constraint ------------------ */ -static void child_get_inverse_matrix(Scene *scene, Object *ob, bConstraint *con, float invmat[4][4], const int owner) +static void child_get_inverse_matrix(const bContext *C, Scene *scene, Object *ob, bConstraint *con, float invmat[4][4], const int owner) { + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); + /* nullify inverse matrix first */ unit_m4(invmat); @@ -800,7 +806,7 @@ static void child_get_inverse_matrix(Scene *scene, Object *ob, bConstraint *con, * to use as baseline ("pmat") to derive delta from. This extra calc saves users * from having pressing "Clear Inverse" first */ - BKE_pose_where_is(scene, ob); + BKE_pose_where_is(&eval_ctx, scene, ob); copy_m4_m4(pmat, pchan->pose_mat); /* 2. knock out constraints starting from this one */ @@ -817,7 +823,7 @@ static void child_get_inverse_matrix(Scene *scene, Object *ob, bConstraint *con, } /* 3. solve pose without disabled constraints */ - BKE_pose_where_is(scene, ob); + BKE_pose_where_is(&eval_ctx, scene, ob); /* 4. determine effect of constraint by removing the newly calculated * pchan->pose_mat from the original pchan->pose_mat, thus determining @@ -840,7 +846,7 @@ static void child_get_inverse_matrix(Scene *scene, Object *ob, bConstraint *con, } /* 6. recalculate pose with new inv-mat applied */ - BKE_pose_where_is(scene, ob); + BKE_pose_where_is(&eval_ctx, scene, ob); } } if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) { @@ -851,7 +857,7 @@ static void child_get_inverse_matrix(Scene *scene, Object *ob, bConstraint *con, BLI_assert(BLI_findindex(&ob->constraints, con) != -1); /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */ - BKE_object_workob_calc_parent(scene, ob, &workob); + BKE_object_workob_calc_parent(&eval_ctx, scene, ob, &workob); invert_m4_m4(invmat, workob.obmat); } } @@ -873,7 +879,7 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - child_get_inverse_matrix(scene, ob, con, data->invmat, owner); + child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner); WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); @@ -1095,7 +1101,7 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - child_get_inverse_matrix(scene, ob, con, data->invmat, owner); + child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner); WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); @@ -1196,9 +1202,9 @@ void ED_object_constraint_update(Object *ob) object_test_constraints(ob); if (ob->type == OB_ARMATURE) - DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); else - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } static void object_pose_tag_update(Main *bmain, Object *ob) @@ -1221,7 +1227,7 @@ void ED_object_constraint_dependency_update(Main *bmain, Object *ob) if (ob->pose) { object_pose_tag_update(bmain, ob); } - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } void ED_object_constraint_tag_update(Object *ob, bConstraint *con) @@ -1233,9 +1239,9 @@ void ED_object_constraint_tag_update(Object *ob, bConstraint *con) object_test_constraint(ob, con); if (ob->type == OB_ARMATURE) - DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); else - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstraint *con) @@ -1245,7 +1251,7 @@ void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstr if (ob->pose) { object_pose_tag_update(bmain, ob); } - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } static int constraint_poll(bContext *C) @@ -1269,7 +1275,7 @@ static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op)) ED_object_constraint_update(ob); /* needed to set the flags on posebones correctly */ /* relatiols */ - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); /* notifiers */ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob); @@ -1411,12 +1417,12 @@ static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op)) CTX_DATA_END; /* force depsgraph to get recalculated since relationships removed */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); /* note, calling BIK_clear_data() isn't needed here */ /* do updates */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob); return OPERATOR_FINISHED; @@ -1443,12 +1449,12 @@ static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op)) CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { BKE_constraints_free(&ob->constraints); - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } CTX_DATA_END; /* force depsgraph to get recalculated since relationships removed */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); /* do updates */ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, NULL); @@ -1496,13 +1502,13 @@ static int pose_constraint_copy_exec(bContext *C, wmOperator *op) chan->constflag |= pchan->constflag; BKE_pose_tag_recalc(bmain, ob->pose); - DAG_id_tag_update((ID *)ob, OB_RECALC_DATA); + DEG_id_tag_update((ID *)ob, OB_RECALC_DATA); } } BLI_freelistN(&lb); /* force depsgraph to get recalculated since new relationships added */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL); @@ -1535,13 +1541,13 @@ static int object_constraint_copy_exec(bContext *C, wmOperator *UNUSED(op)) /* if we're not handling the object we're copying from, copy all constraints over */ if (obact != ob) { BKE_constraints_copy(&ob->constraints, &obact->constraints, true); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } CTX_DATA_END; /* force depsgraph to get recalculated since new relationships added */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); /* notifiers for updates */ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, NULL); @@ -1682,14 +1688,15 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob if ((found == false) && (add)) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Base *base = BASACT, *newbase = NULL; + SceneLayer *sl = CTX_data_scene_layer(C); + Base *base = BASACT(sl), *newbase = NULL; Object *obt; /* add new target object */ - obt = BKE_object_add(bmain, scene, OB_EMPTY, NULL); + obt = BKE_object_add(bmain, scene, sl, OB_EMPTY, NULL); /* set layers OK */ - newbase = BASACT; + newbase = BASACT(sl); newbase->lay = base->lay; obt->lay = newbase->lay; @@ -1708,8 +1715,8 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob } /* restore, BKE_object_add sets active */ - BASACT = base; - base->flag |= SELECT; + BASACT(sl) = base; + base->flag |= BASE_SELECTED; /* make our new target the new object */ *tar_ob = obt; @@ -1817,7 +1824,7 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase /* force depsgraph to get recalculated since new relationships added */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); if ((ob->type == OB_ARMATURE) && (pchan)) { BKE_pose_tag_recalc(bmain, ob->pose); /* sort pose channels */ @@ -1827,10 +1834,10 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase * XXX Temp hack until new depsgraph hopefully solves this. */ ob->adt->recalc |= ADT_RECALC_ANIM; } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); } else - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); /* notifiers for updates */ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, ob); @@ -2070,7 +2077,7 @@ static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op)) CTX_DATA_END; /* refresh depsgraph */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob); diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 7845cfe1022..2daa8652335 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -40,13 +40,14 @@ #include "BKE_context.h" #include "BKE_data_transfer.h" -#include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_remap.h" #include "BKE_object.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -93,15 +94,17 @@ static const EnumPropertyItem DT_layer_items[] = { static const EnumPropertyItem *dt_layers_select_src_itemf( bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { + EvaluationContext eval_ctx; EnumPropertyItem *item = NULL, tmp_item = {0}; int totitem = 0; - const int data_type = RNA_enum_get(ptr, "data_type"); if (!C) { /* needed for docs and i18n tools */ return rna_enum_dt_layers_select_src_items; } + CTX_data_eval_ctx(C, &eval_ctx); + RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ACTIVE_SRC); RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ALL_SRC); @@ -135,19 +138,19 @@ static const EnumPropertyItem *dt_layers_select_src_itemf( if (ob_src) { DerivedMesh *dm_src; - CustomData *pdata; + CustomData *ldata; int num_data, i; /* XXX Is this OK? */ - dm_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MTEXPOLY); - pdata = dm_src->getPolyDataLayout(dm_src); - num_data = CustomData_number_of_layers(pdata, CD_MTEXPOLY); + dm_src = mesh_get_derived_final(&eval_ctx, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPUV); + ldata = dm_src->getLoopDataLayout(dm_src); + num_data = CustomData_number_of_layers(ldata, CD_MLOOPUV); RNA_enum_item_add_separator(&item, &totitem); for (i = 0; i < num_data; i++) { tmp_item.value = i; - tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(pdata, CD_MTEXPOLY, i); + tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPUV, i); RNA_enum_item_add(&item, &totitem, &tmp_item); } } @@ -162,7 +165,7 @@ static const EnumPropertyItem *dt_layers_select_src_itemf( int num_data, i; /* XXX Is this OK? */ - dm_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL); + dm_src = mesh_get_derived_final(&eval_ctx, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL); ldata = dm_src->getLoopDataLayout(dm_src); num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL); @@ -344,6 +347,9 @@ static int data_transfer_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob_src = ED_object_active_context(C); + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); ListBase ctx_objects; CollectionPointerLink *ctx_ob_dst; @@ -412,7 +418,7 @@ static int data_transfer_exec(bContext *C, wmOperator *op) } if (BKE_object_data_transfer_mesh( - scene, ob_src, ob_dst, data_type, use_create, + &eval_ctx, scene, ob_src, ob_dst, data_type, use_create, map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode, space_transform, use_auto_transform, max_distance, ray_radius, islands_precision, @@ -423,7 +429,7 @@ static int data_transfer_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); if (reverse_transfer) { SWAP(Object *, ob_src, ob_dst); @@ -622,8 +628,11 @@ static int datalayout_transfer_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob_act = ED_object_active_context(C); + EvaluationContext eval_ctx; DataTransferModifierData *dtmd; + CTX_data_eval_ctx(C, &eval_ctx); + dtmd = (DataTransferModifierData *)edit_modifier_property_get(op, ob_act, eModifierType_DataTransfer); /* If we have a modifier, we transfer data layout from this modifier's source object to active one. @@ -638,10 +647,10 @@ static int datalayout_transfer_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_object_data_transfer_layout(scene, ob_src, ob_dst, dtmd->data_types, use_delete, + BKE_object_data_transfer_layout(&eval_ctx, scene, ob_src, ob_dst, dtmd->data_types, use_delete, dtmd->layers_select_src, dtmd->layers_select_dst); - DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); } else { Object *ob_src = ob_act; @@ -668,11 +677,11 @@ static int datalayout_transfer_exec(bContext *C, wmOperator *op) for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) { Object *ob_dst = ctx_ob_dst->ptr.data; if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, false)) { - BKE_object_data_transfer_layout(scene, ob_src, ob_dst, data_type, use_delete, + BKE_object_data_transfer_layout(&eval_ctx, scene, ob_src, ob_dst, data_type, use_delete, layers_select_src, layers_select_dst); } - DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); } BLI_freelistN(&ctx_objects); diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index d7c7976c344..eaf42d4a53c 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -58,6 +58,7 @@ #include "DNA_meshdata_types.h" #include "DNA_vfont_types.h" #include "DNA_mesh_types.h" +#include "DNA_workspace_types.h" #include "IMB_imbuf_types.h" @@ -66,7 +67,6 @@ #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_effect.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_image.h" #include "BKE_lattice.h" @@ -83,6 +83,10 @@ #include "BKE_modifier.h" #include "BKE_editmesh.h" #include "BKE_report.h" +#include "BKE_workspace.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" #include "ED_armature.h" #include "ED_curve.h" @@ -132,192 +136,6 @@ Object *ED_object_active_context(bContext *C) } -/* ********* clear/set restrict view *********/ -static int object_hide_view_clear_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - ScrArea *sa = CTX_wm_area(C); - View3D *v3d = sa->spacedata.first; - Scene *scene = CTX_data_scene(C); - Base *base; - bool changed = false; - const bool select = RNA_boolean_get(op->ptr, "select"); - - /* XXX need a context loop to handle such cases */ - for (base = FIRSTBASE; base; base = base->next) { - if ((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) { - if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) { - SET_FLAG_FROM_TEST(base->flag, select, SELECT); - } - base->object->flag = base->flag; - base->object->restrictflag &= ~OB_RESTRICT_VIEW; - changed = true; - } - } - if (changed) { - DAG_id_type_tag(bmain, ID_OB); - DAG_relations_tag_update(bmain); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - } - - return OPERATOR_FINISHED; -} - -void OBJECT_OT_hide_view_clear(wmOperatorType *ot) -{ - - /* identifiers */ - ot->name = "Clear Restrict View"; - ot->description = "Reveal the object by setting the hide flag"; - ot->idname = "OBJECT_OT_hide_view_clear"; - - /* api callbacks */ - ot->exec = object_hide_view_clear_exec; - ot->poll = ED_operator_view3d_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "select", true, "Select", ""); -} - -static int object_hide_view_set_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - bool changed = false; - const bool unselected = RNA_boolean_get(op->ptr, "unselected"); - - CTX_DATA_BEGIN(C, Base *, base, visible_bases) - { - if (!unselected) { - if (base->flag & SELECT) { - base->flag &= ~SELECT; - base->object->flag = base->flag; - base->object->restrictflag |= OB_RESTRICT_VIEW; - changed = true; - if (base == BASACT) { - ED_base_object_activate(C, NULL); - } - } - } - else { - if (!(base->flag & SELECT)) { - base->object->restrictflag |= OB_RESTRICT_VIEW; - changed = true; - if (base == BASACT) { - ED_base_object_activate(C, NULL); - } - } - } - } - CTX_DATA_END; - - if (changed) { - DAG_id_type_tag(bmain, ID_OB); - DAG_relations_tag_update(bmain); - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - - } - - return OPERATOR_FINISHED; -} - -void OBJECT_OT_hide_view_set(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Set Restrict View"; - ot->description = "Hide the object by setting the hide flag"; - ot->idname = "OBJECT_OT_hide_view_set"; - - /* api callbacks */ - ot->exec = object_hide_view_set_exec; - ot->poll = ED_operator_view3d_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects"); - -} - -/* 99% same as above except no need for scene refreshing (TODO, update render preview) */ -static int object_hide_render_clear_exec(bContext *C, wmOperator *UNUSED(op)) -{ - bool changed = false; - - /* XXX need a context loop to handle such cases */ - CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects) - { - if (ob->restrictflag & OB_RESTRICT_RENDER) { - ob->restrictflag &= ~OB_RESTRICT_RENDER; - changed = true; - } - } - CTX_DATA_END; - - if (changed) - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL); - - return OPERATOR_FINISHED; -} - -void OBJECT_OT_hide_render_clear(wmOperatorType *ot) -{ - - /* identifiers */ - ot->name = "Clear Restrict Render"; - ot->description = "Reveal the render object by setting the hide render flag"; - ot->idname = "OBJECT_OT_hide_render_clear"; - - /* api callbacks */ - ot->exec = object_hide_render_clear_exec; - ot->poll = ED_operator_view3d_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -static int object_hide_render_set_exec(bContext *C, wmOperator *op) -{ - const bool unselected = RNA_boolean_get(op->ptr, "unselected"); - - CTX_DATA_BEGIN(C, Base *, base, visible_bases) - { - if (!unselected) { - if (base->flag & SELECT) { - base->object->restrictflag |= OB_RESTRICT_RENDER; - } - } - else { - if (!(base->flag & SELECT)) { - base->object->restrictflag |= OB_RESTRICT_RENDER; - } - } - } - CTX_DATA_END; - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL); - return OPERATOR_FINISHED; -} - -void OBJECT_OT_hide_render_set(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Set Restrict Render"; - ot->description = "Hide the render object by setting the hide render flag"; - ot->idname = "OBJECT_OT_hide_render_set"; - - /* api callbacks */ - ot->exec = object_hide_render_set_exec; - ot->poll = ED_operator_view3d_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects"); -} - /* ******************* toggle editmode operator ***************** */ static bool mesh_needs_keyindex(const Mesh *me) @@ -379,7 +197,7 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f * to inform dependency graph about this. But is it really the * best place to do this? */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { ED_curve_editnurb_load(obedit); @@ -401,7 +219,7 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f /* Tag update so no access to freed data referenced from * derived cache will happen. */ - DAG_id_tag_update((ID *)obedit->data, 0); + DEG_id_tag_update((ID *)obedit->data, 0); return true; } @@ -417,6 +235,7 @@ void ED_object_editmode_exit(bContext *C, int flag) /* Note! only in exceptional cases should 'EM_DO_UNDO' NOT be in the flag */ /* Note! if 'EM_FREEDATA' isn't in the flag, use ED_object_editmode_load directly */ Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); const bool freedata = (flag & EM_FREEDATA) != 0; @@ -425,8 +244,8 @@ void ED_object_editmode_exit(bContext *C, int flag) if (ED_object_editmode_load_ex(CTX_data_main(C), obedit, freedata) == false) { /* in rare cases (background mode) its possible active object * is flagged for editmode, without 'obedit' being set [#35489] */ - if (UNLIKELY(scene->basact && (scene->basact->object->mode & OB_MODE_EDIT))) { - scene->basact->object->mode &= ~OB_MODE_EDIT; + if (UNLIKELY(sl->basact && (sl->basact->object->mode & OB_MODE_EDIT))) { + sl->basact->object->mode &= ~OB_MODE_EDIT; } if (flag & EM_WAITCURSOR) waitcursor(0); return; @@ -451,7 +270,7 @@ void ED_object_editmode_exit(bContext *C, int flag) BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED); /* also flush ob recalc, doesn't take much overhead, but used for particles */ - DAG_id_tag_update(&obedit->id, OB_RECALC_OB | OB_RECALC_DATA); + DEG_id_tag_update(&obedit->id, OB_RECALC_OB | OB_RECALC_DATA); if (flag & EM_DO_UNDO) ED_undo_push(C, "Editmode"); @@ -462,37 +281,31 @@ void ED_object_editmode_exit(bContext *C, int flag) } if (flag & EM_WAITCURSOR) waitcursor(0); + + /* This way we ensure scene's obedit is copied into all CoW scenes. */ + DEG_id_tag_update(&scene->id, 0); } void ED_object_editmode_enter(bContext *C, int flag) { Scene *scene = CTX_data_scene(C); - Base *base = NULL; + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob; - ScrArea *sa = CTX_wm_area(C); - View3D *v3d = NULL; bool ok = false; if (ID_IS_LINKED(scene)) return; - if (sa && sa->spacetype == SPACE_VIEW3D) - v3d = sa->spacedata.first; - if ((flag & EM_IGNORE_LAYER) == 0) { - base = CTX_data_active_base(C); /* active layer checked here for view3d */ + ob = CTX_data_active_object(C); /* active layer checked here for view3d */ - if (base == NULL) return; - else if (v3d && (base->lay & v3d->lay) == 0) return; - else if (!v3d && (base->lay & scene->lay) == 0) return; + if (ob == NULL) return; } else { - base = scene->basact; + ob = sl->basact->object; } - if (ELEM(NULL, base, base->object, base->object->data)) return; - - ob = base->object; + if (ELEM(NULL, ob, ob->data)) return; /* this checks actual object->data, for cases when other scenes have it in editmode context */ if (BKE_object_is_in_editmode(ob)) @@ -551,7 +364,7 @@ void ED_object_editmode_enter(bContext *C, int flag) scene->obedit = ob; ED_armature_to_edit(arm); /* to ensure all goes in restposition and without striding */ - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* XXX: should this be OB_RECALC_DATA? */ + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* XXX: should this be OB_RECALC_DATA? */ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene); } @@ -585,7 +398,9 @@ void ED_object_editmode_enter(bContext *C, int flag) } if (ok) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + /* This way we ensure scene's obedit is copied into all CoW scenes. */ + DEG_id_tag_update(&scene->id, 0); } else { scene->obedit = NULL; /* XXX for context */ @@ -697,7 +512,7 @@ void OBJECT_OT_posemode_toggle(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob) +static void copymenu_properties(SceneLayer *sl, Object *ob) { //XXX no longer used - to be removed - replaced by game_properties_copy_exec bProperty *prop; @@ -730,8 +545,8 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob) nr = pupmenu(str); if (nr == 1 || nr == 2) { - for (base = FIRSTBASE; base; base = base->next) { - if ((base != BASACT) && (TESTBASELIB(v3d, base))) { + for (base = FIRSTBASE(sl); base; base = base->next) { + if ((base != BASACT(sl)) && (TESTBASELIB(base))) { if (nr == 1) { /* replace */ BKE_bproperty_copy_list(&base->object->prop, &ob->prop); } @@ -747,8 +562,8 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob) prop = BLI_findlink(&ob->prop, nr - 4); /* account for first 3 menu items & menu index starting at 1*/ if (prop) { - for (base = FIRSTBASE; base; base = base->next) { - if ((base != BASACT) && (TESTBASELIB(v3d, base))) { + for (base = FIRSTBASE(sl); base; base = base->next) { + if ((base != BASACT(sl)) && (TESTBASELIB(base))) { BKE_bproperty_object_set(base->object, prop); } } @@ -758,14 +573,14 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob) } -static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob) +static void copymenu_logicbricks(SceneLayer *sl, Object *ob) { //XXX no longer used - to be removed - replaced by logicbricks_copy_exec Base *base; - for (base = FIRSTBASE; base; base = base->next) { + for (base = FIRSTBASE(sl); base; base = base->next) { if (base->object != ob) { - if (TESTBASELIB(v3d, base)) { + if (TESTBASELIB(base)) { /* first: free all logic */ free_sensors(&base->object->sensors); @@ -844,7 +659,7 @@ static void copy_texture_space(Object *to, Object *ob) } /* UNUSED, keep in case we want to copy functionality for use elsewhere */ -static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) +static void copy_attr(Main *bmain, Scene *scene, SceneLayer *sl, short event) { Object *ob; Base *base; @@ -854,18 +669,18 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) if (ID_IS_LINKED(scene)) return; - if (!(ob = OBACT)) return; + if (!(ob = OBACT(sl))) return; if (scene->obedit) { // XXX get from context /* obedit_copymenu(); */ return; } if (event == 9) { - copymenu_properties(scene, v3d, ob); + copymenu_properties(sl, ob); return; } else if (event == 10) { - copymenu_logicbricks(scene, v3d, ob); + copymenu_logicbricks(sl, ob); return; } else if (event == 24) { @@ -874,10 +689,10 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) return; } - for (base = FIRSTBASE; base; base = base->next) { - if (base != BASACT) { - if (TESTBASELIB(v3d, base)) { - DAG_id_tag_update(&base->object->id, OB_RECALC_DATA); + for (base = FIRSTBASE(sl); base; base = base->next) { + if (base != BASACT(sl)) { + if (TESTBASELIB(base)) { + DEG_id_tag_update(&base->object->id, OB_RECALC_DATA); if (event == 1) { /* loc */ copy_v3_v3(base->object->loc, ob->loc); @@ -980,7 +795,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) BLI_strncpy(cu1->family, cu->family, sizeof(cu1->family)); - DAG_id_tag_update(&base->object->id, OB_RECALC_DATA); + DEG_id_tag_update(&base->object->id, OB_RECALC_DATA); } } else if (event == 19) { /* bevel settings */ @@ -996,7 +811,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) cu1->ext1 = cu->ext1; cu1->ext2 = cu->ext2; - DAG_id_tag_update(&base->object->id, OB_RECALC_DATA); + DEG_id_tag_update(&base->object->id, OB_RECALC_DATA); } } else if (event == 25) { /* curve resolution */ @@ -1015,7 +830,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) nu = nu->next; } - DAG_id_tag_update(&base->object->id, OB_RECALC_DATA); + DEG_id_tag_update(&base->object->id, OB_RECALC_DATA); } } else if (event == 21) { @@ -1031,7 +846,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) } modifier_copyData(md, tmd); - DAG_id_tag_update(&base->object->id, OB_RECALC_DATA); + DEG_id_tag_update(&base->object->id, OB_RECALC_DATA); } } } @@ -1092,16 +907,16 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) } if (do_depgraph_update) - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } -static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, View3D *v3d) +static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, SceneLayer *sl) { Object *ob; short event; char str[512]; - if (!(ob = OBACT)) return; + if (!(ob = OBACT(sl))) return; if (scene->obedit) { /* XXX get from context */ /* if (ob->type == OB_MESH) */ @@ -1149,7 +964,7 @@ static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, View3D * event = pupmenu(str); if (event <= 0) return; - copy_attr(bmain, scene, v3d, event); + copy_attr(bmain, scene, sl, event); } /* ******************* force field toggle operator ***************** */ @@ -1218,6 +1033,9 @@ void OBJECT_OT_forcefield_toggle(wmOperatorType *ot) */ void ED_objects_recalculate_paths(bContext *C, Scene *scene) { + struct Main *bmain = CTX_data_main(C); + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); ListBase targets = {NULL, NULL}; /* loop over objects in scene */ @@ -1230,7 +1048,7 @@ void ED_objects_recalculate_paths(bContext *C, Scene *scene) CTX_DATA_END; /* recalculate paths, then free */ - animviz_calc_motionpaths(scene, &targets); + animviz_calc_motionpaths(&eval_ctx, bmain, scene, &targets); BLI_freelistN(&targets); } @@ -1451,7 +1269,8 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) if (ob->type == OB_MESH) { BKE_mesh_smooth_flag_set(ob, !clear); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); done = true; @@ -1464,7 +1283,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) else nu->flag &= ~ME_SMOOTH; } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); done = true; @@ -1515,7 +1334,7 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot) /* ********************** */ -static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d) +static void UNUSED_FUNCTION(image_aspect) (Scene *scene, SceneLayer *sl) { /* all selected objects with an image map: scale in image aspect */ Base *base; @@ -1528,8 +1347,8 @@ static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d) if (scene->obedit) return; // XXX get from context if (ID_IS_LINKED(scene)) return; - for (base = FIRSTBASE; base; base = base->next) { - if (TESTBASELIB(v3d, base)) { + for (base = FIRSTBASE(sl); base; base = base->next) { + if (TESTBASELIB(base)) { ob = base->object; done = false; @@ -1562,7 +1381,7 @@ static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d) else ob->size[1] = ob->size[0] * y / x; done = true; - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); BKE_image_release_ibuf(tex->ima, ibuf, NULL); } @@ -1697,8 +1516,15 @@ bool ED_object_mode_compat_set(bContext *C, Object *ob, int mode, ReportList *re { bool ok; if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) { + WorkSpace *workspace = CTX_wm_workspace(C); const char *opstring = object_mode_op_string(ob->mode); + WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL); +#ifdef USE_WORKSPACE_MODE + BKE_workspace_object_mode_set(workspace, ob->mode); +#else + UNUSED_VARS(workspace); +#endif ok = ELEM(ob->mode, mode, OB_MODE_OBJECT); if (!ok) { wmOperatorType *ot = WM_operatortype_find(opstring, false); @@ -1808,13 +1634,23 @@ void OBJECT_OT_mode_set(wmOperatorType *ot) } - void ED_object_toggle_modes(bContext *C, int mode) { if (mode != OB_MODE_OBJECT) { const char *opstring = object_mode_op_string(mode); + if (opstring) { +#ifdef USE_WORKSPACE_MODE + WorkSpace *workspace = CTX_wm_workspace(C); +#endif WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL); + +#ifdef USE_WORKSPACE_MODE + Object *ob = CTX_data_active_object(C); + if (ob) { + BKE_workspace_object_mode_set(workspace, ob->mode); + } +#endif } } } diff --git a/source/blender/editors/object/object_facemap_ops.c b/source/blender/editors/object/object_facemap_ops.c new file mode 100644 index 00000000000..857446ac6b0 --- /dev/null +++ b/source/blender/editors/object/object_facemap_ops.c @@ -0,0 +1,492 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_listbase.h" + +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" + +#include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_editmesh.h" +#include "BKE_object.h" +#include "BKE_object_facemap.h" +#include "BKE_object_deform.h" + +#include "DEG_depsgraph.h" + +#include "RNA_define.h" +#include "RNA_access.h" + +#include "WM_types.h" +#include "WM_api.h" + +#include "ED_mesh.h" +#include "ED_object.h" + +#include "object_intern.h" + +/* called while not in editmode */ +void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum) +{ + int fmap_nr; + if (GS(((ID *)ob->data)->name) != ID_ME) + return; + + /* get the face map number, exit if it can't be found */ + fmap_nr = BLI_findindex(&ob->fmaps, fmap); + + if (fmap_nr != -1) { + int *facemap; + Mesh *me = ob->data; + + /* if there's is no facemap layer then create one */ + if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL) + facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, NULL, me->totpoly); + + facemap[facenum] = fmap_nr; + } +} + +/* called while not in editmode */ +void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum) +{ + int fmap_nr; + if (GS(((ID *)ob->data)->name) != ID_ME) + return; + + /* get the face map number, exit if it can't be found */ + fmap_nr = BLI_findindex(&ob->fmaps, fmap); + + if (fmap_nr != -1) { + int *facemap; + Mesh *me = ob->data; + + /* if there's is no facemap layer then create one */ + if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL) + return; + + facemap[facenum] = -1; + } +} + +static void object_fmap_swap_edit_mode(Object *ob, int num1, int num2) +{ + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + + if (me->edit_btmesh) { + BMEditMesh *em = me->edit_btmesh; + const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP); + + if (cd_fmap_offset != -1) { + BMFace *efa; + BMIter iter; + int *map; + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset); + + if (map) { + if (num1 != -1) { + if (*map == num1) + *map = num2; + else if (*map == num2) + *map = num1; + } + } + } + } + } + } +} + +static void object_fmap_swap_object_mode(Object *ob, int num1, int num2) +{ + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + + if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) { + int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP); + int i; + + if (map) { + for (i = 0; i < me->totpoly; i++) { + if (num1 != -1) { + if (map[i] == num1) + map[i] = num2; + else if (map[i] == num2) + map[i] = num1; + } + } + } + } + } +} + +static void object_facemap_swap(Object *ob, int num1, int num2) +{ + if (BKE_object_is_in_editmode(ob)) + object_fmap_swap_edit_mode(ob, num1, num2); + else + object_fmap_swap_object_mode(ob, num1, num2); +} + +static int face_map_supported_poll(bContext *C) +{ + Object *ob = ED_object_context(C); + ID *data = (ob) ? ob->data : NULL; + return (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib); +} + +static int face_map_supported_edit_mode_poll(bContext *C) +{ + Object *ob = ED_object_context(C); + ID *data = (ob) ? ob->data : NULL; + return (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib && ob->mode == OB_MODE_EDIT); +} + +static int face_map_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = ED_object_context(C); + + BKE_object_facemap_add(ob); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_face_map_add(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Face Map"; + ot->idname = "OBJECT_OT_face_map_add"; + ot->description = "Add a new face map to the active object"; + + /* api callbacks */ + ot->poll = face_map_supported_poll; + ot->exec = face_map_add_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int face_map_remove_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = ED_object_context(C); + bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1); + + if (fmap) { + BKE_object_facemap_remove(ob, fmap); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + } + return OPERATOR_FINISHED; +} + +void OBJECT_OT_face_map_remove(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Face Map"; + ot->idname = "OBJECT_OT_face_map_remove"; + ot->description = "Remove a face map from the active object"; + + /* api callbacks */ + ot->poll = face_map_supported_poll; + ot->exec = face_map_remove_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int face_map_assign_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = ED_object_context(C); + bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1); + + if (fmap) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + BMFace *efa; + BMIter iter; + int *map; + int cd_fmap_offset; + + if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) + BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP); + + cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset); + + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + *map = ob->actfmap - 1; + } + } + + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + } + return OPERATOR_FINISHED; +} + +void OBJECT_OT_face_map_assign(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Assign Face Map"; + ot->idname = "OBJECT_OT_face_map_assign"; + ot->description = "Assign faces to a face map"; + + /* api callbacks */ + ot->poll = face_map_supported_edit_mode_poll; + ot->exec = face_map_assign_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int face_map_remove_from_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = ED_object_context(C); + bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1); + + if (fmap) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + BMFace *efa; + BMIter iter; + int *map; + int cd_fmap_offset; + int mapindex = ob->actfmap - 1; + + if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) + return OPERATOR_CANCELLED; + + cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset); + + if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && *map == mapindex) { + *map = -1; + } + } + + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + } + return OPERATOR_FINISHED; +} + +void OBJECT_OT_face_map_remove_from(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove From Face Map"; + ot->idname = "OBJECT_OT_face_map_remove_from"; + ot->description = "Remove faces from a face map"; + + /* api callbacks */ + ot->poll = face_map_supported_edit_mode_poll; + ot->exec = face_map_remove_from_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static void fmap_select(Object *ob, bool select) +{ + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + BMFace *efa; + BMIter iter; + int *map; + int cd_fmap_offset; + int mapindex = ob->actfmap - 1; + + if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) + BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP); + + cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset); + + if (*map == mapindex) { + BM_face_select_set(em->bm, efa, select); + } + } +} + +static int face_map_select_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = ED_object_context(C); + bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1); + + if (fmap) { + fmap_select(ob, true); + + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + } + return OPERATOR_FINISHED; +} + +void OBJECT_OT_face_map_select(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Face Map Faces"; + ot->idname = "OBJECT_OT_face_map_select"; + ot->description = "Select faces belonging to a face map"; + + /* api callbacks */ + ot->poll = face_map_supported_edit_mode_poll; + ot->exec = face_map_select_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int face_map_deselect_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = ED_object_context(C); + bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1); + + if (fmap) { + fmap_select(ob, false); + + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + } + return OPERATOR_FINISHED; +} + +void OBJECT_OT_face_map_deselect(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Deselect Face Map Faces"; + ot->idname = "OBJECT_OT_face_map_deselect"; + ot->description = "Deselect faces belonging to a face map"; + + /* api callbacks */ + ot->poll = face_map_supported_edit_mode_poll; + ot->exec = face_map_deselect_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + + +static int face_map_move_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_context(C); + bFaceMap *fmap; + int dir = RNA_enum_get(op->ptr, "direction"); + int pos1, pos2 = -1, count; + + fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1); + if (!fmap) { + return OPERATOR_CANCELLED; + } + + count = BLI_listbase_count(&ob->fmaps); + pos1 = BLI_findindex(&ob->fmaps, fmap); + + if (dir == 1) { /*up*/ + void *prev = fmap->prev; + + if (prev) { + pos2 = pos1 - 1; + } + else { + pos2 = count - 1; + } + + BLI_remlink(&ob->fmaps, fmap); + BLI_insertlinkbefore(&ob->fmaps, prev, fmap); + } + else { /*down*/ + void *next = fmap->next; + + if (next) { + pos2 = pos1 + 1; + } + else { + pos2 = 0; + } + + BLI_remlink(&ob->fmaps, fmap); + BLI_insertlinkafter(&ob->fmaps, next, fmap); + } + + /* iterate through mesh and substitute the indices as necessary */ + object_facemap_swap(ob, pos2, pos1); + + ob->actfmap = pos2 + 1; + + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); + + return OPERATOR_FINISHED; +} + + +void OBJECT_OT_face_map_move(wmOperatorType *ot) +{ + static EnumPropertyItem fmap_slot_move[] = { + {1, "UP", 0, "Up", ""}, + {-1, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Move Face Map"; + ot->idname = "OBJECT_OT_face_map_move"; + ot->description = "Move the active face map up/down in the list"; + + /* api callbacks */ + ot->poll = face_map_supported_poll; + ot->exec = face_map_move_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "direction", fmap_slot_move, 0, "Direction", "Direction to move, UP or DOWN"); +} diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index 46c2c4e4b7d..27c1a03190a 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -40,7 +40,6 @@ #include "DNA_scene_types.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_group.h" #include "BKE_library.h" #include "BKE_library_remap.h" @@ -48,6 +47,8 @@ #include "BKE_report.h" #include "BKE_object.h" +#include "DEG_depsgraph_build.h" + #include "ED_screen.h" #include "ED_object.h" @@ -128,7 +129,6 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); int single_group_index = RNA_enum_get(op->ptr, "group"); Group *single_group = group_object_active_find_index(ob, single_group_index); Group *group; @@ -151,7 +151,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) continue; if (!BKE_group_object_cyclic_check(bmain, base->object, group)) { - BKE_group_object_add(group, base->object, scene, base); + BKE_group_object_add(group, base->object); updated = true; } else { @@ -167,7 +167,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) if (!updated) return OPERATOR_CANCELLED; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); return OPERATOR_FINISHED; @@ -200,8 +200,8 @@ void GROUP_OT_objects_add_active(wmOperatorType *ot) static int objects_remove_active_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - Object *ob = OBACT; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = OBACT(sl); int single_group_index = RNA_enum_get(op->ptr, "group"); Group *single_group = group_object_active_find_index(ob, single_group_index); Group *group; @@ -221,7 +221,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) /* Remove groups from selected objects */ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { - BKE_group_object_unlink(group, base->object, scene, base); + BKE_group_object_unlink(group, base->object); ok = 1; } CTX_DATA_END; @@ -231,7 +231,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) if (!ok) BKE_report(op->reports, RPT_ERROR, "Active object contains no groups"); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); return OPERATOR_FINISHED; @@ -264,15 +264,14 @@ void GROUP_OT_objects_remove_active(wmOperatorType *ot) static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { - BKE_object_groups_clear(scene, base, base->object); + BKE_object_groups_clear(base->object); } CTX_DATA_END; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); return OPERATOR_FINISHED; @@ -297,7 +296,6 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); int single_group_index = RNA_enum_get(op->ptr, "group"); Group *single_group = group_object_active_find_index(ob, single_group_index); Group *group; @@ -315,7 +313,7 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op) /* now remove all selected objects from the group */ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { - BKE_group_object_unlink(group, base->object, scene, base); + BKE_group_object_unlink(group, base->object); updated = true; } CTX_DATA_END; @@ -324,7 +322,7 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op) if (!updated) return OPERATOR_CANCELLED; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); return OPERATOR_FINISHED; @@ -357,7 +355,6 @@ void GROUP_OT_objects_remove(wmOperatorType *ot) static int group_create_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); Group *group = NULL; char name[MAX_ID_NAME - 2]; /* id name */ @@ -367,11 +364,11 @@ static int group_create_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - BKE_group_object_add(group, base->object, scene, base); + BKE_group_object_add(group, base->object); } CTX_DATA_END; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); return OPERATOR_FINISHED; @@ -398,7 +395,6 @@ void GROUP_OT_create(wmOperatorType *ot) static int group_add_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); Object *ob = ED_object_context(C); Main *bmain = CTX_data_main(C); Group *group; @@ -407,7 +403,7 @@ static int group_add_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; group = BKE_group_add(bmain, "Group"); - BKE_group_object_add(group, ob, scene, NULL); + BKE_group_object_add(group, ob); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -432,7 +428,6 @@ void OBJECT_OT_group_add(wmOperatorType *ot) static int group_link_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); Object *ob = ED_object_context(C); Group *group = BLI_findlink(&bmain->group, RNA_enum_get(op->ptr, "group")); @@ -457,7 +452,7 @@ static int group_link_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_group_object_add(group, ob, scene, NULL); + BKE_group_object_add(group, ob); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -490,14 +485,13 @@ void OBJECT_OT_group_link(wmOperatorType *ot) static int group_remove_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); Object *ob = ED_object_context(C); Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data; if (!ob || !group) return OPERATOR_CANCELLED; - BKE_group_object_unlink(group, ob, scene, NULL); /* base will be used if found */ + BKE_group_object_unlink(group, ob); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -559,8 +553,10 @@ static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select o CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) { - ED_base_object_select(base, BA_SELECT); + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (BKE_group_object_exists(group, base->object)) { + ED_object_base_select(base, BA_SELECT); + } } } CTX_DATA_END; diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 42e3a4a6837..3f6651299be 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -48,7 +48,7 @@ #include "BKE_action.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_modifier.h" #include "BKE_object.h" @@ -57,6 +57,9 @@ #include "BKE_deform.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "RNA_define.h" #include "RNA_access.h" #include "RNA_enum_types.h" @@ -318,7 +321,7 @@ static bool object_hook_index_array(Scene *scene, Object *obedit, EDBM_mesh_load(obedit); EDBM_mesh_make(scene->toolsettings, obedit, true); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); em = me->edit_btmesh; @@ -445,34 +448,37 @@ static int hook_op_edit_poll(bContext *C) return 0; } -static Object *add_hook_object_new(Main *bmain, Scene *scene, Object *obedit) +static Object *add_hook_object_new(Main *bmain, Scene *scene, SceneLayer *sl, Object *obedit) { Base *base, *basedit; Object *ob; - ob = BKE_object_add(bmain, scene, OB_EMPTY, NULL); + ob = BKE_object_add(bmain, scene, sl, OB_EMPTY, NULL); - basedit = BKE_scene_base_find(scene, obedit); - base = scene->basact; + basedit = BKE_scene_layer_base_find(sl, obedit); + base = sl->basact; base->lay = ob->lay = obedit->lay; - BLI_assert(scene->basact->object == ob); + BLI_assert(sl->basact->object == ob); /* icky, BKE_object_add sets new base as active. * so set it back to the original edit object */ - scene->basact = basedit; + sl->basact = basedit; return ob; } -static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob, int mode, ReportList *reports) +static int add_hook_object(const bContext *C, Main *bmain, Scene *scene, SceneLayer *sl, Object *obedit, Object *ob, int mode, ReportList *reports) { ModifierData *md = NULL; HookModifierData *hmd = NULL; + EvaluationContext eval_ctx; float cent[3]; float pose_mat[4][4]; int tot, ok, *indexar; char name[MAX_NAME]; + CTX_data_eval_ctx(C, &eval_ctx); + ok = object_hook_index_array(scene, obedit, &tot, &indexar, name, cent); if (!ok) { @@ -482,7 +488,7 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob if (mode == OBJECT_ADDHOOK_NEWOB && !ob) { - ob = add_hook_object_new(bmain, scene, obedit); + ob = add_hook_object_new(bmain, scene, sl, obedit); /* transform cent to global coords for loc */ mul_v3_m4v3(ob->loc, obedit->obmat, cent); @@ -541,13 +547,13 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob /* matrix calculus */ /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */ /* (parentinv ) */ - BKE_object_where_is_calc(scene, ob); + BKE_object_where_is_calc(&eval_ctx, scene, ob); invert_m4_m4(ob->imat, ob->obmat); /* apparently this call goes from right to left... */ mul_m4_series(hmd->parentinv, pose_mat, ob->imat, obedit->obmat); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); return true; } @@ -556,6 +562,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); Object *obsel = NULL; const bool use_bone = RNA_boolean_get(op->ptr, "use_bone"); @@ -580,7 +587,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (add_hook_object(bmain, scene, obedit, obsel, mode, op->reports)) { + if (add_hook_object(C, bmain, scene, sl, obedit, obsel, mode, op->reports)) { WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit); return OPERATOR_FINISHED; } @@ -611,9 +618,10 @@ static int object_add_hook_newob_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); - if (add_hook_object(bmain, scene, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) { + if (add_hook_object(C, bmain, scene, sl, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) { WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit); return OPERATOR_FINISHED; @@ -655,7 +663,7 @@ static int object_hook_remove_exec(bContext *C, wmOperator *op) BLI_remlink(&ob->modifiers, (ModifierData *)hmd); modifier_free((ModifierData *)hmd); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -729,7 +737,7 @@ static int object_hook_reset_exec(bContext *C, wmOperator *op) BKE_object_modifier_hook_reset(ob, hmd); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -779,7 +787,7 @@ static int object_hook_recenter_exec(bContext *C, wmOperator *op) sub_v3_v3v3(hmd->cent, scene->cursor, ob->obmat[3]); mul_m3_v3(imat, hmd->cent); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -837,7 +845,7 @@ static int object_hook_assign_exec(bContext *C, wmOperator *op) hmd->indexar = indexar; hmd->totindex = tot; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index b8957bdedf9..3e655fa04a4 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -55,6 +55,7 @@ void OBJECT_OT_scale_clear(struct wmOperatorType *ot); void OBJECT_OT_origin_clear(struct wmOperatorType *ot); void OBJECT_OT_visual_transform_apply(struct wmOperatorType *ot); void OBJECT_OT_transform_apply(struct wmOperatorType *ot); +void OBJECT_OT_transform_axis_target(struct wmOperatorType *ot); void OBJECT_OT_origin_set(struct wmOperatorType *ot); /* object_relations.c */ @@ -70,7 +71,6 @@ void OBJECT_OT_make_local(struct wmOperatorType *ot); void OBJECT_OT_make_single_user(struct wmOperatorType *ot); void OBJECT_OT_make_links_scene(struct wmOperatorType *ot); void OBJECT_OT_make_links_data(struct wmOperatorType *ot); -void OBJECT_OT_move_to_layer(struct wmOperatorType *ot); void OBJECT_OT_drop_named_material(struct wmOperatorType *ot); void OBJECT_OT_unlink_data(struct wmOperatorType *ot); @@ -78,10 +78,6 @@ void OBJECT_OT_unlink_data(struct wmOperatorType *ot); void OBJECT_OT_mode_set(struct wmOperatorType *ot); void OBJECT_OT_editmode_toggle(struct wmOperatorType *ot); void OBJECT_OT_posemode_toggle(struct wmOperatorType *ot); -void OBJECT_OT_hide_view_set(struct wmOperatorType *ot); -void OBJECT_OT_hide_view_clear(struct wmOperatorType *ot); -void OBJECT_OT_hide_render_set(struct wmOperatorType *ot); -void OBJECT_OT_hide_render_clear(struct wmOperatorType *ot); void OBJECT_OT_proxy_make(struct wmOperatorType *ot); void OBJECT_OT_shade_smooth(struct wmOperatorType *ot); void OBJECT_OT_shade_flat(struct wmOperatorType *ot); @@ -117,6 +113,7 @@ void OBJECT_OT_metaball_add(struct wmOperatorType *ot); void OBJECT_OT_text_add(struct wmOperatorType *ot); void OBJECT_OT_armature_add(struct wmOperatorType *ot); void OBJECT_OT_empty_add(struct wmOperatorType *ot); +void OBJECT_OT_lightprobe_add(struct wmOperatorType *ot); void OBJECT_OT_drop_named_image(struct wmOperatorType *ot); void OBJECT_OT_lamp_add(struct wmOperatorType *ot); void OBJECT_OT_effector_add(struct wmOperatorType *ot); @@ -247,6 +244,15 @@ void OBJECT_OT_vertex_weight_set_active(struct wmOperatorType *ot); void OBJECT_OT_vertex_weight_normalize_active_vertex(struct wmOperatorType *ot); void OBJECT_OT_vertex_weight_copy(struct wmOperatorType *ot); +/* object_facemap_ops.c */ +void OBJECT_OT_face_map_add(struct wmOperatorType *ot); +void OBJECT_OT_face_map_remove(struct wmOperatorType *ot); +void OBJECT_OT_face_map_assign(struct wmOperatorType *ot); +void OBJECT_OT_face_map_remove_from(struct wmOperatorType *ot); +void OBJECT_OT_face_map_select(struct wmOperatorType *ot); +void OBJECT_OT_face_map_deselect(struct wmOperatorType *ot); +void OBJECT_OT_face_map_move(struct wmOperatorType *ot); + /* object_warp.c */ void TRANSFORM_OT_vertex_warp(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c index 57053ddc020..b2f9bee27ff 100644 --- a/source/blender/editors/object/object_lattice.c +++ b/source/blender/editors/object/object_lattice.c @@ -52,12 +52,13 @@ #include "RNA_enum_types.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_deform.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "ED_lattice.h" #include "ED_object.h" #include "ED_screen.h" @@ -590,7 +591,7 @@ static int make_regular_exec(bContext *C, wmOperator *UNUSED(op)) BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL); } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); return OPERATOR_FINISHED; @@ -810,7 +811,7 @@ static int lattice_flip_exec(bContext *C, wmOperator *op) } /* updates */ - DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + DEG_id_tag_update(&obedit->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 4e90a9bc7c4..a498e8a1564 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -54,7 +54,6 @@ #include "BKE_animsys.h" #include "BKE_curve.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_DerivedMesh.h" #include "BKE_effect.h" @@ -75,6 +74,9 @@ #include "BKE_softbody.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -171,8 +173,8 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc } } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - DAG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_relations_tag_update(bmain); return new_md; } @@ -253,7 +255,7 @@ bool ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v) for (md = ob->modifiers.first; md; md = md->next) { if (md->type == eModifierType_Multires) { multires_set_tot_level(ob, (MultiresModifierData *)md, totlevel); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } return false; @@ -320,7 +322,7 @@ static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md, ob->mode &= ~OB_MODE_PARTICLE_EDIT; } - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); BLI_remlink(&ob->modifiers, md); modifier_free(md); @@ -341,8 +343,8 @@ bool ED_object_modifier_remove(ReportList *reports, Main *bmain, Object *ob, Mod return 0; } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - DAG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_relations_tag_update(bmain); return 1; } @@ -365,8 +367,8 @@ void ED_object_modifier_clear(Main *bmain, Object *ob) md = next_md; } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - DAG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_relations_tag_update(bmain); } int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md) @@ -411,7 +413,7 @@ int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData * return 1; } -int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, Object *ob, ModifierData *md) +int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, SceneLayer *sl, Object *ob, ModifierData *md) { Object *obn; ParticleSystem *psys; @@ -463,7 +465,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene * if (totvert == 0) return 0; /* add new mesh */ - obn = BKE_object_add(bmain, scene, OB_MESH, NULL); + obn = BKE_object_add(bmain, scene, sl, OB_MESH, NULL); me = obn->data; me->totvert = totvert; @@ -515,14 +517,17 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene * } } - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); return 1; } -static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, ModifierData *md) +static int modifier_apply_shape(ReportList *reports, const bContext *C, Scene *scene, Object *ob, ModifierData *md) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); md->scene = scene; @@ -553,7 +558,7 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M return 0; } - dm = mesh_create_derived_for_modifier(scene, ob, md, 0); + dm = mesh_create_derived_for_modifier(&eval_ctx, scene, ob, md, 0); if (!dm) { BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply"); return 0; @@ -580,9 +585,12 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M return 1; } -static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, ModifierData *md) +static int modifier_apply_obdata(ReportList *reports, const bContext *C, Scene *scene, Object *ob, ModifierData *md) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); md->scene = scene; @@ -606,13 +614,13 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, multires_force_update(ob); if (mmd && mmd->totlvl && mti->type == eModifierTypeType_OnlyDeform) { - if (!multiresModifier_reshapeFromDeformMod(scene, mmd, ob, md)) { + if (!multiresModifier_reshapeFromDeformMod(&eval_ctx, scene, mmd, ob, md)) { BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply"); return 0; } } else { - dm = mesh_create_derived_for_modifier(scene, ob, md, 1); + dm = mesh_create_derived_for_modifier(&eval_ctx, scene, ob, md, 1); if (!dm) { BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply"); return 0; @@ -638,12 +646,12 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices"); vertexCos = BKE_curve_nurbs_vertexCos_get(&cu->nurb, &numVerts); - mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0); + mti->deformVerts(md, &eval_ctx, ob, NULL, vertexCos, numVerts, 0); BK_curve_nurbs_vertexCos_apply(&cu->nurb, vertexCos); MEM_freeN(vertexCos); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } else { BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type"); @@ -660,14 +668,14 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, if (psys->part->type != PART_HAIR) continue; - psys_apply_hair_lattice(scene, ob, psys); + psys_apply_hair_lattice(&eval_ctx, scene, ob, psys); } } return 1; } -int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md, int mode) +int ED_object_modifier_apply(ReportList *reports, const bContext *C, Scene *scene, Object *ob, ModifierData *md, int mode) { int prev_mode; @@ -695,13 +703,13 @@ int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, Modi md->mode |= eModifierMode_Realtime; if (mode == MODIFIER_APPLY_SHAPE) { - if (!modifier_apply_shape(reports, scene, ob, md)) { + if (!modifier_apply_shape(reports, C, scene, ob, md)) { md->mode = prev_mode; return 0; } } else { - if (!modifier_apply_obdata(reports, scene, ob, md)) { + if (!modifier_apply_obdata(reports, C, scene, ob, md)) { md->mode = prev_mode; return 0; } @@ -874,7 +882,7 @@ ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type) static int modifier_remove_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); int mode_orig = ob->mode; @@ -887,7 +895,7 @@ static int modifier_remove_exec(bContext *C, wmOperator *op) /* if cloth/softbody was removed, particle mode could be cleared */ if (mode_orig & OB_MODE_PARTICLE_EDIT) if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) - if (scene->basact && scene->basact->object == ob) + if (sl->basact && sl->basact->object == ob) WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); return OPERATOR_FINISHED; @@ -926,7 +934,7 @@ static int modifier_move_up_exec(bContext *C, wmOperator *op) if (!md || !ED_object_modifier_move_up(op->reports, ob, md)) return OPERATOR_CANCELLED; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -965,7 +973,7 @@ static int modifier_move_down_exec(bContext *C, wmOperator *op) if (!md || !ED_object_modifier_move_down(op->reports, ob, md)) return OPERATOR_CANCELLED; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -1003,11 +1011,11 @@ static int modifier_apply_exec(bContext *C, wmOperator *op) ModifierData *md = edit_modifier_property_get(op, ob, 0); int apply_as = RNA_enum_get(op->ptr, "apply_as"); - if (!md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) { + if (!md || !ED_object_modifier_apply(op->reports, C, scene, ob, md, apply_as)) { return OPERATOR_CANCELLED; } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -1050,13 +1058,14 @@ static int modifier_convert_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); - if (!md || !ED_object_modifier_convert(op->reports, bmain, scene, ob, md)) + if (!md || !ED_object_modifier_convert(op->reports, bmain, scene, sl, ob, md)) return OPERATOR_CANCELLED; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -1095,7 +1104,7 @@ static int modifier_copy_exec(bContext *C, wmOperator *op) if (!md || !ED_object_modifier_copy(op->reports, ob, md)) return OPERATOR_CANCELLED; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -1189,7 +1198,7 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op) ED_object_multires_update_totlevels_cb, &mmd->totlvl); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); if (ob->mode & OB_MODE_SCULPT) { @@ -1229,8 +1238,11 @@ static int multires_reshape_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_active_context(C), *secondob = NULL; Scene *scene = CTX_data_scene(C); + EvaluationContext eval_ctx; MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires); + CTX_data_eval_ctx(C, &eval_ctx); + if (!mmd) return OPERATOR_CANCELLED; @@ -1253,12 +1265,12 @@ static int multires_reshape_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (!multiresModifier_reshape(scene, mmd, ob, secondob)) { + if (!multiresModifier_reshape(&eval_ctx, scene, mmd, ob, secondob)) { BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices"); return OPERATOR_CANCELLED; } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -1406,7 +1418,7 @@ static int multires_base_apply_exec(bContext *C, wmOperator *op) multiresModifier_base_apply(mmd, ob); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -1512,7 +1524,7 @@ static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op)) BLI_gset_free(visited, NULL); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -1567,7 +1579,7 @@ static int skin_loose_mark_clear_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -1617,7 +1629,7 @@ static int skin_radii_equalize_exec(bContext *C, wmOperator *UNUSED(op)) } } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -1686,8 +1698,10 @@ static void skin_armature_bone_create(Object *skin_ob, } } -static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object *skin_ob) +static Object *modifier_skin_armature_create(const bContext *C, Scene *scene, SceneLayer *sl, Object *skin_ob) { + Main *bmain = CTX_data_main(C); + EvaluationContext eval_ctx; BLI_bitmap *edges_visited; DerivedMesh *deform_dm; MVert *mvert; @@ -1699,7 +1713,9 @@ static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object * int *emap_mem; int v; - deform_dm = mesh_get_derived_deform(scene, skin_ob, CD_MASK_BAREMESH); + CTX_data_eval_ctx(C, &eval_ctx); + + deform_dm = mesh_get_derived_deform(&eval_ctx, scene, skin_ob, CD_MASK_BAREMESH); mvert = deform_dm->getVertArray(deform_dm); /* add vertex weights to original mesh */ @@ -1709,7 +1725,7 @@ static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object * NULL, me->totvert); - arm_ob = BKE_object_add(bmain, scene, OB_ARMATURE, NULL); + arm_ob = BKE_object_add(bmain, scene, sl, OB_ARMATURE, NULL); BKE_object_transform_copy(arm_ob, skin_ob); arm = arm_ob->data; arm->layer = 1; @@ -1768,6 +1784,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob = CTX_data_active_object(C), *arm_ob; Mesh *me = ob->data; ModifierData *skin_md; @@ -1779,7 +1796,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) } /* create new armature */ - arm_ob = modifier_skin_armature_create(bmain, scene, ob); + arm_ob = modifier_skin_armature_create(C, scene, sl, ob); /* add a modifier to connect the new armature to the mesh */ arm_md = (ArmatureModifierData *)modifier_new(eModifierType_Armature); @@ -1789,8 +1806,8 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) arm_md->object = arm_ob; arm_md->deformflag = ARM_DEF_VGROUP | ARM_DEF_QUATERNION; - DAG_relations_tag_update(bmain); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); @@ -1857,7 +1874,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) csmd->bind_coords_num = (unsigned int)-1; } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -1899,8 +1916,11 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); + EvaluationContext eval_ctx; MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_MeshDeform); + CTX_data_eval_ctx(C, &eval_ctx); + if (!mmd) return OPERATOR_CANCELLED; @@ -1926,7 +1946,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op) mmd->totcagevert = 0; mmd->totinfluence = 0; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); } else { @@ -1938,17 +1958,17 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op) mmd->modifier.mode |= eModifierMode_Realtime; if (ob->type == OB_MESH) { - dm = mesh_create_derived_view(scene, ob, 0); + dm = mesh_create_derived_view(&eval_ctx, scene, ob, 0); dm->release(dm); } else if (ob->type == OB_LATTICE) { - BKE_lattice_modifiers_calc(scene, ob); + BKE_lattice_modifiers_calc(&eval_ctx, scene, ob); } else if (ob->type == OB_MBALL) { - BKE_displist_make_mball(CTX_data_main(C)->eval_ctx, scene, ob); + BKE_displist_make_mball(&eval_ctx, scene, ob); } else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - BKE_displist_make_curveTypes(scene, ob, 0); + BKE_displist_make_curveTypes(&eval_ctx, scene, ob, 0); } mmd->bindfunc = NULL; @@ -2000,7 +2020,7 @@ static int explode_refresh_exec(bContext *C, wmOperator *op) emd->flag |= eExplodeFlag_CalcFaces; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -2145,7 +2165,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) if (free) { omd->refresh |= MOD_OCEAN_REFRESH_CLEAR_CACHE; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; } @@ -2173,7 +2193,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) * this part of the process before a threaded job is created */ //scene->r.cfra = f; - //ED_update_for_newframe(CTX_data_main(C), scene, 1); + //ED_update_for_newframe(CTX_data_main(C), scene); /* ok, this doesn't work with drivers, but is way faster. * let's use this for now and hope nobody wants to drive the time value... */ @@ -2195,7 +2215,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) scene->r.cfra = cfra; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); #endif @@ -2268,7 +2288,7 @@ static int laplaciandeform_bind_exec(bContext *C, wmOperator *op) else { lmd->flag |= MOD_LAPLACIANDEFORM_BIND; } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; } @@ -2320,7 +2340,7 @@ static int surfacedeform_bind_exec(bContext *C, wmOperator *op) smd->flags |= MOD_SDEF_BIND; } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 9b9f77a1dbb..c87df877d5c 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -61,16 +61,13 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_origin_clear); WM_operatortype_append(OBJECT_OT_visual_transform_apply); WM_operatortype_append(OBJECT_OT_transform_apply); + WM_operatortype_append(OBJECT_OT_transform_axis_target); WM_operatortype_append(OBJECT_OT_origin_set); WM_operatortype_append(OBJECT_OT_mode_set); WM_operatortype_append(OBJECT_OT_editmode_toggle); WM_operatortype_append(OBJECT_OT_posemode_toggle); WM_operatortype_append(OBJECT_OT_proxy_make); - WM_operatortype_append(OBJECT_OT_hide_view_clear); - WM_operatortype_append(OBJECT_OT_hide_view_set); - WM_operatortype_append(OBJECT_OT_hide_render_clear); - WM_operatortype_append(OBJECT_OT_hide_render_set); WM_operatortype_append(OBJECT_OT_shade_smooth); WM_operatortype_append(OBJECT_OT_shade_flat); WM_operatortype_append(OBJECT_OT_paths_calculate); @@ -90,13 +87,11 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_make_single_user); WM_operatortype_append(OBJECT_OT_make_links_scene); WM_operatortype_append(OBJECT_OT_make_links_data); - WM_operatortype_append(OBJECT_OT_move_to_layer); WM_operatortype_append(OBJECT_OT_select_random); WM_operatortype_append(OBJECT_OT_select_all); WM_operatortype_append(OBJECT_OT_select_same_group); WM_operatortype_append(OBJECT_OT_select_by_type); - WM_operatortype_append(OBJECT_OT_select_by_layer); WM_operatortype_append(OBJECT_OT_select_linked); WM_operatortype_append(OBJECT_OT_select_grouped); WM_operatortype_append(OBJECT_OT_select_mirror); @@ -113,6 +108,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_text_add); WM_operatortype_append(OBJECT_OT_armature_add); WM_operatortype_append(OBJECT_OT_empty_add); + WM_operatortype_append(OBJECT_OT_lightprobe_add); WM_operatortype_append(OBJECT_OT_drop_named_image); WM_operatortype_append(OBJECT_OT_lamp_add); WM_operatortype_append(OBJECT_OT_camera_add); @@ -202,6 +198,14 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_vertex_weight_normalize_active_vertex); WM_operatortype_append(OBJECT_OT_vertex_weight_copy); + WM_operatortype_append(OBJECT_OT_face_map_add); + WM_operatortype_append(OBJECT_OT_face_map_remove); + WM_operatortype_append(OBJECT_OT_face_map_assign); + WM_operatortype_append(OBJECT_OT_face_map_remove_from); + WM_operatortype_append(OBJECT_OT_face_map_select); + WM_operatortype_append(OBJECT_OT_face_map_deselect); + WM_operatortype_append(OBJECT_OT_face_map_move); + WM_operatortype_append(TRANSFORM_OT_vertex_warp); WM_operatortype_append(OBJECT_OT_game_property_new); @@ -376,25 +380,6 @@ void ED_keymap_object(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "OBJECT_OT_origin_clear", OKEY, KM_PRESS, KM_ALT, 0); - WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0); - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0); - RNA_boolean_set(kmi->ptr, "unselected", false); - - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "unselected", true); - - /* same as above but for rendering */ - WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_clear", HKEY, KM_PRESS, KM_ALT | KM_CTRL, 0); - WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_set", HKEY, KM_PRESS, KM_CTRL, 0); - - /* conflicts, removing */ -#if 0 - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_set", HKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0) - RNA_boolean_set(kmi->ptr, "unselected", true); -#endif - - WM_keymap_add_item(keymap, "OBJECT_OT_move_to_layer", MKEY, KM_PRESS, 0, 0); - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", XKEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "use_global", false); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index f8c80f2a933..eee1ae64505 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -63,10 +63,10 @@ #include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_camera.h" +#include "BKE_collection.h" #include "BKE_context.h" #include "BKE_constraint.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_displist.h" #include "BKE_global.h" @@ -75,6 +75,7 @@ #include "BKE_idprop.h" #include "BKE_lamp.h" #include "BKE_lattice.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" @@ -92,6 +93,9 @@ #include "BKE_texture.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "WM_api.h" #include "WM_types.h" @@ -123,7 +127,9 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); + EvaluationContext eval_ctx; BMVert *eve; BMIter iter; Curve *cu; @@ -133,6 +139,8 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) Object *par; int a, v1 = 0, v2 = 0, v3 = 0, v4 = 0, nr = 1; + CTX_data_eval_ctx(C, &eval_ctx); + /* we need 1 to 3 selected vertices */ if (obedit->type == OB_MESH) { @@ -142,7 +150,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) EDBM_mesh_load(obedit); EDBM_mesh_make(scene->toolsettings, obedit, true); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); em = me->edit_btmesh; @@ -151,7 +159,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) /* derivedMesh might be needed for solving parenting, * so re-create it here */ - makeDerivedMesh(scene, obedit, em, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX, false); + makeDerivedMesh(&eval_ctx, scene, obedit, em, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX, false); BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { @@ -230,7 +238,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { if (ob != obedit) { - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); par = obedit->parent; if (BKE_object_parent_loop_check(par, ob)) { @@ -239,7 +247,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) else { Object workob; - ob->parent = BASACT->object; + ob->parent = BASACT(sl)->object; if (v3) { ob->partype = PARVERT3; ob->par1 = v1 - 1; @@ -247,7 +255,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) ob->par3 = v3 - 1; /* inverse parent matrix */ - BKE_object_workob_calc_parent(scene, ob, &workob); + BKE_object_workob_calc_parent(&eval_ctx, scene, ob, &workob); invert_m4_m4(ob->parentinv, workob.obmat); } else { @@ -255,7 +263,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) ob->par1 = v1 - 1; /* inverse parent matrix */ - BKE_object_workob_calc_parent(scene, ob, &workob); + BKE_object_workob_calc_parent(&eval_ctx, scene, ob, &workob); invert_m4_m4(ob->parentinv, workob.obmat); } } @@ -263,7 +271,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT, NULL); @@ -334,6 +342,7 @@ static int make_proxy_exec(bContext *C, wmOperator *op) Object *ob, *gob = ED_object_active_context(C); GroupObject *go; Scene *scene = CTX_data_scene(C); + SceneLayer *scene_layer = CTX_data_scene_layer(C); if (gob->dup_group != NULL) { go = BLI_findlink(&gob->dup_group->gobject, RNA_enum_get(op->ptr, "object")); @@ -346,30 +355,28 @@ static int make_proxy_exec(bContext *C, wmOperator *op) if (ob) { Object *newob; - Base *newbase, *oldbase = BASACT; char name[MAX_ID_NAME + 4]; BLI_snprintf(name, sizeof(name), "%s_proxy", ((ID *)(gob ? gob : ob))->name + 2); /* Add new object for the proxy */ - newob = BKE_object_add(bmain, scene, OB_EMPTY, name); + newob = BKE_object_add_from(bmain, scene, scene_layer, OB_EMPTY, name, gob ? gob : ob); /* set layers OK */ - newbase = BASACT; /* BKE_object_add sets active... */ - newbase->lay = oldbase->lay; - newob->lay = newbase->lay; - - /* remove base, leave user count of object, it gets linked in BKE_object_make_proxy */ - if (gob == NULL) { - BKE_scene_base_unlink(scene, oldbase); - MEM_freeN(oldbase); - } - BKE_object_make_proxy(newob, ob, gob); + /* Set back pointer immediately so dependency graph knows that this is + * is a proxy and will act accordingly. Otherwise correctness of graph + * will depend on order of bases. + * + * TODO(sergey): We really need to get rid of this bi-directional links + * in proxies with something like static overrides. + */ + newob->proxy->proxy_from = newob; + /* depsgraph flushes are needed for the new data */ - DAG_relations_tag_update(bmain); - DAG_id_tag_update(&newob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&newob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob); } else { @@ -524,7 +531,7 @@ void ED_object_parent_clear(Object *ob, const int type) /* Always clear parentinv matrix for sake of consistency, see T41950. */ unit_m4(ob->parentinv); - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } /* note, poll should check for editable scene */ @@ -539,7 +546,7 @@ static int parent_clear_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL); return OPERATOR_FINISHED; @@ -607,13 +614,17 @@ EnumPropertyItem prop_make_parent_types[] = { {0, NULL, 0, NULL, NULL} }; -bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object *ob, Object *par, +bool ED_object_parent_set(ReportList *reports, const bContext *C, Scene *scene, Object *ob, Object *par, int partype, const bool xmirror, const bool keep_transform, const int vert_par[3]) { + Main *bmain = CTX_data_main(C); + EvaluationContext eval_ctx; bPoseChannel *pchan = NULL; const bool pararm = ELEM(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO); - DAG_id_tag_update(&par->id, OB_RECALC_OB); + CTX_data_eval_ctx(C, &eval_ctx); + + DEG_id_tag_update(&par->id, OB_RECALC_OB); /* preconditions */ if (partype == PAR_FOLLOW || partype == PAR_PATH_CONST) { @@ -624,7 +635,7 @@ bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object if ((cu->flag & CU_PATH) == 0) { cu->flag |= CU_PATH | CU_FOLLOW; - BKE_displist_make_curveTypes(scene, par, 0); /* force creation of path data */ + BKE_displist_make_curveTypes(&eval_ctx, scene, par, 0); /* force creation of path data */ } else { cu->flag |= CU_FOLLOW; @@ -710,7 +721,7 @@ bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object ((CurveModifierData *)md)->object = par; } if (par->curve_cache && par->curve_cache->path == NULL) { - DAG_id_tag_update(&par->id, OB_RECALC_DATA); + DEG_id_tag_update(&par->id, OB_RECALC_DATA); } } break; @@ -766,34 +777,36 @@ bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object data = con->data; data->tar = par; - BKE_constraint_target_matrix_get(scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra); + BKE_constraint_target_matrix_get(&eval_ctx, scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra); sub_v3_v3v3(vec, ob->obmat[3], cmat[3]); copy_v3_v3(ob->loc, vec); } else if (pararm && (ob->type == OB_MESH) && (par->type == OB_ARMATURE)) { - if (partype == PAR_ARMATURE_NAME) - create_vgroups_from_armature(reports, scene, ob, par, ARM_GROUPS_NAME, false); - else if (partype == PAR_ARMATURE_ENVELOPE) - create_vgroups_from_armature(reports, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror); + if (partype == PAR_ARMATURE_NAME) { + create_vgroups_from_armature(reports, &eval_ctx, scene, ob, par, ARM_GROUPS_NAME, false); + } + else if (partype == PAR_ARMATURE_ENVELOPE) { + create_vgroups_from_armature(reports, &eval_ctx, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror); + } else if (partype == PAR_ARMATURE_AUTO) { WM_cursor_wait(1); - create_vgroups_from_armature(reports, scene, ob, par, ARM_GROUPS_AUTO, xmirror); + create_vgroups_from_armature(reports, &eval_ctx, scene, ob, par, ARM_GROUPS_AUTO, xmirror); WM_cursor_wait(0); } /* get corrected inverse */ ob->partype = PAROBJECT; - BKE_object_workob_calc_parent(scene, ob, &workob); + BKE_object_workob_calc_parent(&eval_ctx, scene, ob, &workob); invert_m4_m4(ob->parentinv, workob.obmat); } else { /* calculate inverse parent matrix */ - BKE_object_workob_calc_parent(scene, ob, &workob); + BKE_object_workob_calc_parent(&eval_ctx, scene, ob, &workob); invert_m4_m4(ob->parentinv, workob.obmat); } - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); } } @@ -864,7 +877,7 @@ static int parent_set_exec(bContext *C, wmOperator *op) parent_set_vert_find(tree, ob, vert_par, is_tri); } - if (!ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) { + if (!ED_object_parent_set(op->reports, C, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) { ok = false; break; } @@ -879,7 +892,7 @@ static int parent_set_exec(bContext *C, wmOperator *op) if (!ok) return OPERATOR_CANCELLED; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL); @@ -996,7 +1009,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Object *par = ED_object_active_context(C); - DAG_id_tag_update(&par->id, OB_RECALC_OB); + DEG_id_tag_update(&par->id, OB_RECALC_OB); /* context iterator */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) @@ -1011,7 +1024,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op) memset(ob->loc, 0, 3 * sizeof(float)); /* set recalc flags */ - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); /* set parenting type for object - object only... */ ob->parent = par; @@ -1021,7 +1034,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); return OPERATOR_FINISHED; @@ -1048,15 +1061,18 @@ void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot) static int object_slow_parent_clear_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { if (ob->parent) { if (ob->partype & PARSLOW) { ob->partype -= PARSLOW; - BKE_object_where_is_calc(scene, ob); + BKE_object_where_is_calc(&eval_ctx, scene, ob); ob->partype |= PARSLOW; - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } } } @@ -1094,7 +1110,7 @@ static int object_slow_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) if (ob->parent) ob->partype |= PARSLOW; - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } CTX_DATA_END; @@ -1148,7 +1164,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op) /* remove track-object for old track */ ob->track = NULL; - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* also remove all tracking constraints */ for (con = ob->constraints.last; con; con = pcon) { @@ -1162,7 +1178,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); return OPERATOR_FINISHED; @@ -1222,7 +1238,7 @@ static int track_set_exec(bContext *C, wmOperator *op) data = con->data; data->tar = obact; - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* Lamp, Camera and Speaker track differently by default */ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) { @@ -1245,7 +1261,7 @@ static int track_set_exec(bContext *C, wmOperator *op) data = con->data; data->tar = obact; - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* Lamp, Camera and Speaker track differently by default */ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) { @@ -1269,7 +1285,7 @@ static int track_set_exec(bContext *C, wmOperator *op) data = con->data; data->tar = obact; - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* Lamp, Camera and Speaker track differently by default */ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) { @@ -1283,7 +1299,7 @@ static int track_set_exec(bContext *C, wmOperator *op) } } - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); return OPERATOR_FINISHED; @@ -1309,119 +1325,6 @@ void OBJECT_OT_track_set(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", ""); } -/************************** Move to Layer Operator *****************************/ - -static unsigned int move_to_layer_init(bContext *C, wmOperator *op) -{ - int values[20], a; - unsigned int lay = 0; - - if (!RNA_struct_property_is_set(op->ptr, "layers")) { - /* note: layers are set in bases, library objects work for this */ - CTX_DATA_BEGIN (C, Base *, base, selected_bases) - { - lay |= base->lay; - } - CTX_DATA_END; - - for (a = 0; a < 20; a++) - values[a] = (lay & (1 << a)) != 0; - - RNA_boolean_set_array(op->ptr, "layers", values); - } - else { - RNA_boolean_get_array(op->ptr, "layers", values); - - for (a = 0; a < 20; a++) - if (values[a]) - lay |= (1 << a); - } - - return lay; -} - -static int move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - View3D *v3d = CTX_wm_view3d(C); - if (v3d && v3d->localvd) { - return WM_operator_confirm_message(C, op, "Move out of Local View"); - } - else { - move_to_layer_init(C, op); - return WM_operator_props_popup(C, op, event); - } -} - -static int move_to_layer_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - unsigned int lay, local; - /* bool is_lamp = false; */ /* UNUSED */ - - lay = move_to_layer_init(C, op); - lay &= 0xFFFFFF; - - if (lay == 0) return OPERATOR_CANCELLED; - - if (v3d && v3d->localvd) { - /* now we can move out of localview. */ - /* note: layers are set in bases, library objects work for this */ - CTX_DATA_BEGIN (C, Base *, base, selected_bases) - { - lay = base->lay & ~v3d->lay; - base->lay = lay; - base->object->lay = lay; - base->object->flag &= ~SELECT; - base->flag &= ~SELECT; - /* if (base->object->type == OB_LAMP) is_lamp = true; */ - } - CTX_DATA_END; - } - else { - /* normal non localview operation */ - /* note: layers are set in bases, library objects work for this */ - CTX_DATA_BEGIN (C, Base *, base, selected_bases) - { - /* upper byte is used for local view */ - local = base->lay & 0xFF000000; - base->lay = lay + local; - base->object->lay = base->lay; - /* if (base->object->type == OB_LAMP) is_lamp = true; */ - } - CTX_DATA_END; - } - - /* warning, active object may be hidden now */ - - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene); - WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); - - DAG_relations_tag_update(bmain); - - return OPERATOR_FINISHED; -} - -void OBJECT_OT_move_to_layer(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Move to Layer"; - ot->description = "Move the object to different layers"; - ot->idname = "OBJECT_OT_move_to_layer"; - - /* api callbacks */ - ot->invoke = move_to_layer_invoke; - ot->exec = move_to_layer_exec; - ot->poll = ED_operator_objectmode; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_boolean_layer_member(ot->srna, "layers", 20, NULL, "Layer", ""); -} - /************************** Link to Scene Operator *****************************/ #if 0 @@ -1444,20 +1347,6 @@ static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr)) } #endif -Base *ED_object_scene_link(Scene *scene, Object *ob) -{ - Base *base; - - if (BKE_scene_base_find(scene, ob)) { - return NULL; - } - - base = BKE_scene_base_add(scene, ob); - id_us_plus(&ob->id); - - return base; -} - static int make_links_scene_exec(bContext *C, wmOperator *op) { Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene")); @@ -1477,9 +1366,10 @@ static int make_links_scene_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + SceneCollection *sc_to = BKE_collection_master(scene_to); CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - ED_object_scene_link(scene_to, base->object); + BKE_collection_object_add(scene_to, sc_to, base->object); } CTX_DATA_END; @@ -1535,7 +1425,6 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst static int make_links_data_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); const int type = RNA_enum_get(op->ptr, "type"); Object *ob_src; ID *obdata_id; @@ -1572,7 +1461,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) /* if amount of material indices changed: */ test_object_materials(ob_dst, ob_dst->data); - DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); break; case MAKE_LINKS_MATERIALS: /* new approach, using functions from kernel */ @@ -1580,7 +1469,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) Material *ma = give_current_material(ob_src, a + 1); assign_material(ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF); /* also works with ma==NULL */ } - DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); break; case MAKE_LINKS_ANIMDATA: BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, false); @@ -1591,19 +1480,19 @@ static int make_links_data_exec(bContext *C, wmOperator *op) } BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, false); } - DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); break; case MAKE_LINKS_GROUP: { LinkNode *group_node; /* first clear groups */ - BKE_object_groups_clear(scene, base_dst, ob_dst); + BKE_object_groups_clear(ob_dst); /* now add in the groups from the link nodes */ for (group_node = ob_groups; group_node; group_node = group_node->next) { if (ob_dst->dup_group != group_node->link) { - BKE_group_object_add(group_node->link, ob_dst, scene, base_dst); + BKE_group_object_add(group_node->link, ob_dst); } else { is_cycle = true; @@ -1620,7 +1509,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) break; case MAKE_LINKS_MODIFIERS: BKE_object_link_modifiers(ob_dst, ob_src); - DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); break; case MAKE_LINKS_FONTS: { @@ -1649,7 +1538,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) cu_dst->vfontbi = cu_src->vfontbi; id_us_plus((ID *)cu_dst->vfontbi); - DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); break; } } @@ -1672,7 +1561,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_WARNING, "Skipped editing library object data"); } - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, CTX_wm_view3d(C)); WM_event_add_notifier(C, NC_OBJECT, NULL); @@ -1736,48 +1625,82 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot) /**************************** Make Single User ********************************/ +static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob, const bool copy_groups) +{ + if (!ID_IS_LINKED(ob) && ob->id.us > 1) { + /* base gets copy of object */ + Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob)); + + if (copy_groups) { + if (ob->flag & OB_FROMGROUP) { + obn->flag |= OB_FROMGROUP; + } + } + else { + /* copy already clears */ + } + /* remap gpencil parenting */ + + if (scene->gpd) { + bGPdata *gpd = scene->gpd; + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + if (gpl->parent == ob) { + gpl->parent = obn; + } + } + } + + id_us_min(&ob->id); + return obn; + } + return NULL; +} + +static void libblock_relink_scene_collection(SceneCollection *sc) +{ + for (LinkData *link = sc->objects.first; link; link = link->next) { + BKE_libblock_relink_to_newid(link->data); + } + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + libblock_relink_scene_collection(nsc); + } +} + +static void single_object_users_scene_collection(Main *bmain, Scene *scene, SceneCollection *sc, const int flag, const bool copy_groups) +{ + for (LinkData *link = sc->objects.first; link; link = link->next) { + Object *ob = link->data; + /* an object may be in more than one collection */ + if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) { + link->data = single_object_users_object(bmain, scene, link->data, copy_groups); + } + } + + /* we reset filter objects because they should be regenerated after this */ + BLI_freelistN(&sc->filter_objects); + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + single_object_users_scene_collection(bmain, scene, nsc, flag, copy_groups); + } +} + /* Warning, sets ID->newid pointers of objects and groups, but does not clear them. */ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups) { - Base *base; - Object *ob, *obn; Group *group, *groupn; GroupObject *go; clear_sca_new_poins(); /* BGE logic */ - /* duplicate (must set newid) */ - for (base = FIRSTBASE; base; base = base->next) { - ob = base->object; + /* duplicate all the objects of the scene */ + SceneCollection *msc = BKE_collection_master(scene); + single_object_users_scene_collection(bmain, scene, msc, flag, copy_groups); - if ((base->flag & flag) == flag) { - if (!ID_IS_LINKED(ob) && ob->id.us > 1) { - /* base gets copy of object */ - base->object = obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob)); - - if (copy_groups) { - if (ob->flag & OB_FROMGROUP) { - obn->flag |= OB_FROMGROUP; - } - } - else { - /* copy already clears */ - } - /* remap gpencil parenting */ - - if (scene->gpd) { - bGPdata *gpd = scene->gpd; - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - if (gpl->parent == ob) { - gpl->parent = obn; - } - } - } - - base->flag = obn->flag; - - id_us_min(&ob->id); - } + /* loop over SceneLayers and assign the pointers accordingly */ + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + ID_NEW_REMAP(base->object); } } @@ -1810,27 +1733,28 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in if (v3d) ID_NEW_REMAP(v3d->camera); /* object and group pointers */ - for (base = FIRSTBASE; base; base = base->next) { - BKE_libblock_relink_to_newid(&base->object->id); - } + libblock_relink_scene_collection(msc); set_sca_new_poins(); + + /* TODO redo filter */ + TODO_LAYER_SYNC_FILTER } /* not an especially efficient function, only added so the single user * button can be functional.*/ void ED_object_single_user(Main *bmain, Scene *scene, Object *ob) { - Base *base; - const bool copy_groups = false; - - for (base = FIRSTBASE; base; base = base->next) { - if (base->object == ob) base->flag |= OB_DONE; - else base->flag &= ~OB_DONE; + FOREACH_SCENE_OBJECT(scene, ob_iter) + { + ob_iter->flag &= ~OB_DONE; } + FOREACH_SCENE_OBJECT_END - single_object_users(bmain, scene, NULL, OB_DONE, copy_groups); + /* tag only the one object */ + ob->flag |= OB_DONE; + single_object_users(bmain, scene, NULL, OB_DONE, false); BKE_main_id_clear_newpoins(bmain); } @@ -1855,25 +1779,23 @@ static void new_id_matar(Main *bmain, Material **matar, const int totcol) } } -static void single_obdata_users(Main *bmain, Scene *scene, const int flag) +static void single_obdata_users(Main *bmain, Scene *scene, SceneLayer *sl, const int flag) { - Object *ob; Lamp *la; Curve *cu; /* Camera *cam; */ - Base *base; Mesh *me; Lattice *lat; ID *id; int a; - for (base = FIRSTBASE; base; base = base->next) { - ob = base->object; - if (!ID_IS_LINKED(ob) && (base->flag & flag) == flag) { + FOREACH_OBJECT_FLAG(scene, sl, flag, ob) + { + if (!ID_IS_LINKED(ob)) { id = ob->data; if (id && id->us > 1 && !ID_IS_LINKED(id)) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); switch (ob->type) { case OB_LAMP: @@ -1911,7 +1833,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) BKE_animdata_copy_id_action((ID *)lat->key, false); break; case OB_ARMATURE: - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data)); BKE_pose_rebuild(ob, ob->data); break; @@ -1935,6 +1857,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) } } } + FOREACH_OBJECT_FLAG_END me = bmain->mesh.first; while (me) { @@ -1943,31 +1866,24 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) } } -static void single_object_action_users(Scene *scene, const int flag) +static void single_object_action_users(Scene *scene, SceneLayer *sl, const int flag) { - Object *ob; - Base *base; - - for (base = FIRSTBASE; base; base = base->next) { - ob = base->object; - if (!ID_IS_LINKED(ob) && (flag == 0 || (base->flag & SELECT)) ) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + FOREACH_OBJECT_FLAG(scene, sl, flag, ob) + if (!ID_IS_LINKED(ob)) { + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); BKE_animdata_copy_id_action(&ob->id, false); } - } + FOREACH_OBJECT_FLAG_END } -static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bool do_textures) +static void single_mat_users(Main *bmain, Scene *scene, SceneLayer *sl, const int flag, const bool do_textures) { - Object *ob; - Base *base; Material *ma, *man; Tex *tex; int a, b; - for (base = FIRSTBASE; base; base = base->next) { - ob = base->object; - if (!ID_IS_LINKED(ob) && (flag == 0 || (base->flag & SELECT)) ) { + FOREACH_OBJECT_FLAG(scene, sl, flag, ob) + if (!ID_IS_LINKED(ob)) { for (a = 1; a <= ob->totcol; a++) { ma = give_current_material(ob, a); if (ma) { @@ -1996,7 +1912,7 @@ static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bo } } } - } + FOREACH_OBJECT_FLAG_END } static void do_single_tex_user(Main *bmain, Tex **from) @@ -2099,8 +2015,8 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo single_object_users(bmain, scene, NULL, 0, copy_groups); if (full) { - single_obdata_users(bmain, scene, 0); - single_object_action_users(scene, 0); + single_obdata_users(bmain, scene, NULL, 0); + single_object_action_users(scene, NULL, 0); single_mat_users_expand(bmain); single_tex_users_expand(bmain); } @@ -2121,12 +2037,13 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo { IDP_RelinkProperty(scene->id.properties); - for (Base *base = scene->base.first; base; base = base->next) { - Object *ob = base->object; + FOREACH_SCENE_OBJECT(scene, ob) + { if (!ID_IS_LINKED(ob)) { IDP_RelinkProperty(ob->id.properties); } } + FOREACH_SCENE_OBJECT_END if (scene->nodetree) { IDP_RelinkProperty(scene->nodetree->id.properties); @@ -2148,7 +2065,7 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo } } BKE_main_id_clear_newpoins(bmain); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } /******************************* Make Local ***********************************/ @@ -2215,7 +2132,7 @@ static void tag_localizable_objects(bContext *C, const int mode) * Instance indirectly referenced zero user objects, * otherwise they're lost on reload, see T40595. */ -static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene) +static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene, SceneLayer *sl, SceneCollection *sc) { Object *ob; bool changed = false; @@ -2226,10 +2143,11 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene) id_us_plus(&ob->id); - base = BKE_scene_base_add(scene, ob); - base->flag |= SELECT; - base->object->flag = base->flag; - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + BKE_collection_object_add(scene, sc, ob); + base = BKE_scene_layer_base_find(sl, ob); + base->flag |= BASE_SELECTED; + BKE_scene_object_base_flag_sync_from_base(base); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); changed = true; } @@ -2308,12 +2226,15 @@ static int make_local_exec(bContext *C, wmOperator *op) /* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */ if (mode == MAKE_LOCAL_ALL) { + SceneLayer *scene_layer = CTX_data_scene_layer(C); + SceneCollection *scene_collection = CTX_data_scene_collection(C); + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); - /* de-select so the user can differentiate newly instanced from existing objects */ - BKE_scene_base_deselect_all(scene); + /* De-select so the user can differentiate newly instanced from existing objects. */ + BKE_scene_layer_base_deselect_all(scene_layer); - if (make_local_all__instance_indirect_unused(bmain, scene)) { + if (make_local_all__instance_indirect_unused(bmain, scene, scene_layer, scene_collection)) { BKE_report(op->reports, RPT_INFO, "Orphan library objects added to the current scene to avoid loss"); } } @@ -2413,24 +2334,31 @@ static int make_single_user_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); View3D *v3d = CTX_wm_view3d(C); /* ok if this is NULL */ const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0; const bool copy_groups = false; bool update_deps = false; if (RNA_boolean_get(op->ptr, "object")) { - single_object_users(bmain, scene, v3d, flag, copy_groups); + if (flag == SELECT) { + BKE_scene_layer_selected_objects_tag(sl, OB_DONE); + single_object_users(bmain, scene, v3d, OB_DONE, copy_groups); + } + else { + single_object_users(bmain, scene, v3d, 0, copy_groups); + } /* needed since object relationships may have changed */ update_deps = true; } if (RNA_boolean_get(op->ptr, "obdata")) { - single_obdata_users(bmain, scene, flag); + single_obdata_users(bmain, scene, sl, flag); } if (RNA_boolean_get(op->ptr, "material")) { - single_mat_users(bmain, scene, flag, RNA_boolean_get(op->ptr, "texture")); + single_mat_users(bmain, scene, sl, flag, RNA_boolean_get(op->ptr, "texture")); } #if 0 /* can't do this separate from materials */ @@ -2438,7 +2366,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op) single_mat_users(scene, flag, true); #endif if (RNA_boolean_get(op->ptr, "animation")) { - single_object_action_users(scene, flag); + single_object_action_users(scene, sl, flag); } BKE_main_id_clear_newpoins(bmain); @@ -2446,7 +2374,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_WINDOW, NULL); if (update_deps) { - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } return OPERATOR_FINISHED; @@ -2496,7 +2424,7 @@ static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent assign_material(base->object, ma, 1, BKE_MAT_ASSIGN_USERPREF); - DAG_id_tag_update(&base->object->id, OB_RECALC_OB); + DEG_id_tag_update(&base->object->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, base->object); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index 8d5c2387fe9..1542978041e 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -41,6 +41,7 @@ #include "DNA_scene_types.h" #include "DNA_armature_types.h" #include "DNA_lamp_types.h" +#include "DNA_workspace_types.h" #include "BLI_math.h" #include "BLI_listbase.h" @@ -52,12 +53,14 @@ #include "BKE_context.h" #include "BKE_group.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_particle.h" #include "BKE_property.h" #include "BKE_report.h" #include "BKE_scene.h" +#include "BKE_workspace.h" #include "BKE_library.h" #include "BKE_deform.h" @@ -86,37 +89,48 @@ /* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! (or * or a NC_SCENE|ND_OB_VISIBLE in case of visibility toggling */ -void ED_base_object_select(Base *base, short mode) +void ED_object_base_select(Base *base, eObjectSelect_Mode mode) { + if (mode == BA_INVERT) { + mode = (base->flag & BASE_SELECTED) != 0 ? BA_DESELECT : BA_SELECT; + } + if (base) { - if (mode == BA_SELECT) { - if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) - base->flag |= SELECT; - } - else if (mode == BA_DESELECT) { - base->flag &= ~SELECT; + switch (mode) { + case BA_SELECT: + if ((base->flag & BASE_SELECTABLED) != 0) { + base->flag |= BASE_SELECTED; + } + break; + case BA_DESELECT: + base->flag &= ~BASE_SELECTED; + break; + case BA_INVERT: + /* Never happens. */ + break; } - base->object->flag = base->flag; + BKE_scene_object_base_flag_sync_from_base(base); } } -/* also to set active NULL */ -void ED_base_object_activate(bContext *C, Base *base) +/** + * Change active base, it includes the notifier + */ +void ED_object_base_activate(bContext *C, Base *base) { - Scene *scene = CTX_data_scene(C); - - /* sets scene->basact */ - BASACT = base; - + SceneLayer *scene_layer = CTX_data_scene_layer(C); + scene_layer->basact = base; + if (base) { - - /* XXX old signals, remember to handle notifiers now! */ - // select_actionchannel_by_name(base->object->action, "Object", 1); - - WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); +#ifdef USE_WORKSPACE_MODE + WorkSpace *workspace = CTX_wm_workspace(C); + BKE_workspace_object_mode_set(workspace, base->object->mode); +#endif + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene_layer); } - else + else { WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL); + } } /********************** Selection Operators **********************/ @@ -147,7 +161,7 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) if (extend == 0) { CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); } CTX_DATA_END; } @@ -155,7 +169,7 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { if (base->object->type == obtype) { - ED_base_object_select(base, BA_SELECT); + ED_object_base_select(base, BA_SELECT); } } CTX_DATA_END; @@ -210,38 +224,15 @@ static const EnumPropertyItem prop_select_linked_types[] = { {0, NULL, 0, NULL, NULL} }; -// XXX old animation system -#if 0 -static int object_select_all_by_ipo(bContext *C, Ipo *ipo) -{ - bool changed = false; - - CTX_DATA_BEGIN (C, Base *, base, visible_bases) - { - if (base->object->ipo == ipo) { - base->flag |= SELECT; - base->object->flag = base->flag; - - changed = true; - } - } - CTX_DATA_END; - - return changed; -} -#endif - static bool object_select_all_by_obdata(bContext *C, void *obdata) { bool changed = false; CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if ((base->flag & SELECT) == 0) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { if (base->object->data == obdata) { - base->flag |= SELECT; - base->object->flag = base->flag; - + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -257,7 +248,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture, CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if ((base->flag & SELECT) == 0) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { Object *ob = base->object; Material *mat1; int a, b; @@ -267,7 +258,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture, if (!use_texture) { if (mat1 == mat) { - base->flag |= SELECT; + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -275,7 +266,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture, for (b = 0; b < MAX_MTEX; b++) { if (mat1->mtex[b]) { if (tex == mat1->mtex[b]->tex) { - base->flag |= SELECT; + ED_object_base_select(base, BA_SELECT); changed = true; break; } @@ -283,8 +274,6 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture, } } } - - base->object->flag = base->flag; } } CTX_DATA_END; @@ -299,12 +288,10 @@ static bool object_select_all_by_dup_group(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if ((base->flag & SELECT) == 0) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { Group *dup_group_other = (base->object->transflag & OB_DUPLIGROUP) ? base->object->dup_group : NULL; if (dup_group == dup_group_other) { - base->flag |= SELECT; - base->object->flag = base->flag; - + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -321,23 +308,21 @@ static bool object_select_all_by_particle(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if ((base->flag & SELECT) == 0) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { /* loop through other particles*/ ParticleSystem *psys; for (psys = base->object->particlesystem.first; psys; psys = psys->next) { if (psys->part == psys_act->part) { - base->flag |= SELECT; + ED_object_base_select(base, BA_SELECT); changed = true; break; } - if (base->flag & SELECT) { + if (base->flag & BASE_SELECTED) { break; } } - - base->object->flag = base->flag; } } CTX_DATA_END; @@ -351,11 +336,9 @@ static bool object_select_all_by_library(bContext *C, Library *lib) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if ((base->flag & SELECT) == 0) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { if (lib == base->object->id.lib) { - base->flag |= SELECT; - base->object->flag = base->flag; - + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -371,11 +354,9 @@ static bool object_select_all_by_library_obdata(bContext *C, Library *lib) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if ((base->flag & SELECT) == 0) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { if (base->object->data && lib == ((ID *)base->object->data)->lib) { - base->flag |= SELECT; - base->object->flag = base->flag; - + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -408,6 +389,7 @@ void ED_object_select_linked_by_id(bContext *C, ID *id) static int object_select_linked_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob; int nr = RNA_enum_get(op->ptr, "type"); bool changed = false, extend; @@ -417,12 +399,12 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) if (extend == 0) { CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); } CTX_DATA_END; } - ob = OBACT; + ob = OBACT(sl); if (ob == NULL) { BKE_report(op->reports, RPT_ERROR, "No active object"); return OPERATOR_CANCELLED; @@ -517,7 +499,7 @@ enum { OBJECT_GRPSEL_PARENT = 2, OBJECT_GRPSEL_SIBLINGS = 3, OBJECT_GRPSEL_TYPE = 4, - OBJECT_GRPSEL_LAYER = 5, + /*OBJECT_GRPSEL_LAYER = 5,*/ OBJECT_GRPSEL_GROUP = 6, OBJECT_GRPSEL_HOOK = 7, OBJECT_GRPSEL_PASS = 8, @@ -533,7 +515,6 @@ static const EnumPropertyItem prop_select_grouped_types[] = { {OBJECT_GRPSEL_PARENT, "PARENT", 0, "Parent", ""}, {OBJECT_GRPSEL_SIBLINGS, "SIBLINGS", 0, "Siblings", "Shared Parent"}, {OBJECT_GRPSEL_TYPE, "TYPE", 0, "Type", "Shared object type"}, - {OBJECT_GRPSEL_LAYER, "LAYER", 0, "Layer", "Shared layers"}, {OBJECT_GRPSEL_GROUP, "GROUP", 0, "Group", "Shared group"}, {OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""}, {OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"}, @@ -551,13 +532,14 @@ static bool select_grouped_children(bContext *C, Object *ob, const bool recursiv CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { if (ob == base->object->parent) { - if (!(base->flag & SELECT)) { - ED_base_object_select(base, BA_SELECT); + if ((base->flag & BASE_SELECTED) == 0) { + ED_object_base_select(base, BA_SELECT); changed = true; } - if (recursive) + if (recursive) { changed |= select_grouped_children(C, base->object, 1); + } } } CTX_DATA_END; @@ -566,20 +548,20 @@ static bool select_grouped_children(bContext *C, Object *ob, const bool recursiv static bool select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */ { - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - - bool changed = false; + SceneLayer *sl = CTX_data_scene_layer(C); Base *baspar, *basact = CTX_data_active_base(C); + bool changed = false; - if (!basact || !(basact->object->parent)) return 0; /* we know OBACT is valid */ + if (!basact || !(basact->object->parent)) { + return 0; /* we know OBACT is valid */ + } - baspar = BKE_scene_base_find(scene, basact->object->parent); + baspar = BKE_scene_layer_base_find(sl, basact->object->parent); /* can be NULL if parent in other scene */ - if (baspar && BASE_SELECTABLE(v3d, baspar)) { - ED_base_object_select(baspar, BA_SELECT); - ED_base_object_activate(C, baspar); + if (baspar && BASE_SELECTABLE(baspar)) { + ED_object_base_select(baspar, BA_SELECT); + ED_object_base_activate(C, baspar); changed = true; } return changed; @@ -608,9 +590,11 @@ static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in group = ob_groups[0]; CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) { - ED_base_object_select(base, BA_SELECT); - changed = true; + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (BKE_group_object_exists(group, base->object)) { + ED_object_base_select(base, BA_SELECT); + changed = true; + } } } CTX_DATA_END; @@ -632,8 +616,7 @@ static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in static bool select_grouped_object_hooks(bContext *C, Object *ob) { - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); + SceneLayer *sl = CTX_data_scene_layer(C); bool changed = false; Base *base; @@ -644,9 +627,9 @@ static bool select_grouped_object_hooks(bContext *C, Object *ob) if (md->type == eModifierType_Hook) { hmd = (HookModifierData *) md; if (hmd->object && !(hmd->object->flag & SELECT)) { - base = BKE_scene_base_find(scene, hmd->object); - if (base && (BASE_SELECTABLE(v3d, base))) { - ED_base_object_select(base, BA_SELECT); + base = BKE_scene_layer_base_find(sl, hmd->object); + if (base && (BASE_SELECTABLE(base))) { + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -663,8 +646,8 @@ static bool select_grouped_siblings(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if ((base->object->parent == ob->parent) && !(base->flag & SELECT)) { - ED_base_object_select(base, BA_SELECT); + if ((base->object->parent == ob->parent) && ((base->flag & BASE_SELECTED) == 0)) { + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -681,8 +664,8 @@ static bool select_grouped_lamptype(bContext *C, Object *ob) { if (base->object->type == OB_LAMP) { Lamp *la_test = base->object->data; - if ((la->type == la_test->type) && !(base->flag & SELECT)) { - ED_base_object_select(base, BA_SELECT); + if ((la->type == la_test->type) && ((base->flag & BASE_SELECTED) == 0)) { + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -696,23 +679,8 @@ static bool select_grouped_type(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if ((base->object->type == ob->type) && !(base->flag & SELECT)) { - ED_base_object_select(base, BA_SELECT); - changed = true; - } - } - CTX_DATA_END; - return changed; -} - -static bool select_grouped_layer(bContext *C, Object *ob) -{ - bool changed = false; - - CTX_DATA_BEGIN (C, Base *, base, selectable_bases) - { - if ((base->lay & ob->lay) && !(base->flag & SELECT)) { - ED_base_object_select(base, BA_SELECT); + if ((base->object->type == ob->type) && ((base->flag & BASE_SELECTED) == 0)) { + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -726,8 +694,8 @@ static bool select_grouped_index_object(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if ((base->object->index == ob->index) && !(base->flag & SELECT)) { - ED_base_object_select(base, BA_SELECT); + if ((base->object->index == ob->index) && ((base->flag & BASE_SELECTED) == 0)) { + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -741,8 +709,8 @@ static bool select_grouped_color(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if (!(base->flag & SELECT) && (compare_v3v3(base->object->col, ob->col, 0.005f))) { - ED_base_object_select(base, BA_SELECT); + if (((base->flag & BASE_SELECTED) == 0) && (compare_v3v3(base->object->col, ob->col, 0.005f))) { + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -768,8 +736,8 @@ static bool select_grouped_gameprops(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if (!(base->flag & SELECT) && (objects_share_gameprop(base->object, ob))) { - ED_base_object_select(base, BA_SELECT); + if (((base->flag & BASE_SELECTED) == 0) && (objects_share_gameprop(base->object, ob))) { + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -807,7 +775,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { /* only check for this object if it isn't selected already, to limit time wasted */ - if ((base->flag & SELECT) == 0) { + if ((base->flag & BASE_SELECTED) == 0) { KS_Path *ksp; /* this is the slow way... we could end up with > 500 items here, @@ -816,7 +784,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList for (ksp = ks->paths.first; ksp; ksp = ksp->next) { /* if id matches, select then stop looping (match found) */ if (ksp->id == (ID *)base->object) { - ED_base_object_select(base, BA_SELECT); + ED_object_base_select(base, BA_SELECT); changed = true; break; } @@ -831,6 +799,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList static int object_select_grouped_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob; const int type = RNA_enum_get(op->ptr, "type"); bool changed = false, extend; @@ -840,13 +809,13 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) if (extend == 0) { CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); changed = true; } CTX_DATA_END; } - ob = OBACT; + ob = OBACT(sl); if (ob == NULL) { BKE_report(op->reports, RPT_ERROR, "No active object"); return OPERATOR_CANCELLED; @@ -868,9 +837,6 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) case OBJECT_GRPSEL_TYPE: changed |= select_grouped_type(C, ob); break; - case OBJECT_GRPSEL_LAYER: - changed |= select_grouped_layer(C, ob); - break; case OBJECT_GRPSEL_GROUP: changed |= select_grouped_group(C, ob); break; @@ -928,85 +894,6 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", ""); } -/************************* Select by Layer **********************/ -enum { - OB_SEL_LAYERMATCH_EXACT = 1, - OB_SEL_LAYERMATCH_SHARED = 2, -}; - -static int object_select_by_layer_exec(bContext *C, wmOperator *op) -{ - unsigned int layernum; - bool extend; - int match; - - extend = RNA_boolean_get(op->ptr, "extend"); - layernum = RNA_int_get(op->ptr, "layers"); - match = RNA_enum_get(op->ptr, "match"); - - if (extend == false) { - CTX_DATA_BEGIN (C, Base *, base, visible_bases) - { - ED_base_object_select(base, BA_DESELECT); - } - CTX_DATA_END; - } - - CTX_DATA_BEGIN (C, Base *, base, visible_bases) - { - bool ok = false; - - switch (match) { - case OB_SEL_LAYERMATCH_EXACT: - /* Mask out bits used for local view, only work on real layer ones, see T45783. */ - ok = ((base->lay & ((1 << 20) - 1)) == (1 << (layernum - 1))); - break; - case OB_SEL_LAYERMATCH_SHARED: - ok = (base->lay & (1 << (layernum - 1))) != 0; - break; - default: - break; - } - - if (ok) { - ED_base_object_select(base, BA_SELECT); - } - } - CTX_DATA_END; - - /* undo? */ - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); - - return OPERATOR_FINISHED; -} - -void OBJECT_OT_select_by_layer(wmOperatorType *ot) -{ - static const EnumPropertyItem match_items[] = { - {OB_SEL_LAYERMATCH_EXACT, "EXACT", 0, "Exact Match", ""}, - {OB_SEL_LAYERMATCH_SHARED, "SHARED", 0, "Shared Layers", ""}, - {0, NULL, 0, NULL, NULL} - }; - - /* identifiers */ - ot->name = "Select by Layer"; - ot->description = "Select all visible objects on a layer"; - ot->idname = "OBJECT_OT_select_by_layer"; - - /* api callbacks */ - /*ot->invoke = XXX - need a int grid popup*/ - ot->exec = object_select_by_layer_exec; - ot->poll = objects_selectable_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_enum(ot->srna, "match", match_items, OB_SEL_LAYERMATCH_EXACT, "Match", ""); - RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first"); - RNA_def_int(ot->srna, "layers", 1, 1, 20, "Layer", "", 1, 20); -} - /**************************** (De)select All ****************************/ static int object_select_all_exec(bContext *C, wmOperator *op) @@ -1020,7 +907,7 @@ static int object_select_all_exec(bContext *C, wmOperator *op) action = SEL_SELECT; CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (base->flag & SELECT) { + if ((base->flag & BASE_SELECTED) != 0) { action = SEL_DESELECT; break; } @@ -1032,17 +919,17 @@ static int object_select_all_exec(bContext *C, wmOperator *op) { switch (action) { case SEL_SELECT: - ED_base_object_select(base, BA_SELECT); + ED_object_base_select(base, BA_SELECT); break; case SEL_DESELECT: - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); break; case SEL_INVERT: - if (base->flag & SELECT) { - ED_base_object_select(base, BA_DESELECT); + if ((base->flag & BASE_SELECTED) != 0) { + ED_object_base_select(base, BA_DESELECT); } else { - ED_base_object_select(base, BA_SELECT); + ED_object_base_select(base, BA_SELECT); } break; } @@ -1092,8 +979,11 @@ static int object_select_same_group_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) - ED_base_object_select(base, BA_SELECT); + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (BKE_group_object_exists(group, base->object)) { + ED_object_base_select(base, BA_SELECT); + } + } } CTX_DATA_END; @@ -1124,6 +1014,7 @@ void OBJECT_OT_select_same_group(wmOperatorType *ot) static int object_select_mirror_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); bool extend; extend = RNA_boolean_get(op->ptr, "extend"); @@ -1137,15 +1028,15 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op) if (!STREQ(name_flip, primbase->object->id.name + 2)) { Object *ob = (Object *)BKE_libblock_find_name(ID_OB, name_flip); if (ob) { - Base *secbase = BKE_scene_base_find(scene, ob); + Base *secbase = BKE_scene_layer_base_find(sl, ob); if (secbase) { - ED_base_object_select(secbase, BA_SELECT); + ED_object_base_select(secbase, BA_SELECT); } } } - if (extend == false) ED_base_object_select(primbase, BA_DESELECT); + if (extend == false) ED_object_base_select(primbase, BA_DESELECT); } CTX_DATA_END; @@ -1180,9 +1071,9 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot) static bool object_select_more_less(bContext *C, const bool select) { - Scene *scene = CTX_data_scene(C); + SceneLayer *scene_layer = CTX_data_scene_layer(C); - for (Base *base = scene->base.first; base; base = base->next) { + for (Base *base = scene_layer->object_bases.first; base; base = base->next) { Object *ob = base->object; ob->flag &= ~OB_DONE; ob->id.tag &= ~LIB_TAG_DOIT; @@ -1223,7 +1114,7 @@ static bool object_select_more_less(bContext *C, const bool select) Base *base = ctx_base->ptr.data; Object *ob = base->object; if ((ob->id.tag & LIB_TAG_DOIT) && ((ob->flag & SELECT) != select_flag)) { - ED_base_object_select(base, select_mode); + ED_object_base_select(base, select_mode); changed = true; } } @@ -1305,7 +1196,7 @@ static int object_select_random_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { if (BLI_rng_get_float(rng) < randfac) { - ED_base_object_select(base, select); + ED_object_base_select(base, select); } } CTX_DATA_END; diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 27da607c696..1f80cb5f0bc 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -51,7 +51,6 @@ #include "DNA_object_types.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_key.h" #include "BKE_library.h" #include "BKE_main.h" @@ -59,6 +58,9 @@ #include "BKE_lattice.h" #include "BKE_curve.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "BLI_sys_types.h" // for intptr_t support #include "ED_object.h" @@ -213,7 +215,7 @@ static bool object_shape_key_mirror(bContext *C, Object *ob, *r_totmirr = totmirr; *r_totfail = totfail; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return 1; @@ -264,8 +266,8 @@ static int shape_key_add_exec(bContext *C, wmOperator *op) ED_object_shape_key_add(C, ob, from_mix); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - DAG_relations_tag_update(CTX_data_main(C)); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_relations_tag_update(CTX_data_main(C)); return OPERATOR_FINISHED; } @@ -302,8 +304,8 @@ static int shape_key_remove_exec(bContext *C, wmOperator *op) } if (changed) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - DAG_relations_tag_update(CTX_data_main(C)); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; @@ -343,7 +345,7 @@ static int shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) for (kb = key->block.first; kb; kb = kb->next) kb->curval = 0.0f; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; @@ -378,7 +380,7 @@ static int shape_key_retime_exec(bContext *C, wmOperator *UNUSED(op)) for (kb = key->block.first; kb; kb = kb->next) kb->pos = (cfra += 0.1f); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; @@ -469,7 +471,7 @@ static int shape_key_move_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 9fea7bf5b89..100b9018d00 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -39,14 +39,15 @@ #include "DNA_scene_types.h" #include "DNA_group_types.h" #include "DNA_lattice_types.h" +#include "DNA_lamp_types.h" #include "BLI_math.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" +#include "BLI_array.h" #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_idcode.h" #include "BKE_mball.h" @@ -59,6 +60,8 @@ #include "BKE_lattice.h" #include "BKE_tracking.h" +#include "DEG_depsgraph.h" + #include "RNA_define.h" #include "RNA_access.h" @@ -71,6 +74,8 @@ #include "ED_screen.h" #include "ED_view3d.h" +#include "MEM_guardedalloc.h" + #include "object_intern.h" /*************************** Clear Transformation ****************************/ @@ -265,7 +270,7 @@ static int object_clear_transform_generic_exec(bContext *C, wmOperator *op, ED_autokeyframe_object(C, scene, ob, ks); /* tag for updates */ - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } } CTX_DATA_END; @@ -371,7 +376,7 @@ static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op)) mul_m3_v3(mat, v3); } - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } CTX_DATA_END; @@ -399,16 +404,19 @@ void OBJECT_OT_origin_clear(wmOperatorType *ot) /* use this when the loc/size/rot of the parent has changed but the children * should stay in the same place, e.g. for apply-size-rot or object center */ -static void ignore_parent_tx(Main *bmain, Scene *scene, Object *ob) +static void ignore_parent_tx(const bContext *C, Main *bmain, Scene *scene, Object *ob) { Object workob; Object *ob_child; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); /* a change was made, adjust the children to compensate */ for (ob_child = bmain->object.first; ob_child; ob_child = ob_child->id.next) { if (ob_child->parent == ob) { BKE_object_apply_mat4(ob_child, ob_child->obmat, true, false); - BKE_object_workob_calc_parent(scene, ob_child, &workob); + BKE_object_workob_calc_parent(&eval_ctx, scene, ob_child, &workob); invert_m4_m4(ob_child->parentinv, workob.obmat); } } @@ -421,8 +429,11 @@ static int apply_objects_internal( { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + EvaluationContext eval_ctx; float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale; bool changed = true; + + CTX_data_eval_ctx(C, &eval_ctx); /* first check if we can execute */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) @@ -525,7 +536,7 @@ static int apply_objects_internal( Mesh *me = ob->data; if (apply_scale) - multiresModifier_scale_disp(scene, ob); + multiresModifier_scale_disp(&eval_ctx, scene, ob); /* adjust data */ BKE_mesh_transform(me, mat, true); @@ -615,14 +626,14 @@ static int apply_objects_internal( unit_axis_angle(ob->rotAxis, &ob->rotAngle); } - BKE_object_where_is_calc(scene, ob); + BKE_object_where_is_calc(&eval_ctx, scene, ob); if (ob->type == OB_ARMATURE) { - BKE_pose_where_is(scene, ob); /* needed for bone parents */ + BKE_pose_where_is(&eval_ctx, scene, ob); /* needed for bone parents */ } - ignore_parent_tx(bmain, scene, ob); + ignore_parent_tx(C, bmain, scene, ob); - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); changed = true; } @@ -640,16 +651,19 @@ static int apply_objects_internal( static int visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); + EvaluationContext eval_ctx; bool changed = false; + CTX_data_eval_ctx(C, &eval_ctx); + CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { - BKE_object_where_is_calc(scene, ob); + BKE_object_where_is_calc(&eval_ctx, scene, ob); BKE_object_apply_mat4(ob, ob->obmat, true, true); - BKE_object_where_is_calc(scene, ob); + BKE_object_where_is_calc(&eval_ctx, scene, ob); /* update for any children that may get moved */ - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); changed = true; } @@ -730,6 +744,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *obact = CTX_data_active_object(C); Object *obedit = CTX_data_edit_object(C); + EvaluationContext eval_ctx; Object *tob; float cursor[3], cent[3], cent_neg[3], centn[3]; int centermode = RNA_enum_get(op->ptr, "type"); @@ -739,6 +754,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) CollectionPointerLink *ctx_ob; CollectionPointerLink *ctx_ob_act = NULL; + CTX_data_eval_ctx(C, &eval_ctx); + /* keep track of what is changed */ int tot_change = 0, tot_lib_error = 0, tot_multiuser_arm_error = 0; @@ -793,7 +810,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) EDBM_mesh_normals_update(em); tot_change++; - DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + DEG_id_tag_update(&obedit->id, OB_RECALC_DATA); } } @@ -918,7 +935,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (obedit) { if (centermode == GEOMETRY_TO_ORIGIN) { - DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + DEG_id_tag_update(&obedit->id, OB_RECALC_DATA); } break; } @@ -971,10 +988,10 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) arm->id.tag |= LIB_TAG_DOIT; /* do_inverse_offset = true; */ /* docenter_armature() handles this */ - BKE_object_where_is_calc(scene, ob); - BKE_pose_where_is(scene, ob); /* needed for bone parents */ + BKE_object_where_is_calc(&eval_ctx, scene, ob); + BKE_pose_where_is(&eval_ctx, scene, ob); /* needed for bone parents */ - ignore_parent_tx(bmain, scene, ob); + ignore_parent_tx(C, bmain, scene, ob); if (obedit) break; @@ -996,7 +1013,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (obedit) { if (centermode == GEOMETRY_TO_ORIGIN) { - DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + DEG_id_tag_update(&obedit->id, OB_RECALC_DATA); } break; } @@ -1030,12 +1047,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) add_v3_v3(ob->loc, centn); - BKE_object_where_is_calc(scene, ob); + BKE_object_where_is_calc(&eval_ctx, scene, ob); if (ob->type == OB_ARMATURE) { - BKE_pose_where_is(scene, ob); /* needed for bone parents */ + BKE_pose_where_is(&eval_ctx, scene, ob); /* needed for bone parents */ } - ignore_parent_tx(bmain, scene, ob); + ignore_parent_tx(C, bmain, scene, ob); /* other users? */ //CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects) @@ -1054,16 +1071,16 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) (ob->transflag | ob_other->transflag) & OB_DUPLIGROUP))) { ob_other->flag |= OB_DONE; - DAG_id_tag_update(&ob_other->id, OB_RECALC_OB | OB_RECALC_DATA); + DEG_id_tag_update(&ob_other->id, OB_RECALC_OB | OB_RECALC_DATA); mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */ add_v3_v3(ob_other->loc, centn); - BKE_object_where_is_calc(scene, ob_other); + BKE_object_where_is_calc(&eval_ctx, scene, ob_other); if (ob_other->type == OB_ARMATURE) { - BKE_pose_where_is(scene, ob_other); /* needed for bone parents */ + BKE_pose_where_is(&eval_ctx, scene, ob_other); /* needed for bone parents */ } - ignore_parent_tx(bmain, scene, ob_other); + ignore_parent_tx(C, bmain, scene, ob_other); } } //CTX_DATA_END; @@ -1072,9 +1089,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) } BLI_freelistN(&ctx_data_list); - for (tob = bmain->object.first; tob; tob = tob->id.next) - if (tob->data && (((ID *)tob->data)->tag & LIB_TAG_DOIT)) - DAG_id_tag_update(&tob->id, OB_RECALC_OB | OB_RECALC_DATA); + for (tob = bmain->object.first; tob; tob = tob->id.next) { + if (tob->data && (((ID *)tob->data)->tag & LIB_TAG_DOIT)) { + BKE_mesh_batch_cache_dirty(tob->data, BKE_MESH_BATCH_DIRTY_ALL); + DEG_id_tag_update(&tob->id, OB_RECALC_OB | OB_RECALC_DATA); + } + } if (tot_change) { WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); @@ -1131,3 +1151,389 @@ void OBJECT_OT_origin_set(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", ""); RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_AROUND_CENTER_MEAN, "Center", ""); } + +/* -------------------------------------------------------------------- */ + +/** \name Transform Axis Target + * + * Note this is an experemental operator to point lamps/cameras at objects. + * We may re-work how this behaves based on user feedback. + * - campbell. + * \{ */ + +/* When using multiple objects, apply their relative rotational offset to the active object. */ +#define USE_RELATIVE_ROTATION + +struct XFormAxisItem { + Object *ob; + float rot_mat[3][3]; + void *obtfm; + float xform_dist; + +#ifdef USE_RELATIVE_ROTATION + /* use when translating multiple */ + float xform_rot_offset[3][3]; +#endif +}; + +struct XFormAxisData { + ViewContext vc; + struct { + float depth; + float normal[3]; + bool is_depth_valid; + bool is_normal_valid; + } prev; + + struct XFormAxisItem *object_data; + uint object_data_len; + bool is_translate; + + int init_event; +}; + +static bool object_is_target_compat(const Object *ob) +{ + if (ob->type == OB_LAMP) { + const Lamp *la = ob->data; + if (ELEM(la->type, LA_SUN, LA_SPOT, LA_HEMI, LA_AREA)) { + return true; + } + } + /* We might want to enable this later, for now just lamps */ +#if 0 + else if (ob->type == OB_CAMERA) { + return true; + } +#endif + return false; +} + +static void object_transform_axis_target_free_data(wmOperator *op) +{ + struct XFormAxisData *xfd = op->customdata; + struct XFormAxisItem *item = xfd->object_data; + for (int i = 0; i < xfd->object_data_len; i++, item++) { + MEM_freeN(item->obtfm); + } + MEM_freeN(xfd->object_data); + MEM_freeN(xfd); + op->customdata = NULL; +} + +/* We may want to expose as alternative to: BKE_object_apply_rotation */ +static void object_apply_rotation(Object *ob, const float rmat[3][3]) +{ + float size[3]; + float loc[3]; + float rmat4[4][4]; + copy_m4_m3(rmat4, rmat); + + copy_v3_v3(size, ob->size); + copy_v3_v3(loc, ob->loc); + BKE_object_apply_mat4(ob, rmat4, true, true); + copy_v3_v3(ob->size, size); + copy_v3_v3(ob->loc, loc); +} +/* We may want to extract this to: BKE_object_apply_location */ +static void object_apply_location(Object *ob, const float loc[3]) +{ + /* quick but weak */ + Object ob_prev = *ob; + float mat[4][4]; + copy_m4_m4(mat, ob->obmat); + copy_v3_v3(mat[3], loc); + BKE_object_apply_mat4(ob, mat, true, true); + copy_v3_v3(mat[3], ob->loc); + *ob = ob_prev; + copy_v3_v3(ob->loc, mat[3]); +} + +static void object_orient_to_location( + Object *ob, float rot_orig[3][3], const float axis[3], const float location[3]) +{ + float delta[3]; + sub_v3_v3v3(delta, ob->obmat[3], location); + if (normalize_v3(delta) != 0.0f) { + if (len_squared_v3v3(delta, axis) > FLT_EPSILON) { + float delta_rot[3][3]; + float final_rot[3][3]; + rotation_between_vecs_to_mat3(delta_rot, axis, delta); + + mul_m3_m3m3(final_rot, delta_rot, rot_orig); + + object_apply_rotation(ob, final_rot); + + DEG_id_tag_update(&ob->id, OB_RECALC_OB); + } + } +} + +static void object_transform_axis_target_cancel(bContext *C, wmOperator *op) +{ + struct XFormAxisData *xfd = op->customdata; + struct XFormAxisItem *item = xfd->object_data; + for (int i = 0; i < xfd->object_data_len; i++, item++) { + BKE_object_tfm_restore(item->ob, item->obtfm); + DEG_id_tag_update(&item->ob->id, OB_RECALC_OB); + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob); + } + + object_transform_axis_target_free_data(op); +} + +static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + ViewContext vc; + view3d_set_viewcontext(C, &vc); + + if (!object_is_target_compat(vc.obact)) { + /* Falls back to texture space transform. */ + return OPERATOR_PASS_THROUGH; + } + + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); + + ED_view3d_autodist_init(&eval_ctx, vc.depsgraph, vc.ar, vc.v3d, 0); + + if (vc.rv3d->depths != NULL) { + vc.rv3d->depths->damaged = true; + } + ED_view3d_depth_update(vc.ar); + + if (vc.rv3d->depths == NULL) { + BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane"); + return OPERATOR_CANCELLED; + } + + ED_region_tag_redraw(vc.ar); + + struct XFormAxisData *xfd; + xfd = op->customdata = MEM_callocN(sizeof(struct XFormAxisData), __func__); + + /* Don't change this at runtime. */ + xfd->vc = vc; + xfd->vc.mval[0] = event->mval[0]; + xfd->vc.mval[1] = event->mval[1]; + + xfd->prev.depth = 1.0f; + xfd->prev.is_depth_valid = false; + xfd->prev.is_normal_valid = false; + xfd->is_translate = false; + + xfd->init_event = WM_userdef_event_type_from_keymap_type(event->type); + + { + struct XFormAxisItem *object_data = NULL; + BLI_array_declare(object_data); + + struct XFormAxisItem *item = BLI_array_append_ret(object_data); + item->ob = xfd->vc.obact; + + CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) + { + if ((ob != xfd->vc.obact) && object_is_target_compat(ob)) { + item = BLI_array_append_ret(object_data); + item->ob = ob; + } + } + CTX_DATA_END; + + xfd->object_data = object_data; + xfd->object_data_len = BLI_array_count(object_data); + + if (xfd->object_data_len != BLI_array_count(object_data)) { + xfd->object_data = MEM_reallocN(xfd->object_data, xfd->object_data_len * sizeof(*xfd->object_data)); + } + } + + { + struct XFormAxisItem *item = xfd->object_data; + for (int i = 0; i < xfd->object_data_len; i++, item++) { + item->obtfm = BKE_object_tfm_backup(item->ob); + BKE_object_rot_to_mat3(item->ob, item->rot_mat, true); + } + } + + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; +} + +static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + struct XFormAxisData *xfd = op->customdata; + ARegion *ar = xfd->vc.ar; + + view3d_operator_needs_opengl(C); + + const bool is_translate = (event->ctrl != 0); + const bool is_translate_init = is_translate && (xfd->is_translate != is_translate); + + if (event->type == MOUSEMOVE || is_translate_init) { + const ViewDepths *depths = xfd->vc.rv3d->depths; + if (depths && + ((unsigned int)event->mval[0] < depths->w) && + ((unsigned int)event->mval[1] < depths->h)) + { + double depth = (double)ED_view3d_depth_read_cached(&xfd->vc, event->mval); + float location_world[3]; + if (depth == 1.0f) { + if (xfd->prev.is_depth_valid) { + depth = (double)xfd->prev.depth; + } + } + if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) { + xfd->prev.depth = depth; + xfd->prev.is_depth_valid = true; + if (ED_view3d_depth_unproject(ar, event->mval, depth, location_world)) { + if (is_translate) { + + float normal[3]; + bool normal_found = false; + if (ED_view3d_depth_read_cached_normal(&xfd->vc, event->mval, normal)) { + normal_found = true; + + /* cheap attempt to smooth normals out a bit! */ + const uint ofs = 2; + for (uint x = -ofs; x <= ofs; x += ofs / 2) { + for (uint y = -ofs; y <= ofs; y += ofs / 2) { + if (x != 0 && y != 0) { + int mval_ofs[2] = {event->mval[0] + x, event->mval[1] + y}; + float n[3]; + if (ED_view3d_depth_read_cached_normal( + &xfd->vc, mval_ofs, n)) + { + add_v3_v3(normal, n); + } + } + } + } + normalize_v3(normal); + } + else if (xfd->prev.is_normal_valid) { + copy_v3_v3(normal, xfd->prev.normal); + normal_found = true; + } + + if (normal_found) { +#ifdef USE_RELATIVE_ROTATION + if (is_translate_init && xfd->object_data_len > 1) { + float xform_rot_offset_inv_first[3][3]; + struct XFormAxisItem *item = xfd->object_data; + for (int i = 0; i < xfd->object_data_len; i++, item++) { + copy_m3_m4(item->xform_rot_offset, item->ob->obmat); + normalize_m3(item->xform_rot_offset); + + if (i == 0) { + invert_m3_m3(xform_rot_offset_inv_first, xfd->object_data[0].xform_rot_offset); + } + else { + mul_m3_m3m3(item->xform_rot_offset, + item->xform_rot_offset, + xform_rot_offset_inv_first); + } + } + } + +#endif + + struct XFormAxisItem *item = xfd->object_data; + for (int i = 0; i < xfd->object_data_len; i++, item++) { + if (is_translate_init) { + float ob_axis[3]; + item->xform_dist = len_v3v3(item->ob->obmat[3], location_world); + normalize_v3_v3(ob_axis, item->ob->obmat[2]); + /* Scale to avoid adding distance when moving between surfaces. */ + float scale = fabsf(dot_v3v3(ob_axis, normal)); + item->xform_dist *= scale; + } + + float target_normal[3]; + copy_v3_v3(target_normal, normal); + +#ifdef USE_RELATIVE_ROTATION + if (i != 0) { + mul_m3_v3(item->xform_rot_offset, target_normal); + } +#endif + { + float loc[3]; + + copy_v3_v3(loc, location_world); + madd_v3_v3fl(loc, target_normal, item->xform_dist); + object_apply_location(item->ob, loc); + copy_v3_v3(item->ob->obmat[3], loc); /* so orient behaves as expected */ + } + + object_orient_to_location(item->ob, item->rot_mat, item->rot_mat[2], location_world); + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob); + } + copy_v3_v3(xfd->prev.normal, normal); + xfd->prev.is_normal_valid = true; + } + } + else { + struct XFormAxisItem *item = xfd->object_data; + for (int i = 0; i < xfd->object_data_len; i++, item++) { + object_orient_to_location(item->ob, item->rot_mat, item->rot_mat[2], location_world); + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob); + } + xfd->prev.is_normal_valid = false; + } + } + } + } + xfd->is_translate = is_translate; + + ED_region_tag_redraw(xfd->vc.ar); + } + + bool is_finished = false; + + if (ISMOUSE(xfd->init_event)) { + if ((event->type == xfd->init_event) && (event->val == KM_RELEASE)) { + is_finished = true; + } + } + else { + if (ELEM(event->type, LEFTMOUSE, RETKEY, PADENTER)) { + is_finished = true; + } + } + + if (is_finished) { + object_transform_axis_target_free_data(op); + return OPERATOR_FINISHED; + } + else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) { + object_transform_axis_target_cancel(C, op); + return OPERATOR_CANCELLED; + } + + + return OPERATOR_RUNNING_MODAL; +} + +void OBJECT_OT_transform_axis_target(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Interactive Lamp Track to Cursor"; + ot->description = "Interactively point cameras and lamps to a location (Ctrl translates)"; + ot->idname = "OBJECT_OT_transform_axis_target"; + + /* api callbacks */ + ot->invoke = object_transform_axis_target_invoke; + ot->cancel = object_transform_axis_target_cancel; + ot->modal = object_transform_axis_target_modal; + ot->poll = ED_operator_region_view3d_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; +} + +#undef USE_RELATIVE_ROTATION + +/** \} */ diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 9afc3772f90..bf2da284591 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -56,9 +56,9 @@ #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_deform.h" -#include "BKE_depsgraph.h" #include "BKE_mesh_mapping.h" #include "BKE_editmesh.h" +#include "BKE_layer.h" #include "BKE_modifier.h" #include "BKE_report.h" #include "BKE_DerivedMesh.h" @@ -66,6 +66,8 @@ #include "BKE_object.h" #include "BKE_lattice.h" +#include "DEG_depsgraph.h" + #include "DNA_armature_types.h" #include "RNA_access.h" #include "RNA_define.h" @@ -1259,9 +1261,9 @@ static void dm_deform_clear(DerivedMesh *dm, Object *ob) } /* recalculate the deformation */ -static DerivedMesh *dm_deform_recalc(Scene *scene, Object *ob) +static DerivedMesh *dm_deform_recalc(EvaluationContext *eval_ctx, Scene *scene, Object *ob) { - return mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); + return mesh_get_derived_deform(eval_ctx, scene, ob, CD_MASK_BAREMESH); } /* by changing nonzero weights, try to move a vertex in me->mverts with index 'index' to @@ -1273,7 +1275,7 @@ static DerivedMesh *dm_deform_recalc(Scene *scene, Object *ob) * norm and d are the plane's properties for the equation: ax + by + cz + d = 0 * coord is a point on the plane */ -static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, int index, float norm[3], +static void moveCloserToDistanceFromPlane(EvaluationContext *eval_ctx, Scene *scene, Object *ob, Mesh *me, int index, float norm[3], float coord[3], float d, float distToBe, float strength, float cp) { DerivedMesh *dm; @@ -1300,7 +1302,7 @@ static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, in float originalDistToBe = distToBe; do { wasChange = false; - dm = dm_deform_recalc(scene, ob); + dm = dm_deform_recalc(eval_ctx, scene, ob); dm->getVert(dm, index, &m); copy_v3_v3(oldPos, m.co); distToStart = dot_v3v3(norm, oldPos) + d; @@ -1338,7 +1340,7 @@ static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, in if (dw->weight > 1) { dw->weight = 1; } - dm = dm_deform_recalc(scene, ob); + dm = dm_deform_recalc(eval_ctx, scene, ob); dm->getVert(dm, index, &m); getVerticalAndHorizontalChange(norm, d, coord, oldPos, distToStart, m.co, changes, dists, i); dw->weight = oldw; @@ -1448,10 +1450,13 @@ static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, in /* this is used to try to smooth a surface by only adjusting the nonzero weights of a vertex * but it could be used to raise or lower an existing 'bump.' */ -static void vgroup_fix(Scene *scene, Object *ob, float distToBe, float strength, float cp) +static void vgroup_fix(const bContext *C, Scene *scene, Object *ob, float distToBe, float strength, float cp) { + EvaluationContext eval_ctx; int i; + CTX_data_eval_ctx(C, &eval_ctx); + Mesh *me = ob->data; MVert *mvert = me->mvert; int *verts = NULL; @@ -1465,7 +1470,7 @@ static void vgroup_fix(Scene *scene, Object *ob, float distToBe, float strength, MVert *p = MEM_callocN(sizeof(MVert) * (count), "deformedPoints"); int k; - DerivedMesh *dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); + DerivedMesh *dm = mesh_get_derived_deform(&eval_ctx, scene, ob, CD_MASK_BAREMESH); k = count; while (k--) { dm->getVert(dm, verts[k], &m); @@ -1483,7 +1488,7 @@ static void vgroup_fix(Scene *scene, Object *ob, float distToBe, float strength, if (mag) { /* zeros fix */ d = -dot_v3v3(norm, coord); /* dist = (dot_v3v3(norm, m.co) + d); */ /* UNUSED */ - moveCloserToDistanceFromPlane(scene, ob, me, i, norm, coord, d, distToBe, strength, cp); + moveCloserToDistanceFromPlane(&eval_ctx, scene, ob, me, i, norm, coord, d, distToBe, strength, cp); } } @@ -2609,7 +2614,7 @@ static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = ED_object_context(C); BKE_object_defgroup_add(ob); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -2642,7 +2647,7 @@ static int vertex_group_remove_exec(bContext *C, wmOperator *op) else vgroup_delete_active(ob); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -2677,7 +2682,7 @@ static int vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = ED_object_context(C); vgroup_assign_verts(ob, ts->vgroup_weight); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); return OPERATOR_FINISHED; @@ -2750,7 +2755,7 @@ static int vertex_group_remove_from_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); return OPERATOR_FINISHED; @@ -2839,7 +2844,7 @@ static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = ED_object_context(C); vgroup_duplicate(ob); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data); @@ -2875,7 +2880,7 @@ static int vertex_group_levels_exec(bContext *C, wmOperator *op) vgroup_levels_subset(ob, vgroup_validmap, vgroup_tot, subset_count, offset, gain); MEM_freeN((void *)vgroup_validmap); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); @@ -2909,7 +2914,7 @@ static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op)) changed = vgroup_normalize(ob); if (changed) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); @@ -2948,7 +2953,7 @@ static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op) MEM_freeN((void *)vgroup_validmap); if (changed) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); @@ -3001,9 +3006,9 @@ static int vertex_group_fix_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR_INVALID_CONTEXT, "This operator does not support an active mirror modifier"); return OPERATOR_CANCELLED; } - vgroup_fix(scene, ob, distToBe, strength, cp); + vgroup_fix(C, scene, ob, distToBe, strength, cp); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); @@ -3075,7 +3080,7 @@ static int vertex_group_invert_exec(bContext *C, wmOperator *op) vgroup_invert_subset(ob, vgroup_validmap, vgroup_tot, subset_count, auto_assign, auto_remove); MEM_freeN((void *)vgroup_validmap); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); @@ -3117,7 +3122,7 @@ static int vertex_group_smooth_exec(bContext *C, wmOperator *op) vgroup_smooth_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac, repeat, fac_expand); MEM_freeN((void *)vgroup_validmap); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); @@ -3159,7 +3164,7 @@ static int vertex_group_clean_exec(bContext *C, wmOperator *op) vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single); MEM_freeN((void *)vgroup_validmap); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); @@ -3200,7 +3205,7 @@ static int vertex_group_quantize_exec(bContext *C, wmOperator *op) vgroup_quantize_subset(ob, vgroup_validmap, vgroup_tot, subset_count, steps); MEM_freeN((void *)vgroup_validmap); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); @@ -3241,7 +3246,7 @@ static int vertex_group_limit_total_exec(bContext *C, wmOperator *op) BKE_reportf(op->reports, remove_tot ? RPT_INFO : RPT_WARNING, "%d vertex weights limited", remove_tot); if (remove_tot) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); @@ -3286,7 +3291,7 @@ static int vertex_group_mirror_exec(bContext *C, wmOperator *op) ED_mesh_report_mirror(op, totmirr, totfail); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); @@ -3319,25 +3324,26 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot) static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - Object *ob = ED_object_context(C); - Base *base; + Object *ob_active = ED_object_context(C); int retval = OPERATOR_CANCELLED; - for (base = scene->base.first; base; base = base->next) { - if (base->object->type == ob->type) { - if (base->object != ob && base->object->data == ob->data) { - BLI_freelistN(&base->object->defbase); - BLI_duplicatelist(&base->object->defbase, &ob->defbase); - base->object->actdef = ob->actdef; + FOREACH_SCENE_OBJECT(scene, ob_iter) + { + if (ob_iter->type == ob_active->type) { + if (ob_iter != ob_active && ob_iter->data == ob_active->data) { + BLI_freelistN(&ob_iter->defbase); + BLI_duplicatelist(&ob_iter->defbase, &ob_active->defbase); + ob_iter->actdef = ob_active->actdef; - DAG_id_tag_update(&base->object->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, base->object); - WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, base->object->data); + DEG_id_tag_update(&ob_iter->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_iter->data); retval = OPERATOR_FINISHED; } } } + FOREACH_SCENE_OBJECT_END return retval; } @@ -3367,7 +3373,7 @@ static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op) { if (obact != ob) { if (ED_vgroup_array_copy(ob, obact)) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); changed_tot++; } @@ -3410,7 +3416,7 @@ static int set_active_group_exec(bContext *C, wmOperator *op) BLI_assert(nr + 1 >= 0); ob->actdef = nr + 1; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); return OPERATOR_FINISHED; @@ -3624,7 +3630,7 @@ static int vertex_group_sort_exec(bContext *C, wmOperator *op) ret = vgroup_do_remap(ob, name_array, op); if (ret != OPERATOR_CANCELLED) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); } @@ -3674,7 +3680,7 @@ static int vgroup_move_exec(bContext *C, wmOperator *op) ret = vgroup_do_remap(ob, name_array, op); if (ret != OPERATOR_CANCELLED) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); } } @@ -3803,7 +3809,7 @@ static int vertex_weight_paste_exec(bContext *C, wmOperator *op) vgroup_copy_active_to_sel_single(ob, def_nr); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; @@ -3840,7 +3846,7 @@ static int vertex_weight_delete_exec(bContext *C, wmOperator *op) vgroup_remove_weight(ob, def_nr); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; @@ -3873,7 +3879,7 @@ static int vertex_weight_set_active_exec(bContext *C, wmOperator *op) if (wg_index != -1) { ob->actdef = wg_index + 1; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); } @@ -3910,7 +3916,7 @@ static int vertex_weight_normalize_active_vertex_exec(bContext *C, wmOperator *U changed = vgroup_normalize_active_vertex(ob, subset_type); if (changed) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; @@ -3943,7 +3949,7 @@ static int vertex_weight_copy_exec(bContext *C, wmOperator *UNUSED(op)) vgroup_copy_active_to_sel(ob, subset_type); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt index 898422dac51..3cecdccd758 100644 --- a/source/blender/editors/physics/CMakeLists.txt +++ b/source/blender/editors/physics/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../gpu ../../makesdna ../../makesrna diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c index b0c14ef3623..c10604b0edd 100644 --- a/source/blender/editors/physics/dynamicpaint_ops.c +++ b/source/blender/editors/physics/dynamicpaint_ops.c @@ -42,7 +42,6 @@ #include "BKE_context.h" #include "BKE_deform.h" #include "BKE_object_deform.h" -#include "BKE_depsgraph.h" #include "BKE_dynamicpaint.h" #include "BKE_global.h" #include "BKE_main.h" @@ -50,6 +49,9 @@ #include "BKE_report.h" #include "BKE_screen.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "ED_mesh.h" #include "ED_screen.h" #include "ED_object.h" @@ -135,7 +137,7 @@ static int surface_slot_remove_exec(bContext *C, wmOperator *UNUSED(op)) } dynamicPaint_resetPreview(canvas); - DAG_id_tag_update(&obj_ctx->id, OB_RECALC_DATA); + DEG_id_tag_update(&obj_ctx->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obj_ctx); return OPERATOR_FINISHED; @@ -181,8 +183,8 @@ static int type_toggle_exec(bContext *C, wmOperator *op) } /* update dependency */ - DAG_id_tag_update(&cObject->id, OB_RECALC_DATA); - DAG_relations_tag_update(CTX_data_main(C)); + DEG_id_tag_update(&cObject->id, OB_RECALC_DATA); + DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, cObject); return OPERATOR_FINISHED; @@ -286,11 +288,15 @@ typedef struct DynamicPaintBakeJob { struct Main *bmain; Scene *scene; + SceneLayer *scene_layer; + Depsgraph *depsgraph; Object *ob; DynamicPaintSurface *surface; DynamicPaintCanvasSettings *canvas; + EvaluationContext *eval_ctx; + int success; double start; } DynamicPaintBakeJob; @@ -310,6 +316,8 @@ static void dpaint_bake_endjob(void *customdata) dynamicPaint_freeSurfaceData(job->surface); + MEM_freeN(job->eval_ctx); + G.is_rendering = false; BKE_spacedata_draw_locks(false); @@ -357,7 +365,7 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job) frame = surface->start_frame; orig_frame = scene->r.cfra; scene->r.cfra = (int)frame; - ED_update_for_newframe(job->bmain, scene, 1); + ED_update_for_newframe(job->bmain, scene, job->scene_layer, job->depsgraph); /* Init surface */ if (!dynamicPaint_createUVSurface(scene, surface, job->progress, job->do_update)) { @@ -383,8 +391,8 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job) /* calculate a frame */ scene->r.cfra = (int)frame; - ED_update_for_newframe(job->bmain, scene, 1); - if (!dynamicPaint_calculateFrame(surface, scene, cObject, frame)) { + ED_update_for_newframe(job->bmain, scene, job->scene_layer, job->depsgraph); + if (!dynamicPaint_calculateFrame(surface, job->eval_ctx, scene, cObject, frame)) { job->success = 0; return; } @@ -452,6 +460,10 @@ static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op) DynamicPaintCanvasSettings *canvas; Object *ob = ED_object_context(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + EvaluationContext *eval_ctx = MEM_mallocN(sizeof(*eval_ctx), "EvaluationContext"); + + CTX_data_eval_ctx(C, eval_ctx); DynamicPaintSurface *surface; @@ -479,9 +491,12 @@ static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op) DynamicPaintBakeJob *job = MEM_mallocN(sizeof(DynamicPaintBakeJob), "DynamicPaintBakeJob"); job->bmain = CTX_data_main(C); job->scene = scene; + job->scene_layer = sl; + job->depsgraph = CTX_data_depsgraph(C); job->ob = ob; job->canvas = canvas; job->surface = surface; + job->eval_ctx = eval_ctx; wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Dynamic Paint Bake", WM_JOB_PROGRESS, diff --git a/source/blender/editors/physics/particle_boids.c b/source/blender/editors/physics/particle_boids.c index 14b12497c4a..681ac75e847 100644 --- a/source/blender/editors/physics/particle_boids.c +++ b/source/blender/editors/physics/particle_boids.c @@ -39,10 +39,12 @@ #include "BKE_boids.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_particle.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "RNA_access.h" #include "RNA_enum_types.h" #include "RNA_define.h" @@ -75,7 +77,7 @@ static int rule_add_exec(bContext *C, wmOperator *op) BLI_addtail(&state->rules, rule); - DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); + DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); return OPERATOR_FINISHED; } @@ -121,8 +123,8 @@ static int rule_del_exec(bContext *C, wmOperator *UNUSED(op)) if (rule) rule->flag |= BOIDRULE_CURRENT; - DAG_relations_tag_update(bmain); - DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); return OPERATOR_FINISHED; } @@ -158,7 +160,7 @@ static int rule_move_up_exec(bContext *C, wmOperator *UNUSED(op)) BLI_remlink(&state->rules, rule); BLI_insertlinkbefore(&state->rules, rule->prev, rule); - DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); + DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); break; } } @@ -194,7 +196,7 @@ static int rule_move_down_exec(bContext *C, wmOperator *UNUSED(op)) BLI_remlink(&state->rules, rule); BLI_insertlinkafter(&state->rules, rule->next, rule); - DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); + DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); break; } } @@ -277,8 +279,8 @@ static int state_del_exec(bContext *C, wmOperator *UNUSED(op)) state->flag |= BOIDSTATE_CURRENT; - DAG_relations_tag_update(bmain); - DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); return OPERATOR_FINISHED; } @@ -349,7 +351,7 @@ static int state_move_down_exec(bContext *C, wmOperator *UNUSED(op)) if (state->flag & BOIDSTATE_CURRENT && state->next) { BLI_remlink(&boids->states, state); BLI_insertlinkafter(&boids->states, state->next, state); - DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); + DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); break; } } diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index da66ec44235..8986ebd26e9 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -53,7 +53,6 @@ #include "BLI_utildefines.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_object.h" @@ -64,8 +63,9 @@ #include "BKE_bvhutils.h" #include "BKE_pointcache.h" +#include "DEG_depsgraph.h" + #include "BIF_gl.h" -#include "BIF_glutil.h" #include "ED_object.h" #include "ED_physics.h" @@ -73,6 +73,9 @@ #include "ED_particle.h" #include "ED_view3d.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" + #include "UI_resources.h" #include "WM_api.h" @@ -83,7 +86,9 @@ #include "physics_intern.h" -void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys); +void PE_create_particle_edit( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, Object *ob, + PointCache *cache, ParticleSystem *psys); void PTCacheUndo_clear(PTCacheEdit *edit); void recalc_lengths(PTCacheEdit *edit); void recalc_emitter_field(Object *ob, ParticleSystem *psys); @@ -109,24 +114,26 @@ void update_world_cos(Object *ob, PTCacheEdit *edit); int PE_poll(bContext *C) { Scene *scene= CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob= CTX_data_active_object(C); - if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) + if (!scene || !sl || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) return 0; - return (PE_get_current(scene, ob) != NULL); + return (PE_get_current(scene, sl, ob) != NULL); } int PE_hair_poll(bContext *C) { Scene *scene= CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob= CTX_data_active_object(C); PTCacheEdit *edit; if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) return 0; - edit= PE_get_current(scene, ob); + edit= PE_get_current(scene, sl, ob); return (edit && edit->psys); } @@ -211,7 +218,8 @@ static float pe_brush_size_get(const Scene *UNUSED(scene), ParticleBrushData *br * * note: this function runs on poll, therefor it can runs many times a second * keep it fast! */ -static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create) +static PTCacheEdit *pe_get_current( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, Object *ob, int create) { ParticleEditSettings *pset= PE_settings(scene); PTCacheEdit *edit = NULL; @@ -222,6 +230,7 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create) return NULL; pset->scene = scene; + pset->scene_layer = sl; pset->object = ob; BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); @@ -250,18 +259,18 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create) if (psys->part && psys->part->type == PART_HAIR) { if (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) { if (create && !psys->pointcache->edit) - PE_create_particle_edit(scene, ob, pid->cache, NULL); + PE_create_particle_edit(eval_ctx, scene, sl, ob, pid->cache, NULL); edit = pid->cache->edit; } else { if (create && !psys->edit && psys->flag & PSYS_HAIR_DONE) - PE_create_particle_edit(scene, ob, NULL, psys); + PE_create_particle_edit(eval_ctx, scene, sl, ob, NULL, psys); edit = psys->edit; } } else { if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) - PE_create_particle_edit(scene, ob, pid->cache, psys); + PE_create_particle_edit(eval_ctx, scene, sl, ob, pid->cache, psys); edit = pid->cache->edit; } @@ -272,7 +281,7 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create) if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) { pset->flag |= PE_FADE_TIME; // NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB; - PE_create_particle_edit(scene, ob, pid->cache, NULL); + PE_create_particle_edit(eval_ctx, scene, sl, ob, pid->cache, NULL); } edit = pid->cache->edit; break; @@ -281,7 +290,7 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create) if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) { pset->flag |= PE_FADE_TIME; // NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB; - PE_create_particle_edit(scene, ob, pid->cache, NULL); + PE_create_particle_edit(eval_ctx, scene, sl, ob, pid->cache, NULL); } edit = pid->cache->edit; break; @@ -296,20 +305,21 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create) return edit; } -PTCacheEdit *PE_get_current(Scene *scene, Object *ob) +PTCacheEdit *PE_get_current(Scene *scene, SceneLayer *sl, Object *ob) { - return pe_get_current(scene, ob, 0); + return pe_get_current(NULL, scene, sl, ob, 0); } -PTCacheEdit *PE_create_current(Scene *scene, Object *ob) +PTCacheEdit *PE_create_current(const EvaluationContext *eval_ctx, Scene *scene, Object *ob) { - return pe_get_current(scene, ob, 1); + return pe_get_current(eval_ctx, scene, NULL, ob, 1); } -void PE_current_changed(Scene *scene, Object *ob) +void PE_current_changed(const EvaluationContext *eval_ctx, Scene *scene, Object *ob) { - if (ob->mode == OB_MODE_PARTICLE_EDIT) - PE_create_current(scene, ob); + if (ob->mode == OB_MODE_PARTICLE_EDIT) { + PE_create_current(eval_ctx, scene, ob); + } } void PE_hide_keys_time(Scene *scene, PTCacheEdit *edit, float cfra) @@ -351,9 +361,10 @@ static int pe_x_mirror(Object *ob) typedef struct PEData { ViewContext vc; - bglMats mats; + const bContext *context; Scene *scene; + SceneLayer *scene_layer; Object *ob; DerivedMesh *dm; PTCacheEdit *edit; @@ -387,9 +398,10 @@ static void PE_set_data(bContext *C, PEData *data) { memset(data, 0, sizeof(*data)); - data->scene= CTX_data_scene(C); - data->ob= CTX_data_active_object(C); - data->edit= PE_get_current(data->scene, data->ob); + data->scene = CTX_data_scene(C); + data->scene_layer = CTX_data_scene_layer(C); + data->ob = CTX_data_active_object(C); + data->edit = PE_get_current(data->scene, data->scene_layer, data->ob); } static void PE_set_view3d_data(bContext *C, PEData *data) @@ -397,15 +409,16 @@ static void PE_set_view3d_data(bContext *C, PEData *data) PE_set_data(C, data); view3d_set_viewcontext(C, &data->vc); - /* note, the object argument means the modelview matrix does not account for the objects matrix, use viewmat rather than (obmat * viewmat) */ - view3d_get_transformation(data->vc.ar, data->vc.rv3d, NULL, &data->mats); if (V3D_IS_ZBUF(data->vc.v3d)) { if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) { + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + /* needed or else the draw matrix can be incorrect */ view3d_operator_needs_opengl(C); - ED_view3d_backbuf_validate(&data->vc); + ED_view3d_backbuf_validate(&eval_ctx, &data->vc); /* we may need to force an update here by setting the rv3d as dirty * for now it seems ok, but take care!: * rv3d->depths->dirty = 1; */ @@ -438,7 +451,6 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[ { View3D *v3d= data->vc.v3d; ViewDepths *vd = data->vc.rv3d->depths; - double ux, uy, uz; float depth; /* nothing to do */ @@ -454,9 +466,6 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[ } #endif - gluProject(co[0], co[1], co[2], data->mats.modelview, data->mats.projection, - (GLint *)data->mats.viewport, &ux, &uy, &uz); - /* check if screen_co is within bounds because brush_cut uses out of screen coords */ if (screen_co[0] >= 0 && screen_co[0] < vd->w && screen_co[1] >= 0 && screen_co[1] < vd->h) { BLI_assert(vd && vd->depths); @@ -466,7 +475,10 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[ else return 0; - if ((float)uz - 0.00001f > depth) + float win[3]; + ED_view3d_project(data->vc.ar, co, win); + + if (win[2] - 0.00001f > depth) return 0; else return 1; @@ -1151,12 +1163,15 @@ void recalc_emitter_field(Object *ob, ParticleSystem *psys) BLI_kdtree_balance(edit->emitter_field); } -static void PE_update_selection(Scene *scene, Object *ob, int useflag) +static void PE_update_selection(const bContext *C, Scene *scene, SceneLayer *sl, Object *ob, int useflag) { - PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheEdit *edit = PE_get_current(scene, sl, ob); HairKey *hkey; + EvaluationContext eval_ctx; POINT_P; KEY_K; + CTX_data_eval_ctx(C, &eval_ctx); + /* flag all particles to be updated if not using flag */ if (!useflag) LOOP_POINTS @@ -1172,7 +1187,7 @@ static void PE_update_selection(Scene *scene, Object *ob, int useflag) } } - psys_cache_edit_paths(scene, ob, edit, CFRA, G.is_rendering); + psys_cache_edit_paths(&eval_ctx, scene, ob, edit, CFRA, G.is_rendering); /* disable update flag */ @@ -1258,12 +1273,12 @@ static void update_velocities(PTCacheEdit *edit) } } -void PE_update_object(Scene *scene, Object *ob, int useflag) +void PE_update_object(const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, Object *ob, int useflag) { /* use this to do partial particle updates, not usable when adding or * removing, then a full redo is necessary and calling this may crash */ ParticleEditSettings *pset= PE_settings(scene); - PTCacheEdit *edit = PE_get_current(scene, ob); + PTCacheEdit *edit = PE_get_current(scene, sl, ob); POINT_P; if (!edit) @@ -1288,7 +1303,7 @@ void PE_update_object(Scene *scene, Object *ob, int useflag) PE_hide_keys_time(scene, edit, CFRA); /* regenerate path caches */ - psys_cache_edit_paths(scene, ob, edit, CFRA, G.is_rendering); + psys_cache_edit_paths(eval_ctx, scene, ob, edit, CFRA, G.is_rendering); /* disable update flag */ LOOP_POINTS { @@ -1398,8 +1413,9 @@ static void select_action_apply(PTCacheEditPoint *point, PTCacheEditKey *key, in static int pe_select_all_exec(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob= CTX_data_active_object(C); - PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheEdit *edit= PE_get_current(scene, sl, ob); POINT_P; KEY_K; int action = RNA_enum_get(op->ptr, "action"); @@ -1422,7 +1438,7 @@ static int pe_select_all_exec(bContext *C, wmOperator *op) } } - PE_update_selection(scene, ob, 1); + PE_update_selection(C, scene, sl, ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob); return OPERATOR_FINISHED; @@ -1451,10 +1467,11 @@ int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselec { PEData data; Scene *scene= CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob= CTX_data_active_object(C); - PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheEdit *edit= PE_get_current(scene, sl, ob); POINT_P; KEY_K; - + if (!PE_start_edit(edit)) return OPERATOR_CANCELLED; @@ -1479,7 +1496,7 @@ int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselec else for_mouse_hit_keys(&data, toggle_key_select, 1); - PE_update_selection(scene, ob, 1); + PE_update_selection(C, scene, sl, ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob); return OPERATOR_FINISHED; @@ -1520,7 +1537,7 @@ static int select_roots_exec(bContext *C, wmOperator *op) data.select_action = action; foreach_point(&data, select_root); - PE_update_selection(data.scene, data.ob, 1); + PE_update_selection(C, data.scene, data.scene_layer, data.ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob); return OPERATOR_FINISHED; @@ -1585,7 +1602,7 @@ static int select_tips_exec(bContext *C, wmOperator *op) data.select_action = action; foreach_point(&data, select_tip); - PE_update_selection(data.scene, data.ob, 1); + PE_update_selection(C, data.scene, data.scene_layer, data.ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob); return OPERATOR_FINISHED; @@ -1624,6 +1641,7 @@ static int select_random_exec(bContext *C, wmOperator *op) PEData data; int type; Scene *scene; + SceneLayer *sl; Object *ob; /* used by LOOP_VISIBLE_POINTS, LOOP_VISIBLE_KEYS and LOOP_KEYS */ @@ -1643,8 +1661,9 @@ static int select_random_exec(bContext *C, wmOperator *op) PE_set_data(C, &data); data.select_action = SEL_SELECT; scene = CTX_data_scene(C); + sl = CTX_data_scene_layer(C); ob = CTX_data_active_object(C); - edit = PE_get_current(scene, ob); + edit = PE_get_current(scene, sl, ob); rng = BLI_rng_new_srandom(seed); @@ -1669,7 +1688,7 @@ static int select_random_exec(bContext *C, wmOperator *op) BLI_rng_free(rng); - PE_update_selection(data.scene, data.ob, 1); + PE_update_selection(C, data.scene, data.scene_layer, data.ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob); return OPERATOR_FINISHED; @@ -1713,7 +1732,7 @@ static int select_linked_exec(bContext *C, wmOperator *op) data.select= !RNA_boolean_get(op->ptr, "deselect"); for_mouse_hit_keys(&data, select_keys, 1); /* nearest only */ - PE_update_selection(data.scene, data.ob, 1); + PE_update_selection(C, data.scene, data.scene_layer, data.ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob); return OPERATOR_FINISHED; @@ -1761,8 +1780,9 @@ void PE_deselect_all_visible(PTCacheEdit *edit) int PE_border_select(bContext *C, rcti *rect, bool select, bool extend) { Scene *scene= CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob= CTX_data_active_object(C); - PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheEdit *edit= PE_get_current(scene, sl, ob); PEData data; if (!PE_start_edit(edit)) @@ -1777,7 +1797,7 @@ int PE_border_select(bContext *C, rcti *rect, bool select, bool extend) for_mouse_hit_keys(&data, select_key, 0); - PE_update_selection(scene, ob, 1); + PE_update_selection(C, scene, sl, ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob); return OPERATOR_FINISHED; @@ -1788,8 +1808,9 @@ int PE_border_select(bContext *C, rcti *rect, bool select, bool extend) int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad) { Scene *scene= CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob= CTX_data_active_object(C); - PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheEdit *edit= PE_get_current(scene, sl, ob); PEData data; if (!PE_start_edit(edit)) @@ -1802,7 +1823,7 @@ int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad) for_mouse_hit_keys(&data, select_key, 0); - PE_update_selection(scene, ob, 1); + PE_update_selection(C, scene, sl, ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob); return OPERATOR_FINISHED; @@ -1813,10 +1834,11 @@ int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad) int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool extend, bool select) { Scene *scene= CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob= CTX_data_active_object(C); ARegion *ar= CTX_wm_region(C); ParticleEditSettings *pset= PE_settings(scene); - PTCacheEdit *edit = PE_get_current(scene, ob); + PTCacheEdit *edit = PE_get_current(scene, sl, ob); ParticleSystem *psys = edit->psys; ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); POINT_P; KEY_K; @@ -1890,7 +1912,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool } } - PE_update_selection(scene, ob, 1); + PE_update_selection(C, scene, sl, ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob); return OPERATOR_FINISHED; @@ -1902,7 +1924,8 @@ static int hide_exec(bContext *C, wmOperator *op) { Object *ob= CTX_data_active_object(C); Scene *scene= CTX_data_scene(C); - PTCacheEdit *edit= PE_get_current(scene, ob); + SceneLayer *sl = CTX_data_scene_layer(C); + PTCacheEdit *edit= PE_get_current(scene, sl, ob); POINT_P; KEY_K; if (RNA_enum_get(op->ptr, "unselected")) { @@ -1924,7 +1947,7 @@ static int hide_exec(bContext *C, wmOperator *op) } } - PE_update_selection(scene, ob, 1); + PE_update_selection(C, scene, sl, ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob); return OPERATOR_FINISHED; @@ -1954,7 +1977,8 @@ static int reveal_exec(bContext *C, wmOperator *op) { Object *ob= CTX_data_active_object(C); Scene *scene= CTX_data_scene(C); - PTCacheEdit *edit = PE_get_current(scene, ob); + SceneLayer *sl = CTX_data_scene_layer(C); + PTCacheEdit *edit= PE_get_current(scene, sl, ob); const bool select = RNA_boolean_get(op->ptr, "select"); POINT_P; KEY_K; @@ -1969,7 +1993,7 @@ static int reveal_exec(bContext *C, wmOperator *op) } } - PE_update_selection(scene, ob, 1); + PE_update_selection(C, scene, sl, ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob); return OPERATOR_FINISHED; @@ -2031,7 +2055,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) PE_set_data(C, &data); foreach_point(&data, select_less_keys); - PE_update_selection(data.scene, data.ob, 1); + PE_update_selection(C, data.scene, data.scene_layer, data.ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob); return OPERATOR_FINISHED; @@ -2093,7 +2117,7 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op)) PE_set_data(C, &data); foreach_point(&data, select_more_keys); - PE_update_selection(data.scene, data.ob, 1); + PE_update_selection(C, data.scene, data.scene_layer, data.ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob); return OPERATOR_FINISHED; @@ -2126,12 +2150,15 @@ static void rekey_particle(PEData *data, int pa_index) ParticleKey state; HairKey *key, *new_keys, *okey; PTCacheEditKey *ekey; + EvaluationContext eval_ctx; float dval, sta, end; int k; - sim.scene= data->scene; - sim.ob= data->ob; - sim.psys= edit->psys; + CTX_data_eval_ctx(data->context, &eval_ctx); + sim.eval_ctx = &eval_ctx; + sim.scene = data->scene; + sim.ob = data->ob; + sim.psys = edit->psys; pa->flag |= PARS_REKEY; @@ -2182,6 +2209,9 @@ static int rekey_exec(bContext *C, wmOperator *op) { PEData data; + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + PE_set_data(C, &data); data.dval= 1.0f / (float)(data.totrekey-1); @@ -2190,7 +2220,7 @@ static int rekey_exec(bContext *C, wmOperator *op) foreach_selected_point(&data, rekey_particle); recalc_lengths(data.edit); - PE_update_object(data.scene, data.ob, 1); + PE_update_object(&eval_ctx, data.scene, data.scene_layer, data.ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob); return OPERATOR_FINISHED; @@ -2215,24 +2245,28 @@ void PARTICLE_OT_rekey(wmOperatorType *ot) RNA_def_int(ot->srna, "keys_number", 2, 2, INT_MAX, "Number of Keys", "", 2, 100); } -static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float path_time) +static void rekey_particle_to_time(const bContext *C, Scene *scene, SceneLayer *sl, Object *ob, int pa_index, float path_time) { - PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheEdit *edit= PE_get_current(scene, sl, ob); ParticleSystem *psys; - ParticleSimulationData sim= {0}; + ParticleSimulationData sim = {0}; ParticleData *pa; ParticleKey state; HairKey *new_keys, *key; PTCacheEditKey *ekey; + EvaluationContext eval_ctx; int k; + CTX_data_eval_ctx(C, &eval_ctx); + if (!edit || !edit->psys) return; psys = edit->psys; - sim.scene= scene; - sim.ob= ob; - sim.psys= psys; + sim.eval_ctx = &eval_ctx; + sim.scene = scene; + sim.ob = ob; + sim.psys = psys; pa= psys->particles + pa_index; @@ -2442,14 +2476,17 @@ static void subdivide_particle(PEData *data, int pa_index) ParticleKey state; HairKey *key, *nkey, *new_keys; PTCacheEditKey *ekey, *nekey, *new_ekeys; + EvaluationContext eval_ctx; int k; short totnewkey=0; float endtime; - sim.scene= data->scene; - sim.ob= data->ob; - sim.psys= edit->psys; + CTX_data_eval_ctx(data->context, &eval_ctx); + sim.eval_ctx = &eval_ctx; + sim.scene = data->scene; + sim.ob = data->ob; + sim.psys = edit->psys; for (k=0, ekey=point->keys; k<pa->totkey-1; k++, ekey++) { if (ekey->flag&PEK_SELECT && (ekey+1)->flag&PEK_SELECT) @@ -2517,11 +2554,14 @@ static int subdivide_exec(bContext *C, wmOperator *UNUSED(op)) { PEData data; + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + PE_set_data(C, &data); foreach_point(&data, subdivide_particle); recalc_lengths(data.edit); - PE_update_object(data.scene, data.ob, 1); + PE_update_object(&eval_ctx, data.scene, data.scene_layer, data.ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob); return OPERATOR_FINISHED; @@ -2547,8 +2587,9 @@ void PARTICLE_OT_subdivide(wmOperatorType *ot) static int remove_doubles_exec(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob= CTX_data_active_object(C); - PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheEdit *edit= PE_get_current(scene, sl, ob); ParticleSystem *psys = edit->psys; ParticleSystemModifierData *psmd; KDTree *tree; @@ -2610,7 +2651,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) BKE_reportf(op->reports, RPT_INFO, "Removed %d double particles", totremoved); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); return OPERATOR_FINISHED; @@ -2639,9 +2680,10 @@ void PARTICLE_OT_remove_doubles(wmOperatorType *ot) static int weight_set_exec(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); ParticleEditSettings *pset= PE_settings(scene); Object *ob= CTX_data_active_object(C); - PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheEdit *edit= PE_get_current(scene, sl, ob); ParticleSystem *psys = edit->psys; POINT_P; KEY_K; @@ -2662,7 +2704,7 @@ static int weight_set_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); return OPERATOR_FINISHED; @@ -2694,24 +2736,27 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata) ParticleEditSettings *pset= PE_settings(scene); ParticleBrushData *brush; - if (pset->brushtype < 0) + if (pset->brushtype < 0) { return; + } - brush= &pset->brush[pset->brushtype]; + brush = &pset->brush[pset->brushtype]; if (brush) { - glPushMatrix(); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - glTranslatef((float)x, (float)y, 0.0f); + immUniformColor4ub(255, 255, 255, 128); - glColor4ub(255, 255, 255, 128); glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - glutil_draw_lined_arc(0.0, M_PI*2.0, pe_brush_size_get(scene, brush), 40); + + imm_draw_circle_wire_2d(pos, (float)x, (float)y, pe_brush_size_get(scene, brush), 40); + glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - - glPopMatrix(); + + immUnbindProgram(); } } @@ -2768,7 +2813,7 @@ static int delete_exec(bContext *C, wmOperator *op) recalc_lengths(data.edit); } - DAG_id_tag_update(&data.ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&data.ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob); return OPERATOR_FINISHED; @@ -2795,11 +2840,11 @@ void PARTICLE_OT_delete(wmOperatorType *ot) /*************************** mirror operator **************************/ -static void PE_mirror_x(Scene *scene, Object *ob, int tagged) +static void PE_mirror_x(Scene *scene, SceneLayer *sl, Object *ob, int tagged) { Mesh *me= (Mesh *)(ob->data); ParticleSystemModifierData *psmd; - PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheEdit *edit = PE_get_current(scene, sl, ob); ParticleSystem *psys = edit->psys; ParticleData *pa, *newpa, *new_pars; PTCacheEditPoint *newpoint, *new_points; @@ -2946,14 +2991,15 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged) static int mirror_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene= CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob= CTX_data_active_object(C); - PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheEdit *edit= PE_get_current(scene, sl, ob); - PE_mirror_x(scene, ob, 0); + PE_mirror_x(scene, sl, ob, 0); update_world_cos(ob, edit); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); return OPERATOR_FINISHED; } @@ -3086,7 +3132,7 @@ static void brush_cut(PEData *data, int pa_index) edit->points[pa_index].flag |= PEP_TAG; } else { - rekey_particle_to_time(data->scene, ob, pa_index, cut_time); + rekey_particle_to_time(data->context, data->scene, data->scene_layer, ob, pa_index, cut_time); edit->points[pa_index].flag |= PEP_EDIT_RECALC; } } @@ -3334,25 +3380,28 @@ static void intersect_dm_quad_weights(const float v1[3], const float v2[3], cons } /* check intersection with a derivedmesh */ -static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm, +static int particle_intersect_dm(const bContext *C, Scene *scene, Object *ob, DerivedMesh *dm, float *vert_cos, const float co1[3], const float co2[3], float *min_d, int *min_face, float *min_w, float *face_minmax, float *pa_minmax, float radius, float *ipoint) { + EvaluationContext eval_ctx; MFace *mface= NULL; MVert *mvert= NULL; int i, totface, intersect=0; float cur_d, cur_uv[2], v1[3], v2[3], v3[3], v4[3], min[3], max[3], p_min[3], p_max[3]; float cur_ipoint[3]; + CTX_data_eval_ctx(C, &eval_ctx); + if (dm == NULL) { psys_disable_all(ob); - dm=mesh_get_derived_final(scene, ob, 0); + dm = mesh_get_derived_final(&eval_ctx, scene, ob, 0); if (dm == NULL) - dm=mesh_get_derived_deform(scene, ob, 0); + dm = mesh_get_derived_deform(&eval_ctx, scene, ob, 0); psys_enable_all(ob); @@ -3465,8 +3514,9 @@ static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm, return intersect; } -static int brush_add(PEData *data, short number) +static int brush_add(const bContext *C, PEData *data, short number) { + EvaluationContext eval_ctx; Scene *scene= data->scene; Object *ob= data->ob; DerivedMesh *dm; @@ -3494,6 +3544,9 @@ static int brush_add(PEData *data, short number) rng = BLI_rng_new_srandom(psys->seed+data->mval[0]+data->mval[1]); + CTX_data_eval_ctx(C, &eval_ctx); + + sim.eval_ctx = &eval_ctx; sim.scene= scene; sim.ob= ob; sim.psys= psys; @@ -3534,7 +3587,7 @@ static int brush_add(PEData *data, short number) min_d=2.0; /* warning, returns the derived mesh face */ - if (particle_intersect_dm(scene, ob, dm, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) { + if (particle_intersect_dm(C, scene, ob, dm, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) { if (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly) { add_pars[n].num = add_pars[n].num_dmcache; add_pars[n].num_dmcache = DMCACHE_ISCHILD; @@ -3715,6 +3768,7 @@ static int brush_add(PEData *data, short number) typedef struct BrushEdit { Scene *scene; + SceneLayer *sl; Object *ob; PTCacheEdit *edit; @@ -3729,9 +3783,10 @@ typedef struct BrushEdit { static int brush_edit_init(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob= CTX_data_active_object(C); ParticleEditSettings *pset= PE_settings(scene); - PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheEdit *edit= PE_get_current(scene, sl, ob); ARegion *ar= CTX_wm_region(C); BrushEdit *bedit; float min[3], max[3]; @@ -3741,7 +3796,7 @@ static int brush_edit_init(bContext *C, wmOperator *op) /* set the 'distance factor' for grabbing (used in comb etc) */ INIT_MINMAX(min, max); - PE_minmax(scene, min, max); + PE_minmax(scene, sl, min, max); mid_v3_v3v3(min, min, max); bedit= MEM_callocN(sizeof(BrushEdit), "BrushEdit"); @@ -3749,6 +3804,7 @@ static int brush_edit_init(bContext *C, wmOperator *op) op->customdata= bedit; bedit->scene= scene; + bedit->sl = sl; bedit->ob= ob; bedit->edit= edit; @@ -3764,6 +3820,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) { BrushEdit *bedit= op->customdata; Scene *scene= bedit->scene; + SceneLayer *sl = bedit->sl; Object *ob= bedit->ob; PTCacheEdit *edit= bedit->edit; ParticleEditSettings *pset= PE_settings(scene); @@ -3779,6 +3836,9 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) if (!PE_start_edit(edit)) return; + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + RNA_float_get_array(itemptr, "mouse", mousef); mouse[0] = mousef[0]; mouse[1] = mousef[1]; @@ -3904,7 +3964,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) if (edit->psys && edit->psys->part->from==PART_FROM_FACE) { data.mval= mval; - added= brush_add(&data, brush->count); + added= brush_add(C, &data, brush->count); if (pset->flag & PE_KEEP_LENGTHS) recalc_lengths(edit); @@ -3954,21 +4014,22 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_CUT) && (added || removed)) { if (pset->brushtype == PE_BRUSH_ADD && pe_x_mirror(ob)) - PE_mirror_x(scene, ob, 1); + PE_mirror_x(scene, sl, ob, 1); update_world_cos(ob, edit); psys_free_path_cache(NULL, edit); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + } + else { + PE_update_object(&eval_ctx, scene, sl, ob, 1); } - else - PE_update_object(scene, ob, 1); } if (edit->psys) { WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); } else { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); } @@ -4176,7 +4237,7 @@ static void shape_cut(PEData *data, int pa_index) edit->points[pa_index].flag |= PEP_TAG; } else { - rekey_particle_to_time(data->scene, ob, pa_index, cut_time); + rekey_particle_to_time(data->context, data->scene, data->scene_layer, ob, pa_index, cut_time); edit->points[pa_index].flag |= PEP_EDIT_RECALC; } } @@ -4185,9 +4246,10 @@ static void shape_cut(PEData *data, int pa_index) static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob = CTX_data_active_object(C); ParticleEditSettings *pset = PE_settings(scene); - PTCacheEdit *edit = PE_get_current(scene, ob); + PTCacheEdit *edit = PE_get_current(scene, sl, ob); Object *shapeob = pset->shape_object; int selected = count_selected_keys(scene, edit); int lock_root = pset->flag & PE_LOCK_FIRST; @@ -4195,6 +4257,9 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op)) if (!PE_start_edit(edit)) return OPERATOR_CANCELLED; + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + /* disable locking temporatily for disconnected hair */ if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) pset->flag &= ~PE_LOCK_FIRST; @@ -4220,16 +4285,17 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op)) if (removed) { update_world_cos(ob, edit); psys_free_path_cache(NULL, edit); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + } + else { + PE_update_object(&eval_ctx, scene, sl, ob, 1); } - else - PE_update_object(scene, ob, 1); if (edit->psys) { WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); } else { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); } @@ -4395,9 +4461,9 @@ static void get_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo) } } -void PE_undo_push(Scene *scene, const char *str) +void PE_undo_push(Scene *scene, SceneLayer *sl, const char *str) { - PTCacheEdit *edit= PE_get_current(scene, OBACT); + PTCacheEdit *edit= PE_get_current(scene, sl, OBACT(sl)); PTCacheUndo *undo; int nr; @@ -4437,9 +4503,9 @@ void PE_undo_push(Scene *scene, const char *str) make_PTCacheUndo(edit, edit->curundo); } -void PE_undo_step(Scene *scene, int step) +void PE_undo_step(Scene *scene, SceneLayer *sl, int step) { - PTCacheEdit *edit= PE_get_current(scene, OBACT); + PTCacheEdit *edit= PE_get_current(scene, sl, OBACT(sl)); if (!edit) return; @@ -4470,12 +4536,12 @@ void PE_undo_step(Scene *scene, int step) } } - DAG_id_tag_update(&OBACT->id, OB_RECALC_DATA); + DEG_id_tag_update(&OBACT(sl)->id, OB_RECALC_DATA); } -bool PE_undo_is_valid(Scene *scene) +bool PE_undo_is_valid(Scene *scene, SceneLayer *sl) { - PTCacheEdit *edit= PE_get_current(scene, OBACT); + PTCacheEdit *edit= PE_get_current(scene, sl, OBACT(sl)); if (edit) { return (edit->undo.last != edit->undo.first); @@ -4498,19 +4564,19 @@ void PTCacheUndo_clear(PTCacheEdit *edit) edit->curundo= NULL; } -void PE_undo(Scene *scene) +void PE_undo(Scene *scene, SceneLayer *sl) { - PE_undo_step(scene, 1); + PE_undo_step(scene, sl, 1); } -void PE_redo(Scene *scene) +void PE_redo(Scene *scene, SceneLayer *sl) { - PE_undo_step(scene, -1); + PE_undo_step(scene, sl, -1); } -void PE_undo_number(Scene *scene, int nr) +void PE_undo_number(Scene *scene, SceneLayer *sl, int nr) { - PTCacheEdit *edit= PE_get_current(scene, OBACT); + PTCacheEdit *edit= PE_get_current(scene, sl, OBACT(sl)); PTCacheUndo *undo; int a=0; @@ -4518,15 +4584,15 @@ void PE_undo_number(Scene *scene, int nr) if (a==nr) break; } edit->curundo= undo; - PE_undo_step(scene, 0); + PE_undo_step(scene, sl, 0); } /* get name of undo item, return null if no item with this index */ /* if active pointer, set it to 1 if true */ -const char *PE_undo_get_name(Scene *scene, int nr, bool *r_active) +const char *PE_undo_get_name(Scene *scene, SceneLayer *sl, int nr, bool *r_active) { - PTCacheEdit *edit= PE_get_current(scene, OBACT); + PTCacheEdit *edit= PE_get_current(scene, sl, OBACT(sl)); PTCacheUndo *undo; if (r_active) *r_active = false; @@ -4545,10 +4611,10 @@ const char *PE_undo_get_name(Scene *scene, int nr, bool *r_active) /************************ utilities ******************************/ -int PE_minmax(Scene *scene, float min[3], float max[3]) +int PE_minmax(Scene *scene, SceneLayer *sl, float min[3], float max[3]) { - Object *ob= OBACT; - PTCacheEdit *edit= PE_get_current(scene, ob); + Object *ob= OBACT(sl); + PTCacheEdit *edit= PE_get_current(scene, sl, ob); ParticleSystem *psys; ParticleSystemModifierData *psmd = NULL; POINT_P; KEY_K; @@ -4585,7 +4651,8 @@ int PE_minmax(Scene *scene, float min[3], float max[3]) /************************ particle edit toggle operator ************************/ /* initialize needed data for bake edit */ -void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys) +void PE_create_particle_edit( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, Object *ob, PointCache *cache, ParticleSystem *psys) { PTCacheEdit *edit; ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL; @@ -4686,10 +4753,10 @@ void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, Partic recalc_lengths(edit); if (psys && !cache) recalc_emitter_field(ob, psys); - PE_update_object(scene, ob, 1); + PE_update_object(eval_ctx, scene, sl, ob, 1); PTCacheUndo_clear(edit); - PE_undo_push(scene, "Original"); + PE_undo_push(scene, sl, "Original"); } } @@ -4716,6 +4783,9 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op) const int mode_flag = OB_MODE_PARTICLE_EDIT; const bool is_mode_set = (ob->mode & mode_flag) != 0; + BKE_report(op->reports, RPT_INFO, "Particles are changing, editing is not possible"); + return OPERATOR_CANCELLED; + if (!is_mode_set) { if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) { return OPERATOR_CANCELLED; @@ -4724,8 +4794,11 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op) if (!is_mode_set) { PTCacheEdit *edit; + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + ob->mode |= mode_flag; - edit= PE_create_current(scene, ob); + edit= PE_create_current(&eval_ctx, scene, ob); /* mesh may have changed since last entering editmode. * note, this may have run before if the edit data was just created, so could avoid this and speed up a little */ @@ -4741,7 +4814,7 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL); } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); return OPERATOR_FINISHED; } @@ -4782,7 +4855,7 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op)) psys_reset(psys, PSYS_RESET_DEPSGRAPH); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } else { /* some operation might have protected hair from editing so let's clear the flag */ @@ -4790,7 +4863,7 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op)) psys->flag &= ~PSYS_GLOBAL_HAIR; psys->flag &= ~PSYS_EDITED; WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } return OPERATOR_FINISHED; @@ -4893,19 +4966,24 @@ static int unify_length_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = CTX_data_active_object(C); Scene *scene = CTX_data_scene(C); - PTCacheEdit *edit = PE_get_current(scene, ob); + SceneLayer *sl = CTX_data_scene_layer(C); + PTCacheEdit *edit = PE_get_current(scene, sl, ob); float average_length = calculate_average_length(edit); + if (average_length == 0.0f) { return OPERATOR_CANCELLED; } scale_points_to_length(edit, average_length); - PE_update_object(scene, ob, 1); + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + + PE_update_object(&eval_ctx, scene, sl, ob, 1); if (edit->psys) { WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); } else { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); } diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index aaa9afdd8c6..c4ed32e8743 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -43,7 +43,6 @@ #include "BLI_string.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_cdderivedmesh.h" #include "BKE_global.h" @@ -55,6 +54,9 @@ #include "BKE_pointcache.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -69,7 +71,7 @@ #include "physics_intern.h" -extern void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys); +extern void PE_create_particle_edit(const bContext *C, Scene *scene, SceneLayer *sl, Object *ob, PointCache *cache, ParticleSystem *psys); extern void PTCacheUndo_clear(PTCacheEdit *edit); extern void recalc_lengths(PTCacheEdit *edit); extern void recalc_emitter_field(Object *ob, ParticleSystem *psys); @@ -133,6 +135,7 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); int mode_orig; if (!scene || !ob) @@ -146,7 +149,7 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op)) */ if (mode_orig & OB_MODE_PARTICLE_EDIT) { if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) { - if (scene->basact && scene->basact->object == ob) { + if (sl->basact && sl->basact->object == ob) { WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL); } } @@ -208,8 +211,8 @@ static int new_particle_settings_exec(bContext *C, wmOperator *UNUSED(op)) psys_check_boid_data(psys); - DAG_relations_tag_update(bmain); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); @@ -256,8 +259,8 @@ static int new_particle_target_exec(bContext *C, wmOperator *UNUSED(op)) BLI_addtail(&psys->targets, pt); - DAG_relations_tag_update(bmain); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); @@ -304,8 +307,8 @@ static int remove_particle_target_exec(bContext *C, wmOperator *UNUSED(op)) if (pt) pt->flag |= PTARGET_CURRENT; - DAG_relations_tag_update(bmain); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); @@ -344,7 +347,7 @@ static int target_move_up_exec(bContext *C, wmOperator *UNUSED(op)) BLI_remlink(&psys->targets, pt); BLI_insertlinkbefore(&psys->targets, pt->prev, pt); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); break; } @@ -382,7 +385,7 @@ static int target_move_down_exec(bContext *C, wmOperator *UNUSED(op)) BLI_remlink(&psys->targets, pt); BLI_insertlinkafter(&psys->targets, pt->next, pt); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); break; } @@ -565,7 +568,9 @@ void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot) /************************ connect/disconnect hair operators *********************/ -static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys) +static void disconnect_hair( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, + Object *ob, ParticleSystem *psys) { ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); ParticleEditSettings *pset= PE_settings(scene); @@ -611,30 +616,34 @@ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys) if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF)) pset->brushtype = PE_BRUSH_NONE; - PE_update_object(scene, ob, 0); + PE_update_object(eval_ctx, scene, sl, ob, 0); } static int disconnect_hair_exec(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob= ED_object_context(C); ParticleSystem *psys= NULL; const bool all = RNA_boolean_get(op->ptr, "all"); + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + if (!ob) return OPERATOR_CANCELLED; if (all) { for (psys=ob->particlesystem.first; psys; psys=psys->next) { - disconnect_hair(scene, ob, psys); + disconnect_hair(&eval_ctx, scene, sl, ob, psys); } } else { psys = psys_get_current(ob); - disconnect_hair(scene, ob, psys); + disconnect_hair(&eval_ctx, scene, sl, ob, psys); } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); return OPERATOR_FINISHED; @@ -657,9 +666,10 @@ void PARTICLE_OT_disconnect_hair(wmOperatorType *ot) /* from/to_world_space : whether from/to particles are in world or hair space * from/to_mat : additional transform for from/to particles (e.g. for using object space copying) */ -static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys, - Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit, - float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global) +static bool remap_hair_emitter( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, Object *ob, ParticleSystem *psys, + Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit, + float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global) { ParticleSystemModifierData *target_psmd = psys_get_modifier(target_ob, target_psys); ParticleData *pa, *tpa; @@ -843,19 +853,23 @@ static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys, psys_free_path_cache(target_psys, target_edit); - PE_update_object(scene, target_ob, 0); + PE_update_object(eval_ctx, scene, sl, target_ob, 0); return true; } -static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) +static bool connect_hair( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, + Object *ob, ParticleSystem *psys) { bool ok; if (!psys) return false; - ok = remap_hair_emitter(scene, ob, psys, ob, psys, psys->edit, ob->obmat, ob->obmat, psys->flag & PSYS_GLOBAL_HAIR, false); + ok = remap_hair_emitter( + eval_ctx, scene, sl, ob, psys, ob, psys, psys->edit, + ob->obmat, ob->obmat, psys->flag & PSYS_GLOBAL_HAIR, false); psys->flag &= ~PSYS_GLOBAL_HAIR; return ok; @@ -863,7 +877,9 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) static int connect_hair_exec(bContext *C, wmOperator *op) { + EvaluationContext eval_ctx; Scene *scene= CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob= ED_object_context(C); ParticleSystem *psys= NULL; const bool all = RNA_boolean_get(op->ptr, "all"); @@ -872,14 +888,16 @@ static int connect_hair_exec(bContext *C, wmOperator *op) if (!ob) return OPERATOR_CANCELLED; + CTX_data_eval_ctx(C, &eval_ctx); + if (all) { for (psys=ob->particlesystem.first; psys; psys=psys->next) { - any_connected |= connect_hair(scene, ob, psys); + any_connected |= connect_hair(&eval_ctx, scene, sl, ob, psys); } } else { psys = psys_get_current(ob); - any_connected |= connect_hair(scene, ob, psys); + any_connected |= connect_hair(&eval_ctx, scene, sl, ob, psys); } if (!any_connected) { @@ -888,7 +906,7 @@ static int connect_hair_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); return OPERATOR_FINISHED; @@ -915,7 +933,9 @@ typedef enum eCopyParticlesSpace { PAR_COPY_SPACE_WORLD = 1, } eCopyParticlesSpace; -static void copy_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystem *psys_from) +static void copy_particle_edit( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, + Object *ob, ParticleSystem *psys, ParticleSystem *psys_from) { PTCacheEdit *edit_from = psys_from->edit, *edit; ParticleData *pa; @@ -965,10 +985,10 @@ static void copy_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys, P recalc_lengths(edit); recalc_emitter_field(ob, psys); - PE_update_object(scene, ob, true); + PE_update_object(eval_ctx, scene, sl, ob, true); PTCacheUndo_clear(edit); - PE_undo_push(scene, "Original"); + PE_undo_push(scene, sl, "Original"); } static void remove_particle_systems_from_object(Object *ob_to) @@ -996,14 +1016,17 @@ static void remove_particle_systems_from_object(Object *ob_to) } /* single_psys_from is optional, if NULL all psys of ob_from are copied */ -static bool copy_particle_systems_to_object(Main *bmain, +static bool copy_particle_systems_to_object(const bContext *C, Scene *scene, + SceneLayer *sl, Object *ob_from, ParticleSystem *single_psys_from, Object *ob_to, int space, bool duplicate_settings) { + Main *bmain = CTX_data_main(C); + EvaluationContext eval_ctx; ModifierData *md; ParticleSystem *psys_start = NULL, *psys, *psys_from; ParticleSystem **tmp_psys; @@ -1011,6 +1034,8 @@ static bool copy_particle_systems_to_object(Main *bmain, CustomDataMask cdmask; int i, totpsys; + CTX_data_eval_ctx(C, &eval_ctx); + if (ob_to->type != OB_MESH) return false; if (!ob_to->data || ID_IS_LINKED(ob_to->data)) @@ -1049,7 +1074,7 @@ static bool copy_particle_systems_to_object(Main *bmain, psys_start = totpsys > 0 ? tmp_psys[0] : NULL; /* get the DM (psys and their modifiers have not been appended yet) */ - final_dm = mesh_get_derived_final(scene, ob_to, cdmask); + final_dm = mesh_get_derived_final(&eval_ctx, scene, ob_to, cdmask); /* now append psys to the object and make modifiers */ for (i = 0, psys_from = PSYS_FROM_FIRST; @@ -1077,8 +1102,9 @@ static bool copy_particle_systems_to_object(Main *bmain, CDDM_calc_normals(psmd->dm_final); DM_ensure_tessface(psmd->dm_final); - if (psys_from->edit) - copy_particle_edit(scene, ob_to, psys, psys_from); + if (psys_from->edit) { + copy_particle_edit(&eval_ctx, scene, sl, ob_to, psys, psys_from); + } if (duplicate_settings) { id_us_min(&psys->part->id); @@ -1112,7 +1138,9 @@ static bool copy_particle_systems_to_object(Main *bmain, break; } if (ob_from != ob_to) { - remap_hair_emitter(scene, ob_from, psys_from, ob_to, psys, psys->edit, from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR); + remap_hair_emitter( + &eval_ctx, scene, sl, ob_from, psys_from, ob_to, psys, psys->edit, + from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR); } /* tag for recalc */ @@ -1122,7 +1150,7 @@ static bool copy_particle_systems_to_object(Main *bmain, #undef PSYS_FROM_FIRST #undef PSYS_FROM_NEXT - DAG_id_tag_update(&ob_to->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob_to->id, OB_RECALC_DATA); WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to); return true; } @@ -1145,8 +1173,8 @@ static int copy_particle_systems_exec(bContext *C, wmOperator *op) const int space = RNA_enum_get(op->ptr, "space"); const bool remove_target_particles = RNA_boolean_get(op->ptr, "remove_target_particles"); const bool use_active = RNA_boolean_get(op->ptr, "use_active"); - Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob_from = ED_object_active_context(C); ParticleSystem *psys_from = use_active ? CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data : NULL; @@ -1161,7 +1189,7 @@ static int copy_particle_systems_exec(bContext *C, wmOperator *op) remove_particle_systems_from_object(ob_to); changed = true; } - if (copy_particle_systems_to_object(bmain, scene, ob_from, psys_from, ob_to, space, false)) + if (copy_particle_systems_to_object(C, scene, sl, ob_from, psys_from, ob_to, space, false)) changed = true; else fail++; @@ -1222,7 +1250,7 @@ static int duplicate_particle_systems_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data; - copy_particle_systems_to_object(CTX_data_main(C), scene, ob, psys, ob, + copy_particle_systems_to_object(C, scene, CTX_data_scene_layer(C), ob, psys, ob, PAR_COPY_SPACE_OBJECT, duplicate_settings); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 6460e83e2a0..3c4aeaf145f 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -55,6 +55,8 @@ #include "BKE_report.h" #include "BKE_scene.h" +#include "DEG_depsgraph.h" + #include "LBM_fluidsim.h" #include "ED_screen.h" @@ -244,7 +246,7 @@ static void set_channel(float *channel, float time, float *value, int i, int siz } } -static void set_vertex_channel(float *channel, float time, struct Scene *scene, struct FluidObject *fobj, int i) +static void set_vertex_channel(EvaluationContext *eval_ctx, float *channel, float time, struct Scene *scene, struct FluidObject *fobj, int i) { Object *ob = fobj->object; FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); @@ -257,7 +259,7 @@ static void set_vertex_channel(float *channel, float time, struct Scene *scene, if (channel == NULL) return; - initElbeemMesh(scene, ob, &numVerts, &verts, &numTris, &tris, 1, modifierIndex); + initElbeemMesh(eval_ctx, scene, ob, &numVerts, &verts, &numTris, &tris, 1, modifierIndex); /* don't allow mesh to change number of verts in anim sequence */ if (numVerts != fobj->numVerts) { @@ -329,10 +331,15 @@ static void free_all_fluidobject_channels(ListBase *fobjects) static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), FluidsimSettings *domainSettings, FluidAnimChannels *channels, ListBase *fobjects) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); + EvaluationContext eval_ctx; Base *base; int i; int length = channels->length; float eval_time; + + CTX_data_eval_ctx(C, &eval_ctx); /* init time values (assuming that time moves at a constant speed; may be overridden later) */ init_time(domainSettings, channels); @@ -343,7 +350,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid channels->DomainTime = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainTime"); /* allocate fluid objects */ - for (base=scene->base.first; base; base= base->next) { + for (base = FIRSTBASE(sl); base; base = base->next) { Object *ob = base->object; FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); @@ -373,7 +380,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid float *verts=NULL; int *tris=NULL, modifierIndex = BLI_findindex(&ob->modifiers, (ModifierData *)fluidmd); - initElbeemMesh(scene, ob, &fobj->numVerts, &verts, &fobj->numTris, &tris, 0, modifierIndex); + initElbeemMesh(&eval_ctx, scene, ob, &fobj->numVerts, &verts, &fobj->numTris, &tris, 0, modifierIndex); fobj->VertexCache = MEM_callocN(length *((fobj->numVerts*CHANNEL_VEC)+1) * sizeof(float), "fluidobject VertexCache"); MEM_freeN(verts); @@ -402,7 +409,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid /* Modifying the global scene isn't nice, but we can do it in * this part of the process before a threaded job is created */ scene->r.cfra = (int)eval_time; - ED_update_for_newframe(CTX_data_main(C), scene, 1); + ED_update_for_newframe(CTX_data_main(C), scene, sl, depsgraph); /* now scene data should be current according to animation system, so we fill the channels */ @@ -461,15 +468,18 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid } if (fluid_is_animated_mesh(fluidmd->fss)) { - set_vertex_channel(fobj->VertexCache, timeAtFrame, scene, fobj, i); + set_vertex_channel(&eval_ctx, fobj->VertexCache, timeAtFrame, scene, fobj, i); } } } } -static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length) +static void export_fluid_objects(const bContext *C, ListBase *fobjects, Scene *scene, int length) { FluidObject *fobj; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); for (fobj=fobjects->first; fobj; fobj=fobj->next) { Object *ob = fobj->object; @@ -491,7 +501,7 @@ static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length) fsmesh.type = fluidmd->fss->type; fsmesh.name = ob->id.name; - initElbeemMesh(scene, ob, &numVerts, &verts, &numTris, &tris, 0, modifierIndex); + initElbeemMesh(&eval_ctx, scene, ob, &numVerts, &verts, &numTris, &tris, 0, modifierIndex); fsmesh.numVertices = numVerts; fsmesh.numTriangles = numTris; @@ -570,14 +580,14 @@ static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length) } } -static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDomain) +static int fluid_validate_scene(ReportList *reports, SceneLayer *sl, Object *fsDomain) { Base *base; Object *newdomain = NULL; int channelObjCount = 0; int fluidInputCount = 0; - for (base=scene->base.first; base; base= base->next) { + for (base = FIRSTBASE(sl); base; base = base->next) { Object *ob = base->object; FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); @@ -835,7 +845,9 @@ static void fluidsim_delete_until_lastframe(FluidsimSettings *fss, const char *r static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, short do_job) { - Scene *scene= CTX_data_scene(C); + Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); int i; FluidsimSettings *domainSettings; @@ -882,7 +894,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor } /* check scene for sane object/modifier settings */ - if (!fluid_validate_scene(reports, scene, fsDomain)) { + if (!fluid_validate_scene(reports, sl, fsDomain)) { fluidbake_free_data(channels, fobjects, fsset, fb); return 0; } @@ -947,7 +959,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor /* reset to original current frame */ scene->r.cfra = origFrame; - ED_update_for_newframe(CTX_data_main(C), scene, 1); + ED_update_for_newframe(CTX_data_main(C), scene, sl, depsgraph); /* ******** init domain object's matrix ******** */ copy_m4_m4(domainMat, fsDomain->obmat); @@ -1034,7 +1046,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor elbeemAddDomain(fsset); /* ******** export all fluid objects to elbeem ******** */ - export_fluid_objects(fobjects, scene, channels->length); + export_fluid_objects(C, fobjects, scene, channels->length); /* custom data for fluid bake job */ fb->settings = fsset; diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c index b1d708ebc07..758ef43590e 100644 --- a/source/blender/editors/physics/physics_ops.c +++ b/source/blender/editors/physics/physics_ops.c @@ -137,23 +137,6 @@ static void keymap_particle(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "PARTICLE_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "unselected", true); - /* Shift+LMB behavior first, so it has priority over KM_ANY item below. */ - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", true); - RNA_boolean_set(kmi->ptr, "use_accurate", false); - - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", false); - RNA_boolean_set(kmi->ptr, "use_accurate", true); - - /* Using KM_ANY here to allow holding modifiers before starting to transform. */ - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_ANY, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", false); - RNA_boolean_set(kmi->ptr, "use_accurate", false); - WM_keymap_add_item(keymap, "PARTICLE_OT_brush_edit", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "PARTICLE_OT_brush_edit", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c index f36ebb3715e..7dab98036c6 100644 --- a/source/blender/editors/physics/physics_pointcache.c +++ b/source/blender/editors/physics/physics_pointcache.c @@ -42,6 +42,7 @@ #include "BKE_context.h" #include "BKE_screen.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_particle.h" #include "BKE_pointcache.h" @@ -165,6 +166,8 @@ static PTCacheBaker *ptcache_baker_create(bContext *C, wmOperator *op, bool all) baker->main = CTX_data_main(C); baker->scene = CTX_data_scene(C); + baker->scene_layer = CTX_data_scene_layer(C); + baker->depsgraph = CTX_data_depsgraph(C); baker->bake = RNA_boolean_get(op->ptr, "bake"); baker->render = 0; baker->anim_init = 0; @@ -253,22 +256,23 @@ static void ptcache_bake_cancel(bContext *C, wmOperator *op) static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene= CTX_data_scene(C); - Base *base; + Scene *scene = CTX_data_scene(C); PTCacheID *pid; ListBase pidlist; - for (base=scene->base.first; base; base= base->next) { - BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); + FOREACH_SCENE_OBJECT(scene, ob) + { + BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR); - for (pid=pidlist.first; pid; pid=pid->next) { + for (pid = pidlist.first; pid; pid = pid->next) { ptcache_free_bake(pid->cache); } BLI_freelistN(&pidlist); - WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, base->object); + WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob); } + FOREACH_SCENE_OBJECT_END WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c index 1bfc162a331..13b2943b6e6 100644 --- a/source/blender/editors/physics/rigidbody_constraint.c +++ b/source/blender/editors/physics/rigidbody_constraint.c @@ -38,13 +38,15 @@ #include "DNA_scene_types.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_group.h" #include "BKE_main.h" #include "BKE_report.h" #include "BKE_rigidbody.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -89,10 +91,10 @@ bool ED_rigidbody_constraint_add(Main *bmain, Scene *scene, Object *ob, int type ob->rigidbody_constraint->flag |= RBC_FLAG_NEEDS_VALIDATE; /* add constraint to rigid body constraint group */ - BKE_group_object_add(rbw->constraints, ob, scene, NULL); + BKE_group_object_add(rbw->constraints, ob); - DAG_relations_tag_update(bmain); - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); return true; } @@ -102,10 +104,10 @@ void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob) BKE_rigidbody_remove_constraint(scene, ob); if (rbw) - BKE_group_object_unlink(rbw->constraints, ob, scene, NULL); + BKE_group_object_unlink(rbw->constraints, ob); - DAG_relations_tag_update(bmain); - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } /* ********************************************** */ @@ -117,8 +119,9 @@ static int rigidbody_con_add_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); - Object *ob = (scene) ? OBACT : NULL; + Object *ob = OBACT(sl); int type = RNA_enum_get(op->ptr, "type"); bool changed; @@ -166,11 +169,8 @@ static int rigidbody_con_remove_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Object *ob = (scene) ? OBACT : NULL; - - /* sanity checks */ - if (scene == NULL) - return OPERATOR_CANCELLED; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = OBACT(sl); /* apply to active object */ if (ELEM(NULL, ob, ob->rigidbody_constraint)) { diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index fa80fb5fbc1..3b667520550 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -43,13 +43,15 @@ #include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_group.h" #include "BKE_main.h" #include "BKE_report.h" #include "BKE_rigidbody.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -119,10 +121,10 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE; /* add object to rigid body group */ - BKE_group_object_add(rbw->group, ob, scene, NULL); + BKE_group_object_add(rbw->group, ob); - DAG_relations_tag_update(bmain); - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); return true; } @@ -133,10 +135,10 @@ void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob) BKE_rigidbody_remove_object(scene, ob); if (rbw) - BKE_group_object_unlink(rbw->group, ob, scene, NULL); + BKE_group_object_unlink(rbw->group, ob); - DAG_relations_tag_update(bmain); - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } /* ********************************************** */ @@ -345,7 +347,7 @@ static int rigidbody_objects_shape_change_exec(bContext *C, wmOperator *op) RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr); RNA_enum_set(&ptr, "collision_shape", shape); - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); changed = true; } @@ -527,7 +529,7 @@ static int rigidbody_objects_calc_mass_exec(bContext *C, wmOperator *op) RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr); RNA_float_set(&ptr, "mass", mass); - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); changed = true; } diff --git a/source/blender/editors/render/CMakeLists.txt b/source/blender/editors/render/CMakeLists.txt index ec8bf3e955d..ed2e9747d1c 100644 --- a/source/blender/editors/render/CMakeLists.txt +++ b/source/blender/editors/render/CMakeLists.txt @@ -24,6 +24,8 @@ set(INC ../../blenlib ../../blenloader ../../blentranslation + ../../depsgraph + ../../draw ../../gpu ../../imbuf ../../bmesh diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index d0da35aeb9d..701227091b3 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -54,9 +54,9 @@ #include "BKE_camera.h" #include "BKE_context.h" #include "BKE_colortools.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_node.h" @@ -65,6 +65,9 @@ #include "BKE_sequencer.h" #include "BKE_screen.h" #include "BKE_scene.h" +#include "BKE_workspace.h" + +#include "DEG_depsgraph.h" #include "WM_api.h" #include "WM_types.h" @@ -81,6 +84,7 @@ #include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" +#include "GPU_shader.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -97,9 +101,13 @@ static int render_break(void *rjv); typedef struct RenderJob { Main *main; Scene *scene; + SceneLayer *scene_layer; Scene *current_scene; + /* TODO(sergey): Should not be needed once engine will have own + * depsgraph and copy-on-write will be implemented. + */ + Depsgraph *depsgraph; Render *re; - SceneRenderLayer *srl; struct Object *camera_override; int lay_override; bool v3d_override; @@ -252,7 +260,7 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu /* set callbacks, exported to sequence render too. * Only call in foreground (UI) renders. */ -static void screen_render_scene_layer_set(wmOperator *op, Main *mainp, Scene **scene, SceneRenderLayer **srl) +static void screen_render_scene_layer_set(wmOperator *op, Main *mainp, Scene **scene, SceneLayer **scene_layer) { /* single layer re-render */ if (RNA_struct_property_is_set(op->ptr, "scene")) { @@ -272,14 +280,14 @@ static void screen_render_scene_layer_set(wmOperator *op, Main *mainp, Scene **s } if (RNA_struct_property_is_set(op->ptr, "layer")) { - SceneRenderLayer *rl; + SceneLayer *rl; char rl_name[RE_MAXNAME]; RNA_string_get(op->ptr, "layer", rl_name); - rl = (SceneRenderLayer *)BLI_findstring(&(*scene)->r.layers, rl_name, offsetof(SceneRenderLayer, name)); + rl = (SceneLayer *)BLI_findstring(&(*scene)->render_layers, rl_name, offsetof(SceneLayer, name)); if (rl) - *srl = rl; + *scene_layer = rl; } } @@ -287,7 +295,8 @@ static void screen_render_scene_layer_set(wmOperator *op, Main *mainp, Scene **s static int screen_render_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = NULL; + SceneLayer *scene_layer = NULL; + Depsgraph *depsgraph = CTX_data_depsgraph(C); Render *re; Image *ima; View3D *v3d = CTX_wm_view3d(C); @@ -298,7 +307,10 @@ static int screen_render_exec(bContext *C, wmOperator *op) struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL; /* custom scene and single layer re-render */ - screen_render_scene_layer_set(op, mainp, &scene, &srl); + screen_render_scene_layer_set(op, mainp, &scene, &scene_layer); + if (scene_layer == NULL) { + scene_layer = CTX_data_scene_layer(C); + } if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); @@ -306,6 +318,7 @@ static int screen_render_exec(bContext *C, wmOperator *op) } re = RE_NewSceneRender(scene); + RE_SetDepsgraph(re, CTX_data_depsgraph(C)); lay_override = (v3d && v3d->lay != scene->lay) ? v3d->lay : 0; G.is_break = false; @@ -327,13 +340,13 @@ static int screen_render_exec(bContext *C, wmOperator *op) if (is_animation) RE_BlenderAnim(re, mainp, scene, camera_override, lay_override, scene->r.sfra, scene->r.efra, scene->r.frame_step); else - RE_BlenderFrame(re, mainp, scene, srl, camera_override, lay_override, scene->r.cfra, is_write_still); + RE_BlenderFrame(re, mainp, scene, scene_layer, camera_override, lay_override, scene->r.cfra, is_write_still); BLI_end_threaded_malloc(); RE_SetReports(re, NULL); // no redraw needed, we leave state as we entered it - ED_update_for_newframe(mainp, scene, 1); + ED_update_for_newframe(mainp, scene, scene_layer, depsgraph); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene); @@ -489,8 +502,9 @@ static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr, for (wm = rj->main->wm.first; wm && matched_sa == NULL; wm = wm->id.next) { /* only 1 wm */ wmWindow *win; for (win = wm->windows.first; win && matched_sa == NULL; win = win->next) { - ScrArea *sa; - for (sa = win->screen->areabase.first; sa; sa = sa->next) { + const bScreen *screen = WM_window_get_active_screen(win); + + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { if (sa->spacetype == SPACE_IMAGE) { SpaceImage *sima = sa->spacedata.first; // sa->spacedata might be empty when toggling fullscreen mode. @@ -603,7 +617,7 @@ static void render_startjob(void *rjv, short *stop, short *do_update, float *pro if (rj->anim) RE_BlenderAnim(rj->re, rj->main, rj->scene, rj->camera_override, rj->lay_override, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step); else - RE_BlenderFrame(rj->re, rj->main, rj->scene, rj->srl, rj->camera_override, rj->lay_override, rj->scene->r.cfra, rj->write_still); + RE_BlenderFrame(rj->re, rj->main, rj->scene, rj->scene_layer, rj->camera_override, rj->lay_override, rj->scene->r.cfra, rj->write_still); RE_SetReports(rj->re, NULL); } @@ -616,8 +630,9 @@ static void render_image_restore_layer(RenderJob *rj) for (wm = rj->main->wm.first; wm; wm = wm->id.next) { /* only 1 wm */ wmWindow *win; for (win = wm->windows.first; win; win = win->next) { - ScrArea *sa; - for (sa = win->screen->areabase.first; sa; sa = sa->next) { + const bScreen *screen = WM_window_get_active_screen(win); + + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { if (sa == rj->sa) { if (sa->spacetype == SPACE_IMAGE) { SpaceImage *sima = sa->spacedata.first; @@ -645,7 +660,7 @@ static void render_endjob(void *rjv) if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) { /* possible this fails of loading new file while rendering */ if (G.main->wm.first) { - ED_update_for_newframe(G.main, rj->scene, 1); + ED_update_for_newframe(G.main, rj->scene, rj->scene_layer, rj->depsgraph); } } @@ -655,7 +670,7 @@ static void render_endjob(void *rjv) /* potentially set by caller */ rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE; - if (rj->srl) { + if (rj->scene_layer) { nodeUpdateID(rj->scene->nodetree, &rj->scene->id); WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene); } @@ -685,7 +700,7 @@ static void render_endjob(void *rjv) * engine API, so lets use simple and robust way for now * - sergey - */ - if (rj->scene->r.layers.first != rj->scene->r.layers.last || + if (rj->scene->render_layers.first != rj->scene->render_layers.last || rj->image_outdated) { void *lock; @@ -718,7 +733,7 @@ static void render_endjob(void *rjv) scene->lay_updated = 0; } - DAG_on_visible_update(G.main, false); + DEG_on_visible_update(G.main, false); } } @@ -782,33 +797,46 @@ static void screen_render_cancel(bContext *C, wmOperator *op) WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER); } -static void clean_viewport_memory(Main *bmain, Scene *scene, int renderlay) +static void clean_viewport_memory_base(Base *base) { - Object *object; - Scene *sce_iter; - Base *base; + if ((base->flag & BASE_VISIBLED) == 0) { + return; + } + + Object *object = base->object; - for (object = bmain->object.first; object; object = object->id.next) { - object->id.tag |= LIB_TAG_DOIT; + if (object->id.tag & LIB_TAG_DOIT) { + return; } - for (SETLOOPER(scene, sce_iter, base)) { - if ((base->lay & renderlay) == 0) { - continue; - } - if (RE_allow_render_generic_object(base->object)) { - base->object->id.tag &= ~LIB_TAG_DOIT; - } + object->id.tag &= ~LIB_TAG_DOIT; + if (RE_allow_render_generic_object(object)) { + BKE_object_free_derived_caches(object); } +} + +static void clean_viewport_memory(Main *bmain, Scene *scene) +{ + Scene *sce_iter; + Base *base; + + /* Tag all the available objects. */ + BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true); - for (SETLOOPER(scene, sce_iter, base)) { - object = base->object; - if ((object->id.tag & LIB_TAG_DOIT) == 0) { - continue; + /* Go over all the visible objects. */ + for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { + for (wmWindow *win = wm->windows.first; win; win = win->next) { + WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook); + SceneLayer *scene_layer = BKE_scene_layer_from_workspace_get(scene, workspace); + + for (base = scene_layer->object_bases.first; base; base = base->next) { + clean_viewport_memory_base(base); + } } - object->id.tag &= ~LIB_TAG_DOIT; + } - BKE_object_free_derived_caches(object); + for (SETLOOPER_SET_ONLY(scene, sce_iter, base)) { + clean_viewport_memory_base(base); } } @@ -817,8 +845,8 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even { /* new render clears all callbacks */ Main *mainp; + SceneLayer *scene_layer = NULL; Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = NULL; Render *re; wmJob *wm_job; RenderJob *rj; @@ -885,7 +913,10 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS; /* custom scene and single layer re-render */ - screen_render_scene_layer_set(op, mainp, &scene, &srl); + screen_render_scene_layer_set(op, mainp, &scene, &scene_layer); + if (scene_layer == NULL) { + scene_layer = CTX_data_scene_layer(C); + } if (RNA_struct_property_is_set(op->ptr, "layer")) jobflag |= WM_JOB_SUSPEND; @@ -895,7 +926,9 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even rj->main = mainp; rj->scene = scene; rj->current_scene = rj->scene; - rj->srl = srl; + rj->scene_layer = scene_layer; + /* TODO(sergey): Render engine should be using own depsgraph. */ + rj->depsgraph = CTX_data_depsgraph(C); rj->camera_override = camera_override; rj->lay_override = 0; rj->anim = is_animation; @@ -930,8 +963,6 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even /* Lock the user interface depending on render settings. */ if (scene->r.use_lock_interface) { - int renderlay = rj->lay_override ? rj->lay_override : scene->lay; - WM_set_locked_interface(CTX_wm_manager(C), true); /* Set flag interface need to be unlocked. @@ -945,7 +976,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even rj->interface_locked = true; /* Clean memory used by viewport? */ - clean_viewport_memory(rj->main, scene, renderlay); + clean_viewport_memory(rj->main, scene); } /* setup job */ @@ -971,6 +1002,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even RE_current_scene_update_cb(re, rj, current_scene_update); RE_stats_draw_cb(re, rj, image_renderinfo_cb); RE_progress_cb(re, rj, render_progress_update); + RE_SetDepsgraph(re, CTX_data_depsgraph(C)); rj->re = re; G.is_break = false; @@ -1254,10 +1286,10 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda /* initalize always */ if (use_border) { rdata.mode |= R_BORDER; - RE_InitState(re, NULL, &rdata, NULL, rp->ar->winx, rp->ar->winy, &cliprct); + RE_InitState(re, NULL, &rdata, &rp->scene->render_layers, rp->scene->active_layer, &rp->scene->view_render, NULL, rp->ar->winx, rp->ar->winy, &cliprct); } else - RE_InitState(re, NULL, &rdata, NULL, rp->ar->winx, rp->ar->winy, NULL); + RE_InitState(re, NULL, &rdata, &rp->scene->render_layers, rp->scene->active_layer, &rp->scene->view_render, NULL, rp->ar->winx, rp->ar->winy, NULL); } if (orth) @@ -1545,11 +1577,10 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C) if (force_fallback == false) { if (IMB_colormanagement_setup_glsl_draw(&scene->view_settings, &scene->display_settings, dither, true)) { glEnable(GL_BLEND); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - glPixelZoom(scale_x, scale_y); - glaDrawPixelsTex(xof, yof, rres.rectx, rres.recty, - GL_RGBA, GL_FLOAT, GL_NEAREST, rres.rectf); - glPixelZoom(1.0f, 1.0f); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, xof, yof, rres.rectx, rres.recty, + GL_RGBA, GL_FLOAT, GL_NEAREST, rres.rectf, + scale_x, scale_y, NULL);; glDisable(GL_BLEND); IMB_colormanagement_finish_glsl_draw(); @@ -1566,12 +1597,11 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C) 4, dither, &scene->view_settings, &scene->display_settings); glEnable(GL_BLEND); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - glPixelZoom(scale_x, scale_y); - glaDrawPixelsAuto(xof, yof, rres.rectx, rres.recty, - GL_RGBA, GL_UNSIGNED_BYTE, - GL_NEAREST, display_buffer); - glPixelZoom(1.0f, 1.0f); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, xof, yof, rres.rectx, rres.recty, + GL_RGBA, GL_UNSIGNED_BYTE, + GL_NEAREST, display_buffer, + scale_x, scale_y, NULL); glDisable(GL_BLEND); MEM_freeN(display_buffer); diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index a27026878e1..e0193a0caea 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -55,6 +55,8 @@ #include "BKE_sequencer.h" #include "BKE_writeavi.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -70,9 +72,10 @@ #include "RNA_access.h" #include "RNA_define.h" -#include "GPU_glew.h" #include "GPU_compositing.h" #include "GPU_framebuffer.h" +#include "GPU_glew.h" +#include "GPU_matrix.h" #include "render_intern.h" @@ -91,6 +94,9 @@ typedef struct OGLRender { Main *bmain; Render *re; Scene *scene; + WorkSpace *workspace; + SceneLayer *scene_layer; + Depsgraph *depsgraph; View3D *v3d; RegionView3D *rv3d; @@ -148,17 +154,6 @@ typedef struct OGLRender { #endif } OGLRender; -/* added because v3d is not always valid */ -static unsigned int screen_opengl_layers(OGLRender *oglrender) -{ - if (oglrender->v3d) { - return oglrender->scene->lay | oglrender->v3d->lay; - } - else { - return oglrender->scene->lay; - } -} - static bool screen_opengl_is_multiview(OGLRender *oglrender) { View3D *v3d = oglrender->v3d; @@ -271,9 +266,10 @@ static void screen_opengl_views_setup(OGLRender *oglrender) RE_ReleaseResult(oglrender->re); } -static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) +static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, RenderResult *rr) { Scene *scene = oglrender->scene; + SceneLayer *scene_layer = oglrender->scene_layer; ARegion *ar = oglrender->ar; View3D *v3d = oglrender->v3d; RegionView3D *rv3d = oglrender->rv3d; @@ -286,6 +282,9 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) unsigned char *rect = NULL; const char *viewname = RE_GetActiveRenderView(oglrender->re); ImBuf *ibuf_result = NULL; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); if (oglrender->is_sequencer) { SpaceSeq *sseq = oglrender->sseq; @@ -330,7 +329,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); wmOrtho2(0, sizex, 0, sizey); - glTranslatef(sizex / 2, sizey / 2, 0.0f); + gpuTranslate2f(sizex / 2, sizey / 2); G.f |= G_RENDER_OGL; ED_gpencil_draw_ex(scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ); @@ -355,7 +354,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) if (view_context) { ibuf_view = ED_view3d_draw_offscreen_imbuf( - scene, v3d, ar, sizex, sizey, + &eval_ctx, scene, scene_layer, v3d, ar, sizex, sizey, IB_rect, draw_bgpic, alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname, oglrender->fx, oglrender->ofs, err_out); @@ -367,7 +366,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) } else { ibuf_view = ED_view3d_draw_offscreen_imbuf_simple( - scene, scene->camera, oglrender->sizex, oglrender->sizey, + &eval_ctx, scene, scene_layer, scene->camera, oglrender->sizex, oglrender->sizey, IB_rect, OB_SOLID, false, true, true, alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname, oglrender->fx, oglrender->ofs, err_out); @@ -430,7 +429,7 @@ static void addAlphaOverFloat(float dest[4], const float source[4]) } /* add renderlayer and renderpass for each grease pencil layer for using in composition */ -static void add_gpencil_renderpass(OGLRender *oglrender, RenderResult *rr, RenderView *rv) +static void add_gpencil_renderpass(const bContext *C, OGLRender *oglrender, RenderResult *rr, RenderView *rv) { bGPdata *gpd = oglrender->scene->gpd; Scene *scene = oglrender->scene; @@ -474,7 +473,7 @@ static void add_gpencil_renderpass(OGLRender *oglrender, RenderResult *rr, Rende } /* render this gp layer */ - screen_opengl_render_doit(oglrender, rr); + screen_opengl_render_doit(C, oglrender, rr); /* add RendePass composite */ RenderPass *rp = RE_create_gp_pass(rr, gpl->info, rv->name); @@ -514,7 +513,7 @@ static void add_gpencil_renderpass(OGLRender *oglrender, RenderResult *rr, Rende scene->r.alphamode = oldalphamode; } -static void screen_opengl_render_apply(OGLRender *oglrender) +static void screen_opengl_render_apply(const bContext *C, OGLRender *oglrender) { RenderResult *rr; RenderView *rv; @@ -552,10 +551,10 @@ static void screen_opengl_render_apply(OGLRender *oglrender) /* add grease pencil passes. For sequencer, the render does not include renderpasses * TODO: The sequencer render of grease pencil should be rethought */ if (!oglrender->is_sequencer) { - add_gpencil_renderpass(oglrender, rr, rv); + add_gpencil_renderpass(C, oglrender, rr, rv); } /* render composite */ - screen_opengl_render_doit(oglrender, rr); + screen_opengl_render_doit(C, oglrender, rr); } RE_ReleaseResult(oglrender->re); @@ -571,11 +570,30 @@ static void screen_opengl_render_apply(OGLRender *oglrender) } } +static bool screen_opengl_fullsample_enabled(Scene *scene) +{ + if (scene->r.scemode & R_FULL_SAMPLE) { + return true; + } + else { + /* XXX TODO: + * Technically if the hardware supports MSAA we could keep using Blender 2.7x approach. + * However anti-aliasing without full_sample is not playing well even in 2.7x. + * + * For example, if you enable depth of field, there is aliasing, even if the viewport is fine. + * For 2.8x this is more complicated because so many things rely on shader. + * So until we fix the gpu_framebuffer anti-aliasing suupport we need to force full sample. + */ + return true; + } +} + static bool screen_opengl_render_init(bContext *C, wmOperator *op) { /* new render clears all callbacks */ wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); + WorkSpace *workspace = CTX_wm_workspace(C); Scene *scene = CTX_data_scene(C); ScrArea *prevsa = CTX_wm_area(C); @@ -584,7 +602,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) OGLRender *oglrender; int sizex, sizey; const int samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0; - const bool full_samples = (samples != 0) && (scene->r.scemode & R_FULL_SAMPLE); + const bool full_samples = (samples != 0) && screen_opengl_fullsample_enabled(scene); bool is_view_context = RNA_boolean_get(op->ptr, "view_context"); const bool is_animation = RNA_boolean_get(op->ptr, "animation"); const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer"); @@ -647,6 +665,9 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) oglrender->sizey = sizey; oglrender->bmain = CTX_data_main(C); oglrender->scene = scene; + oglrender->workspace = workspace; + oglrender->scene_layer = CTX_data_scene_layer(C); + oglrender->depsgraph = CTX_data_depsgraph(C); oglrender->cfrao = scene->r.cfra; oglrender->write_still = is_write_still && !is_animation; @@ -682,6 +703,8 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) /* create render */ oglrender->re = RE_NewSceneRender(scene); + ViewRender *view_render = BKE_viewrender_get(scene, workspace); + RE_SetEngineByID(oglrender->re, view_render->engine_id); /* create image and image user */ oglrender->ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); @@ -692,7 +715,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) oglrender->iuser.ok = 1; /* create render result */ - RE_InitState(oglrender->re, NULL, &scene->r, NULL, sizex, sizey, NULL); + RE_InitState(oglrender->re, NULL, &scene->r, &scene->render_layers, scene->active_layer, view_render, NULL, sizex, sizey, NULL); /* create render views */ screen_opengl_views_setup(oglrender); @@ -789,8 +812,10 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender) } if (oglrender->timer) { /* exec will not have a timer */ + Depsgraph *depsgraph = oglrender->depsgraph; + SceneLayer *scene_layer = oglrender->scene_layer; scene->r.cfra = oglrender->cfrao; - BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, screen_opengl_layers(oglrender)); + BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, scene_layer); WM_event_remove_timer(oglrender->wm, oglrender->win, oglrender->timer); } @@ -990,6 +1015,8 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); OGLRender *oglrender = op->customdata; Scene *scene = oglrender->scene; + SceneLayer *scene_layer = oglrender->scene_layer; + Depsgraph *depsgraph = oglrender->depsgraph; char name[FILE_MAX]; bool ok = false; const bool view_context = (oglrender->v3d != NULL); @@ -1000,12 +1027,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) if (CFRA < oglrender->nfra) CFRA++; while (CFRA < oglrender->nfra) { - unsigned int lay = screen_opengl_layers(oglrender); - - if (lay & 0xFF000000) - lay &= 0xFF000000; - - BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, lay); + BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, scene_layer); CFRA++; } @@ -1027,11 +1049,11 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) WM_cursor_time(oglrender->win, scene->r.cfra); - BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, screen_opengl_layers(oglrender)); + BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, scene_layer); if (view_context) { if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera && oglrender->v3d->scenelock) { - /* since BKE_scene_update_for_newframe() is used rather + /* since BKE_scene_graph_update_for_newframe() is used rather * then ED_update_for_newframe() the camera needs to be set */ if (BKE_scene_camera_switch_update(scene)) { oglrender->v3d->camera = scene->camera; @@ -1043,7 +1065,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) } /* render into offscreen buffer */ - screen_opengl_render_apply(oglrender); + screen_opengl_render_apply(C, oglrender); /* save to disk */ rr = RE_AcquireResultRead(oglrender->re); @@ -1093,7 +1115,7 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene); if (anim == 0) { - screen_opengl_render_apply(op->customdata); + screen_opengl_render_apply(C, op->customdata); screen_opengl_render_end(C, op->customdata); return OPERATOR_FINISHED; } @@ -1144,7 +1166,7 @@ static int screen_opengl_render_exec(bContext *C, wmOperator *op) if (!is_animation) { /* same as invoke */ /* render image */ - screen_opengl_render_apply(op->customdata); + screen_opengl_render_apply(C, op->customdata); screen_opengl_render_end(C, op->customdata); return OPERATOR_FINISHED; @@ -1161,7 +1183,7 @@ static int screen_opengl_render_exec(bContext *C, wmOperator *op) } /* no redraw needed, we leave state as we entered it */ -// ED_update_for_newframe(C, 1); +// ED_update_for_newframe(C); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, CTX_data_scene(C)); return OPERATOR_FINISHED; diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 35d772afae7..47eca1ccba3 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -69,6 +69,7 @@ #include "BKE_image.h" #include "BKE_icons.h" #include "BKE_lamp.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_remap.h" #include "BKE_main.h" @@ -78,6 +79,9 @@ #include "BKE_texture.h" #include "BKE_world.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "IMB_thumbs.h" @@ -85,6 +89,7 @@ #include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_shader.h" #include "RE_pipeline.h" #include "RE_engine.h" @@ -94,6 +99,7 @@ #include "ED_datafiles.h" #include "ED_render.h" +#include "ED_screen.h" #ifndef NDEBUG /* Used for database init assert(). */ @@ -167,6 +173,7 @@ typedef struct ShaderPreview { Main *bmain; Main *pr_main; + ViewRender *view_render; } ShaderPreview; typedef struct IconPreviewSize { @@ -181,6 +188,7 @@ typedef struct IconPreview { void *owner; ID *id; ListBase sizes; + ViewRender *view_render; } IconPreview; /* *************************** Preview for buttons *********************** */ @@ -223,7 +231,7 @@ void ED_preview_ensure_dbase(void) static bool check_engine_supports_textures(Scene *scene) { - RenderEngineType *type = RE_engines_find(scene->r.engine); + RenderEngineType *type = RE_engines_find(scene->view_render.engine_id); return type->flag & RE_USE_TEXTURE_PREVIEW; } @@ -269,20 +277,77 @@ static Scene *preview_get_scene(Main *pr_main) return pr_main->scene.first; } +static const char *preview_layer_name(const char pr_type) +{ + switch (pr_type) { + case MA_FLAT: + return "Flat"; + case MA_SPHERE: + return "Sphere"; + case MA_CUBE: + return "Cube"; + case MA_MONKEY: + return "Monkey"; + case MA_SPHERE_A: + return "World Sphere"; + case MA_TEXTURE: + return "Texture"; + case MA_LAMP: + return "Lamp"; + case MA_SKY: + return "Sky"; + case MA_HAIR: + return "Hair"; + case MA_ATMOS: + return "Atmosphere"; + default: + BLI_assert(!"Unknown preview type"); + return ""; + } +} + +static void set_preview_layer(SceneLayer *scene_layer, char pr_type) +{ + LayerCollection *lc; + const char *collection_name = preview_layer_name(pr_type); + + for (lc = scene_layer->layer_collections.first; lc; lc = lc->next) { + if (STREQ(lc->scene_collection->name, collection_name)) { + lc->flag = COLLECTION_VISIBLE | COLLECTION_DISABLED; + BKE_collection_enable(scene_layer, lc); + } + else { + BKE_collection_disable(scene_layer, lc); + } + } +} + +static World *preview_get_localized_world(ShaderPreview *sp, World *world) +{ + if (world == NULL) { + return NULL; + } + if (sp->worldcopy != NULL) { + return sp->worldcopy; + } + sp->worldcopy = localize_world(world); + BLI_addtail(&sp->pr_main->world, sp->worldcopy); + return sp->worldcopy; +} /* call this with a pointer to initialize preview scene */ /* call this with NULL to restore assigned ID pointers in preview scene */ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp) { Scene *sce; - Base *base; Main *pr_main = sp->pr_main; memcpy(pr_main->name, bmain->name, sizeof(pr_main->name)); sce = preview_get_scene(pr_main); if (sce) { - + SceneLayer *scene_layer = BKE_scene_layer_from_scene_get(sce); + /* this flag tells render to not execute depsgraph or ipos etc */ sce->r.scemode |= R_BUTS_PREVIEW; /* set world always back, is used now */ @@ -320,10 +385,10 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty * seems commonly used render engines does not support * such kind of rendering. */ - BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_RENDER, sizeof(sce->r.engine)); + BLI_strncpy(sce->view_render.engine_id, RE_engine_id_BLENDER_RENDER, sizeof(sce->view_render.engine_id)); } else { - BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine)); + BLI_strncpy(sce->view_render.engine_id, scene->view_render.engine_id, sizeof(sce->view_render.engine_id)); } if (id_type == ID_MA) { @@ -357,50 +422,60 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty /* this only works in a specific case where the preview.blend contains * an object starting with 'c' which has a material linked to it (not the obdata) * and that material has a fake shadow texture in the active texture slot */ - for (base = sce->base.first; base; base = base->next) { - if (base->object->id.name[2] == 'c') { - Material *shadmat = give_current_material(base->object, base->object->actcol); + for (Base *base = scene_layer->object_bases.first; base; base = base->next) { + Object *ob = base->object; + if (ob->id.name[2] == 'c') { + Material *shadmat = give_current_material(ob, ob->actcol); if (shadmat) { - if (mat->mode2 & MA_CASTSHADOW) shadmat->septex = 0; - else shadmat->septex |= 1; + if (mat->mode2 & MA_CASTSHADOW) { + shadmat->septex = 0; + } + else { + shadmat->septex |= 1; + } } } } /* turn off bounce lights for volume, * doesn't make much visual difference and slows it down too */ - for (base = sce->base.first; base; base = base->next) { - if (base->object->type == OB_LAMP) { + for (Base *base = scene_layer->object_bases.first; base; base = base->next) { + Object *ob = base->object; + if (ob->type == OB_LAMP) { /* if doesn't match 'Lamp.002' --> main key light */ - if (!STREQ(base->object->id.name + 2, "Lamp.002")) { - if (mat->material_type == MA_TYPE_VOLUME) - base->object->restrictflag |= OB_RESTRICT_RENDER; - else - base->object->restrictflag &= ~OB_RESTRICT_RENDER; + if (!STREQ(ob->id.name + 2, "Lamp.002")) { + if (mat->material_type == MA_TYPE_VOLUME) { + base->flag &= ~BASE_VISIBLED; + } + else { + base->flag |= BASE_VISIBLED; + } } } } } else { /* use current scene world to light sphere */ - if (mat->pr_type == MA_SPHERE_A) - sce->world = scene->world; + if (mat->pr_type == MA_SPHERE_A) { + sce->world = preview_get_localized_world(sp, scene->world); + } } if (sp->pr_method == PR_ICON_RENDER) { if (mat->material_type == MA_TYPE_HALO) { - sce->lay = 1 << MA_FLAT; + set_preview_layer(scene_layer, MA_FLAT); } else { - sce->lay = 1 << MA_SPHERE_A; + set_preview_layer(scene_layer, MA_SPHERE_A); /* same as above, use current scene world to light sphere */ if (BKE_scene_use_new_shading_nodes(scene)) - sce->world = scene->world; + sce->world = preview_get_localized_world(sp, scene->world); } } else { - sce->lay = 1 << mat->pr_type; + set_preview_layer(scene_layer, mat->pr_type); + if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) { /* two previews, they get copied by wmJob */ BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true); @@ -413,7 +488,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty } - for (base = sce->base.first; base; base = base->next) { + for (Base *base = scene_layer->object_bases.first; base; base = base->next) { if (base->object->id.name[2] == 'p') { /* copy over object color, in case material uses it */ copy_v4_v4(base->object->col, sp->col); @@ -427,7 +502,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty (*matar)[actcol] = mat; } else if (base->object->type == OB_LAMP) { - base->object->restrictflag &= ~OB_RESTRICT_RENDER; + base->flag |= BASE_VISIBLED; } } } @@ -440,9 +515,9 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty sp->texcopy = tex; BLI_addtail(&pr_main->tex, tex); } - sce->lay = 1 << MA_TEXTURE; + set_preview_layer(scene_layer, MA_TEXTURE); - for (base = sce->base.first; base; base = base->next) { + for (Base *base = scene_layer->object_bases.first; base; base = base->next) { if (base->object->id.name[2] == 't') { Material *mat = give_current_material(base->object, base->object->actcol); if (mat && mat->mtex[0]) { @@ -481,21 +556,23 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty BLI_addtail(&pr_main->lamp, la); } - sce->lay = 1 << MA_LAMP; - if (!BKE_scene_use_new_shading_nodes(scene)) { if (la && la->type == LA_SUN && (la->sun_effect_type & LA_SUN_EFFECT_SKY)) { - sce->lay = 1 << MA_ATMOS; - sce->world = scene->world; + set_preview_layer(scene_layer, MA_ATMOS); + sce->world = preview_get_localized_world(sp, scene->world); sce->camera = (Object *)BLI_findstring(&pr_main->object, "CameraAtmo", offsetof(ID, name) + 2); } else { sce->world = NULL; sce->camera = (Object *)BLI_findstring(&pr_main->object, "Camera", offsetof(ID, name) + 2); + set_preview_layer(scene_layer, MA_LAMP); } } + else { + set_preview_layer(scene_layer, MA_LAMP); + } - for (base = sce->base.first; base; base = base->next) { + for (Base *base = scene_layer->object_bases.first; base; base = base->next) { if (base->object->id.name[2] == 'p') { if (base->object->type == OB_LAMP) base->object->data = la; @@ -517,7 +594,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty BLI_addtail(&pr_main->world, wrld); } - sce->lay = 1 << MA_SKY; + set_preview_layer(scene_layer, MA_SKY); sce->world = wrld; if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) { @@ -527,6 +604,12 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty } } + Depsgraph *depsgraph = BKE_scene_get_depsgraph(sce, scene_layer, true); + /* TODO(sergey): Use proper flag for tagging here. */ + DEG_graph_id_tag_update(pr_main, depsgraph, &sce->id, 0); + DEG_relations_tag_update(pr_main); + BKE_scene_graph_update_tagged(pr_main->eval_ctx, depsgraph, pr_main, sce, scene_layer); + return sce; } @@ -593,7 +676,9 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, if (re) RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte, 0); - glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, fx, fy, rres.rectx, rres.recty, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect_byte, + 1.0f, 1.0f, NULL); MEM_freeN(rect_byte); @@ -775,7 +860,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs ((Camera *)sce->camera->data)->lens *= (float)sp->sizey / (float)sizex; /* entire cycle for render engine */ - RE_PreviewRender(re, pr_main, sce); + RE_PreviewRender(re, pr_main, sce, sp->view_render); ((Camera *)sce->camera->data)->lens = oldlens; @@ -1022,6 +1107,12 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat *do_update = true; } + else if (idtype == ID_SCR) { + bScreen *screen = (bScreen *)id; + + ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect); + *do_update = true; + } else { /* re-use shader job */ shader_preview_startjob(customdata, stop, do_update); @@ -1096,6 +1187,7 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short /* construct shader preview from image size and previewcustomdata */ sp->scene = ip->scene; + sp->view_render = ip->view_render; sp->owner = ip->owner; sp->sizex = cur_size->sizex; sp->sizey = cur_size->sizey; @@ -1180,6 +1272,7 @@ void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, unsigned int *rec ip.bmain = bmain; ip.scene = scene; + ip.view_render = &scene->view_render; ip.owner = BKE_previewimg_id_ensure(id); ip.id = id; @@ -1213,6 +1306,7 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r /* customdata for preview thread */ ip->bmain = CTX_data_main(C); ip->scene = CTX_data_scene(C); + ip->view_render = &ip->scene->view_render; ip->owner = owner; ip->id = id; @@ -1240,8 +1334,12 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M wmJob *wm_job; ShaderPreview *sp; Scene *scene = CTX_data_scene(C); + WorkSpace *workspace = CTX_wm_workspace(C); short id_type = GS(id->name); - bool use_new_shading = BKE_scene_use_new_shading_nodes(scene); + + /* Use workspace render only for buttons Window, since the other previews are related to the datablock. */ + ViewRender *view_render = (method == PR_BUTS_RENDER) ? BKE_viewrender_get(scene, workspace) : &scene->view_render; + bool use_new_shading = BKE_viewrender_use_new_shading_nodes(view_render); /* Only texture node preview is supported with Cycles. */ if (use_new_shading && method == PR_NODE_RENDER && id_type != ID_TE) { @@ -1264,6 +1362,7 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M sp->parent = parent; sp->slot = slot; sp->bmain = CTX_data_main(C); + sp->view_render = view_render; /* hardcoded preview .blend for cycles/internal, this should be solved * once with custom preview .blend path for external engines */ diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 0a7bca1f490..a98751176fc 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -50,10 +50,10 @@ #include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_font.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_linestyle.h" #include "BKE_main.h" @@ -65,7 +65,8 @@ #include "BKE_world.h" #include "BKE_editmesh.h" - +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" #ifdef WITH_FREESTYLE # include "BKE_freestyle.h" @@ -83,6 +84,7 @@ #include "ED_mesh.h" #include "ED_node.h" #include "ED_render.h" +#include "ED_scene.h" #include "ED_screen.h" #include "RNA_define.h" @@ -153,7 +155,7 @@ static int material_slot_remove_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob); WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob); @@ -219,7 +221,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op)) } } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); return OPERATOR_FINISHED; @@ -359,7 +361,7 @@ static int material_slot_copy_exec(bContext *C, wmOperator *UNUSED(op)) if (ob_iter->totcol == ob->totcol) { ob_iter->actcol = ob->actcol; - DAG_id_tag_update(&ob_iter->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob_iter->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter); } } @@ -424,7 +426,7 @@ static int material_slot_move_exec(bContext *C, wmOperator *op) MEM_freeN(slot_remap); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW | ND_DATA, ob); return OPERATOR_FINISHED; @@ -626,11 +628,12 @@ static int render_layer_add_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - BKE_scene_add_render_layer(scene, NULL); - scene->r.actlay = BLI_listbase_count(&scene->r.layers) - 1; + BKE_scene_layer_add(scene, NULL); + scene->active_layer = BLI_listbase_count(&scene->render_layers) - 1; - DAG_id_tag_update(&scene->id, 0); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + DEG_id_tag_update(&scene->id, 0); + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); return OPERATOR_FINISHED; } @@ -651,15 +654,16 @@ void SCENE_OT_render_layer_add(wmOperatorType *ot) static int render_layer_remove_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - SceneRenderLayer *rl = BLI_findlink(&scene->r.layers, scene->r.actlay); + SceneLayer *scene_layer = BKE_scene_layer_from_scene_get(scene); - if (!BKE_scene_remove_render_layer(CTX_data_main(C), scene, rl)) + if (!ED_scene_render_layer_delete(bmain, scene, scene_layer, NULL)) { return OPERATOR_CANCELLED; + } - DAG_id_tag_update(&scene->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); - + return OPERATOR_FINISHED; } @@ -768,9 +772,9 @@ static int freestyle_active_module_poll(bContext *C) static int freestyle_module_add_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); - BKE_freestyle_module_add(&srl->freestyleConfig); + BKE_freestyle_module_add(&scene_layer->freestyle_config); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); @@ -794,13 +798,13 @@ void SCENE_OT_freestyle_module_add(wmOperatorType *ot) static int freestyle_module_remove_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings); FreestyleModuleConfig *module = ptr.data; - BKE_freestyle_module_delete(&srl->freestyleConfig, module); + BKE_freestyle_module_delete(&scene_layer->freestyle_config, module); - DAG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); return OPERATOR_FINISHED; @@ -824,13 +828,13 @@ void SCENE_OT_freestyle_module_remove(wmOperatorType *ot) static int freestyle_module_move_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings); FreestyleModuleConfig *module = ptr.data; int dir = RNA_enum_get(op->ptr, "direction"); - if (BKE_freestyle_module_move(&srl->freestyleConfig, module, dir)) { - DAG_id_tag_update(&scene->id, 0); + if (BKE_freestyle_module_move(&scene_layer->freestyle_config, module, dir)) { + DEG_id_tag_update(&scene->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); } @@ -866,11 +870,11 @@ static int freestyle_lineset_add_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); - BKE_freestyle_lineset_add(bmain, &srl->freestyleConfig, NULL); + BKE_freestyle_lineset_add(bmain, &scene_layer->freestyle_config, NULL); - DAG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); return OPERATOR_FINISHED; @@ -893,21 +897,21 @@ void SCENE_OT_freestyle_lineset_add(wmOperatorType *ot) static int freestyle_active_lineset_poll(bContext *C) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); - if (!srl) { + if (!scene_layer) { return false; } - return BKE_freestyle_lineset_get_active(&srl->freestyleConfig) != NULL; + return BKE_freestyle_lineset_get_active(&scene_layer->freestyle_config) != NULL; } static int freestyle_lineset_copy_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); - FRS_copy_active_lineset(&srl->freestyleConfig); + FRS_copy_active_lineset(&scene_layer->freestyle_config); return OPERATOR_FINISHED; } @@ -930,11 +934,11 @@ void SCENE_OT_freestyle_lineset_copy(wmOperatorType *ot) static int freestyle_lineset_paste_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); - FRS_paste_active_lineset(&srl->freestyleConfig); + FRS_paste_active_lineset(&scene_layer->freestyle_config); - DAG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); return OPERATOR_FINISHED; @@ -958,11 +962,11 @@ void SCENE_OT_freestyle_lineset_paste(wmOperatorType *ot) static int freestyle_lineset_remove_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); - FRS_delete_active_lineset(&srl->freestyleConfig); + FRS_delete_active_lineset(&scene_layer->freestyle_config); - DAG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); return OPERATOR_FINISHED; @@ -986,11 +990,11 @@ void SCENE_OT_freestyle_lineset_remove(wmOperatorType *ot) static int freestyle_lineset_move_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); int dir = RNA_enum_get(op->ptr, "direction"); - if (FRS_move_active_lineset(&srl->freestyleConfig, dir)) { - DAG_id_tag_update(&scene->id, 0); + if (FRS_move_active_lineset(&scene_layer->freestyle_config, dir)) { + DEG_id_tag_update(&scene->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); } @@ -1026,8 +1030,8 @@ static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&scene_layer->freestyle_config); if (!lineset) { BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to"); @@ -1040,7 +1044,7 @@ static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op) else { lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle"); } - DAG_id_tag_update(&lineset->linestyle->id, 0); + DEG_id_tag_update(&lineset->linestyle->id, 0); WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); return OPERATOR_FINISHED; @@ -1064,8 +1068,8 @@ void SCENE_OT_freestyle_linestyle_new(wmOperatorType *ot) static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&scene_layer->freestyle_config); int type = RNA_enum_get(op->ptr, "type"); if (!freestyle_linestyle_check_report(lineset, op->reports)) { @@ -1076,7 +1080,7 @@ static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type"); return OPERATOR_CANCELLED; } - DAG_id_tag_update(&lineset->linestyle->id, 0); + DEG_id_tag_update(&lineset->linestyle->id, 0); WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); return OPERATOR_FINISHED; @@ -1104,8 +1108,8 @@ void SCENE_OT_freestyle_color_modifier_add(wmOperatorType *ot) static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&scene_layer->freestyle_config); int type = RNA_enum_get(op->ptr, "type"); if (!freestyle_linestyle_check_report(lineset, op->reports)) { @@ -1116,7 +1120,7 @@ static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type"); return OPERATOR_CANCELLED; } - DAG_id_tag_update(&lineset->linestyle->id, 0); + DEG_id_tag_update(&lineset->linestyle->id, 0); WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); return OPERATOR_FINISHED; @@ -1144,8 +1148,8 @@ void SCENE_OT_freestyle_alpha_modifier_add(wmOperatorType *ot) static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&scene_layer->freestyle_config); int type = RNA_enum_get(op->ptr, "type"); if (!freestyle_linestyle_check_report(lineset, op->reports)) { @@ -1156,7 +1160,7 @@ static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type"); return OPERATOR_CANCELLED; } - DAG_id_tag_update(&lineset->linestyle->id, 0); + DEG_id_tag_update(&lineset->linestyle->id, 0); WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); return OPERATOR_FINISHED; @@ -1184,8 +1188,8 @@ void SCENE_OT_freestyle_thickness_modifier_add(wmOperatorType *ot) static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&scene_layer->freestyle_config); int type = RNA_enum_get(op->ptr, "type"); if (!freestyle_linestyle_check_report(lineset, op->reports)) { @@ -1196,7 +1200,7 @@ static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type"); return OPERATOR_CANCELLED; } - DAG_id_tag_update(&lineset->linestyle->id, 0); + DEG_id_tag_update(&lineset->linestyle->id, 0); WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); return OPERATOR_FINISHED; @@ -1237,8 +1241,8 @@ static int freestyle_get_modifier_type(PointerRNA *ptr) static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&scene_layer->freestyle_config); PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier); LineStyleModifier *modifier = ptr.data; @@ -1263,7 +1267,7 @@ static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier"); return OPERATOR_CANCELLED; } - DAG_id_tag_update(&lineset->linestyle->id, 0); + DEG_id_tag_update(&lineset->linestyle->id, 0); WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); return OPERATOR_FINISHED; @@ -1287,8 +1291,8 @@ void SCENE_OT_freestyle_modifier_remove(wmOperatorType *ot) static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&scene_layer->freestyle_config); PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier); LineStyleModifier *modifier = ptr.data; @@ -1313,7 +1317,7 @@ static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier"); return OPERATOR_CANCELLED; } - DAG_id_tag_update(&lineset->linestyle->id, 0); + DEG_id_tag_update(&lineset->linestyle->id, 0); WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); return OPERATOR_FINISHED; @@ -1337,8 +1341,8 @@ void SCENE_OT_freestyle_modifier_copy(wmOperatorType *ot) static int freestyle_modifier_move_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig); + SceneLayer *scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&scene_layer->freestyle_config); PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier); LineStyleModifier *modifier = ptr.data; int dir = RNA_enum_get(op->ptr, "direction"); @@ -1367,7 +1371,7 @@ static int freestyle_modifier_move_exec(bContext *C, wmOperator *op) } if (changed) { - DAG_id_tag_update(&lineset->linestyle->id, 0); + DEG_id_tag_update(&lineset->linestyle->id, 0); WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); } @@ -1488,7 +1492,7 @@ static int texture_slot_move_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(id, 0); + DEG_id_tag_update(id, 0); WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C)); } diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 4e02ff77a31..f38b190b92c 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -38,9 +38,12 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" +#include "DNA_workspace_types.h" #include "DNA_world_types.h" #include "DNA_windowmanager_types.h" +#include "DRW_engine.h" + #include "BLI_listbase.h" #include "BLI_threads.h" #include "BLI_utildefines.h" @@ -48,12 +51,15 @@ #include "BKE_context.h" #include "BKE_DerivedMesh.h" #include "BKE_icons.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_node.h" #include "BKE_paint.h" #include "BKE_scene.h" +#include "BKE_workspace.h" +#include "GPU_lamp.h" #include "GPU_material.h" #include "GPU_buffers.h" @@ -64,6 +70,8 @@ #include "ED_render.h" #include "ED_view3d.h" +#include "WM_api.h" + #include "render_intern.h" // own include extern Material defmaterial; @@ -102,12 +110,14 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated) wm = bmain->wm.first; for (win = wm->windows.first; win; win = win->next) { - bScreen *sc = win->screen; + bScreen *sc = WM_window_get_active_screen(win); ScrArea *sa; ARegion *ar; CTX_wm_window_set(C, win); - + WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook); + ViewRender *view_render = BKE_viewrender_get(win->scene, workspace); + for (sa = sc->areabase.first; sa; sa = sa->next) { if (sa->spacetype != SPACE_VIEW3D) continue; @@ -133,6 +143,16 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated) engine->flag &= ~RE_ENGINE_DO_UPDATE; engine->type->view_update(engine, C); + + } + else if ((RE_engines_find(view_render->engine_id)->flag & RE_USE_LEGACY_PIPELINE) == 0) { + if (updated) { + CTX_wm_screen_set(C, sc); + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, ar); + + DRW_notify_view_update(C); + } } } } @@ -198,7 +218,7 @@ void ED_render_engine_changed(Main *bmain) } /***************************** Updates *********************************** - * ED_render_id_flush_update gets called from DAG_id_tag_update, to do * + * ED_render_id_flush_update gets called from DEG_id_tag_update, to do * * editor level updates when the ID changes. when these ID blocks are in * * the dependency graph, we can get rid of the manual dependency checks */ @@ -295,8 +315,11 @@ static void material_changed(Main *bmain, Material *ma) BKE_icon_changed(BKE_icon_id_ensure(&ma->id)); /* glsl */ - if (ma->gpumaterial.first) - GPU_material_free(&ma->gpumaterial); + if (ma->id.tag & LIB_TAG_ID_RECALC) { + if (!BLI_listbase_is_empty(&ma->gpumaterial)) { + GPU_material_free(&ma->gpumaterial); + } + } /* find node materials using this */ for (parent = bmain->mat.first; parent; parent = parent->id.next) { @@ -344,7 +367,6 @@ static void material_changed(Main *bmain, Material *ma) static void lamp_changed(Main *bmain, Lamp *la) { Object *ob; - Material *ma; /* icons */ BKE_icon_changed(BKE_icon_id_ensure(&la->id)); @@ -354,10 +376,6 @@ static void lamp_changed(Main *bmain, Lamp *la) if (ob->data == la && ob->gpulamp.first) GPU_lamp_free(ob); - for (ma = bmain->mat.first; ma; ma = ma->id.next) - if (ma->gpumaterial.first) - GPU_material_free(&ma->gpumaterial); - if (defmaterial.gpumaterial.first) GPU_material_free(&defmaterial.gpumaterial); } @@ -378,6 +396,7 @@ static void texture_changed(Main *bmain, Tex *tex) Lamp *la; World *wo; Scene *scene; + SceneLayer *sl; Object *ob; bNode *node; bool texture_draw = false; @@ -386,8 +405,11 @@ static void texture_changed(Main *bmain, Tex *tex) BKE_icon_changed(BKE_icon_id_ensure(&tex->id)); /* paint overlays */ - for (scene = bmain->scene.first; scene; scene = scene->id.next) - BKE_paint_invalidate_overlay_tex(scene, tex); + for (scene = bmain->scene.first; scene; scene = scene->id.next) { + for (sl = scene->render_layers.first; sl; sl = sl->next) { + BKE_paint_invalidate_overlay_tex(scene, sl, tex); + } + } /* find materials */ for (ma = bmain->mat.first; ma; ma = ma->id.next) { @@ -468,23 +490,23 @@ static void texture_changed(Main *bmain, Tex *tex) } } -static void world_changed(Main *bmain, World *wo) +static void world_changed(Main *UNUSED(bmain), World *wo) { - Material *ma; - /* icons */ BKE_icon_changed(BKE_icon_id_ensure(&wo->id)); - - /* glsl */ - for (ma = bmain->mat.first; ma; ma = ma->id.next) - if (ma->gpumaterial.first) - GPU_material_free(&ma->gpumaterial); - if (defmaterial.gpumaterial.first) - GPU_material_free(&defmaterial.gpumaterial); - - if (wo->gpumaterial.first) - GPU_material_free(&wo->gpumaterial); + /* XXX temporary flag waiting for depsgraph proper tagging */ + wo->update_flag = 1; + + /* glsl */ + if (wo->id.tag & LIB_TAG_ID_RECALC) { + if (!BLI_listbase_is_empty(&defmaterial.gpumaterial)) { + GPU_material_free(&defmaterial.gpumaterial); + } + if (!BLI_listbase_is_empty(&wo->gpumaterial)) { + GPU_material_free(&wo->gpumaterial); + } + } } static void image_changed(Main *bmain, Image *ima) @@ -503,31 +525,15 @@ static void image_changed(Main *bmain, Image *ima) static void scene_changed(Main *bmain, Scene *scene) { Object *ob; - Material *ma; - World *wo; /* glsl */ for (ob = bmain->object.first; ob; ob = ob->id.next) { - if (ob->gpulamp.first) - GPU_lamp_free(ob); - if (ob->mode & OB_MODE_TEXTURE_PAINT) { BKE_texpaint_slots_refresh_object(scene, ob); BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); GPU_drawobject_free(ob->derivedFinal); } } - - for (ma = bmain->mat.first; ma; ma = ma->id.next) - if (ma->gpumaterial.first) - GPU_material_free(&ma->gpumaterial); - - for (wo = bmain->world.first; wo; wo = wo->id.next) - if (wo->gpumaterial.first) - GPU_material_free(&wo->gpumaterial); - - if (defmaterial.gpumaterial.first) - GPU_material_free(&defmaterial.gpumaterial); } void ED_render_id_flush_update(Main *bmain, ID *id) @@ -572,6 +578,6 @@ void ED_render_internal_init(void) RenderEngineType *ret = RE_engines_find(RE_engine_id_BLENDER_RENDER); ret->view_update = render_view3d_update; - ret->view_draw = render_view3d_draw; + ret->render_to_view = render_view3d_draw; } diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c index c4a9af79ec2..e4bae9d78ea 100644 --- a/source/blender/editors/render/render_view.c +++ b/source/blender/editors/render/render_view.c @@ -90,8 +90,10 @@ static ScrArea *find_area_showing_r_result(bContext *C, Scene *scene, wmWindow * /* find an imagewindow showing render result */ for (*win = wm->windows.first; *win; *win = (*win)->next) { - if ((*win)->screen->scene == scene) { - for (sa = (*win)->screen->areabase.first; sa; sa = sa->next) { + if (WM_window_get_active_scene(*win) == scene) { + const bScreen *screen = WM_window_get_active_screen(*win); + + for (sa = screen->areabase.first; sa; sa = sa->next) { if (sa->spacetype == SPACE_IMAGE) { sima = sa->spacedata.first; if (sima->image && sima->image->type == IMA_TYPE_R_RESULT) @@ -246,7 +248,7 @@ static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(op)) } /* test if we have a temp screen in front */ - if (win->screen->temp) { + if (WM_window_is_temp_screen(win)) { wm_window_lower(win); return OPERATOR_FINISHED; } @@ -292,7 +294,7 @@ static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *e wmWindow *wincur = CTX_wm_window(C); /* test if we have currently a temp screen active */ - if (wincur->screen->temp) { + if (WM_window_is_temp_screen(wincur)) { wm_window_lower(wincur); } else { @@ -301,8 +303,9 @@ static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *e /* is there another window on current scene showing result? */ for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) { - bScreen *sc = win->screen; - if ((sc->temp && ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) || + const bScreen *sc = WM_window_get_active_screen(win); + + if ((WM_window_is_temp_screen(win) && ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) || (win == winshow && winshow != wincur)) { wm_window_raise(win); diff --git a/source/blender/editors/scene/CMakeLists.txt b/source/blender/editors/scene/CMakeLists.txt new file mode 100644 index 00000000000..9fbebbc58cc --- /dev/null +++ b/source/blender/editors/scene/CMakeLists.txt @@ -0,0 +1,44 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Contributor(s): Jacques Beaurain. +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + ../include + ../../blenkernel + ../../blenlib + ../../blentranslation + ../../depsgraph + ../../makesdna + ../../makesrna + ../../windowmanager +) + +set(INC_SYS + +) + +set(SRC + scene_edit.c +) + +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + +blender_add_lib(bf_editor_scene "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c new file mode 100644 index 00000000000..0ff77701eec --- /dev/null +++ b/source/blender/editors/scene/scene_edit.c @@ -0,0 +1,273 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/scene/scene_edit.c + * \ingroup edscene + */ + +#include <stdio.h> + +#include "BLI_compiler_attrs.h" +#include "BLI_listbase.h" + +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_layer.h" +#include "BKE_library_remap.h" +#include "BKE_main.h" +#include "BKE_node.h" +#include "BKE_report.h" +#include "BKE_scene.h" +#include "BKE_workspace.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + +#include "BLT_translation.h" + +#include "DNA_workspace_types.h" + +#include "ED_object.h" +#include "ED_render.h" +#include "ED_scene.h" +#include "ED_screen.h" +#include "ED_util.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + + +Scene *ED_scene_add(Main *bmain, bContext *C, wmWindow *win, eSceneCopyMethod method) +{ + Scene *scene_new; + + if (method == SCE_COPY_NEW) { + scene_new = BKE_scene_add(bmain, DATA_("Scene")); + } + else { /* different kinds of copying */ + Scene *scene_old = WM_window_get_active_scene(win); + + scene_new = BKE_scene_copy(bmain, scene_old, method); + + /* these can't be handled in blenkernel currently, so do them here */ + if (method == SCE_COPY_LINK_DATA) { + ED_object_single_users(bmain, scene_new, false, true); + } + else if (method == SCE_COPY_FULL) { + ED_editors_flush_edits(C, false); + ED_object_single_users(bmain, scene_new, true, true); + } + } + + WM_window_change_active_scene(bmain, C, win, scene_new); + + WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, scene_new); + + return scene_new; +} + +/** + * \note Only call outside of area/region loops + * \return true if successful + */ +bool ED_scene_delete(bContext *C, Main *bmain, wmWindow *win, Scene *scene) +{ + Scene *scene_new; + + if (scene->id.prev) + scene_new = scene->id.prev; + else if (scene->id.next) + scene_new = scene->id.next; + else + return false; + + WM_window_change_active_scene(bmain, C, win, scene_new); + + BKE_libblock_remap(bmain, scene, scene_new, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE); + + id_us_clear_real(&scene->id); + if (scene->id.us == 0) { + BKE_libblock_free(bmain, scene); + } + + return true; +} + +void ED_scene_exit(bContext *C) +{ + ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO); +} + +void ED_scene_changed_update(Main *bmain, bContext *C, Scene *scene_new, const bScreen *active_screen) +{ + /* XXX Just using active scene render-layer for workspace when switching, + * but workspace should remember the last one set. Could store render-layer + * per window-workspace combination (using WorkSpaceDataRelation) */ + SceneLayer *layer_new = BLI_findlink(&scene_new->render_layers, scene_new->active_layer); + Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene_new, layer_new, true); + + CTX_data_scene_set(C, scene_new); + BKE_workspace_render_layer_set(CTX_wm_workspace(C), layer_new); + BKE_scene_set_background(bmain, scene_new); + DEG_graph_relations_update(depsgraph, bmain, scene_new, layer_new); + DEG_on_visible_update(bmain, false); + + ED_screen_update_after_scene_change(active_screen, scene_new, layer_new); + ED_render_engine_changed(bmain); + ED_update_for_newframe(bmain, scene_new, layer_new, depsgraph); + + /* complete redraw */ + WM_event_add_notifier(C, NC_WINDOW, NULL); +} + +static bool scene_render_layer_remove_poll( + const Scene *scene, const SceneLayer *layer) +{ + const int act = BLI_findindex(&scene->render_layers, layer); + + if (act == -1) { + return false; + } + else if ((scene->render_layers.first == scene->render_layers.last) && + (scene->render_layers.first == layer)) + { + /* ensure 1 layer is kept */ + return false; + } + + return true; +} + +static void scene_render_layer_remove_unset_nodetrees(const Main *bmain, Scene *scene, SceneLayer *layer) +{ + int act_layer_index = BLI_findindex(&scene->render_layers, layer); + + for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) { + if (sce->nodetree) { + BKE_nodetree_remove_layer_n(sce->nodetree, scene, act_layer_index); + } + } +} + +bool ED_scene_render_layer_delete( + Main *bmain, Scene *scene, SceneLayer *layer, + ReportList *reports) +{ + if (scene_render_layer_remove_poll(scene, layer) == false) { + if (reports) { + BKE_reportf(reports, RPT_ERROR, "Render layer '%s' could not be removed from scene '%s'", + layer->name, scene->id.name + 2); + } + + return false; + } + + BLI_remlink(&scene->render_layers, layer); + BLI_assert(BLI_listbase_is_empty(&scene->render_layers) == false); + scene->active_layer = 0; + + ED_workspace_render_layer_unset(bmain, layer, scene->render_layers.first); + scene_render_layer_remove_unset_nodetrees(bmain, scene, layer); + + BKE_scene_layer_free(layer); + + DEG_id_tag_update(&scene->id, 0); + DEG_relations_tag_update(bmain); + WM_main_add_notifier(NC_SCENE | ND_LAYER | NA_REMOVED, scene); + + return true; +} + +static int scene_new_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + wmWindow *win = CTX_wm_window(C); + int type = RNA_enum_get(op->ptr, "type"); + + ED_scene_add(bmain, C, win, type); + + return OPERATOR_FINISHED; +} + +static void SCENE_OT_new(wmOperatorType *ot) +{ + static EnumPropertyItem type_items[] = { + {SCE_COPY_NEW, "NEW", 0, "New", "Add new scene"}, + {SCE_COPY_EMPTY, "EMPTY", 0, "Copy Settings", "Make a copy without any objects"}, + {SCE_COPY_LINK_OB, "LINK_OBJECTS", 0, "Link Objects", "Link to the objects from the current scene"}, + {SCE_COPY_LINK_DATA, "LINK_OBJECT_DATA", 0, "Link Object Data", "Copy objects linked to data from the current scene"}, + {SCE_COPY_FULL, "FULL_COPY", 0, "Full Copy", "Make a full copy of the current scene"}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "New Scene"; + ot->description = "Add new scene by type"; + ot->idname = "SCENE_OT_new"; + + /* api callbacks */ + ot->exec = scene_new_exec; + ot->invoke = WM_menu_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", ""); +} + +static int scene_delete_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + + if (ED_scene_delete(C, CTX_data_main(C), CTX_wm_window(C), scene) == false) { + return OPERATOR_CANCELLED; + } + + if (G.debug & G_DEBUG) + printf("scene delete %p\n", scene); + + WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene); + + return OPERATOR_FINISHED; +} + +static void SCENE_OT_delete(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Delete Scene"; + ot->description = "Delete active scene"; + ot->idname = "SCENE_OT_delete"; + + /* api callbacks */ + ot->exec = scene_delete_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +void ED_operatortypes_scene(void) +{ + WM_operatortype_append(SCENE_OT_new); + WM_operatortype_append(SCENE_OT_delete); +} diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt index ed86ffa5e16..02584a4611b 100644 --- a/source/blender/editors/screen/CMakeLists.txt +++ b/source/blender/editors/screen/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC ../../blenfont ../../blenkernel ../../blenlib + ../../blenloader ../../blentranslation ../../bmesh ../../gpu @@ -42,9 +43,12 @@ set(SRC area.c glutil.c screen_context.c + screen_draw.c screen_edit.c screen_ops.c screendump.c + workspace_edit.c + workspace_layout_edit.c screen_intern.h ) diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 9cfaf3b4c1d..315b02cde93 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -57,8 +57,11 @@ #include "ED_screen_types.h" #include "ED_space_api.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" +#include "GPU_draw.h" + #include "BLF_api.h" #include "IMB_imbuf.h" @@ -71,7 +74,7 @@ #include "screen_intern.h" -extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); /* xxx temp */ +extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3, const float color[4]); /* xxx temp */ /* general area and region code */ @@ -89,21 +92,30 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct) glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBegin(GWN_PRIM_LINE_STRIP, 5); + /* right */ - glColor4ub(0, 0, 0, 30); - sdrawline(rect.xmax, rect.ymin, rect.xmax, rect.ymax); + immAttrib4ub(color, 0, 0, 0, 30); + immVertex2f(pos, rect.xmax, rect.ymax); + immVertex2f(pos, rect.xmax, rect.ymin); /* bottom */ - glColor4ub(0, 0, 0, 30); - sdrawline(rect.xmin, rect.ymin, rect.xmax, rect.ymin); + immVertex2f(pos, rect.xmin, rect.ymin); - /* top */ - glColor4ub(255, 255, 255, 30); - sdrawline(rect.xmin, rect.ymax, rect.xmax, rect.ymax); - /* left */ - glColor4ub(255, 255, 255, 30); - sdrawline(rect.xmin, rect.ymin, rect.xmin, rect.ymax); + immAttrib4ub(color, 255, 255, 255, 30); + immVertex2f(pos, rect.xmin, rect.ymax); + + /* top */ + immVertex2f(pos, rect.xmax, rect.ymax); + + immEnd(); + immUnbindProgram(); glDisable(GL_BLEND); } @@ -111,11 +123,11 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct) void ED_region_pixelspace(ARegion *ar) { wmOrtho2_region_pixelspace(ar); - glLoadIdentity(); + gpuLoadIdentity(); } /* only exported for WM */ -void ED_region_do_listen(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *note) +void ED_region_do_listen(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *note, const Scene *scene) { /* generic notes first */ switch (note->category) { @@ -129,15 +141,15 @@ void ED_region_do_listen(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *note } if (ar->type && ar->type->listener) - ar->type->listener(sc, sa, ar, note); + ar->type->listener(sc, sa, ar, note, scene); } /* only exported for WM */ -void ED_area_do_listen(bScreen *sc, ScrArea *sa, wmNotifier *note) +void ED_area_do_listen(bScreen *sc, ScrArea *sa, wmNotifier *note, Scene *scene, WorkSpace *workspace) { /* no generic notes? */ if (sa->type && sa->type->listener) { - sa->type->listener(sc, sa, note); + sa->type->listener(sc, sa, note, scene, workspace); } } @@ -206,15 +218,27 @@ static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, f if (G.debug_value == 1) { rcti click_rect; float icon_size = UI_DPI_ICON_SIZE + 7 * UI_DPI_FAC; - char alpha_debug = 255 * alpha; + unsigned char alpha_debug = 255 * alpha; BLI_rcti_init(&click_rect, x, x + icon_size, y, y + icon_size); - glColor4ub(255, 0, 0, alpha_debug); - fdrawbox(click_rect.xmin, click_rect.ymin, click_rect.xmax, click_rect.ymax); - glColor4ub(0, 255, 255, alpha_debug); - fdrawline(click_rect.xmin, click_rect.ymin, click_rect.xmax, click_rect.ymax); - fdrawline(click_rect.xmin, click_rect.ymax, click_rect.xmax, click_rect.ymin); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immAttrib4ub(color, 255, 0, 0, alpha_debug); + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + imm_draw_box_wire_2d(pos, click_rect.xmin, click_rect.ymin, click_rect.xmax, click_rect.ymax); + + immAttrib4ub(color, 0, 255, 255, alpha_debug); + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, click_rect.xmin, click_rect.ymin); + immVertex2f(pos, click_rect.xmax, click_rect.ymax); + immVertex2f(pos, click_rect.xmin, click_rect.ymax); + immVertex2f(pos, click_rect.xmax, click_rect.ymin); + immEnd(); + + immUnbindProgram(); } } @@ -229,69 +253,96 @@ static void area_draw_azone(short x1, short y1, short x2, short y2) dx = copysign(ceilf(0.3f * abs(dx)), dx); dy = copysign(ceilf(0.3f * abs(dy)), dy); - glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBegin(GWN_PRIM_LINES, 12); + + immAttrib4ub(col, 255, 255, 255, 180); + immVertex2f(pos, x1, y2); + immVertex2f(pos, x2, y1); + + immAttrib4ub(col, 255, 255, 255, 130); + immVertex2f(pos, x1, y2 - dy); + immVertex2f(pos, x2 - dx, y1); + + immAttrib4ub(col, 255, 255, 255, 80); + immVertex2f(pos, x1, y2 - 2 * dy); + immVertex2f(pos, x2 - 2 * dx, y1); - glColor4ub(255, 255, 255, 180); - fdrawline(x1, y2, x2, y1); - glColor4ub(255, 255, 255, 130); - fdrawline(x1, y2 - dy, x2 - dx, y1); - glColor4ub(255, 255, 255, 80); - fdrawline(x1, y2 - 2 * dy, x2 - 2 * dx, y1); - - glColor4ub(0, 0, 0, 210); - fdrawline(x1, y2 + 1, x2 + 1, y1); - glColor4ub(0, 0, 0, 180); - fdrawline(x1, y2 - dy + 1, x2 - dx + 1, y1); - glColor4ub(0, 0, 0, 150); - fdrawline(x1, y2 - 2 * dy + 1, x2 - 2 * dx + 1, y1); + immAttrib4ub(col, 0, 0, 0, 210); + immVertex2f(pos, x1, y2 + 1); + immVertex2f(pos, x2 + 1, y1); + + immAttrib4ub(col, 0, 0, 0, 180); + immVertex2f(pos, x1, y2 - dy + 1); + immVertex2f(pos, x2 - dx + 1, y1); + + immAttrib4ub(col, 0, 0, 0, 150); + immVertex2f(pos, x1, y2 - 2 * dy + 1); + immVertex2f(pos, x2 - 2 * dx + 1, y1); + + immEnd(); + immUnbindProgram(); glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); } static void region_draw_azone_icon(AZone *az) { - GLUquadricObj *qobj = NULL; - short midx = az->x1 + (az->x2 - az->x1) / 2; - short midy = az->y1 + (az->y2 - az->y1) / 2; - - qobj = gluNewQuadric(); - - glPushMatrix(); - glTranslatef(midx, midy, 0.0); - - /* outlined circle */ - glEnable(GL_LINE_SMOOTH); + float midx = az->x1 + (az->x2 - az->x1) * 0.5f; + float midy = az->y1 + (az->y2 - az->y1) * 0.5f; - glColor4f(1.f, 1.f, 1.f, 0.8f); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - gluQuadricDrawStyle(qobj, GLU_FILL); - gluDisk(qobj, 0.0, 4.25f, 16, 1); + /* outlined circle */ + GPU_enable_program_point_size(); /* TODO: make a fixed-size shader to avoid this */ + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f); + immUniform4f("outlineColor", 0.2f, 0.2f, 0.2f, 0.9f); + immUniform1f("outlineWidth", 1.0f); + immUniform1f("size", 9.5f); + immBegin(GWN_PRIM_POINTS, 1); + immVertex2f(pos, midx, midy); + immEnd(); + immUnbindProgram(); + GPU_disable_program_point_size(); - glColor4f(0.2f, 0.2f, 0.2f, 0.9f); - - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - gluDisk(qobj, 0.0, 4.25f, 16, 1); - - glDisable(GL_LINE_SMOOTH); - - glPopMatrix(); - gluDeleteQuadric(qobj); - /* + */ - sdrawline(midx, midy - 2, midx, midy + 3); - sdrawline(midx - 2, midy, midx + 3, midy); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4f(0.2f, 0.2f, 0.2f, 0.9f); + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, midx, midy - 2); + immVertex2f(pos, midx, midy + 3); + immVertex2f(pos, midx - 2, midy); + immVertex2f(pos, midx + 3, midy); + immEnd(); + immUnbindProgram(); } static void draw_azone_plus(float x1, float y1, float x2, float y2) { float width = 0.1f * U.widget_unit; float pad = 0.2f * U.widget_unit; - - glRectf((x1 + x2 - width) * 0.5f, y1 + pad, (x1 + x2 + width) * 0.5f, y2 - pad); - glRectf(x1 + pad, (y1 + y2 - width) * 0.5f, (x1 + x2 - width) * 0.5f, (y1 + y2 + width) * 0.5f); - glRectf((x1 + x2 + width) * 0.5f, (y1 + y2 - width) * 0.5f, x2 - pad, (y1 + y2 + width) * 0.5f); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + glEnable(GL_BLEND); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4f(0.8f, 0.8f, 0.8f, 0.4f); + + immRectf(pos, (x1 + x2 - width) * 0.5f, y1 + pad, (x1 + x2 + width) * 0.5f, y2 - pad); + immRectf(pos, x1 + pad, (y1 + y2 - width) * 0.5f, (x1 + x2 - width) * 0.5f, (y1 + y2 + width) * 0.5f); + immRectf(pos, (x1 + x2 + width) * 0.5f, (y1 + y2 - width) * 0.5f, x2 - pad, (y1 + y2 + width) * 0.5f); + + immUnbindProgram(); + glDisable(GL_BLEND); } static void region_draw_azone_tab_plus(AZone *az) @@ -314,54 +365,41 @@ static void region_draw_azone_tab_plus(AZone *az) break; } - glColor4f(0.05f, 0.05f, 0.05f, 0.4f); - UI_draw_roundbox((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f); - - glEnable(GL_BLEND); + float color[4] = {0.05f, 0.05f, 0.05f, 0.4f}; + UI_draw_roundbox_aa(true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, color); - glColor4f(0.8f, 0.8f, 0.8f, 0.4f); draw_azone_plus((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2); - - glDisable(GL_BLEND); } static void region_draw_azone_tab(AZone *az) { - float col[3]; + float col[4], black[4] = {0.0f, 0.0f, 0.0f, 0.5f}; glEnable(GL_BLEND); UI_GetThemeColor3fv(TH_HEADER, col); - glColor4f(col[0], col[1], col[2], 0.5f); - + col[3] = 0.5f; + /* add code to draw region hidden as 'too small' */ switch (az->edge) { case AE_TOP_TO_BOTTOMRIGHT: - UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT | UI_RB_ALPHA); - - UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f); - glColor4ub(0, 0, 0, 255); - UI_draw_roundbox_unfilled((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f); + UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT); + UI_draw_roundbox_shade_x(true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col); + UI_draw_roundbox_aa(false, (float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f, black); break; case AE_BOTTOM_TO_TOPLEFT: - UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA); - - UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f); - glColor4ub(0, 0, 0, 255); - UI_draw_roundbox_unfilled((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f); + UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT); + UI_draw_roundbox_shade_x(true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col); + UI_draw_roundbox_aa(false, (float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f, black); break; case AE_LEFT_TO_TOPRIGHT: - UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA); - - UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f); - glColor4ub(0, 0, 0, 255); - UI_draw_roundbox_unfilled((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f); + UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT); + UI_draw_roundbox_shade_x(true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col); + UI_draw_roundbox_aa(false, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, black); break; case AE_RIGHT_TO_TOPLEFT: - UI_draw_roundbox_corner_set(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT | UI_RB_ALPHA); - - UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f); - glColor4ub(0, 0, 0, 255); - UI_draw_roundbox_unfilled((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f); + UI_draw_roundbox_corner_set(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT); + UI_draw_roundbox_shade_x(true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col); + UI_draw_roundbox_aa(false, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, black); break; } @@ -372,24 +410,24 @@ static void region_draw_azone_tria(AZone *az) { glEnable(GL_BLEND); //UI_GetThemeColor3fv(TH_HEADER, col); - glColor4f(0.0f, 0.0f, 0.0f, 0.35f); + float color[4] = {0.0f, 0.0f, 0.0f, 0.35f}; /* add code to draw region hidden as 'too small' */ switch (az->edge) { case AE_TOP_TO_BOTTOMRIGHT: - ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y1, (float)(az->x1 + az->x2) / 2, (float)az->y2); + ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y1, (float)(az->x1 + az->x2) / 2, (float)az->y2, color); break; case AE_BOTTOM_TO_TOPLEFT: - ui_draw_anti_tria((float)az->x1, (float)az->y2, (float)az->x2, (float)az->y2, (float)(az->x1 + az->x2) / 2, (float)az->y1); + ui_draw_anti_tria((float)az->x1, (float)az->y2, (float)az->x2, (float)az->y2, (float)(az->x1 + az->x2) / 2, (float)az->y1, color); break; case AE_LEFT_TO_TOPRIGHT: - ui_draw_anti_tria((float)az->x2, (float)az->y1, (float)az->x2, (float)az->y2, (float)az->x1, (float)(az->y1 + az->y2) / 2); + ui_draw_anti_tria((float)az->x2, (float)az->y1, (float)az->x2, (float)az->y2, (float)az->x1, (float)(az->y1 + az->y2) / 2, color); break; case AE_RIGHT_TO_TOPLEFT: - ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x1, (float)az->y2, (float)az->x2, (float)(az->y1 + az->y2) / 2); + ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x1, (float)az->y2, (float)az->x2, (float)(az->y1 + az->y2) / 2, color); break; } @@ -413,8 +451,8 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar) glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glPushMatrix(); - glTranslatef(-ar->winrct.xmin, -ar->winrct.ymin, 0.0f); + gpuPushMatrix(); + gpuTranslate2f(-ar->winrct.xmin, -ar->winrct.ymin); for (az = sa->actionzones.first; az; az = az->next) { /* test if action zone is over this region */ @@ -451,7 +489,7 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar) } } - glPopMatrix(); + gpuPopMatrix(); glDisable(GL_BLEND); } @@ -511,7 +549,7 @@ void ED_region_do_draw(bContext *C, ARegion *ar) UI_ThemeClearColor(TH_HEADER); glClear(GL_COLOR_BUFFER_BIT); - UI_ThemeColor(TH_TEXT); + UI_FontThemeColor(BLF_default(), TH_TEXT); BLF_draw_default(UI_UNIT_X, 0.4f * UI_UNIT_Y, 0.0f, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX); } else if (at->draw) { @@ -528,9 +566,13 @@ void ED_region_do_draw(bContext *C, ARegion *ar) /* for debugging unneeded area redraws and partial redraw */ #if 0 glEnable(GL_BLEND); - glColor4f(drand48(), drand48(), drand48(), 0.1f); - glRectf(ar->drawrct.xmin - ar->winrct.xmin, ar->drawrct.ymin - ar->winrct.ymin, + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4f(drand48(), drand48(), drand48(), 0.1f); + immRectf(pos, ar->drawrct.xmin - ar->winrct.xmin, ar->drawrct.ymin - ar->winrct.ymin, ar->drawrct.xmax - ar->winrct.xmin, ar->drawrct.ymax - ar->winrct.ymin); + immUnbindProgram(); glDisable(GL_BLEND); #endif @@ -539,9 +581,11 @@ void ED_region_do_draw(bContext *C, ARegion *ar) UI_blocklist_free_inactive(C, &ar->uiblocks); if (sa) { + const bScreen *screen = WM_window_get_active_screen(win); + /* disable emboss when the area is full, * unless we need to see division between regions (quad-split for eg) */ - if (((win->screen->state == SCREENFULL) && (ar->alignment == RGN_ALIGN_NONE)) == 0) { + if (((screen->state == SCREENFULL) && (ar->alignment == RGN_ALIGN_NONE)) == 0) { region_draw_emboss(ar, &ar->winrct); } } @@ -655,7 +699,7 @@ void ED_area_headerprint(ScrArea *sa, const char *str) /* ************************************************************ */ -static void area_azone_initialize(wmWindow *win, bScreen *screen, ScrArea *sa) +static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea *sa) { AZone *az; @@ -1311,7 +1355,9 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti * must be minimum '4' */ } else { - if (ELEM(win->screen->state, SCREENNORMAL, SCREENMAXIMIZED)) { + const bScreen *screen = WM_window_get_active_screen(win); + + if (ELEM(screen->state, SCREENNORMAL, SCREENMAXIMIZED)) { region_azone_add(sa, ar, alignment, false); } else { @@ -1435,6 +1481,7 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand /* called in screen_refresh, or screens_init, also area size changes */ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) { + const bScreen *screen = WM_window_get_active_screen(win); ARegion *ar; rcti rect; @@ -1453,7 +1500,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) area_calc_totrct(sa, WM_window_pixels_x(win), WM_window_pixels_y(win)); /* clear all azones, add the area triange widgets */ - area_azone_initialize(win, win->screen, sa); + area_azone_initialize(win, screen, sa); /* region rect sizes */ rect = sa->totrct; @@ -1473,8 +1520,9 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) /* default region handlers */ ed_default_handlers(wm, sa, &ar->handlers, ar->type->keymapflag); /* own handlers */ - if (ar->type->init) + if (ar->type->init) { ar->type->init(wm, ar); + } } else { /* prevent uiblocks to run */ @@ -1968,8 +2016,12 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c /* view should be in pixelspace */ UI_view2d_view_restore(C); glEnable(GL_BLEND); - UI_ThemeColor4((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK); - glRecti(0, 0, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct) + 1); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK); + immRecti(pos, 0, 0, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct) + 1); + immUnbindProgram(); glDisable(GL_BLEND); } else { @@ -2073,22 +2125,37 @@ int ED_area_headersize(void) return (int)(HEADERY * UI_DPI_FAC); } -void ED_region_info_draw(ARegion *ar, const char *text, float fill_color[4], const bool full_redraw) +void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float fill_color[4], const bool full_redraw) { const int header_height = UI_UNIT_Y; uiStyle *style = UI_style_get_dpi(); int fontid = style->widget.uifont_id; GLint scissor[4]; rcti rect; + int num_lines = 0; /* background box */ ED_region_visible_rect(ar, &rect); - rect.ymin = BLI_rcti_size_y(&ar->winrct) - header_height; - /* box fill entire width or just around text */ - if (!full_redraw) - rect.xmax = min_ii(rect.xmax, rect.xmin + BLF_width(fontid, text, BLF_DRAW_STR_DUMMY_MAX) + 1.2f * U.widget_unit); + /* Box fill entire width or just around text. */ + if (!full_redraw) { + const char **text = &text_array[0]; + while (*text) { + rect.xmax = min_ii(rect.xmax, rect.xmin + BLF_width(fontid, *text, BLF_DRAW_STR_DUMMY_MAX) + 1.2f * U.widget_unit); + text++; + num_lines++; + } + } + /* Just count the line number. */ + else { + const char **text = &text_array[0]; + while (*text) { + text++; + num_lines++; + } + } + rect.ymin = BLI_rcti_size_y(&ar->winrct) - header_height * num_lines; rect.ymax = BLI_rcti_size_y(&ar->winrct); /* setup scissor */ @@ -2098,17 +2165,28 @@ void ED_region_info_draw(ARegion *ar, const char *text, float fill_color[4], con glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4fv(fill_color); - glRecti(rect.xmin, rect.ymin, rect.xmax + 1, rect.ymax + 1); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv(fill_color); + immRecti(pos, rect.xmin, rect.ymin, rect.xmax + 1, rect.ymax + 1); + immUnbindProgram(); glDisable(GL_BLEND); /* text */ - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(fontid, TH_TEXT_HI); BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_enable(fontid, BLF_CLIPPING); - BLF_position(fontid, rect.xmin + 0.6f * U.widget_unit, rect.ymin + 0.3f * U.widget_unit, 0.0f); - - BLF_draw(fontid, text, BLF_DRAW_STR_DUMMY_MAX); + int offset = num_lines - 1; + { + const char **text = &text_array[0]; + while (*text) { + BLF_position(fontid, rect.xmin + 0.6f * U.widget_unit, rect.ymin + 0.3f * U.widget_unit + offset * header_height, 0.0f); + BLF_draw(fontid, *text, BLF_DRAW_STR_DUMMY_MAX); + text++; + offset--; + } + } BLF_disable(fontid, BLF_CLIPPING); @@ -2116,6 +2194,11 @@ void ED_region_info_draw(ARegion *ar, const char *text, float fill_color[4], con glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); } +void ED_region_info_draw(ARegion *ar, const char *text, float fill_color[4], const bool full_redraw) +{ + ED_region_info_draw_multiline(ar, (const char *[2]){text, NULL}, fill_color, full_redraw); +} + #define MAX_METADATA_STR 1024 static const char *meta_data_list[] = @@ -2284,11 +2367,11 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame, return; /* find window pixel coordinates of origin */ - glPushMatrix(); + gpuPushMatrix(); /* offset and zoom using ogl */ - glTranslatef(x, y, 0.0f); - glScalef(zoomx, zoomy, 1.0f); + gpuTranslate2f(x, y); + gpuScale2f(zoomx, zoomy); BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f * U.pixelsize, U.dpi); @@ -2298,17 +2381,20 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame, box_y = metadata_box_height_get(ibuf, blf_mono_font, true); if (box_y) { - UI_ThemeColor(TH_METADATA_BG); - /* set up rect */ BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymax, frame->ymax + box_y); /* draw top box */ - glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_METADATA_BG); + immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + immUnbindProgram(); BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_enable(blf_mono_font, BLF_CLIPPING); - UI_ThemeColor(TH_METADATA_TEXT); + UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT); metadata_draw_imbuf(ibuf, &rect, blf_mono_font, true); BLF_disable(blf_mono_font, BLF_CLIPPING); @@ -2320,23 +2406,26 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame, box_y = metadata_box_height_get(ibuf, blf_mono_font, false); if (box_y) { - UI_ThemeColor(TH_METADATA_BG); - /* set up box rect */ BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymin - box_y, frame->ymin); /* draw top box */ - glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_METADATA_BG); + immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + immUnbindProgram(); BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_enable(blf_mono_font, BLF_CLIPPING); - UI_ThemeColor(TH_METADATA_TEXT); + UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT); metadata_draw_imbuf(ibuf, &rect, blf_mono_font, false); BLF_disable(blf_mono_font, BLF_CLIPPING); } - glPopMatrix(); + gpuPopMatrix(); } void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) @@ -2346,11 +2435,16 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) int x1, y1, x2, y2; /* the image is located inside (0, 0), (1, 1) as set by view2d */ - UI_ThemeColorShade(TH_BACK, 20); - UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x1, &y1); UI_view2d_view_to_region(&ar->v2d, 1.0f, 1.0f, &x2, &y2); - glRectf(x1, y1, x2, y2); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColorShade(TH_BACK, 20); + immRectf(pos, x1, y1, x2, y2); + immUnbindProgram(); /* gridsize adapted to zoom level */ gridsize = 0.5f * (zoomx + zoomy); @@ -2370,33 +2464,52 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) } } - /* the fine resolution level */ blendfac = 0.25f * gridsize - floorf(0.25f * gridsize); CLAMP(blendfac, 0.0f, 1.0f); - UI_ThemeColorShade(TH_BACK, (int)(20.0f * (1.0f - blendfac))); - fac = 0.0f; - glBegin(GL_LINES); - while (fac < 1.0f) { - glVertex2f(x1, y1 * (1.0f - fac) + y2 * fac); - glVertex2f(x2, y1 * (1.0f - fac) + y2 * fac); - glVertex2f(x1 * (1.0f - fac) + x2 * fac, y1); - glVertex2f(x1 * (1.0f - fac) + x2 * fac, y2); - fac += gridstep; - } + int count_fine = 1.0f / gridstep; + int count_large = 1.0f / (4.0f * gridstep); - /* the large resolution level */ - UI_ThemeColor(TH_BACK); + if (count_fine > 0) { + GWN_vertformat_clear(format); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBegin(GWN_PRIM_LINES, 4 * count_fine + 4 * count_large); + + float theme_color[3]; + UI_GetThemeColorShade3fv(TH_BACK, (int)(20.0f * (1.0f - blendfac)), theme_color); + immAttrib3fv(color, theme_color); + fac = 0.0f; + + /* the fine resolution level */ + for (int i = 0; i < count_fine; i++) { + immVertex2f(pos, x1, y1 * (1.0f - fac) + y2 * fac); + immVertex2f(pos, x2, y1 * (1.0f - fac) + y2 * fac); + immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y1); + immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y2); + fac += gridstep; + } - fac = 0.0f; - while (fac < 1.0f) { - glVertex2f(x1, y1 * (1.0f - fac) + y2 * fac); - glVertex2f(x2, y1 * (1.0f - fac) + y2 * fac); - glVertex2f(x1 * (1.0f - fac) + x2 * fac, y1); - glVertex2f(x1 * (1.0f - fac) + x2 * fac, y2); - fac += 4.0f * gridstep; + if (count_large > 0) { + UI_GetThemeColor3fv(TH_BACK, theme_color); + immAttrib3fv(color, theme_color); + fac = 0.0f; + + /* the large resolution level */ + for (int i = 0; i < count_large; i++) { + immVertex2f(pos, x1, y1 * (1.0f - fac) + y2 * fac); + immVertex2f(pos, x2, y1 * (1.0f - fac) + y2 * fac); + immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y1); + immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y2); + fac += 4.0f * gridstep; + } + } + + immEnd(); + immUnbindProgram(); } - glEnd(); } /* If the area has overlapping regions, it returns visible rect for Region *ar */ @@ -2433,8 +2546,11 @@ void ED_region_visible_rect(ARegion *ar, rcti *rect) void ED_region_cache_draw_background(const ARegion *ar) { - glColor4ub(128, 128, 255, 64); - glRecti(0, 0, ar->winx, 8 * UI_DPI_FAC); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ub(128, 128, 255, 64); + immRecti(pos, 0, 0, ar->winx, 8 * UI_DPI_FAC); + immUnbindProgram(); } void ED_region_cache_draw_curfra_label(const int framenr, const float x, const float y) @@ -2450,9 +2566,13 @@ void ED_region_cache_draw_curfra_label(const int framenr, const float x, const f BLF_width_and_height(fontid, numstr, sizeof(numstr), &font_dims[0], &font_dims[1]); - glRecti(x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_CFRAME); + immRecti(pos, x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f); + immUnbindProgram(); - UI_ThemeColor(TH_TEXT); + UI_FontThemeColor(fontid, TH_TEXT); BLF_position(fontid, x + 2.0f, y + 2.0f, 0.0f); BLF_draw(fontid, numstr, sizeof(numstr)); } @@ -2460,17 +2580,18 @@ void ED_region_cache_draw_curfra_label(const int framenr, const float x, const f void ED_region_cache_draw_cached_segments(const ARegion *ar, const int num_segments, const int *points, const int sfra, const int efra) { if (num_segments) { - int a; - - glColor4ub(128, 128, 255, 128); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ub(128, 128, 255, 128); - for (a = 0; a < num_segments; a++) { - float x1, x2; + for (int a = 0; a < num_segments; a++) { + float x1 = (float)(points[a * 2] - sfra) / (efra - sfra + 1) * ar->winx; + float x2 = (float)(points[a * 2 + 1] - sfra + 1) / (efra - sfra + 1) * ar->winx; - x1 = (float)(points[a * 2] - sfra) / (efra - sfra + 1) * ar->winx; - x2 = (float)(points[a * 2 + 1] - sfra + 1) / (efra - sfra + 1) * ar->winx; - - glRecti(x1, 0, x2, 8 * UI_DPI_FAC); + immRecti(pos, x1, 0, x2, 8 * UI_DPI_FAC); + /* TODO(merwin): use primitive restart to draw multiple rects more efficiently */ } + + immUnbindProgram(); } } diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 216cbe9d7f4..7ce16efdb97 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -49,133 +49,11 @@ #include "IMB_imbuf_types.h" #include "GPU_basic_shader.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" #include "UI_interface.h" -#ifndef GL_CLAMP_TO_EDGE -#define GL_CLAMP_TO_EDGE 0x812F -#endif - -/* UNUSED */ -#if 0 -void fdrawbezier(float vec[4][3]) -{ - float dist; - float curve_res = 24, spline_step = 0.0f; - - dist = 0.5f * fabsf(vec[0][0] - vec[3][0]); - - /* check direction later, for top sockets */ - vec[1][0] = vec[0][0] + dist; - vec[1][1] = vec[0][1]; - - vec[2][0] = vec[3][0] - dist; - vec[2][1] = vec[3][1]; - /* we can reuse the dist variable here to increment the GL curve eval amount */ - dist = 1.0f / curve_res; - - cpack(0x0); - glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]); - glBegin(GL_LINE_STRIP); - while (spline_step < 1.000001f) { -#if 0 - if (do_shaded) - UI_ThemeColorBlend(th_col1, th_col2, spline_step); -#endif - glEvalCoord1f(spline_step); - spline_step += dist; - } - glEnd(); -} -#endif - -void fdrawline(float x1, float y1, float x2, float y2) -{ - glBegin(GL_LINES); - glVertex2f(x1, y1); - glVertex2f(x2, y2); - glEnd(); -} - -void fdrawbox(float x1, float y1, float x2, float y2) -{ - glBegin(GL_LINE_LOOP); - - glVertex2f(x1, y1); - glVertex2f(x1, y2); - glVertex2f(x2, y2); - glVertex2f(x2, y1); - - glEnd(); -} - -void fdrawcheckerboard(float x1, float y1, float x2, float y2) -{ - unsigned char col1[4] = {40, 40, 40}, col2[4] = {50, 50, 50}; - - glColor3ubv(col1); - glRectf(x1, y1, x2, y2); - glColor3ubv(col2); - - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_CHECKER_8PX); - glRectf(x1, y1, x2, y2); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); -} - -void sdrawline(int x1, int y1, int x2, int y2) -{ - glBegin(GL_LINES); - glVertex2i(x1, y1); - glVertex2i(x2, y2); - glEnd(); -} - -/* UNUSED */ -#if 0 -/* - * x1,y2 - * | \ - * | \ - * | \ - * x1,y1-- x2,y1 - */ - -static void sdrawtripoints(int x1, int y1, int x2, int y2) -{ - glVertex2i(x1, y1); - glVertex2i(x1, y2); - glVertex2i(x2, y1); -} - -void sdrawtri(int x1, int y1, int x2, int y2) -{ - glBegin(GL_LINE_STRIP); - sdrawtripoints(x1, y1, x2, y2); - glEnd(); -} - -void sdrawtrifill(int x1, int y1, int x2, int y2) -{ - glBegin(GL_TRIANGLES); - sdrawtripoints(x1, y1, x2, y2); - glEnd(); -} -#endif - -void sdrawbox(int x1, int y1, int x2, int y2) -{ - glBegin(GL_LINE_LOOP); - - glVertex2i(x1, y1); - glVertex2i(x1, y2); - glVertex2i(x2, y2); - glVertex2i(x2, y1); - - glEnd(); -} - - /* ******************************************** */ void setlinestyle(int nr) @@ -204,122 +82,6 @@ void set_inverted_drawing(int enable) GL_TOGGLE(GL_DITHER, !enable); } -/* UNUSED */ -#if 0 -void sdrawXORline(int x0, int y0, int x1, int y1) -{ - if (x0 == x1 && y0 == y1) return; - - set_inverted_drawing(1); - - glBegin(GL_LINES); - glVertex2i(x0, y0); - glVertex2i(x1, y1); - glEnd(); - - set_inverted_drawing(0); -} - -void sdrawXORline4(int nr, int x0, int y0, int x1, int y1) -{ - static int old[4][2][2]; - static char flags[4] = {0, 0, 0, 0}; - - /* with builtin memory, max 4 lines */ - - set_inverted_drawing(1); - - glBegin(GL_LINES); - if (nr == -1) { /* flush */ - for (nr = 0; nr < 4; nr++) { - if (flags[nr]) { - glVertex2iv(old[nr][0]); - glVertex2iv(old[nr][1]); - flags[nr] = 0; - } - } - } - else { - if (nr >= 0 && nr < 4) { - if (flags[nr]) { - glVertex2iv(old[nr][0]); - glVertex2iv(old[nr][1]); - } - - old[nr][0][0] = x0; - old[nr][0][1] = y0; - old[nr][1][0] = x1; - old[nr][1][1] = y1; - - flags[nr] = 1; - } - - glVertex2i(x0, y0); - glVertex2i(x1, y1); - } - glEnd(); - - set_inverted_drawing(0); -} - -void fdrawXORellipse(float xofs, float yofs, float hw, float hh) -{ - if (hw == 0) return; - - set_inverted_drawing(1); - - glPushMatrix(); - glTranslatef(xofs, yofs, 0.0f); - glScalef(1.0f, hh / hw, 1.0f); - glutil_draw_lined_arc(0.0, M_PI * 2.0, hw, 20); - glPopMatrix(); - - set_inverted_drawing(0); -} - -#endif - -void fdrawXORcirc(float xofs, float yofs, float rad) -{ - set_inverted_drawing(1); - - glPushMatrix(); - glTranslatef(xofs, yofs, 0.0); - glutil_draw_lined_arc(0.0, M_PI * 2.0, rad, 20); - glPopMatrix(); - - set_inverted_drawing(0); -} - -void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments) -{ - int i; - - glBegin(GL_TRIANGLE_FAN); - glVertex2f(0.0, 0.0); - for (i = 0; i < nsegments; i++) { - float t = (float) i / (nsegments - 1); - float cur = start + t * angle; - - glVertex2f(cosf(cur) * radius, sinf(cur) * radius); - } - glEnd(); -} - -void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments) -{ - int i; - - glBegin(GL_LINE_STRIP); - for (i = 0; i < nsegments; i++) { - float t = (float) i / (nsegments - 1); - float cur = start + t * angle; - - glVertex2f(cosf(cur) * radius, sinf(cur) * radius); - } - glEnd(); -} - float glaGetOneFloat(int param) { GLfloat v; @@ -375,24 +137,66 @@ static int get_cached_work_texture(int *r_w, int *r_h) return texid; } -void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, +static void immDrawPixelsTexSetupAttributes(IMMDrawPixelsTexState *state) +{ + Gwn_VertFormat *vert_format = immVertexFormat(); + state->pos = GWN_vertformat_attr_add(vert_format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + state->texco = GWN_vertformat_attr_add(vert_format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); +} + +/* To be used before calling immDrawPixelsTex + * Default shader is GPU_SHADER_2D_IMAGE_COLOR + * You can still set uniforms with : + * GPU_shader_uniform_int(shader, GPU_shader_get_uniform(shader, "name"), 0); + * */ +IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin) +{ + IMMDrawPixelsTexState state; + immDrawPixelsTexSetupAttributes(&state); + + state.shader = GPU_shader_get_builtin_shader(builtin); + + /* Shader will be unbind by immUnbindProgram in immDrawPixelsTexScaled_clipping */ + immBindBuiltinProgram(builtin); + immUniform1i("image", 0); + state.do_shader_unbind = true; + + return state; +} + +/* Use the currently bound shader. + * + * Use immDrawPixelsTexSetup to bind the shader you + * want before calling immDrawPixelsTex. + * + * If using a special shader double check it uses the same + * attributes "pos" "texCoord" and uniform "image". + * + * If color is NULL then use white by default + * + * Be also aware that this function unbinds the shader when + * it's finished. + * */ +void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, + float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY, float clip_min_x, float clip_min_y, - float clip_max_x, float clip_max_y) + float clip_max_x, float clip_max_y, + float xzoom, float yzoom, float color[4]) { unsigned char *uc_rect = (unsigned char *) rect; const float *f_rect = (float *)rect; - float xzoom = glaGetOneFloat(GL_ZOOM_X), yzoom = glaGetOneFloat(GL_ZOOM_Y); int subpart_x, subpart_y, tex_w, tex_h; int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y; int texid = get_cached_work_texture(&tex_w, &tex_h); int components; const bool use_clipping = ((clip_min_x < clip_max_x) && (clip_min_y < clip_max_y)); + float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + + GLint unpack_row_length; + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpack_row_length); - /* Specify the color outside this function, and tex will modulate it. - * This is useful for changing alpha without using glPixelTransferf() - */ glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w); glBindTexture(GL_TEXTURE_2D, texid); @@ -401,18 +205,12 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter); -#if defined(__APPLE__) && 0 - /* [merwin] disable this workaround and see if anyone is affected. If not scrap it! Also at end of this function */ - /* workaround for os x 10.5/10.6 driver bug: http://lists.apple.com/archives/Mac-opengl/2008/Jul/msg00117.html */ - glPixelZoom(1.0f, 1.0f); -#endif - /* setup seamless 2=on, 0=off */ seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0; - + offset_x = tex_w - seamless; offset_y = tex_h - seamless; - + nsubparts_x = (img_w + (offset_x - 1)) / (offset_x); nsubparts_y = (img_h + (offset_y - 1)) / (offset_y); @@ -420,7 +218,7 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, components = 4; else if (format == GL_RGB) components = 3; - else if (ELEM(format, GL_LUMINANCE, GL_ALPHA)) + else if (format == GL_RED) components = 1; else { BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled"); @@ -436,6 +234,7 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, * it's possible to use GL_RGBA16F_ARB */ + /* TODO viewport : remove extension */ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, tex_w, tex_h, 0, format, GL_FLOAT, NULL); } else { @@ -443,6 +242,16 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL); } + unsigned int pos = state->pos, texco = state->texco; + + /* optional */ + /* NOTE: Shader could be null for GLSL OCIO drawing, it is fine, since + * it does not need color. + */ + if (state->shader != NULL && GPU_shader_get_uniform(state->shader, "color") != -1) { + immUniformColor4fv((color) ? color : white); + } + for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) { for (subpart_x = 0; subpart_x < nsubparts_x; subpart_x++) { int remainder_x = img_w - subpart_x * offset_x; @@ -474,7 +283,7 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, if (type == GL_FLOAT) { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]); - + /* add an extra border of pixels so linear looks ok at edges of full image */ if (subpart_w < tex_w) glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); @@ -485,7 +294,7 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, } else { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]); - + if (subpart_w < tex_w) glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); if (subpart_h < tex_h) @@ -494,158 +303,55 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); } - GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR); - glBegin(GL_QUADS); - glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h); - glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom); + immBegin(GWN_PRIM_TRI_FAN, 4); + immAttrib2f(texco, (float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h); + immVertex2f(pos, rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom); - glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h); - glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * yzoom); + immAttrib2f(texco, (float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h); + immVertex2f(pos, rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * yzoom); - glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(subpart_h - offset_top) / tex_h); - glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY); + immAttrib2f(texco, (float)(subpart_w - offset_right) / tex_w, (float)(subpart_h - offset_top) / tex_h); + immVertex2f(pos, rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY); - glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h); - glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY); - glEnd(); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + immAttrib2f(texco, (float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h); + immVertex2f(pos, rast_x + (float)offset_left * xzoom, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY); + immEnd(); } } + if (state->do_shader_unbind) { + immUnbindProgram(); + } + glBindTexture(GL_TEXTURE_2D, 0); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - -#if defined(__APPLE__) && 0 - /* workaround for os x 10.5/10.6 driver bug (above) */ - glPixelZoom(xzoom, yzoom); -#endif + glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_row_length); } -void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, +void immDrawPixelsTexScaled(IMMDrawPixelsTexState *state, + float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, - float scaleX, float scaleY) + float scaleX, float scaleY, float xzoom, float yzoom, float color[4]) { - glaDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, - scaleX, scaleY, 0.0f, 0.0f, 0.0f, 0.0f); + immDrawPixelsTexScaled_clipping(state, x, y, img_w, img_h, format, type, zoomfilter, rect, + scaleX, scaleY, 0.0f, 0.0f, 0.0f, 0.0f, xzoom, yzoom, color); } -void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect) +void immDrawPixelsTex(IMMDrawPixelsTexState *state, + float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, + float xzoom, float yzoom, float color[4]) { - glaDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f, - 0.0f, 0.0f, 0.0f, 0.0f); + immDrawPixelsTexScaled_clipping(state, x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f, + 0.0f, 0.0f, 0.0f, 0.0f, xzoom, yzoom, color); } -void glaDrawPixelsTex_clipping(float x, float y, int img_w, int img_h, +void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state, + float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, - float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y) -{ - glaDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f, - clip_min_x, clip_min_y, clip_max_x, clip_max_y); -} - -void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect) -{ - float xzoom = glaGetOneFloat(GL_ZOOM_X); - float yzoom = glaGetOneFloat(GL_ZOOM_Y); - - /* The pixel space coordinate of the intersection of - * the [zoomed] image with the origin. - */ - float ix = -x / xzoom; - float iy = -y / yzoom; - - /* The maximum pixel amounts the image can be cropped - * at the lower left without exceeding the origin. - */ - int off_x = floor(max_ff(ix, 0.0f)); - int off_y = floor(max_ff(iy, 0.0f)); - - /* The zoomed space coordinate of the raster position - * (starting at the lower left most unclipped pixel). - */ - float rast_x = x + off_x * xzoom; - float rast_y = y + off_y * yzoom; - - GLfloat viewport[4]; - int draw_w, draw_h; - - /* Determine the smallest number of pixels we need to draw - * before the image would go off the upper right corner. - * - * It may seem this is just an optimization but some graphics - * cards (ATI) freak out if there is a large zoom factor and - * a large number of pixels off the screen (probably at some - * level the number of image pixels to draw is getting multiplied - * by the zoom and then clamped). Making sure we draw the - * fewest pixels possible keeps everyone mostly happy (still - * fails if we zoom in on one really huge pixel so that it - * covers the entire screen). - */ - glGetFloatv(GL_VIEWPORT, viewport); - draw_w = min_ii(img_w - off_x, ceil((viewport[2] - rast_x) / xzoom)); - draw_h = min_ii(img_h - off_y, ceil((viewport[3] - rast_y) / yzoom)); - - if (draw_w > 0 && draw_h > 0) { - - int bound_options; - GPU_BASIC_SHADER_DISABLE_AND_STORE(bound_options); - - /* Don't use safe RasterPos (slower) if we can avoid it. */ - if (rast_x >= 0 && rast_y >= 0) { - glRasterPos2f(rast_x, rast_y); - } - else { - glaRasterPosSafe2f(rast_x, rast_y, 0, 0); - } - - glPixelStorei(GL_UNPACK_ROW_LENGTH, row_w); - if (format == GL_LUMINANCE || format == GL_RED) { - if (type == GL_FLOAT) { - const float *f_rect = (float *)rect; - glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y * row_w + off_x)); - } - else if (type == GL_INT || type == GL_UNSIGNED_INT) { - const int *i_rect = (int *)rect; - glDrawPixels(draw_w, draw_h, format, type, i_rect + (off_y * row_w + off_x)); - } - } - else { /* RGBA */ - if (type == GL_FLOAT) { - const float *f_rect = (float *)rect; - glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y * row_w + off_x) * 4); - } - else if (type == GL_UNSIGNED_BYTE) { - unsigned char *uc_rect = (unsigned char *) rect; - glDrawPixels(draw_w, draw_h, format, type, uc_rect + (off_y * row_w + off_x) * 4); - } - } - - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - - GPU_BASIC_SHADER_ENABLE_AND_RESTORE(bound_options); - } -} - -/* uses either DrawPixelsSafe or DrawPixelsTex, based on user defined maximum */ -void glaDrawPixelsAuto_clipping(float x, float y, int img_w, int img_h, - int format, int type, int zoomfilter, void *rect, - float clip_min_x, float clip_min_y, - float clip_max_x, float clip_max_y) + float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y, + float xzoom, float yzoom, float color[4]) { - if (U.image_draw_method != IMAGE_DRAW_METHOD_DRAWPIXELS) { - glColor4f(1.0, 1.0, 1.0, 1.0); - glaDrawPixelsTex_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, - clip_min_x, clip_min_y, clip_max_x, clip_max_y); - } - else { - glaDrawPixelsSafe(x, y, img_w, img_h, img_w, format, type, rect); - } -} - -void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect) -{ - glaDrawPixelsAuto_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, - 0.0f, 0.0f, 0.0f, 0.0f); + immDrawPixelsTexScaled_clipping(state, x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f, + clip_min_x, clip_min_y, clip_max_x, clip_max_y, xzoom, yzoom, color); } /* 2D Drawing Assistance */ @@ -664,15 +370,12 @@ void glaDefine2DArea(rcti *screen_rect) * Programming Guide, Appendix H, Correctness Tips. */ - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0, sc_w, 0.0, sc_h, -1, 1); - glTranslatef(GLA_PIXEL_OFS, GLA_PIXEL_OFS, 0.0); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + gpuOrtho2D(GLA_PIXEL_OFS, sc_w + GLA_PIXEL_OFS, GLA_PIXEL_OFS, sc_h + GLA_PIXEL_OFS); + gpuLoadIdentity(); } +/* TODO(merwin): put the following 2D code to use, or build new 2D code inspired & informd by it */ + #if 0 /* UNUSED */ struct gla2DDrawInfo { @@ -726,8 +429,8 @@ gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect) glGetIntegerv(GL_VIEWPORT, (GLint *)di->orig_vp); glGetIntegerv(GL_SCISSOR_BOX, (GLint *)di->orig_sc); - glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *)di->orig_projmat); - glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)di->orig_viewmat); + gpuGetProjectionMatrix(di->orig_projmat); + gpuGetModelViewMatrix(di->orig_viewmat); di->screen_rect = *screen_rect; if (world_rect) { @@ -778,42 +481,14 @@ void glaEnd2DDraw(gla2DDrawInfo *di) { glViewport(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]); glScissor(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]); - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(di->orig_projmat); - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(di->orig_viewmat); + gpuLoadProjectionMatrix(di->orig_projmat); + gpuLoadMatrix(di->orig_viewmat); MEM_freeN(di); } -#endif +#endif /* UNUSED */ -/* Uses current OpenGL state to get view matrices for gluProject/gluUnProject */ -void bgl_get_mats(bglMats *mats) -{ - const double badvalue = 1.0e-6; - - glGetDoublev(GL_MODELVIEW_MATRIX, mats->modelview); - glGetDoublev(GL_PROJECTION_MATRIX, mats->projection); - glGetIntegerv(GL_VIEWPORT, (GLint *)mats->viewport); - - /* Very strange code here - it seems that certain bad values in the - * modelview matrix can cause gluUnProject to give bad results. */ - if (mats->modelview[0] < badvalue && - mats->modelview[0] > -badvalue) - { - mats->modelview[0] = 0; - } - if (mats->modelview[5] < badvalue && - mats->modelview[5] > -badvalue) - { - mats->modelview[5] = 0; - } - - /* Set up viewport so that gluUnProject will give correct values */ - mats->viewport[0] = 0; - mats->viewport[1] = 0; -} /* *************** glPolygonOffset hack ************* */ @@ -831,8 +506,7 @@ void bglPolygonOffset(float viewdist, float dist) // glPolygonOffset(-1.0, -1.0); /* hack below is to mimic polygon offset */ - glMatrixMode(GL_PROJECTION); - glGetFloatv(GL_PROJECTION_MATRIX, (float *)winmat); + gpuGetProjectionMatrix(winmat); /* dist is from camera to center point */ @@ -863,17 +537,13 @@ void bglPolygonOffset(float viewdist, float dist) winmat[14] -= offs; offset += offs; - - glLoadMatrixf(winmat); - glMatrixMode(GL_MODELVIEW); } else { - glMatrixMode(GL_PROJECTION); winmat[14] += offset; offset = 0.0; - glLoadMatrixf(winmat); - glMatrixMode(GL_MODELVIEW); } + + gpuLoadProjectionMatrix(winmat); } /* **** Color management helper functions for GLSL display/transform ***** */ @@ -883,7 +553,8 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter, ColorManagedViewSettings *view_settings, ColorManagedDisplaySettings *display_settings, float clip_min_x, float clip_min_y, - float clip_max_x, float clip_max_y) + float clip_max_x, float clip_max_y, + float zoom_x, float zoom_y) { bool force_fallback = false; bool need_fallback = true; @@ -902,6 +573,11 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter, if (force_fallback == false) { int ok; + IMMDrawPixelsTexState state = {0}; + /* We want GLSL state to be fully handled by OCIO. */ + state.do_shader_unbind = false; + immDrawPixelsTexSetupAttributes(&state); + if (ibuf->rect_float) { if (ibuf->float_colorspace) { ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, @@ -920,8 +596,6 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter, } if (ok) { - glColor4f(1.0, 1.0, 1.0, 1.0); - if (ibuf->rect_float) { int format = 0; @@ -933,16 +607,20 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter, BLI_assert(!"Incompatible number of channels for GLSL display"); if (format != 0) { - glaDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, format, GL_FLOAT, + immDrawPixelsTex_clipping(&state, + x, y, ibuf->x, ibuf->y, format, GL_FLOAT, zoomfilter, ibuf->rect_float, - clip_min_x, clip_min_y, clip_max_x, clip_max_y); + clip_min_x, clip_min_y, clip_max_x, clip_max_y, + zoom_x, zoom_y, NULL); } } else if (ibuf->rect) { /* ibuf->rect is always RGBA */ - glaDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, + immDrawPixelsTex_clipping(&state, + x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, zoomfilter, ibuf->rect, - clip_min_x, clip_min_y, clip_max_x, clip_max_y); + clip_min_x, clip_min_y, clip_max_x, clip_max_y, + zoom_x, zoom_y, NULL); } IMB_colormanagement_finish_glsl_draw(); @@ -959,9 +637,12 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter, display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle); if (display_buffer) { - glaDrawPixelsAuto_clipping(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, - zoomfilter, display_buffer, - clip_min_x, clip_min_y, clip_max_x, clip_max_y); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex_clipping(&state, + x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, + zoomfilter, display_buffer, + clip_min_x, clip_min_y, clip_max_x, clip_max_y, + zoom_x, zoom_y, NULL); } IMB_display_buffer_release(cache_handle); @@ -970,10 +651,11 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter, void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter, ColorManagedViewSettings *view_settings, - ColorManagedDisplaySettings *display_settings) + ColorManagedDisplaySettings *display_settings, + float zoom_x, float zoom_y) { glaDrawImBuf_glsl_clipping(ibuf, x, y, zoomfilter, view_settings, display_settings, - 0.0f, 0.0f, 0.0f, 0.0f); + 0.0f, 0.0f, 0.0f, 0.0f, zoom_x, zoom_y); } void glaDrawImBuf_glsl_ctx_clipping(const bContext *C, @@ -981,7 +663,8 @@ void glaDrawImBuf_glsl_ctx_clipping(const bContext *C, float x, float y, int zoomfilter, float clip_min_x, float clip_min_y, - float clip_max_x, float clip_max_y) + float clip_max_x, float clip_max_y, + float zoom_x, float zoom_y) { ColorManagedViewSettings *view_settings; ColorManagedDisplaySettings *display_settings; @@ -989,22 +672,19 @@ void glaDrawImBuf_glsl_ctx_clipping(const bContext *C, IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings); glaDrawImBuf_glsl_clipping(ibuf, x, y, zoomfilter, view_settings, display_settings, - clip_min_x, clip_min_y, clip_max_x, clip_max_y); -} - -void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter) -{ - glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, zoomfilter, 0.0f, 0.0f, 0.0f, 0.0f); + clip_min_x, clip_min_y, clip_max_x, clip_max_y, + zoom_x, zoom_y); } -void cpack(unsigned int x) +void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter, + float zoom_x, float zoom_y) { - glColor3ub(( (x) & 0xFF), - (((x) >> 8) & 0xFF), - (((x) >> 16) & 0xFF)); + glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, zoomfilter, 0.0f, 0.0f, 0.0f, 0.0f, zoom_x, zoom_y); } -void glaDrawBorderCorners(const rcti *border, float zoomx, float zoomy) +/* don't move to GPU_immediate_util.h because this uses user-prefs + * and isn't very low level */ +void immDrawBorderCorners(unsigned int pos, const rcti *border, float zoomx, float zoomy) { float delta_x = 4.0f * UI_DPI_FAC / zoomx; float delta_y = 4.0f * UI_DPI_FAC / zoomy; @@ -1013,30 +693,30 @@ void glaDrawBorderCorners(const rcti *border, float zoomx, float zoomy) delta_y = min_ff(delta_y, border->ymax - border->ymin); /* left bottom corner */ - glBegin(GL_LINE_STRIP); - glVertex2f(border->xmin, border->ymin + delta_y); - glVertex2f(border->xmin, border->ymin); - glVertex2f(border->xmin + delta_x, border->ymin); - glEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, border->xmin, border->ymin + delta_y); + immVertex2f(pos, border->xmin, border->ymin); + immVertex2f(pos, border->xmin + delta_x, border->ymin); + immEnd(); /* left top corner */ - glBegin(GL_LINE_STRIP); - glVertex2f(border->xmin, border->ymax - delta_y); - glVertex2f(border->xmin, border->ymax); - glVertex2f(border->xmin + delta_x, border->ymax); - glEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, border->xmin, border->ymax - delta_y); + immVertex2f(pos, border->xmin, border->ymax); + immVertex2f(pos, border->xmin + delta_x, border->ymax); + immEnd(); /* right bottom corner */ - glBegin(GL_LINE_STRIP); - glVertex2f(border->xmax - delta_x, border->ymin); - glVertex2f(border->xmax, border->ymin); - glVertex2f(border->xmax, border->ymin + delta_y); - glEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, border->xmax - delta_x, border->ymin); + immVertex2f(pos, border->xmax, border->ymin); + immVertex2f(pos, border->xmax, border->ymin + delta_y); + immEnd(); /* right top corner */ - glBegin(GL_LINE_STRIP); - glVertex2f(border->xmax - delta_x, border->ymax); - glVertex2f(border->xmax, border->ymax); - glVertex2f(border->xmax, border->ymax - delta_y); - glEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2f(pos, border->xmax - delta_x, border->ymax); + immVertex2f(pos, border->xmax, border->ymax); + immVertex2f(pos, border->xmax, border->ymax - delta_y); + immEnd(); } diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 1190423e2f1..b8575b2da2a 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -38,6 +38,7 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_windowmanager_types.h" +#include "DNA_workspace_types.h" #include "BLI_utildefines.h" @@ -47,8 +48,10 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_gpencil.h" +#include "BKE_layer.h" #include "BKE_screen.h" #include "BKE_sequencer.h" +#include "BKE_workspace.h" #include "RNA_access.h" @@ -61,20 +64,8 @@ #include "screen_intern.h" -static unsigned int context_layers(bScreen *sc, Scene *scene, ScrArea *sa_ctx) -{ - /* needed for 'USE_ALLSELECT' define, otherwise we end up editing off-screen layers. */ - if (sc && sa_ctx && (sa_ctx->spacetype == SPACE_BUTS)) { - const unsigned int lay = BKE_screen_view3d_layer_all(sc); - if (lay) { - return lay; - } - } - return scene->lay; -} - const char *screen_context_dir[] = { - "scene", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases", + "scene", "render_layer", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases", "selected_objects", "selected_bases", "editable_objects", "editable_bases", "selected_editable_objects", "selected_editable_bases", @@ -93,20 +84,14 @@ const char *screen_context_dir[] = { int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result) { + wmWindow *win = CTX_wm_window(C); bScreen *sc = CTX_wm_screen(C); ScrArea *sa = CTX_wm_area(C); - Scene *scene = sc->scene; - Base *base; - -#if 0 /* Using the context breaks adding objects in the UI. Need to find out why - campbell */ - Object *obact = CTX_data_active_object(C); - Object *obedit = CTX_data_edit_object(C); - base = CTX_data_active_base(C); -#else + Scene *scene = WM_window_get_active_scene(win); + WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook); + SceneLayer *sl = BKE_scene_layer_from_workspace_get(scene, workspace); Object *obedit = scene->obedit; - Object *obact = OBACT; - base = BASACT; -#endif + Object *obact = sl->basact ? sl->basact->object : NULL; if (CTX_data_dir(member)) { CTX_data_dir_set(result, screen_context_dir); @@ -116,84 +101,100 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult CTX_data_id_pointer_set(result, &scene->id); return 1; } - else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool visible_objects = CTX_data_equals(member, "visible_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) { - if (visible_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + else if (CTX_data_equals(member, "visible_objects")) { + FOREACH_VISIBLE_OBJECT(sl, ob) + { + CTX_data_id_list_add(result, &ob->id); + } + FOREACH_VISIBLE_BASE_END + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selectable_objects")) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if (((base->flag & BASE_VISIBLED) != 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + CTX_data_id_list_add(result, &base->object->id); } } CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool selectable_objects = CTX_data_equals(member, "selectable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (base->lay & lay) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) { - if (selectable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } + else if (CTX_data_equals(member, "selected_objects")) { + FOREACH_SELECTED_OBJECT(sl, ob) + { + CTX_data_id_list_add(result, &ob->id); + } + FOREACH_SELECTED_OBJECT_END + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selected_editable_objects")) { + FOREACH_SELECTED_OBJECT(sl, ob) + { + if (0 == BKE_object_is_libdata(ob)) { + CTX_data_id_list_add(result, &ob->id); } } + FOREACH_SELECTED_OBJECT_END CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool selected_objects = CTX_data_equals(member, "selected_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if (selected_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + else if (CTX_data_equals(member, "editable_objects")) { + /* Visible + Editable, but not necessarily selected */ + FOREACH_VISIBLE_OBJECT(sl, ob) + { + if (0 == BKE_object_is_libdata(ob)) { + CTX_data_id_list_add(result, &ob->id); } } + FOREACH_VISIBLE_OBJECT_END CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (0 == BKE_object_is_libdata(base->object)) { - if (selected_editable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } + else if ( CTX_data_equals(member, "visible_bases")) { + FOREACH_VISIBLE_BASE(sl, base) + { + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + } + FOREACH_VISIBLE_BASE_END + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selectable_bases")) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTABLED) != 0) { + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + } + } + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selected_bases")) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTED) != 0) { + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + } + } + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selected_editable_bases")) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTED) != 0) { + if (0 == BKE_object_is_libdata(base->object)) { + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); } } } CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "editable_objects") || CTX_data_equals(member, "editable_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool editable_objects = CTX_data_equals(member, "editable_objects"); - + else if (CTX_data_equals(member, "editable_bases")) { /* Visible + Editable, but not necessarily selected */ - for (base = scene->base.first; base; base = base->next) { - if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { if (0 == BKE_object_is_libdata(base->object)) { - if (editable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); } } } @@ -345,8 +346,8 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } } else if (CTX_data_equals(member, "active_base")) { - if (base) - CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, base); + if (sl->basact) + CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, sl->basact); return 1; } diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c new file mode 100644 index 00000000000..5690076fedb --- /dev/null +++ b/source/blender/editors/screen/screen_draw.c @@ -0,0 +1,496 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/screen/screen_draw.c + * \ingroup edscr + */ + +#include "ED_screen.h" + +#include "GPU_framebuffer.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "screen_intern.h" + + +/** + * Draw horizontal shape visualizing future joining (left as well right direction of future joining). + */ +static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos) +{ + vec2f points[10]; + short i; + float w, h; + float width = sa->v3->vec.x - sa->v1->vec.x; + float height = sa->v3->vec.y - sa->v1->vec.y; + + if (height < width) { + h = height / 8; + w = height / 4; + } + else { + h = width / 8; + w = width / 4; + } + + points[0].x = sa->v1->vec.x; + points[0].y = sa->v1->vec.y + height / 2; + + points[1].x = sa->v1->vec.x; + points[1].y = sa->v1->vec.y; + + points[2].x = sa->v4->vec.x - w; + points[2].y = sa->v4->vec.y; + + points[3].x = sa->v4->vec.x - w; + points[3].y = sa->v4->vec.y + height / 2 - 2 * h; + + points[4].x = sa->v4->vec.x - 2 * w; + points[4].y = sa->v4->vec.y + height / 2; + + points[5].x = sa->v4->vec.x - w; + points[5].y = sa->v4->vec.y + height / 2 + 2 * h; + + points[6].x = sa->v3->vec.x - w; + points[6].y = sa->v3->vec.y; + + points[7].x = sa->v2->vec.x; + points[7].y = sa->v2->vec.y; + + points[8].x = sa->v4->vec.x; + points[8].y = sa->v4->vec.y + height / 2 - h; + + points[9].x = sa->v4->vec.x; + points[9].y = sa->v4->vec.y + height / 2 + h; + + if (dir == 'l') { + /* when direction is left, then we flip direction of arrow */ + float cx = sa->v1->vec.x + width; + for (i = 0; i < 10; i++) { + points[i].x -= cx; + points[i].x = -points[i].x; + points[i].x += sa->v1->vec.x; + } + } + + immBegin(GWN_PRIM_TRI_FAN, 5); + + for (i = 0; i < 5; i++) { + immVertex2f(pos, points[i].x, points[i].y); + } + + immEnd(); + + immBegin(GWN_PRIM_TRI_FAN, 5); + + for (i = 4; i < 8; i++) { + immVertex2f(pos, points[i].x, points[i].y); + } + + immVertex2f(pos, points[0].x, points[0].y); + immEnd(); + + immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y); + immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y); +} + +/** + * Draw vertical shape visualizing future joining (up/down direction). + */ +static void draw_vertical_join_shape(ScrArea *sa, char dir, unsigned int pos) +{ + vec2f points[10]; + short i; + float w, h; + float width = sa->v3->vec.x - sa->v1->vec.x; + float height = sa->v3->vec.y - sa->v1->vec.y; + + if (height < width) { + h = height / 4; + w = height / 8; + } + else { + h = width / 4; + w = width / 8; + } + + points[0].x = sa->v1->vec.x + width / 2; + points[0].y = sa->v3->vec.y; + + points[1].x = sa->v2->vec.x; + points[1].y = sa->v2->vec.y; + + points[2].x = sa->v1->vec.x; + points[2].y = sa->v1->vec.y + h; + + points[3].x = sa->v1->vec.x + width / 2 - 2 * w; + points[3].y = sa->v1->vec.y + h; + + points[4].x = sa->v1->vec.x + width / 2; + points[4].y = sa->v1->vec.y + 2 * h; + + points[5].x = sa->v1->vec.x + width / 2 + 2 * w; + points[5].y = sa->v1->vec.y + h; + + points[6].x = sa->v4->vec.x; + points[6].y = sa->v4->vec.y + h; + + points[7].x = sa->v3->vec.x; + points[7].y = sa->v3->vec.y; + + points[8].x = sa->v1->vec.x + width / 2 - w; + points[8].y = sa->v1->vec.y; + + points[9].x = sa->v1->vec.x + width / 2 + w; + points[9].y = sa->v1->vec.y; + + if (dir == 'u') { + /* when direction is up, then we flip direction of arrow */ + float cy = sa->v1->vec.y + height; + for (i = 0; i < 10; i++) { + points[i].y -= cy; + points[i].y = -points[i].y; + points[i].y += sa->v1->vec.y; + } + } + + immBegin(GWN_PRIM_TRI_FAN, 5); + + for (i = 0; i < 5; i++) { + immVertex2f(pos, points[i].x, points[i].y); + } + + immEnd(); + + immBegin(GWN_PRIM_TRI_FAN, 5); + + for (i = 4; i < 8; i++) { + immVertex2f(pos, points[i].x, points[i].y); + } + + immVertex2f(pos, points[0].x, points[0].y); + immEnd(); + + immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y); + immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y); +} + +/** + * Draw join shape due to direction of joining. + */ +static void draw_join_shape(ScrArea *sa, char dir, unsigned int pos) +{ + if (dir == 'u' || dir == 'd') { + draw_vertical_join_shape(sa, dir, pos); + } + else { + draw_horizontal_join_shape(sa, dir, pos); + } +} + +/** + * Draw screen area darker with arrow (visualization of future joining). + */ +static void scrarea_draw_shape_dark(ScrArea *sa, char dir, unsigned int pos) +{ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + immUniformColor4ub(0, 0, 0, 50); + + draw_join_shape(sa, dir, pos); +} + +/** + * Draw screen area ligher with arrow shape ("eraser" of previous dark shape). + */ +static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir), unsigned int pos) +{ + glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA); + /* value 181 was hardly computed: 181~105 */ + immUniformColor4ub(255, 255, 255, 50); + /* draw_join_shape(sa, dir); */ + + immRectf(pos, sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y); +} + +static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, short x2, short y2, unsigned int pos) +{ + int count = 0; + + if (x2 < sizex - 1) count += 2; + if (x1 > 0) count += 2; + if (y2 < sizey - 1) count += 2; + if (y1 > 0) count += 2; + + if (count == 0) { + return; + } + + immBegin(GWN_PRIM_LINES, count); + + /* right border area */ + if (x2 < sizex - 1) { + immVertex2f(pos, x2, y1); + immVertex2f(pos, x2, y2); + } + + /* left border area */ + if (x1 > 0) { /* otherwise it draws the emboss of window over */ + immVertex2f(pos, x1, y1); + immVertex2f(pos, x1, y2); + } + + /* top border area */ + if (y2 < sizey - 1) { + immVertex2f(pos, x1, y2); + immVertex2f(pos, x2, y2); + } + + /* bottom border area */ + if (y1 > 0) { + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y1); + } + + immEnd(); +} + +/** + * \brief Screen edges drawing. + */ +static void drawscredge_area(ScrArea *sa, int sizex, int sizey, unsigned int pos) +{ + short x1 = sa->v1->vec.x; + short y1 = sa->v1->vec.y; + short x2 = sa->v3->vec.x; + short y2 = sa->v3->vec.y; + + drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, pos); +} + +/** + * Only for edge lines between areas, and the blended join arrows. + */ +void ED_screen_draw(wmWindow *win) +{ + bScreen *screen = WM_window_get_active_screen(win); + const int winsize_x = WM_window_pixels_x(win); + const int winsize_y = WM_window_pixels_y(win); + + ScrArea *sa; + ScrArea *sa1 = NULL; + ScrArea *sa2 = NULL; + ScrArea *sa3 = NULL; + + wmSubWindowSet(win, screen->mainwin); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* Note: first loop only draws if U.pixelsize > 1, skip otherwise */ + if (U.pixelsize > 1.0f) { + /* FIXME: doesn't our glLineWidth already scale by U.pixelsize? */ + glLineWidth((2.0f * U.pixelsize) - 1); + immUniformColor3ub(0x50, 0x50, 0x50); + + for (sa = screen->areabase.first; sa; sa = sa->next) { + drawscredge_area(sa, winsize_x, winsize_y, pos); + } + } + + glLineWidth(1); + immUniformColor3ub(0, 0, 0); + + for (sa = screen->areabase.first; sa; sa = sa->next) { + drawscredge_area(sa, winsize_x, winsize_y, pos); + + /* gather area split/join info */ + if (sa->flag & AREA_FLAG_DRAWJOINFROM) sa1 = sa; + if (sa->flag & AREA_FLAG_DRAWJOINTO) sa2 = sa; + if (sa->flag & (AREA_FLAG_DRAWSPLIT_H | AREA_FLAG_DRAWSPLIT_V)) sa3 = sa; + } + + /* blended join arrow */ + if (sa1 && sa2) { + int dir = area_getorientation(sa1, sa2); + int dira = -1; + if (dir != -1) { + switch (dir) { + case 0: /* W */ + dir = 'r'; + dira = 'l'; + break; + case 1: /* N */ + dir = 'd'; + dira = 'u'; + break; + case 2: /* E */ + dir = 'l'; + dira = 'r'; + break; + case 3: /* S */ + dir = 'u'; + dira = 'd'; + break; + } + } + + glEnable(GL_BLEND); + + scrarea_draw_shape_dark(sa2, dir, pos); + scrarea_draw_shape_light(sa1, dira, pos); + + glDisable(GL_BLEND); + } + + /* splitpoint */ + if (sa3) { + glEnable(GL_BLEND); + immUniformColor4ub(255, 255, 255, 100); + + immBegin(GWN_PRIM_LINES, 2); + + if (sa3->flag & AREA_FLAG_DRAWSPLIT_H) { + immVertex2f(pos, sa3->totrct.xmin, win->eventstate->y); + immVertex2f(pos, sa3->totrct.xmax, win->eventstate->y); + + immEnd(); + + immUniformColor4ub(0, 0, 0, 100); + + immBegin(GWN_PRIM_LINES, 2); + + immVertex2f(pos, sa3->totrct.xmin, win->eventstate->y + 1); + immVertex2f(pos, sa3->totrct.xmax, win->eventstate->y + 1); + } + else { + immVertex2f(pos, win->eventstate->x, sa3->totrct.ymin); + immVertex2f(pos, win->eventstate->x, sa3->totrct.ymax); + + immEnd(); + + immUniformColor4ub(0, 0, 0, 100); + + immBegin(GWN_PRIM_LINES, 2); + + immVertex2f(pos, win->eventstate->x + 1, sa3->totrct.ymin); + immVertex2f(pos, win->eventstate->x + 1, sa3->totrct.ymax); + } + + immEnd(); + + glDisable(GL_BLEND); + } + + immUnbindProgram(); + + screen->do_draw = false; +} + + +/* -------------------------------------------------------------------- */ +/* Screen Thumbnail Preview */ + +/** + * Calculates a scale factor to squash the preview for \a screen into a rectangle of given size and aspect. + */ +static void screen_preview_scale_get( + const bScreen *screen, float size_x, float size_y, + const float asp[2], + float r_scale[2]) +{ + float max_x = 0, max_y = 0; + + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + max_x = MAX2(max_x, sa->totrct.xmax); + max_y = MAX2(max_y, sa->totrct.ymax); + } + r_scale[0] = (size_x * asp[0]) / max_x; + r_scale[1] = (size_y * asp[1]) / max_y; +} + +static void screen_preview_draw_areas(const bScreen *screen, const float scale[2], const float col[4], + const float ofs_between_areas) +{ + const float ofs_h = ofs_between_areas * 0.5f; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv(col); + + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + rctf rect = { + .xmin = sa->totrct.xmin * scale[0] + ofs_h, + .xmax = sa->totrct.xmax * scale[0] - ofs_h, + .ymin = sa->totrct.ymin * scale[1] + ofs_h, + .ymax = sa->totrct.ymax * scale[1] - ofs_h + }; + + immBegin(GWN_PRIM_TRI_FAN, 4); + immVertex2f(pos, rect.xmin, rect.ymin); + immVertex2f(pos, rect.xmax, rect.ymin); + immVertex2f(pos, rect.xmax, rect.ymax); + immVertex2f(pos, rect.xmin, rect.ymax); + immEnd(); + } + + immUnbindProgram(); +} + +static void screen_preview_draw(const bScreen *screen, int size_x, int size_y) +{ + const float asp[2] = {1.0f, 0.8f}; /* square previews look a bit ugly */ + /* could use theme color (tui.wcol_menu_item.text), but then we'd need to regenerate all previews when changing */ + const float col[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + float scale[2]; + + wmOrtho2(0.0f, size_x, 0.0f, size_y); + /* center */ + gpuPushMatrix(); + gpuTranslate2f(size_x * (1.0f - asp[0]) * 0.5f, size_y * (1.0f - asp[1]) * 0.5f); + + screen_preview_scale_get(screen, size_x, size_y, asp, scale); + screen_preview_draw_areas(screen, scale, col, 1.5f); + + gpuPopMatrix(); +} + +/** + * Render the preview for a screen layout in \a screen. + */ +void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, unsigned int *r_rect) +{ + char err_out[256] = "unknown"; + GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, 0, err_out); + + GPU_offscreen_bind(offscreen, true); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + screen_preview_draw(screen, size_x, size_y); + + GPU_offscreen_read_pixels(offscreen, GL_UNSIGNED_BYTE, r_rect); + GPU_offscreen_unbind(offscreen, true); + + GPU_offscreen_free(offscreen); +} diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 8f1132dc1e5..dfe2942868f 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -34,6 +34,7 @@ #include "MEM_guardedalloc.h" #include "DNA_scene_types.h" +#include "DNA_workspace_types.h" #include "DNA_userdef_types.h" #include "BLI_math.h" @@ -41,18 +42,17 @@ #include "BLI_utildefines.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" +#include "BKE_icons.h" #include "BKE_image.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_remap.h" #include "BKE_main.h" #include "BKE_node.h" #include "BKE_screen.h" #include "BKE_scene.h" - -#include "BIF_gl.h" -#include "BIF_glutil.h" +#include "BKE_workspace.h" #include "WM_api.h" #include "WM_types.h" @@ -266,7 +266,7 @@ bool scredge_is_horizontal(ScrEdge *se) } /* need win size to make sure not to include edges along screen edge */ -ScrEdge *screen_find_active_scredge(bScreen *sc, +ScrEdge *screen_find_active_scredge(const bScreen *sc, const int winsize_x, const int winsize_y, const int mx, const int my) { @@ -457,21 +457,17 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge) return newa; } -/* empty screen, with 1 dummy area without spacedata */ -/* uses window size */ -bScreen *ED_screen_add(wmWindow *win, Scene *scene, const char *name) +/** + * Empty screen, with 1 dummy area without spacedata. Uses window size. + */ +bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y) { - const int winsize_x = WM_window_pixels_x(win); - const int winsize_y = WM_window_pixels_y(win); - bScreen *sc; ScrVert *sv1, *sv2, *sv3, *sv4; sc = BKE_libblock_alloc(G.main, ID_SCR, name, 0); - sc->scene = scene; sc->do_refresh = true; sc->redraws_flag = TIME_ALL_3D_WIN | TIME_ALL_ANIM_WIN; - sc->winid = win->winid; sv1 = screen_addvert(sc, 0, 0); sv2 = screen_addvert(sc, 0, winsize_y - 1); @@ -489,7 +485,7 @@ bScreen *ED_screen_add(wmWindow *win, Scene *scene, const char *name) return sc; } -static void screen_copy(bScreen *to, bScreen *from) +void screen_data_copy(bScreen *to, bScreen *from) { ScrVert *s1, *s2; ScrEdge *se; @@ -532,7 +528,16 @@ static void screen_copy(bScreen *to, bScreen *from) /* put at zero (needed?) */ for (s1 = from->vertbase.first; s1; s1 = s1->next) s1->newv = NULL; +} +/** + * Prepare a newly created screen for initializing it as active screen. + */ +void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new) +{ + screen_new->winid = win->winid; + screen_new->do_refresh = true; + screen_new->do_draw = true; } @@ -615,7 +620,9 @@ int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2) screen_delarea(C, scr, sa2); removedouble_scrverts(scr); sa1->flag &= ~AREA_FLAG_DRAWJOINFROM; - + /* Update preview thumbnail */ + BKE_icon_changed(scr->id.icon_id); + return 1; } @@ -838,241 +845,23 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y) } -/* *********************** DRAWING **************************************** */ - -/* draw vertical shape visualizing future joining (left as well - * right direction of future joining) */ -static void draw_horizontal_join_shape(ScrArea *sa, char dir) -{ - vec2f points[10]; - short i; - float w, h; - float width = sa->v3->vec.x - sa->v1->vec.x; - float height = sa->v3->vec.y - sa->v1->vec.y; - - if (height < width) { - h = height / 8; - w = height / 4; - } - else { - h = width / 8; - w = width / 4; - } - - points[0].x = sa->v1->vec.x; - points[0].y = sa->v1->vec.y + height / 2; - - points[1].x = sa->v1->vec.x; - points[1].y = sa->v1->vec.y; - - points[2].x = sa->v4->vec.x - w; - points[2].y = sa->v4->vec.y; - - points[3].x = sa->v4->vec.x - w; - points[3].y = sa->v4->vec.y + height / 2 - 2 * h; - - points[4].x = sa->v4->vec.x - 2 * w; - points[4].y = sa->v4->vec.y + height / 2; - - points[5].x = sa->v4->vec.x - w; - points[5].y = sa->v4->vec.y + height / 2 + 2 * h; - - points[6].x = sa->v3->vec.x - w; - points[6].y = sa->v3->vec.y; - - points[7].x = sa->v2->vec.x; - points[7].y = sa->v2->vec.y; - - points[8].x = sa->v4->vec.x; - points[8].y = sa->v4->vec.y + height / 2 - h; - - points[9].x = sa->v4->vec.x; - points[9].y = sa->v4->vec.y + height / 2 + h; - - if (dir == 'l') { - /* when direction is left, then we flip direction of arrow */ - float cx = sa->v1->vec.x + width; - for (i = 0; i < 10; i++) { - points[i].x -= cx; - points[i].x = -points[i].x; - points[i].x += sa->v1->vec.x; - } - } - - glBegin(GL_POLYGON); - for (i = 0; i < 5; i++) - glVertex2f(points[i].x, points[i].y); - glEnd(); - glBegin(GL_POLYGON); - for (i = 4; i < 8; i++) - glVertex2f(points[i].x, points[i].y); - glVertex2f(points[0].x, points[0].y); - glEnd(); - - glRectf(points[2].x, points[2].y, points[8].x, points[8].y); - glRectf(points[6].x, points[6].y, points[9].x, points[9].y); -} - -/* draw vertical shape visualizing future joining (up/down direction) */ -static void draw_vertical_join_shape(ScrArea *sa, char dir) -{ - vec2f points[10]; - short i; - float w, h; - float width = sa->v3->vec.x - sa->v1->vec.x; - float height = sa->v3->vec.y - sa->v1->vec.y; - - if (height < width) { - h = height / 4; - w = height / 8; - } - else { - h = width / 4; - w = width / 8; - } - - points[0].x = sa->v1->vec.x + width / 2; - points[0].y = sa->v3->vec.y; - - points[1].x = sa->v2->vec.x; - points[1].y = sa->v2->vec.y; - - points[2].x = sa->v1->vec.x; - points[2].y = sa->v1->vec.y + h; - - points[3].x = sa->v1->vec.x + width / 2 - 2 * w; - points[3].y = sa->v1->vec.y + h; - - points[4].x = sa->v1->vec.x + width / 2; - points[4].y = sa->v1->vec.y + 2 * h; - - points[5].x = sa->v1->vec.x + width / 2 + 2 * w; - points[5].y = sa->v1->vec.y + h; - - points[6].x = sa->v4->vec.x; - points[6].y = sa->v4->vec.y + h; - - points[7].x = sa->v3->vec.x; - points[7].y = sa->v3->vec.y; - - points[8].x = sa->v1->vec.x + width / 2 - w; - points[8].y = sa->v1->vec.y; - - points[9].x = sa->v1->vec.x + width / 2 + w; - points[9].y = sa->v1->vec.y; - - if (dir == 'u') { - /* when direction is up, then we flip direction of arrow */ - float cy = sa->v1->vec.y + height; - for (i = 0; i < 10; i++) { - points[i].y -= cy; - points[i].y = -points[i].y; - points[i].y += sa->v1->vec.y; - } - } - - glBegin(GL_POLYGON); - for (i = 0; i < 5; i++) - glVertex2f(points[i].x, points[i].y); - glEnd(); - glBegin(GL_POLYGON); - for (i = 4; i < 8; i++) - glVertex2f(points[i].x, points[i].y); - glVertex2f(points[0].x, points[0].y); - glEnd(); - - glRectf(points[2].x, points[2].y, points[8].x, points[8].y); - glRectf(points[6].x, points[6].y, points[9].x, points[9].y); -} - -/* draw join shape due to direction of joining */ -static void draw_join_shape(ScrArea *sa, char dir) -{ - if (dir == 'u' || dir == 'd') - draw_vertical_join_shape(sa, dir); - else - draw_horizontal_join_shape(sa, dir); -} - -/* draw screen area darker with arrow (visualization of future joining) */ -static void scrarea_draw_shape_dark(ScrArea *sa, char dir) -{ - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4ub(0, 0, 0, 50); - draw_join_shape(sa, dir); -} - -/* draw screen area ligher with arrow shape ("eraser" of previous dark shape) */ -static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir)) -{ - glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA); - /* value 181 was hardly computed: 181~105 */ - glColor4ub(255, 255, 255, 50); - /* draw_join_shape(sa, dir); */ - glRecti(sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y); -} - -static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, short x2, short y2) -{ - /* right border area */ - if (x2 < sizex - 1) { - glVertex2s(x2, y1); - glVertex2s(x2, y2); - } - - /* left border area */ - if (x1 > 0) { /* otherwise it draws the emboss of window over */ - glVertex2s(x1, y1); - glVertex2s(x1, y2); - } - - /* top border area */ - if (y2 < sizey - 1) { - glVertex2s(x1, y2); - glVertex2s(x2, y2); - } - - /* bottom border area */ - if (y1 > 0) { - glVertex2s(x1, y1); - glVertex2s(x2, y1); - } -} - -/** screen edges drawing **/ -static void drawscredge_area(ScrArea *sa, int sizex, int sizey) -{ - short x1 = sa->v1->vec.x; - short y1 = sa->v1->vec.y; - short x2 = sa->v3->vec.x; - short y2 = sa->v3->vec.y; - - drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2); -} /* ****************** EXPORTED API TO OTHER MODULES *************************** */ -bScreen *ED_screen_duplicate(wmWindow *win, bScreen *sc) -{ - bScreen *newsc; - - if (sc->state != SCREENNORMAL) return NULL; /* XXX handle this case! */ - - /* make new empty screen: */ - newsc = ED_screen_add(win, sc->scene, sc->id.name + 2); - /* copy all data */ - screen_copy(newsc, sc); - - return newsc; -} - /* screen sets cursor based on swinid */ static void region_cursor_set(wmWindow *win, int swinid, int swin_changed) { - for (ScrArea *sa = win->screen->areabase.first; sa; sa = sa->next) { + bScreen *screen = WM_window_get_active_screen(win); + + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->swinid == swinid) { if (swin_changed || (ar->type && ar->type->event_cursor)) { + if (ar->manipulator_map != NULL) { + if (WM_manipulatormap_cursor_set(ar->manipulator_map, win)) { + return; + } + } ED_region_cursor_set(win, sa, ar); } return; @@ -1084,19 +873,20 @@ static void region_cursor_set(wmWindow *win, int swinid, int swin_changed) void ED_screen_do_listen(bContext *C, wmNotifier *note) { wmWindow *win = CTX_wm_window(C); - + bScreen *screen = CTX_wm_screen(C); + /* generic notes */ switch (note->category) { case NC_WM: if (note->data == ND_FILEREAD) - win->screen->do_draw = true; + screen->do_draw = true; break; case NC_WINDOW: - win->screen->do_draw = true; + screen->do_draw = true; break; case NC_SCREEN: if (note->action == NA_EDITED) - win->screen->do_draw = win->screen->do_refresh = true; + screen->do_draw = screen->do_refresh = true; break; case NC_SCENE: if (note->data == ND_MODE) @@ -1105,100 +895,6 @@ void ED_screen_do_listen(bContext *C, wmNotifier *note) } } -/* only for edge lines between areas, and the blended join arrows */ -void ED_screen_draw(wmWindow *win) -{ - const int winsize_x = WM_window_pixels_x(win); - const int winsize_y = WM_window_pixels_y(win); - - ScrArea *sa; - ScrArea *sa1 = NULL; - ScrArea *sa2 = NULL; - ScrArea *sa3 = NULL; - - wmSubWindowSet(win, win->screen->mainwin); - - /* Note: first loop only draws if U.pixelsize > 1, skip otherwise */ - if (U.pixelsize > 1.0f) { - /* FIXME: doesn't our glLineWidth already scale by U.pixelsize? */ - glLineWidth((2.0f * U.pixelsize) - 1); - glColor3ub(0x50, 0x50, 0x50); - glBegin(GL_LINES); - for (sa = win->screen->areabase.first; sa; sa = sa->next) - drawscredge_area(sa, winsize_x, winsize_y); - glEnd(); - } - - glLineWidth(1); - glColor3ub(0, 0, 0); - glBegin(GL_LINES); - for (sa = win->screen->areabase.first; sa; sa = sa->next) { - drawscredge_area(sa, winsize_x, winsize_y); - - /* gather area split/join info */ - if (sa->flag & AREA_FLAG_DRAWJOINFROM) sa1 = sa; - if (sa->flag & AREA_FLAG_DRAWJOINTO) sa2 = sa; - if (sa->flag & (AREA_FLAG_DRAWSPLIT_H | AREA_FLAG_DRAWSPLIT_V)) sa3 = sa; - } - glEnd(); - - /* blended join arrow */ - if (sa1 && sa2) { - int dir = area_getorientation(sa1, sa2); - int dira = -1; - if (dir != -1) { - switch (dir) { - case 0: /* W */ - dir = 'r'; - dira = 'l'; - break; - case 1: /* N */ - dir = 'd'; - dira = 'u'; - break; - case 2: /* E */ - dir = 'l'; - dira = 'r'; - break; - case 3: /* S */ - dir = 'u'; - dira = 'd'; - break; - } - } - glEnable(GL_BLEND); - scrarea_draw_shape_dark(sa2, dir); - scrarea_draw_shape_light(sa1, dira); - glDisable(GL_BLEND); - } - - /* splitpoint */ - if (sa3) { - glEnable(GL_BLEND); - glBegin(GL_LINES); - glColor4ub(255, 255, 255, 100); - - if (sa3->flag & AREA_FLAG_DRAWSPLIT_H) { - glVertex2s(sa3->totrct.xmin, win->eventstate->y); - glVertex2s(sa3->totrct.xmax, win->eventstate->y); - glColor4ub(0, 0, 0, 100); - glVertex2s(sa3->totrct.xmin, win->eventstate->y + 1); - glVertex2s(sa3->totrct.xmax, win->eventstate->y + 1); - } - else { - glVertex2s(win->eventstate->x, sa3->totrct.ymin); - glVertex2s(win->eventstate->x, sa3->totrct.ymax); - glColor4ub(0, 0, 0, 100); - glVertex2s(win->eventstate->x + 1, sa3->totrct.ymin); - glVertex2s(win->eventstate->x + 1, sa3->totrct.ymax); - } - glEnd(); - glDisable(GL_BLEND); - } - - win->screen->do_draw = false; -} - /* helper call for below, dpi changes headers */ static void screen_refresh_headersizes(void) { @@ -1214,7 +910,9 @@ static void screen_refresh_headersizes(void) /* make this screen usable */ /* for file read and first use, for scaling window, area moves */ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) -{ +{ + bScreen *screen = WM_window_get_active_screen(win); + /* exception for bg mode, we only need the screen context */ if (!G.background) { const int winsize_x = WM_window_pixels_x(win); @@ -1231,32 +929,34 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) WM_window_set_dpi(win); screen_refresh_headersizes(); - screen_test_scale(win->screen, winsize_x, winsize_y); + screen_test_scale(screen, winsize_x, winsize_y); - if (win->screen->mainwin == 0) { - win->screen->mainwin = wm_subwindow_open(win, &winrct, false); + if (screen->mainwin == 0) { + screen->mainwin = wm_subwindow_open(win, &winrct, false); } else { - wm_subwindow_position(win, win->screen->mainwin, &winrct, false); + wm_subwindow_position(win, screen->mainwin, &winrct, false); } - for (sa = win->screen->areabase.first; sa; sa = sa->next) { + for (sa = screen->areabase.first; sa; sa = sa->next) { /* set spacetype and region callbacks, calls init() */ /* sets subwindows for regions, adds handlers */ ED_area_initialize(wm, win, sa); } /* wake up animtimer */ - if (win->screen->animtimer) - WM_event_timer_sleep(wm, win, win->screen->animtimer, false); + if (screen->animtimer) + WM_event_timer_sleep(wm, win, screen->animtimer, false); } if (G.debug & G_DEBUG_EVENTS) { printf("%s: set screen\n", __func__); } - win->screen->do_refresh = false; + screen->do_refresh = false; + /* prevent multiwin errors */ + screen->winid = win->winid; - win->screen->context = ed_screen_context; + screen->context = ed_screen_context; } /* file read, set all screens, ... */ @@ -1265,10 +965,10 @@ void ED_screens_initialize(wmWindowManager *wm) wmWindow *win; for (win = wm->windows.first; win; win = win->next) { - - if (win->screen == NULL) - win->screen = G.main->screen.first; - + if (WM_window_get_active_workspace(win) == NULL) { + WM_window_set_active_workspace(win, G.main->workspaces.first); + } + ED_screen_refresh(wm, win); } } @@ -1279,15 +979,18 @@ void ED_screens_initialize(wmWindowManager *wm) void ED_region_exit(bContext *C, ARegion *ar) { wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); ARegion *prevar = CTX_wm_region(C); if (ar->type && ar->type->exit) ar->type->exit(wm, ar); CTX_wm_region_set(C, ar); + WM_event_remove_handlers(C, &ar->handlers); + WM_event_modal_handler_region_replace(win, ar, NULL); if (ar->swinid) { - wm_subwindow_close(CTX_wm_window(C), ar->swinid); + wm_subwindow_close(win, ar->swinid); ar->swinid = 0; } @@ -1297,7 +1000,7 @@ void ED_region_exit(bContext *C, ARegion *ar) } if (ar->regiontimer) { - WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), ar->regiontimer); + WM_event_remove_timer(wm, win, ar->regiontimer); ar->regiontimer = NULL; } @@ -1307,6 +1010,7 @@ void ED_region_exit(bContext *C, ARegion *ar) void ED_area_exit(bContext *C, ScrArea *sa) { wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); ScrArea *prevsa = CTX_wm_area(C); ARegion *ar; @@ -1314,10 +1018,13 @@ void ED_area_exit(bContext *C, ScrArea *sa) sa->type->exit(wm, sa); CTX_wm_area_set(C, sa); + for (ar = sa->regionbase.first; ar; ar = ar->next) ED_region_exit(C, ar); WM_event_remove_handlers(C, &sa->handlers); + WM_event_modal_handler_area_replace(win, sa, NULL); + CTX_wm_area_set(C, prevsa); } @@ -1349,7 +1056,7 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen) /* mark it available for use for other windows */ screen->winid = 0; - if (prevwin->screen->temp == 0) { + if (!WM_window_is_temp_screen(prevwin)) { /* use previous window if possible */ CTX_wm_window_set(C, prevwin); } @@ -1365,13 +1072,14 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen) /* case when on area-edge or in azones, or outside window */ static void screen_cursor_set(wmWindow *win, const wmEvent *event) { + const bScreen *screen = WM_window_get_active_screen(win); const int winsize_x = WM_window_pixels_x(win); const int winsize_y = WM_window_pixels_y(win); AZone *az = NULL; ScrArea *sa; - for (sa = win->screen->areabase.first; sa; sa = sa->next) + for (sa = screen->areabase.first; sa; sa = sa->next) if ((az = is_in_area_actionzone(sa, &event->x))) break; @@ -1386,7 +1094,7 @@ static void screen_cursor_set(wmWindow *win, const wmEvent *event) } } else { - ScrEdge *actedge = screen_find_active_scredge(win->screen, winsize_x, winsize_y, event->x, event->y); + ScrEdge *actedge = screen_find_active_scredge(screen, winsize_x, winsize_y, event->x, event->y); if (actedge) { if (scredge_is_horizontal(actedge)) @@ -1405,9 +1113,9 @@ static void screen_cursor_set(wmWindow *win, const wmEvent *event) void ED_screen_set_subwinactive(bContext *C, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); - - if (win->screen) { - bScreen *scr = win->screen; + bScreen *scr = WM_window_get_active_screen(win); + + if (scr) { ScrArea *sa; ARegion *ar; int oldswin = scr->subwinactive; @@ -1460,7 +1168,7 @@ void ED_screen_set_subwinactive(bContext *C, const wmEvent *event) /* this used to be a notifier, but needs to be done immediate * because it can undo setting the right button as active due * to delayed notifier handling */ - UI_screen_free_active_but(C, win->screen); + UI_screen_free_active_but(C, scr); } else region_cursor_set(win, scr->subwinactive, false); @@ -1488,177 +1196,120 @@ int ED_screen_area_active(const bContext *C) return 0; } + +/* -------------------------------------------------------------------- */ +/* Screen changing */ + +static bScreen *screen_fullscreen_find_associated_normal_screen(const Main *bmain, bScreen *screen) +{ + for (bScreen *screen_iter = bmain->screen.first; screen_iter; screen_iter = screen_iter->id.next) { + ScrArea *sa = screen_iter->areabase.first; + if (sa->full == screen) { + return screen_iter; + } + } + + return screen; +} + /** - * operator call, WM + Window + screen already existed before - * - * \warning Do NOT call in area/region queues! - * \returns success. + * \return the screen to activate. + * \warning The returned screen may not always equal \a screen_new! */ -bool ED_screen_set(bContext *C, bScreen *sc) +bScreen *screen_change_prepare(bScreen *screen_old, bScreen *screen_new, Main *bmain, bContext *C, wmWindow *win) { - Main *bmain = CTX_data_main(C); - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); - bScreen *oldscreen = CTX_wm_screen(C); - /* validate screen, it's called with notifier reference */ - if (BLI_findindex(&bmain->screen, sc) == -1) { - return true; + if (BLI_findindex(&bmain->screen, screen_new) == -1) { + return NULL; } - if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) { - /* find associated full */ - bScreen *sc1; - for (sc1 = bmain->screen.first; sc1; sc1 = sc1->id.next) { - ScrArea *sa = sc1->areabase.first; - if (sa->full == sc) { - sc = sc1; - break; - } - } + if (ELEM(screen_new->state, SCREENMAXIMIZED, SCREENFULL)) { + screen_new = screen_fullscreen_find_associated_normal_screen(bmain, screen_new); } /* check for valid winid */ - if (sc->winid != 0 && sc->winid != win->winid) { - return false; + if (!(screen_new->winid == 0 || screen_new->winid == win->winid)) { + return NULL; } - - if (oldscreen != sc) { - wmTimer *wt = oldscreen->animtimer; - ScrArea *sa; - Scene *oldscene = oldscreen->scene; + + if (screen_old != screen_new) { + wmTimer *wt = screen_old->animtimer; /* remove handlers referencing areas in old screen */ - for (sa = oldscreen->areabase.first; sa; sa = sa->next) { + for (ScrArea *sa = screen_old->areabase.first; sa; sa = sa->next) { WM_event_remove_area_handler(&win->modalhandlers, sa); } /* we put timer to sleep, so screen_exit has to think there's no timer */ - oldscreen->animtimer = NULL; + screen_old->animtimer = NULL; if (wt) { - WM_event_timer_sleep(wm, win, wt, true); + WM_event_timer_sleep(CTX_wm_manager(C), win, wt, true); } - - ED_screen_exit(C, win, oldscreen); + ED_screen_exit(C, win, screen_old); /* Same scene, "transfer" playback to new screen. */ if (wt) { - if (oldscene == sc->scene) { - sc->animtimer = wt; - } - /* Else, stop playback. */ - else { - oldscreen->animtimer = wt; - ED_screen_animation_play(C, 0, 0); - } + screen_new->animtimer = wt; } - win->screen = sc; - CTX_wm_window_set(C, win); // stores C->wm.screen... hrmf - - /* prevent multiwin errors */ - sc->winid = win->winid; - - ED_screen_refresh(CTX_wm_manager(C), CTX_wm_window(C)); - WM_event_add_notifier(C, NC_WINDOW, NULL); - WM_event_add_notifier(C, NC_SCREEN | ND_SCREENSET, sc); - - /* makes button hilites work */ - WM_event_add_mousemove(C); - - /* Needed to make sure all the derivedMeshes are - * up-to-date before viewport starts acquiring this. - * - * This is needed in cases when, for example, boolean - * modifier uses operant from invisible layer. - * Without this trick boolean wouldn't apply correct. - * - * Quite the same happens when setting screen's scene, - * so perhaps this is in fact correct thing to do. - */ - if (oldscene != sc->scene) { - BKE_scene_set_background(bmain, sc->scene); - } - - /* Always do visible update since it's possible new screen will - * have different layers visible in 3D view-ports. - * This is possible because of view3d.lock_camera_and_layers option. - */ - DAG_on_visible_update(bmain, false); + return screen_new; } - return true; + return NULL; } -static bool ed_screen_used(wmWindowManager *wm, bScreen *sc) +void screen_changed_update(bContext *C, wmWindow *win, bScreen *sc) { - wmWindow *win; + Scene *scene = WM_window_get_active_scene(win); + WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook); + WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, sc); - for (win = wm->windows.first; win; win = win->next) { - if (win->screen == sc) { - return true; - } + CTX_wm_window_set(C, win); /* stores C->wm.screen... hrmf */ - if (ELEM(win->screen->state, SCREENMAXIMIZED, SCREENFULL)) { - ScrArea *sa = win->screen->areabase.first; - if (sa->full == sc) { - return true; - } - } - } + ED_screen_refresh(CTX_wm_manager(C), win); - return false; + BKE_screen_view3d_scene_sync(sc, scene); /* sync new screen with scene data */ + WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTSET, layout); + + /* makes button hilites work */ + WM_event_add_mousemove(C); } -/* only call outside of area/region loops */ -bool ED_screen_delete(bContext *C, bScreen *sc) + +/** + * \brief Change the active screen. + * + * Operator call, WM + Window + screen already existed before + * + * \warning Do NOT call in area/region queues! + * \returns if screen changing was successful. + */ +bool ED_screen_change(bContext *C, bScreen *sc) { Main *bmain = CTX_data_main(C); - wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); - bScreen *newsc; - - /* don't allow deleting temp fullscreens for now */ - if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) { - return false; - } - - /* screen can only be in use by one window at a time, so as - * long as we are able to find a screen that is unused, we - * can safely assume ours is not in use anywhere an delete it */ - - for (newsc = sc->id.prev; newsc; newsc = newsc->id.prev) - if (!ed_screen_used(wm, newsc) && !newsc->temp) - break; - - if (!newsc) { - for (newsc = sc->id.next; newsc; newsc = newsc->id.next) - if (!ed_screen_used(wm, newsc) && !newsc->temp) - break; - } + bScreen *screen_old = CTX_wm_screen(C); + bScreen *screen_new = screen_change_prepare(screen_old, sc, bmain, C, win); - if (!newsc) { - return false; - } + if (screen_new) { + WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook); + WM_window_set_active_screen(win, workspace, sc); + screen_changed_update(C, win, screen_new); - ED_screen_set(C, newsc); - - if (win->screen != sc) { - BKE_libblock_free(bmain, sc); return true; } - else { - return false; - } + + return false; } -static void ed_screen_set_3dview_camera(Scene *scene, bScreen *sc, ScrArea *sa, View3D *v3d) +static void screen_set_3dview_camera(Scene *scene, SceneLayer *scene_layer, ScrArea *sa, View3D *v3d) { /* fix any cameras that are used in the 3d view but not in the scene */ BKE_screen_view3d_sync(v3d, scene); - if (!v3d->camera || !BKE_scene_base_find(scene, v3d->camera)) { - v3d->camera = BKE_scene_camera_find(sc->scene); + if (!v3d->camera || !BKE_scene_layer_base_find(scene_layer, v3d->camera)) { + v3d->camera = BKE_scene_layer_camera_find(scene_layer); // XXX if (sc == curscreen) handle_view3d_lock(); if (!v3d->camera) { ARegion *ar; @@ -1682,93 +1333,16 @@ static void ed_screen_set_3dview_camera(Scene *scene, bScreen *sc, ScrArea *sa, } } -/* only call outside of area/region loops */ -void ED_screen_set_scene(bContext *C, bScreen *screen, Scene *scene) +void ED_screen_update_after_scene_change(const bScreen *screen, Scene *scene_new, SceneLayer *scene_layer) { - Main *bmain = CTX_data_main(C); - bScreen *sc; - - if (screen == NULL) - return; - - if (ed_screen_used(CTX_wm_manager(C), screen)) - ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO); - - for (sc = bmain->screen.first; sc; sc = sc->id.next) { - if ((U.flag & USER_SCENEGLOBAL) || sc == screen) { - - if (scene != sc->scene) { - /* all areas endlocalview */ - // XXX ScrArea *sa = sc->areabase.first; - // while (sa) { - // endlocalview(sa); - // sa = sa->next; - // } - sc->scene = scene; - } - - } - } - - // copy_view3d_lock(0); /* space.c */ - - /* are there cameras in the views that are not in the scene? */ - for (sc = bmain->screen.first; sc; sc = sc->id.next) { - if ((U.flag & USER_SCENEGLOBAL) || sc == screen) { - ScrArea *sa = sc->areabase.first; - while (sa) { - SpaceLink *sl = sa->spacedata.first; - while (sl) { - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *) sl; - ed_screen_set_3dview_camera(scene, sc, sa, v3d); - - } - sl = sl->next; - } - sa = sa->next; + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + screen_set_3dview_camera(scene_new, scene_layer, sa, v3d); } } } - - CTX_data_scene_set(C, scene); - BKE_scene_set_background(bmain, scene); - DAG_on_visible_update(bmain, false); - - ED_render_engine_changed(bmain); - ED_update_for_newframe(bmain, scene, 1); - - /* complete redraw */ - WM_event_add_notifier(C, NC_WINDOW, NULL); - -} - -/** - * \note Only call outside of area/region loops - * \return true if successful - */ -bool ED_screen_delete_scene(bContext *C, Scene *scene) -{ - Main *bmain = CTX_data_main(C); - Scene *newscene; - - if (scene->id.prev) - newscene = scene->id.prev; - else if (scene->id.next) - newscene = scene->id.next; - else - return false; - - ED_screen_set_scene(C, CTX_wm_screen(C), newscene); - - BKE_libblock_remap(bmain, scene, newscene, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE); - - id_us_clear_real(&scene->id); - if (scene->id.us == 0) { - BKE_libblock_free(bmain, scene); - } - - return true; } ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type) @@ -1875,6 +1449,7 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa) ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const short state) { wmWindowManager *wm = CTX_wm_manager(C); + WorkSpace *workspace = WM_window_get_active_workspace(win); bScreen *sc, *oldscreen; ARegion *ar; @@ -1896,9 +1471,10 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s } if (sa && sa->full) { + WorkSpaceLayout *layout_old = WM_window_get_active_layout(win); /* restoring back to SCREENNORMAL */ sc = sa->full; /* the old screen to restore */ - oldscreen = win->screen; /* the one disappearing */ + oldscreen = WM_window_get_active_screen(win); /* the one disappearing */ sc->state = SCREENNORMAL; @@ -1937,9 +1513,9 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s sc->animtimer = oldscreen->animtimer; oldscreen->animtimer = NULL; - ED_screen_set(C, sc); + ED_screen_change(C, sc); - BKE_libblock_free(CTX_data_main(C), oldscreen); + BKE_workspace_layout_remove(CTX_data_main(C), workspace, layout_old); /* After we've restored back to SCREENNORMAL, we have to wait with * screen handling as it uses the area coords which aren't updated yet. @@ -1949,14 +1525,18 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s } else { /* change from SCREENNORMAL to new state */ + WorkSpaceLayout *layout_new; ScrArea *newa; char newname[MAX_ID_NAME - 2]; - oldscreen = win->screen; + oldscreen = WM_window_get_active_screen(win); oldscreen->state = state; BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal"); - sc = ED_screen_add(win, oldscreen->scene, newname); + + layout_new = ED_workspace_layout_add(workspace, win, newname); + + sc = BKE_workspace_layout_screen_get(layout_new); sc->state = state; sc->redraws_flag = oldscreen->redraws_flag; sc->temp = oldscreen->temp; @@ -2011,7 +1591,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s BLI_assert(false); } - ED_screen_set(C, sc); + ED_screen_change(C, sc); } /* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */ @@ -2146,14 +1726,9 @@ void ED_screen_animation_timer_update(bScreen *screen, int redraws, int refresh) } } -/* results in fully updated anim system - * screen can be NULL */ -void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute)) +/* results in fully updated anim system */ +void ED_update_for_newframe(Main *bmain, Scene *scene, SceneLayer *scene_layer, struct Depsgraph *depsgraph) { - wmWindowManager *wm = bmain->wm.first; - wmWindow *window; - int layers = 0; - #ifdef DURIAN_CAMERA_SWITCH void *camera = BKE_scene_camera_switch_find(scene); if (camera && scene->camera != camera) { @@ -2161,19 +1736,15 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute)) scene->camera = camera; /* are there cameras in the views that are not in the scene? */ for (sc = bmain->screen.first; sc; sc = sc->id.next) { - BKE_screen_view3d_scene_sync(sc); + BKE_screen_view3d_scene_sync(sc, scene); } } #endif ED_clip_update_frame(bmain, scene->r.cfra); - /* get layers from all windows */ - for (window = wm->windows.first; window; window = window->next) - layers |= BKE_screen_visible_layers(window->screen, scene); - /* this function applies the changes too */ - BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, layers); + BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, scene_layer); /* composite */ if (scene->use_nodes && scene->nodetree) @@ -2194,11 +1765,10 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute)) /* * return true if any active area requires to see in 3D */ -bool ED_screen_stereo3d_required(bScreen *screen) +bool ED_screen_stereo3d_required(const bScreen *screen, const Scene *scene) { ScrArea *sa; - Scene *sce = screen->scene; - const bool is_multiview = (sce->r.scemode & R_MULTIVIEW) != 0; + const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0; for (sa = screen->areabase.first; sa; sa = sa->next) { switch (sa->spacetype) { @@ -2273,3 +1843,19 @@ bool ED_screen_stereo3d_required(bScreen *screen) return false; } + +/** + * Find the scene displayed in \a screen. + * \note Assumes \a screen to be visible/active! + */ +Scene *ED_screen_scene_find(const bScreen *screen, const wmWindowManager *wm) +{ + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (WM_window_get_active_screen(win) == screen) { + return WM_window_get_active_scene(win); + } + } + + BLI_assert(0); + return NULL; +} diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h index ccb6d5a6dca..4eb68d01df7 100644 --- a/source/blender/editors/screen/screen_intern.h +++ b/source/blender/editors/screen/screen_intern.h @@ -31,6 +31,9 @@ #ifndef __SCREEN_INTERN_H__ #define __SCREEN_INTERN_H__ +struct bContextDataResult; +struct Main; + /* internal exports only */ #define AZONESPOT (0.6f * U.widget_unit) @@ -40,12 +43,17 @@ /* area.c */ void ED_area_data_copy(ScrArea *sa_dst, ScrArea *sa_src, const bool do_free); void ED_area_data_swap(ScrArea *sa1, ScrArea *sa2); -void region_toggle_hidden(bContext *C, ARegion *ar, const bool do_fade); +void region_toggle_hidden(struct bContext *C, ARegion *ar, const bool do_fade); /* screen_edit.c */ +bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y); +void screen_data_copy(bScreen *to, bScreen *from); +void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new); +void screen_changed_update(struct bContext *C, wmWindow *win, bScreen *sc); +bScreen *screen_change_prepare(bScreen *screen_old, bScreen *screen_new, struct Main *bmain, struct bContext *C, wmWindow *win); ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2); ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge); -int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2); +int screen_area_join(struct bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2); int area_getorientation(ScrArea *sa, ScrArea *sb); void select_connected_scredge(bScreen *sc, ScrEdge *edge); @@ -54,14 +62,14 @@ void removedouble_scrverts(bScreen *sc); void removedouble_scredges(bScreen *sc); void removenotused_scredges(bScreen *sc); bool scredge_is_horizontal(ScrEdge *se); -ScrEdge *screen_find_active_scredge(bScreen *sc, +ScrEdge *screen_find_active_scredge(const bScreen *sc, const int winsize_x, const int winsize_y, const int mx, const int my); struct AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]); /* screen_context.c */ -int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result); +int ed_screen_context(const struct bContext *C, const char *member, struct bContextDataResult *result); extern const char *screen_context_dir[]; /* doc access */ @@ -72,5 +80,8 @@ void SCREEN_OT_screencast(struct wmOperatorType *ot); /* screen_ops.c */ void region_blend_start(struct bContext *C, struct ScrArea *sa, struct ARegion *ar); +/* workspace_layout_edit.c */ +bool workspace_layout_set_poll(const struct WorkSpaceLayout *layout); + #endif /* __SCREEN_INTERN_H__ */ diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 908d218d353..cb53de23983 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -48,11 +48,13 @@ #include "DNA_meta_types.h" #include "DNA_mask_types.h" #include "DNA_node_types.h" +#include "DNA_workspace_types.h" #include "DNA_userdef_types.h" #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_global.h" +#include "BKE_icons.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" @@ -61,6 +63,7 @@ #include "BKE_editmesh.h" #include "BKE_sound.h" #include "BKE_mask.h" +#include "BKE_workspace.h" #include "WM_api.h" #include "WM_types.h" @@ -571,8 +574,8 @@ int ED_operator_mask(bContext *C) case SPACE_IMAGE: { SpaceImage *sima = sa->spacedata.first; - Scene *scene = CTX_data_scene(C); - return ED_space_image_check_show_maskedit(scene, sima); + SceneLayer *sl = CTX_data_scene_layer(C); + return ED_space_image_check_show_maskedit(sl, sima); } } } @@ -580,6 +583,12 @@ int ED_operator_mask(bContext *C) return false; } +int ED_operator_camera(bContext *C) +{ + struct Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; + return (cam != NULL); +} + /* *************************** action zone operator ************************** */ /* operator state vars used: @@ -977,13 +986,17 @@ static void SCREEN_OT_area_swap(wmOperatorType *ot) /* operator callback */ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - wmWindow *newwin, *win; - bScreen *newsc, *sc; + wmWindow *newwin, *win = CTX_wm_window(C); + Scene *scene; + WorkSpace *workspace = WM_window_get_active_workspace(win); + WorkSpaceLayout *layout_old = WM_window_get_active_layout(win); + WorkSpaceLayout *layout_new; + bScreen *newsc; ScrArea *sa; rcti rect; win = CTX_wm_window(C); - sc = CTX_wm_screen(C); + scene = CTX_data_scene(C); sa = CTX_wm_area(C); /* XXX hrmf! */ @@ -1009,11 +1022,15 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event) } *newwin->stereo3d_format = *win->stereo3d_format; - + + newwin->scene = scene; + + WM_window_set_active_workspace(newwin, workspace); /* allocs new screen and adds to newly created window, using window size */ - newsc = ED_screen_add(newwin, CTX_data_scene(C), sc->id.name + 2); - newwin->screen = newsc; - + layout_new = ED_workspace_layout_add(workspace, newwin, BKE_workspace_layout_name_get(layout_old)); + newsc = BKE_workspace_layout_screen_get(layout_new); + WM_window_set_active_layout(newwin, workspace, layout_new); + /* copy area to new screen */ ED_area_data_copy((ScrArea *)newsc->areabase.first, sa, true); @@ -1220,6 +1237,8 @@ static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int } WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); /* redraw everything */ + /* Update preview thumbnail */ + BKE_icon_changed(sc->id.icon_id); } } @@ -1508,7 +1527,9 @@ static int area_split_apply(bContext *C, wmOperator *op) ED_area_tag_redraw(sd->narea); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); - + /* Update preview thumbnail */ + BKE_icon_changed(sc->id.icon_id); + return 1; } @@ -1709,7 +1730,7 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event) } } - CTX_wm_window(C)->screen->do_draw = true; + CTX_wm_screen(C)->do_draw = true; } @@ -2079,12 +2100,11 @@ static void areas_do_frame_follow(bContext *C, bool middle) bScreen *scr = CTX_wm_screen(C); Scene *scene = CTX_data_scene(C); wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *window; - for (window = wm->windows.first; window; window = window->next) { - ScrArea *sa; - for (sa = window->screen->areabase.first; sa; sa = sa->next) { - ARegion *ar; - for (ar = sa->regionbase.first; ar; ar = ar->next) { + for (wmWindow *window = wm->windows.first; window; window = window->next) { + const bScreen *screen = WM_window_get_active_screen(window); + + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { /* do follow here if editor type supports it */ if ((scr->redraws_flag & TIME_FOLLOW)) { if ((ar->regiontype == RGN_TYPE_WINDOW && @@ -2383,64 +2403,16 @@ static void SCREEN_OT_marker_jump(wmOperatorType *ot) /* ************** switch screen operator ***************************** */ -static bool screen_set_is_ok(bScreen *screen, bScreen *screen_prev) -{ - return ((screen->winid == 0) && - /* in typical usage these should have a nonzero winid - * (all temp screens should be used, or closed & freed). */ - (screen->temp == false) && - (screen->state == SCREENNORMAL) && - (screen != screen_prev) && - (screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT))); -} - /* function to be called outside UI context, or for redo */ static int screen_set_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - bScreen *screen = CTX_wm_screen(C); - bScreen *screen_prev = screen; - - ScrArea *sa = CTX_wm_area(C); - int tot = BLI_listbase_count(&bmain->screen); + WorkSpace *workspace = CTX_wm_workspace(C); int delta = RNA_int_get(op->ptr, "delta"); - - /* temp screens are for userpref or render display */ - if (screen->temp || (sa && sa->full && sa->full->temp)) { - return OPERATOR_CANCELLED; - } - - if (delta == 1) { - while (tot--) { - screen = screen->id.next; - if (screen == NULL) screen = bmain->screen.first; - if (screen_set_is_ok(screen, screen_prev)) { - break; - } - } - } - else if (delta == -1) { - while (tot--) { - screen = screen->id.prev; - if (screen == NULL) screen = bmain->screen.last; - if (screen_set_is_ok(screen, screen_prev)) { - break; - } - } - } - else { - screen = NULL; - } - - if (screen && screen_prev != screen) { - /* return to previous state before switching screens */ - if (sa && sa->full) { - ED_screen_full_restore(C, sa); /* may free 'screen_prev' */ - } - - ED_screen_set(C, screen); + + if (ED_workspace_layout_cycle(workspace, delta, C)) { return OPERATOR_FINISHED; } + return OPERATOR_CANCELLED; } @@ -3252,7 +3224,7 @@ static int header_toggle_menus_exec(bContext *C, wmOperator *UNUSED(op)) sa->flag = sa->flag ^ HEADER_NO_PULLDOWN; ED_area_tag_redraw(sa); - WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); return OPERATOR_FINISHED; } @@ -3436,6 +3408,8 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv if (screen->animtimer && screen->animtimer == event->customdata) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *scene_layer = CTX_data_scene_layer(C); + struct Depsgraph *depsgraph = CTX_data_depsgraph(C); wmTimer *wt = screen->animtimer; ScreenAnimData *sad = wt->customdata; wmWindowManager *wm = CTX_wm_manager(C); @@ -3546,10 +3520,12 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } /* since we follow drawflags, we can't send notifier but tag regions ourselves */ - ED_update_for_newframe(bmain, scene, 1); + ED_update_for_newframe(bmain, scene, scene_layer, depsgraph); for (window = wm->windows.first; window; window = window->next) { - for (sa = window->screen->areabase.first; sa; sa = sa->next) { + const bScreen *win_screen = WM_window_get_active_screen(window); + + for (sa = win_screen->areabase.first; sa; sa = sa->next) { ARegion *ar; for (ar = sa->regionbase.first; ar; ar = ar->next) { bool redraw = false; @@ -3623,11 +3599,11 @@ static void SCREEN_OT_animation_step(wmOperatorType *ot) /* find window that owns the animation timer */ bScreen *ED_screen_animation_playing(const wmWindowManager *wm) { - wmWindow *win; + for (wmWindow *win = wm->windows.first; win; win = win->next) { + bScreen *screen = WM_window_get_active_screen(win); - for (win = wm->windows.first; win; win = win->next) { - if (win->screen->animtimer || win->screen->scrubbing) { - return win->screen; + if (screen->animtimer || screen->scrubbing) { + return screen; } } @@ -3636,11 +3612,11 @@ bScreen *ED_screen_animation_playing(const wmWindowManager *wm) bScreen *ED_screen_animation_no_scrub(const wmWindowManager *wm) { - wmWindow *win; + for (wmWindow *win = wm->windows.first; win; win = win->next) { + bScreen *screen = WM_window_get_active_screen(win); - for (win = wm->windows.first; win; win = win->next) { - if (win->screen->animtimer) { - return win->screen; + if (screen->animtimer) { + return screen; } } @@ -3874,11 +3850,13 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot) static int screen_new_exec(bContext *C, wmOperator *UNUSED(op)) { wmWindow *win = CTX_wm_window(C); - bScreen *sc = CTX_wm_screen(C); - - sc = ED_screen_duplicate(win, sc); - WM_event_add_notifier(C, NC_SCREEN | ND_SCREENBROWSE, sc); - + WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook); + WorkSpaceLayout *layout_old = BKE_workspace_active_layout_get(win->workspace_hook); + WorkSpaceLayout *layout_new; + + layout_new = ED_workspace_layout_duplicate(workspace, layout_old, win); + WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTBROWSE, layout_new); + return OPERATOR_FINISHED; } @@ -3899,9 +3877,11 @@ static void SCREEN_OT_new(wmOperatorType *ot) static int screen_delete_exec(bContext *C, wmOperator *UNUSED(op)) { bScreen *sc = CTX_wm_screen(C); - - WM_event_add_notifier(C, NC_SCREEN | ND_SCREENDELETE, sc); - + WorkSpace *workspace = CTX_wm_workspace(C); + WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, sc); + + WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTDELETE, layout); + return OPERATOR_FINISHED; } @@ -3916,95 +3896,6 @@ static void SCREEN_OT_delete(wmOperatorType *ot) ot->exec = screen_delete_exec; } -/********************* new scene operator *********************/ - -static int scene_new_exec(bContext *C, wmOperator *op) -{ - Scene *newscene, *scene = CTX_data_scene(C); - Main *bmain = CTX_data_main(C); - int type = RNA_enum_get(op->ptr, "type"); - - if (type == SCE_COPY_NEW) { - newscene = BKE_scene_add(bmain, DATA_("Scene")); - } - else { /* different kinds of copying */ - newscene = BKE_scene_copy(bmain, scene, type); - - /* these can't be handled in blenkernel currently, so do them here */ - if (type == SCE_COPY_LINK_DATA) { - ED_object_single_users(bmain, newscene, false, true); - } - else if (type == SCE_COPY_FULL) { - ED_editors_flush_edits(C, false); - ED_object_single_users(bmain, newscene, true, true); - } - } - - ED_screen_set_scene(C, CTX_wm_screen(C), newscene); - - WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, newscene); - - return OPERATOR_FINISHED; -} - -static void SCENE_OT_new(wmOperatorType *ot) -{ - static const EnumPropertyItem type_items[] = { - {SCE_COPY_NEW, "NEW", 0, "New", "Add new scene"}, - {SCE_COPY_EMPTY, "EMPTY", 0, "Copy Settings", "Make a copy without any objects"}, - {SCE_COPY_LINK_OB, "LINK_OBJECTS", 0, "Link Objects", "Link to the objects from the current scene"}, - {SCE_COPY_LINK_DATA, "LINK_OBJECT_DATA", 0, "Link Object Data", "Copy objects linked to data from the current scene"}, - {SCE_COPY_FULL, "FULL_COPY", 0, "Full Copy", "Make a full copy of the current scene"}, - {0, NULL, 0, NULL, NULL}}; - - /* identifiers */ - ot->name = "New Scene"; - ot->description = "Add new scene by type"; - ot->idname = "SCENE_OT_new"; - - /* api callbacks */ - ot->exec = scene_new_exec; - ot->invoke = WM_menu_invoke; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", ""); -} - -/********************* delete scene operator *********************/ - -static int scene_delete_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Scene *scene = CTX_data_scene(C); - - if (ED_screen_delete_scene(C, scene) == false) { - return OPERATOR_CANCELLED; - } - - if (G.debug & G_DEBUG) - printf("scene delete %p\n", scene); - - WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene); - - return OPERATOR_FINISHED; -} - -static void SCENE_OT_delete(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Delete Scene"; - ot->description = "Delete active scene"; - ot->idname = "SCENE_OT_delete"; - - /* api callbacks */ - ot->exec = scene_delete_exec; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - /* ***************** region alpha blending ***************** */ /* implementation note: a disappearing region needs at least 1 last draw with 100% backbuffer @@ -4275,13 +4166,11 @@ void ED_operatortypes_screen(void) WM_operatortype_append(SCREEN_OT_animation_step); WM_operatortype_append(SCREEN_OT_animation_play); WM_operatortype_append(SCREEN_OT_animation_cancel); - + /* new/delete */ WM_operatortype_append(SCREEN_OT_new); WM_operatortype_append(SCREEN_OT_delete); - WM_operatortype_append(SCENE_OT_new); - WM_operatortype_append(SCENE_OT_delete); - + /* tools shared by more space types */ WM_operatortype_append(ED_OT_undo); WM_operatortype_append(ED_OT_undo_push); diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 2dd7400bc37..69891a727d4 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -54,7 +54,9 @@ #include "BKE_writeavi.h" #include "BIF_gl.h" -#include "BIF_glutil.h" + +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" #include "RNA_access.h" #include "RNA_define.h" @@ -451,25 +453,24 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float /* Helper callback for drawing the cursor itself */ static void screencast_draw_cursor(bContext *UNUSED(C), int x, int y, void *UNUSED(p_ptr)) { - - glPushMatrix(); - - glTranslatef((float)x, (float)y, 0.0f); - - glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - - glColor4ub(0, 0, 0, 32); - glutil_draw_filled_arc(0.0, M_PI * 2.0, 20, 40); - - glColor4ub(255, 255, 255, 128); - glutil_draw_lined_arc(0.0, M_PI * 2.0, 20, 40); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4ub(0, 0, 0, 32); + imm_draw_circle_fill_2d(pos, (float)x, (float)y, 20, 40); + + immUniformColor4ub(255, 255, 255, 128); + imm_draw_circle_wire_2d(pos, (float)x, (float)y, 20, 40); + + immUnbindProgram(); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - - glPopMatrix(); } /* Turn brush cursor in 3D view on/off */ diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c new file mode 100644 index 00000000000..e90c63f7a45 --- /dev/null +++ b/source/blender/editors/screen/workspace_edit.c @@ -0,0 +1,443 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/screen/workspace_edit.c + * \ingroup edscr + */ + +#include <stdlib.h> +#include <string.h> + +#include "BLI_utildefines.h" +#include "BLI_fileops.h" +#include "BLI_listbase.h" +#include "BLI_path_util.h" +#include "BLI_string.h" + +#include "BKE_appdir.h" +#include "BKE_blendfile.h" +#include "BKE_context.h" +#include "BKE_idcode.h" +#include "BKE_main.h" +#include "BKE_library.h" +#include "BKE_report.h" +#include "BKE_scene.h" +#include "BKE_screen.h" +#include "BKE_workspace.h" + +#include "BLO_readfile.h" + +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_windowmanager_types.h" +#include "DNA_workspace_types.h" + +#include "ED_object.h" +#include "ED_screen.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "screen_intern.h" + + +/** \name Workspace API + * + * \brief API for managing workspaces and their data. + * \{ */ + +WorkSpace *ED_workspace_add( + Main *bmain, const char *name, SceneLayer *act_render_layer, ViewRender *view_render) +{ + WorkSpace *workspace = BKE_workspace_add(bmain, name); + +#ifdef USE_WORKSPACE_MODE + BKE_workspace_object_mode_set(workspace, OB_MODE_OBJECT); +#endif + + BKE_workspace_render_layer_set(workspace, act_render_layer); + BKE_viewrender_copy(&workspace->view_render, view_render); + + return workspace; +} + +#ifdef USE_WORKSPACE_MODE +/** + * Changes the object mode (if needed) to the one set in \a workspace_new. + * Object mode is still stored on object level. In future it should all be workspace level instead. + */ +static void workspace_change_update_mode( + const WorkSpace *workspace_old, const WorkSpace *workspace_new, + bContext *C, Object *ob_act, ReportList *reports) +{ + eObjectMode mode_old = BKE_workspace_object_mode_get(workspace_old); + eObjectMode mode_new = BKE_workspace_object_mode_get(workspace_new); + + if (mode_old != mode_new) { + ED_object_mode_compat_set(C, ob_act, mode_new, reports); + ED_object_toggle_modes(C, mode_new); + } +} +#endif + +static void workspace_change_update_render_layer( + WorkSpace *workspace_new, const WorkSpace *workspace_old) +{ + if (!BKE_workspace_render_layer_get(workspace_new)) { + BKE_workspace_render_layer_set(workspace_new, BKE_workspace_render_layer_get(workspace_old)); + } +} + +static void workspace_change_update( + WorkSpace *workspace_new, const WorkSpace *workspace_old, + bContext *C, wmWindowManager *wm) +{ + /* needs to be done before changing mode! (to ensure right context) */ + workspace_change_update_render_layer(workspace_new, workspace_old); +#ifdef USE_WORKSPACE_MODE + workspace_change_update_mode(workspace_old, workspace_new, C, CTX_data_active_object(C), &wm->reports); +#else + UNUSED_VARS(C, wm); +#endif +} + +static bool workspace_change_find_new_layout_cb(const WorkSpaceLayout *layout, void *UNUSED(arg)) +{ + /* return false to stop the iterator if we've found a layout that can be activated */ + return workspace_layout_set_poll(layout) ? false : true; +} + +static WorkSpaceLayout *workspace_change_get_new_layout( + WorkSpace *workspace_new, wmWindow *win) +{ + /* ED_workspace_duplicate may have stored a layout to activate once the workspace gets activated. */ + WorkSpaceLayout *layout_new; + bScreen *screen_new; + + if (win->workspace_hook->temp_workspace_store) { + layout_new = win->workspace_hook->temp_layout_store; + } + else { + layout_new = BKE_workspace_hook_layout_for_workspace_get(win->workspace_hook, workspace_new); + if (!layout_new) { + layout_new = BKE_workspace_layouts_get(workspace_new)->first; + } + } + screen_new = BKE_workspace_layout_screen_get(layout_new); + + if (screen_new->winid) { + /* screen is already used, try to find a free one */ + WorkSpaceLayout *layout_temp = BKE_workspace_layout_iter_circular( + workspace_new, layout_new, workspace_change_find_new_layout_cb, + NULL, false); + if (!layout_temp) { + /* fallback solution: duplicate layout */ + layout_temp = ED_workspace_layout_duplicate(workspace_new, layout_new, win); + } + layout_new = layout_temp; + } + + return layout_new; +} + +/** + * \brief Change the active workspace. + * + * Operator call, WM + Window + screen already existed before + * Pretty similar to #ED_screen_change since changing workspace also changes screen. + * + * \warning Do NOT call in area/region queues! + * \returns if workspace changing was successful. + */ +bool ED_workspace_change( + WorkSpace *workspace_new, bContext *C, wmWindowManager *wm, wmWindow *win) +{ + Main *bmain = CTX_data_main(C); + WorkSpace *workspace_old = WM_window_get_active_workspace(win); + WorkSpaceLayout *layout_new = workspace_change_get_new_layout(workspace_new, win); + bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new); + bScreen *screen_old = BKE_workspace_active_screen_get(win->workspace_hook); + + win->workspace_hook->temp_layout_store = NULL; + if (workspace_old == workspace_new) { + /* Could also return true, everything that needs to be done was done (nothing :P), but nothing changed */ + return false; + } + + screen_new = screen_change_prepare(screen_old, screen_new, bmain, C, win); + BLI_assert(BKE_workspace_layout_screen_get(layout_new) == screen_new); + + if (screen_new) { + WM_window_set_active_layout(win, workspace_new, layout_new); + WM_window_set_active_workspace(win, workspace_new); + + /* update screen *after* changing workspace - which also causes the actual screen change */ + screen_changed_update(C, win, screen_new); + workspace_change_update(workspace_new, workspace_old, C, wm); + + BLI_assert(BKE_workspace_render_layer_get(workspace_new) != NULL); + BLI_assert(CTX_wm_workspace(C) == workspace_new); + + return true; + } + + return false; +} + +/** + * Duplicate a workspace including its layouts. Does not activate the workspace, but + * it stores the screen-layout to be activated (BKE_workspace_temp_layout_store) + */ +WorkSpace *ED_workspace_duplicate( + WorkSpace *workspace_old, Main *bmain, wmWindow *win) +{ + WorkSpaceLayout *layout_active_old = BKE_workspace_active_layout_get(win->workspace_hook); + ListBase *layouts_old = BKE_workspace_layouts_get(workspace_old); + WorkSpace *workspace_new = ED_workspace_add( + bmain, workspace_old->id.name + 2, + BKE_workspace_render_layer_get(workspace_old), + &workspace_old->view_render); + ListBase *transform_orientations_old = BKE_workspace_transform_orientations_get(workspace_old); + ListBase *transform_orientations_new = BKE_workspace_transform_orientations_get(workspace_new); + +#ifdef USE_WORKSPACE_MODE + BKE_workspace_object_mode_set(workspace_new, BKE_workspace_object_mode_get(workspace_old)); +#endif + BLI_duplicatelist(transform_orientations_new, transform_orientations_old); + + for (WorkSpaceLayout *layout_old = layouts_old->first; layout_old; layout_old = layout_old->next) { + WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(workspace_new, layout_old, win); + + if (layout_active_old == layout_old) { + win->workspace_hook->temp_layout_store = layout_new; + } + } + return workspace_new; +} + +/** + * \return if succeeded. + */ +bool ED_workspace_delete( + WorkSpace *workspace, Main *bmain, bContext *C, wmWindowManager *wm) +{ + ID *workspace_id = (ID *)workspace; + + if (BLI_listbase_is_single(&bmain->workspaces)) { + return false; + } + + for (wmWindow *win = wm->windows.first; win; win = win->next) { + WorkSpace *prev = workspace_id->prev; + WorkSpace *next = workspace_id->next; + + ED_workspace_change((prev != NULL) ? prev : next, C, wm, win); + } + BKE_libblock_free(bmain, workspace_id); + + return true; +} + +/** + * Some editor data may need to be synced with scene data (3D View camera and layers). + * This function ensures data is synced for editors in active layout of \a workspace. + */ +void ED_workspace_scene_data_sync( + WorkSpaceInstanceHook *hook, Scene *scene) +{ + bScreen *screen = BKE_workspace_active_screen_get(hook); + BKE_screen_view3d_scene_sync(screen, scene); +} + +void ED_workspace_render_layer_unset( + const Main *bmain, const SceneLayer *layer_unset, SceneLayer *layer_new) +{ + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + if (BKE_workspace_render_layer_get(workspace) == layer_unset) { + BKE_workspace_render_layer_set(workspace, layer_new); + } + } +} + +/** \} Workspace API */ + + +/** \name Workspace Operators + * + * \{ */ + +static int workspace_new_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain = CTX_data_main(C); + wmWindow *win = CTX_wm_window(C); + WorkSpace *workspace = ED_workspace_duplicate(WM_window_get_active_workspace(win), bmain, win); + + WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, workspace); + + return OPERATOR_FINISHED; +} + +static void WORKSPACE_OT_workspace_duplicate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "New Workspace"; + ot->description = "Add a new workspace"; + ot->idname = "WORKSPACE_OT_workspace_duplicate"; + + /* api callbacks */ + ot->exec = workspace_new_exec; + ot->poll = WM_operator_winactive; +} + +static int workspace_delete_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); + + ED_workspace_delete(WM_window_get_active_workspace(win), bmain, C, wm); + + return OPERATOR_FINISHED; +} + +static void WORKSPACE_OT_workspace_delete(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Delete Workspace"; + ot->description = "Delete the active workspace"; + ot->idname = "WORKSPACE_OT_workspace_delete"; + + /* api callbacks */ + ot->exec = workspace_delete_exec; +} + +static void workspace_config_file_path_from_folder_id( + const Main *bmain, int folder_id, char *r_path) +{ + const char *app_template = U.app_template[0] ? U.app_template : NULL; + const char * const cfgdir = BKE_appdir_folder_id(folder_id, app_template); + + if (cfgdir) { + BLI_make_file_string(bmain->name, r_path, cfgdir, BLENDER_WORKSPACES_FILE); + } + else { + r_path[0] = '\0'; + } +} + +ATTR_NONNULL(1) +static WorkspaceConfigFileData *workspace_config_file_read( + const Main *bmain, ReportList *reports) +{ + char workspace_config_path[FILE_MAX]; + bool has_path = false; + + workspace_config_file_path_from_folder_id(bmain, BLENDER_USER_CONFIG, workspace_config_path); + if (BLI_exists(workspace_config_path)) { + has_path = true; + } + else { + workspace_config_file_path_from_folder_id(bmain, BLENDER_DATAFILES, workspace_config_path); + if (BLI_exists(workspace_config_path)) { + has_path = true; + } + } + + return has_path ? BKE_blendfile_workspace_config_read(workspace_config_path, reports) : NULL; +} + +static void workspace_append_button( + uiLayout *layout, wmOperatorType *ot_append, const WorkSpace *workspace, const Main *from_main) +{ + const ID *id = (ID *)workspace; + PointerRNA opptr; + char lib_path[FILE_MAX_LIBEXTRA]; + + BLI_path_join( + lib_path, sizeof(lib_path), from_main->name, BKE_idcode_to_name(GS(id->name)), NULL); + + BLI_assert(STREQ(ot_append->idname, "WM_OT_append")); + uiItemFullO_ptr( + layout, ot_append, workspace->id.name + 2, ICON_NONE, NULL, + WM_OP_EXEC_DEFAULT, 0, &opptr); + RNA_string_set(&opptr, "directory", lib_path); + RNA_string_set(&opptr, "filename", id->name + 2); +} + +ATTR_NONNULL(1, 2) +static void workspace_config_file_append_buttons( + uiLayout *layout, const Main *bmain, ReportList *reports) +{ + WorkspaceConfigFileData *workspace_config = workspace_config_file_read(bmain, reports); + + if (workspace_config) { + wmOperatorType *ot_append = WM_operatortype_find("WM_OT_append", true); + + for (WorkSpace *workspace = workspace_config->workspaces.first; workspace; workspace = workspace->id.next) { + workspace_append_button(layout, ot_append, workspace, workspace_config->main); + } + + BKE_blendfile_workspace_config_data_free(workspace_config); + } +} + +static int workspace_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + const Main *bmain = CTX_data_main(C); + + uiPopupMenu *pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE); + uiLayout *layout = UI_popup_menu_layout(pup); + + uiItemO(layout, "Duplicate Current", ICON_NONE, "WORKSPACE_OT_workspace_duplicate"); + uiItemS(layout); + workspace_config_file_append_buttons(layout, bmain, op->reports); + + UI_popup_menu_end(C, pup); + + return OPERATOR_INTERFACE; +} + +static void WORKSPACE_OT_workspace_add_menu(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Workspace"; + ot->description = "Add a new workspace by duplicating the current one or appending one " + "from the user configuration"; + ot->idname = "WORKSPACE_OT_workspace_add_menu"; + + /* api callbacks */ + ot->invoke = workspace_add_invoke; +} + +void ED_operatortypes_workspace(void) +{ + WM_operatortype_append(WORKSPACE_OT_workspace_duplicate); + WM_operatortype_append(WORKSPACE_OT_workspace_delete); + WM_operatortype_append(WORKSPACE_OT_workspace_add_menu); +} + +/** \} Workspace Operators */ diff --git a/source/blender/editors/screen/workspace_layout_edit.c b/source/blender/editors/screen/workspace_layout_edit.c new file mode 100644 index 00000000000..d84df160125 --- /dev/null +++ b/source/blender/editors/screen/workspace_layout_edit.c @@ -0,0 +1,197 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/screen/workspace_layout_edit.c + * \ingroup edscr + */ + +#include <stdlib.h> + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" + +#include "DNA_screen_types.h" +#include "DNA_workspace_types.h" + +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_screen.h" +#include "BKE_workspace.h" + +#include "WM_api.h" + +#include "ED_screen.h" + +#include "screen_intern.h" + +/** + * Empty screen, with 1 dummy area without spacedata. Uses window size. + */ +WorkSpaceLayout *ED_workspace_layout_add( + WorkSpace *workspace, + wmWindow *win, + const char *name) +{ + const int winsize_x = WM_window_pixels_x(win); + const int winsize_y = WM_window_pixels_y(win); + + bScreen *screen = screen_add(name, winsize_x, winsize_y); + WorkSpaceLayout *layout = BKE_workspace_layout_add(workspace, screen, name); + + return layout; +} + +WorkSpaceLayout *ED_workspace_layout_duplicate( + WorkSpace *workspace, const WorkSpaceLayout *layout_old, + wmWindow *win) +{ + bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old); + const char *name = BKE_workspace_layout_name_get(layout_old); + bScreen *screen_new; + WorkSpaceLayout *layout_new; + + if (BKE_screen_is_fullscreen_area(screen_old)) { + return NULL; /* XXX handle this case! */ + } + + layout_new = ED_workspace_layout_add(workspace, win, name); + screen_new = BKE_workspace_layout_screen_get(layout_new); + screen_data_copy(screen_new, screen_old); + + return layout_new; +} + +static bool workspace_layout_delete_doit( + WorkSpace *workspace, WorkSpaceLayout *layout_old, WorkSpaceLayout *layout_new, + bContext *C) +{ + Main *bmain = CTX_data_main(C); + wmWindow *win = CTX_wm_window(C); + bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new); + + ED_screen_change(C, screen_new); + + if (BKE_workspace_active_layout_get(win->workspace_hook) != layout_old) { + BKE_workspace_layout_remove(bmain, workspace, layout_old); + return true; + } + + return false; +} + +bool workspace_layout_set_poll(const WorkSpaceLayout *layout) +{ + const bScreen *screen = BKE_workspace_layout_screen_get(layout); + + return ((BKE_screen_is_used(screen) == false) && + /* in typical usage temp screens should have a nonzero winid + * (all temp screens should be used, or closed & freed). */ + (screen->temp == false) && + (BKE_screen_is_fullscreen_area(screen) == false) && + (screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT))); +} + +static WorkSpaceLayout *workspace_layout_delete_find_new(const WorkSpaceLayout *layout_old) +{ + for (WorkSpaceLayout *layout_new = layout_old->prev; layout_new; layout_new = layout_new->next) { + if (workspace_layout_set_poll(layout_new)) { + return layout_new; + } + } + + for (WorkSpaceLayout *layout_new = layout_old->next; layout_new; layout_new = layout_new->next) { + if (workspace_layout_set_poll(layout_new)) { + return layout_new; + } + } + + return NULL; +} + +/** + * \warning Only call outside of area/region loops! + * \return true if succeeded. + */ +bool ED_workspace_layout_delete( + WorkSpace *workspace, WorkSpaceLayout *layout_old, + bContext *C) +{ + const bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old); + WorkSpaceLayout *layout_new; + + BLI_assert(BLI_findindex(BKE_workspace_layouts_get(workspace), layout_old) != -1); + + /* don't allow deleting temp fullscreens for now */ + if (BKE_screen_is_fullscreen_area(screen_old)) { + return false; + } + + /* A layout/screen can only be in use by one window at a time, so as + * long as we are able to find a layout/screen that is unused, we + * can safely assume ours is not in use anywhere an delete it. */ + + layout_new = workspace_layout_delete_find_new(layout_old); + + if (layout_new) { + return workspace_layout_delete_doit(workspace, layout_old, layout_new, C); + } + + return false; +} + +static bool workspace_layout_cycle_iter_cb(const WorkSpaceLayout *layout, void *UNUSED(arg)) +{ + /* return false to stop iterator when we have found a layout to activate */ + return !workspace_layout_set_poll(layout); +} + +bool ED_workspace_layout_cycle( + WorkSpace *workspace, const short direction, bContext *C) +{ + wmWindow *win = CTX_wm_window(C); + WorkSpaceLayout *old_layout = BKE_workspace_active_layout_get(win->workspace_hook); + WorkSpaceLayout *new_layout; + const bScreen *old_screen = BKE_workspace_layout_screen_get(old_layout); + ScrArea *sa = CTX_wm_area(C); + + if (old_screen->temp || (sa && sa->full && sa->full->temp)) { + return false; + } + + BLI_assert(ELEM(direction, 1, -1)); + new_layout = BKE_workspace_layout_iter_circular(workspace, old_layout, workspace_layout_cycle_iter_cb, + NULL, (direction == -1) ? true : false); + + if (new_layout && (old_layout != new_layout)) { + bScreen *new_screen = BKE_workspace_layout_screen_get(new_layout); + + if (sa && sa->full) { + /* return to previous state before switching screens */ + ED_screen_full_restore(C, sa); /* may free screen of old_layout */ + } + + ED_screen_change(C, new_screen); + + return true; + } + + return false; +} diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 69f14c950bb..b3e125baae3 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -25,6 +25,7 @@ set(INC ../../blenlib ../../blentranslation ../../bmesh + ../../depsgraph ../../gpu ../../imbuf ../../makesdna diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index f0d9a0bbb68..e1e90506299 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -54,14 +54,14 @@ #include "WM_api.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" - #include "IMB_imbuf_types.h" #include "ED_view3d.h" -#include "GPU_basic_shader.h" +#include "GPU_draw.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" #include "UI_resources.h" @@ -336,8 +336,8 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima glBindTexture(GL_TEXTURE_2D, target->overlay_texture); if (refresh) { - GLenum format = col ? GL_RGBA : GL_ALPHA; - GLenum internalformat = col ? GL_RGBA8 : GL_ALPHA8; + GLenum format = col ? GL_RGBA : GL_RED; + GLenum internalformat = col ? GL_RGBA8 : GL_R8; if (!init || (target->old_col != col)) { glTexImage2D(GL_TEXTURE_2D, 0, internalformat, size, size, 0, format, GL_UNSIGNED_BYTE, buffer); @@ -352,8 +352,6 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima target->old_col = col; } - GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -460,18 +458,16 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom) if (refresh) { if (!init) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, size, size, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, size, size, 0, GL_RED, GL_UNSIGNED_BYTE, buffer); } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_ALPHA, GL_UNSIGNED_BYTE, buffer); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_RED, GL_UNSIGNED_BYTE, buffer); } if (buffer) MEM_freeN(buffer); } - GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -605,22 +601,20 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush, glDepthMask(GL_FALSE); glDepthFunc(GL_ALWAYS); - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - glLoadIdentity(); - if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { + gpuPushMatrix(); + /* brush rotation */ - glTranslatef(0.5, 0.5, 0); - glRotatef((double)RAD2DEGF((primary) ? ups->brush_rotation : ups->brush_rotation_sec), - 0.0, 0.0, 1.0); - glTranslatef(-0.5f, -0.5f, 0); + gpuTranslate2f(x, y); + gpuRotate2D(-RAD2DEGF(primary ? ups->brush_rotation : ups->brush_rotation_sec)); + gpuTranslate2f(-x, -y); /* scale based on tablet pressure */ if (primary && ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) { - glTranslatef(0.5f, 0.5f, 0); - glScalef(1.0f / ups->size_pressure_value, 1.0f / ups->size_pressure_value, 1); - glTranslatef(-0.5f, -0.5f, 0); + const float scale = ups->size_pressure_value; + gpuTranslate2f(x, y); + gpuScale2f(scale, scale); + gpuTranslate2f(-x, -y); } if (ups->draw_anchored) { @@ -658,41 +652,46 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush, quad.xmax = brush->mask_stencil_dimension[0]; quad.ymax = brush->mask_stencil_dimension[1]; } - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); + gpuPushMatrix(); if (primary) - glTranslate2fv(brush->stencil_pos); + gpuTranslate2fv(brush->stencil_pos); else - glTranslate2fv(brush->mask_stencil_pos); - glRotatef(RAD2DEGF(mtex->rot), 0, 0, 1); - glMatrixMode(GL_TEXTURE); + gpuTranslate2fv(brush->mask_stencil_pos); + gpuRotate2D(RAD2DEGF(mtex->rot)); } /* set quad color. Colored overlay does not get blending */ + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + if (col) { - glColor4f(1.0, 1.0, 1.0, overlay_alpha / 100.0f); + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); + immUniformColor4f(1.0f, 1.0f, 1.0f, overlay_alpha * 0.01f); } else { - glColor4f(UNPACK3(U.sculpt_paint_overlay_col), overlay_alpha / 100.0f); + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_ALPHA_COLOR); + immUniformColor3fvAlpha(U.sculpt_paint_overlay_col, overlay_alpha * 0.01f); } /* draw textured quad */ - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(quad.xmin, quad.ymin); - glTexCoord2f(1, 0); - glVertex2f(quad.xmax, quad.ymin); - glTexCoord2f(1, 1); - glVertex2f(quad.xmax, quad.ymax); - glTexCoord2f(0, 1); - glVertex2f(quad.xmin, quad.ymax); - glEnd(); - - glPopMatrix(); - - if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) { - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + immUniform1i("image", GL_TEXTURE0); + + immBegin(GWN_PRIM_TRI_FAN, 4); + immAttrib2f(texCoord, 0.0f, 0.0f); + immVertex2f(pos, quad.xmin, quad.ymin); + immAttrib2f(texCoord, 1.0f, 0.0f); + immVertex2f(pos, quad.xmax, quad.ymin); + immAttrib2f(texCoord, 1.0f, 1.0f); + immVertex2f(pos, quad.xmax, quad.ymax); + immAttrib2f(texCoord, 0.0f, 1.0f); + immVertex2f(pos, quad.xmin, quad.ymax); + immEnd(); + + immUnbindProgram(); + + if (ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_VIEW)) { + gpuPopMatrix(); } } } @@ -740,32 +739,41 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush, /* scale based on tablet pressure */ if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) { do_pop = true; - glPushMatrix(); - glLoadIdentity(); - glTranslate2fv(center); - glScalef(ups->size_pressure_value, ups->size_pressure_value, 1); - glTranslatef(-center[0], -center[1], 0); + gpuPushMatrix(); + gpuLoadIdentity(); + gpuTranslate2fv(center); + gpuScaleUniform(ups->size_pressure_value); + gpuTranslate2f(-center[0], -center[1]); } - glColor4f(U.sculpt_paint_overlay_col[0], - U.sculpt_paint_overlay_col[1], - U.sculpt_paint_overlay_col[2], - brush->cursor_overlay_alpha / 100.0f); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); + + immUniformColor3fvAlpha(U.sculpt_paint_overlay_col, brush->cursor_overlay_alpha * 0.01f); + + /* draw textured quad */ /* draw textured quad */ - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(quad.xmin, quad.ymin); - glTexCoord2f(1, 0); - glVertex2f(quad.xmax, quad.ymin); - glTexCoord2f(1, 1); - glVertex2f(quad.xmax, quad.ymax); - glTexCoord2f(0, 1); - glVertex2f(quad.xmin, quad.ymax); - glEnd(); + immUniform1i("image", GL_TEXTURE0); + + immBegin(GWN_PRIM_TRI_FAN, 4); + immAttrib2f(texCoord, 0.0f, 0.0f); + immVertex2f(pos, quad.xmin, quad.ymin); + immAttrib2f(texCoord, 1.0f, 0.0f); + immVertex2f(pos, quad.xmax, quad.ymin); + immAttrib2f(texCoord, 1.0f, 1.0f); + immVertex2f(pos, quad.xmax, quad.ymax); + immAttrib2f(texCoord, 0.0f, 1.0f); + immVertex2f(pos, quad.xmin, quad.ymax); + immEnd(); + + immUnbindProgram(); if (do_pop) - glPopMatrix(); + gpuPopMatrix(); } } @@ -775,19 +783,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush, /* color means that primary brush texture is colured and secondary is used for alpha/mask control */ bool col = ELEM(mode, ePaintTextureProjective, ePaintTexture2D, ePaintVertex) ? true : false; eOverlayControlFlags flags = BKE_paint_get_overlay_flags(); - /* save lots of GL state - * TODO: check on whether all of these are needed? */ - glPushAttrib(GL_COLOR_BUFFER_BIT | - GL_CURRENT_BIT | - GL_DEPTH_BUFFER_BIT | - GL_ENABLE_BIT | - GL_LINE_BIT | - GL_POLYGON_BIT | - GL_STENCIL_BUFFER_BIT | - GL_TRANSFORM_BIT | - GL_VIEWPORT_BIT | - GL_TEXTURE_BIT); - + gpuPushAttrib(GPU_DEPTH_BUFFER_BIT | GPU_BLEND_BIT); /* coloured overlay should be drawn separately */ if (col) { @@ -805,86 +801,98 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush, paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom); } - glPopAttrib(); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + gpuPopAttrib(); } -BLI_INLINE void draw_tri_point(float *co, float width, bool selected) +BLI_INLINE void draw_tri_point( + unsigned int pos, float sel_col[4], float pivot_col[4], + float *co, float width, bool selected) { + immUniformColor4fv(selected ? sel_col : pivot_col); + + glLineWidth(3.0f); + float w = width / 2.0f; - if (selected) - UI_ThemeColor4(TH_VERTEX_SELECT); - else - UI_ThemeColor4(TH_PAINT_CURVE_PIVOT); - - glLineWidth(3.0); - - glBegin(GL_LINE_LOOP); - glVertex2f(co[0], co[1] + w); - glVertex2f(co[0] - w, co[1] - w); - glVertex2f(co[0] + w, co[1] - w); - glEnd(); - - glColor4f(1.0, 1.0, 1.0, 0.5); - glLineWidth(1.0); - - glBegin(GL_LINE_LOOP); - glVertex2f(co[0], co[1] + w); - glVertex2f(co[0] - w, co[1] - w); - glVertex2f(co[0] + w, co[1] - w); - glEnd(); + float tri[3][2] = { + {co[0], co[1] + w}, + {co[0] - w, co[1] - w}, + {co[0] + w, co[1] - w}, + }; + + immBegin(GWN_PRIM_LINE_LOOP, 3); + immVertex2fv(pos, tri[0]); + immVertex2fv(pos, tri[1]); + immVertex2fv(pos, tri[2]); + immEnd(); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f); + glLineWidth(1.0f); + + immBegin(GWN_PRIM_LINE_LOOP, 3); + immVertex2fv(pos, tri[0]); + immVertex2fv(pos, tri[1]); + immVertex2fv(pos, tri[2]); + immEnd(); } -BLI_INLINE void draw_rect_point(float *co, float width, bool selected) +BLI_INLINE void draw_rect_point( + unsigned int pos, float sel_col[4], float handle_col[4], + float *co, float width, bool selected) { + immUniformColor4fv(selected ? sel_col : handle_col); + + glLineWidth(3.0f); + float w = width / 2.0f; - if (selected) - UI_ThemeColor4(TH_VERTEX_SELECT); - else - UI_ThemeColor4(TH_PAINT_CURVE_HANDLE); - glLineWidth(3.0); - - glBegin(GL_LINE_LOOP); - glVertex2f(co[0] + w, co[1] + w); - glVertex2f(co[0] - w, co[1] + w); - glVertex2f(co[0] - w, co[1] - w); - glVertex2f(co[0] + w, co[1] - w); - glEnd(); - - glColor4f(1.0, 1.0, 1.0, 0.5); - glLineWidth(1.0); - - glBegin(GL_LINE_LOOP); - glVertex2f(co[0] + w, co[1] + w); - glVertex2f(co[0] - w, co[1] + w); - glVertex2f(co[0] - w, co[1] - w); - glVertex2f(co[0] + w, co[1] - w); - glEnd(); + float minx = co[0] - w; + float miny = co[1] - w; + float maxx = co[0] + w; + float maxy = co[1] + w; + + imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f); + glLineWidth(1.0f); + + imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy); } -BLI_INLINE void draw_bezier_handle_lines(BezTriple *bez) +BLI_INLINE void draw_bezier_handle_lines(unsigned int pos, float sel_col[4], BezTriple *bez) { - short line1[] = {0, 1}; - short line2[] = {1, 2}; - - glVertexPointer(2, GL_FLOAT, 3 * sizeof(float), bez->vec); - glColor4f(0.0, 0.0, 0.0, 0.5); - glLineWidth(3.0); - glDrawArrays(GL_LINE_STRIP, 0, 3); - - glLineWidth(1.0); - if (bez->f1 || bez->f2) - UI_ThemeColor4(TH_VERTEX_SELECT); - else - glColor4f(1.0, 1.0, 1.0, 0.5); - glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, line1); - if (bez->f3 || bez->f2) - UI_ThemeColor4(TH_VERTEX_SELECT); - else - glColor4f(1.0, 1.0, 1.0, 0.5); - glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, line2); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f); + glLineWidth(3.0f); + + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2fv(pos, bez->vec[0]); + immVertex2fv(pos, bez->vec[1]); + immVertex2fv(pos, bez->vec[2]); + immEnd(); + + glLineWidth(1.0f); + + if (bez->f1 || bez->f2) { + immUniformColor4fv(sel_col); + } + else { + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f); + } + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(pos, bez->vec[0]); + immVertex2fv(pos, bez->vec[1]); + immEnd(); + + if (bez->f3 || bez->f2) { + immUniformColor4fv(sel_col); + } + else { + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f); + } + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(pos, bez->vec[1]); + immVertex2fv(pos, bez->vec[2]); + immEnd(); } static void paint_draw_curve_cursor(Brush *brush) @@ -896,18 +904,26 @@ static void paint_draw_curve_cursor(Brush *brush) glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - glEnableClientState(GL_VERTEX_ARRAY); /* draw the bezier handles and the curve segment between the current and next point */ + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + float selec_col[4], handle_col[4], pivot_col[4]; + UI_GetThemeColor4fv(TH_VERTEX_SELECT, selec_col); + UI_GetThemeColor4fv(TH_PAINT_CURVE_HANDLE, handle_col); + UI_GetThemeColor4fv(TH_PAINT_CURVE_PIVOT, pivot_col); + for (i = 0; i < pc->tot_points - 1; i++, cp++) { int j; PaintCurvePoint *cp_next = cp + 1; float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2]; /* use color coding to distinguish handles vs curve segments */ - draw_bezier_handle_lines(&cp->bez); - draw_tri_point(&cp->bez.vec[1][0], 10.0, cp->bez.f2); - draw_rect_point(&cp->bez.vec[0][0], 8.0, cp->bez.f1 || cp->bez.f2); - draw_rect_point(&cp->bez.vec[2][0], 8.0, cp->bez.f3 || cp->bez.f2); + draw_bezier_handle_lines(pos, selec_col, &cp->bez); + draw_tri_point(pos, selec_col, pivot_col, &cp->bez.vec[1][0], 10.0f, cp->bez.f2); + draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[0][0], 8.0f, cp->bez.f1 || cp->bez.f2); + draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[2][0], 8.0f, cp->bez.f3 || cp->bez.f2); for (j = 0; j < 2; j++) BKE_curve_forward_diff_bezier( @@ -917,25 +933,35 @@ static void paint_draw_curve_cursor(Brush *brush) cp_next->bez.vec[1][j], data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2])); - glVertexPointer(2, GL_FLOAT, 0, data); - glLineWidth(3.0); - glColor4f(0.0, 0.0, 0.0, 0.5); - glDrawArrays(GL_LINE_STRIP, 0, PAINT_CURVE_NUM_SEGMENTS + 1); + float (*v)[2] = (float(*)[2])data; + + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f); + glLineWidth(3.0f); + immBegin(GWN_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1); + for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) { + immVertex2fv(pos, v[j]); + } + immEnd(); - glLineWidth(1.0); - glColor4f(0.9, 0.9, 1.0, 0.5); - glDrawArrays(GL_LINE_STRIP, 0, PAINT_CURVE_NUM_SEGMENTS + 1); + immUniformColor4f(0.9f, 0.9f, 1.0f, 0.5f); + glLineWidth(1.0f); + immBegin(GWN_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1); + for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) { + immVertex2fv(pos, v[j]); + } + immEnd(); } /* draw last line segment */ - draw_bezier_handle_lines(&cp->bez); - draw_tri_point(&cp->bez.vec[1][0], 10.0, cp->bez.f2); - draw_rect_point(&cp->bez.vec[0][0], 8.0, cp->bez.f1 || cp->bez.f2); - draw_rect_point(&cp->bez.vec[2][0], 8.0, cp->bez.f3 || cp->bez.f2); + draw_bezier_handle_lines(pos, selec_col, &cp->bez); + draw_tri_point(pos, selec_col, pivot_col, &cp->bez.vec[1][0], 10.0f, cp->bez.f2); + draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[0][0], 8.0f, cp->bez.f1 || cp->bez.f2); + draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[2][0], 8.0f, cp->bez.f3 || cp->bez.f2); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - glDisableClientState(GL_VERTEX_ARRAY); + + immUnbindProgram(); } } @@ -989,11 +1015,6 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) Paint *paint = BKE_paint_get_active_from_context(C); Brush *brush = BKE_paint_brush(paint); ePaintMode mode = BKE_paintmode_get_active_from_context(C); - ViewContext vc; - float final_radius; - float translation[2]; - float outline_alpha, *outline_col; - float zoomx, zoomy; /* check that brush drawing is enabled */ if (ommit_cursor_drawing(paint, mode, brush)) @@ -1001,6 +1022,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) /* can't use stroke vc here because this will be called during * mouse over too, not just during a stroke */ + ViewContext vc; view3d_set_viewcontext(C, &vc); if (vc.rv3d && (vc.rv3d->rflag & RV3D_NAVIGATING)) { @@ -1013,15 +1035,15 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) return; } + float zoomx, zoomy; get_imapaint_zoom(C, &zoomx, &zoomy); zoomx = max_ff(zoomx, zoomy); /* set various defaults */ - translation[0] = x; - translation[1] = y; - outline_alpha = 0.5; - outline_col = brush->add_col; - final_radius = (BKE_brush_size_get(scene, brush) * zoomx); + const float *outline_col = brush->add_col; + const float outline_alpha = 0.5f; + float translation[2] = { x, y }; + float final_radius = (BKE_brush_size_get(scene, brush) * zoomx); /* don't calculate rake angles while a stroke is active because the rake variables are global and * we may get interference with the stroke itself. For line strokes, such interference is visible */ @@ -1037,10 +1059,9 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) if ((mode == ePaintSculpt) && vc.obact->sculpt) { float location[3]; int pixel_radius; - bool hit; /* test if brush is over the mesh */ - hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location, ups); + bool hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location, ups); if (BKE_brush_use_locked_size(scene, brush)) BKE_brush_size_set(scene, brush, pixel_radius); @@ -1067,24 +1088,25 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) /* make lines pretty */ glLineWidth(1.0f); - glEnable(GL_BLEND); + glEnable(GL_BLEND); /* TODO: also set blend mode? */ glEnable(GL_LINE_SMOOTH); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* set brush color */ - glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha); + immUniformColor3fvAlpha(outline_col, outline_alpha); /* draw brush outline */ - glTranslate2fv(translation); - - /* draw an inner brush */ if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) { /* inner at full alpha */ - glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius * ups->size_pressure_value, 40); + imm_draw_circle_wire_2d(pos, translation[0], translation[1], final_radius * ups->size_pressure_value, 40); /* outer at half alpha */ - glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha * 0.5f); + immUniformColor3fvAlpha(outline_col, outline_alpha * 0.5f); } - glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius, 40); - glTranslatef(-translation[0], -translation[1], 0); + imm_draw_circle_wire_2d(pos, translation[0], translation[1], final_radius, 40); + + immUnbindProgram(); /* restore GL state */ glDisable(GL_BLEND); diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index d085c6953da..8377b22756e 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -52,7 +52,7 @@ #include "BKE_paint.h" #include "BKE_subsurf.h" -#include "BIF_glutil.h" +#include "DEG_depsgraph.h" #include "WM_api.h" #include "WM_types.h" @@ -323,12 +323,10 @@ static void clip_planes_from_rect(bContext *C, { ViewContext vc; BoundBox bb; - bglMats mats = {{0}}; view3d_operator_needs_opengl(C); view3d_set_viewcontext(C, &vc); - view3d_get_transformation(vc.ar, vc.rv3d, vc.obact, &mats); - ED_view3d_clipping_calc(&bb, clip_planes, &mats, rect); + ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, rect); negate_m4(clip_planes); } @@ -364,6 +362,7 @@ static int hide_show_exec(bContext *C, wmOperator *op) { ARegion *ar = CTX_wm_region(C); Object *ob = CTX_data_active_object(C); + EvaluationContext eval_ctx; Mesh *me = ob->data; PartialVisAction action; PartialVisArea area; @@ -375,6 +374,8 @@ static int hide_show_exec(bContext *C, wmOperator *op) rcti rect; int totnode, i; + CTX_data_eval_ctx(C, &eval_ctx); + /* read operator properties */ action = RNA_enum_get(op->ptr, "action"); area = RNA_enum_get(op->ptr, "area"); @@ -382,7 +383,7 @@ static int hide_show_exec(bContext *C, wmOperator *op) clip_planes_from_rect(C, clip_planes, &rect); - dm = mesh_get_derived_final(CTX_data_scene(C), ob, CD_MASK_BAREMESH); + dm = mesh_get_derived_final(&eval_ctx, CTX_data_scene(C), ob, CD_MASK_BAREMESH); pbvh = dm->getPBVH(ob, dm); ob->sculpt->pbvh = pbvh; diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 6b197bbb392..92ab30f7f3d 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -51,7 +51,6 @@ #include "DNA_object_types.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_brush.h" #include "BKE_image.h" @@ -61,6 +60,8 @@ #include "BKE_paint.h" #include "BKE_texture.h" +#include "DEG_depsgraph.h" + #include "UI_interface.h" #include "UI_view2d.h" @@ -78,9 +79,9 @@ #include "GPU_draw.h" #include "GPU_buffers.h" +#include "GPU_immediate.h" #include "BIF_gl.h" -#include "BIF_glutil.h" #include "IMB_colormanagement.h" @@ -372,7 +373,7 @@ void ED_image_undo_restore(bContext *C, ListBase *lb) ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; - DAG_id_tag_update(&ima->id, 0); + DEG_id_tag_update(&ima->id, 0); BKE_image_release_ibuf(ima, ibuf, NULL); } @@ -721,12 +722,28 @@ static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customda glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + glLineWidth(4.0); - glColor4ub(0, 0, 0, 255); - sdrawline(x, y, pop->startmouse[0], pop->startmouse[1]); + immUniformColor4ub(0, 0, 0, 255); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2i(pos, x, y); + immVertex2i(pos, pop->startmouse[0], pop->startmouse[1]); + immEnd(); + glLineWidth(2.0); - glColor4ub(255, 255, 255, 255); - sdrawline(x, y, pop->startmouse[0], pop->startmouse[1]); + immUniformColor4ub(255, 255, 255, 255); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2i(pos, x, y); + immVertex2i(pos, pop->startmouse[0], pop->startmouse[1]); + immEnd(); + + immUnbindProgram(); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); @@ -748,7 +765,8 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo /* initialize from context */ if (CTX_wm_region_view3d(C)) { - Object *ob = OBACT; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = OBACT(sl); bool uvs, mat, tex, stencil; if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, &stencil)) { BKE_paint_data_warning(op->reports, uvs, mat, tex, stencil); @@ -1039,16 +1057,20 @@ static void toggle_paint_cursor(bContext *C, int enable) void ED_space_image_paint_update(wmWindowManager *wm, Scene *scene) { ToolSettings *settings = scene->toolsettings; - wmWindow *win; - ScrArea *sa; ImagePaintSettings *imapaint = &settings->imapaint; bool enabled = false; - for (win = wm->windows.first; win; win = win->next) - for (sa = win->screen->areabase.first; sa; sa = sa->next) - if (sa->spacetype == SPACE_IMAGE) - if (((SpaceImage *)sa->spacedata.first)->mode == SI_MODE_PAINT) + for (wmWindow *win = wm->windows.first; win; win = win->next) { + bScreen *screen = WM_window_get_active_screen(win); + + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_IMAGE) { + if (((SpaceImage *)sa->spacedata.first)->mode == SI_MODE_PAINT) { enabled = true; + } + } + } + } if (enabled) { BKE_paint_init(scene, ePaintTexture2D, PAINT_CURSOR_TEXTURE_PAINT); @@ -1517,7 +1539,7 @@ void ED_imapaint_bucket_fill(struct bContext *C, float color[3], wmOperator *op) ED_undo_paint_push_end(UNDO_PAINT_IMAGE); - DAG_id_tag_update(&ima->id, 0); + DEG_id_tag_update(&ima->id, 0); } diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index 09b0847b306..30830e4e7bc 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -45,13 +45,14 @@ #include "BLI_task.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_brush.h" #include "BKE_image.h" #include "BKE_paint.h" #include "BKE_report.h" #include "BKE_texture.h" +#include "DEG_depsgraph.h" + #include "ED_paint.h" #include "ED_screen.h" @@ -1359,7 +1360,7 @@ void paint_2d_redraw(const bContext *C, void *ps, bool final) /* compositor listener deals with updating */ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image); - DAG_id_tag_update(&s->image->id, 0); + DEG_id_tag_update(&s->image->id, 0); } else { if (!s->sima || !s->sima->lock) diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index ae6dbbf440c..2f4a28963fe 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -64,7 +64,6 @@ #include "BKE_camera.h" #include "BKE_context.h" #include "BKE_colortools.h" -#include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_idprop.h" #include "BKE_brush.h" @@ -80,6 +79,8 @@ #include "BKE_scene.h" #include "BKE_texture.h" +#include "DEG_depsgraph.h" + #include "UI_interface.h" #include "ED_mesh.h" @@ -3420,12 +3421,15 @@ static void project_paint_bleed_add_face_user( #endif /* Return true if DM can be painted on, false otherwise */ -static bool proj_paint_state_dm_init(ProjPaintState *ps) +static bool proj_paint_state_dm_init(const bContext *C, ProjPaintState *ps) { + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + /* Workaround for subsurf selection, try the display mesh first */ if (ps->source == PROJ_SRC_IMAGE_CAM) { /* using render mesh, assume only camera was rendered from */ - ps->dm = mesh_create_derived_render(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE); + ps->dm = mesh_create_derived_render(&eval_ctx, ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE); ps->dm_release = true; } else if (ps->ob->derivedFinal && @@ -3437,7 +3441,7 @@ static bool proj_paint_state_dm_init(ProjPaintState *ps) } else { ps->dm = mesh_get_derived_final( - ps->scene, ps->ob, + &eval_ctx, ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE | (ps->do_face_sel ? CD_ORIGINDEX : 0)); ps->dm_release = true; } @@ -3487,7 +3491,7 @@ static void proj_paint_layer_clone_init( /* use clone mtface? */ if (ps->do_layer_clone) { - const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY); + const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV); ps->dm_mloopuv_clone = MEM_mallocN(ps->dm_totpoly * sizeof(MLoopUV *), "proj_paint_mtfaces"); @@ -3817,7 +3821,7 @@ static void project_paint_prepare_all_faces( /* run once per stroke before projection painting */ static void project_paint_begin( - ProjPaintState *ps, + const bContext *C, ProjPaintState *ps, const bool is_multi_view, const char symmetry_flag) { ProjPaintLayerClone layer_clone; @@ -3840,7 +3844,7 @@ static void project_paint_begin( /* paint onto the derived mesh */ if (ps->is_shared_user == false) { - if (!proj_paint_state_dm_init(ps)) { + if (!proj_paint_state_dm_init(C, ps)) { return; } } @@ -3850,7 +3854,7 @@ static void project_paint_begin( if (ps->do_layer_stencil || ps->do_stencil_brush) { //int layer_num = CustomData_get_stencil_layer(&ps->dm->loopData, CD_MLOOPUV); - int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY); + int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV); if (layer_num != -1) ps->dm_mloopuv_stencil = CustomData_get_layer_n(&ps->dm->loopData, CD_MLOOPUV, layer_num); @@ -3938,7 +3942,7 @@ static void project_paint_end(ProjPaintState *ps) ProjPaintImage *projIma; for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) { BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL); - DAG_id_tag_update(&projIma->ima->id, 0); + DEG_id_tag_update(&projIma->ima->id, 0); } } @@ -5023,7 +5027,9 @@ void paint_proj_stroke( /* clone gets special treatment here to avoid going through image initialization */ if (ps_handle->is_clone_cursor_pick) { + EvaluationContext eval_ctx; Scene *scene = ps_handle->scene; + struct Depsgraph *graph = CTX_data_depsgraph(C); View3D *v3d = CTX_wm_view3d(C); ARegion *ar = CTX_wm_region(C); float *cursor = ED_view3d_cursor3d_get(scene, v3d); @@ -5031,8 +5037,11 @@ void paint_proj_stroke( view3d_operator_needs_opengl(C); - if (!ED_view3d_autodist(scene, ar, v3d, mval_i, cursor, false, NULL)) + CTX_data_eval_ctx(C, &eval_ctx); + + if (!ED_view3d_autodist(&eval_ctx, graph, ar, v3d, mval_i, cursor, false, NULL)) { return; + } ED_region_tag_redraw(ar); @@ -5210,7 +5219,7 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m project_state_init(C, ob, ps, mode); - if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) { + if (ps->ob == NULL) { ps_handle->ps_views_tot = i + 1; goto fail; } @@ -5234,7 +5243,7 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m PROJ_PAINT_STATE_SHARED_MEMCPY(ps, ps_handle->ps_views[0]); } - project_paint_begin(ps, is_multi_view, symmetry_flag_views[i]); + project_paint_begin(C, ps, is_multi_view, symmetry_flag_views[i]); paint_proj_begin_clone(ps, mouse); @@ -5312,11 +5321,12 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) { Image *image = BLI_findlink(&CTX_data_main(C)->image, RNA_enum_get(op->ptr, "image")); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); ProjPaintState ps = {NULL}; int orig_brush_size; IDProperty *idgroup; IDProperty *view_data = NULL; - Object *ob = OBACT; + Object *ob = OBACT(sl); bool uvs, mat, tex; if (ob == NULL || ob->type != OB_MESH) { @@ -5387,7 +5397,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) ED_image_undo_restore, ED_image_undo_free, NULL); /* allocate and initialize spatial data structures */ - project_paint_begin(&ps, false, 0); + project_paint_begin(C, &ps, false, 0); if (ps.dm == NULL) { BKE_brush_size_set(scene, ps.brush, orig_brush_size); @@ -5445,12 +5455,16 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) char filename[FILE_MAX]; Scene *scene = CTX_data_scene(C); + SceneLayer *scene_layer = CTX_data_scene_layer(C); + EvaluationContext eval_ctx; ToolSettings *settings = scene->toolsettings; int w = settings->imapaint.screen_grab_size[0]; int h = settings->imapaint.screen_grab_size[1]; int maxsize; char err_out[256] = "unknown"; + CTX_data_eval_ctx(C, &eval_ctx); + RNA_string_get(op->ptr, "filepath", filename); maxsize = GPU_max_texture_size(); @@ -5459,7 +5473,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) if (h > maxsize) h = maxsize; ibuf = ED_view3d_draw_offscreen_imbuf( - scene, CTX_wm_view3d(C), CTX_wm_region(C), + &eval_ctx, scene, scene_layer, CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, false, R_ALPHAPREMUL, 0, false, NULL, NULL, NULL, err_out); if (!ibuf) { @@ -5593,7 +5607,7 @@ bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *m } me = BKE_mesh_from_object(ob); - layernum = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); + layernum = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); if (layernum == 0) { hasuvs = false; @@ -5742,7 +5756,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op) BKE_texpaint_slot_refresh_cache(scene, ma); BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE); WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima); - DAG_id_tag_update(&ma->id, 0); + DEG_id_tag_update(&ma->id, 0); ED_area_tag_redraw(CTX_wm_area(C)); BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); @@ -5858,7 +5872,7 @@ static int texture_paint_delete_texture_paint_slot_exec(bContext *C, wmOperator ma->mtex[slot->index] = NULL; BKE_texpaint_slot_refresh_cache(scene, ma); - DAG_id_tag_update(&ma->id, 0); + DEG_id_tag_update(&ma->id, 0); WM_event_add_notifier(C, NC_MATERIAL, ma); /* we need a notifier for data change since we change the displayed modifier uvs */ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); @@ -5916,7 +5930,7 @@ static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op)) BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); - DAG_id_tag_update(ob->data, 0); + DEG_id_tag_update(ob->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 48fcf0596e3..28d9dfe13b0 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -155,10 +155,10 @@ void PAINT_OT_weight_sample_group(struct wmOperatorType *ot); /* paint_vertex_proj.c */ struct VertProjHandle; struct VertProjHandle *ED_vpaint_proj_handle_create( - struct Scene *scene, struct Object *ob, + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct DMCoNo **r_vcosnos); void ED_vpaint_proj_handle_update( - struct VertProjHandle *vp_handle, + const struct EvaluationContext *eval_ctx, struct VertProjHandle *vp_handle, /* runtime vars */ struct ARegion *ar, const float mval_fl[2]); void ED_vpaint_proj_handle_free( @@ -237,7 +237,6 @@ bool paint_convert_bb_to_rect(struct rcti *rect, * 2D screens-space bounding box into four 3D planes) */ void paint_calc_redraw_planes(float planes[4][4], const struct ARegion *ar, - struct RegionView3D *rv3d, struct Object *ob, const struct rcti *screen_rect); diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 3b1b993a3e3..0fec4c4fc80 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -35,8 +35,6 @@ #include "DNA_meshdata_types.h" #include "DNA_object_types.h" -#include "BIF_glutil.h" - #include "BLI_bitmap_draw_2d.h" #include "BLI_math_matrix.h" #include "BLI_math_geom.h" @@ -52,6 +50,8 @@ #include "BKE_paint.h" #include "BKE_subsurf.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -131,6 +131,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) ARegion *ar = CTX_wm_region(C); struct Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); + EvaluationContext eval_ctx; PaintMaskFloodMode mode; float value; PBVH *pbvh; @@ -139,10 +140,12 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) bool multires; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + CTX_data_eval_ctx(C, &eval_ctx); + mode = RNA_enum_get(op->ptr, "mode"); value = RNA_float_get(op->ptr, "value"); - BKE_sculpt_update_mesh_elements(scene, sd, ob, false, true); + BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, false, true); pbvh = ob->sculpt->pbvh; multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS); @@ -249,9 +252,9 @@ static void mask_box_select_task_cb(void *userdata, const int i) int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *rect, bool select, bool UNUSED(extend)) { + EvaluationContext eval_ctx; Sculpt *sd = vc->scene->toolsettings->sculpt; BoundBox bb; - bglMats mats = {{0}}; float clip_planes[4][4]; float clip_planes_final[4][4]; ARegion *ar = vc->ar; @@ -265,15 +268,16 @@ int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *r int totnode, symmpass; int symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL; + CTX_data_eval_ctx(C, &eval_ctx); + mode = PAINT_MASK_FLOOD_VALUE; value = select ? 1.0 : 0.0; /* transform the clip planes in object space */ - view3d_get_transformation(vc->ar, vc->rv3d, vc->obact, &mats); - ED_view3d_clipping_calc(&bb, clip_planes, &mats, rect); + ED_view3d_clipping_calc(&bb, clip_planes, vc->ar, vc->obact, rect); negate_m4(clip_planes); - BKE_sculpt_update_mesh_elements(scene, sd, ob, false, true); + BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, false, true); pbvh = ob->sculpt->pbvh; multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS); @@ -409,9 +413,9 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); if (mcords) { + EvaluationContext eval_ctx; float clip_planes[4][4], clip_planes_final[4][4]; BoundBox bb; - bglMats mats = {{0}}; Object *ob; ViewContext vc; LassoMaskData data; @@ -425,11 +429,12 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) PaintMaskFloodMode mode = RNA_enum_get(op->ptr, "mode"); float value = RNA_float_get(op->ptr, "value"); + CTX_data_eval_ctx(C, &eval_ctx); + /* Calculations of individual vertices are done in 2D screen space to diminish the amount of * calculations done. Bounding box PBVH collision is not computed against enclosing rectangle * of lasso */ view3d_set_viewcontext(C, &vc); - view3d_get_transformation(vc.ar, vc.rv3d, vc.obact, &mats); /* lasso data calculations */ data.vc = &vc; @@ -445,10 +450,10 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) mcords, mcords_tot, mask_lasso_px_cb, &data); - ED_view3d_clipping_calc(&bb, clip_planes, &mats, &data.rect); + ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, &data.rect); negate_m4(clip_planes); - BKE_sculpt_update_mesh_elements(scene, sd, ob, false, true); + BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, false, true); pbvh = ob->sculpt->pbvh; multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 2c8e88e3ccb..dacaea6a96e 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -51,6 +51,7 @@ #include "BKE_curve.h" #include "BKE_colortools.h" #include "BKE_image.h" +#include "BKE_mesh.h" #include "WM_api.h" #include "WM_types.h" @@ -58,7 +59,7 @@ #include "BIF_gl.h" #include "BIF_glutil.h" -#include "GPU_basic_shader.h" +#include "GPU_immediate.h" #include "ED_screen.h" #include "ED_view3d.h" @@ -145,9 +146,18 @@ static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata if (stroke && brush) { glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - glColor4ubv(paint->paint_cursor_col); - sdrawline(x, y, (int)stroke->last_mouse_position[0], - (int)stroke->last_mouse_position[1]); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv(paint->paint_cursor_col); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, x, y); + immVertex2f(pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]); + immEnd(); + + immUnbindProgram(); + glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); } @@ -159,36 +169,35 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata) PaintStroke *stroke = customdata; glEnable(GL_LINE_SMOOTH); - glEnable(GL_BLEND); - GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); - GPU_basic_shader_line_stipple(3, 0xAAAA); - GPU_basic_shader_line_width(3.0); + uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - glColor4ub(0, 0, 0, paint->paint_cursor_col[3]); - if (stroke->constrain_line) { - sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1], - stroke->constrained_pos[0], stroke->constrained_pos[1]); - } - else { - sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1], - x, y); - } + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 2); /* "advanced" mode */ + const float alpha = (float)paint->paint_cursor_col[3] / 255.0f; + immUniformArray4fv("colors", (float *)(float[][4]){{0.0f, 0.0f, 0.0f, alpha}, {1.0f, 1.0f, 1.0f, alpha}}, 2); + immUniform1f("dash_width", 6.0f); + + immBegin(GWN_PRIM_LINES, 2); - glColor4ub(255, 255, 255, paint->paint_cursor_col[3]); - GPU_basic_shader_line_width(1.0); if (stroke->constrain_line) { - sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1], - stroke->constrained_pos[0], stroke->constrained_pos[1]); + immVertex2f(shdr_pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]); + immVertex2f(shdr_pos, stroke->constrained_pos[0], stroke->constrained_pos[1]); } else { - sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1], - x, y); + immVertex2f(shdr_pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]); + immVertex2f(shdr_pos, x, y); } - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); + immEnd(); + + immUnbindProgram(); - glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); } diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 1c2ab442e95..6eadf373da4 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -56,11 +56,13 @@ #include "BKE_paint.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" +#include "GPU_glew.h" +#include "GPU_matrix.h" #include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" @@ -130,17 +132,12 @@ bool paint_convert_bb_to_rect(rcti *rect, * 2D screens-space bounding box into four 3D planes) */ void paint_calc_redraw_planes(float planes[4][4], const ARegion *ar, - RegionView3D *rv3d, Object *ob, const rcti *screen_rect) { BoundBox bb; - bglMats mats; rcti rect; - memset(&bb, 0, sizeof(BoundBox)); - view3d_get_transformation(ar, rv3d, ob, &mats); - /* use some extra space just in case */ rect = *screen_rect; rect.xmin -= 2; @@ -148,7 +145,7 @@ void paint_calc_redraw_planes(float planes[4][4], rect.ymin -= 2; rect.ymax += 2; - ED_view3d_clipping_calc(&bb, planes, &mats, &rect); + ED_view3d_clipping_calc(&bb, planes, ar, ob, &rect); negate_m4(planes); } @@ -277,9 +274,9 @@ static void imapaint_tri_weights(float matrix[4][4], GLint view[4], } /* compute uv coordinates of mouse in face */ -static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2]) +static void imapaint_pick_uv(EvaluationContext *eval_ctx, Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2]) { - DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH); const int tottri = dm->getNumLoopTri(dm); int i, findex; float p[2], w[3], absw, minabsw; @@ -293,8 +290,8 @@ static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, c /* get the needed opengl matrices */ glGetIntegerv(GL_VIEWPORT, view); - glGetFloatv(GL_MODELVIEW_MATRIX, (float *)matrix); - glGetFloatv(GL_PROJECTION_MATRIX, (float *)proj); + gpuGetModelViewMatrix(matrix); + gpuGetProjectionMatrix(proj); view[0] = view[1] = 0; mul_m4_m4m4(matrix, matrix, ob->obmat); mul_m4_m4m4(matrix, proj, matrix); @@ -355,13 +352,15 @@ static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, c } /* returns 0 if not found, otherwise 1 */ -static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *r_index, unsigned int totpoly) +static int imapaint_pick_face( + const struct EvaluationContext *eval_ctx, ViewContext *vc, const int mval[2], + unsigned int *r_index, unsigned int totpoly) { if (totpoly == 0) return 0; /* sample only on the exact position */ - *r_index = ED_view3d_backbuf_sample(vc, mval[0], mval[1]); + *r_index = ED_view3d_backbuf_sample(eval_ctx, vc, mval[0], mval[1]); if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) { return 0; @@ -427,6 +426,7 @@ void flip_qt_qt(float out[4], const float in[4], const char symm) void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_proj, bool use_palette) { Scene *scene = CTX_data_scene(C); + EvaluationContext eval_ctx; Paint *paint = BKE_paint_get_active_from_context(C); Palette *palette = BKE_paint_palette(paint); PaletteColor *color = NULL; @@ -434,6 +434,8 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr unsigned int col; const unsigned char *cp; + CTX_data_eval_ctx(C, &eval_ctx); + CLAMP(x, 0, ar->winx); CLAMP(y, 0, ar->winy); @@ -450,14 +452,15 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr if (CTX_wm_view3d(C) && texpaint_proj) { /* first try getting a colour directly from the mesh faces if possible */ - Object *ob = OBACT; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = OBACT(sl); bool sample_success = false; ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL); if (ob) { Mesh *me = (Mesh *)ob->data; - DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + DerivedMesh *dm = mesh_get_derived_final(&eval_ctx, scene, ob, CD_MASK_BAREMESH); ViewContext vc; const int mval[2] = {x, y}; @@ -469,7 +472,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr view3d_operator_needs_opengl(C); - if (imapaint_pick_face(&vc, mval, &faceindex, totpoly)) { + if (imapaint_pick_face(&eval_ctx, &vc, mval, &faceindex, totpoly)) { Image *image; if (use_material) @@ -482,7 +485,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr if (ibuf && ibuf->rect) { float uv[2]; float u, v; - imapaint_pick_uv(scene, ob, faceindex, mval, uv); + imapaint_pick_uv(&eval_ctx, scene, ob, faceindex, mval, uv); sample_success = true; u = fmodf(uv[0], 1.0f); @@ -564,8 +567,9 @@ static int brush_curve_preset_exec(bContext *C, wmOperator *op) if (br) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape")); - BKE_paint_invalidate_cursor_overlay(scene, br->curve); + BKE_paint_invalidate_cursor_overlay(scene, sl, br->curve); } return OPERATOR_FINISHED; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index d61777a6d12..d9df8c78ba9 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -54,7 +54,6 @@ #include "BKE_brush.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_deform.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" @@ -63,6 +62,8 @@ #include "BKE_report.h" #include "BKE_subsurf.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -937,11 +938,11 @@ static void do_weight_paint_vertex( /* Toggle operator for turning vertex paint mode on or off (copied from sculpt.c) */ -static void vertex_paint_init_session(Scene *scene, Object *ob) +static void vertex_paint_init_session(const EvaluationContext *eval_ctx, Scene *scene, Object *ob) { if (ob->sculpt == NULL) { ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session"); - BKE_sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, 0, false); + BKE_sculpt_update_mesh_elements(eval_ctx, scene, scene->toolsettings->sculpt, ob, 0, false); } } @@ -1070,6 +1071,10 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op) paint_cursor_delete_textures(); } else { + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); + ob->mode |= mode_flag; if (wp == NULL) @@ -1087,15 +1092,17 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op) if (ob->sculpt) { BKE_sculptsession_free(ob); } - vertex_paint_init_session(scene, ob); + vertex_paint_init_session(&eval_ctx, scene, ob); } + BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL); + /* Weightpaint works by overriding colors in mesh, * so need to make sure we recalc on enter and * exit (exit needs doing regardless because we * should redeform). */ - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene); @@ -1278,11 +1285,14 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo bool *defbase_sel; SculptSession *ss = ob->sculpt; VPaint *vp = CTX_data_tool_settings(C)->wpaint; + EvaluationContext eval_ctx; if (ED_wpaint_ensure_data(C, op->reports, WPAINT_ENSURE_MIRROR, &vgroup_index) == false) { return false; } + CTX_data_eval_ctx(C, &eval_ctx); + { /* check if we are attempting to paint onto a locked vertex group, * and other options disallow it from doing anything useful */ @@ -1381,7 +1391,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo } /* If not previously created, create vertex/weight paint mode session data */ - vertex_paint_init_session(scene, ob); + vertex_paint_init_session(&eval_ctx, scene, ob); vwpaint_update_cache_invariants(C, vp, ss, op, mouse); vertex_paint_init_session_data(ts, ob); @@ -2021,7 +2031,9 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P /* also needed for "View Selected" on last stroke */ paint_last_stroke_update(scene, vc->ar, mval); - DAG_id_tag_update(ob->data, 0); + BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL); + + DEG_id_tag_update(ob->data, 0); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); swap_m4m4(wpd->vc.rv3d->persmat, mat); @@ -2085,7 +2097,7 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) } } - DAG_id_tag_update(ob->data, 0); + DEG_id_tag_update(ob->data, 0); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -2204,6 +2216,10 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op) paint_cursor_delete_textures(); } else { + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); + ob->mode |= mode_flag; ED_mesh_color_ensure(me, NULL); @@ -2223,11 +2239,13 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op) } BKE_sculptsession_free(ob); } - vertex_paint_init_session(scene, ob); + vertex_paint_init_session(&eval_ctx, scene, ob); } + BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL); + /* update modifier stack for mapping requirements */ - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene); @@ -2313,6 +2331,9 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f Object *ob = CTX_data_active_object(C); Mesh *me; SculptSession *ss = ob->sculpt; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); /* context checks could be a poll() */ me = BKE_mesh_from_object(ob); @@ -2360,12 +2381,12 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f /* Create projection handle */ if (vpd->is_texbrush) { ob->sculpt->building_vp_handle = true; - vpd->vp_handle = ED_vpaint_proj_handle_create(scene, ob, &vpd->vertexcosnos); + vpd->vp_handle = ED_vpaint_proj_handle_create(&eval_ctx, scene, ob, &vpd->vertexcosnos); ob->sculpt->building_vp_handle = false; } /* If not previously created, create vertex/weight paint mode session data */ - vertex_paint_init_session(scene, ob); + vertex_paint_init_session(&eval_ctx, scene, ob); vwpaint_update_cache_invariants(C, vp, ss, op, mouse); vertex_paint_init_session_data(ts, ob); @@ -2937,6 +2958,8 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P swap_m4m4(vc->rv3d->persmat, mat); + BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL); + if (vp->paint.brush->vertexpaint_tool == PAINT_BLEND_SMEAR) { memcpy(vpd->smear.color_prev, vpd->smear.color_curr, sizeof(uint) * ((Mesh *)ob->data)->totloop); } @@ -2950,7 +2973,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P if (vpd->use_fast_update == false) { /* recalculate modifier stack to get new colors, slow, * avoid this if we can! */ - DAG_id_tag_update(ob->data, 0); + DEG_id_tag_update(ob->data, 0); } else { /* If using new VBO drawing, mark mcol as dirty to force colors gpu buffer refresh! */ @@ -3049,3 +3072,4 @@ void PAINT_OT_vertex_paint(wmOperatorType *ot) paint_stroke_operator_properties(ot); } + diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c index b69ca32e5af..d7668a48139 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c @@ -33,10 +33,11 @@ #include "BLI_math_color.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_mesh.h" #include "BKE_deform.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -97,7 +98,7 @@ static bool vertex_color_set(Object *ob, uint paintcol) /* remove stale me->mcol, will be added later */ BKE_mesh_tessface_clear(me); - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); return true; } @@ -168,7 +169,7 @@ static bool vertex_paint_from_weight(Object *ob) } while (j < mp->totloop); } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); return true; } @@ -304,7 +305,7 @@ static bool vertex_color_smooth(Object *ob) MEM_freeN(mlooptag); - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); return true; } diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c b/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c index 398512287c4..a8045232e05 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c @@ -38,9 +38,10 @@ #include "IMB_colormanagement.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_mesh.h" +#include "DEG_depsgraph.h" + #include "ED_mesh.h" #include "paint_intern.h" /* own include */ @@ -87,7 +88,7 @@ bool ED_vpaint_color_transform( /* remove stale me->mcol, will be added later */ BKE_mesh_tessface_clear(me); - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); return true; } diff --git a/source/blender/editors/sculpt_paint/paint_vertex_proj.c b/source/blender/editors/sculpt_paint/paint_vertex_proj.c index c939eb6df35..999c9dc7880 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_proj.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_proj.c @@ -42,6 +42,8 @@ #include "BKE_DerivedMesh.h" #include "BKE_context.h" +#include "DEG_depsgraph.h" + #include "ED_screen.h" #include "ED_view3d.h" @@ -98,13 +100,14 @@ static void vpaint_proj_dm_map_cosnos_init__map_cb(void *userData, int index, co } } -static void vpaint_proj_dm_map_cosnos_init(Scene *scene, Object *ob, - struct VertProjHandle *vp_handle) +static void vpaint_proj_dm_map_cosnos_init( + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, + struct VertProjHandle *vp_handle) { Mesh *me = ob->data; DerivedMesh *dm; - dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); + dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); if (dm->foreachMappedVert) { memset(vp_handle->vcosnos, 0, sizeof(DMCoNo) * me->totvert); @@ -169,8 +172,9 @@ static void vpaint_proj_dm_map_cosnos_update__map_cb(void *userData, int index, } } -static void vpaint_proj_dm_map_cosnos_update(struct VertProjHandle *vp_handle, - ARegion *ar, const float mval_fl[2]) +static void vpaint_proj_dm_map_cosnos_update( + const struct EvaluationContext *eval_ctx, struct VertProjHandle *vp_handle, + ARegion *ar, const float mval_fl[2]) { struct VertProjUpdate vp_update = {vp_handle, ar, mval_fl}; @@ -182,7 +186,7 @@ static void vpaint_proj_dm_map_cosnos_update(struct VertProjHandle *vp_handle, /* quick sanity check - we shouldn't have to run this if there are no modifiers */ BLI_assert(BLI_listbase_is_empty(&ob->modifiers) == false); - dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); + dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); /* highly unlikely this will become unavailable once painting starts (perhaps with animated modifiers) */ if (LIKELY(dm->foreachMappedVert)) { @@ -198,8 +202,9 @@ static void vpaint_proj_dm_map_cosnos_update(struct VertProjHandle *vp_handle, /* -------------------------------------------------------------------- */ /* Public Functions */ -struct VertProjHandle *ED_vpaint_proj_handle_create(Scene *scene, Object *ob, - DMCoNo **r_vcosnos) +struct VertProjHandle *ED_vpaint_proj_handle_create( + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, + DMCoNo **r_vcosnos) { struct VertProjHandle *vp_handle = MEM_mallocN(sizeof(struct VertProjHandle), __func__); Mesh *me = ob->data; @@ -209,7 +214,7 @@ struct VertProjHandle *ED_vpaint_proj_handle_create(Scene *scene, Object *ob, vp_handle->use_update = false; /* sets 'use_update' if needed */ - vpaint_proj_dm_map_cosnos_init(scene, ob, vp_handle); + vpaint_proj_dm_map_cosnos_init(eval_ctx, scene, ob, vp_handle); if (vp_handle->use_update) { vp_handle->dists_sq = MEM_mallocN(sizeof(float) * me->totvert, __func__); @@ -228,11 +233,12 @@ struct VertProjHandle *ED_vpaint_proj_handle_create(Scene *scene, Object *ob, return vp_handle; } -void ED_vpaint_proj_handle_update(struct VertProjHandle *vp_handle, - ARegion *ar, const float mval_fl[2]) +void ED_vpaint_proj_handle_update( + const struct EvaluationContext *eval_ctx, struct VertProjHandle *vp_handle, + ARegion *ar, const float mval_fl[2]) { if (vp_handle->use_update) { - vpaint_proj_dm_map_cosnos_update(vp_handle, ar, mval_fl); + vpaint_proj_dm_map_cosnos_update(eval_ctx, vp_handle, ar, mval_fl); } } diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c index 2afbecbc6fb..1348847167c 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -49,7 +49,6 @@ #include "BKE_DerivedMesh.h" #include "BKE_brush.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_deform.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" @@ -59,6 +58,8 @@ #include "BKE_report.h" #include "BKE_colortools.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -130,9 +131,13 @@ static int weight_from_bones_exec(bContext *C, wmOperator *op) Mesh *me = ob->data; int type = RNA_enum_get(op->ptr, "type"); - create_vgroups_from_armature(op->reports, scene, ob, armob, type, (me->editflag & ME_EDIT_MIRROR_X)); + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); + + create_vgroups_from_armature(op->reports, &eval_ctx, scene, ob, armob, type, (me->editflag & ME_EDIT_MIRROR_X)); - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); return OPERATOR_FINISHED; @@ -366,7 +371,7 @@ static int weight_sample_group_exec(bContext *C, wmOperator *op) BLI_assert(type + 1 >= 0); vc.obact->actdef = type + 1; - DAG_id_tag_update(&vc.obact->id, OB_RECALC_DATA); + DEG_id_tag_update(&vc.obact->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, vc.obact); return OPERATOR_FINISHED; } @@ -482,7 +487,7 @@ static bool weight_paint_set(Object *ob, float paintweight) wpaint_prev_destroy(&wpp); - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); return true; } @@ -694,7 +699,7 @@ static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEven } MEM_freeN(vert_cache); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); } else if (ret & OPERATOR_FINISHED) { @@ -720,7 +725,12 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) float sco_start[2] = {x_start, y_start}; float sco_end[2] = {x_end, y_end}; const bool is_interactive = (gesture != NULL); - DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); + + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); + + DerivedMesh *dm = mesh_get_derived_final(&eval_ctx, scene, ob, scene->customdata_mask); DMGradient_userData data = {NULL}; @@ -792,7 +802,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) dm->foreachMappedVert(dm, gradientVertUpdate__mapFunc, &data, DM_FOREACH_NOP); } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); if (is_interactive == false) { diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 53d7684e331..6e08f47f60d 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -56,7 +56,6 @@ #include "BKE_brush.h" #include "BKE_ccg.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_image.h" #include "BKE_key.h" @@ -72,6 +71,8 @@ #include "BKE_subsurf.h" #include "BKE_colortools.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -491,8 +492,7 @@ bool sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d, return 1; } -void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar, - RegionView3D *rv3d, Object *ob) +void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar, Object *ob) { PBVH *pbvh = ob->sculpt->pbvh; /* copy here, original will be used below */ @@ -500,7 +500,7 @@ void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar, sculpt_extend_redraw_rect_previous(ob, &rect); - paint_calc_redraw_planes(planes, ar, rv3d, ob, &rect); + paint_calc_redraw_planes(planes, ar, ob, &rect); /* we will draw this rect, so now we can set it as the previous partial rect. * Note that we don't update with the union of previous/current (rect), only with @@ -2045,6 +2045,10 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) mul_v3_v3(offset, ss->cache->scale); mul_v3_fl(offset, bstrength); + /* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise + * initialize before threads so they can do curve mapping */ + curvemapping_initialize(brush->curve); + /* threaded loop over nodes */ SculptThreadedTaskData data = { .sd = sd, .ob = ob, .brush = brush, .nodes = nodes, @@ -4409,10 +4413,13 @@ static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob) SculptSession *ss = ob->sculpt; if (ss->kb || ss->modifiers_active) { + EvaluationContext eval_ctx; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); - BKE_sculpt_update_mesh_elements(CTX_data_scene(C), sd, ob, + CTX_data_eval_ctx(C, &eval_ctx); + + BKE_sculpt_update_mesh_elements(&eval_ctx, CTX_data_scene(C), sd, ob, sculpt_any_smooth_mode(brush, ss->cache, 0), false); } } @@ -4618,12 +4625,15 @@ static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + EvaluationContext eval_ctx; SculptSession *ss = CTX_data_active_object(C)->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); int mode = RNA_enum_get(op->ptr, "mode"); bool is_smooth; bool need_mask = false; + CTX_data_eval_ctx(C, &eval_ctx); + if (brush->sculpt_tool == SCULPT_TOOL_MASK) { need_mask = true; } @@ -4632,7 +4642,7 @@ static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op) sculpt_brush_init_tex(scene, sd, ss); is_smooth = sculpt_any_smooth_mode(brush, NULL, mode); - BKE_sculpt_update_mesh_elements(scene, sd, ob, is_smooth, need_mask); + BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, is_smooth, need_mask); return 1; } @@ -4676,7 +4686,7 @@ static void sculpt_flush_update(bContext *C) GPU_drawobject_free(ob->derivedFinal); if (ss->kb || ss->modifiers_active) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); ED_region_tag_redraw(ar); } else { @@ -4706,6 +4716,9 @@ static void sculpt_flush_update(bContext *C) ED_region_tag_redraw_partial(ar, &r); } } + + /* 2.8x - avoid full mesh update! */ + BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_SCULPT_COORDS); } /* Returns whether the mouse/stylus is over the mesh (1) @@ -4789,7 +4802,7 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(st * Could be optimized later, but currently don't think it's so * much common scenario. * - * Same applies to the DAG_id_tag_update() invoked from + * Same applies to the DEG_id_tag_update() invoked from * sculpt_flush_update(). */ if (ss->modifiers_active) { @@ -4863,7 +4876,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str /* try to avoid calling this, only for e.g. linked duplicates now */ if (((Mesh *)ob->data)->id.us > 1) - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); } @@ -5059,10 +5072,13 @@ void sculpt_update_after_dynamic_topology_toggle(bContext *C) { Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); + EvaluationContext eval_ctx; Sculpt *sd = scene->toolsettings->sculpt; + CTX_data_eval_ctx(C, &eval_ctx); + /* Create the PBVH */ - BKE_sculpt_update_mesh_elements(scene, sd, ob, false, false); + BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, false, false); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); } @@ -5396,11 +5412,15 @@ static void SCULPT_OT_symmetrize(wmOperatorType *ot) /**** Toggle operator for turning sculpt mode on or off ****/ -static void sculpt_init_session(Scene *scene, Object *ob) +static void sculpt_init_session(const bContext *C, Scene *scene, Object *ob) { + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); + ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session"); - BKE_sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, 0, false); + BKE_sculpt_update_mesh_elements(&eval_ctx, scene, scene->toolsettings->sculpt, ob, 0, false); } @@ -5436,7 +5456,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) * a consistent state. */ if (true || flush_recalc || (ob->sculpt && ob->sculpt->bm)) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) { @@ -5461,7 +5481,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) ob->mode |= mode_flag; if (flush_recalc) - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* Create persistent sculpt mode data */ if (!ts->sculpt) { @@ -5492,7 +5512,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) if (ob->sculpt) BKE_sculptsession_free(ob); - sculpt_init_session(scene, ob); + sculpt_init_session(C, scene, ob); /* Mask layer is required */ if (mmd) { diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 44bd872d107..a10c7477dc6 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -51,12 +51,12 @@ #include "BKE_ccg.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_multires.h" #include "BKE_paint.h" #include "BKE_key.h" #include "BKE_mesh.h" #include "BKE_subsurf.h" +#include "DEG_depsgraph.h" #include "WM_api.h" #include "WM_types.h" @@ -127,9 +127,12 @@ static bool sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoN Scene *scene = CTX_data_scene(C); Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Object *ob = CTX_data_active_object(C); + EvaluationContext eval_ctx; SculptSession *ss = ob->sculpt; MVert *mvert; int *index; + + CTX_data_eval_ctx(C, &eval_ctx); if (unode->maxvert) { /* regular mesh restore */ @@ -143,7 +146,7 @@ static bool sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoN if (kb) { ob->shapenr = BLI_findindex(&key->block, kb) + 1; - BKE_sculpt_update_mesh_elements(scene, sd, ob, 0, false); + BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, 0, false); WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob); } else { @@ -451,6 +454,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb) Scene *scene = CTX_data_scene(C); Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Object *ob = CTX_data_active_object(C); + EvaluationContext eval_ctx; DerivedMesh *dm; SculptSession *ss = ob->sculpt; SculptUndoNode *unode; @@ -458,6 +462,8 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb) bool need_mask = false; bool partial_update = true; + CTX_data_eval_ctx(C, &eval_ctx); + for (unode = lb->first; unode; unode = unode->next) { if (STREQ(unode->idname, ob->id.name)) { if (unode->type == SCULPT_UNDO_MASK) { @@ -469,10 +475,10 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb) } } - BKE_sculpt_update_mesh_elements(scene, sd, ob, 0, need_mask); + BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, 0, need_mask); /* call _after_ sculpt_update_mesh_elements() which may update 'ob->derivedFinal' */ - dm = mesh_get_derived_final(scene, ob, 0); + dm = mesh_get_derived_final(&eval_ctx, scene, ob, 0); if (lb->first && sculpt_undo_bmesh_restore(C, lb->first, ob, ss)) return; @@ -555,7 +561,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb) } if (tag_update) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } else { sculpt_update_object_bounding_box(ob); diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index abc4b28ee50..c9453f94e61 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -46,15 +46,19 @@ #include "BKE_paint.h" #include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_mesh_mapping.h" #include "BKE_customdata.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" + #include "ED_screen.h" #include "ED_image.h" #include "ED_mesh.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" + #include "WM_api.h" #include "WM_types.h" @@ -64,9 +68,6 @@ #include "paint_intern.h" #include "uvedit_intern.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" - #include "UI_view2d.h" #define MARK_BOUNDARY 1 @@ -173,7 +174,7 @@ static int uv_sculpt_brush_poll_do(bContext *C, const bool check_region) } em = BKE_editmesh_from_object(obedit); - ret = EDBM_mtexpoly_check(em); + ret = EDBM_uv_check(em); if (ret) { ARegion *ar = CTX_wm_region(C); @@ -212,18 +213,17 @@ static void brush_drawcursor_uvsculpt(bContext *C, int x, int y, void *UNUSED(cu alpha *= (size - PX_SIZE_FADE_MIN) / (PX_SIZE_FADE_MAX - PX_SIZE_FADE_MIN); } - glPushMatrix(); - - glTranslatef((float)x, (float)y, 0.0f); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3fvAlpha(brush->add_col, alpha); - glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha); glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - glutil_draw_lined_arc(0, (float)(M_PI * 2.0), size, 40); + imm_draw_circle_wire_2d(pos, (float)x, (float)y, size, 40); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - glPopMatrix(); + immUnbindProgram(); } #undef PX_SIZE_FADE_MAX #undef PX_SIZE_FADE_MIN @@ -899,7 +899,7 @@ static int uv_sculpt_stroke_modal(bContext *C, wmOperator *op, const wmEvent *ev ED_region_tag_redraw(CTX_wm_region(C)); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_RUNNING_MODAL; } diff --git a/source/blender/editors/sound/CMakeLists.txt b/source/blender/editors/sound/CMakeLists.txt index 535cd579030..9efdf11e8d7 100644 --- a/source/blender/editors/sound/CMakeLists.txt +++ b/source/blender/editors/sound/CMakeLists.txt @@ -39,7 +39,7 @@ set(SRC ) if(WITH_AUDASPACE) - add_definitions(${AUDASPACE_DEFINITIONS}) + add_definitions(-DWITH_AUDASPACE) list(APPEND INC_SYS ${AUDASPACE_C_INCLUDE_DIRS} diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 0c349e6433e..4fed7c4467e 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -67,7 +67,7 @@ #include "WM_types.h" #ifdef WITH_AUDASPACE -# include AUD_SPECIAL_H +# include <AUD_Special.h> #endif #include "ED_sound.h" @@ -311,6 +311,8 @@ static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *scene_layer = CTX_data_scene_layer(C); + struct Depsgraph *depsgraph = CTX_data_depsgraph(C); int oldfra = scene->r.cfra; int cfra; @@ -318,11 +320,11 @@ static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op)) for (cfra = (scene->r.sfra > 0) ? (scene->r.sfra - 1) : 0; cfra <= scene->r.efra + 1; cfra++) { scene->r.cfra = cfra; - BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay); + BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, scene_layer); } scene->r.cfra = oldfra; - BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay); + BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, scene_layer); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_action/action_buttons.c b/source/blender/editors/space_action/action_buttons.c index bfc808f6d83..80ec9107984 100644 --- a/source/blender/editors/space_action/action_buttons.c +++ b/source/blender/editors/space_action/action_buttons.c @@ -48,7 +48,6 @@ #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_main.h" #include "BKE_global.h" diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 0764f586de9..11ac1d60f39 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -61,6 +61,7 @@ #include "ED_keyframes_draw.h" #include "action_intern.h" +#include "GPU_immediate.h" /* ************************************************************************* */ /* Channel List */ @@ -156,15 +157,12 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; - int filter; View2D *v2d = &ar->v2d; bDopeSheet *ads = &saction->ads; AnimData *adt = NULL; float act_start, act_end, y; - size_t items; - int height; unsigned char col1[3], col2[3]; unsigned char col1a[3], col2a[3]; @@ -194,10 +192,10 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) } /* build list of channels to draw */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac))); + int height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac))); /* don't use totrect set, as the width stays the same * (NOTE: this is ok here, the configuration is pretty straightforward) */ @@ -205,6 +203,12 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) /* first backdrop strips */ y = (float)(-ACHANNEL_HEIGHT(ac)); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + glEnable(GL_BLEND); for (ale = anim_data.first; ale; ale = ale->next) { @@ -223,28 +227,26 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) /* determine if channel is selected */ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT)) sel = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT); - + if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) { switch (ale->type) { case ANIMTYPE_SUMMARY: { /* reddish color from NLA */ - UI_ThemeColor4(TH_ANIM_ACTIVE); + immUniformThemeColor(TH_ANIM_ACTIVE); break; } case ANIMTYPE_SCENE: case ANIMTYPE_OBJECT: { - if (sel) glColor4ub(col1b[0], col1b[1], col1b[2], 0x45); - else glColor4ub(col1b[0], col1b[1], col1b[2], 0x22); + immUniformColor3ubvAlpha(col1b, sel ? 0x45 : 0x22); break; } case ANIMTYPE_FILLACTD: case ANIMTYPE_DSSKEY: case ANIMTYPE_DSWOR: { - if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45); - else glColor4ub(col2b[0], col2b[1], col2b[2], 0x22); + immUniformColor3ubvAlpha(col2b, sel ? 0x45 : 0x22); break; } case ANIMTYPE_GROUP: @@ -252,17 +254,14 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) bActionGroup *agrp = ale->data; if (show_group_colors && agrp->customCol) { if (sel) { - unsigned char *cp = (unsigned char *)agrp->cs.select; - glColor4ub(cp[0], cp[1], cp[2], 0x45); + immUniformColor3ubvAlpha((unsigned char *)agrp->cs.select, 0x45); } else { - unsigned char *cp = (unsigned char *)agrp->cs.solid; - glColor4ub(cp[0], cp[1], cp[2], 0x1D); + immUniformColor3ubvAlpha((unsigned char *)agrp->cs.solid, 0x1D); } } else { - if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22); - else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22); + immUniformColor3ubvAlpha(sel ? col1a : col2a, 0x22); } break; } @@ -270,53 +269,43 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) { FCurve *fcu = ale->data; if (show_group_colors && fcu->grp && fcu->grp->customCol) { - unsigned char *cp = (unsigned char *)fcu->grp->cs.active; - - if (sel) glColor4ub(cp[0], cp[1], cp[2], 0x65); - else glColor4ub(cp[0], cp[1], cp[2], 0x0B); + immUniformColor3ubvAlpha((unsigned char *)fcu->grp->cs.active, sel ? 0x65 : 0x0B); } else { - if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22); - else glColor4ub(col2[0], col2[1], col2[2], 0x22); + immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22); } break; } default: { - if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22); - else glColor4ub(col2[0], col2[1], col2[2], 0x22); - break; + immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22); } } /* draw region twice: firstly backdrop, then the current range */ - glRectf(v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac)); + immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac)); if (ac->datatype == ANIMCONT_ACTION) - glRectf(act_start, (float)y - ACHANNEL_HEIGHT_HALF(ac), act_end, (float)y + ACHANNEL_HEIGHT_HALF(ac)); + immRectf(pos, act_start, (float)y - ACHANNEL_HEIGHT_HALF(ac), act_end, (float)y + ACHANNEL_HEIGHT_HALF(ac)); } else if (ac->datatype == ANIMCONT_GPENCIL) { /* frames less than one get less saturated background */ - if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22); - else glColor4ub(col2[0], col2[1], col2[2], 0x22); - glRectf(0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac)); + immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22); + immRectf(pos, 0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac)); /* frames one and higher get a saturated background */ - if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44); - else glColor4ub(col2[0], col2[1], col2[2], 0x44); - glRectf(v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac)); + immUniformColor3ubvAlpha(sel ? col1 : col2, 0x44); + immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac)); } else if (ac->datatype == ANIMCONT_MASK) { /* TODO --- this is a copy of gpencil */ /* frames less than one get less saturated background */ - if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22); - else glColor4ub(col2[0], col2[1], col2[2], 0x22); - glRectf(0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac)); + immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22); + immRectf(pos, 0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac)); /* frames one and higher get a saturated background */ - if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44); - else glColor4ub(col2[0], col2[1], col2[2], 0x44); - glRectf(v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac)); + immUniformColor3ubvAlpha(sel ? col1 : col2, 0x44); + immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac)); } } } @@ -325,18 +314,29 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) y -= ACHANNEL_STEP(ac); } glDisable(GL_BLEND); - - /* Draw keyframes + + /* black line marking 'current frame' for Time-Slide transform mode */ + if (saction->flag & SACTION_MOVING) { + immUniformColor3f(0.0f, 0.0f, 0.0f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD); + immVertex2f(pos, saction->timeslide, v2d->cur.ymax); + immEnd(); + } + immUnbindProgram(); + + /* Draw keyframes * 1) Only channels that are visible in the Action Editor get drawn/evaluated. * This is to try to optimize this for heavier data sets * 2) Keyframes which are out of view horizontally are disregarded */ y = (float)(-ACHANNEL_HEIGHT(ac)); - + for (ale = anim_data.first; ale; ale = ale->next) { const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac)); const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac)); - + /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) @@ -344,7 +344,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) /* check if anything to show for this channel */ if (ale->datatype != ALE_NONE) { adt = ANIM_nla_mapping_get(ac, ale); - + /* draw 'keyframes' for each specific datatype */ switch (ale->datatype) { case ALE_ALL: @@ -374,20 +374,10 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) } } } - + y -= ACHANNEL_STEP(ac); } - - /* free tempolary channels used for drawing */ - ANIM_animdata_freelist(&anim_data); - /* black line marking 'current frame' for Time-Slide transform mode */ - if (saction->flag & SACTION_MOVING) { - glColor3f(0.0f, 0.0f, 0.0f); - - glBegin(GL_LINES); - glVertex2f(saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD); - glVertex2f(saction->timeslide, v2d->cur.ymax); - glEnd(); - } + /* free temporary channels used for drawing */ + ANIM_animdata_freelist(&anim_data); } diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 5cde224b7dc..50882571dad 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -308,7 +308,9 @@ static void action_header_region_draw(const bContext *C, ARegion *ar) ED_region_header(C, ar); } -static void action_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void action_channel_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -351,7 +353,9 @@ static void action_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED( } } -static void action_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void action_main_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -391,7 +395,11 @@ static void action_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa) if (wmn->action == NA_RENAME) ED_region_tag_redraw(ar); break; - + case NC_SCREEN: + if (ELEM(wmn->data, ND_LAYER)) { + ED_region_tag_redraw(ar); + } + break; default: if (wmn->data == ND_KEYS) ED_region_tag_redraw(ar); @@ -400,7 +408,9 @@ static void action_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa) } /* editor level listener */ -static void action_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) +static void action_listener( + bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { SpaceAction *saction = (SpaceAction *)sa->spacedata.first; @@ -507,7 +517,9 @@ static void action_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) } } -static void action_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void action_header_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { // SpaceAction *saction = (SpaceAction *)sa->spacedata.first; @@ -559,7 +571,9 @@ static void action_buttons_area_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, NULL, -1, true); } -static void action_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void action_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index ac6e3123e4e..32f6ac40d12 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -55,6 +55,7 @@ #include "ED_paint.h" #include "ED_physics.h" #include "ED_render.h" +#include "ED_scene.h" #include "ED_screen.h" #include "ED_sculpt.h" #include "ED_space_api.h" @@ -65,6 +66,7 @@ #include "ED_clip.h" #include "ED_mask.h" #include "ED_sequencer.h" +#include "ED_manipulator_library.h" #include "io_ops.h" @@ -99,6 +101,8 @@ void ED_spacetypes_init(void) // ... /* register operator types for screen and all spaces */ + ED_operatortypes_workspace(); + ED_operatortypes_scene(); ED_operatortypes_screen(); ED_operatortypes_anim(); ED_operatortypes_animchannels(); @@ -121,12 +125,26 @@ void ED_spacetypes_init(void) ED_operatortypes_view2d(); ED_operatortypes_ui(); - - /* register operators */ + + /* manipulator types */ + ED_manipulatortypes_dial_3d(); + ED_manipulatortypes_grab_3d(); + ED_manipulatortypes_arrow_2d(); + ED_manipulatortypes_arrow_3d(); + ED_manipulatortypes_primitive_3d(); + ED_manipulatortypes_cage_2d(); + ED_manipulatortypes_cage_3d(); + + /* register types for operators and manipulators */ spacetypes = BKE_spacetypes_list(); for (type = spacetypes->first; type; type = type->next) { - if (type->operatortypes) + /* init manipulator types first, operator-types need them */ + if (type->manipulators) { + type->manipulators(); + } + if (type->operatortypes) { type->operatortypes(); + } } /* register internal render callbacks */ @@ -251,7 +269,6 @@ void ED_region_draw_cb_draw(const bContext *C, ARegion *ar, int type) for (rdc = ar->type->drawcalls.first; rdc; rdc = rdc->next) { if (rdc->type == type) { - UI_reinit_gl_state(); rdc->draw(C, ar, rdc->customdata); } } diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index da3364d872d..392efd03ee1 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -49,6 +49,7 @@ #include "BKE_context.h" #include "BKE_action.h" +#include "BKE_layer.h" #include "BKE_material.h" #include "BKE_modifier.h" #include "BKE_paint.h" @@ -56,6 +57,7 @@ #include "BKE_screen.h" #include "BKE_texture.h" #include "BKE_linestyle.h" +#include "BKE_workspace.h" #include "RNA_access.h" @@ -167,27 +169,53 @@ static int buttons_context_path_linestyle(ButsContextPath *path) return 0; } +static int buttons_context_path_workspace(ButsContextPath *path) +{ + PointerRNA *ptr = &path->ptr[path->len - 1]; + + /* This one just verifies. */ + return RNA_struct_is_a(ptr->type, &RNA_WorkSpace); +} + +static int buttons_context_path_collection(ButsContextPath *path) +{ + PointerRNA *ptr = &path->ptr[path->len - 1]; + + /* if we already have a (pinned) Collection, we're done */ + if (RNA_struct_is_a(ptr->type, &RNA_LayerCollection)) { + return 1; + } + + SceneLayer *sl = ptr->data; + LayerCollection *sc = BKE_layer_collection_get_active(sl); + + if (sc) { + RNA_pointer_create(NULL, &RNA_LayerCollection, sc, &path->ptr[path->len]); + path->len++; + return 1; + } + + /* no path to a collection possible */ + return 0; +} + static int buttons_context_path_object(ButsContextPath *path) { - Scene *scene; - Object *ob; PointerRNA *ptr = &path->ptr[path->len - 1]; /* if we already have a (pinned) object, we're done */ if (RNA_struct_is_a(ptr->type, &RNA_Object)) { return 1; } - /* if we have a scene, use the scene's active object */ - else if (buttons_context_path_scene(path)) { - scene = path->ptr[path->len - 1].data; - ob = (scene->basact) ? scene->basact->object : NULL; - if (ob) { - RNA_id_pointer_create(&ob->id, &path->ptr[path->len]); - path->len++; + SceneLayer *sl = ptr->data; + Object *ob = (sl->basact) ? sl->basact->object : NULL; - return 1; - } + if (ob) { + RNA_id_pointer_create(&ob->id, &path->ptr[path->len]); + path->len++; + + return 1; } /* no path to a object possible */ @@ -208,6 +236,7 @@ static int buttons_context_path_data(ButsContextPath *path, int type) else if (RNA_struct_is_a(ptr->type, &RNA_Camera) && (type == -1 || type == OB_CAMERA)) return 1; else if (RNA_struct_is_a(ptr->type, &RNA_Lamp) && (type == -1 || type == OB_LAMP)) return 1; else if (RNA_struct_is_a(ptr->type, &RNA_Speaker) && (type == -1 || type == OB_SPEAKER)) return 1; + else if (RNA_struct_is_a(ptr->type, &RNA_LightProbe) && (type == -1 || type == OB_LIGHTPROBE)) return 1; /* try to get an object in the path, no pinning supported here */ else if (buttons_context_path_object(path)) { ob = path->ptr[path->len - 1].data; @@ -367,7 +396,7 @@ static int buttons_context_path_particle(ButsContextPath *path) return 0; } -static int buttons_context_path_brush(ButsContextPath *path) +static int buttons_context_path_brush(const bContext *C, ButsContextPath *path) { Scene *scene; Brush *br = NULL; @@ -381,8 +410,10 @@ static int buttons_context_path_brush(ButsContextPath *path) else if (buttons_context_path_scene(path)) { scene = path->ptr[path->len - 1].data; - if (scene) - br = BKE_paint_brush(BKE_paint_get_active(scene)); + if (scene) { + SceneLayer *sl = CTX_data_scene_layer(C); + br = BKE_paint_brush(BKE_paint_get_active(scene, sl)); + } if (br) { RNA_id_pointer_create((ID *)br, &path->ptr[path->len]); @@ -396,7 +427,7 @@ static int buttons_context_path_brush(ButsContextPath *path) return 0; } -static int buttons_context_path_texture(ButsContextPath *path, ButsContextTexture *ct) +static int buttons_context_path_texture(const bContext *C, ButsContextPath *path, ButsContextTexture *ct) { if (ct) { /* new shading system */ @@ -414,7 +445,7 @@ static int buttons_context_path_texture(ButsContextPath *path, ButsContextTextur if (id) { if (GS(id->name) == ID_BR) - buttons_context_path_brush(path); + buttons_context_path_brush(C, path); else if (GS(id->name) == ID_MA) buttons_context_path_material(path, false, true); else if (GS(id->name) == ID_WO) @@ -530,7 +561,7 @@ static int buttons_context_path_texture(ButsContextPath *path, ButsContextTextur static bool buttons_context_linestyle_pinnable(const bContext *C) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *actsrl; + SceneLayer *active_scene_layer; FreestyleConfig *config; SpaceButs *sbuts; @@ -539,8 +570,8 @@ static bool buttons_context_linestyle_pinnable(const bContext *C) return false; } /* if Freestyle is not in the Parameter Editor mode */ - actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay); - config = &actsrl->freestyleConfig; + active_scene_layer = BLI_findlink(&scene->render_layers, scene->active_layer); + config = &active_scene_layer->freestyle_config; if (config->mode != FREESTYLE_CONTROL_EDITOR_MODE) { return false; } @@ -556,6 +587,8 @@ static bool buttons_context_linestyle_pinnable(const bContext *C) static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag) { SpaceButs *sbuts = CTX_wm_space_buts(C); + Scene *scene = CTX_data_scene(C); + WorkSpace *workspace = CTX_wm_workspace(C); ID *id; int found; @@ -563,18 +596,32 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma path->flag = flag; path->tex_ctx = sbuts->texture_context; - /* if some ID datablock is pinned, set the root pointer */ + const bool use_scene_settings = BKE_workspace_use_scene_settings_get(workspace); + + /* If some ID datablock is pinned, set the root pointer. */ if (sbuts->pinid) { id = sbuts->pinid; RNA_id_pointer_create(id, &path->ptr[0]); path->len++; } + /* No pinned root, use scene or workspace as initial root. */ + else { + if ((mainb != BCONTEXT_WORKSPACE) && (use_scene_settings || + ELEM(mainb, BCONTEXT_SCENE, BCONTEXT_RENDER, BCONTEXT_RENDER_LAYER, BCONTEXT_WORLD))) + { + RNA_id_pointer_create(&scene->id, &path->ptr[0]); + path->len++; + } + else { + RNA_id_pointer_create(&workspace->id, &path->ptr[0]); + path->len++; + } + } - /* no pinned root, use scene as root */ - if (path->len == 0) { - id = (ID *)CTX_data_scene(C); - RNA_id_pointer_create(id, &path->ptr[0]); + if (!ELEM(mainb, BCONTEXT_WORKSPACE, BCONTEXT_SCENE, BCONTEXT_RENDER, BCONTEXT_RENDER_LAYER, BCONTEXT_WORLD)) { + SceneLayer *scene_layer = BKE_scene_layer_from_workspace_get(scene, workspace); + RNA_pointer_create(NULL, &RNA_SceneLayer, scene_layer, &path->ptr[path->len]); path->len++; } @@ -599,6 +646,12 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma case BCONTEXT_WORLD: found = buttons_context_path_world(path); break; + case BCONTEXT_WORKSPACE: + found = buttons_context_path_workspace(path); + break; + case BCONTEXT_COLLECTION: + found = buttons_context_path_collection(path); + break; case BCONTEXT_OBJECT: case BCONTEXT_PHYSICS: case BCONTEXT_CONSTRAINT: @@ -617,7 +670,7 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma found = buttons_context_path_material(path, false, (sbuts->texuser != NULL)); break; case BCONTEXT_TEXTURE: - found = buttons_context_path_texture(path, sbuts->texuser); + found = buttons_context_path_texture(C, path, sbuts->texuser); break; case BCONTEXT_BONE: found = buttons_context_path_bone(path); @@ -740,11 +793,11 @@ void buttons_context_compute(const bContext *C, SpaceButs *sbuts) const char *buttons_context_dir[] = { "texture_slot", "scene", "world", "object", "mesh", "armature", "lattice", "curve", - "meta_ball", "lamp", "speaker", "camera", "material", "material_slot", + "meta_ball", "lamp", "speaker", "lightprobe", "camera", "material", "material_slot", "texture", "texture_user", "texture_user_property", "bone", "edit_bone", "pose_bone", "particle_system", "particle_system_editable", "particle_settings", "cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint", - "line_style", NULL + "line_style", "collection", "workspace", NULL }; int buttons_context(const bContext *C, const char *member, bContextDataResult *result) @@ -773,6 +826,10 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r set_pointer_type(path, result, &RNA_World); return 1; } + else if (CTX_data_equals(member, "workspace")) { + /* Do not return one here if scene not found in path, in this case we want to get default context scene! */ + return set_pointer_type(path, result, &RNA_WorkSpace); + } else if (CTX_data_equals(member, "object")) { set_pointer_type(path, result, &RNA_Object); return 1; @@ -809,6 +866,10 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r set_pointer_type(path, result, &RNA_Speaker); return 1; } + else if (CTX_data_equals(member, "lightprobe")) { + set_pointer_type(path, result, &RNA_LightProbe); + return 1; + } else if (CTX_data_equals(member, "material")) { set_pointer_type(path, result, &RNA_Material); return 1; @@ -1064,6 +1125,10 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r set_pointer_type(path, result, &RNA_FreestyleLineStyle); return 1; } + else if (CTX_data_equals(member, "collection")) { + set_pointer_type(path, result, &RNA_LayerCollection); + return 1; + } else { return 0; /* not found */ } @@ -1121,10 +1186,14 @@ void buttons_context_draw(const bContext *C, uiLayout *layout) name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL); if (name) { - if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene) + if ((!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene) || + (!ELEM(sbuts->mainb, BCONTEXT_WORKSPACE) && ptr->type == &RNA_WorkSpace)) + { uiItemLDrag(row, ptr, "", icon); /* save some space */ - else + } + else { uiItemLDrag(row, ptr, name, icon); + } if (name != namebuf) MEM_freeN(name); diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index e3d72ba67d8..8a23c762b8c 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -54,6 +54,7 @@ #include "DNA_linestyle_types.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_linestyle.h" #include "BKE_material.h" #include "BKE_modifier.h" @@ -108,14 +109,14 @@ bool ED_texture_context_check_linestyle(const bContext *C) { #ifdef WITH_FREESTYLE Scene *scene = CTX_data_scene(C); - SceneRenderLayer *actsrl; + SceneLayer *active_render_layer; FreestyleConfig *config; FreestyleLineSet *lineset; FreestyleLineStyle *linestyle; if (scene && (scene->r.mode & R_EDGE_FRS)) { - actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay); - config = &actsrl->freestyleConfig; + active_render_layer = BLI_findlink(&scene->render_layers, scene->active_layer); + config = &active_render_layer->freestyle_config; if (config->mode == FREESTYLE_CONTROL_EDITOR_MODE) { lineset = BKE_freestyle_lineset_get_active(config); if (lineset) { @@ -324,6 +325,7 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext * Material *ma = NULL; Lamp *la = NULL; World *wrld = NULL; + WorkSpace *workspace = NULL; FreestyleLineStyle *linestyle = NULL; Brush *brush = NULL; ID *pinid = sbuts->pinid; @@ -345,17 +347,25 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext * brush = (Brush *)pinid; else if (GS(pinid->name) == ID_LS) linestyle = (FreestyleLineStyle *)pinid; + else if (GS(pinid->name) == ID_WS) + workspace = (WorkSpace *)workspace; } if (!scene) scene = CTX_data_scene(C); if (!pinid || GS(pinid->name) == ID_SCE) { - ob = (scene->basact) ? scene->basact->object : NULL; wrld = scene->world; brush = BKE_paint_brush(BKE_paint_get_active_from_context(C)); linestyle = BKE_linestyle_active_from_scene(scene); } + else if (!pinid || GS(pinid->name) == ID_WS) { + if (!workspace) { + workspace = CTX_wm_workspace(C); + } + SceneLayer *scene_layer = BKE_scene_layer_from_workspace_get(scene, workspace); + ob = OBACT(scene_layer); + } if (ob && ob->type == OB_LAMP && !la) la = ob->data; diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index e4c23ad74f8..3607f817721 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -151,6 +151,10 @@ static void buttons_main_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, "render_layer", sbuts->mainb, vertical); else if (sbuts->mainb == BCONTEXT_WORLD) ED_region_panels(C, ar, "world", sbuts->mainb, vertical); + else if (sbuts->mainb == BCONTEXT_WORKSPACE) + ED_region_panels(C, ar, "workspace", sbuts->mainb, vertical); + else if (sbuts->mainb == BCONTEXT_COLLECTION) + ED_region_panels(C, ar, "collection", sbuts->mainb, vertical); else if (sbuts->mainb == BCONTEXT_OBJECT) ED_region_panels(C, ar, "object", sbuts->mainb, vertical); else if (sbuts->mainb == BCONTEXT_DATA) @@ -176,6 +180,20 @@ static void buttons_main_region_draw(const bContext *C, ARegion *ar) sbuts->mainbo = sbuts->mainb; } +static void buttons_main_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn, + const Scene *UNUSED(scene)) +{ + /* context changes */ + switch (wmn->category) { + case NC_SCREEN: + if (ELEM(wmn->data, ND_LAYER)) { + ED_region_tag_redraw(ar); + } + break; + } +} + static void buttons_operatortypes(void) { WM_operatortype_append(BUTTONS_OT_toolbox); @@ -218,7 +236,9 @@ static void buttons_area_redraw(ScrArea *sa, short buttons) } /* reused! */ -static void buttons_area_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) +static void buttons_area_listener( + bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { SpaceButs *sbuts = sa->spacedata.first; @@ -468,6 +488,7 @@ void ED_spacetype_buttons(void) art->regionid = RGN_TYPE_WINDOW; art->init = buttons_main_region_init; art->draw = buttons_main_region_draw; + art->listener = buttons_main_region_listener; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt index 32d48c9c564..8fa4a0de53f 100644 --- a/source/blender/editors/space_clip/CMakeLists.txt +++ b/source/blender/editors/space_clip/CMakeLists.txt @@ -27,6 +27,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../imbuf ../../gpu ../../makesdna diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 0378c68d12c..eb9aadd2e72 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -47,11 +47,12 @@ #include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_screen.h" #include "BKE_movieclip.h" #include "BKE_tracking.h" +#include "DEG_depsgraph.h" + #include "ED_gpencil.h" #include "UI_interface.h" @@ -236,7 +237,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event) marker->pos[1] = cb->marker_pos[1] / height; /* to update position of "parented" objects */ - DAG_id_tag_update(&cb->clip->id, 0); + DEG_id_tag_update(&cb->clip->id, 0); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); ok = true; @@ -321,7 +322,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event) sub_v2_v2(cb->track->markers[i].pos, delta); /* to update position of "parented" objects */ - DAG_id_tag_update(&cb->clip->id, 0); + DEG_id_tag_update(&cb->clip->id, 0); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); ok = true; diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c index 4bf4c1e7baa..631d891ce02 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_draw.c +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c @@ -42,8 +42,6 @@ #include "ED_screen.h" #include "ED_clip.h" -#include "BIF_gl.h" - #include "WM_types.h" #include "UI_interface.h" @@ -54,6 +52,9 @@ #include "RNA_access.h" +#include "GPU_draw.h" +#include "GPU_immediate.h" + #include "clip_intern.h" /* own include */ static void track_channel_color(MovieTrackingTrack *track, float default_color[3], float color[3]) @@ -72,78 +73,25 @@ static void track_channel_color(MovieTrackingTrack *track, float default_color[3 } } -static void draw_keyframe_shape(float x, float y, float xscale, float yscale, bool sel, float alpha) +static void draw_keyframe_shape(float x, float y, bool sel, float alpha, + unsigned int pos_id, unsigned int color_id) { - /* coordinates for diamond shape */ - static const float _unit_diamond_shape[4][2] = { - {0.0f, 1.0f}, /* top vert */ - {1.0f, 0.0f}, /* mid-right */ - {0.0f, -1.0f}, /* bottom vert */ - {-1.0f, 0.0f} /* mid-left */ - }; - static GLuint displist1 = 0; - static GLuint displist2 = 0; - int hsize = STRIP_HEIGHT_HALF; - - /* initialize 2 display lists for diamond shape - one empty, one filled */ - if (displist1 == 0) { - displist1 = glGenLists(1); - glNewList(displist1, GL_COMPILE); - - glBegin(GL_LINE_LOOP); - glVertex2fv(_unit_diamond_shape[0]); - glVertex2fv(_unit_diamond_shape[1]); - glVertex2fv(_unit_diamond_shape[2]); - glVertex2fv(_unit_diamond_shape[3]); - glEnd(); - glEndList(); + float color[4] = { 0.91f, 0.91f, 0.91f, alpha }; + if (sel) { + UI_GetThemeColorShadeAlpha4fv(TH_STRIP_SELECT, 50, -255 * (1.0f - alpha), color); } - if (displist2 == 0) { - displist2 = glGenLists(1); - glNewList(displist2, GL_COMPILE); - - glBegin(GL_QUADS); - glVertex2fv(_unit_diamond_shape[0]); - glVertex2fv(_unit_diamond_shape[1]); - glVertex2fv(_unit_diamond_shape[2]); - glVertex2fv(_unit_diamond_shape[3]); - glEnd(); - glEndList(); - } - - glPushMatrix(); - - /* adjust view transform before starting */ - glTranslatef(x, y, 0.0f); - glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f); - - /* anti-aliased lines for more consistent appearance */ - glEnable(GL_LINE_SMOOTH); - - if (sel) - UI_ThemeColorShadeAlpha(TH_STRIP_SELECT, 50, -255 * (1.0f - alpha)); - else - glColor4f(0.91f, 0.91f, 0.91f, alpha); - - glCallList(displist2); - /* exterior - black frame */ - glColor4f(0.0f, 0.0f, 0.0f, alpha); - glCallList(displist1); - - glDisable(GL_LINE_SMOOTH); - - /* restore view transform */ - glPopMatrix(); + immAttrib4fv(color_id, color); + immVertex2f(pos_id, x, y); } -static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip) +static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip, unsigned int pos_id) { View2D *v2d = &ar->v2d; MovieTracking *tracking = &clip->tracking; MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; MovieTrackingDopesheetCoverageSegment *coverage_segment; - + for (coverage_segment = dopesheet->coverage_segments.first; coverage_segment; coverage_segment = coverage_segment->next) @@ -153,12 +101,13 @@ static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip) int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, coverage_segment->end_frame); if (coverage_segment->coverage == TRACKING_COVERAGE_BAD) { - glColor4f(1.0f, 0.0f, 0.0f, 0.07f); + immUniformColor4f(1.0f, 0.0f, 0.0f, 0.07f); + } + else { + immUniformColor4f(1.0f, 1.0f, 0.0f, 0.07f); } - else - glColor4f(1.0f, 1.0f, 0.0f, 0.07f); - glRectf(start_frame, v2d->cur.ymin, end_frame, v2d->cur.ymax); + immRectf(pos_id, start_frame, v2d->cur.ymin, end_frame, v2d->cur.ymax); } } } @@ -175,18 +124,21 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) MovieTracking *tracking = &clip->tracking; MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; MovieTrackingDopesheetChannel *channel; - float y, xscale, yscale; float strip[4], selected_strip[4]; float height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT); + unsigned int keyframe_ct = 0; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* don't use totrect set, as the width stays the same * (NOTE: this is ok here, the configuration is pretty straightforward) */ v2d->tot.ymin = (float)(-height); - y = (float) CHANNEL_FIRST; - - UI_view2d_scale_get(v2d, &xscale, &yscale); + float y = (float) CHANNEL_FIRST; /* setup colors for regular and selected strips */ UI_GetThemeColor3fv(TH_STRIP, strip); @@ -197,7 +149,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) glEnable(GL_BLEND); - clip_draw_dopesheet_background(ar, clip); + clip_draw_dopesheet_background(ar, clip, pos_id); for (channel = dopesheet->channels.first; channel; channel = channel->next) { float yminc = (float) (y - CHANNEL_HEIGHT_HALF); @@ -208,7 +160,6 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { MovieTrackingTrack *track = channel->track; - float alpha; int i; bool sel = (track->flag & TRACK_DOPE_SEL) != 0; @@ -218,32 +169,26 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) float default_color[4] = {0.8f, 0.93f, 0.8f, 0.3f}; track_channel_color(track, default_color, color); - glColor4fv(color); + immUniformColor4fv(color); - glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF, - v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF); + immRectf(pos_id, v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF, + v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF); } - alpha = (track->flag & TRACK_LOCKED) ? 0.5f : 1.0f; - /* tracked segments */ for (i = 0; i < channel->tot_segment; i++) { int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i]); int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i + 1]); - if (sel) - glColor4fv(selected_strip); - else - glColor4fv(strip); + immUniformColor4fv(sel ? selected_strip : strip); if (start_frame != end_frame) { - glRectf(start_frame, (float) y - STRIP_HEIGHT_HALF, - end_frame, (float) y + STRIP_HEIGHT_HALF); - draw_keyframe_shape(start_frame, y, xscale, yscale, sel, alpha); - draw_keyframe_shape(end_frame, y, xscale, yscale, sel, alpha); + immRectf(pos_id, start_frame, (float) y - STRIP_HEIGHT_HALF, + end_frame, (float) y + STRIP_HEIGHT_HALF); + keyframe_ct += 2; } else { - draw_keyframe_shape(start_frame, y, xscale, yscale, sel, alpha); + keyframe_ct++; } } @@ -253,9 +198,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) MovieTrackingMarker *marker = &track->markers[i]; if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) { - int framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr); - - draw_keyframe_shape(framenr, y, xscale, yscale, sel, alpha); + keyframe_ct++; } i++; @@ -266,6 +209,76 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) y -= CHANNEL_STEP; } + immUnbindProgram(); + + if (keyframe_ct > 0) { + /* draw keyframe markers */ + format = immVertexFormat(); + pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + unsigned int outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + GPU_enable_program_point_size(); + immBegin(GWN_PRIM_POINTS, keyframe_ct); + + /* all same size with black outline */ + immAttrib1f(size_id, 2.0f * STRIP_HEIGHT_HALF); + immAttrib4ub(outline_color_id, 0, 0, 0, 255); + + y = (float) CHANNEL_FIRST; /* start again at the top */ + for (channel = dopesheet->channels.first; channel; channel = channel->next) { + float yminc = (float) (y - CHANNEL_HEIGHT_HALF); + float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF); + + /* check if visible */ + if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) + { + MovieTrackingTrack *track = channel->track; + int i; + bool sel = (track->flag & TRACK_DOPE_SEL) != 0; + float alpha = (track->flag & TRACK_LOCKED) ? 0.5f : 1.0f; + + /* tracked segments */ + for (i = 0; i < channel->tot_segment; i++) { + int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i]); + int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i + 1]); + + if (start_frame != end_frame) { + draw_keyframe_shape(start_frame, y, sel, alpha, pos_id, color_id); + draw_keyframe_shape(end_frame, y, sel, alpha, pos_id, color_id); + } + else { + draw_keyframe_shape(start_frame, y, sel, alpha, pos_id, color_id); + } + } + + /* keyframes */ + i = 0; + while (i < track->markersnr) { + MovieTrackingMarker *marker = &track->markers[i]; + + if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) { + int framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr); + + draw_keyframe_shape(framenr, y, sel, alpha, pos_id, color_id); + } + + i++; + } + } + + /* adjust y-position for next one */ + y -= CHANNEL_STEP; + } + + immEnd(); + GPU_disable_program_point_size(); + immUnbindProgram(); + } + glDisable(GL_BLEND); } @@ -279,22 +292,15 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) SpaceClip *sc = CTX_wm_space_clip(C); View2D *v2d = &ar->v2d; MovieClip *clip = ED_space_clip_get_clip(sc); - MovieTracking *tracking; - MovieTrackingDopesheet *dopesheet; - MovieTrackingDopesheetChannel *channel; uiStyle *style = UI_style_get(); - uiBlock *block; int fontid = style->widget.uifont_id; - int height; - float y; - PropertyRNA *chan_prop_lock; - + if (!clip) return; - tracking = &clip->tracking; - dopesheet = &tracking->dopesheet; - height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT); + MovieTracking *tracking = &clip->tracking; + MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; + int height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT); if (height > BLI_rcti_size_y(&v2d->mask)) { /* don't use totrect set, as the width stays the same @@ -309,6 +315,37 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) /* loop through channels, and set up drawing depending on their type * first pass: just the standard GL-drawing for backdrop + text */ + float y = (float) CHANNEL_FIRST; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + MovieTrackingDopesheetChannel *channel; + for (channel = dopesheet->channels.first; channel; channel = channel->next) { + float yminc = (float) (y - CHANNEL_HEIGHT_HALF); + float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF); + + /* check if visible */ + if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) + { + MovieTrackingTrack *track = channel->track; + float color[3]; + track_channel_color(track, NULL, color); + immUniformColor3fv(color); + + immRectf(pos, v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF, + v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF); + } + + /* adjust y-position for next one */ + y -= CHANNEL_STEP; + } + immUnbindProgram(); + + /* second pass: text */ y = (float) CHANNEL_FIRST; BLF_size(fontid, 11.0f * U.pixelsize, U.dpi); @@ -322,21 +359,11 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { MovieTrackingTrack *track = channel->track; - float font_height, color[3]; bool sel = (track->flag & TRACK_DOPE_SEL) != 0; - track_channel_color(track, NULL, color); - glColor3fv(color); - - glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF, - v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF); - - if (sel) - UI_ThemeColor(TH_TEXT_HI); - else - UI_ThemeColor(TH_TEXT); + UI_FontThemeColor(fontid, sel ? TH_TEXT_HI : TH_TEXT); - font_height = BLF_height(fontid, channel->name, sizeof(channel->name)); + float font_height = BLF_height(fontid, channel->name, sizeof(channel->name)); BLF_position(fontid, v2d->cur.xmin + CHANNEL_PAD, y - font_height / 2.0f, 0.0f); BLF_draw(fontid, channel->name, strlen(channel->name)); @@ -346,12 +373,12 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) y -= CHANNEL_STEP; } - /* second pass: widgets */ - block = UI_block_begin(C, ar, __func__, UI_EMBOSS); + /* third pass: widgets */ + uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS); y = (float) CHANNEL_FIRST; /* get RNA properties (once) */ - chan_prop_lock = RNA_struct_type_find_property(&RNA_MovieTrackingTrack, "lock"); + PropertyRNA *chan_prop_lock = RNA_struct_type_find_property(&RNA_MovieTrackingTrack, "lock"); BLI_assert(chan_prop_lock); glEnable(GL_BLEND); diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index a71b2baa96f..09d225fc1b8 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -55,10 +55,11 @@ #include "ED_mask.h" #include "ED_gpencil.h" -#include "BIF_gl.h" #include "BIF_glutil.h" -#include "GPU_basic_shader.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" #include "WM_types.h" @@ -66,26 +67,25 @@ #include "UI_resources.h" #include "UI_view2d.h" - #include "BLF_api.h" #include "clip_intern.h" // own include /*********************** main area drawing *************************/ -static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int width) +static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int width, unsigned int pos) { int height = (frame == cfra) ? 22 : 10; int x = (frame - sfra) * framelen; if (width == 1) { - glBegin(GL_LINES); - glVertex2i(x, 0); - glVertex2i(x, height * UI_DPI_FAC); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex2i(pos, x, 0); + immVertex2i(pos, x, height * UI_DPI_FAC); + immEnd(); } else { - glRecti(x, 0, x + width, height * UI_DPI_FAC); + immRecti(pos, x, 0, x + width, height * UI_DPI_FAC); } } @@ -166,6 +166,9 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc BKE_movieclip_get_cache_segments(clip, &sc->user, &totseg, &points); ED_region_cache_draw_cached_segments(ar, totseg, points, sfra, efra); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* track */ if (act_track || act_plane_track) { for (i = sfra - clip->start_frame + 1, a = 0; i <= efra - clip->start_frame + 1; i++) { @@ -189,14 +192,17 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc if (generic_track_is_marker_enabled(act_track, act_plane_track, a)) { framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a); - if (framenr != i) - glColor4ub(128, 128, 0, 96); - else if (generic_track_is_marker_keyframed(act_track, act_plane_track, a)) - glColor4ub(255, 255, 0, 196); - else - glColor4ub(255, 255, 0, 96); + if (framenr != i) { + immUniformColor4ub(128, 128, 0, 96); + } + else if (generic_track_is_marker_keyframed(act_track, act_plane_track, a)) { + immUniformColor4ub(255, 255, 0, 196); + } + else { + immUniformColor4ub(255, 255, 0, 96); + } - glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4 * UI_DPI_FAC); + immRecti(pos, (i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4 * UI_DPI_FAC); } } } @@ -206,7 +212,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc int n = reconstruction->camnr; MovieReconstructedCamera *cameras = reconstruction->cameras; - glColor4ub(255, 0, 0, 96); + immUniformColor4ub(255, 0, 0, 96); for (i = sfra, a = 0; i <= efra; i++) { bool ok = false; @@ -223,8 +229,9 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc a++; } - if (!ok) - glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8 * UI_DPI_FAC); + if (!ok) { + immRecti(pos, (i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8 * UI_DPI_FAC); + } } } @@ -233,15 +240,22 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc /* current frame */ x = (sc->user.framenr - sfra) / (efra - sfra + 1) * ar->winx; - UI_ThemeColor(TH_CFRAME); - glRecti(x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC); + immUniformThemeColor(TH_CFRAME); + immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC); + + immUnbindProgram(); ED_region_cache_draw_curfra_label(sc->user.framenr, x, 8.0f * UI_DPI_FAC); + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* solver keyframes */ - glColor4ub(175, 255, 0, 255); - draw_keyframe(act_object->keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2); - draw_keyframe(act_object->keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2); + immUniformColor4ub(175, 255, 0, 255); + draw_keyframe(act_object->keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2, pos); + draw_keyframe(act_object->keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2, pos); + + immUnbindProgram(); /* movie clip animation */ if ((sc->mode == SC_MODE_MASKEDIT) && sc->mask_info.mask) { @@ -275,11 +289,16 @@ static void draw_movieclip_muted(ARegion *ar, int width, int height, float zoomx { int x, y; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* find window pixel coordinates of origin */ UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y); - glColor3f(0.0f, 0.0f, 0.0f); - glRectf(x, y, x + zoomx * width, y + zoomy * height); + immUniformColor3f(0.0f, 0.0f, 0.0f); + immRectf(pos, x, y, x + zoomx * width, y + zoomy * height); + + immUnbindProgram(); } static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf, @@ -297,7 +316,7 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - fdrawcheckerboard(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y); + imm_draw_box_checker_2d(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y); } /* non-scaled proxy shouldn't use filtering */ @@ -307,13 +326,7 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, filter = GL_NEAREST; } - /* set zoom */ - glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y); - - glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter); - /* reset zoom */ - glPixelZoom(1.0f, 1.0f); - + glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter, zoomx * width / ibuf->x, zoomy * height / ibuf->y); if (sc->flag & SC_SHOW_METADATA) { rctf frame; @@ -335,31 +348,37 @@ static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int /* draw boundary border for frame if stabilization is enabled */ if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) { - glColor3f(0.0f, 0.0f, 0.0f); - - GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); - GPU_basic_shader_line_stipple(3, 0xAAAA); + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + /* Exclusive OR allows to get orig value when second operand is 0, + * and negative of orig value when second operand is 1. */ glEnable(GL_COLOR_LOGIC_OP); - glLogicOp(GL_NOR); + glLogicOp(GL_XOR); + + gpuPushMatrix(); + gpuTranslate2f(x, y); + + gpuScale2f(zoomx, zoomy); + gpuMultMatrix(sc->stabmat); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); - glPushMatrix(); - glTranslatef(x, y, 0.0f); + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.0f); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); - glScalef(zoomx, zoomy, 1.0f); - glMultMatrixf(sc->stabmat); + imm_draw_box_wire_2d(shdr_pos, 0.0f, 0.0f, width, height); - glBegin(GL_LINE_LOOP); - glVertex2f(0.0f, 0.0f); - glVertex2f(width, 0.0f); - glVertex2f(width, height); - glVertex2f(0.0f, height); - glEnd(); + immUnbindProgram(); - glPopMatrix(); + gpuPopMatrix(); glDisable(GL_COLOR_LOGIC_OP); - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); } } @@ -432,53 +451,97 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin i++; } + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + if (!tiny) { - UI_ThemeColor(TH_MARKER_OUTLINE); + immUniformThemeColor(TH_MARKER_OUTLINE); if (TRACK_VIEW_SELECTED(sc, track)) { - glPointSize(5.0f); - glBegin(GL_POINTS); - for (i = a; i < b; i++) { - if (i != curindex) - glVertex2f(path[i][0], path[i][1]); + if ((b - a - 1) >= 1) { + glPointSize(5.0f); + + immBegin(GWN_PRIM_POINTS, b - a - 1); + + for (i = a; i < b; i++) { + if (i != curindex) { + immVertex2f(pos, path[i][0], path[i][1]); + } + } + + immEnd(); } - glEnd(); } - glLineWidth(3.0f); - glBegin(GL_LINE_STRIP); - for (i = a; i < b; i++) - glVertex2f(path[i][0], path[i][1]); - glEnd(); - } + if ((b - a) >= 2) { + glLineWidth(3.0f); + + immBegin(GWN_PRIM_LINE_STRIP, b - a); + + for (i = a; i < b; i++) { + immVertex2f(pos, path[i][0], path[i][1]); + } - UI_ThemeColor(TH_PATH_BEFORE); + immEnd(); + } + } if (TRACK_VIEW_SELECTED(sc, track)) { glPointSize(3.0f); - glBegin(GL_POINTS); - for (i = a; i < b; i++) { - if (i == count + 1) - UI_ThemeColor(TH_PATH_AFTER); - if (i != curindex) - glVertex2f(path[i][0], path[i][1]); + if ((curindex - a) >= 1) { + immUniformThemeColor(TH_PATH_BEFORE); + + immBegin(GWN_PRIM_POINTS, curindex - a); + + for (i = a; i < curindex; i++) { + immVertex2f(pos, path[i][0], path[i][1]); + } + + immEnd(); } - glEnd(); - } - UI_ThemeColor(TH_PATH_BEFORE); + if ((b - curindex - 1) >= 1) { + immUniformThemeColor(TH_PATH_AFTER); + + immBegin(GWN_PRIM_POINTS, b - curindex - 1); + + for (i = curindex + 1; i < b; i++) { + immVertex2f(pos, path[i][0], path[i][1]); + } + + immEnd(); + } + } glLineWidth(1); - glBegin(GL_LINE_STRIP); - for (i = a; i < b; i++) { - if (i == count + 1) - UI_ThemeColor(TH_PATH_AFTER); + if ((curindex - a + 1) >= 2) { + immUniformThemeColor(TH_PATH_BEFORE); + + immBegin(GWN_PRIM_LINE_STRIP, curindex - a + 1); + + for (i = a; i <= curindex; i++) { + immVertex2f(pos, path[i][0], path[i][1]); + } + + immEnd(); + } + + if ((b - curindex) >= 2) { + immUniformThemeColor(TH_PATH_AFTER); + + immBegin(GWN_PRIM_LINE_STRIP, b - curindex); + + for (i = curindex; i < b; i++) { + immVertex2f(pos, path[i][0], path[i][1]); + } - glVertex2f(path[i][0], path[i][1]); + immEnd(); } - glEnd(); + + immUnbindProgram(); if (path != path_static) { MEM_freeN(path); @@ -487,19 +550,19 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin } static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, - const float marker_pos[2], int width, int height) + const float marker_pos[2], int width, int height, unsigned int position) { int tiny = sc->flag & SC_SHOW_TINY_MARKER; bool show_search = false; float px[2]; - UI_ThemeColor(TH_MARKER_OUTLINE); - px[0] = 1.0f / width / sc->zoom; px[1] = 1.0f / height / sc->zoom; glLineWidth(tiny ? 1.0f : 3.0f); + immUniformThemeColor(TH_MARKER_OUTLINE); + if ((marker->flag & MARKER_DISABLED) == 0) { float pos[2]; float p[2]; @@ -514,51 +577,54 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT marker->pattern_corners[2], marker->pattern_corners[3])) { glPointSize(tiny ? 3.0f : 4.0f); - glBegin(GL_POINTS); - glVertex2f(pos[0], pos[1]); - glEnd(); + + immBegin(GWN_PRIM_POINTS, 1); + immVertex2f(position, pos[0], pos[1]); + immEnd(); } else { - glBegin(GL_LINES); - glVertex2f(pos[0] + px[0] * 2, pos[1]); - glVertex2f(pos[0] + px[0] * 8, pos[1]); + immBegin(GWN_PRIM_LINES, 8); + + immVertex2f(position, pos[0] + px[0] * 2, pos[1]); + immVertex2f(position, pos[0] + px[0] * 8, pos[1]); + + immVertex2f(position, pos[0] - px[0] * 2, pos[1]); + immVertex2f(position, pos[0] - px[0] * 8, pos[1]); - glVertex2f(pos[0] - px[0] * 2, pos[1]); - glVertex2f(pos[0] - px[0] * 8, pos[1]); + immVertex2f(position, pos[0], pos[1] - px[1] * 2); + immVertex2f(position, pos[0], pos[1] - px[1] * 8); - glVertex2f(pos[0], pos[1] - px[1] * 2); - glVertex2f(pos[0], pos[1] - px[1] * 8); + immVertex2f(position, pos[0], pos[1] + px[1] * 2); + immVertex2f(position, pos[0], pos[1] + px[1] * 8); - glVertex2f(pos[0], pos[1] + px[1] * 2); - glVertex2f(pos[0], pos[1] + px[1] * 8); - glEnd(); + immEnd(); } } /* pattern and search outline */ - glPushMatrix(); - glTranslate2fv(marker_pos); + gpuPushMatrix(); + gpuTranslate2fv(marker_pos); if (sc->flag & SC_SHOW_MARKER_PATTERN) { - glBegin(GL_LINE_LOOP); - glVertex2fv(marker->pattern_corners[0]); - glVertex2fv(marker->pattern_corners[1]); - glVertex2fv(marker->pattern_corners[2]); - glVertex2fv(marker->pattern_corners[3]); - glEnd(); + immBegin(GWN_PRIM_LINE_LOOP, 4); + immVertex2fv(position, marker->pattern_corners[0]); + immVertex2fv(position, marker->pattern_corners[1]); + immVertex2fv(position, marker->pattern_corners[2]); + immVertex2fv(position, marker->pattern_corners[3]); + immEnd(); } show_search = (TRACK_VIEW_SELECTED(sc, track) && ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0; + if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) { - glBegin(GL_LINE_LOOP); - glVertex2f(marker->search_min[0], marker->search_min[1]); - glVertex2f(marker->search_max[0], marker->search_min[1]); - glVertex2f(marker->search_max[0], marker->search_max[1]); - glVertex2f(marker->search_min[0], marker->search_max[1]); - glEnd(); - } - glPopMatrix(); + imm_draw_box_wire_2d(position, marker->search_min[0], + marker->search_min[1], + marker->search_max[0], + marker->search_max[1]); + } + + gpuPopMatrix(); } static void track_colors(MovieTrackingTrack *track, int act, float col[3], float scol[3]) @@ -582,11 +648,12 @@ static void track_colors(MovieTrackingTrack *track, int act, float col[3], float } static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, - const float marker_pos[2], int width, int height, int act, int sel) + const float marker_pos[2], int width, int height, int act, int sel, const uint shdr_pos) { int tiny = sc->flag & SC_SHOW_TINY_MARKER; bool show_search = false; - float col[3], scol[3], px[2]; + float col[3], scol[3]; + float px[2]; track_colors(track, act, col, scol); @@ -595,23 +662,34 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra glLineWidth(1.0f); + /* Since we are switching solid and dashed lines in rather complex logic here, just always go with dashed shader. */ + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 0); /* "simple" mode */ + /* marker position and offset position */ if ((track->flag & SELECT) == sel && (marker->flag & MARKER_DISABLED) == 0) { float pos[2], p[2]; if (track->flag & TRACK_LOCKED) { - if (act) - UI_ThemeColor(TH_ACT_MARKER); - else if (track->flag & SELECT) - UI_ThemeColorShade(TH_LOCK_MARKER, 64); - else - UI_ThemeColor(TH_LOCK_MARKER); + if (act) { + immUniformThemeColor(TH_ACT_MARKER); + } + else if (track->flag & SELECT) { + immUniformThemeColorShade(TH_LOCK_MARKER, 64); + } + else { + immUniformThemeColor(TH_LOCK_MARKER); + } } else { - if (track->flag & SELECT) - glColor3fv(scol); - else - glColor3fv(col); + immUniformColor3fv((track->flag & SELECT) ? scol : col); } add_v2_v2v2(pos, marker->pos, track->offset); @@ -623,123 +701,114 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra marker->pattern_corners[2], marker->pattern_corners[3])) { glPointSize(tiny ? 1.0f : 2.0f); - glBegin(GL_POINTS); - glVertex2f(pos[0], pos[1]); - glEnd(); + + immUniform1f("dash_factor", 2.0f); /* Solid "line" */ + + immBegin(GWN_PRIM_POINTS, 1); + immVertex2f(shdr_pos, pos[0], pos[1]); + immEnd(); } else { - glBegin(GL_LINES); - glVertex2f(pos[0] + px[0] * 3, pos[1]); - glVertex2f(pos[0] + px[0] * 7, pos[1]); + immUniform1f("dash_factor", 2.0f); /* Solid line */ + + immBegin(GWN_PRIM_LINES, 8); + + immVertex2f(shdr_pos, pos[0] + px[0] * 3, pos[1]); + immVertex2f(shdr_pos, pos[0] + px[0] * 7, pos[1]); + + immVertex2f(shdr_pos, pos[0] - px[0] * 3, pos[1]); + immVertex2f(shdr_pos, pos[0] - px[0] * 7, pos[1]); - glVertex2f(pos[0] - px[0] * 3, pos[1]); - glVertex2f(pos[0] - px[0] * 7, pos[1]); + immVertex2f(shdr_pos, pos[0], pos[1] - px[1] * 3); + immVertex2f(shdr_pos, pos[0], pos[1] - px[1] * 7); - glVertex2f(pos[0], pos[1] - px[1] * 3); - glVertex2f(pos[0], pos[1] - px[1] * 7); + immVertex2f(shdr_pos, pos[0], pos[1] + px[1] * 3); + immVertex2f(shdr_pos, pos[0], pos[1] + px[1] * 7); - glVertex2f(pos[0], pos[1] + px[1] * 3); - glVertex2f(pos[0], pos[1] + px[1] * 7); - glEnd(); + immEnd(); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.0f); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); - glColor3f(0.0f, 0.0f, 0.0f); - GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); - GPU_basic_shader_line_stipple(3, 0xAAAA); glEnable(GL_COLOR_LOGIC_OP); - glLogicOp(GL_NOR); + glLogicOp(GL_XOR); - glBegin(GL_LINES); - glVertex2fv(pos); - glVertex2fv(marker_pos); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(shdr_pos, pos); + immVertex2fv(shdr_pos, marker_pos); + immEnd(); glDisable(GL_COLOR_LOGIC_OP); - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); } } /* pattern */ - glPushMatrix(); - glTranslate2fv(marker_pos); - - if (tiny) { - GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); - GPU_basic_shader_line_stipple(3, 0xAAAA); - } - else { - GPU_basic_shader_bind_enable(GPU_SHADER_LINE); - } + gpuPushMatrix(); + gpuTranslate2fv(marker_pos); - if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) { - if (track->flag & TRACK_LOCKED) { - if (act) - UI_ThemeColor(TH_ACT_MARKER); - else if (track->pat_flag & SELECT) - UI_ThemeColorShade(TH_LOCK_MARKER, 64); - else UI_ThemeColor(TH_LOCK_MARKER); + if (track->flag & TRACK_LOCKED) { + if (act) { + immUniformThemeColor(TH_ACT_MARKER); } - else if (marker->flag & MARKER_DISABLED) { - if (act) - UI_ThemeColor(TH_ACT_MARKER); - else if (track->pat_flag & SELECT) - UI_ThemeColorShade(TH_DIS_MARKER, 128); - else UI_ThemeColor(TH_DIS_MARKER); + else if (track->pat_flag & SELECT) { + immUniformThemeColorShade(TH_LOCK_MARKER, 64); } else { - if (track->pat_flag & SELECT) - glColor3fv(scol); - else glColor3fv(col); + immUniformThemeColor(TH_LOCK_MARKER); } - - glBegin(GL_LINE_LOOP); - glVertex2fv(marker->pattern_corners[0]); - glVertex2fv(marker->pattern_corners[1]); - glVertex2fv(marker->pattern_corners[2]); - glVertex2fv(marker->pattern_corners[3]); - glEnd(); } - - /* search */ - show_search = (TRACK_VIEW_SELECTED(sc, track) && - ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0; - if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) { - if (track->flag & TRACK_LOCKED) { - if (act) - UI_ThemeColor(TH_ACT_MARKER); - else if (track->search_flag & SELECT) - UI_ThemeColorShade(TH_LOCK_MARKER, 64); - else UI_ThemeColor(TH_LOCK_MARKER); + else if (marker->flag & MARKER_DISABLED) { + if (act) { + immUniformThemeColor(TH_ACT_MARKER); } - else if (marker->flag & MARKER_DISABLED) { - if (act) - UI_ThemeColor(TH_ACT_MARKER); - else if (track->search_flag & SELECT) - UI_ThemeColorShade(TH_DIS_MARKER, 128); - else UI_ThemeColor(TH_DIS_MARKER); + else if (track->pat_flag & SELECT) { + immUniformThemeColorShade(TH_DIS_MARKER, 128); } else { - if (track->search_flag & SELECT) - glColor3fv(scol); - else - glColor3fv(col); + immUniformThemeColor(TH_DIS_MARKER); } - - glBegin(GL_LINE_LOOP); - glVertex2f(marker->search_min[0], marker->search_min[1]); - glVertex2f(marker->search_max[0], marker->search_min[1]); - glVertex2f(marker->search_max[0], marker->search_max[1]); - glVertex2f(marker->search_min[0], marker->search_max[1]); - glEnd(); + } + else { + immUniformColor3fv((track->pat_flag & SELECT) ? scol : col); } if (tiny) { - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); } else { - GPU_basic_shader_bind_disable(GPU_SHADER_LINE); + immUniform1f("dash_factor", 2.0f); /* Solid line */ + } + + if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) { + immBegin(GWN_PRIM_LINE_LOOP, 4); + immVertex2fv(shdr_pos, marker->pattern_corners[0]); + immVertex2fv(shdr_pos, marker->pattern_corners[1]); + immVertex2fv(shdr_pos, marker->pattern_corners[2]); + immVertex2fv(shdr_pos, marker->pattern_corners[3]); + immEnd(); + } + + /* search */ + show_search = (TRACK_VIEW_SELECTED(sc, track) && + ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0; + + if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) { + imm_draw_box_wire_2d(shdr_pos, marker->search_min[0], marker->search_min[1], + marker->search_max[0], marker->search_max[1]); } - glPopMatrix(); + gpuPopMatrix(); + + /* Restore default shader */ + immUnbindProgram(); + + const uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + BLI_assert(pos == shdr_pos); + UNUSED_VARS_NDEBUG(pos); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); } static float get_shortest_pattern_side(MovieTrackingMarker *marker) @@ -760,7 +829,7 @@ static float get_shortest_pattern_side(MovieTrackingMarker *marker) return sqrtf(len_sq); } -static void draw_marker_slide_square(float x, float y, float dx, float dy, int outline, float px[2]) +static void draw_marker_slide_square(float x, float y, float dx, float dy, int outline, float px[2], unsigned int pos) { float tdx, tdy; @@ -772,15 +841,10 @@ static void draw_marker_slide_square(float x, float y, float dx, float dy, int o tdy += px[1]; } - glBegin(GL_QUADS); - glVertex3f(x - tdx, y + tdy, 0.0f); - glVertex3f(x + tdx, y + tdy, 0.0f); - glVertex3f(x + tdx, y - tdy, 0.0f); - glVertex3f(x - tdx, y - tdy, 0.0f); - glEnd(); + immRectf(pos, x - tdx, y - tdy, x + tdx, y + tdy); } -static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int outline, float px[2]) +static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int outline, float px[2], unsigned int pos) { float tdx, tdy; @@ -792,15 +856,16 @@ static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int tdy += px[1]; } - glBegin(GL_TRIANGLES); - glVertex3f(x, y, 0.0f); - glVertex3f(x - tdx, y, 0.0f); - glVertex3f(x, y + tdy, 0.0f); - glEnd(); + immBegin(GWN_PRIM_TRIS, 3); + immVertex2f(pos, x, y); + immVertex2f(pos, x - tdx, y); + immVertex2f(pos, x, y + tdy); + immEnd(); } static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, - const float marker_pos[2], int outline, int sel, int act, int width, int height) + const float marker_pos[2], int outline, int sel, int act, + int width, int height, unsigned int pos) { float dx, dy, patdx, patdy, searchdx, searchdy; int tiny = sc->flag & SC_SHOW_TINY_MARKER; @@ -815,11 +880,11 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo track_colors(track, act, col, scol); if (outline) { - UI_ThemeColor(TH_MARKER_OUTLINE); + immUniformThemeColor(TH_MARKER_OUTLINE); } - glPushMatrix(); - glTranslate2fv(marker_pos); + gpuPushMatrix(); + gpuTranslate2fv(marker_pos); dx = 6.0f / width / sc->zoom; dy = 6.0f / height / sc->zoom; @@ -836,17 +901,14 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo if ((sc->flag & SC_SHOW_MARKER_SEARCH) && ((track->search_flag & SELECT) == sel || outline)) { if (!outline) { - if (track->search_flag & SELECT) - glColor3fv(scol); - else - glColor3fv(col); + immUniformColor3fv((track->search_flag & SELECT) ? scol : col); } /* search offset square */ - draw_marker_slide_square(marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px); + draw_marker_slide_square(marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px, pos); /* search re-sizing triangle */ - draw_marker_slide_triangle(marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px); + draw_marker_slide_triangle(marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px, pos); } if ((sc->flag & SC_SHOW_MARKER_PATTERN) && ((track->pat_flag & SELECT) == sel || outline)) { @@ -856,16 +918,13 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo float tilt_ctrl[2]; if (!outline) { - if (track->pat_flag & SELECT) - glColor3fv(scol); - else - glColor3fv(col); + immUniformColor3fv((track->pat_flag & SELECT) ? scol : col); } /* pattern's corners sliding squares */ for (i = 0; i < 4; i++) { draw_marker_slide_square(marker->pattern_corners[i][0], marker->pattern_corners[i][1], - patdx / 1.5f, patdy / 1.5f, outline, px); + patdx / 1.5f, patdy / 1.5f, outline, px, pos); } /* ** sliders to control overall pattern ** */ @@ -875,18 +934,16 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo glLineWidth(outline ? 3.0f : 1.0f); - glBegin(GL_LINES); - glVertex2f(0.0f, 0.0f); - glVertex2fv(tilt_ctrl); - glEnd(); - - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, 0.0f, 0.0f); + immVertex2fv(pos, tilt_ctrl); + immEnd(); /* slider to control pattern tilt */ - draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px); + draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px, pos); } - glPopMatrix(); + gpuPopMatrix(); } static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, @@ -904,16 +961,17 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra fontsize = BLF_height_max(fontid); if (marker->flag & MARKER_DISABLED) { - if (act) - UI_ThemeColor(TH_ACT_MARKER); - else - UI_ThemeColorShade(TH_DIS_MARKER, 128); + if (act) { + UI_FontThemeColor(fontid, TH_ACT_MARKER); + } + else { + unsigned char color[4]; + UI_GetThemeColorShade4ubv(TH_DIS_MARKER, 128, color); + BLF_color4ubv(fontid, color); + } } else { - if (act) - UI_ThemeColor(TH_ACT_MARKER); - else - UI_ThemeColor(TH_SEL_MARKER); + UI_FontThemeColor(fontid, act ? TH_ACT_MARKER : TH_SEL_MARKER); } if ((sc->flag & SC_SHOW_MARKER_SEARCH) && @@ -974,10 +1032,7 @@ static void plane_track_colors(bool is_active, float color[3], float selected_co { UI_GetThemeColor3fv(TH_MARKER, color); - if (is_active) - UI_GetThemeColor3fv(TH_ACT_MARKER, selected_color); - else - UI_GetThemeColor3fv(TH_SEL_MARKER, selected_color); + UI_GetThemeColor3fv(is_active ? TH_ACT_MARKER : TH_SEL_MARKER, selected_color); } static void getArrowEndPoint(const int width, const int height, const float zoom, @@ -1074,9 +1129,6 @@ static void draw_plane_marker_image(Scene *scene, glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - glColor4f(1.0, 1.0, 1.0, plane_track->image_opacity); - - GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR); glGenTextures(1, (GLuint *)&texid); glBindTexture(GL_TEXTURE_2D, texid); @@ -1087,20 +1139,38 @@ static void draw_plane_marker_image(Scene *scene, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer); - glPushMatrix(); - glMultMatrixf(gl_matrix); + gpuPushMatrix(); + gpuMultMatrix(gl_matrix); + + Gwn_VertFormat *imm_format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(imm_format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int texCoord = GWN_vertformat_attr_add(imm_format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); + immUniformColor4f(1.0f, 1.0f, 1.0f, plane_track->image_opacity); + immUniform1i("image", GL_TEXTURE0); + + immBegin(GWN_PRIM_TRI_FAN, 4); + + immAttrib2f(texCoord, 0.0f, 0.0f); + immVertex2f(pos, 0.0f, 0.0f); + + immAttrib2f(texCoord, 1.0f, 0.0f); + immVertex2f(pos, 1.0f, 0.0f); + + immAttrib2f(texCoord, 1.0f, 1.0f); + immVertex2f(pos, 1.0f, 1.0f); + + immAttrib2f(texCoord, 0.0f, 1.0f); + immVertex2f(pos, 0.0f, 1.0f); + + immEnd(); - glBegin(GL_QUADS); - glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); - glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 0.0f); - glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f); - glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 1.0f); - glEnd(); + immUnbindProgram(); - glPopMatrix(); + gpuPopMatrix(); glBindTexture(GL_TEXTURE_2D, 0); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); if (transparent) { glDisable(GL_BLEND); @@ -1123,20 +1193,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane BKE_image_has_ibuf(plane_track->image, NULL); const bool draw_plane_quad = !has_image || plane_track->image_opacity == 0.0f; float px[2]; - - if (draw_outline) { - UI_ThemeColor(TH_MARKER_OUTLINE); - } - else { - float color[3], selected_color[3]; - plane_track_colors(is_active_track, color, selected_color); - if (is_selected_track) { - glColor3fv(selected_color); - } - else { - glColor3fv(color); - } - } + float color[3], selected_color[3]; px[0] = 1.0f / width / sc->zoom; px[1] = 1.0f / height / sc->zoom; @@ -1146,66 +1203,92 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane draw_plane_marker_image(scene, plane_track, plane_marker); } - if (draw_plane_quad) { + if (draw_plane_quad || is_selected_track) { + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - const bool stipple = !draw_outline && tiny; - const bool thick = draw_outline && !tiny; + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - if (stipple) { - GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); - GPU_basic_shader_line_stipple(3, 0xAAAA); - } - else { - GPU_basic_shader_bind_enable(GPU_SHADER_LINE); - } + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); - GPU_basic_shader_line_width(thick ? 3.0f : 1.0f); + immUniform1i("num_colors", 0); /* "simple" mode */ - /* Draw rectangle itself. */ - glBegin(GL_LINE_LOOP); - glVertex2fv(plane_marker->corners[0]); - glVertex2fv(plane_marker->corners[1]); - glVertex2fv(plane_marker->corners[2]); - glVertex2fv(plane_marker->corners[3]); - glEnd(); + if (draw_plane_quad) { + const bool stipple = !draw_outline && tiny; + const bool thick = draw_outline && !tiny; - /* Draw axis. */ - if (!draw_outline) { - float end_point[2]; - glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT); + glLineWidth(thick ? 3.0f : 1.0f); - glBegin(GL_LINES); + if (stipple) { + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + } + else { + immUniform1f("dash_factor", 2.0f); /* Solid line */ + } - getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point); - glColor3f(1.0, 0.0, 0.0f); - glVertex2fv(plane_marker->corners[0]); - glVertex2fv(end_point); + if (draw_outline) { + immUniformThemeColor(TH_MARKER_OUTLINE); + } + else { + plane_track_colors(is_active_track, color, selected_color); + immUniformColor3fv(is_selected_track ? selected_color : color); + } - getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point); - glColor3f(0.0, 1.0, 0.0f); - glVertex2fv(plane_marker->corners[0]); - glVertex2fv(end_point); + /* Draw rectangle itself. */ + immBegin(GWN_PRIM_LINE_LOOP, 4); + immVertex2fv(shdr_pos, plane_marker->corners[0]); + immVertex2fv(shdr_pos, plane_marker->corners[1]); + immVertex2fv(shdr_pos, plane_marker->corners[2]); + immVertex2fv(shdr_pos, plane_marker->corners[3]); + immEnd(); - glEnd(); + /* Draw axis. */ + if (!draw_outline) { + float end_point[2]; - glPopAttrib(); - } + immUniformColor3f(1.0f, 0.0f, 0.0f); - if (stipple) { - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); - } - else { - GPU_basic_shader_bind_disable(GPU_SHADER_LINE); + immBegin(GWN_PRIM_LINES, 2); + + getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point); + immVertex2fv(shdr_pos, plane_marker->corners[0]); + immVertex2fv(shdr_pos, end_point); + + immEnd(); + + immUniformColor3f(0.0f, 1.0f, 0.0f); + + immBegin(GWN_PRIM_LINES, 2); + + getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point); + immVertex2fv(shdr_pos, plane_marker->corners[0]); + immVertex2fv(shdr_pos, end_point); + + immEnd(); + } } - } - /* Draw sliders. */ - if (is_selected_track) { - int i; - for (i = 0; i < 4; i++) { - draw_marker_slide_square(plane_marker->corners[i][0], plane_marker->corners[i][1], - 3.0f * px[0], 3.0f * px[1], draw_outline, px); + /* Draw sliders. */ + if (is_selected_track) { + immUniform1f("dash_factor", 2.0f); /* Solid line */ + + if (draw_outline) { + immUniformThemeColor(TH_MARKER_OUTLINE); + } + else { + immUniformColor3fv(selected_color); + } + + int i; + for (i = 0; i < 4; i++) { + draw_marker_slide_square(plane_marker->corners[i][0], plane_marker->corners[i][1], + 3.0f * px[0], 3.0f * px[1], draw_outline, px, shdr_pos); + } } + + immUnbindProgram(); } } @@ -1257,13 +1340,13 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y); - glPushMatrix(); - glTranslatef(x, y, 0); + gpuPushMatrix(); + gpuTranslate2f(x, y); - glPushMatrix(); - glScalef(zoomx, zoomy, 0); - glMultMatrixf(sc->stabmat); - glScalef(width, height, 0); + gpuPushMatrix(); + gpuScale2f(zoomx, zoomy); + gpuMultMatrix(sc->stabmat); + gpuScale2f(width, height); act_track = BKE_tracking_track_get_active(tracking); @@ -1329,6 +1412,10 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie } } + unsigned int position = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* markers outline and non-selected areas */ track = tracksbase->first; fp = marker_pos; @@ -1339,10 +1426,10 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie if (MARKER_VISIBLE(sc, track, marker)) { copy_v2_v2(cur_pos, fp ? fp : marker->pos); - draw_marker_outline(sc, track, marker, cur_pos, width, height); - draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0); - draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height); - draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height); + draw_marker_outline(sc, track, marker, cur_pos, width, height, position); + draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0, position); + draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height, position); + draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height, position); if (fp) fp += 2; @@ -1365,8 +1452,8 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie if (!act) { copy_v2_v2(cur_pos, fp ? fp : marker->pos); - draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1); - draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height); + draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1, position); + draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height, position); } if (fp) @@ -1385,8 +1472,8 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie if (MARKER_VISIBLE(sc, act_track, marker)) { copy_v2_v2(cur_pos, active_pos ? active_pos : marker->pos); - draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1); - draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height); + draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1, position); + draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height, position); } } } @@ -1395,7 +1482,6 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); float pos[4], vec[4], mat[4][4], aspy; - glEnable(GL_POINT_SMOOTH); glPointSize(3.0f); aspy = 1.0f / clip->tracking.camera.pixel_aspect; @@ -1424,28 +1510,34 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie sub_v2_v2(vec, npos); - if (len_squared_v2(vec) < (3.0f * 3.0f)) - glColor3f(0.0f, 1.0f, 0.0f); - else - glColor3f(1.0f, 0.0f, 0.0f); + if (len_squared_v2(vec) < (3.0f * 3.0f)) { + immUniformColor3f(0.0f, 1.0f, 0.0f); + } + else { + immUniformColor3f(1.0f, 0.0f, 0.0f); + } - glBegin(GL_POINTS); - if (undistort) - glVertex3f(pos[0] / width, pos[1] / (height * aspy), 0); - else - glVertex3f(npos[0] / width, npos[1] / (height * aspy), 0); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + + if (undistort) { + immVertex2f(position, pos[0] / width, pos[1] / (height * aspy)); + } + else { + immVertex2f(position, npos[0] / width, npos[1] / (height * aspy)); + } + + immEnd(); } } } track = track->next; } - - glDisable(GL_POINT_SMOOTH); } - glPopMatrix(); + immUnbindProgram(); + + gpuPopMatrix(); if (sc->flag & SC_SHOW_NAMES) { /* scaling should be cleared before drawing texts, otherwise font would also be scaled */ @@ -1471,7 +1563,7 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie } } - glPopMatrix(); + gpuPopMatrix(); if (marker_pos) MEM_freeN(marker_pos); @@ -1498,11 +1590,15 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y); - glPushMatrix(); - glTranslatef(x, y, 0); - glScalef(zoomx, zoomy, 0); - glMultMatrixf(sc->stabmat); - glScalef(width, height, 0); + gpuPushMatrix(); + gpuTranslate2f(x, y); + gpuScale2f(zoomx, zoomy); + gpuMultMatrix(sc->stabmat); + gpuScale2f(width, height); + + unsigned int position = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* grid */ if (sc->flag & SC_SHOW_GRID) { @@ -1574,22 +1670,26 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, pos[1] += dy; } - glColor3f(1.0f, 0.0f, 0.0f); + immUniformColor3f(1.0f, 0.0f, 0.0f); for (i = 0; i <= n; i++) { - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, n + 1); + for (j = 0; j <= n; j++) { - glVertex2fv(grid[i][j]); + immVertex2fv(position, grid[i][j]); } - glEnd(); + + immEnd(); } for (j = 0; j <= n; j++) { - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, n + 1); + for (i = 0; i <= n; i++) { - glVertex2fv(grid[i][j]); + immVertex2fv(position, grid[i][j]); } - glEnd(); + + immEnd(); } } @@ -1608,7 +1708,8 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, continue; } - glColor4fv(layer->color); + immUniformColor4fv(layer->color); + glLineWidth(layer->thickness); glPointSize((float)(layer->thickness + 2)); @@ -1618,7 +1719,6 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, while (stroke) { if (stroke->flag & GP_STROKE_2DSPACE) { if (stroke->totpoints > 1) { - glBegin(GL_LINE_STRIP); for (i = 0; i < stroke->totpoints - 1; i++) { float npos[2], dpos[2], len; int steps; @@ -1641,19 +1741,22 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, sub_v2_v2v2(dpos, npos, pos); mul_v2_fl(dpos, 1.0f / steps); + immBegin(GWN_PRIM_LINE_STRIP, steps + 1); + for (j = 0; j <= steps; j++) { BKE_tracking_distort_v2(tracking, pos, tpos); - glVertex2f(tpos[0] / width, tpos[1] / (height * aspy)); + immVertex2f(position, tpos[0] / width, tpos[1] / (height * aspy)); add_v2_v2(pos, dpos); } + + immEnd(); } - glEnd(); } else if (stroke->totpoints == 1) { - glBegin(GL_POINTS); - glVertex2f(stroke->points[0].x + offsx, stroke->points[0].y + offsy); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex2f(position, stroke->points[0].x + offsx, stroke->points[0].y + offsy); + immEnd(); } } @@ -1667,7 +1770,9 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, } } - glPopMatrix(); + immUnbindProgram(); + + gpuPopMatrix(); } void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar) @@ -1764,8 +1869,8 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d) * associated with the clip is already drawn in draw_distortion */ if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || is_track_source) { - glPushMatrix(); - glMultMatrixf(sc->unistabmat); + gpuPushMatrix(); + gpuMultMatrix(sc->unistabmat); if (is_track_source) { MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking); @@ -1774,13 +1879,13 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d) int framenr = ED_space_clip_get_clip_frame_number(sc); MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); - glTranslate2fv(marker->pos); + gpuTranslate2fv(marker->pos); } } ED_gpencil_draw_2dimage(C); - glPopMatrix(); + gpuPopMatrix(); } } else { diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 59dd755173f..942bc2661c3 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -305,15 +305,12 @@ bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r void ED_clip_update_frame(const Main *mainp, int cfra) { - wmWindowManager *wm; - wmWindow *win; - /* image window, compo node users */ - for (wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */ - for (win = wm->windows.first; win; win = win->next) { - ScrArea *sa; + for (wmWindowManager *wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */ + for (wmWindow *win = wm->windows.first; win; win = win->next) { + bScreen *screen = WM_window_get_active_screen(win); - for (sa = win->screen->areabase.first; sa; sa = sa->next) { + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { if (sa->spacetype == SPACE_CLIP) { SpaceClip *sc = sa->spacedata.first; diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c index 424d25defdd..1bd1ad69d64 100644 --- a/source/blender/editors/space_clip/clip_graph_draw.c +++ b/source/blender/editors/space_clip/clip_graph_draw.c @@ -42,7 +42,9 @@ #include "ED_screen.h" #include "ED_clip.h" -#include "BIF_gl.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" #include "WM_types.h" @@ -53,52 +55,30 @@ #include "clip_intern.h" // own include -static void draw_curve_knot(float x, float y, float xscale, float yscale, float hsize) -{ - static GLuint displist = 0; - - /* initialize round circle shape */ - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - gluDisk(qobj, 0, 0.7, 8, 1); - gluDeleteQuadric(qobj); - - glEndList(); - } - - glPushMatrix(); - - glTranslatef(x, y, 0.0f); - glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f); - glCallList(displist); - - glPopMatrix(); -} +typedef struct TrackMotionCurveUserData { + MovieTrackingTrack *act_track; + bool sel; + float xscale, yscale, hsize; + unsigned int pos; +} TrackMotionCurveUserData; -static void tracking_segment_point_cb(void *UNUSED(userdata), MovieTrackingTrack *UNUSED(track), +static void tracking_segment_point_cb(void *userdata, MovieTrackingTrack *UNUSED(track), MovieTrackingMarker *UNUSED(marker), int UNUSED(coord), int scene_framenr, float val) { - glVertex2f(scene_framenr, val); + TrackMotionCurveUserData *data = (TrackMotionCurveUserData *) userdata; + + immVertex2f(data->pos, scene_framenr, val); } -static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord) +static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord, bool is_point) { - const float colors[2][3] = { - {1.0f, 0.0f, 0.0f}, - {0.0f, 1.0f, 0.0f}, - }; - float col[4]; + TrackMotionCurveUserData *data = (TrackMotionCurveUserData *) userdata; + float col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - copy_v3_v3(col, colors[coord]); + col[coord] = 1.0f; - if (track == userdata) { + if (track == data->act_track) { col[3] = 1.0f; glLineWidth(2.0f); } @@ -107,22 +87,22 @@ static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, glLineWidth(1.0f); } - glColor4fv(col); + immUniformColor4fv(col); - glBegin(GL_LINE_STRIP); + if (is_point) { + immBeginAtMost(GWN_PRIM_POINTS, 1); + } + else { + /* Graph can be composed of smaller segments, if any marker is disabled */ + immBeginAtMost(GWN_PRIM_LINE_STRIP, track->markersnr); + } } static void tracking_segment_end_cb(void *UNUSED(userdata), int UNUSED(coord)) { - glEnd(); + immEnd(); } -typedef struct TrackMotionCurveUserData { - MovieTrackingTrack *act_track; - bool sel; - float xscale, yscale, hsize; -} TrackMotionCurveUserData; - static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, int scene_framenr, float val) { @@ -136,16 +116,19 @@ static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track, sel = (marker->flag & sel_flag) ? 1 : 0; if (sel == data->sel) { - if (sel) - UI_ThemeColor(TH_HANDLE_VERTEX_SELECT); - else - UI_ThemeColor(TH_HANDLE_VERTEX); + immUniformThemeColor(sel ? TH_HANDLE_VERTEX_SELECT : TH_HANDLE_VERTEX); + + gpuPushMatrix(); + gpuTranslate2f(scene_framenr, val); + gpuScale2f(1.0f / data->xscale * data->hsize, 1.0f / data->yscale * data->hsize); - draw_curve_knot(scene_framenr, val, data->xscale, data->yscale, data->hsize); + imm_draw_circle_wire_2d(data->pos, 0, 0, 0.7, 8); + + gpuPopMatrix(); } } -static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc) +static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc, unsigned int pos) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; @@ -162,18 +145,18 @@ static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc) userdata.hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); userdata.sel = false; userdata.act_track = act_track; + userdata.pos = pos; UI_view2d_scale_get(v2d, &userdata.xscale, &userdata.yscale); clip_graph_tracking_values_iterate(sc, (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, &userdata, tracking_segment_knot_cb, NULL, NULL); - /* draw graph lines */ glEnable(GL_BLEND); clip_graph_tracking_values_iterate(sc, (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, - act_track, tracking_segment_point_cb, tracking_segment_start_cb, + &userdata, tracking_segment_point_cb, tracking_segment_start_cb, tracking_segment_end_cb); glDisable(GL_BLEND); @@ -195,6 +178,7 @@ typedef struct TrackErrorCurveUserData { float projection_matrix[4][4]; int width, height; float aspy; + unsigned int pos; } TrackErrorCurveUserData; static void tracking_error_segment_point_cb(void *userdata, @@ -230,11 +214,11 @@ static void tracking_error_segment_point_cb(void *userdata, sub_v2_v2v2(delta, reprojected_position, marker_position); reprojection_error = len_v2(delta) * weight; - glVertex2f(scene_framenr, reprojection_error); + immVertex2f(data->pos, scene_framenr, reprojection_error); } } -static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord) +static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord, bool is_point) { if (coord == 1) { TrackErrorCurveUserData *data = (TrackErrorCurveUserData *) userdata; @@ -249,20 +233,26 @@ static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack * glLineWidth(1.0f); } - glColor4fv(col); + immUniformColor4fv(col); - glBegin(GL_LINE_STRIP); + if (is_point) { /* This probably never happens here, but just in case... */ + immBeginAtMost(GWN_PRIM_POINTS, 1); + } + else { + /* Graph can be composed of smaller segments, if any marker is disabled */ + immBeginAtMost(GWN_PRIM_LINE_STRIP, track->markersnr); + } } } static void tracking_error_segment_end_cb(void *UNUSED(userdata), int coord) { if (coord == 1) { - glEnd(); + immEnd(); } } -static void draw_tracks_error_curves(SpaceClip *sc) +static void draw_tracks_error_curves(SpaceClip *sc, unsigned int pos) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; @@ -273,6 +263,7 @@ static void draw_tracks_error_curves(SpaceClip *sc) data.tracking_object = BKE_tracking_object_get_active(tracking); data.active_track = BKE_tracking_track_get_active(tracking); data.matrix_initialized = false; + data.pos = pos; BKE_movieclip_get_size(clip, &sc->user, &data.width, &data.height); data.aspy = 1.0f / tracking->camera.pixel_aspect; @@ -289,37 +280,38 @@ static void draw_tracks_error_curves(SpaceClip *sc) tracking_error_segment_end_cb); } -static void draw_frame_curves(SpaceClip *sc) +static void draw_frame_curves(SpaceClip *sc, unsigned int pos) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking); int i, lines = 0, prevfra = 0; - glColor3f(0.0f, 0.0f, 1.0f); + immUniformColor3f(0.0f, 0.0f, 1.0f); for (i = 0; i < reconstruction->camnr; i++) { MovieReconstructedCamera *camera = &reconstruction->cameras[i]; int framenr; if (lines && camera->framenr != prevfra + 1) { - glEnd(); + immEnd(); lines = 0; } if (!lines) { - glBegin(GL_LINE_STRIP); + immBeginAtMost(GWN_PRIM_LINE_STRIP, reconstruction->camnr); lines = 1; } framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, camera->framenr); - glVertex2f(framenr, camera->error); + immVertex2f(pos, framenr, camera->error); prevfra = camera->framenr; } - if (lines) - glEnd(); + if (lines) { + immEnd(); + } } void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene) @@ -335,14 +327,24 @@ void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene) UI_view2d_grid_free(grid); if (clip) { - if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) - draw_tracks_motion_curves(v2d, sc); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + glPointSize(3.0f); - if (sc->flag & SC_SHOW_GRAPH_TRACKS_ERROR) - draw_tracks_error_curves(sc); + if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) { + draw_tracks_motion_curves(v2d, sc, pos); + } + + if (sc->flag & SC_SHOW_GRAPH_TRACKS_ERROR) { + draw_tracks_error_curves(sc, pos); + } + + if (sc->flag & SC_SHOW_GRAPH_FRAMES) { + draw_frame_curves(sc, pos); + } - if (sc->flag & SC_SHOW_GRAPH_FRAMES) - draw_frame_curves(sc); + immUnbindProgram(); } /* frame range */ diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index 9ad4fd4642a..e5a3cb6b57b 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -37,7 +37,8 @@ #include "BKE_context.h" #include "BKE_tracking.h" -#include "BKE_depsgraph.h" + +#include "DEG_depsgraph.h" #include "WM_api.h" #include "WM_types.h" @@ -691,7 +692,7 @@ static int graph_disable_markers_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip); diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 14393c6968b..ffc7a41f0aa 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -125,12 +125,12 @@ void ED_clip_tool_props_register(struct ARegionType *art); /* clip_utils.c */ void clip_graph_tracking_values_iterate_track(struct SpaceClip *sc, struct MovieTrackingTrack *track, void *userdata, void (*func)(void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, int scene_framenr, float val), - void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord), + void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord, bool is_point), void (*segment_end)(void *userdata, int coord)); void clip_graph_tracking_values_iterate(struct SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata, void (*func)(void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, int scene_framenr, float val), - void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord), + void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord, bool is_point), void (*segment_end)(void *userdata, int coord)); void clip_graph_tracking_iterate(struct SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata, diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 7d8dd629562..4afec844f6d 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -56,7 +56,6 @@ #include "BKE_context.h" #include "BKE_global.h" -#include "BKE_depsgraph.h" #include "BKE_report.h" #include "BKE_library.h" #include "BKE_main.h" @@ -83,6 +82,8 @@ #include "PIL_time.h" +#include "DEG_depsgraph_build.h" + #include "clip_intern.h" // own include /******************** view navigation utilities *********************/ @@ -248,7 +249,7 @@ static int open_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_MOVIECLIP | NA_ADDED, clip); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); MEM_freeN(op->customdata); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index e901b9f8026..40661937bae 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -41,10 +41,11 @@ #include "BKE_context.h" #include "BKE_movieclip.h" #include "BKE_tracking.h" -#include "BKE_depsgraph.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" +#include "DEG_depsgraph.h" + +#include "GPU_immediate.h" +#include "GPU_matrix.h" #include "WM_api.h" #include "WM_types.h" @@ -52,7 +53,6 @@ #include "ED_screen.h" #include "ED_clip.h" - #include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -63,7 +63,7 @@ void clip_graph_tracking_values_iterate_track( SpaceClip *sc, MovieTrackingTrack *track, void *userdata, void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, int scene_framenr, float val), - void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), + void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord, bool is_point), void (*segment_end)(void *userdata, int coord)) { MovieClip *clip = ED_space_clip_get_clip(sc); @@ -92,8 +92,14 @@ void clip_graph_tracking_values_iterate_track( } if (!open) { - if (segment_start) - segment_start(userdata, track, coord); + if (segment_start) { + if ((i + 1) == track->markersnr) { + segment_start(userdata, track, coord, true); + } + else { + segment_start(userdata, track, coord, (track->markers[i + 1].flag & MARKER_DISABLED)); + } + } open = true; prevval = marker->pos[coord]; @@ -124,7 +130,7 @@ void clip_graph_tracking_values_iterate( SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata, void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, int scene_framenr, float val), - void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), + void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord, bool is_point), void (*segment_end)(void *userdata, int coord)) { MovieClip *clip = ED_space_clip_get_clip(sc); @@ -205,7 +211,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); } - DAG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&clip->id, 0); if (has_bundle) WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); @@ -238,31 +244,35 @@ void clip_view_center_to_point(SpaceClip *sc, float x, float y) void clip_draw_cfra(SpaceClip *sc, ARegion *ar, Scene *scene) { + /* Draw a light green line to indicate current frame */ View2D *v2d = &ar->v2d; - float xscale, yscale; + float x = (float)(sc->user.framenr * scene->r.framelen); - /* Draw a light green line to indicate current frame */ - UI_ThemeColor(TH_CFRAME); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - float x = (float)(sc->user.framenr * scene->r.framelen); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_CFRAME); + glLineWidth(2.0f); - glLineWidth(2.0); + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, x, v2d->cur.ymin); + immVertex2f(pos, x, v2d->cur.ymax); + immEnd(); - glBegin(GL_LINES); - glVertex2f(x, v2d->cur.ymin); - glVertex2f(x, v2d->cur.ymax); - glEnd(); + immUnbindProgram(); UI_view2d_view_orthoSpecial(ar, v2d, 1); /* because the frame number text is subject to the same scaling as the contents of the view */ - UI_view2d_scale_get(v2d, &xscale, &yscale); - glScalef(1.0f / xscale, 1.0f, 1.0f); + float xscale; + UI_view2d_scale_get(v2d, &xscale, NULL); + gpuPushMatrix(); + gpuScale2f(1.0f / xscale, 1.0f); ED_region_cache_draw_curfra_label(sc->user.framenr, (float)sc->user.framenr * xscale, 18); /* restore view transform */ - glScalef(xscale, 1.0, 1.0); + gpuPopMatrix(); } void clip_draw_sfra_efra(View2D *v2d, Scene *scene) @@ -272,15 +282,27 @@ void clip_draw_sfra_efra(View2D *v2d, Scene *scene) /* currently clip editor supposes that editing clip length is equal to scene frame range */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); - glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax); - glRectf((float)EFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); + immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax); + immRectf(pos, (float)EFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + glDisable(GL_BLEND); - UI_ThemeColorShade(TH_BACK, -60); + immUniformThemeColorShade(TH_BACK, -60); /* thin lines where the actual frames are */ - fdrawline((float)SFRA, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax); - fdrawline((float)EFRA, v2d->cur.ymin, (float)EFRA, v2d->cur.ymax); + glLineWidth(1.0f); + + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, (float)SFRA, v2d->cur.ymin); + immVertex2f(pos, (float)SFRA, v2d->cur.ymax); + immVertex2f(pos, (float)EFRA, v2d->cur.ymin); + immVertex2f(pos, (float)EFRA, v2d->cur.ymax); + immEnd(); + + immUnbindProgram(); } diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 58930fa2cf2..478254fb165 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -60,7 +60,8 @@ #include "IMB_imbuf.h" -#include "BIF_gl.h" +#include "GPU_glew.h" +#include "GPU_matrix.h" #include "WM_api.h" #include "WM_types.h" @@ -329,7 +330,8 @@ static SpaceLink *clip_duplicate(SpaceLink *sl) return (SpaceLink *)scn; } -static void clip_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) +static void clip_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { /* context changes */ switch (wmn->category) { @@ -1214,13 +1216,13 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar) show_cursor |= sc->around == V3D_AROUND_CURSOR; if (show_cursor) { - glPushMatrix(); - glTranslatef(x, y, 0); - glScalef(zoomx, zoomy, 0); - glMultMatrixf(sc->stabmat); - glScalef(width, height, 0); + gpuPushMatrix(); + gpuTranslate2f(x, y); + gpuScale2f(zoomx, zoomy); + gpuMultMatrix(sc->stabmat); + gpuScale2f(width, height); ED_image_draw_cursor(ar, sc->cursor); - glPopMatrix(); + gpuPopMatrix(); } clip_draw_cache_and_notes(C, sc, ar); @@ -1239,7 +1241,9 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar) } } -static void clip_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void clip_main_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -1350,7 +1354,9 @@ static void clip_preview_region_draw(const bContext *C, ARegion *ar) dopesheet_region_draw(C, ar); } -static void clip_preview_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn)) +static void clip_preview_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), + wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene)) { } @@ -1391,7 +1397,9 @@ static void clip_channels_region_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); } -static void clip_channels_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn)) +static void clip_channels_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), + wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene)) { } @@ -1408,7 +1416,9 @@ static void clip_header_region_draw(const bContext *C, ARegion *ar) ED_region_header(C, ar); } -static void clip_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void clip_header_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -1448,7 +1458,9 @@ static void clip_tools_region_draw(const bContext *C, ARegion *ar) /****************** tool properties region ******************/ -static void clip_props_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void clip_props_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -1493,7 +1505,9 @@ static void clip_properties_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, NULL, -1, true); } -static void clip_properties_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void clip_properties_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index f32071b81dc..2439ac06d9c 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -42,10 +42,11 @@ #include "BKE_context.h" #include "BKE_movieclip.h" #include "BKE_tracking.h" -#include "BKE_depsgraph.h" #include "BKE_report.h" #include "BKE_sound.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -905,7 +906,7 @@ static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event) } WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - DAG_id_tag_update(&sc->clip->id, 0); + DEG_id_tag_update(&sc->clip->id, 0); } else if (data->area == TRACK_AREA_PAT) { if (data->action == SLIDE_ACTION_SIZE) { @@ -1200,7 +1201,7 @@ static int disable_markers_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip); diff --git a/source/blender/editors/space_clip/tracking_ops_orient.c b/source/blender/editors/space_clip/tracking_ops_orient.c index 71a5a825b0e..e62b6499dea 100644 --- a/source/blender/editors/space_clip/tracking_ops_orient.c +++ b/source/blender/editors/space_clip/tracking_ops_orient.c @@ -43,10 +43,12 @@ #include "BKE_constraint.h" #include "BKE_tracking.h" #include "BKE_global.h" -#include "BKE_depsgraph.h" +#include "BKE_layer.h" #include "BKE_object.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -69,17 +71,16 @@ static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip) return camera; } - for (Base *base = scene->base.first; - base != NULL; - base = base->next) + FOREACH_SCENE_OBJECT(scene, ob) { - if (base->object->type == OB_CAMERA) { - if (BKE_object_movieclip_get(scene, base->object, false) == clip) { - camera = base->object; + if (ob->type == OB_CAMERA) { + if (BKE_object_movieclip_get(scene, ob, false) == clip) { + camera = ob; break; } } } + FOREACH_SCENE_OBJECT_END return camera; } @@ -87,6 +88,7 @@ static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip) static Object *get_orientation_object(bContext *C) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; @@ -97,7 +99,7 @@ static Object *get_orientation_object(bContext *C) object = get_camera_with_movieclip(scene, clip); } else { - object = OBACT; + object = OBACT(sl); } if (object != NULL && object->parent != NULL) { @@ -111,7 +113,7 @@ static int set_orientation_poll(bContext *C) { SpaceClip *sc = CTX_wm_space_clip(C); if (sc != NULL) { - Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); MovieClip *clip = ED_space_clip_get_clip(sc); if (clip != NULL) { MovieTracking *tracking = &clip->tracking; @@ -120,7 +122,7 @@ static int set_orientation_poll(bContext *C) return true; } else { - return OBACT != NULL; + return OBACT(sl) != NULL; } } } @@ -247,8 +249,8 @@ static int set_origin_exec(bContext *C, wmOperator *op) copy_v3_v3(object->loc, vec); } - DAG_id_tag_update(&clip->id, 0); - DAG_id_tag_update(&object->id, OB_RECALC_OB); + DEG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&object->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); @@ -404,6 +406,7 @@ static int set_plane_exec(bContext *C, wmOperator *op) ListBase *tracksbase; Object *object; Object *camera = get_camera_with_movieclip(scene, clip); + EvaluationContext eval_ctx; int tot = 0; float vec[3][3], mat[4][4], obmat[4][4], newmat[4][4], orig[3] = {0.0f, 0.0f, 0.0f}; int plane = RNA_enum_get(op->ptr, "plane"); @@ -428,6 +431,8 @@ static int set_plane_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + CTX_data_eval_ctx(C, &eval_ctx); + BKE_tracking_get_camera_object_matrix(scene, camera, mat); /* Get 3 bundles to use as reference. */ @@ -490,11 +495,11 @@ static int set_plane_exec(bContext *C, wmOperator *op) BKE_object_apply_mat4(object, mat, 0, 0); } - BKE_object_where_is_calc(scene, object); + BKE_object_where_is_calc(&eval_ctx, scene, object); set_axis(scene, object, clip, tracking_object, axis_track, 'X'); - DAG_id_tag_update(&clip->id, 0); - DAG_id_tag_update(&object->id, OB_RECALC_OB); + DEG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&object->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); @@ -567,8 +572,8 @@ static int set_axis_exec(bContext *C, wmOperator *op) set_axis(scene, object, clip, tracking_object, track, axis == 0 ? 'X' : 'Y'); - DAG_id_tag_update(&clip->id, 0); - DAG_id_tag_update(&object->id, OB_RECALC_OB); + DEG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&object->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); @@ -694,10 +699,10 @@ static int do_set_scale(bContext *C, tracking_object->scale = scale; } - DAG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&clip->id, 0); if (object) - DAG_id_tag_update(&object->id, OB_RECALC_OB); + DEG_id_tag_update(&object->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); diff --git a/source/blender/editors/space_clip/tracking_ops_plane.c b/source/blender/editors/space_clip/tracking_ops_plane.c index aa8518befaa..6c85bdfc4ec 100644 --- a/source/blender/editors/space_clip/tracking_ops_plane.c +++ b/source/blender/editors/space_clip/tracking_ops_plane.c @@ -39,9 +39,10 @@ #include "BKE_context.h" #include "BKE_tracking.h" -#include "BKE_depsgraph.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -372,7 +373,7 @@ static int slide_plane_marker_modal(bContext *C, data->previous_mval[1] = event->mval[1]; copy_v2_v2(data->previous_corner, data->corner); - DAG_id_tag_update(&sc->clip->id, 0); + DEG_id_tag_update(&sc->clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL); @@ -390,7 +391,7 @@ static int slide_plane_marker_modal(bContext *C, clip_tracking_show_cursor(C); - DAG_id_tag_update(&sc->clip->id, 0); + DEG_id_tag_update(&sc->clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_clip/tracking_ops_solve.c b/source/blender/editors/space_clip/tracking_ops_solve.c index 5c74c1947e3..89dfadc8974 100644 --- a/source/blender/editors/space_clip/tracking_ops_solve.c +++ b/source/blender/editors/space_clip/tracking_ops_solve.c @@ -43,10 +43,11 @@ #include "BKE_movieclip.h" #include "BKE_tracking.h" #include "BKE_global.h" -#include "BKE_depsgraph.h" #include "BKE_report.h" #include "BKE_library.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -180,7 +181,7 @@ static void solve_camera_freejob(void *scv) MEM_freeN(tracking->stats); tracking->stats = NULL; - DAG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&clip->id, 0); WM_main_add_notifier(NC_MOVIECLIP | NA_EVALUATED, clip); WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, NULL); @@ -327,7 +328,7 @@ static int clear_solution_exec(bContext *C, wmOperator *UNUSED(op)) reconstruction->camnr = 0; reconstruction->flag &= ~TRACKING_RECONSTRUCTED; - DAG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); diff --git a/source/blender/editors/space_clip/tracking_ops_stabilize.c b/source/blender/editors/space_clip/tracking_ops_stabilize.c index 35b1aead343..4eb6a4fbb24 100644 --- a/source/blender/editors/space_clip/tracking_ops_stabilize.c +++ b/source/blender/editors/space_clip/tracking_ops_stabilize.c @@ -38,7 +38,8 @@ #include "BKE_context.h" #include "BKE_tracking.h" -#include "BKE_depsgraph.h" + +#include "DEG_depsgraph.h" #include "WM_api.h" #include "WM_types.h" @@ -84,7 +85,7 @@ static int stabilize_2d_add_exec(bContext *C, wmOperator *UNUSED(op)) } if (update) { - DAG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); } @@ -138,7 +139,7 @@ static int stabilize_2d_remove_exec(bContext *C, wmOperator *UNUSED(op)) } if (update) { - DAG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); } @@ -227,7 +228,7 @@ static int stabilize_2d_rotation_add_exec(bContext *C, wmOperator *UNUSED(op)) } if (update) { - DAG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); } @@ -281,7 +282,7 @@ static int stabilize_2d_rotation_remove_exec(bContext *C, wmOperator *UNUSED(op) } if (update) { - DAG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); } diff --git a/source/blender/editors/space_clip/tracking_ops_track.c b/source/blender/editors/space_clip/tracking_ops_track.c index 0dd0ee8c7d4..cd8e92c9b9c 100644 --- a/source/blender/editors/space_clip/tracking_ops_track.c +++ b/source/blender/editors/space_clip/tracking_ops_track.c @@ -297,7 +297,8 @@ static void track_markers_endjob(void *tmv) tmj->scene->r.cfra = BKE_movieclip_remap_clip_to_scene_frame(tmj->clip, tmj->lastfra); if (wm != NULL) { - ED_update_for_newframe(tmj->main, tmj->scene, 0); + // XXX: ... + // ED_update_for_newframe(tmj->main, tmj->scene); } BKE_autotrack_context_sync(tmj->context); diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c index 6396b390ca0..c8a06545e0f 100644 --- a/source/blender/editors/space_console/console_draw.c +++ b/source/blender/editors/space_console/console_draw.c @@ -40,6 +40,7 @@ #include "MEM_guardedalloc.h" #include "BIF_gl.h" +#include "GPU_immediate.h" #include "UI_interface.h" #include "UI_resources.h" @@ -157,6 +158,8 @@ static int console_textview_line_color(struct TextViewContext *tvc, unsigned cha int offl = 0, offc = 0; int xy[2] = {CONSOLE_DRAW_MARGIN, CONSOLE_DRAW_MARGIN}; int pen[2]; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); xy[1] += tvc->lheight / 6; console_cursor_wrap_offset(sc->prompt, tvc->console_width, &offl, &offc, NULL); @@ -168,14 +171,17 @@ static int console_textview_line_color(struct TextViewContext *tvc, unsigned cha pen[1] += tvc->lheight * offl; /* cursor */ - UI_GetThemeColor3ubv(TH_CONSOLE_CURSOR, fg); - glColor3ubv(fg); - - glRecti((xy[0] + pen[0]) - 1, - (xy[1] + pen[1]), - (xy[0] + pen[0]) + 1, - (xy[1] + pen[1] + tvc->lheight) - ); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_CONSOLE_CURSOR); + + immRectf(pos, + (xy[0] + pen[0]) - 1, + (xy[1] + pen[1]), + (xy[0] + pen[0]) + 1, + (xy[1] + pen[1] + tvc->lheight) + ); + + immUnbindProgram(); } console_line_color(fg, cl_iter->type); diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index 97a85bce006..9a2f4b5d431 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -368,7 +368,9 @@ static void console_header_region_draw(const bContext *C, ARegion *ar) ED_region_header(C, ar); } -static void console_main_region_listener(bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar, wmNotifier *wmn) +static void console_main_region_listener( + bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { // SpaceInfo *sinfo = sa->spacedata.first; diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 52d01063175..c1e298c426f 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -42,7 +42,6 @@ # include "BLI_winstuff.h" #endif -#include "BIF_gl.h" #include "BIF_glutil.h" #include "BKE_context.h" @@ -71,6 +70,9 @@ #include "WM_api.h" #include "WM_types.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" + #include "filelist.h" #include "file_intern.h" // own include @@ -258,9 +260,10 @@ void file_draw_buttons(const bContext *C, ARegion *ar) static void draw_tile(int sx, int sy, int width, int height, int colorid, int shade) { - UI_ThemeColorShade(colorid, shade); + float color[4]; + UI_GetThemeColorShade4fv(colorid, shade, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox((float)sx, (float)(sy - height), (float)(sx + width), (float)sy, 5.0f); + UI_draw_roundbox_aa(true, (float)sx, (float)(sy - height), (float)(sx + width), (float)sy, 5.0f, color); } @@ -285,7 +288,8 @@ static void file_draw_icon(uiBlock *block, const char *path, int sx, int sy, int } -static void file_draw_string(int sx, int sy, const char *string, float width, int height, short align) +static void file_draw_string(int sx, int sy, const char *string, float width, int height, short align, + const unsigned char col[4]) { uiStyle *style; uiFontStyle fs; @@ -310,7 +314,7 @@ static void file_draw_string(int sx, int sy, const char *string, float width, in rect.ymin = sy - height; rect.ymax = sy; - UI_fontstyle_draw(&fs, &rect, fname); + UI_fontstyle_draw(&fs, &rect, fname, col); } void file_calc_previews(const bContext *C, ARegion *ar) @@ -335,6 +339,7 @@ static void file_draw_preview( float scale; int ex, ey; bool use_dropshadow = !is_icon && (typeflags & FILE_TYPE_IMAGE); + float col[4] = {1.0f, 1.0f, 1.0f, 1.0f}; BLI_assert(imb != NULL); @@ -381,12 +386,12 @@ static void file_draw_preview( /* the image */ if (!is_icon && typeflags & FILE_TYPE_FTFONT) { - UI_ThemeColor(TH_TEXT); - } - else { - glColor4f(1.0, 1.0, 1.0, 1.0); + UI_GetThemeColor4fv(TH_TEXT, col); } - glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale); + + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTexScaled(&state, (float)xco, (float)yco, imb->x, imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, + scale, scale, 1.0f, 1.0f, col); if (icon) { UI_icon_draw_aspect((float)xco, (float)yco, icon, icon_aspect, 1.0f); @@ -394,8 +399,13 @@ static void file_draw_preview( /* border */ if (use_dropshadow) { - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); - fdrawbox((float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey)); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); + imm_draw_box_wire_2d(pos, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey)); + immUnbindProgram(); } but = uiDefBut(block, UI_BTYPE_LABEL, 0, "", xco, yco, ex, ey, NULL, 0.0, 0.0, 0, 0, NULL); @@ -451,49 +461,70 @@ static void draw_background(FileLayout *layout, View2D *v2d) int i; int sy; - UI_ThemeColorShade(TH_BACK, -7); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColorShade(TH_BACK, -7); /* alternating flat shade background */ for (i = 0; (i <= layout->rows); i += 2) { sy = (int)v2d->cur.ymax - i * (layout->tile_h + 2 * layout->tile_border_y) - layout->tile_border_y; - glRectf(v2d->cur.xmin, (float)sy, v2d->cur.xmax, (float)(sy + layout->tile_h + 2 * layout->tile_border_y)); - + immRectf(pos, v2d->cur.xmin, (float)sy, v2d->cur.xmax, (float)(sy + layout->tile_h + 2 * layout->tile_border_y)); } + + immUnbindProgram(); } static void draw_dividers(FileLayout *layout, View2D *v2d) { + /* vertical column dividers */ + const int step = (layout->tile_w + 2 * layout->tile_border_x); - int v1[2], v2[2]; - int sx; - unsigned char col_hi[3], col_lo[3]; - UI_GetThemeColorShade3ubv(TH_BACK, 30, col_hi); - UI_GetThemeColorShade3ubv(TH_BACK, -30, col_lo); + unsigned int vertex_ct = 0; + int sx = (int)v2d->tot.xmin; + while (sx < v2d->cur.xmax) { + sx += step; + vertex_ct += 4; /* vertex_count = 2 points per line * 2 lines per divider */ + } - v1[1] = v2d->cur.ymax - layout->tile_border_y; - v2[1] = v2d->cur.ymin; + if (vertex_ct > 0) { + int v1[2], v2[2]; + unsigned char col_hi[3], col_lo[3]; - glBegin(GL_LINES); + UI_GetThemeColorShade3ubv(TH_BACK, 30, col_hi); + UI_GetThemeColorShade3ubv(TH_BACK, -30, col_lo); - /* vertical column dividers */ - sx = (int)v2d->tot.xmin; - while (sx < v2d->cur.xmax) { - sx += step; + v1[1] = v2d->cur.ymax - layout->tile_border_y; + v2[1] = v2d->cur.ymin; - glColor3ubv(col_lo); - v1[0] = v2[0] = sx; - glVertex2iv(v1); - glVertex2iv(v2); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); - glColor3ubv(col_hi); - v1[0] = v2[0] = sx + 1; - glVertex2iv(v1); - glVertex2iv(v2); - } + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBegin(GWN_PRIM_LINES, vertex_ct); + + sx = (int)v2d->tot.xmin; + while (sx < v2d->cur.xmax) { + sx += step; + + v1[0] = v2[0] = sx; + immSkipAttrib(color); + immVertex2iv(pos, v1); + immAttrib3ubv(color, col_lo); + immVertex2iv(pos, v2); - glEnd(); + v1[0] = v2[0] = sx + 1; + immSkipAttrib(color); + immVertex2iv(pos, v1); + immAttrib3ubv(color, col_hi); + immVertex2iv(pos, v2); + } + + immEnd(); + immUnbindProgram(); + } } void file_draw_list(const bContext *C, ARegion *ar) @@ -517,6 +548,7 @@ void file_draw_list(const bContext *C, ARegion *ar) short align; bool do_drag; int column_space = 0.6f * UI_UNIT_X; + unsigned char text_col[4]; const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size); const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size); const float thumb_icon_aspect = sqrtf(64.0f / (float)(params->thumbnail_size)); @@ -587,9 +619,6 @@ void file_draw_list(const bContext *C, ARegion *ar) BLI_join_dirfile(path, sizeof(path), root, file->relpath); - UI_ThemeColor4(TH_TEXT); - - if (!(file_selflag & FILE_SEL_EDITING)) { if ((params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) || (file_selflag & FILE_SEL_SELECTED)) @@ -625,7 +654,7 @@ void file_draw_list(const bContext *C, ARegion *ar) sx += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X; } - UI_ThemeColor4(TH_TEXT); + UI_GetThemeColor4ubv(TH_TEXT, text_col); if (file_selflag & FILE_SEL_EDITING) { uiBut *but; @@ -656,7 +685,7 @@ void file_draw_list(const bContext *C, ARegion *ar) if (!(file_selflag& FILE_SEL_EDITING)) { int tpos = (FILE_IMGDISPLAY == params->display) ? sy - layout->tile_h + layout->textheight : sy; - file_draw_string(sx + 1, tpos, file->name, (float)textwidth, textheight, align); + file_draw_string(sx + 1, tpos, file->name, (float)textwidth, textheight, align, text_col); } sx += (int)layout->column_widths[COLUMN_NAME] + column_space; @@ -668,7 +697,8 @@ void file_draw_list(const bContext *C, ARegion *ar) BLI_filelist_entry_size_to_string(NULL, file->entry->size, small_size, file->entry->size_str); } file_draw_string( - sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h, align); + sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h, + align, text_col); } sx += (int)layout->column_widths[COLUMN_SIZE] + column_space; } @@ -679,10 +709,12 @@ void file_draw_list(const bContext *C, ARegion *ar) NULL, file->entry->time, small_size, file->entry->time_str, file->entry->date_str); } file_draw_string( - sx, sy, file->entry->date_str, layout->column_widths[COLUMN_DATE], layout->tile_h, align); + sx, sy, file->entry->date_str, layout->column_widths[COLUMN_DATE], layout->tile_h, + align, text_col); sx += (int)layout->column_widths[COLUMN_DATE] + column_space; file_draw_string( - sx, sy, file->entry->time_str, layout->column_widths[COLUMN_TIME], layout->tile_h, align); + sx, sy, file->entry->time_str, layout->column_widths[COLUMN_TIME], layout->tile_h, + align, text_col); sx += (int)layout->column_widths[COLUMN_TIME] + column_space; } else { @@ -697,7 +729,8 @@ void file_draw_list(const bContext *C, ARegion *ar) BLI_filelist_entry_size_to_string(NULL, file->entry->size, small_size, file->entry->size_str); } file_draw_string( - sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h, align); + sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h, + align, text_col); } sx += (int)layout->column_widths[COLUMN_SIZE] + column_space; } diff --git a/source/blender/editors/space_file/file_utils.c b/source/blender/editors/space_file/file_utils.c index c1caf5ae8ac..fc870399696 100644 --- a/source/blender/editors/space_file/file_utils.c +++ b/source/blender/editors/space_file/file_utils.c @@ -26,6 +26,7 @@ #include "BLI_rect.h" #include "BLI_fileops.h" +#include "BLI_listbase.h" #include "BLO_readfile.h" diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 7abe5ff5070..3dfeb5eb5b3 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -215,7 +215,8 @@ short ED_fileselect_set_params(SpaceFile *sfile) FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS | FILTER_ID_LT | FILTER_ID_MA | FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO | - FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF; + FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS | + FILTER_ID_LP; if (U.uiflag & USER_HIDE_DOT) { params->flag |= FILE_HIDE_DOT; @@ -228,7 +229,7 @@ short ED_fileselect_set_params(SpaceFile *sfile) if (params->type == FILE_LOADLIB) { params->flag |= RNA_boolean_get(op->ptr, "link") ? FILE_LINK : 0; params->flag |= RNA_boolean_get(op->ptr, "autoselect") ? FILE_AUTOSELECT : 0; - params->flag |= RNA_boolean_get(op->ptr, "active_layer") ? FILE_ACTIVELAY : 0; + params->flag |= RNA_boolean_get(op->ptr, "active_collection") ? FILE_ACTIVE_COLLECTION : 0; } if ((prop = RNA_struct_find_property(op->ptr, "display_type"))) { diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 287b98fa589..780c2ec5a47 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -292,7 +292,8 @@ static void file_refresh(const bContext *C, ScrArea *sa) } } -static void file_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) +static void file_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { SpaceFile *sfile = (SpaceFile *)sa->spacedata.first; @@ -334,7 +335,9 @@ static void file_main_region_init(wmWindowManager *wm, ARegion *ar) WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } -static void file_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void file_main_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -598,7 +601,9 @@ static void file_tools_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, NULL, -1, true); } -static void file_tools_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn)) +static void file_tools_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), + wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene)) { #if 0 /* context changes */ @@ -660,7 +665,9 @@ static void file_ui_region_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); } -static void file_ui_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void file_ui_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { diff --git a/source/blender/editors/space_graph/CMakeLists.txt b/source/blender/editors/space_graph/CMakeLists.txt index 40a196fa95b..2840324e65e 100644 --- a/source/blender/editors/space_graph/CMakeLists.txt +++ b/source/blender/editors/space_graph/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../gpu ../../makesdna ../../makesrna @@ -48,7 +49,7 @@ set(SRC ) if(WITH_AUDASPACE) - add_definitions(${AUDASPACE_DEFINITIONS}) + add_definitions(-DWITH_AUDASPACE) list(APPEND INC_SYS ${AUDASPACE_C_INCLUDE_DIRS} diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index df6bd01144d..49f498b3419 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -48,13 +48,13 @@ #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_main.h" #include "BKE_global.h" #include "BKE_screen.h" #include "BKE_unit.h" +#include "DEG_depsgraph_build.h" #include "WM_api.h" #include "WM_types.h" @@ -481,7 +481,7 @@ static void do_graph_region_driver_buttons(bContext *C, void *UNUSED(arg), int e case B_IPO_DEPCHANGE: { /* rebuild depsgraph for the new deps */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); break; } } diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index 96a078b2817..d917e3b85a2 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -46,10 +46,12 @@ #include "BKE_curve.h" #include "BKE_fcurve.h" - -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_draw.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" + #include "ED_anim_api.h" #include "graph_intern.h" @@ -82,38 +84,59 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d) FCM_EnvelopeData *fed; const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur); int i; - + + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + glLineWidth(1.0f); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 0); /* Simple dashes. */ + immUniformColor3f(0.0f, 0.0f, 0.0f); + immUniform1f("dash_width", 10.0f); + immUniform1f("dash_factor", 0.5f); + /* draw two black lines showing the standard reference levels */ - glColor3f(0.0f, 0.0f, 0.0f); - glLineWidth(1); - setlinestyle(5); - - glBegin(GL_LINES); - glVertex2f(v2d->cur.xmin, env->midval + env->min); - glVertex2f(v2d->cur.xmax, env->midval + env->min); - - glVertex2f(v2d->cur.xmin, env->midval + env->max); - glVertex2f(v2d->cur.xmax, env->midval + env->max); - glEnd(); - setlinestyle(0); - - /* set size of vertices (non-adjustable for now) */ - glPointSize(2.0f); - - /* for now, point color is fixed, and is white */ - glColor3f(1.0f, 1.0f, 1.0f); - - glBegin(GL_POINTS); - for (i = 0, fed = env->data; i < env->totvert; i++, fed++) { - /* only draw if visible - * - min/max here are fixed, not relative - */ - if (IN_RANGE(fed->time, (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) { - glVertex2f(fed->time, fed->min); - glVertex2f(fed->time, fed->max); + + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->min); + immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->min); + + immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->max); + immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->max); + immEnd(); + + immUnbindProgram(); + + if (env->totvert > 0) { + /* set size of vertices (non-adjustable for now) */ + glPointSize(2.0f); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* for now, point color is fixed, and is white */ + immUniformColor3f(1.0f, 1.0f, 1.0f); + + immBeginAtMost(GWN_PRIM_POINTS, env->totvert * 2); + + for (i = 0, fed = env->data; i < env->totvert; i++, fed++) { + /* only draw if visible + * - min/max here are fixed, not relative + */ + if (IN_RANGE(fed->time, (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) { + immVertex2f(shdr_pos, fed->time, fed->min); + immVertex2f(shdr_pos, fed->time, fed->max); + } } + + immEnd(); + + immUnbindProgram(); } - glEnd(); } /* *************************** */ @@ -121,16 +144,37 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d) /* Points ---------------- */ -/* helper func - draw keyframe vertices only for an F-Curve */ -static void draw_fcurve_vertices_keyframes(FCurve *fcu, SpaceIpo *UNUSED(sipo), View2D *v2d, short edit, short sel) +/* helper func - set color to draw F-Curve data with */ +static void set_fcurve_vertex_color(FCurve *fcu, bool sel) +{ + /* Fade the 'intensity' of the vertices based on the selection of the curves too */ + int alphaOffset = (int)((fcurve_display_alpha(fcu) - 1.0f) * 255); + + float color[4]; + + /* Set color of curve vertex based on state of curve (i.e. 'Edit' Mode) */ + if ((fcu->flag & FCURVE_PROTECTED) == 0) { + /* Curve's points ARE BEING edited */ + UI_GetThemeColorShadeAlpha4fv(sel ? TH_VERTEX_SELECT : TH_VERTEX, 0, alphaOffset, color); + } + else { + /* Curve's points CANNOT BE edited */ + UI_GetThemeColorShadeAlpha4fv(sel ? TH_TEXT_HI : TH_TEXT, 0, alphaOffset, color); + } + + immUniformColor4fv(color); +} + +static void draw_fcurve_selected_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, bool sel, unsigned pos) { - BezTriple *bezt = fcu->bezt; const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur); - int i; - - glBegin(GL_POINTS); - - for (i = 0; i < fcu->totvert; i++, bezt++) { + + set_fcurve_vertex_color(fcu, sel); + + immBeginAtMost(GWN_PRIM_POINTS, fcu->totvert); + + BezTriple *bezt = fcu->bezt; + for (int i = 0; i < fcu->totvert; i++, bezt++) { /* as an optimization step, only draw those in view * - we apply a correction factor to ensure that points don't pop in/out due to slight twitches of view size */ @@ -141,80 +185,50 @@ static void draw_fcurve_vertices_keyframes(FCurve *fcu, SpaceIpo *UNUSED(sipo), * - */ if ((bezt->f2 & SELECT) == sel) - glVertex3fv(bezt->vec[1]); + immVertex2fv(pos, bezt->vec[1]); } else { /* no check for selection here, as curve is not editable... */ /* XXX perhaps we don't want to even draw points? maybe add an option for that later */ - glVertex3fv(bezt->vec[1]); + immVertex2fv(pos, bezt->vec[1]); } } } - - glEnd(); -} + immEnd(); +} -/* helper func - draw handle vertex for an F-Curve as a round unfilled circle - * NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise, the controls don't - * have a consistent appearance (due to off-pixel alignments)... - */ -static void draw_fcurve_handle_control(float x, float y, float xscale, float yscale, float hsize) +/* helper func - draw keyframe vertices only for an F-Curve */ +static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, unsigned pos) { - static GLuint displist = 0; - - /* initialize round circle shape */ - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - gluDisk(qobj, 0, 0.7, 8, 1); - gluDeleteQuadric(qobj); - - glEndList(); - } - - /* adjust view transform before starting */ - glTranslatef(x, y, 0.0f); - glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f); - - /* draw! */ - glCallList(displist); - - /* restore view transform */ - glScalef(xscale / hsize, yscale / hsize, 1.0); - glTranslatef(-x, -y, 0.0f); + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + + immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize); + + draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, false, pos); + draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, true, pos); + + immUnbindProgram(); } + /* helper func - draw handle vertices only for an F-Curve (if it is not protected) */ -static void draw_fcurve_vertices_handles(FCurve *fcu, SpaceIpo *sipo, View2D *v2d, short sel, short sel_handle_only, float units_scale) +static void draw_fcurve_selected_handle_vertices(FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, unsigned pos) { - BezTriple *bezt = fcu->bezt; - BezTriple *prevbezt = NULL; - float hsize, xscale, yscale; - int i; - - /* get view settings */ - hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize; - UI_view2d_scale_get(v2d, &xscale, &yscale); + (void) v2d; /* TODO: use this to draw only points in view */ - /* Compensate OGL scale sued for unit mapping, so circle will be circle, not ellipse */ - yscale *= units_scale; - /* set handle color */ - if (sel) UI_ThemeColor(TH_HANDLE_VERTEX_SELECT); - else UI_ThemeColor(TH_HANDLE_VERTEX); - - /* anti-aliased lines for more consistent appearance */ - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH); - glEnable(GL_BLEND); - - for (i = 0; i < fcu->totvert; i++, prevbezt = bezt, bezt++) { - /* Draw the editmode handles for a bezier curve (others don't have handles) + float hcolor[3]; + UI_GetThemeColor3fv(sel ? TH_HANDLE_VERTEX_SELECT : TH_HANDLE_VERTEX, hcolor); + immUniform4f("outlineColor", hcolor[0], hcolor[1], hcolor[2], 1.0f); + immUniformColor3fvAlpha(hcolor, 0.01f); /* almost invisible - only keep for smoothness */ + + immBeginAtMost(GWN_PRIM_POINTS, fcu->totvert * 2); + + BezTriple *bezt = fcu->bezt; + BezTriple *prevbezt = NULL; + for (int i = 0; i < fcu->totvert; i++, prevbezt = bezt, bezt++) { + /* Draw the editmode handles for a bezier curve (others don't have handles) * if their selection status matches the selection status we're drawing for * - first handle only if previous beztriple was bezier-mode * - second handle only if current beztriple is bezier-mode @@ -225,68 +239,61 @@ static void draw_fcurve_vertices_handles(FCurve *fcu, SpaceIpo *sipo, View2D *v2 if (!sel_handle_only || BEZT_ISSEL_ANY(bezt)) { if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) { if ((bezt->f1 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax)*/ - draw_fcurve_handle_control(bezt->vec[0][0], bezt->vec[0][1], xscale, yscale, hsize); + immVertex2fv(pos, bezt->vec[0]); } - + if (bezt->ipo == BEZT_IPO_BEZ) { if ((bezt->f3 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax)*/ - draw_fcurve_handle_control(bezt->vec[2][0], bezt->vec[2][1], xscale, yscale, hsize); + immVertex2fv(pos, bezt->vec[2]); } } } - - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); + + immEnd(); } -/* helper func - set color to draw F-Curve data with */ -static void set_fcurve_vertex_color(FCurve *fcu, short sel) +/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */ +static void draw_fcurve_handle_vertices(FCurve *fcu, View2D *v2d, bool sel_handle_only, unsigned pos) { - /* Fade the 'intensity' of the vertices based on the selection of the curves too */ - int alphaOffset = (int)((fcurve_display_alpha(fcu) - 1.0f) * 255); - - /* Set color of curve vertex based on state of curve (i.e. 'Edit' Mode) */ - if ((fcu->flag & FCURVE_PROTECTED) == 0) { - /* Curve's points ARE BEING edited */ - if (sel) UI_ThemeColorShadeAlpha(TH_VERTEX_SELECT, 0, alphaOffset); - else UI_ThemeColorShadeAlpha(TH_VERTEX, 0, alphaOffset); - } - else { - /* Curve's points CANNOT BE edited */ - if (sel) UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, alphaOffset); - else UI_ThemeColorShadeAlpha(TH_TEXT, 0, alphaOffset); - } + /* smooth outlines for more consistent appearance */ + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); + + /* set handle size */ + immUniform1f("size", (1.4f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE)) * U.pixelsize); + immUniform1f("outlineWidth", 1.5f * U.pixelsize); + + draw_fcurve_selected_handle_vertices(fcu, v2d, false, sel_handle_only, pos); + draw_fcurve_selected_handle_vertices(fcu, v2d, true, sel_handle_only, pos); + + immUnbindProgram(); } -static void draw_fcurve_vertices(SpaceIpo *sipo, ARegion *ar, FCurve *fcu, short do_handles, short sel_handle_only, float units_scale) +static void draw_fcurve_vertices(ARegion *ar, FCurve *fcu, bool do_handles, bool sel_handle_only) { View2D *v2d = &ar->v2d; - + /* only draw points if curve is visible - * - draw unselected points before selected points as separate passes to minimize color-changing overhead - * (XXX dunno if this is faster than drawing all in one pass though) - * and also to make sure in the case of overlapping points that the selected is always visible + * - draw unselected points before selected points as separate passes + * to make sure in the case of overlapping points that the selected is always visible * - draw handles before keyframes, so that keyframes will overlap handles (keyframes are more important for users) */ - - glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + glEnable(GL_BLEND); + GPU_enable_program_point_size(); + /* draw the two handles first (if they're shown, the curve doesn't have just a single keyframe, and the curve is being edited) */ if (do_handles) { - set_fcurve_vertex_color(fcu, 0); - draw_fcurve_vertices_handles(fcu, sipo, v2d, 0, sel_handle_only, units_scale); - - set_fcurve_vertex_color(fcu, 1); - draw_fcurve_vertices_handles(fcu, sipo, v2d, 1, sel_handle_only, units_scale); + draw_fcurve_handle_vertices(fcu, v2d, sel_handle_only, pos); } - + /* draw keyframes over the handles */ - set_fcurve_vertex_color(fcu, 0); - draw_fcurve_vertices_keyframes(fcu, sipo, v2d, !(fcu->flag & FCURVE_PROTECTED), 0); - - set_fcurve_vertex_color(fcu, 1); - draw_fcurve_vertices_keyframes(fcu, sipo, v2d, !(fcu->flag & FCURVE_PROTECTED), 1); + draw_fcurve_keyframe_vertices(fcu, v2d, !(fcu->flag & FCURVE_PROTECTED), pos); + + GPU_disable_program_point_size(); + glDisable(GL_BLEND); } /* Handles ---------------- */ @@ -303,10 +310,10 @@ static bool draw_fcurve_handles_check(SpaceIpo *sipo, FCurve *fcu) (fcu->totvert <= 1) /* do not show handles if there is only 1 keyframe, otherwise they all clump together in an ugly ball */ ) { - return 0; + return false; } else { - return 1; + return true; } } @@ -315,13 +322,10 @@ static bool draw_fcurve_handles_check(SpaceIpo *sipo, FCurve *fcu) static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu) { int sel, b; - - /* a single call to GL_LINES here around these calls should be sufficient to still - * get separate line segments, but which aren't wrapped with GL_LINE_STRIP every time we - * want a single line - */ - glBegin(GL_LINES); - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* slightly hacky, but we want to draw unselected points before selected ones * so that selected points are clearly visible */ @@ -348,18 +352,24 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu) if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) { UI_GetThemeColor3ubv(basecol + bezt->h1, col); col[3] = fcurve_display_alpha(fcu) * 255; - glColor4ubv((GLubyte *)col); - - glVertex2fv(fp); glVertex2fv(fp + 3); + immUniformColor4ubv(col); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(pos, fp); + immVertex2fv(pos, fp + 3); + immEnd(); } /* only draw second handle if this segment is bezier */ if (bezt->ipo == BEZT_IPO_BEZ) { UI_GetThemeColor3ubv(basecol + bezt->h2, col); col[3] = fcurve_display_alpha(fcu) * 255; - glColor4ubv((GLubyte *)col); - - glVertex2fv(fp + 3); glVertex2fv(fp + 6); + immUniformColor4ubv(col); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(pos, fp + 3); + immVertex2fv(pos, fp + 6); + immEnd(); } } else { @@ -370,9 +380,12 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu) fp = bezt->vec[0]; UI_GetThemeColor3ubv(basecol + bezt->h1, col); col[3] = fcurve_display_alpha(fcu) * 255; - glColor4ubv((GLubyte *)col); - - glVertex2fv(fp); glVertex2fv(fp + 3); + immUniformColor4ubv(col); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(pos, fp); + immVertex2fv(pos, fp + 3); + immEnd(); } /* only draw second handle if this segment is bezier, and selection is ok */ @@ -382,15 +395,18 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu) fp = bezt->vec[1]; UI_GetThemeColor3ubv(basecol + bezt->h2, col); col[3] = fcurve_display_alpha(fcu) * 255; - glColor4ubv((GLubyte *)col); - - glVertex2fv(fp); glVertex2fv(fp + 3); + immUniformColor4ubv(col); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(pos, fp); + immVertex2fv(pos, fp + 3); + immEnd(); } } } } - - glEnd(); /* GL_LINES */ + + immUnbindProgram(); } /* Samples ---------------- */ @@ -399,36 +415,24 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu) * NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise, the controls don't * have a consistent appearance (due to off-pixel alignments)... */ -static void draw_fcurve_sample_control(float x, float y, float xscale, float yscale, float hsize) +static void draw_fcurve_sample_control(float x, float y, float xscale, float yscale, float hsize, unsigned int pos) { - static GLuint displist = 0; - - /* initialize X shape */ - if (displist == 0) { - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - glBegin(GL_LINES); - glVertex2f(-0.7f, -0.7f); - glVertex2f(+0.7f, +0.7f); - - glVertex2f(-0.7f, +0.7f); - glVertex2f(+0.7f, -0.7f); - glEnd(); /* GL_LINES */ - - glEndList(); - } - /* adjust view transform before starting */ - glTranslatef(x, y, 0.0f); - glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f); - - /* draw! */ - glCallList(displist); - + gpuPushMatrix(); + gpuTranslate2f(x, y); + gpuScale2f(1.0f / xscale * hsize, 1.0f / yscale * hsize); + + /* draw X shape */ + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, -0.7f, -0.7f); + immVertex2f(pos, +0.7f, +0.7f); + + immVertex2f(pos, -0.7f, +0.7f); + immVertex2f(pos, +0.7f, -0.7f); + immEnd(); + /* restore view transform */ - glScalef(xscale / hsize, yscale / hsize, 1.0); - glTranslatef(-x, -y, 0.0f); + gpuPopMatrix(); } /* helper func - draw keyframe vertices only for an F-Curve */ @@ -441,10 +445,6 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu) hsize = UI_GetThemeValuef(TH_VERTEX_SIZE); UI_view2d_scale_get(&ar->v2d, &xscale, &yscale); - /* set vertex color */ - if (fcu->flag & (FCURVE_ACTIVE | FCURVE_SELECTED)) UI_ThemeColor(TH_TEXT_HI); - else UI_ThemeColor(TH_TEXT); - /* get verts */ first = fcu->fpt; last = (first) ? (first + (fcu->totvert - 1)) : (NULL); @@ -454,10 +454,17 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu) /* anti-aliased lines for more consistent appearance */ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - - draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize); - draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize); - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColor((fcu->flag & FCURVE_SELECTED) ? TH_TEXT_HI : TH_TEXT); + + draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize, pos); + draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize, pos); + + immUnbindProgram(); + glDisable(GL_BLEND); if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH); } @@ -466,7 +473,7 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu) /* Curve ---------------- */ /* helper func - just draw the F-Curve by sampling the visible region (for drawing curves with modifiers) */ -static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, View2DGrid *grid) +static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, View2DGrid *grid, unsigned int pos) { SpaceIpo *sipo = (SpaceIpo *)ac->sl; ChannelDriver *driver; @@ -536,37 +543,50 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d * - apply the unit correction factor to the calculated values so that * the displayed values appear correctly in the viewport */ - glBegin(GL_LINE_STRIP); - + n = (etime - stime) / samplefreq + 0.5f; - for (i = 0; i <= n; i++) { - float ctime = stime + i * samplefreq; - glVertex2f(ctime, (evaluate_fcurve(fcu, ctime) + offset) * unitFac); + + if (n > 0) { + immBegin(GWN_PRIM_LINE_STRIP, (n + 1)); + + for (i = 0; i <= n; i++) { + float ctime = stime + i * samplefreq; + immVertex2f(pos, ctime, (evaluate_fcurve(fcu, ctime) + offset) * unitFac); + } + + immEnd(); } - - glEnd(); - + /* restore driver */ fcu->driver = driver; } /* helper func - draw a samples-based F-Curve */ -static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d) +static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, const uint shdr_pos) { FPoint *prevfpt = fcu->fpt; FPoint *fpt = prevfpt + 1; float fac, v[2]; - int b = fcu->totvert - 1; + int b = fcu->totvert; float unit_scale, offset; short mapping_flag = ANIM_get_normalization_flags(ac); + int count = fcu->totvert; + + if (prevfpt->vec[0] > v2d->cur.xmin) { + count++; + } + + if ((prevfpt + b - 1)->vec[0] < v2d->cur.xmax) { + count++; + } /* apply unit mapping */ - glPushMatrix(); + gpuPushMatrix(); unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); - glScalef(1.0f, unit_scale, 1.0f); - glTranslatef(0.0f, offset, 0.0f); + gpuScale2f(1.0f, unit_scale); + gpuTranslate2f(0.0f, offset); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, count); /* extrapolate to left? - left-side of view comes before first keyframe? */ if (prevfpt->vec[0] > v2d->cur.xmin) { @@ -584,26 +604,19 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]); } - glVertex2fv(v); + immVertex2fv(shdr_pos, v); } - /* if only one sample, add it now */ - if (fcu->totvert == 1) - glVertex2fv(prevfpt->vec); - /* loop over samples, drawing segments */ /* draw curve between first and last keyframe (if there are enough to do so) */ while (b--) { /* Linear interpolation: just add one point (which should add a new line segment) */ - glVertex2fv(prevfpt->vec); + immVertex2fv(shdr_pos, prevfpt->vec); /* get next pointers */ - prevfpt = fpt; - fpt++; - - /* last point? */ - if (b == 0) - glVertex2fv(prevfpt->vec); + if (b > 0) { + prevfpt++; + } } /* extrapolate to right? (see code for left-extrapolation above too) */ @@ -623,11 +636,12 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]); } - glVertex2fv(v); + immVertex2fv(shdr_pos, v); } - glEnd(); - glPopMatrix(); + immEnd(); + + gpuPopMatrix(); } /* helper func - check if the F-Curve only contains easily drawable segments @@ -648,7 +662,7 @@ static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu) } /* helper func - draw one repeat of an F-Curve (using Bezier curve approximations) */ -static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d) +static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, unsigned int pos) { BezTriple *prevbezt = fcu->bezt; BezTriple *bezt = prevbezt + 1; @@ -661,12 +675,15 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 short mapping_flag = ANIM_get_normalization_flags(ac); /* apply unit mapping */ - glPushMatrix(); + gpuPushMatrix(); unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); - glScalef(1.0f, unit_scale, 1.0f); - glTranslatef(0.0f, offset, 0.0f); + gpuScale2f(1.0f, unit_scale); + gpuTranslate2f(0.0f, offset); - glBegin(GL_LINE_STRIP); + /* For now, this assumes the worst case scenario, where all the keyframes have + * bezier interpolation, and are drawn at full res. + * This is tricky to optimize, but maybe can be improved at some point... */ + immBeginAtMost(GWN_PRIM_LINE_STRIP, (b * 32 + 3)); /* extrapolate to left? */ if (prevbezt->vec[1][0] > v2d->cur.xmin) { @@ -691,14 +708,14 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[0][1] - prevbezt->vec[1][1]); } - glVertex2fv(v1); + immVertex2fv(pos, v1); } /* if only one keyframe, add it now */ if (fcu->totvert == 1) { v1[0] = prevbezt->vec[1][0]; v1[1] = prevbezt->vec[1][1]; - glVertex2fv(v1); + immVertex2fv(pos, v1); } /* draw curve between first and last keyframe (if there are enough to do so) */ @@ -708,17 +725,17 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 /* Constant-Interpolation: draw segment between previous keyframe and next, but holding same value */ v1[0] = prevbezt->vec[1][0]; v1[1] = prevbezt->vec[1][1]; - glVertex2fv(v1); + immVertex2fv(pos, v1); v1[0] = bezt->vec[1][0]; v1[1] = prevbezt->vec[1][1]; - glVertex2fv(v1); + immVertex2fv(pos, v1); } else if (prevbezt->ipo == BEZT_IPO_LIN) { /* Linear interpolation: just add one point (which should add a new line segment) */ v1[0] = prevbezt->vec[1][0]; v1[1] = prevbezt->vec[1][1]; - glVertex2fv(v1); + immVertex2fv(pos, v1); } else if (prevbezt->ipo == BEZT_IPO_BEZ) { /* Bezier-Interpolation: draw curve as series of segments between keyframes @@ -738,7 +755,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 /* only draw one */ v1[0] = prevbezt->vec[1][0]; v1[1] = prevbezt->vec[1][1]; - glVertex2fv(v1); + immVertex2fv(pos, v1); } else { /* clamp resolution to max of 32 */ @@ -760,8 +777,9 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3); BKE_curve_forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3); - for (fp = data; resol; resol--, fp += 3) - glVertex2fv(fp); + for (fp = data; resol; resol--, fp += 3) { + immVertex2fv(pos, fp); + } } } @@ -773,7 +791,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 if (b == 0) { v1[0] = prevbezt->vec[1][0]; v1[1] = prevbezt->vec[1][1]; - glVertex2fv(v1); + immVertex2fv(pos, v1); } } @@ -800,11 +818,12 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[2][1] - prevbezt->vec[1][1]); } - glVertex2fv(v1); + immVertex2fv(pos, v1); } - glEnd(); - glPopMatrix(); + immEnd(); + + gpuPopMatrix(); } /* Debugging -------------------------------- */ @@ -825,7 +844,16 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) /* for now, only show when debugging driver... */ //if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0) // return; - + + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 0); /* Simple dashes. */ + /* No curve to modify/visualize the result? * => We still want to show the 1-1 default... */ @@ -833,26 +861,24 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) float t; /* draw with thin dotted lines in style of what curve would have been */ - glColor3fv(fcu->color); + immUniformColor3fv(fcu->color); - setlinestyle(20); + immUniform1f("dash_width", 40.0f); + immUniform1f("dash_factor", 0.5f); glLineWidth(2.0f); /* draw 1-1 line, stretching just past the screen limits * NOTE: we need to scale the y-values to be valid for the units */ - glBegin(GL_LINES); - { - t = v2d->cur.xmin; - glVertex2f(t, (t + offset) * unitfac); - - t = v2d->cur.xmax; - glVertex2f(t, (t + offset) * unitfac); - } - glEnd(); - - /* cleanup line drawing */ - setlinestyle(0); + immBegin(GWN_PRIM_LINES, 2); + + t = v2d->cur.xmin; + immVertex2f(shdr_pos, t, (t + offset) * unitfac); + + t = v2d->cur.xmax; + immVertex2f(shdr_pos, t, (t + offset) * unitfac); + + immEnd(); } /* draw driver only if actually functional */ @@ -866,53 +892,59 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) float co[2]; /* draw dotted lines leading towards this point from both axes ....... */ - glColor3f(0.9f, 0.9f, 0.9f); - setlinestyle(5); - - glBegin(GL_LINES); - { - /* x-axis lookup */ - co[0] = x; - - if (y >= v2d->cur.ymin) { - co[1] = v2d->cur.ymin - 1.0f; - glVertex2fv(co); - - co[1] = y; - glVertex2fv(co); - } - - /* y-axis lookup */ + immUniformColor3f(0.9f, 0.9f, 0.9f); + immUniform1f("dash_width", 10.0f); + immUniform1f("dash_factor", 0.5f); + + immBegin(GWN_PRIM_LINES, (y >= v2d->cur.ymin) ? 4 : 2); + + /* x-axis lookup */ + co[0] = x; + + if (y >= v2d->cur.ymin) { + co[1] = v2d->cur.ymin - 1.0f; + immVertex2fv(shdr_pos, co); + co[1] = y; - - co[0] = v2d->cur.xmin - 1.0f; - glVertex2fv(co); - - co[0] = x; - glVertex2fv(co); + immVertex2fv(shdr_pos, co); } - glEnd(); - - setlinestyle(0); + + /* y-axis lookup */ + co[1] = y; + + co[0] = v2d->cur.xmin - 1.0f; + immVertex2fv(shdr_pos, co); + + co[0] = x; + immVertex2fv(shdr_pos, co); + + immEnd(); + immUnbindProgram(); + + /* GWN_PRIM_POINTS do not survive dashed line geometry shader... */ + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* x marks the spot .................................................... */ /* -> outer frame */ - glColor3f(0.9f, 0.9f, 0.9f); + immUniformColor3f(0.9f, 0.9f, 0.9f); glPointSize(7.0); - glBegin(GL_POINTS); - glVertex2f(x, y); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex2f(shdr_pos, x, y); + immEnd(); /* inner frame */ - glColor3f(0.9f, 0.0f, 0.0f); + immUniformColor3f(0.9f, 0.0f, 0.0f); glPointSize(3.0); - glBegin(GL_POINTS); - glVertex2f(x, y); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex2f(shdr_pos, x, y); + immEnd(); } } + + immUnbindProgram(); } /* Public Curve-Drawing API ---------------- */ @@ -925,29 +957,43 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar) FCurve *fcu; /* draw with thick dotted lines */ - setlinestyle(10); glLineWidth(3.0f); /* anti-aliased lines for less jagged appearance */ - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH); + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + glEnable(GL_LINE_SMOOTH); + } glEnable(GL_BLEND); - + + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 0); /* Simple dashes. */ + immUniform1f("dash_width", 20.0f); + immUniform1f("dash_factor", 0.5f); + /* the ghost curves are simply sampled F-Curves stored in sipo->ghostCurves */ for (fcu = sipo->ghostCurves.first; fcu; fcu = fcu->next) { /* set whatever color the curve has set * - this is set by the function which creates these * - draw with a fixed opacity of 2 */ - glColor4f(fcu->color[0], fcu->color[1], fcu->color[2], 0.5f); + immUniformColor3fvAlpha(fcu->color, 0.5f); /* simply draw the stored samples */ - draw_fcurve_curve_samples(ac, NULL, fcu, &ar->v2d); + draw_fcurve_curve_samples(ac, NULL, fcu, &ar->v2d, shdr_pos); + } + + immUnbindProgram(); + + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + glDisable(GL_LINE_SMOOTH); } - - /* restore settings */ - setlinestyle(0); - - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); } @@ -975,9 +1021,10 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid AnimData *adt = ANIM_nla_mapping_get(ac, ale); /* map keyframes for drawing if scaled F-Curve */ - if (adt) - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0); - + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0); + } + /* draw curve: * - curve line may be result of one or more destructive modifiers or just the raw data, * so we need to check which method should be used @@ -986,60 +1033,82 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid */ /* 1) draw curve line */ + if (((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) || + (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert))) { /* set color/drawing style for curve itself */ + /* draw active F-Curve thicker than the rest to make it stand out */ + if (fcu->flag & FCURVE_ACTIVE) { + glLineWidth(2.5); + } + else { + glLineWidth(1.0); + } + + /* anti-aliased lines for less jagged appearance */ + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + glEnable(GL_LINE_SMOOTH); + } + glEnable(GL_BLEND); + + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 0); /* Simple dashes. */ + if (BKE_fcurve_is_protected(fcu)) { /* protected curves (non editable) are drawn with dotted lines */ - setlinestyle(2); + immUniform1f("dash_width", 4.0f); + immUniform1f("dash_factor", 0.5f); + } + else { + immUniform1f("dash_factor", 2.0f); /* solid line */ } + if (((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) || (fcu->flag & FCURVE_MUTED)) { /* muted curves are drawn in a grayish hue */ /* XXX should we have some variations? */ - UI_ThemeColorShade(TH_HEADER, 50); + immUniformThemeColorShade(TH_HEADER, 50); } else { - /* set whatever color the curve has set + /* set whatever color the curve has set * - unselected curves draw less opaque to help distinguish the selected ones */ - glColor4f(fcu->color[0], fcu->color[1], fcu->color[2], fcurve_display_alpha(fcu)); - } - - /* draw active F-Curve thicker than the rest to make it stand out */ - if (fcu->flag & FCURVE_ACTIVE) { - glLineWidth(2.0); - } - else { - glLineWidth(1.0); + immUniformColor3fvAlpha(fcu->color, fcurve_display_alpha(fcu)); } - - /* anti-aliased lines for less jagged appearance */ - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH); - glEnable(GL_BLEND); - + /* draw F-Curve */ if ((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) { /* draw a curve affected by modifiers or only allowed to have integer values * by sampling it at various small-intervals over the visible region */ - draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid); + draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid, shdr_pos); } else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) { /* just draw curve based on defined data (i.e. no modifiers) */ if (fcu->bezt) { - if (fcurve_can_use_simple_bezt_drawing(fcu)) - draw_fcurve_curve_bezts(ac, ale->id, fcu, &ar->v2d); - else - draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid); + if (fcurve_can_use_simple_bezt_drawing(fcu)) { + draw_fcurve_curve_bezts(ac, ale->id, fcu, &ar->v2d, shdr_pos); + } + else { + draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid, shdr_pos); + } } else if (fcu->fpt) { - draw_fcurve_curve_samples(ac, ale->id, fcu, &ar->v2d); + draw_fcurve_curve_samples(ac, ale->id, fcu, &ar->v2d, shdr_pos); } } - - /* restore settings */ - setlinestyle(0); - - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH); + + immUnbindProgram(); + + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + glDisable(GL_LINE_SMOOTH); + } glDisable(GL_BLEND); } @@ -1047,7 +1116,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid * - if the option to only show controls if the F-Curve is selected is enabled, we must obey this */ if (!(sipo->flag & SIPO_SELCUVERTSONLY) || (fcu->flag & FCURVE_SELECTED)) { - if (fcurve_are_keyframes_usable(fcu) == 0) { + if (!fcurve_are_keyframes_usable(fcu) && !(fcu->fpt && fcu->totvert)) { /* only draw controls if this is the active modifier */ if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) { switch (fcm->type) { @@ -1063,9 +1132,9 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); /* apply unit-scaling to all values via OpenGL */ - glPushMatrix(); - glScalef(1.0f, unit_scale, 1.0f); - glTranslatef(0.0f, offset, 0.0f); + gpuPushMatrix(); + gpuScale2f(1.0f, unit_scale); + gpuTranslate2f(0.0f, offset); /* set this once and for all - all handles and handle-verts should use the same thickness */ glLineWidth(1.0); @@ -1080,14 +1149,14 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid glDisable(GL_BLEND); } - draw_fcurve_vertices(sipo, ar, fcu, do_handles, (sipo->flag & SIPO_SELVHANDLESONLY), unit_scale); + draw_fcurve_vertices(ar, fcu, do_handles, (sipo->flag & SIPO_SELVHANDLESONLY)); } else { /* samples: only draw two indicators at either end as indicators */ draw_fcurve_samples(sipo, ar, fcu); } - glPopMatrix(); + gpuPopMatrix(); } } diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 839fce48b1c..2876fccaa51 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -36,7 +36,7 @@ #include <float.h> #ifdef WITH_AUDASPACE -# include AUD_SPECIAL_H +# include <AUD_Special.h> #endif #include "MEM_guardedalloc.h" @@ -54,13 +54,14 @@ #include "BLT_translation.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_nla.h" #include "BKE_context.h" #include "BKE_report.h" +#include "DEG_depsgraph_build.h" + #include "UI_view2d.h" #include "ED_anim_api.h" @@ -2714,7 +2715,7 @@ static int graph_driver_vars_paste_exec(bContext *C, wmOperator *op) /* successful or not? */ if (ok) { /* rebuild depsgraph, now that there are extra deps here */ - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); /* set notifier that keyframes have changed */ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, CTX_data_scene(C)); diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index f12db310856..4b89c8db9e6 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -53,7 +53,7 @@ #include "ED_anim_api.h" #include "ED_markers.h" -#include "BIF_gl.h" +#include "GPU_immediate.h" #include "WM_api.h" #include "WM_types.h" @@ -265,43 +265,52 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) /* only free grid after drawing data, as we need to use it to determine sampling rate */ UI_view2d_grid_free(grid); - - /* horizontal component of value-cursor (value line before the current frame line) */ - if ((sipo->flag & SIPO_NODRAWCURSOR) == 0) { - float y = sipo->cursorVal; - - /* Draw a green line to indicate the cursor value */ - UI_ThemeColorShadeAlpha(TH_CFRAME, -10, -50); - glEnable(GL_BLEND); - glLineWidth(2.0); + if (((sipo->flag & SIPO_NODRAWCURSOR) == 0) || (sipo->mode == SIPO_MODE_DRIVERS)) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - glBegin(GL_LINES); - glVertex2f(v2d->cur.xmin, y); - glVertex2f(v2d->cur.xmax, y); - glEnd(); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - glDisable(GL_BLEND); - } - - /* current frame or vertical component of vertical component of the cursor */ - if (sipo->mode == SIPO_MODE_DRIVERS) { - /* cursor x-value */ - float x = sipo->cursorTime; - - /* to help differentiate this from the current frame, draw slightly darker like the horizontal one */ - UI_ThemeColorShadeAlpha(TH_CFRAME, -40, -50); - glEnable(GL_BLEND); - glLineWidth(2.0); - - glBegin(GL_LINES); - glVertex2f(x, v2d->cur.ymin); - glVertex2f(x, v2d->cur.ymax); - glEnd(); + /* horizontal component of value-cursor (value line before the current frame line) */ + if ((sipo->flag & SIPO_NODRAWCURSOR) == 0) { + + float y = sipo->cursorVal; + + /* Draw a green line to indicate the cursor value */ + immUniformThemeColorShadeAlpha(TH_CFRAME, -10, -50); + glEnable(GL_BLEND); + glLineWidth(2.0); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, v2d->cur.xmin, y); + immVertex2f(pos, v2d->cur.xmax, y); + immEnd(); + + glDisable(GL_BLEND); + } + + /* current frame or vertical component of vertical component of the cursor */ + if (sipo->mode == SIPO_MODE_DRIVERS) { + /* cursor x-value */ + float x = sipo->cursorTime; + + /* to help differentiate this from the current frame, draw slightly darker like the horizontal one */ + immUniformThemeColorShadeAlpha(TH_CFRAME, -40, -50); + glEnable(GL_BLEND); + glLineWidth(2.0); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, x, v2d->cur.ymin); + immVertex2f(pos, x, v2d->cur.ymax); + immEnd(); + + glDisable(GL_BLEND); + } - glDisable(GL_BLEND); + immUnbindProgram(); } - else { + + if (sipo->mode != SIPO_MODE_DRIVERS) { /* current frame */ if (sipo->flag & SIPO_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS; if ((sipo->flag & SIPO_NODRAWCFRANUM) == 0) flag |= DRAWCFRA_SHOW_NUMBOX; @@ -404,7 +413,9 @@ static void graph_buttons_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, NULL, -1, true); } -static void graph_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void graph_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -450,6 +461,11 @@ static void graph_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), AReg if (wmn->action == NA_RENAME) ED_region_tag_redraw(ar); break; + case NC_SCREEN: + if (ELEM(wmn->data, ND_LAYER)) { + ED_region_tag_redraw(ar); + } + break; default: if (wmn->data == ND_KEYS) ED_region_tag_redraw(ar); @@ -459,7 +475,8 @@ static void graph_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), AReg } /* editor level listener */ -static void graph_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) +static void graph_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { SpaceIpo *sipo = (SpaceIpo *)sa->spacedata.first; diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt index c60d194b620..0bc09981ba5 100644 --- a/source/blender/editors/space_image/CMakeLists.txt +++ b/source/blender/editors/space_image/CMakeLists.txt @@ -25,6 +25,7 @@ set(INC ../../blenlib ../../blentranslation ../../bmesh + ../../depsgraph ../../imbuf ../../gpu ../../makesdna diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 8cb23c9e021..23c4fbbe45e 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -60,9 +60,12 @@ #include "BKE_image.h" #include "BKE_paint.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" + #include "BLF_api.h" #include "ED_gpencil.h" @@ -87,7 +90,6 @@ static void draw_render_info(const bContext *C, float zoomx, float zoomy) { - RenderResult *rr; Render *re = RE_GetSceneRender(scene); RenderData *rd = RE_engine_get_render_data(re); Scene *stats_scene = ED_render_job_get_scene(C); @@ -95,7 +97,7 @@ static void draw_render_info(const bContext *C, stats_scene = CTX_data_scene(C); } - rr = BKE_image_acquire_renderresult(stats_scene, ima); + RenderResult *rr = BKE_image_acquire_renderresult(stats_scene, ima); if (rr && rr->text) { float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f}; @@ -107,39 +109,41 @@ static void draw_render_info(const bContext *C, if (re) { int total_tiles; bool need_free_tiles; - rcti *tiles; - - tiles = RE_engine_get_current_tiles(re, &total_tiles, &need_free_tiles); + rcti *tiles = RE_engine_get_current_tiles(re, &total_tiles, &need_free_tiles); if (total_tiles) { - int i, x, y; - rcti *tile; - /* find window pixel coordinates of origin */ + int x, y; UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y); - glPushMatrix(); - glTranslatef(x, y, 0.0f); - glScalef(zoomx, zoomy, 1.0f); + gpuPushMatrix(); + gpuTranslate2f(x, y); + gpuScale2f(zoomx, zoomy); if (rd->mode & R_BORDER) { - glTranslatef((int)(-rd->border.xmin * rd->xsch * rd->size / 100.0f), - (int)(-rd->border.ymin * rd->ysch * rd->size / 100.0f), - 0.0f); + /* TODO: round or floor instead of casting to int */ + gpuTranslate2f((int)(-rd->border.xmin * rd->xsch * rd->size * 0.01f), + (int)(-rd->border.ymin * rd->ysch * rd->size * 0.01f)); } - UI_ThemeColor(TH_FACE_SELECT); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_FACE_SELECT); glLineWidth(1.0f); - for (i = 0, tile = tiles; i < total_tiles; i++, tile++) { - glaDrawBorderCorners(tile, zoomx, zoomy); + + rcti *tile = tiles; + for (int i = 0; i < total_tiles; i++, tile++) { + immDrawBorderCorners(pos, tile, zoomx, zoomy); } + immUnbindProgram(); + if (need_free_tiles) { MEM_freeN(tiles); } - glPopMatrix(); + gpuPopMatrix(); } } } @@ -169,28 +173,34 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* noisy, high contrast make impossible to read if lower alpha is used. */ - glColor4ub(0, 0, 0, 190); - glRecti(0.0, 0.0, BLI_rcti_size_x(&ar->winrct) + 1, UI_UNIT_Y); + immUniformColor4ub(0, 0, 0, 190); + immRecti(pos, 0, 0, BLI_rcti_size_x(&ar->winrct) + 1, UI_UNIT_Y); + + immUnbindProgram(); + glDisable(GL_BLEND); BLF_size(blf_mono_font, 11 * U.pixelsize, U.dpi); - glColor3ub(255, 255, 255); + BLF_color3ub(blf_mono_font, 255, 255, 255); BLI_snprintf(str, sizeof(str), "X:%-4d Y:%-4d |", x, y); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); if (zp) { - glColor3ub(255, 255, 255); + BLF_color3ub(blf_mono_font, 255, 255, 255); BLI_snprintf(str, sizeof(str), " Z:%-.4f |", 0.5f + 0.5f * (((float)*zp) / (float)0x7fffffff)); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); } if (zpf) { - glColor3ub(255, 255, 255); + BLF_color3ub(blf_mono_font, 255, 255, 255); BLI_snprintf(str, sizeof(str), " Z:%-.3f |", *zpf); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); @@ -204,14 +214,14 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d else if (cp != NULL) { BLI_snprintf(str, sizeof(str), " Val:%-.3f |", cp[0] / 255.0f); } - glColor3ub(255, 255, 255); + BLF_color3ub(blf_mono_font, 255, 255, 255); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); } if (channels >= 3) { - glColor3ubv(red); + BLF_color3ubv(blf_mono_font, red); if (fp) BLI_snprintf(str, sizeof(str), " R:%-.5f", fp[0]); else if (cp) @@ -222,7 +232,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); - glColor3ubv(green); + BLF_color3ubv(blf_mono_font, green); if (fp) BLI_snprintf(str, sizeof(str), " G:%-.5f", fp[1]); else if (cp) @@ -233,7 +243,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); - glColor3ubv(blue); + BLF_color3ubv(blf_mono_font, blue); if (fp) BLI_snprintf(str, sizeof(str), " B:%-.5f", fp[2]); else if (cp) @@ -245,7 +255,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d dx += BLF_width(blf_mono_font, str, sizeof(str)); if (channels == 4) { - glColor3ub(255, 255, 255); + BLF_color3ub(blf_mono_font, 255, 255, 255); if (fp) BLI_snprintf(str, sizeof(str), " A:%-.4f", fp[3]); else if (cp) @@ -267,9 +277,9 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d rgba[3] = linearcol[3]; if (use_default_view) - IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, NULL, &scene->display_settings); + IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, NULL, &scene->display_settings); else - IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, &scene->view_settings, &scene->display_settings); + IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, &scene->view_settings, &scene->display_settings); BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", rgba[0], rgba[1], rgba[2]); BLF_position(blf_mono_font, dx, dy, 0); @@ -305,9 +315,9 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d if (color_manage) { if (use_default_view) - IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings); + IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings); else - IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings); + IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings); } else { copy_v4_v4(finalcol, col); @@ -318,13 +328,18 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d BLI_rcti_init(&color_rect, dx, dx + (1.5f * UI_UNIT_X), 0.15f * UI_UNIT_Y, 0.85f * UI_UNIT_Y); + /* BLF uses immediate mode too, so we must reset our vertex format */ + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + if (channels == 4) { rcti color_rect_half; int color_quater_x, color_quater_y; color_rect_half = color_rect; color_rect_half.xmax = BLI_rcti_cent_x(&color_rect); - glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax); + /* what color ??? */ + immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax); color_rect_half = color_rect; color_rect_half.xmin = BLI_rcti_cent_x(&color_rect); @@ -332,31 +347,34 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d color_quater_x = BLI_rcti_cent_x(&color_rect_half); color_quater_y = BLI_rcti_cent_y(&color_rect_half); - glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255); - glRecti(color_rect_half.xmin, color_rect_half.ymin, color_rect_half.xmax, color_rect_half.ymax); + immUniformColor3ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK); + immRecti(pos, color_rect_half.xmin, color_rect_half.ymin, color_rect_half.xmax, color_rect_half.ymax); - glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255); - glRecti(color_quater_x, color_quater_y, color_rect_half.xmax, color_rect_half.ymax); - glRecti(color_rect_half.xmin, color_rect_half.ymin, color_quater_x, color_quater_y); + immUniformColor3ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT); + immRecti(pos, color_quater_x, color_quater_y, color_rect_half.xmax, color_rect_half.ymax); + immRecti(pos, color_rect_half.xmin, color_rect_half.ymin, color_quater_x, color_quater_y); glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(UNPACK3(finalcol), fp ? fp[3] : (cp[3] / 255.0f)); - glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax); + immUniformColor3fvAlpha(finalcol, fp ? fp[3] : (cp[3] / 255.0f)); + immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax); glDisable(GL_BLEND); } else { - glColor3fv(finalcol); - glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax); + immUniformColor3fv(finalcol); + immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax); } + immUnbindProgram(); /* draw outline */ - glColor3ub(128, 128, 128); - sdrawbox(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax); + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3ub(128, 128, 128); + imm_draw_box_wire_2d(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax); + immUnbindProgram(); dx += 1.75f * UI_UNIT_X; - glColor3ub(255, 255, 255); + BLF_color3ub(blf_mono_font, 255, 255, 255); if (channels == 1) { if (fp) { rgb_to_hsv(fp[0], fp[0], fp[0], &hue, &sat, &val); @@ -375,7 +393,6 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d BLI_snprintf(str, sizeof(str), " L:%-.4f", lum); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); - dx += BLF_width(blf_mono_font, str, sizeof(str)); } else if (channels >= 3) { rgb_to_hsv(finalcol[0], finalcol[1], finalcol[2], &hue, &sat, &val); @@ -399,70 +416,37 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d BLI_snprintf(str, sizeof(str), " L:%-.4f", lum); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); - dx += BLF_width(blf_mono_font, str, sizeof(str)); } - - (void)dx; } /* image drawing */ - -static void sima_draw_alpha_pixels(float x1, float y1, int rectx, int recty, unsigned int *recti) +static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *rect, + float zoomx, float zoomy) { - - /* swap bytes, so alpha is most significant one, then just draw it as luminance int */ - if (ENDIAN_ORDER == B_ENDIAN) - glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); + float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; - glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_UNSIGNED_INT, recti); - glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); -} + /* Slowwww */ + int *recti = MEM_mallocN(rectx * recty * sizeof(int), "temp"); + for (int a = rectx * recty - 1; a >= 0; a--) { + /* zbuffer values are signed, so we need to shift color range */ + recti[a] = rect[a] * 0.5f + 0.5f; + } -static void sima_draw_alpha_pixelsf(float x1, float y1, int rectx, int recty, float *rectf) -{ - float *trectf = MEM_mallocN(rectx * recty * 4, "temp"); - int a, b; - - for (a = rectx * recty - 1, b = 4 * a + 3; a >= 0; a--, b -= 4) - trectf[a] = rectf[b]; - - glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, trectf); - MEM_freeN(trectf); - /* ogl trick below is slower... (on ATI 9600) */ -// glColorMask(1, 0, 0, 0); -// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 3); -// glColorMask(0, 1, 0, 0); -// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 2); -// glColorMask(0, 0, 1, 0); -// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 1); -// glColorMask(1, 1, 1, 1); -} + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); + GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); -static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *recti) -{ - /* zbuffer values are signed, so we need to shift color range */ - glPixelTransferf(GL_RED_SCALE, 0.5f); - glPixelTransferf(GL_GREEN_SCALE, 0.5f); - glPixelTransferf(GL_BLUE_SCALE, 0.5f); - glPixelTransferf(GL_RED_BIAS, 0.5f); - glPixelTransferf(GL_GREEN_BIAS, 0.5f); - glPixelTransferf(GL_BLUE_BIAS, 0.5f); - - glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_INT, recti); - - glPixelTransferf(GL_RED_SCALE, 1.0f); - glPixelTransferf(GL_GREEN_SCALE, 1.0f); - glPixelTransferf(GL_BLUE_SCALE, 1.0f); - glPixelTransferf(GL_RED_BIAS, 0.0f); - glPixelTransferf(GL_GREEN_BIAS, 0.0f); - glPixelTransferf(GL_BLUE_BIAS, 0.0f); + immDrawPixelsTex(&state, x1, y1, rectx, recty, GL_RED, GL_INT, GL_NEAREST, recti, zoomx, zoomy, NULL); + + MEM_freeN(recti); } -static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rectx, int recty, float *rect_float) +static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rectx, int recty, + float *rect_float, float zoomx, float zoomy) { float bias, scale, *rectf, clipend; int a; - + float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; + if (scene->camera && scene->camera->type == OB_CAMERA) { bias = ((Camera *)scene->camera->data)->clipsta; clipend = ((Camera *)scene->camera->data)->clipend; @@ -473,8 +457,8 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec scale = 0.01f; clipend = 100.0f; } - - rectf = MEM_mallocN(rectx * recty * 4, "temp"); + + rectf = MEM_mallocN(rectx * recty * sizeof(float), "temp"); for (a = rectx * recty - 1; a >= 0; a--) { if (rect_float[a] > clipend) rectf[a] = 0.0f; @@ -485,92 +469,85 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec rectf[a] *= rectf[a]; } } - glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, rectf); - - MEM_freeN(rectf); -} -static int draw_image_channel_offset(SpaceImage *sima) -{ -#ifdef __BIG_ENDIAN__ - if (sima->flag & SI_SHOW_R) return 0; - else if (sima->flag & SI_SHOW_G) return 1; - else return 2; -#else - if (sima->flag & SI_SHOW_R) return 1; - else if (sima->flag & SI_SHOW_G) return 2; - else return 3; -#endif + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); + GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); + + immDrawPixelsTex(&state, x1, y1, rectx, recty, GL_RED, GL_FLOAT, GL_NEAREST, rectf, zoomx, zoomy, NULL); + + MEM_freeN(rectf); } static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) { int x, y; - /* set zoom */ - glPixelZoom(zoomx, zoomy); - glaDefine2DArea(&ar->winrct); /* find window pixel coordinates of origin */ UI_view2d_view_to_region(&ar->v2d, fx, fy, &x, &y); /* this part is generic image display */ - if (sima->flag & SI_SHOW_ALPHA) { - if (ibuf->rect) - sima_draw_alpha_pixels(x, y, ibuf->x, ibuf->y, ibuf->rect); - else if (ibuf->rect_float && ibuf->channels == 4) - sima_draw_alpha_pixelsf(x, y, ibuf->x, ibuf->y, ibuf->rect_float); - } - else if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) { + if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) { if (ibuf->zbuf) - sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf); + sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf, zoomx, zoomy); else if (ibuf->zbuf_float) - sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->zbuf_float); + sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->zbuf_float, zoomx, zoomy); else if (ibuf->channels == 1) - sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float); + sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float, zoomx, zoomy); } else { + int clip_max_x, clip_max_y; + UI_view2d_view_to_region(&ar->v2d, + ar->v2d.cur.xmax, ar->v2d.cur.ymax, + &clip_max_x, &clip_max_y); + if (sima->flag & SI_USE_ALPHA) { + imm_draw_box_checker_2d(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy); + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - fdrawcheckerboard(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy); } - if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B)) == 0) { - int clip_max_x, clip_max_y; - UI_view2d_view_to_region(&ar->v2d, - ar->v2d.cur.xmax, ar->v2d.cur.ymax, - &clip_max_x, &clip_max_y); + /* If RGBA display with color management */ + if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) { + glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, GL_NEAREST, - 0, 0, clip_max_x, clip_max_y); + 0, 0, clip_max_x, clip_max_y, zoomx, zoomy); } else { + float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f}; unsigned char *display_buffer; void *cache_handle; - - /* TODO(sergey): Ideally GLSL shading should be capable of either - * disabling some channels or displaying buffer with custom offset. - */ - display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); - - if (display_buffer != NULL) { - int channel_offset = draw_image_channel_offset(sima); - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, - display_buffer - (4 - channel_offset)); - } - if (cache_handle != NULL) { - IMB_display_buffer_release(cache_handle); + ColorManagedViewSettings *view_settings; + ColorManagedDisplaySettings *display_settings; + + if (sima->flag & SI_SHOW_R) + shuffle[0] = 1.0f; + else if (sima->flag & SI_SHOW_G) + shuffle[1] = 1.0f; + else if (sima->flag & SI_SHOW_B) + shuffle[2] = 1.0f; + else if (sima->flag & SI_SHOW_ALPHA) + shuffle[3] = 1.0f; + + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); + GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle); + + IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings); + display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle); + + if (display_buffer) { + immDrawPixelsTex_clipping(&state, x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer, + 0, 0, clip_max_x, clip_max_y, zoomx, zoomy, NULL); } + + IMB_display_buffer_release(cache_handle); } if (sima->flag & SI_USE_ALPHA) glDisable(GL_BLEND); } - - /* reset zoom */ - glPixelZoom(1.0f, 1.0f); } static unsigned int *get_part_from_buffer(unsigned int *buffer, int width, short startx, short starty, short endx, short endy) @@ -601,7 +578,7 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, unsigned int *rect; int dx, dy, sx, sy, x, y; void *cache_handle; - int channel_offset = -1; + float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* verify valid values, just leave this a while */ if (ima->xrep < 1) return; @@ -615,8 +592,6 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, if (!display_buffer) return; - glPixelZoom(zoomx, zoomy); - if (sima->curtile >= ima->xrep * ima->yrep) sima->curtile = ima->xrep * ima->yrep - 1; @@ -628,24 +603,34 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, rect = get_part_from_buffer((unsigned int *)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy); /* draw repeated */ - if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B)) != 0) { - channel_offset = draw_image_channel_offset(sima); + if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) != 0) { + if (sima->flag & SI_SHOW_R) + shuffle[0] = 1.0f; + else if (sima->flag & SI_SHOW_G) + shuffle[1] = 1.0f; + else if (sima->flag & SI_SHOW_B) + shuffle[2] = 1.0f; + else if (sima->flag & SI_SHOW_ALPHA) + shuffle[3] = 1.0f; } + for (sy = 0; sy + dy <= ibuf->y; sy += dy) { for (sx = 0; sx + dx <= ibuf->x; sx += dx) { UI_view2d_view_to_region(&ar->v2d, fx + (float)sx / (float)ibuf->x, fy + (float)sy / (float)ibuf->y, &x, &y); - if (channel_offset == -1) { - glaDrawPixelsSafe(x, y, dx, dy, dx, GL_RGBA, GL_UNSIGNED_BYTE, rect); + + if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) { + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, x, y, dx, dy, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect, zoomx, zoomy, NULL); } else { - glaDrawPixelsSafe(x, y, dx, dy, dx, GL_LUMINANCE, GL_UNSIGNED_INT, - (unsigned char *)rect - (4 - channel_offset)); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); + GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle); + + immDrawPixelsTex(&state, x, y, dx, dy, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect, zoomx, zoomy, NULL); } } } - glPixelZoom(1.0f, 1.0f); - IMB_display_buffer_release(cache_handle); MEM_freeN(rect); @@ -701,134 +686,62 @@ void draw_image_sample_line(SpaceImage *sima) if (sima->sample_line_hist.flag & HISTO_FLAG_SAMPLELINE) { Histogram *hist = &sima->sample_line_hist; - glBegin(GL_LINES); - glColor3ub(0, 0, 0); - glVertex2fv(hist->co[0]); - glVertex2fv(hist->co[1]); - glEnd(); - - setlinestyle(1); - glBegin(GL_LINES); - glColor3ub(255, 255, 255); - glVertex2fv(hist->co[0]); - glVertex2fv(hist->co[1]); - glEnd(); - setlinestyle(0); - - } -} - -/* XXX becomes WM paint cursor */ -#if 0 -static void draw_image_view_tool(Scene *scene) -{ - ToolSettings *settings = scene->toolsettings; - Brush *brush = settings->imapaint.brush; - int mval[2]; - float radius; - int draw = 0; - - if (brush) { - if (settings->imapaint.flag & IMAGEPAINT_DRAWING) { - if (settings->imapaint.flag & IMAGEPAINT_DRAW_TOOL_DRAWING) - draw = 1; - } - else if (settings->imapaint.flag & IMAGEPAINT_DRAW_TOOL) - draw = 1; - - if (draw) { - getmouseco_areawin(mval); - - radius = BKE_brush_size_get(brush) * G.sima->zoom; - fdrawXORcirc(mval[0], mval[1], radius); - - if (brush->innerradius != 1.0) { - radius *= brush->innerradius; - fdrawXORcirc(mval[0], mval[1], radius); - } - } - } -} -#endif - -static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int *width, int *height) -{ - Brush *brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint); - ImBuf *ibuf; - unsigned int size, alpha; - unsigned char *display_buffer; - unsigned char *rect, *cp; - void *cache_handle; - - if (!brush || !brush->clone.image) - return NULL; - - ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL); - - if (!ibuf) - return NULL; - - display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int shdr_dashed_pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - if (!display_buffer) { - BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); - IMB_display_buffer_release(cache_handle); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - return NULL; - } + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); - rect = MEM_dupallocN(display_buffer); + immUniform1i("num_colors", 2); /* Advanced dashes. */ + immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2); + immUniform1f("dash_width", 2.0f); - IMB_display_buffer_release(cache_handle); + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(shdr_dashed_pos, hist->co[0]); + immVertex2fv(shdr_dashed_pos, hist->co[1]); + immEnd(); - if (!rect) { - BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); - return NULL; + immUnbindProgram(); } - - *width = ibuf->x; - *height = ibuf->y; - - size = (*width) * (*height); - alpha = (unsigned char)255 * brush->clone.alpha; - cp = rect; - - while (size-- > 0) { - cp[3] = alpha; - cp += 4; - } - - BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); - - return rect; } static void draw_image_paint_helpers(const bContext *C, ARegion *ar, Scene *scene, float zoomx, float zoomy) { Brush *brush; - int x, y, w, h; - unsigned char *clonerect; + int x, y; + ImBuf *ibuf; brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint); - if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE)) { - /* this is not very efficient, but glDrawPixels doesn't allow - * drawing with alpha */ - clonerect = get_alpha_clone_image(C, scene, &w, &h); + if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE) && brush->clone.image) { + ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL); - if (clonerect) { + if (ibuf) { + void *cache_handle = NULL; + float col[4] = {1.0f, 1.0f, 1.0f, brush->clone.alpha}; UI_view2d_view_to_region(&ar->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y); - glPixelZoom(zoomx, zoomy); + unsigned char *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); + + if (!display_buffer) { + BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); + IMB_display_buffer_release(cache_handle); + return; + } glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, clonerect); - glDisable(GL_BLEND); - glPixelZoom(1.0, 1.0); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer, zoomx, zoomy, col); - MEM_freeN(clonerect); + glDisable(GL_BLEND); + + BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); + IMB_display_buffer_release(cache_handle); } } } @@ -924,23 +837,6 @@ void draw_image_main(const bContext *C, ARegion *ar) if (show_paint) draw_image_paint_helpers(C, ar, scene, zoomx, zoomy); - /* XXX integrate this code */ -#if 0 - if (ibuf) { - float xoffs = 0.0f, yoffs = 0.0f; - - if (image_preview_active(sa, &xim, &yim)) { - xoffs = scene->r.disprect.xmin; - yoffs = scene->r.disprect.ymin; - glColor3ub(0, 0, 0); - calc_image_view(sima, 'f'); - myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax); - glRectf(0.0f, 0.0f, 1.0f, 1.0f); - glLoadIdentity(); - } - } -#endif - if (show_viewer) { BLI_unlock_thread(LOCK_DRAW_IMAGE); } @@ -1002,8 +898,12 @@ void draw_image_cache(const bContext *C, ARegion *ar) /* Draw current frame. */ x = (cfra - sfra) / (efra - sfra + 1) * ar->winx; - UI_ThemeColor(TH_CFRAME); - glRecti(x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_CFRAME); + immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC); + immUnbindProgram(); + ED_region_cache_draw_curfra_label(cfra, x, 8.0f * UI_DPI_FAC); if (mask != NULL) { diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 8f2f6595408..e47a5427605 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -365,7 +365,7 @@ bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit) struct BMEditMesh *em = BKE_editmesh_from_object(obedit); bool ret; - ret = EDBM_mtexpoly_check(em); + ret = EDBM_uv_check(em); return ret; } @@ -374,10 +374,10 @@ bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit) } /* matches clip function */ -bool ED_space_image_check_show_maskedit(Scene *scene, SpaceImage *sima) +bool ED_space_image_check_show_maskedit(SceneLayer *sl, SpaceImage *sima) { /* check editmode - this is reserved for UV editing */ - Object *ob = OBACT; + Object *ob = OBACT(sl); if (ob && ob->mode & OB_MODE_EDIT && ED_space_image_show_uvedit(sima, ob)) { return false; } @@ -390,8 +390,8 @@ int ED_space_image_maskedit_poll(bContext *C) SpaceImage *sima = CTX_wm_space_image(C); if (sima) { - Scene *scene = CTX_data_scene(C); - return ED_space_image_check_show_maskedit(scene, sima); + SceneLayer *sl = CTX_data_scene_layer(C); + return ED_space_image_check_show_maskedit(sl, sima); } return false; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 24db8ba40fd..906bbf74a96 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -48,6 +48,7 @@ #include "BLT_translation.h" +#include "DNA_camera_types.h" #include "DNA_object_types.h" #include "DNA_node_types.h" #include "DNA_packedFile_types.h" @@ -56,7 +57,6 @@ #include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_icons.h" #include "BKE_image.h" @@ -70,6 +70,8 @@ #include "BKE_sound.h" #include "BKE_scene.h" +#include "DEG_depsgraph.h" + #include "GPU_draw.h" #include "GPU_buffers.h" @@ -792,6 +794,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) SpaceImage *sima; ARegion *ar; Scene *scene; + SceneLayer *sl; Object *obedit; Image *ima; @@ -799,6 +802,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) sima = CTX_wm_space_image(C); ar = CTX_wm_region(C); scene = CTX_data_scene(C); + sl = CTX_data_scene_layer(C); obedit = CTX_data_edit_object(C); ima = ED_space_image(sima); @@ -810,7 +814,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } } - else if (ED_space_image_check_show_maskedit(scene, sima)) { + else if (ED_space_image_check_show_maskedit(sl, sima)) { if (!ED_mask_selected_minmax(C, min, max)) { return OPERATOR_CANCELLED; } @@ -1306,21 +1310,23 @@ static int image_open_exec(bContext *C, wmOperator *op) ED_space_image_set(sima, scene, obedit, ima); iuser = &sima->iuser; } - else if (sa && sa->spacetype == SPACE_VIEW3D) { - View3D *v3d = sa->spacedata.first; - - for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { - if (bgpic->ima == ima) { - iuser = &bgpic->iuser; - break; - } - } - } else { Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data; if (tex && tex->type == TEX_IMAGE) { iuser = &tex->iuser; } + + if (iuser == NULL) { + Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; + if (cam) { + for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) { + if (bgpic->ima == ima) { + iuser = &bgpic->iuser; + break; + } + } + } + } } /* initialize because of new image */ @@ -2340,7 +2346,7 @@ static int image_reload_exec(bContext *C, wmOperator *UNUSED(op)) // XXX other users? BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_RELOAD); - DAG_id_tag_update(&ima->id, 0); + DEG_id_tag_update(&ima->id, 0); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 6ddf78290aa..fab98a14fc6 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -44,10 +44,15 @@ #include "BKE_colortools.h" #include "BKE_context.h" +#include "BKE_editmesh.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_material.h" + +#include "DEG_depsgraph.h" #include "IMB_imbuf_types.h" @@ -59,6 +64,7 @@ #include "ED_space_api.h" #include "ED_screen.h" #include "ED_uvedit.h" +#include "ED_transform.h" #include "BIF_gl.h" @@ -422,27 +428,23 @@ static void image_refresh(const bContext *C, ScrArea *sa) } else { /* old shading system, we set texface */ - MTexPoly *tf; - - if (em && EDBM_mtexpoly_check(em)) { - tf = EDBM_mtexpoly_active_get(em, NULL, sloppy, selected); + if (em && EDBM_uv_check(em)) { + BMFace *efa = BM_mesh_active_face_get(em->bm, sloppy, selected); - if (tf) { + if (efa) { /* don't need to check for pin here, see above */ - sima->image = tf->tpage; - - if ((sima->flag & SI_EDITTILE) == 0) { - sima->curtile = tf->tile; - } + Image *image = BKE_object_material_edit_image_get(obedit, efa->mat_nr); + + sima->image = image; } } } } } -static void image_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn) +static void image_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *scene, + WorkSpace *workspace) { - Scene *scene = sc->scene; SpaceImage *sima = (SpaceImage *)sa->spacedata.first; /* context changes */ @@ -535,7 +537,8 @@ static void image_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn) case ND_TRANSFORM: case ND_MODIFIER: { - Object *ob = OBACT; + SceneLayer *sl = BKE_scene_layer_from_workspace_get(scene, workspace); + Object *ob = OBACT(sl); if (ob && (ob == wmn->reference) && (ob->mode & OB_MODE_EDIT)) { if (sima->lock && (sima->flag & SI_DRAWSHADOW)) { ED_area_tag_refresh(sa); @@ -587,6 +590,27 @@ static int image_context(const bContext *C, const char *member, bContextDataResu return 0; } +static void IMAGE_WGT_manipulator2d(wmManipulatorGroupType *wgt) +{ + wgt->name = "UV Transform Manipulator"; + wgt->idname = "IMAGE_WGT_manipulator2d"; + + wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT; + + wgt->poll = ED_widgetgroup_manipulator2d_poll; + wgt->setup = ED_widgetgroup_manipulator2d_setup; + wgt->refresh = ED_widgetgroup_manipulator2d_refresh; + wgt->draw_prepare = ED_widgetgroup_manipulator2d_draw_prepare; +} + +static void image_widgets(void) +{ + wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure( + &(const struct wmManipulatorMapType_Params){SPACE_IMAGE, RGN_TYPE_WINDOW}); + + WM_manipulatorgrouptype_append_and_link(mmap_type, IMAGE_WGT_manipulator2d); +} + /************************** main region ***************************/ /* sets up the fields of the View2D from zoom and offset */ @@ -650,6 +674,16 @@ static void image_main_region_init(wmWindowManager *wm, ARegion *ar) // image space manages own v2d // UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy); + /* manipulators */ + if (ar->manipulator_map == NULL) { + const struct wmManipulatorMapType_Params wmap_params = { + .spaceid = SPACE_IMAGE, + .regionid = RGN_TYPE_WINDOW, + }; + ar->manipulator_map = WM_manipulatormap_new_from_type(&wmap_params); + } + WM_manipulatormap_add_handlers(ar, ar->manipulator_map); + /* mask polls mode */ keymap = WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); @@ -675,7 +709,6 @@ static void image_main_region_init(wmWindowManager *wm, ARegion *ar) WM_event_add_keymap_handler(&ar->handlers, keymap); keymap = WM_keymap_find(wm->defaultconf, "Image", SPACE_IMAGE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - } static void image_main_region_draw(const bContext *C, ARegion *ar) @@ -684,9 +717,11 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) SpaceImage *sima = CTX_wm_space_image(C); Object *obact = CTX_data_active_object(C); Object *obedit = CTX_data_edit_object(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); Mask *mask = NULL; bool curve = false; Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); View2D *v2d = &ar->v2d; //View2DScrollers *scrollers; float col[3]; @@ -722,7 +757,7 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); - ED_uvedit_draw_main(sima, ar, scene, obedit, obact); + ED_uvedit_draw_main(sima, ar, scene, sl, obedit, obact, depsgraph); /* check for mask (delay draw) */ if (ED_space_image_show_uvedit(sima, obedit)) { @@ -791,6 +826,8 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); } + WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_2D); + draw_image_cache(C, ar); /* scrollers? */ @@ -801,10 +838,16 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) #endif } -static void image_main_region_listener(bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar, wmNotifier *wmn) +static void image_main_region_listener( + bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { + case NC_GEOM: + if (ELEM(wmn->data, ND_DATA, ND_SELECT)) + WM_manipulatormap_tag_refresh(ar->manipulator_map); + break; case NC_GPENCIL: if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) ED_region_tag_redraw(ar); @@ -814,6 +857,7 @@ static void image_main_region_listener(bScreen *UNUSED(sc), ScrArea *sa, ARegion case NC_IMAGE: if (wmn->action == NA_PAINTING) ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(ar->manipulator_map); break; case NC_MATERIAL: if (wmn->data == ND_SHADING_LINKS) { @@ -823,6 +867,11 @@ static void image_main_region_listener(bScreen *UNUSED(sc), ScrArea *sa, ARegion ED_region_tag_redraw(ar); } break; + case NC_SCREEN: + if (ELEM(wmn->data, ND_LAYER)) { + ED_region_tag_redraw(ar); + } + break; } } @@ -845,7 +894,9 @@ static void image_buttons_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, NULL, -1, true); } -static void image_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void image_buttons_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -918,7 +969,9 @@ static void image_tools_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, NULL, -1, true); } -static void image_tools_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void image_tools_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -964,7 +1017,9 @@ static void image_header_region_draw(const bContext *C, ARegion *ar) ED_region_header(C, ar); } -static void image_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void image_header_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -1033,6 +1088,7 @@ void ED_spacetype_image(void) st->refresh = image_refresh; st->listener = image_listener; st->context = image_context; + st->manipulators = image_widgets; st->id_remap = image_id_remap; /* regions: main window */ diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 8dc6c4229b2..463195f74f7 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -49,6 +49,7 @@ #include "BKE_displist.h" #include "BKE_DerivedMesh.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_paint.h" #include "BKE_particle.h" #include "BKE_editmesh.h" @@ -271,7 +272,7 @@ static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats) static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats) { - if (base->flag & SELECT) stats->totobjsel++; + if (base->flag & BASE_SELECTED) stats->totobjsel++; if (ob->transflag & OB_DUPLIPARTS) { /* Dupli Particles */ @@ -300,7 +301,7 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats) } } - stats_object(ob, base->flag & SELECT, 1, stats); + stats_object(ob, base->flag & BASE_SELECTED, 1, stats); stats->totobj++; } else if (ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES))) { @@ -316,23 +317,23 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats) } stats->totobj += tot; - stats_object(ob, base->flag & SELECT, tot, stats); + stats_object(ob, base->flag & BASE_SELECTED, tot, stats); } else if (ob->transflag & OB_DUPLIFRAMES) { /* Dupli Frames */ int tot = count_duplilist(ob); stats->totobj += tot; - stats_object(ob, base->flag & SELECT, tot, stats); + stats_object(ob, base->flag & BASE_SELECTED, tot, stats); } else if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) { /* Dupli Group */ int tot = count_duplilist(ob); stats->totobj += tot; - stats_object(ob, base->flag & SELECT, tot, stats); + stats_object(ob, base->flag & BASE_SELECTED, tot, stats); } else { /* No Dupli */ - stats_object(ob, base->flag & SELECT, 1, stats); + stats_object(ob, base->flag & BASE_SELECTED, 1, stats); stats->totobj++; } } @@ -344,10 +345,10 @@ static bool stats_is_object_dynamic_topology_sculpt(Object *ob) } /* Statistics displayed in info header. Called regularly on scene changes. */ -static void stats_update(Scene *scene) +static void stats_update(Scene *scene, SceneLayer *sl) { SceneStats stats = {0}; - Object *ob = (scene->basact) ? scene->basact->object : NULL; + Object *ob = (sl->basact) ? sl->basact->object : NULL; Base *base; if (scene->obedit) { @@ -364,23 +365,25 @@ static void stats_update(Scene *scene) } else { /* Objects */ - for (base = scene->base.first; base; base = base->next) - if (scene->lay & base->lay) + for (base = sl->object_bases.first; base; base = base->next) + if (base->flag & BASE_VISIBLED) { stats_dupli_object(base, base->object, &stats); + } } - if (!scene->stats) - scene->stats = MEM_callocN(sizeof(SceneStats), "SceneStats"); + if (!sl->stats) { + sl->stats = MEM_callocN(sizeof(SceneStats), "SceneStats"); + } - *(scene->stats) = stats; + *(sl->stats) = stats; } -static void stats_string(Scene *scene) +static void stats_string(Scene *scene, SceneLayer *sl) { #define MAX_INFO_MEM_LEN 64 - SceneStats *stats = scene->stats; + SceneStats *stats = sl->stats; SceneStatsFmt stats_fmt; - Object *ob = (scene->basact) ? scene->basact->object : NULL; + Object *ob = (sl->basact) ? sl->basact->object : NULL; uintptr_t mem_in_use, mmap_in_use; char memstr[MAX_INFO_MEM_LEN]; char gpumemstr[MAX_INFO_MEM_LEN] = ""; @@ -487,19 +490,20 @@ static void stats_string(Scene *scene) #undef MAX_INFO_LEN -void ED_info_stats_clear(Scene *scene) +void ED_info_stats_clear(SceneLayer *sl) { - if (scene->stats) { - MEM_freeN(scene->stats); - scene->stats = NULL; + if (sl->stats) { + MEM_freeN(sl->stats); + sl->stats = NULL; } } -const char *ED_info_stats_string(Scene *scene) +const char *ED_info_stats_string(Scene *scene, SceneLayer *sl) { - if (!scene->stats) - stats_update(scene); - stats_string(scene); + if (!sl->stats) { + stats_update(scene, sl); + } + stats_string(scene, sl); - return scene->stats->infostr; + return sl->stats->infostr; } diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c index 21777fd8afa..4f042364c63 100644 --- a/source/blender/editors/space_info/space_info.c +++ b/source/blender/editors/space_info/space_info.c @@ -236,7 +236,9 @@ static void info_header_region_draw(const bContext *C, ARegion *ar) ED_region_header(C, ar); } -static void info_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void info_main_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { // SpaceInfo *sinfo = sa->spacedata.first; @@ -251,13 +253,16 @@ static void info_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), } } -static void info_header_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void info_header_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { case NC_SCREEN: - if (ELEM(wmn->data, ND_SCREENCAST, ND_ANIMPLAY)) + if (ELEM(wmn->data, ND_LAYER, ND_SCREENCAST, ND_ANIMPLAY)) { ED_region_tag_redraw(ar); + } break; case NC_WM: if (wmn->data == ND_JOB) diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index c801a736e31..3eb0158e7b5 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -39,6 +39,8 @@ #include "BLI_utildefines.h" #include "BLI_string_utf8.h" +#include "GPU_immediate.h" + #include "BIF_gl.h" #include "BKE_text.h" @@ -81,9 +83,15 @@ static void console_draw_sel(const char *str, const int sel[2], const int xy[2], glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4ubv(bg_sel); - glRecti(xy[0] + (cwidth * sta), xy[1] - 2 + lheight, xy[0] + (cwidth * end), xy[1] - 2); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4ubv(bg_sel); + immRecti(pos, xy[0] + (cwidth * sta), xy[1] - 2 + lheight, xy[0] + (cwidth * end), xy[1] - 2); + + immUnbindProgram(); glDisable(GL_BLEND); } @@ -182,21 +190,25 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str cdc->sel[1] = str_len - sel_orig[0]; if (bg) { - glColor3ubv(bg); - glRecti(0, cdc->xy[1], cdc->winx, (cdc->xy[1] + (cdc->lheight * tot_lines))); - } + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - glColor3ubv(fg); + immUniformColor3ubv(bg); + immRecti(pos, 0, cdc->xy[1], cdc->winx, (cdc->xy[1] + (cdc->lheight * tot_lines))); + + immUnbindProgram(); + } /* last part needs no clipping */ BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0); + BLF_color3ubv(cdc->font_id, fg); BLF_draw_mono(cdc->font_id, s, len, cdc->cwidth); if (cdc->sel[0] != cdc->sel[1]) { console_step_sel(cdc, -initial_offset); - // glColor4ub(255, 0, 0, 96); // debug + /* BLF_color3ub(cdc->font_id, 255, 0, 0); // debug */ console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel); - glColor3ubv(fg); } cdc->xy[1] += cdc->lheight; @@ -210,9 +222,8 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str if (cdc->sel[0] != cdc->sel[1]) { console_step_sel(cdc, len); - // glColor4ub(0, 255, 0, 96); // debug + /* BLF_color3ub(cdc->font_id, 0, 255, 0); // debug */ console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel); - glColor3ubv(fg); } cdc->xy[1] += cdc->lheight; @@ -230,12 +241,17 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str else { /* simple, no wrap */ if (bg) { - glColor3ubv(bg); - glRecti(0, cdc->xy[1], cdc->winx, cdc->xy[1] + cdc->lheight); - } + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - glColor3ubv(fg); + immUniformColor3ubv(bg); + immRecti(pos, 0, cdc->xy[1], cdc->winx, cdc->xy[1] + cdc->lheight); + + immUnbindProgram(); + } + BLF_color3ubv(cdc->font_id, fg); BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0); BLF_draw_mono(cdc->font_id, str, str_len, cdc->cwidth); @@ -245,7 +261,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str isel[0] = str_len - cdc->sel[1]; isel[1] = str_len - cdc->sel[0]; - // glColor4ub(255, 255, 0, 96); // debug + /* BLF_color3ub(cdc->font_id, 255, 255, 0); // debug */ console_draw_sel(str, isel, cdc->xy, str_len, cdc->cwidth, cdc->lheight, bg_sel); console_step_sel(cdc, -(str_len + 1)); } diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index 3de44174d6a..9851dcac231 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -461,13 +461,13 @@ static void set_sca_ob(Object *ob) static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisflag) { Base *base; - Main *bmain= CTX_data_main(C); - Scene *scene= CTX_data_scene(C); - Object *ob, *obt, *obact= CTX_data_active_object(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob, *obt, *obact = CTX_data_active_object(C); ID **idar; bSensor *sens; bController *cont; - unsigned int lay; int a, nr, do_it; /* we need a sorted object list */ @@ -485,19 +485,12 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf ob= ob->id.next; } - /* XXX here it checked 3d lay */ - lay= scene->lay; - - base= FIRSTBASE; - while (base) { - if (base->lay & lay) { - if (base->flag & SELECT) { - if (scavisflag & BUTS_SENS_SEL) base->object->scavisflag |= OB_VIS_SENS; - if (scavisflag & BUTS_CONT_SEL) base->object->scavisflag |= OB_VIS_CONT; - if (scavisflag & BUTS_ACT_SEL) base->object->scavisflag |= OB_VIS_ACT; - } + for (base = FIRSTBASE(sl); base; base = base->next) { + if ((base->flag & BASE_VISIBLED) && (base->flag & SELECT)) { + if (scavisflag & BUTS_SENS_SEL) base->object->scavisflag |= OB_VIS_SENS; + if (scavisflag & BUTS_CONT_SEL) base->object->scavisflag |= OB_VIS_CONT; + if (scavisflag & BUTS_ACT_SEL) base->object->scavisflag |= OB_VIS_ACT; } - base= base->next; } if (obact) { diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c index 12ca141128b..af90ef487e0 100644 --- a/source/blender/editors/space_logic/space_logic.c +++ b/source/blender/editors/space_logic/space_logic.c @@ -198,7 +198,9 @@ static void logic_refresh(const bContext *UNUSED(C), ScrArea *UNUSED(sa)) } -static void logic_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void logic_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index c261821db16..fc8c4b51635 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -45,6 +45,7 @@ #include "BKE_nla.h" #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_report.h" @@ -123,40 +124,37 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe } case ANIMTYPE_OBJECT: { - bDopeSheet *ads = (bDopeSheet *)ac->data; - Scene *sce = (Scene *)ads->source; + SceneLayer *scene_layer = ac->scene_layer; Base *base = (Base *)ale->data; Object *ob = base->object; AnimData *adt = ob->adt; - if (nlaedit_is_tweakmode_on(ac) == 0 && (ob->restrictflag & OB_RESTRICT_SELECT) == 0) { + if (nlaedit_is_tweakmode_on(ac) == 0 && (base->flag & BASE_SELECTABLED)) { /* set selection status */ if (selectmode == SELECT_INVERT) { /* swap select */ - base->flag ^= SELECT; - ob->flag = base->flag; + ED_object_base_select(base, BA_INVERT); + BKE_scene_object_base_flag_sync_from_base(base); if (adt) adt->flag ^= ADT_UI_SELECTED; } else { - Base *b; - /* deselect all */ /* TODO: should this deselect all other types of channels too? */ - for (b = sce->base.first; b; b = b->next) { - b->flag &= ~SELECT; - b->object->flag = b->flag; + for (Base *b = scene_layer->object_bases.first; b; b = b->next) { + ED_object_base_select(b, BA_DESELECT); + BKE_scene_object_base_flag_sync_from_base(b); if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE); } /* select object now */ - base->flag |= SELECT; - ob->flag |= SELECT; + ED_object_base_select(base, BA_SELECT); + BKE_scene_object_base_flag_sync_from_base(base); if (adt) adt->flag |= ADT_UI_SELECTED; } /* change active object - regardless of whether it is now selected [T37883] */ - ED_base_object_activate(C, base); /* adds notifier */ + ED_object_base_activate(C, base); /* adds notifier */ if ((adt) && (adt->flag & ADT_UI_SELECTED)) adt->flag |= ADT_UI_ACTIVE; diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 255fc0d6f8f..cb20b76a3ee 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -53,9 +53,12 @@ #include "ED_anim_api.h" #include "ED_keyframes_draw.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_draw.h" + #include "WM_types.h" #include "UI_interface.h" @@ -97,50 +100,68 @@ void nla_action_get_color(AnimData *adt, bAction *act, float color[4]) } /* draw the keyframes in the specified Action */ -static void nla_action_draw_keyframes(AnimData *adt, bAction *act, View2D *v2d, float y, float ymin, float ymax) +static void nla_action_draw_keyframes(AnimData *adt, bAction *act, float y, float ymin, float ymax) { - DLRBT_Tree keys; - ActKeyColumn *ak; - float xscale, f1, f2; - float color[4]; - /* get a list of the keyframes with NLA-scaling applied */ + DLRBT_Tree keys; BLI_dlrbTree_init(&keys); action_to_keylist(adt, act, &keys, NULL); BLI_dlrbTree_linkedlist_sync(&keys); - + if (ELEM(NULL, act, keys.first)) return; - + /* draw a darkened region behind the strips * - get and reset the background color, this time without the alpha to stand out better * (amplified alpha is used instead) */ + float color[4]; nla_action_get_color(adt, act, color); color[3] *= 2.5f; - - glColor4fv(color); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4fv(color); + /* - draw a rect from the first to the last frame (no extra overlaps for now) * that is slightly stumpier than the track background (hardcoded 2-units here) */ - f1 = ((ActKeyColumn *)keys.first)->cfra; - f2 = ((ActKeyColumn *)keys.last)->cfra; - - glRectf(f1, ymin + 2, f2, ymax - 2); - - - /* get View2D scaling factor */ - UI_view2d_scale_get(v2d, &xscale, NULL); - - /* for now, color is hardcoded to be black */ - glColor3f(0.0f, 0.0f, 0.0f); - - /* just draw each keyframe as a simple dot (regardless of the selection status) - * - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction - */ - for (ak = keys.first; ak; ak = ak->next) - draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f); - + float f1 = ((ActKeyColumn *)keys.first)->cfra; + float f2 = ((ActKeyColumn *)keys.last)->cfra; + + immRectf(pos_id, f1, ymin + 2, f2, ymax - 2); + immUnbindProgram(); + + /* count keys before drawing */ + /* Note: It's safe to cast DLRBT_Tree, as it's designed to degrade down to a ListBase */ + unsigned int key_ct = BLI_listbase_count((ListBase *)&keys); + + if (key_ct > 0) { + format = immVertexFormat(); + pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + unsigned int outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + GPU_enable_program_point_size(); + immBegin(GWN_PRIM_POINTS, key_ct); + + /* - disregard the selection status of keyframes so they draw a certain way + * - size is 6.0f which is smaller than the editable keyframes, so that there is a distinction + */ + for (ActKeyColumn *ak = keys.first; ak; ak = ak->next) { + draw_keyframe_shape(ak->cfra, y, 6.0f, false, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f, + pos_id, size_id, color_id, outline_color_id); + } + + immEnd(); + GPU_disable_program_point_size(); + immUnbindProgram(); + } + /* free icons */ BLI_dlrbTree_free(&keys); } @@ -148,57 +169,70 @@ static void nla_action_draw_keyframes(AnimData *adt, bAction *act, View2D *v2d, /* Strip Markers ------------------------ */ /* Markers inside an action strip */ -static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymaxc) +static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymaxc, int shade, const bool dashed) { - bAction *act = strip->act; - TimeMarker *marker; - - if (ELEM(NULL, strip->act, strip->act->markers.first)) + const bAction *act = strip->act; + + if (ELEM(NULL, act, act->markers.first)) return; - - for (marker = act->markers.first; marker; marker = marker->next) { + + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + if (dashed) { + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + } + else { + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + } + immUniformThemeColorShade(TH_STRIP_SELECT, shade); + + immBeginAtMost(GWN_PRIM_LINES, BLI_listbase_count(&act->markers) * 2); + for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) { if ((marker->frame > strip->actstart) && (marker->frame < strip->actend)) { float frame = nlastrip_get_frame(strip, marker->frame, NLATIME_CONVERT_MAP); - + /* just a simple line for now */ - // XXX: draw a triangle instead... - fdrawline(frame, yminc + 1, frame, ymaxc - 1); + /* XXX: draw a triangle instead... */ + immVertex2f(shdr_pos, frame, yminc + 1); + immVertex2f(shdr_pos, frame, ymaxc - 1); } } + immEnd(); + + immUnbindProgram(); } /* Markers inside a NLA-Strip */ static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc) { - glLineWidth(2.0); + glLineWidth(2.0f); if (strip->type == NLASTRIP_TYPE_CLIP) { /* try not to be too conspicuous, while being visible enough when transforming */ - if (strip->flag & NLASTRIP_FLAG_SELECT) - UI_ThemeColorShade(TH_STRIP_SELECT, -60); - else - UI_ThemeColorShade(TH_STRIP_SELECT, -40); - - setlinestyle(3); - + int shade = (strip->flag & NLASTRIP_FLAG_SELECT) ? -60 : -40; + /* just draw the markers in this clip */ - nla_actionclip_draw_markers(strip, yminc, ymaxc); - - setlinestyle(0); + nla_actionclip_draw_markers(strip, yminc, ymaxc, shade, true); } else if (strip->flag & NLASTRIP_FLAG_TEMP_META) { /* just a solid color, so that it is very easy to spot */ - UI_ThemeColorShade(TH_STRIP_SELECT, 20); - + int shade = 20; /* draw the markers in the first level of strips only (if they are actions) */ for (NlaStrip *nls = strip->strips.first; nls; nls = nls->next) { if (nls->type == NLASTRIP_TYPE_CLIP) { - nla_actionclip_draw_markers(nls, yminc, ymaxc); + nla_actionclip_draw_markers(nls, yminc, ymaxc, shade, false); } } } - glLineWidth(1.0); + glLineWidth(1.0f); } /* Strips (Proper) ---------------------- */ @@ -266,15 +300,12 @@ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float col } /* helper call for drawing influence/time control curves for a given NLA-strip */ -static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc) +static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, unsigned int pos) { const float yheight = ymaxc - yminc; - /* drawing color is simply a light-gray */ - // TODO: is this color suitable? - // XXX nasty hacked color for now... which looks quite bad too... - glColor3f(0.7f, 0.7f, 0.7f); - + immUniformColor3f(0.7f, 0.7f, 0.7f); + /* draw with AA'd line */ glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); @@ -285,57 +316,93 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc) float cfra; /* plot the curve (over the strip's main region) */ - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, abs((int)(strip->end - strip->start) + 1)); + /* sample at 1 frame intervals, and draw * - min y-val is yminc, max is y-maxc, so clamp in those regions */ for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) { - float y = evaluate_fcurve(fcu, cfra); + float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */ CLAMP(y, 0.0f, 1.0f); - glVertex2f(cfra, ((y * yheight) + yminc)); + immVertex2f(pos, cfra, ((y * yheight) + yminc)); } - glEnd(); // GL_LINE_STRIP + + immEnd(); } else { /* use blend in/out values only if both aren't zero */ if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f)) == 0) { - glBegin(GL_LINE_STRIP); + immBeginAtMost(GWN_PRIM_LINE_STRIP, 4); + /* start of strip - if no blendin, start straight at 1, otherwise from 0 to 1 over blendin frames */ if (IS_EQF(strip->blendin, 0.0f) == 0) { - glVertex2f(strip->start, yminc); - glVertex2f(strip->start + strip->blendin, ymaxc); + immVertex2f(pos, strip->start, yminc); + immVertex2f(pos, strip->start + strip->blendin, ymaxc); } else - glVertex2f(strip->start, ymaxc); + immVertex2f(pos, strip->start, ymaxc); /* end of strip */ if (IS_EQF(strip->blendout, 0.0f) == 0) { - glVertex2f(strip->end - strip->blendout, ymaxc); - glVertex2f(strip->end, yminc); + immVertex2f(pos, strip->end - strip->blendout, ymaxc); + immVertex2f(pos, strip->end, yminc); } else - glVertex2f(strip->end, ymaxc); - glEnd(); // GL_LINE_STRIP + immVertex2f(pos, strip->end, ymaxc); + + immEnd(); } } - - /* time -------------------------- */ - // XXX do we want to draw this curve? in a different color too? - + /* turn off AA'd lines */ glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); } +/* helper call to setup dashed-lines for strip outlines */ +static uint nla_draw_use_dashed_outlines(float color[4], bool muted) +{ + /* Note that we use dashed shader here, and make it draw solid lines if not muted... */ + uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 0); /* Simple dashes. */ + immUniformColor3fv(color); + + /* line style: dotted for muted */ + if (muted) { + /* dotted - and slightly thicker for readability of the dashes */ + immUniform1f("dash_width", 5.0f); + immUniform1f("dash_factor", 0.4f); + glLineWidth(1.5f); + } + else { + /* solid line */ + immUniform1f("dash_factor", 2.0f); + glLineWidth(1.0f); + } + + return shdr_pos; +} + /* main call for drawing a single NLA-strip */ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc) { const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0); - float color[3]; + const bool muted = ((nlt->flag & NLATRACK_MUTED) || (strip->flag & NLASTRIP_FLAG_MUTED)); + float color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + uint shdr_pos; /* get color of strip */ nla_strip_get_color_inside(adt, strip, color); + shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* draw extrapolation info first (as backdrop) * - but this should only be drawn if track has some contribution */ @@ -343,7 +410,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri /* enable transparency... */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - + switch (strip->extendmode) { /* since this does both sides, only do the 'before' side, and leave the rest to the next case */ case NLASTRIP_EXTEND_HOLD: @@ -352,15 +419,10 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri */ if (strip->prev == NULL) { /* set the drawing color to the color of the strip, but with very faint alpha */ - glColor4f(color[0], color[1], color[2], 0.15f); - + immUniformColor3fvAlpha(color, 0.15f); + /* draw the rect to the edge of the screen */ - glBegin(GL_QUADS); - glVertex2f(v2d->cur.xmin, yminc); - glVertex2f(v2d->cur.xmin, ymaxc); - glVertex2f(strip->start, ymaxc); - glVertex2f(strip->start, yminc); - glEnd(); + immRectf(shdr_pos, v2d->cur.xmin, yminc, strip->start, ymaxc); } ATTR_FALLTHROUGH; @@ -369,118 +431,132 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri /* only need to try and draw if the next strip doesn't occur immediately after */ if ((strip->next == NULL) || (IS_EQF(strip->next->start, strip->end) == 0)) { /* set the drawing color to the color of the strip, but this time less faint */ - glColor4f(color[0], color[1], color[2], 0.3f); + immUniformColor3fvAlpha(color, 0.3f); /* draw the rect to the next strip or the edge of the screen */ - glBegin(GL_QUADS); - glVertex2f(strip->end, yminc); - glVertex2f(strip->end, ymaxc); - - if (strip->next) { - glVertex2f(strip->next->start, ymaxc); - glVertex2f(strip->next->start, yminc); - } - else { - glVertex2f(v2d->cur.xmax, ymaxc); - glVertex2f(v2d->cur.xmax, yminc); - } - glEnd(); + float x2 = strip->next ? strip->next->start : v2d->cur.xmax; + immRectf(shdr_pos, strip->end, yminc, x2, ymaxc); } break; } - + glDisable(GL_BLEND); } - - + + /* draw 'inside' of strip itself */ if (non_solo == 0) { + immUnbindProgram(); + /* strip is in normal track */ - glColor3fv(color); UI_draw_roundbox_corner_set(UI_CNR_ALL); /* all corners rounded */ - - UI_draw_roundbox_shade_x(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1); + UI_draw_roundbox_shade_x(true, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1, color); + + /* restore current vertex format & program (roundbox trashes it) */ + shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); } else { /* strip is in disabled track - make less visible */ - glColor4f(color[0], color[1], color[2], 0.1f); + immUniformColor3fvAlpha(color, 0.1f); glEnable(GL_BLEND); - glRectf(strip->start, yminc, strip->end, ymaxc); + immRectf(shdr_pos, strip->start, yminc, strip->end, ymaxc); glDisable(GL_BLEND); } - - + + /* draw strip's control 'curves' * - only if user hasn't hidden them... */ if ((snla->flag & SNLA_NOSTRIPCURVES) == 0) - nla_draw_strip_curves(strip, yminc, ymaxc); - - + nla_draw_strip_curves(strip, yminc, ymaxc, shdr_pos); + + immUnbindProgram(); + /* draw markings indicating locations of local markers (useful for lining up different actions) */ if ((snla->flag & SNLA_NOLOCALMARKERS) == 0) nla_strip_draw_markers(strip, yminc, ymaxc); - - /* draw strip outline + + /* draw strip outline * - color used here is to indicate active vs non-active */ if (strip->flag & NLASTRIP_FLAG_ACTIVE) { /* strip should appear 'sunken', so draw a light border around it */ - glColor3f(0.9f, 1.0f, 0.9f); // FIXME: hardcoded temp-hack colors + color[0] = 0.9f; /* FIXME: hardcoded temp-hack colors */ + color[1] = 1.0f; + color[2] = 0.9f; } else { /* strip should appear to stand out, so draw a dark border around it */ - glColor3f(0.0f, 0.0f, 0.0f); + color[0] = color[1] = color[2] = 0.0f; /* FIXME: or 1.0f ?? */ } - - /* - line style: dotted for muted */ - if ((nlt->flag & NLATRACK_MUTED) || (strip->flag & NLASTRIP_FLAG_MUTED)) - setlinestyle(4); + + /* draw outline + * - dashed-line shader is loaded after this block + */ + if (muted) { + /* muted - draw dotted, squarish outline (for simplicity) */ + shdr_pos = nla_draw_use_dashed_outlines(color, muted); + imm_draw_box_wire_2d(shdr_pos, strip->start, yminc, strip->end, ymaxc); + } + else { + /* non-muted - draw solid, rounded outline */ + UI_draw_roundbox_shade_x(false, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1, color); - /* draw outline */ - UI_draw_roundbox_shade_x(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1); - + /* restore current vertex format & program (roundbox trashes it) */ + shdr_pos = nla_draw_use_dashed_outlines(color, muted); + } + /* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */ if ((strip->type == NLASTRIP_TYPE_CLIP) && IS_EQF(strip->repeat, 1.0f) == 0) { float repeatLen = (strip->actend - strip->actstart) * strip->scale; - int i; - + /* only draw lines for whole-numbered repeats, starting from the first full-repeat * up to the last full repeat (but not if it lies on the end of the strip) */ - for (i = 1; i < strip->repeat; i++) { + immBeginAtMost(GWN_PRIM_LINES, 2 * (strip->repeat - 1)); + for (int i = 1; i < strip->repeat; i++) { float repeatPos = strip->start + (repeatLen * i); - + /* don't draw if line would end up on or after the end of the strip */ - if (repeatPos < strip->end) - fdrawline(repeatPos, yminc + 4, repeatPos, ymaxc - 4); + if (repeatPos < strip->end) { + immVertex2f(shdr_pos, repeatPos, yminc + 4); + immVertex2f(shdr_pos, repeatPos, ymaxc - 4); + } } + immEnd(); } /* or if meta-strip, draw lines delimiting extents of sub-strips (in same color as outline, if more than 1 exists) */ else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) { - NlaStrip *cs; - float y = (ymaxc - yminc) / 2.0f + yminc; - + const float y = (ymaxc - yminc) * 0.5f + yminc; + + immBeginAtMost(GWN_PRIM_LINES, 4 * BLI_listbase_count(&strip->strips)); /* up to 2 lines per strip */ + /* only draw first-level of child-strips, but don't draw any lines on the endpoints */ - for (cs = strip->strips.first; cs; cs = cs->next) { + for (NlaStrip *cs = strip->strips.first; cs; cs = cs->next) { /* draw start-line if not same as end of previous (and only if not the first strip) * - on upper half of strip */ - if ((cs->prev) && IS_EQF(cs->prev->end, cs->start) == 0) - fdrawline(cs->start, y, cs->start, ymaxc); - + if ((cs->prev) && IS_EQF(cs->prev->end, cs->start) == 0) { + immVertex2f(shdr_pos, cs->start, y); + immVertex2f(shdr_pos, cs->start, ymaxc); + } + /* draw end-line if not the last strip * - on lower half of strip */ - if (cs->next) - fdrawline(cs->end, yminc, cs->end, y); + if (cs->next) { + immVertex2f(shdr_pos, cs->end, yminc); + immVertex2f(shdr_pos, cs->end, y); + } } + + immEnd(); } - - /* reset linestyle */ - setlinestyle(0); -} + + immUnbindProgram(); +} /* add the relevant text to the cache of text-strings to draw in pixelspace */ static void nla_draw_strip_text( @@ -491,7 +567,6 @@ static void nla_draw_strip_text( char str[256]; size_t str_len; char col[4]; - rctf rect; /* just print the name and the range */ if (strip->flag & NLASTRIP_FLAG_TEMP_META) { @@ -518,12 +593,14 @@ static void nla_draw_strip_text( /* set bounding-box for text * - padding of 2 'units' on either side */ - // TODO: make this centered? - rect.xmin = xminc; - rect.ymin = yminc; - rect.xmax = xmaxc; - rect.ymax = ymaxc; - + /* TODO: make this centered? */ + rctf rect = { + .xmin = xminc, + .ymin = yminc, + .xmax = xmaxc, + .ymax = ymaxc + }; + /* add this string to the cache of texts to draw */ UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col); } @@ -537,8 +614,7 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V const char col[4] = {220, 220, 220, 255}; /* light gray */ char numstr[32]; size_t numstr_len; - - + /* Always draw times above the strip, whereas sequencer drew below + above. * However, we should be fine having everything on top, since these tend to be * quite spaced out. @@ -548,7 +624,7 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V /* start frame */ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->start); UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col); - + /* end frame */ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->end); UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, numstr_len, col); @@ -558,20 +634,14 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - View2D *v2d = &ar->v2d; - float y = 0.0f; - size_t items; - int height; const float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); const float text_margin_x = (8 * UI_DPI_FAC) * pixelx; /* build list of channels to draw */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + ListBase anim_data = {NULL, NULL}; + int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Update max-extent of channels here (taking into account scrollers): * - this is done to allow the channel list to be scrollable, but must be done here @@ -579,16 +649,17 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar) * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for * start of list offset, and the second is as a correction for the scrollers. */ - height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2)); + int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2)); + /* don't use totrect set, as the width stays the same * (NOTE: this is ok here, the configuration is pretty straightforward) */ v2d->tot.ymin = (float)(-height); /* loop through channels, and set up drawing depending on their type */ - y = (float)(-NLACHANNEL_HEIGHT(snla)); + float y = (float)(-NLACHANNEL_HEIGHT(snla)); - for (ale = anim_data.first; ale; ale = ale->next) { + for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) { const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla)); const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla)); @@ -631,45 +702,60 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar) case ANIMTYPE_NLAACTION: { AnimData *adt = ale->adt; - float color[4]; - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* just draw a semi-shaded rect spanning the width of the viewable area if there's data, * and a second darker rect within which we draw keyframe indicator dots if there's data */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - + /* get colors for drawing */ + float color[4]; nla_action_get_color(adt, ale->data, color); - glColor4fv(color); - + immUniformColor4fv(color); + /* draw slightly shifted up for greater separation from standard channels, * but also slightly shorter for some more contrast when viewing the strips */ - glRectf(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); - - /* draw keyframes in the action */ - nla_action_draw_keyframes(adt, ale->data, v2d, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP); + immRectf(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); /* draw 'embossed' lines above and below the strip for effect */ /* white base-lines */ glLineWidth(2.0f); - glColor4f(1.0f, 1.0f, 1.0f, 0.3); - fdrawline(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); - fdrawline(v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); - + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.3f); + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); + immEnd(); + /* black top-lines */ glLineWidth(1.0f); - glColor3f(0.0f, 0.0f, 0.0f); - fdrawline(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); - fdrawline(v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); - + immUniformColor3f(0.0f, 0.0f, 0.0f); + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); + immEnd(); + + /* TODO: these lines but better --^ */ + + immUnbindProgram(); + + /* draw keyframes in the action */ + nla_action_draw_keyframes(adt, ale->data, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP); + glDisable(GL_BLEND); break; } } } - + /* adjust y-position for next one */ y -= NLACHANNEL_STEP(snla); } @@ -691,7 +777,6 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar) View2D *v2d = &ar->v2d; float y = 0.0f; size_t items; - int height; /* build list of channels to draw */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); @@ -703,7 +788,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar) * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for * start of list offset, and the second is as a correction for the scrollers. */ - height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2)); + int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2)); /* don't use totrect set, as the width stays the same * (NOTE: this is ok here, the configuration is pretty straightforward) */ diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 3b5604087b9..f6068087f02 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -353,7 +353,9 @@ static void nla_buttons_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, NULL, -1, true); } -static void nla_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void nla_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -386,7 +388,9 @@ static void nla_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegio } -static void nla_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void nla_main_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -424,6 +428,11 @@ static void nla_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), A if (wmn->action == NA_RENAME) ED_region_tag_redraw(ar); break; + case NC_SCREEN: + if (ELEM(wmn->data, ND_LAYER)) { + ED_region_tag_redraw(ar); + } + break; default: if (wmn->data == ND_KEYS) ED_region_tag_redraw(ar); @@ -431,7 +440,9 @@ static void nla_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), A } } -static void nla_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void nla_channel_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -466,7 +477,8 @@ static void nla_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa) } /* editor level listener */ -static void nla_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) +static void nla_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { /* context changes */ switch (wmn->category) { diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index cde818333e4..77b1351435b 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../imbuf ../../gpu ../../makesdna @@ -47,6 +48,7 @@ set(SRC node_draw.c node_edit.c node_group.c + node_manipulators.c node_ops.c node_relationships.c node_select.c diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 8b103200862..eff8ce6665b 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -50,9 +50,12 @@ #include "BLF_api.h" #include "BLT_translation.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_draw.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -62,6 +65,7 @@ #include "WM_types.h" #include "UI_resources.h" +#include "UI_view2d.h" #include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" @@ -80,49 +84,6 @@ static void node_socket_button_label(bContext *UNUSED(C), uiLayout *layout, Poin uiItemL(layout, text, 0); } - -/* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */ - -#if 0 /* UNUSED */ -static void node_draw_socket_new(bNodeSocket *sock, float size) -{ - float x = sock->locx, y = sock->locy; - - /* 16 values of sin function */ - static float si[16] = { - 0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f, - 0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f, - -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f, - -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f - }; - /* 16 values of cos function */ - static float co[16] = { - 1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f, - -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f, - -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f, - 0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f, - }; - int a; - - glColor3ub(180, 180, 180); - - glBegin(GL_POLYGON); - for (a = 0; a < 16; a++) - glVertex2f(x + size * si[a], y + size * co[a]); - glEnd(); - - glColor4ub(0, 0, 0, 150); - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - glBegin(GL_LINE_LOOP); - for (a = 0; a < 16; a++) - glVertex2f(x + size * si[a], y + size * co[a]); - glEnd(); - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); -} -#endif - /* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */ static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -392,6 +353,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp const int font_size = data->label_size / aspect; const float margin = (float)(NODE_DY / 4); int label_height; + unsigned char color[3]; nodeLabel(ntree, node, label, sizeof(label)); @@ -400,7 +362,8 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp BLF_size(fontid, MIN2(24, font_size), U.dpi); /* clamp otherwise it can suck up a LOT of memory */ /* title color */ - UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); + UI_GetThemeColorBlendShade3ubv(TH_TEXT, color_id, 0.4f, 10, color); + BLF_color3ubv(fontid, color); width = BLF_width(fontid, label, sizeof(label)); ascender = BLF_ascender(fontid); @@ -465,7 +428,7 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode, { rctf *rct = &node->totr; int color_id = node_get_colorid(node); - unsigned char color[4]; + float color[4]; float alpha; /* skip if out of view */ @@ -475,40 +438,32 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode, return; } - UI_GetThemeColor4ubv(TH_NODE_FRAME, color); - alpha = (float)(color[3]) / 255.0f; + UI_GetThemeColor4fv(TH_NODE_FRAME, color); + alpha = color[3]; /* shadow */ node_draw_shadow(snode, node, BASIS_RAD, alpha); /* body */ - if (node->flag & NODE_CUSTOM_COLOR) - glColor4f(node->color[0], node->color[1], node->color[2], alpha); + if (node->flag & NODE_CUSTOM_COLOR) { + rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], alpha); + } else - UI_ThemeColor4(TH_NODE_FRAME); - glEnable(GL_BLEND); + UI_GetThemeColor4fv(TH_NODE_FRAME, color); + UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD); - glDisable(GL_BLEND); + UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color); /* outline active and selected emphasis */ if (node->flag & SELECT) { - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - if (node->flag & NODE_ACTIVE) - UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40); + UI_GetThemeColorShadeAlpha4fv(TH_ACTIVE, 0, -40, color); else - UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40); - UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, - rct->xmin, rct->ymin, - rct->xmax, rct->ymax, BASIS_RAD); - - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); + UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -40, color); + + UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color); } - + /* label */ node_draw_frame_label(ntree, node, snode->aspect); @@ -580,15 +535,9 @@ static void node_draw_reroute_prepare(const bContext *UNUSED(C), bNodeTree *UNUS static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode), bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key)) { - bNodeSocket *sock; char showname[128]; /* 128 used below */ rctf *rct = &node->totr; -#if 0 /* UNUSED */ - float size = NODE_REROUTE_SIZE; -#endif - float socket_size = NODE_SOCKSIZE; - /* skip if out of view */ if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax || node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax) @@ -602,23 +551,26 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED( * selection state is indicated by socket outline below! */ #if 0 + float size = NODE_REROUTE_SIZE; + /* body */ + float debug_color[4]; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_ThemeColor4(TH_NODE); - glEnable(GL_BLEND); - UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size); - glDisable(GL_BLEND); + UI_GetThemeColor4fv(TH_NODE, debug_color); + UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color); /* outline active and selected emphasis */ if (node->flag & SELECT) { glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); /* using different shades of TH_TEXT_HI for the empasis, like triangle */ - if (node->flag & NODE_ACTIVE) - UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, -40); - else - UI_ThemeColorShadeAlpha(TH_TEXT_HI, -20, -120); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size); + if (node->flag & NODE_ACTIVE) { + UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, 0, -40, debug_color); + } + else { + UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, -20, -120, debug_color); + } + UI_draw_roundbox_4fv(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); @@ -637,9 +589,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED( /* only draw input socket. as they all are placed on the same position. * highlight also if node itself is selected, since we don't display the node body separately! */ - for (sock = node->inputs.first; sock; sock = sock->next) { - node_socket_draw(C, ntree, node, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT)); - } + node_draw_sockets(&ar->v2d, C, ntree, node, false, node->flag & SELECT); UI_block_end(C, node->block); UI_block_draw(C, node->block); @@ -798,7 +748,7 @@ static void node_shader_buts_geometry(uiLayout *layout, bContext *C, PointerRNA if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); - uiItemPointerR(col, ptr, "uv_layer", &dataptr, "uv_textures", "", ICON_NONE); + uiItemPointerR(col, ptr, "uv_layer", &dataptr, "uv_layers", "", ICON_NONE); uiItemPointerR(col, ptr, "color_layer", &dataptr, "vertex_colors", "", ICON_NONE); } else { @@ -1016,7 +966,7 @@ static void node_shader_buts_uvmap(uiLayout *layout, bContext *C, PointerRNA *pt if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); - uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE); + uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE); } } } @@ -1035,7 +985,7 @@ static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRN if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); - uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE); + uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE); } else uiItemR(layout, ptr, "uv_map", 0, "", 0); @@ -1057,7 +1007,7 @@ static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA * if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); - uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE); + uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE); } else uiItemR(row, ptr, "uv_map", 0, "", 0); @@ -2218,14 +2168,21 @@ static void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNo const float cy = y + snode->zoom * backdropHeight * node->custom4; const float cross_size = 12 * U.pixelsize; - glColor3f(1.0, 1.0, 1.0); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - glBegin(GL_LINES); - glVertex2f(cx - cross_size, cy - cross_size); - glVertex2f(cx + cross_size, cy + cross_size); - glVertex2f(cx + cross_size, cy - cross_size); - glVertex2f(cx - cross_size, cy + cross_size); - glEnd(); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3f(1.0f, 1.0f, 1.0f); + + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, cx - cross_size, cy - cross_size); + immVertex2f(pos, cx + cross_size, cy + cross_size); + immVertex2f(pos, cx + cross_size, cy - cross_size); + immVertex2f(pos, cx - cross_size, cy + cross_size); + immEnd(); + + immUnbindProgram(); } } @@ -2244,9 +2201,6 @@ static void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bN float cx, cy, x1, x2, x3, x4; float y1, y2, y3, y4; - - glColor3f(1.0, 1.0, 1.0); - cx = x + snode->zoom * backdropWidth * boxmask->x; cy = y + snode->zoom * backdropHeight * boxmask->y; @@ -2259,12 +2213,21 @@ static void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bN y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom; y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom; - glBegin(GL_LINE_LOOP); - glVertex2f(x1, y1); - glVertex2f(x2, y2); - glVertex2f(x3, y3); - glVertex2f(x4, y4); - glEnd(); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3f(1.0f, 1.0f, 1.0f); + + immBegin(GWN_PRIM_LINE_LOOP, 4); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x3, y3); + immVertex2f(pos, x4, y4); + immEnd(); + + immUnbindProgram(); } static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y) @@ -2282,9 +2245,6 @@ static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop float cx, cy, x1, x2, x3, x4; float y1, y2, y3, y4; - - glColor3f(1.0, 1.0, 1.0); - cx = x + snode->zoom * backdropWidth * ellipsemask->x; cy = y + snode->zoom * backdropHeight * ellipsemask->y; @@ -2297,13 +2257,21 @@ static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom; y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom; - glBegin(GL_LINE_LOOP); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3f(1.0f, 1.0f, 1.0f); - glVertex2f(x1, y1); - glVertex2f(x2, y2); - glVertex2f(x3, y3); - glVertex2f(x4, y4); - glEnd(); + immBegin(GWN_PRIM_LINE_LOOP, 4); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x3, y3); + immVertex2f(pos, x4, y4); + immEnd(); + + immUnbindProgram(); } static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -3209,6 +3177,7 @@ void ED_init_node_socket_type_virtual(bNodeSocketType *stype) void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeInstanceKey parent_key) { bNodeInstanceKey active_viewer_key = (snode->nodetree ? snode->nodetree->active_viewer_key : NODE_INSTANCE_KEY_NONE); + float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f}; Image *ima; void *lock; ImBuf *ibuf; @@ -3223,12 +3192,10 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf) { float x, y; - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - + + gpuPushProjectionMatrix(); + gpuPushMatrix(); + /* somehow the offset has to be calculated inverse */ glaDefine2DArea(&ar->winrct); @@ -3241,60 +3208,37 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b unsigned char *display_buffer = NULL; void *cache_handle = NULL; - if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B)) { - int ofs; - - display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); - -#ifdef __BIG_ENDIAN__ - if (snode->flag & SNODE_SHOW_R) ofs = 0; - else if (snode->flag & SNODE_SHOW_G) ofs = 1; - else ofs = 2; -#else - if (snode->flag & SNODE_SHOW_R) ofs = 1; - else if (snode->flag & SNODE_SHOW_G) ofs = 2; - else ofs = 3; -#endif + if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B | SNODE_SHOW_ALPHA)) { - glPixelZoom(snode->zoom, snode->zoom); - /* swap bytes, so alpha is most significant one, then just draw it as luminance int */ - - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, - display_buffer - (4 - ofs)); - - glPixelZoom(1.0f, 1.0f); - } - else if (snode->flag & SNODE_SHOW_ALPHA) { display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); - - glPixelZoom(snode->zoom, snode->zoom); - /* swap bytes, so alpha is most significant one, then just draw it as luminance int */ -#ifdef __BIG_ENDIAN__ - glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); -#endif - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, display_buffer); - -#ifdef __BIG_ENDIAN__ - glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); -#endif - glPixelZoom(1.0f, 1.0f); + + if (snode->flag & SNODE_SHOW_R) + shuffle[0] = 1.0f; + else if (snode->flag & SNODE_SHOW_G) + shuffle[1] = 1.0f; + else if (snode->flag & SNODE_SHOW_B) + shuffle[2] = 1.0f; + else + shuffle[3] = 1.0f; + + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); + GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle); + + immDrawPixelsTex(&state, x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, + display_buffer, snode->zoom, snode->zoom, NULL); + + GPU_shader_unbind(); } else if (snode->flag & SNODE_USE_ALPHA) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glPixelZoom(snode->zoom, snode->zoom); - - glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST); - - glPixelZoom(1.0f, 1.0f); + + glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom); + glDisable(GL_BLEND); } else { - glPixelZoom(snode->zoom, snode->zoom); - - glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST); - - glPixelZoom(1.0f, 1.0f); + glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom); } if (cache_handle) @@ -3319,20 +3263,24 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b viewer_border->ymin < viewer_border->ymax) { rcti pixel_border; - UI_ThemeColor(TH_ACTIVE); BLI_rcti_init(&pixel_border, x + snode->zoom * viewer_border->xmin * ibuf->x, x + snode->zoom * viewer_border->xmax * ibuf->x, y + snode->zoom * viewer_border->ymin * ibuf->y, y + snode->zoom * viewer_border->ymax * ibuf->y); - glaDrawBorderCorners(&pixel_border, 1.0f, 1.0f); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_ACTIVE); + + immDrawBorderCorners(pos, &pixel_border, 1.0f, 1.0f); + + immUnbindProgram(); } } - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + + gpuPopProjectionMatrix(); + gpuPopMatrix(); } BKE_image_release_ibuf(ima, ibuf, lock); @@ -3444,6 +3392,7 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, float linew; float arrow[2], arrow1[2], arrow2[2]; glGetFloatv(GL_LINE_WIDTH, &linew); + unsigned int pos; /* we can reuse the dist variable here to increment the GL curve eval amount*/ dist = 1.0f / (float)LINK_RESOL; @@ -3467,141 +3416,89 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, arrow[0] = coord_array[LINK_ARROW][0]; arrow[1] = coord_array[LINK_ARROW][1]; } + + if (do_triple || drawarrow || (!do_shaded)) { + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + } + if (do_triple) { - UI_ThemeColorShadeAlpha(th_col3, -80, -120); + immUniformThemeColorShadeAlpha(th_col3, -80, -120); glLineWidth(4.0f); - - glBegin(GL_LINE_STRIP); + + immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1)); + for (i = 0; i <= LINK_RESOL; i++) { - glVertex2fv(coord_array[i]); + immVertex2fv(pos, coord_array[i]); } - glEnd(); + + immEnd(); + if (drawarrow) { - glBegin(GL_LINE_STRIP); - glVertex2fv(arrow1); - glVertex2fv(arrow); - glVertex2fv(arrow2); - glEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2fv(pos, arrow1); + immVertex2fv(pos, arrow); + immVertex2fv(pos, arrow2); + immEnd(); } } - - /* XXX using GL_LINES for shaded node lines is a workaround - * for Intel hardware, this breaks with GL_LINE_STRIP and - * changing color in begin/end blocks. - */ + glLineWidth(1.5f); - if (do_shaded) { - glBegin(GL_LINES); - for (i = 0; i < LINK_RESOL; i++) { - UI_ThemeColorBlend(th_col1, th_col2, spline_step); - glVertex2fv(coord_array[i]); - - UI_ThemeColorBlend(th_col1, th_col2, spline_step + dist); - glVertex2fv(coord_array[i + 1]); - - spline_step += dist; - } - glEnd(); + + if (drawarrow) { + immUniformThemeColorBlend(th_col1, th_col2, 0.5f); + + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2fv(pos, arrow1); + immVertex2fv(pos, arrow); + immVertex2fv(pos, arrow2); + immEnd(); } - else { - UI_ThemeColor(th_col1); - glBegin(GL_LINE_STRIP); + + if (!do_shaded) { + immUniformThemeColor(th_col1); + + immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1)); + for (i = 0; i <= LINK_RESOL; i++) { - glVertex2fv(coord_array[i]); + immVertex2fv(pos, coord_array[i]); } - glEnd(); + + immEnd(); } - - if (drawarrow) { - glBegin(GL_LINE_STRIP); - glVertex2fv(arrow1); - glVertex2fv(arrow); - glVertex2fv(arrow2); - glEnd(); + + if (do_triple || drawarrow || (!do_shaded)) { + immUnbindProgram(); } - - glDisable(GL_LINE_SMOOTH); - } -} -#if 0 /* not used in 2.5x yet */ -static void node_link_straight_points(View2D *UNUSED(v2d), SpaceNode *snode, bNodeLink *link, float coord_array[][2]) -{ - if (link->fromsock) { - coord_array[0][0] = link->fromsock->locx; - coord_array[0][1] = link->fromsock->locy; - } - else { - if (snode == NULL) return; - coord_array[0][0] = snode->mx; - coord_array[0][1] = snode->my; - } - if (link->tosock) { - coord_array[1][0] = link->tosock->locx; - coord_array[1][1] = link->tosock->locy; - } - else { - if (snode == NULL) return; - coord_array[1][0] = snode->mx; - coord_array[1][1] = snode->my; - } -} + if (do_shaded) { + unsigned char col[3]; -void node_draw_link_straight(View2D *v2d, SpaceNode *snode, bNodeLink *link, - int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3) -{ - float coord_array[2][2]; - int i; - - node_link_straight_points(v2d, snode, link, coord_array); - - glEnable(GL_LINE_SMOOTH); - - if (do_triple) { - UI_ThemeColorShadeAlpha(th_col3, -80, -120); - glLineWidth(4.0f); - - glBegin(GL_LINES); - glVertex2fv(coord_array[0]); - glVertex2fv(coord_array[1]); - glEnd(); - } - - UI_ThemeColor(th_col1); - glLineWidth(1.5f); - - /* XXX using GL_LINES for shaded node lines is a workaround - * for Intel hardware, this breaks with GL_LINE_STRIP and - * changing color in begin/end blocks. - */ - if (do_shaded) { - glBegin(GL_LINES); - for (i = 0; i < LINK_RESOL - 1; ++i) { - float t = (float)i / (float)(LINK_RESOL - 1); - UI_ThemeColorBlend(th_col1, th_col2, t); - glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0], - (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]); - - t = (float)(i + 1) / (float)(LINK_RESOL - 1); - UI_ThemeColorBlend(th_col1, th_col2, t); - glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0], - (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]); - } - glEnd(); - } - else { - glBegin(GL_LINE_STRIP); - for (i = 0; i < LINK_RESOL; ++i) { - float t = (float)i / (float)(LINK_RESOL - 1); - glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0], - (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]); + Gwn_VertFormat *format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + + immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1)); + + for (i = 0; i <= LINK_RESOL; i++) { + UI_GetThemeColorBlend3ubv(th_col1, th_col2, spline_step, col); + immAttrib3ubv(color, col); + + immVertex2fv(pos, coord_array[i]); + + spline_step += dist; + } + + immEnd(); + + immUnbindProgram(); } - glEnd(); + + glDisable(GL_LINE_SMOOTH); } - - glDisable(GL_LINE_SMOOTH); } -#endif /* note; this is used for fake links in groups too */ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) @@ -3649,27 +3546,27 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) // node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3); } -void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border) +void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos) { - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, 4); if (border & (NODE_LEFT | NODE_RIGHT)) { - glVertex2f(cent[0], v2d->cur.ymin); - glVertex2f(cent[0], v2d->cur.ymax); + immVertex2f(pos, cent[0], v2d->cur.ymin); + immVertex2f(pos, cent[0], v2d->cur.ymax); } else { - glVertex2f(cent[0], cent[1] - size); - glVertex2f(cent[0], cent[1] + size); + immVertex2f(pos, cent[0], cent[1] - size); + immVertex2f(pos, cent[0], cent[1] + size); } if (border & (NODE_TOP | NODE_BOTTOM)) { - glVertex2f(v2d->cur.xmin, cent[1]); - glVertex2f(v2d->cur.xmax, cent[1]); + immVertex2f(pos, v2d->cur.xmin, cent[1]); + immVertex2f(pos, v2d->cur.xmax, cent[1]); } else { - glVertex2f(cent[0] - size, cent[1]); - glVertex2f(cent[0] + size, cent[1]); + immVertex2f(pos, cent[0] - size, cent[1]); + immVertex2f(pos, cent[0] + size, cent[1]); } - glEnd(); + immEnd(); } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index d7119302611..231039b2e22 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -44,16 +44,21 @@ #include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_node.h" +#include "DEG_depsgraph.h" + #include "BLF_api.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_draw.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" + #include "WM_api.h" #include "WM_types.h" @@ -128,10 +133,10 @@ void ED_node_tag_update_id(ID *id) * all the users of this tree will have update * flushed from the tree, */ - DAG_id_tag_update(&ntree->id, 0); + DEG_id_tag_update(&ntree->id, 0); if (ntree->type == NTREE_SHADER) { - DAG_id_tag_update(id, 0); + DEG_id_tag_update(id, 0); if (GS(id->name) == ID_MA) WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id); @@ -144,12 +149,12 @@ void ED_node_tag_update_id(ID *id) WM_main_add_notifier(NC_SCENE | ND_NODES, id); } else if (ntree->type == NTREE_TEXTURE) { - DAG_id_tag_update(id, 0); + DEG_id_tag_update(id, 0); WM_main_add_notifier(NC_TEXTURE | ND_NODES, id); } else if (id == &ntree->id) { /* node groups */ - DAG_id_tag_update(id, 0); + DEG_id_tag_update(id, 0); } } @@ -617,103 +622,16 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) glDisable(GL_LINE_SMOOTH); } -static void node_socket_shape_draw( - float x, float y, float size, const float col[4], bool highlight, - const float coords[][2], int coords_len) -{ - int a; - - glColor4fv(col); - - glEnable(GL_BLEND); - glBegin(GL_POLYGON); - for (a = 0; a < coords_len; a++) { - glVertex2f(x + size * coords[a][0], y + size * coords[a][1]); - } - glEnd(); - glDisable(GL_BLEND); - - if (highlight) { - UI_ThemeColor(TH_TEXT_HI); - glLineWidth(1.5f); - } - else { - glColor4ub(0, 0, 0, 150); - } - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - glBegin(GL_LINE_LOOP); - for (a = 0; a < coords_len; a++) { - glVertex2f(x + size * coords[a][0], y + size * coords[a][1]); - } - glEnd(); - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); -} - - -void node_socket_draw(const bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock, float size, bool highlight) +static void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, PointerRNA node_ptr, bNodeSocket *sock, unsigned pos, unsigned col) { - PointerRNA ptr, node_ptr; + PointerRNA ptr; float color[4]; RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); - RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr); sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color); - - /* 16 values of {sin, cos} function */ - const float shape_circle[16][2] = { - {0.00000000f, 1.00000000f}, - {0.39435585f, 0.91895781f}, - {0.72479278f, 0.68896691f}, - {0.93775213f, 0.34730525f}, - {0.99871650f, -0.05064916f}, - {0.89780453f, -0.44039415f}, - {0.65137248f, -0.75875812f}, - {0.29936312f, -0.95413925f}, - {-0.10116832f, -0.99486932f}, - {-0.48530196f, -0.87434661f}, - {-0.79077573f, -0.61210598f}, - {-0.96807711f, -0.25065253f}, - {-0.98846832f, 0.15142777f}, - {-0.84864425f, 0.52896401f}, - {-0.57126821f, 0.82076344f}, - {-0.20129852f, 0.97952994f } - }; - - const float shape_diamond[4][2] = { - {0.0f, 1.2f}, - {1.2f, 0.0f}, - {0.0f, -1.2f}, - {-1.2f, 0.0f}, - }; - - const float shape_square[4][2] = { - {-0.9f, 0.9f}, - {0.9f, 0.9f}, - {0.9f, -0.9f}, - {-0.9f, -0.9f}, - }; - - const float (*shape)[2]; - int shape_len; - switch (sock->draw_shape) { - default: - case SOCK_DRAW_SHAPE_CIRCLE: - shape = shape_circle; - shape_len = ARRAY_SIZE(shape_circle); - break; - case SOCK_DRAW_SHAPE_DIAMOND: - shape = shape_diamond; - shape_len = ARRAY_SIZE(shape_diamond); - break; - case SOCK_DRAW_SHAPE_SQUARE: - shape = shape_square; - shape_len = ARRAY_SIZE(shape_square); - break; - } - - node_socket_shape_draw(sock->locx, sock->locy, size, color, highlight, shape, shape_len); + + immAttrib4fv(col, color); + immVertex2f(pos, sock->locx, sock->locy); } /* ************** Socket callbacks *********** */ @@ -722,10 +640,15 @@ static void node_draw_preview_background(float tile, rctf *rect) { float x, y; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* draw checkerboard backdrop to show alpha */ - glColor3ub(120, 120, 120); - glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax); - glColor3ub(160, 160, 160); + immUniformColor3ub(120, 120, 120); + immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + immUniformColor3ub(160, 160, 160); for (y = rect->ymin; y < rect->ymax; y += tile * 2) { for (x = rect->xmin; x < rect->xmax; x += tile * 2) { @@ -736,7 +659,7 @@ static void node_draw_preview_background(float tile, rctf *rect) if (y + tile > rect->ymax) tiley = rect->ymax - y; - glRectf(x, y, x + tilex, y + tiley); + immRectf(pos, x, y, x + tilex, y + tiley); } } for (y = rect->ymin + tile; y < rect->ymax; y += tile * 2) { @@ -748,9 +671,10 @@ static void node_draw_preview_background(float tile, rctf *rect) if (y + tile > rect->ymax) tiley = rect->ymax - y; - glRectf(x, y, x + tilex, y + tiley); + immRectf(pos, x, y, x + tilex, y + tiley); } } + immUnbindProgram(); } /* not a callback */ @@ -783,15 +707,17 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv) glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */ - glColor4f(1.0, 1.0, 1.0, 1.0); - glPixelZoom(scale, scale); - glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect); - glPixelZoom(1.0f, 1.0f); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect, + scale, scale, NULL); glDisable(GL_BLEND); - UI_ThemeColorShadeAlpha(TH_BACK, -15, +100); - fdrawbox(draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColorShadeAlpha(TH_BACK, -15, +100); + imm_draw_box_wire_2d(pos, draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax); + immUnbindProgram(); } /* common handle function for operator buttons that need to select the node first */ @@ -816,23 +742,134 @@ void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha) else { const float margin = 3.0f; - glColor4f(0.0f, 0.0f, 0.0f, 0.33f); - glEnable(GL_BLEND); - UI_draw_roundbox(rct->xmin - margin, rct->ymin - margin, - rct->xmax + margin, rct->ymax + margin, radius + margin); - glDisable(GL_BLEND); + float color[4] = {0.0f, 0.0f, 0.0f, 0.33f}; + UI_draw_roundbox_aa(true, rct->xmin - margin, rct->ymin - margin, + rct->xmax + margin, rct->ymax + margin, radius + margin, color); + } +} + +void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *node, bool draw_outputs, bool select_all) +{ + const unsigned int total_input_ct = BLI_listbase_count(&node->inputs); + const unsigned int total_output_ct = BLI_listbase_count(&node->outputs); + + if (total_input_ct + total_output_ct == 0) { + return; + } + + PointerRNA node_ptr; + RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr); + + float scale; + UI_view2d_scale_get(v2d, &scale, NULL); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + + glEnable(GL_BLEND); + GPU_enable_program_point_size(); + + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA); + + /* set handle size */ + immUniform1f("size", 2.0f * NODE_SOCKSIZE * scale); /* 2 * size to have diameter */ + + if (!select_all) { + /* outline for unselected sockets */ + immUniform1f("outlineWidth", 1.0f); + immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 0.6f); + + immBeginAtMost(GWN_PRIM_POINTS, total_input_ct + total_output_ct); + } + + /* socket inputs */ + short selected_input_ct = 0; + bNodeSocket *sock; + for (sock = node->inputs.first; sock; sock = sock->next) { + if (nodeSocketIsHidden(sock)) + continue; + if (select_all || (sock->flag & SELECT)) { + ++selected_input_ct; + continue; + } + + node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col); + } + + /* socket outputs */ + short selected_output_ct = 0; + if (draw_outputs) { + for (sock = node->outputs.first; sock; sock = sock->next) { + if (nodeSocketIsHidden(sock)) + continue; + if (select_all || (sock->flag & SELECT)) { + ++selected_output_ct; + continue; + } + + node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col); + } + } + + if (!select_all) { + immEnd(); + } + + /* go back and draw selected sockets */ + if (selected_input_ct + selected_output_ct > 0) { + /* outline for selected sockets */ + float c[3]; + UI_GetThemeColor3fv(TH_TEXT_HI, c); + immUniform4f("outlineColor", c[0], c[1], c[2], 1.0f); + immUniform1f("outlineWidth", 1.5f); + + immBegin(GWN_PRIM_POINTS, selected_input_ct + selected_output_ct); + + if (selected_input_ct) { + /* socket inputs */ + for (sock = node->inputs.first; sock; sock = sock->next) { + if (nodeSocketIsHidden(sock)) + continue; + if (select_all || (sock->flag & SELECT)) { + node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col); + if (--selected_input_ct == 0) + break; /* stop as soon as last one is drawn */ + } + } + } + + if (selected_output_ct) { + /* socket outputs */ + for (sock = node->outputs.first; sock; sock = sock->next) { + if (nodeSocketIsHidden(sock)) + continue; + if (select_all || (sock->flag & SELECT)) { + node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col); + if (--selected_output_ct == 0) + break; /* stop as soon as last one is drawn */ + } + } + } + + immEnd(); } + + immUnbindProgram(); + + GPU_disable_program_point_size(); + glDisable(GL_BLEND); } static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key) { bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data; - bNodeSocket *sock; rctf *rct = &node->totr; float iconofs; /* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */ float iconbutw = 0.8f * UI_UNIT_X; int color_id = node_get_colorid(node); + float color[4]; char showname[128]; /* 128 used below */ View2D *v2d = &ar->v2d; @@ -841,7 +878,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN nodeSynchronizeID(node, false); /* skip if out of view */ - if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == false) { + if (BLI_rctf_isect(&node->totr, &v2d->cur, NULL) == false) { UI_block_end(C, node->block); node->block = NULL; return; @@ -850,23 +887,24 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN /* shadow */ node_draw_shadow(snode, node, BASIS_RAD, 1.0f); - /* header uses color from backdrop, but we make it opaqie */ - if (color_id == TH_NODE) { - float col[3]; - UI_GetThemeColorShade3fv(color_id, -20, col); - glColor4f(col[0], col[1], col[2], 1.0f); + if (node->flag & NODE_MUTED) { + UI_GetThemeColorBlendShade4fv(color_id, TH_REDALERT, 0.5f, 0, color); + } + else { + /* header uses color from backdrop, but we make it opaque */ + if (color_id == TH_NODE) { + UI_GetThemeColorShade3fv(color_id, -20, color); + color[3] = 1.0f; + } + else { + UI_GetThemeColor4fv(color_id, color); + } } - else - UI_ThemeColor(color_id); - - if (node->flag & NODE_MUTED) - UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f); - glLineWidth(1.0f); UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT); - UI_draw_roundbox(rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD); + UI_draw_roundbox_aa(true, rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD, color); /* show/hide icons */ iconofs = rct->xmax - 0.35f * U.widget_unit; @@ -899,10 +937,12 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN } /* title */ - if (node->flag & SELECT) - UI_ThemeColor(TH_SELECT); - else - UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); + if (node->flag & SELECT) { + UI_GetThemeColor4fv(TH_SELECT, color); + } + else { + UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color); + } /* open/close entirely? */ { @@ -917,17 +957,9 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN UI_block_emboss_set(node->block, UI_EMBOSS); /* custom draw function for this button */ - UI_draw_icon_tri(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v'); + UI_draw_icon_tri(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v', color); } - /* this isn't doing anything for the label, so commenting out */ -#if 0 - if (node->flag & SELECT) - UI_ThemeColor(TH_TEXT_HI); - else - UI_ThemeColor(TH_TEXT); -#endif - nodeLabel(ntree, node, showname, sizeof(showname)); //if (node->flag & NODE_MUTED) @@ -940,55 +972,30 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN /* body */ if (!nodeIsRegistered(node)) - UI_ThemeColor4(TH_REDALERT); /* use warning color to indicate undefined types */ - else if (node->flag & NODE_CUSTOM_COLOR) - glColor3fv(node->color); + UI_GetThemeColor4fv(TH_REDALERT, color); /* use warning color to indicate undefined types */ + else if (node->flag & NODE_CUSTOM_COLOR) { + rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], 1.0f); + } else - UI_ThemeColor4(TH_NODE); - glEnable(GL_BLEND); + UI_GetThemeColor4fv(TH_NODE, color); + UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT); - UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD); - glDisable(GL_BLEND); + UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD, color); /* outline active and selected emphasis */ if (node->flag & SELECT) { - - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - - if (node->flag & NODE_ACTIVE) - UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40); - else - UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40); - + UI_GetThemeColorShadeAlpha4fv((node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color); + UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD); - - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); + UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color); } /* disable lines */ if (node->flag & NODE_MUTED) node_draw_mute_line(v2d, snode, node); - - /* socket inputs, buttons */ - for (sock = node->inputs.first; sock; sock = sock->next) { - if (nodeSocketIsHidden(sock)) - continue; - - node_socket_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT); - } - - /* socket outputs */ - for (sock = node->outputs.first; sock; sock = sock->next) { - if (nodeSocketIsHidden(sock)) - continue; - - node_socket_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT); - } - + node_draw_sockets(v2d, C, ntree, node, true, false); + /* preview */ if (node->flag & NODE_PREVIEW && previews) { bNodePreview *preview = BKE_node_instance_hash_lookup(previews, key); @@ -1008,37 +1015,33 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key)) { - bNodeSocket *sock; rctf *rct = &node->totr; float dx, centy = BLI_rctf_cent_y(rct); float hiddenrad = BLI_rctf_size_y(rct) / 2.0f; - float socket_size = NODE_SOCKSIZE; int color_id = node_get_colorid(node); + float color[4]; char showname[128]; /* 128 is used below */ + View2D *v2d = &ar->v2d; + float scale; + + UI_view2d_scale_get(v2d, &scale, NULL); /* shadow */ node_draw_shadow(snode, node, hiddenrad, 1.0f); /* body */ - UI_ThemeColor(color_id); if (node->flag & NODE_MUTED) - UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f); - - UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad); + UI_GetThemeColorBlendShade4fv(color_id, TH_REDALERT, 0.5f, 0, color); + else + UI_GetThemeColor4fv(color_id, color); + + UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color); /* outline active and selected emphasis */ if (node->flag & SELECT) { - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - - if (node->flag & NODE_ACTIVE) - UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40); - else - UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad); - - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); + UI_GetThemeColorShadeAlpha4fv((node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color); + + UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color); } /* custom color inline */ @@ -1046,18 +1049,19 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - glColor3fv(node->color); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin + 1, rct->ymin + 1, rct->xmax -1, rct->ymax - 1, hiddenrad); + UI_draw_roundbox_3fvAlpha(false, rct->xmin + 1, rct->ymin + 1, rct->xmax -1, rct->ymax - 1, hiddenrad, node->color, 1.0f); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); } /* title */ - if (node->flag & SELECT) - UI_ThemeColor(TH_SELECT); - else - UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); + if (node->flag & SELECT) { + UI_GetThemeColor4fv(TH_SELECT, color); + } + else { + UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color); + } /* open entirely icon */ { @@ -1072,18 +1076,13 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b UI_block_emboss_set(node->block, UI_EMBOSS); /* custom draw function for this button */ - UI_draw_icon_tri(rct->xmin + 10.0f, centy, 'h'); + UI_draw_icon_tri(rct->xmin + 10.0f, centy, 'h', color); } /* disable lines */ if (node->flag & NODE_MUTED) node_draw_mute_line(&ar->v2d, snode, node); - - if (node->flag & SELECT) - UI_ThemeColor(TH_SELECT); - else - UI_ThemeColor(TH_TEXT); - + if (node->miniwidth > 0.0f) { nodeLabel(ntree, node, showname, sizeof(showname)); @@ -1097,29 +1096,35 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b } /* scale widget thing */ - UI_ThemeColorShade(color_id, -10); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColorShade(color_id, -10); dx = 10.0f; - fdrawline(rct->xmax - dx, centy - 4.0f, rct->xmax - dx, centy + 4.0f); - fdrawline(rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); - - UI_ThemeColorShade(color_id, +30); + + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, rct->xmax - dx, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx, centy + 4.0f); + + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); + immEnd(); + + immUniformThemeColorShade(color_id, 30); dx -= snode->aspect; - fdrawline(rct->xmax - dx, centy - 4.0f, rct->xmax - dx, centy + 4.0f); - fdrawline(rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); - /* sockets */ - for (sock = node->inputs.first; sock; sock = sock->next) { - if (!nodeSocketIsHidden(sock)) { - node_socket_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT); - } - } - - for (sock = node->outputs.first; sock; sock = sock->next) { - if (!nodeSocketIsHidden(sock)) { - node_socket_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT); - } - } - + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, rct->xmax - dx, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx, centy + 4.0f); + + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); + immEnd(); + + immUnbindProgram(); + + node_draw_sockets(v2d, C, ntree, node, true, false); + UI_block_end(C, node->block); UI_block_draw(C, node->block); node->block = NULL; @@ -1260,7 +1265,7 @@ static void draw_tree_path(SpaceNode *snode) ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info)); - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); BLF_draw_default(1.5f * UI_UNIT_X, 1.5f * UI_UNIT_Y, 0.0f, info, sizeof(info)); } @@ -1293,12 +1298,14 @@ static void draw_group_overlay(const bContext *C, ARegion *ar) View2D *v2d = &ar->v2d; rctf rect = v2d->cur; uiBlock *block; - + float color[4]; + /* shade node groups to separate them visually */ - UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70); glEnable(GL_BLEND); + + UI_GetThemeColorShadeAlpha4fv(TH_NODE_GROUP, 0, -70, color); UI_draw_roundbox_corner_set(UI_CNR_NONE); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0); + UI_draw_roundbox_4fv(true, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0, color); glDisable(GL_BLEND); /* set the block bounds to clip mouse events from underlying nodes */ @@ -1330,7 +1337,6 @@ void drawnodespace(const bContext *C, ARegion *ar) /* only set once */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_MAP1_VERTEX_3); /* nodes */ snode_set_context(C); @@ -1390,7 +1396,23 @@ void drawnodespace(const bContext *C, ARegion *ar) /* backdrop */ draw_nodespace_back_pix(C, ar, snode, path->parent_key); - + + { + float original_proj[4][4]; + gpuGetProjectionMatrix(original_proj); + + gpuPushMatrix(); + gpuLoadIdentity(); + + glaDefine2DArea(&ar->winrct); + wmOrtho2_pixelspace(ar->winx, ar->winy); + + WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_2D); + + gpuPopMatrix(); + gpuLoadProjectionMatrix(original_proj); + } + draw_nodetree(C, ar, ntree, path->parent_key); } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index e38b48d4bb8..5a682338eee 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -41,7 +41,6 @@ #include "BLI_blenlib.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_image.h" #include "BKE_library.h" @@ -50,6 +49,8 @@ #include "BKE_report.h" #include "BKE_scene.h" +#include "DEG_depsgraph.h" + #include "RE_engine.h" #include "RE_pipeline.h" @@ -123,7 +124,7 @@ static int compo_get_recalc_flags(const bContext *C) int recalc_flags = 0; for (win = wm->windows.first; win; win = win->next) { - bScreen *sc = win->screen; + const bScreen *sc = WM_window_get_active_screen(win); ScrArea *sa; for (sa = sc->areabase.first; sa; sa = sa->next) { @@ -328,11 +329,11 @@ void snode_dag_update(bContext *C, SpaceNode *snode) if (snode->edittree != snode->nodetree) { FOREACH_NODETREE(bmain, tntree, id) { if (ntreeHasTree(tntree, snode->edittree)) - DAG_id_tag_update(id, 0); + DEG_id_tag_update(id, 0); } FOREACH_NODETREE_END } - DAG_id_tag_update(snode->id, 0); + DEG_id_tag_update(snode->id, 0); } void snode_notify(bContext *C, SpaceNode *snode) @@ -382,7 +383,7 @@ bool ED_node_is_texture(struct SpaceNode *snode) /* called from shading buttons or header */ void ED_node_shader_default(const bContext *C, ID *id) { - Scene *scene = CTX_data_scene(C); + ViewRender *view_render = CTX_data_view_render(C); bNode *in, *out; bNodeSocket *fromsock, *tosock, *sock; bNodeTree *ntree; @@ -397,7 +398,11 @@ void ED_node_shader_default(const bContext *C, ID *id) Material *ma = (Material *)id; ma->nodetree = ntree; - if (BKE_scene_use_new_shading_nodes(scene)) { + if (BKE_viewrender_uses_blender_eevee(view_render)) { + output_type = SH_NODE_OUTPUT_MATERIAL; + shader_type = SH_NODE_BSDF_PRINCIPLED; + } + else if (BKE_viewrender_use_new_shading_nodes(view_render)) { output_type = SH_NODE_OUTPUT_MATERIAL; shader_type = SH_NODE_BSDF_DIFFUSE; } @@ -455,7 +460,7 @@ void ED_node_shader_default(const bContext *C, ID *id) nodeAddLink(ntree, in, fromsock, out, tosock); /* default values */ - if (BKE_scene_use_new_shading_nodes(scene)) { + if (BKE_viewrender_use_new_shading_nodes(view_render)) { PointerRNA sockptr; sock = in->inputs.first; RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr); @@ -695,12 +700,12 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) for (scene = bmain->scene.first; scene; scene = scene->id.next) { if (scene->nodetree && scene->use_nodes && ntreeHasTree(scene->nodetree, ntree)) { if (node->id == NULL || node->id == (ID *)scene) { - int num_layers = BLI_listbase_count(&scene->r.layers); - scene->r.actlay = node->custom1; + int num_layers = BLI_listbase_count(&scene->render_layers); + scene->active_layer = node->custom1; /* Clamp the value, because it might have come from a different * scene which could have more render layers than new one. */ - scene->r.actlay = min_ff(scene->r.actlay, num_layers - 1); + scene->active_layer = min_ff(scene->active_layer, num_layers - 1); } } } @@ -1361,13 +1366,13 @@ int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op)) } } if (node) { - SceneRenderLayer *srl = BLI_findlink(&sce->r.layers, node->custom1); + SceneLayer *scene_layer = BLI_findlink(&sce->render_layers, node->custom1); - if (srl) { + if (scene_layer) { PointerRNA op_ptr; WM_operator_properties_create(&op_ptr, "RENDER_OT_render"); - RNA_string_set(&op_ptr, "layer", srl->name); + RNA_string_set(&op_ptr, "layer", scene_layer->name); RNA_string_set(&op_ptr, "scene", sce->id.name + 2); /* to keep keypositions */ @@ -2348,7 +2353,7 @@ void NODE_OT_tree_socket_move(wmOperatorType *ot) static int node_shader_script_update_poll(bContext *C) { Scene *scene = CTX_data_scene(C); - RenderEngineType *type = RE_engines_find(scene->r.engine); + RenderEngineType *type = RE_engines_find(scene->view_render.engine_id); SpaceNode *snode = CTX_wm_space_node(C); bNode *node; Text *text; @@ -2418,7 +2423,7 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op) bool found = false; /* setup render engine */ - type = RE_engines_find(scene->r.engine); + type = RE_engines_find(scene->view_render.engine_id); engine = RE_engine_create(type); engine->reports = op->reports; diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 352f9e51012..12e3c33007e 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -67,13 +67,11 @@ void snode_group_offset(struct SpaceNode *snode, float *x, float *y); /* transfo /* node_draw.c */ int node_get_colorid(struct bNode *node); -void node_socket_draw( - const struct bContext *C, struct bNodeTree *ntree, struct bNode *node, - struct bNodeSocket *sock, float size, bool highlight); int node_get_resize_cursor(int directions); void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha); void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key); +void node_draw_sockets(struct View2D *v2d, const struct bContext *C, struct bNodeTree *ntree, struct bNode *node, bool draw_outputs, bool select_all); void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node); int node_select_area_default(struct bNode *node, int x, int y); int node_tweak_area_default(struct bNode *node, int x, int y); @@ -221,6 +219,13 @@ void NODE_OT_shader_script_update(struct wmOperatorType *ot); void NODE_OT_viewer_border(struct wmOperatorType *ot); void NODE_OT_clear_viewer_border(struct wmOperatorType *ot); +/* node_widgets.c */ +void NODE_WGT_backdrop_transform(struct wmManipulatorGroupType *wgt); +void NODE_WGT_backdrop_crop(struct wmManipulatorGroupType *wgt); +void NODE_WGT_backdrop_sun_beams(struct wmManipulatorGroupType *wgt); +void NODE_WGT_backdrop_corner_pin(struct wmManipulatorGroupType *wgt); + + extern const char *node_context_dir[]; // XXXXXX diff --git a/source/blender/editors/space_node/node_manipulators.c b/source/blender/editors/space_node/node_manipulators.c new file mode 100644 index 00000000000..73b0f44b043 --- /dev/null +++ b/source/blender/editors/space_node/node_manipulators.c @@ -0,0 +1,616 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_node/node_manipulators.c + * \ingroup spnode + */ + +#include <math.h> + +#include "BLI_utildefines.h" +#include "BLI_math_matrix.h" +#include "BLI_math_vector.h" +#include "BLI_rect.h" + +#include "BKE_context.h" +#include "BKE_image.h" + +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +#include "IMB_imbuf_types.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "node_intern.h" + + +/* -------------------------------------------------------------------- */ + +/** \name Local Utilities + * \{ */ + +static void node_manipulator_calc_matrix_space( + const SpaceNode *snode, const ARegion *ar, float matrix_space[4][4]) +{ + unit_m4(matrix_space); + mul_v3_fl(matrix_space[0], snode->zoom); + mul_v3_fl(matrix_space[1], snode->zoom); + matrix_space[3][0] = (ar->winx / 2) + snode->xof; + matrix_space[3][1] = (ar->winy / 2) + snode->yof; +} + +static void node_manipulator_calc_matrix_space_with_image_dims( + const SpaceNode *snode, const ARegion *ar, const float image_dims[2], float matrix_space[4][4]) +{ + unit_m4(matrix_space); + mul_v3_fl(matrix_space[0], snode->zoom * image_dims[0]); + mul_v3_fl(matrix_space[1], snode->zoom * image_dims[1]); + matrix_space[3][0] = ((ar->winx / 2) + snode->xof) - ((image_dims[0] / 2.0f) * snode->zoom); + matrix_space[3][1] = ((ar->winy / 2) + snode->yof) - ((image_dims[1] / 2.0f) * snode->zoom); +} + +/** \} */ + + + +/* -------------------------------------------------------------------- */ + +/** \name Backdrop Manipulator + * \{ */ + +static void manipulator_node_backdrop_prop_matrix_get( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + void *value_p) +{ + float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + const SpaceNode *snode = mpr_prop->custom_func.user_data; + matrix[0][0] = snode->zoom; + matrix[1][1] = snode->zoom; + matrix[3][0] = snode->xof; + matrix[3][1] = snode->yof; +} + +static void manipulator_node_backdrop_prop_matrix_set( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + const float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + SpaceNode *snode = mpr_prop->custom_func.user_data; + snode->zoom = matrix[0][0]; + snode->zoom = matrix[1][1]; + snode->xof = matrix[3][0]; + snode->yof = matrix[3][1]; +} + +static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if ((snode->flag & SNODE_BACKDRAW) == 0) { + return false; + } + + if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { + bNode *node = nodeGetActive(snode->edittree); + + if (node && ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + return true; + } + } + + return false; +} + +static void WIDGETGROUP_node_transform_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__); + + wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL); + + RNA_enum_set(wwrapper->manipulator->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM); + + mgroup->customdata = wwrapper; +} + +static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmManipulator *cage = ((wmManipulatorWrapper *)mgroup->customdata)->manipulator; + const ARegion *ar = CTX_wm_region(C); + /* center is always at the origin */ + const float origin[3] = {ar->winx / 2, ar->winy / 2}; + + void *lock; + Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + + if (ibuf) { + const float dims[2] = { + (ibuf->x > 0) ? ibuf->x : 64.0f, + (ibuf->y > 0) ? ibuf->y : 64.0f, + }; + + RNA_float_set_array(cage->ptr, "dimensions", dims); + WM_manipulator_set_matrix_location(cage, origin); + WM_manipulator_set_flag(cage, WM_MANIPULATOR_HIDDEN, false); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + SpaceNode *snode = CTX_wm_space_node(C); +#if 0 + PointerRNA nodeptr; + RNA_pointer_create(snode->id, &RNA_SpaceNodeEditor, snode, &nodeptr); + WM_manipulator_target_property_def_rna(cage, "offset", &nodeptr, "backdrop_offset", -1); + WM_manipulator_target_property_def_rna(cage, "scale", &nodeptr, "backdrop_zoom", -1); +#endif + + WM_manipulator_target_property_def_func( + cage, "matrix", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_node_backdrop_prop_matrix_get, + .value_set_fn = manipulator_node_backdrop_prop_matrix_set, + .range_get_fn = NULL, + .user_data = snode, + }); + } + else { + WM_manipulator_set_flag(cage, WM_MANIPULATOR_HIDDEN, true); + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + +void NODE_WGT_backdrop_transform(wmManipulatorGroupType *wgt) +{ + wgt->name = "Backdrop Transform Widget"; + wgt->idname = "NODE_WGT_backdrop_transform"; + + wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT; + + wgt->poll = WIDGETGROUP_node_transform_poll; + wgt->setup = WIDGETGROUP_node_transform_setup; + wgt->refresh = WIDGETGROUP_node_transform_refresh; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Crop Manipulator + * \{ */ + +struct NodeCropWidgetGroup { + wmManipulator *border; + + struct { + float dims[2]; + } state; + + struct { + PointerRNA ptr; + PropertyRNA *prop; + bContext *context; + } update_data; +}; + +static void manipulator_node_crop_update(struct NodeCropWidgetGroup *crop_group) +{ + RNA_property_update(crop_group->update_data.context, &crop_group->update_data.ptr, crop_group->update_data.prop); +} + +static void two_xy_to_rect(const NodeTwoXYs *nxy, rctf *rect, const float dims[2], bool is_relative) +{ + if (is_relative) { + rect->xmin = nxy->fac_x1; + rect->xmax = nxy->fac_x2; + rect->ymin = nxy->fac_y1; + rect->ymax = nxy->fac_y2; + } + else { + rect->xmin = nxy->x1 / dims[0]; + rect->xmax = nxy->x2 / dims[0]; + rect->ymin = nxy->y1 / dims[1]; + rect->ymax = nxy->y2 / dims[1]; + } +} + +static void two_xy_from_rect(NodeTwoXYs *nxy, const rctf *rect, const float dims[2], bool is_relative) +{ + if (is_relative) { + nxy->fac_x1 = rect->xmin; + nxy->fac_x2 = rect->xmax; + nxy->fac_y1 = rect->ymin; + nxy->fac_y2 = rect->ymax; + } + else { + nxy->x1 = rect->xmin * dims[0]; + nxy->x2 = rect->xmax * dims[0]; + nxy->y1 = rect->ymin * dims[1]; + nxy->y2 = rect->ymax * dims[1]; + } +} + +/* scale callbacks */ +static void manipulator_node_crop_prop_matrix_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + struct NodeCropWidgetGroup *crop_group = mpr->parent_mgroup->customdata; + const float *dims = crop_group->state.dims; + const bNode *node = mpr_prop->custom_func.user_data; + const NodeTwoXYs *nxy = node->storage; + bool is_relative = (bool)node->custom2; + rctf rct; + two_xy_to_rect(nxy, &rct, dims, is_relative); + matrix[0][0] = BLI_rctf_size_x(&rct); + matrix[1][1] = BLI_rctf_size_y(&rct); + matrix[3][0] = (BLI_rctf_cent_x(&rct) - 0.5f) * dims[0]; + matrix[3][1] = (BLI_rctf_cent_y(&rct) - 0.5f) * dims[1]; +} + +static void manipulator_node_crop_prop_matrix_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + const float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + struct NodeCropWidgetGroup *crop_group = mpr->parent_mgroup->customdata; + const float *dims = crop_group->state.dims; + bNode *node = mpr_prop->custom_func.user_data; + NodeTwoXYs *nxy = node->storage; + bool is_relative = (bool)node->custom2; + rctf rct; + two_xy_to_rect(nxy, &rct, dims, is_relative); + BLI_rctf_resize(&rct, matrix[0][0], matrix[1][1]); + BLI_rctf_recenter(&rct, (matrix[3][0] / dims[0]) + 0.5f, (matrix[3][1] / dims[1]) + 0.5f); + BLI_rctf_isect(&(rctf){.xmin = 0, .ymin = 0, .xmax = 1, .ymax = 1}, &rct, &rct); + two_xy_from_rect(nxy, &rct, dims, is_relative); + manipulator_node_crop_update(crop_group); +} + +static bool WIDGETGROUP_node_crop_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if ((snode->flag & SNODE_BACKDRAW) == 0) { + return false; + } + + if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { + bNode *node = nodeGetActive(snode->edittree); + + if (node && ELEM(node->type, CMP_NODE_CROP)) { + /* ignore 'use_crop_size', we can't usefully edit the crop in this case. */ + if ((node->custom1 & (0 << 1)) == 0) { + return true; + } + } + } + + return false; +} + +static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + struct NodeCropWidgetGroup *crop_group = MEM_mallocN(sizeof(struct NodeCropWidgetGroup), __func__); + + crop_group->border = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL); + + RNA_enum_set(crop_group->border->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE); + + mgroup->customdata = crop_group; +} + +static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + ARegion *ar = CTX_wm_region(C); + wmManipulator *mpr = mgroup->manipulators.first; + + SpaceNode *snode = CTX_wm_space_node(C); + + node_manipulator_calc_matrix_space(snode, ar, mpr->matrix_space); +} + +static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct NodeCropWidgetGroup *crop_group = mgroup->customdata; + wmManipulator *mpr = crop_group->border; + + void *lock; + Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + + if (ibuf) { + crop_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f; + crop_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f; + + RNA_float_set_array(mpr->ptr, "dimensions", crop_group->state.dims); + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + + SpaceNode *snode = CTX_wm_space_node(C); + bNode *node = nodeGetActive(snode->edittree); + + crop_group->update_data.context = (bContext *)C; + RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeCrop, node, &crop_group->update_data.ptr); + crop_group->update_data.prop = RNA_struct_find_property(&crop_group->update_data.ptr, "relative"); + + WM_manipulator_target_property_def_func( + mpr, "matrix", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_node_crop_prop_matrix_get, + .value_set_fn = manipulator_node_crop_prop_matrix_set, + .range_get_fn = NULL, + .user_data = node, + }); + } + else { + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + +void NODE_WGT_backdrop_crop(wmManipulatorGroupType *wgt) +{ + wgt->name = "Backdrop Crop Widget"; + wgt->idname = "NODE_WGT_backdrop_crop"; + + wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT; + + wgt->poll = WIDGETGROUP_node_crop_poll; + wgt->setup = WIDGETGROUP_node_crop_setup; + wgt->draw_prepare = WIDGETGROUP_node_crop_draw_prepare; + wgt->refresh = WIDGETGROUP_node_crop_refresh; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Sun Beams + * \{ */ + +struct NodeSunBeamsWidgetGroup { + wmManipulator *manipulator; + + struct { + float dims[2]; + } state; +}; + +static bool WIDGETGROUP_node_sbeam_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if ((snode->flag & SNODE_BACKDRAW) == 0) { + return false; + } + + if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { + bNode *node = nodeGetActive(snode->edittree); + + if (node && ELEM(node->type, CMP_NODE_SUNBEAMS)) { + return true; + } + } + + return false; +} + +static void WIDGETGROUP_node_sbeam_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + struct NodeSunBeamsWidgetGroup *sbeam_group = MEM_mallocN(sizeof(struct NodeSunBeamsWidgetGroup), __func__); + + sbeam_group->manipulator = WM_manipulator_new("MANIPULATOR_WT_grab_3d", mgroup, NULL); + wmManipulator *mpr = sbeam_group->manipulator; + + RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_CROSS_2D); + + mpr->scale_basis = 0.05f; + + mgroup->customdata = sbeam_group; +} + +static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct NodeSunBeamsWidgetGroup *sbeam_group = mgroup->customdata; + ARegion *ar = CTX_wm_region(C); + wmManipulator *mpr = mgroup->manipulators.first; + + SpaceNode *snode = CTX_wm_space_node(C); + + node_manipulator_calc_matrix_space_with_image_dims(snode, ar, sbeam_group->state.dims, mpr->matrix_space); +} + +static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct NodeSunBeamsWidgetGroup *sbeam_group = mgroup->customdata; + wmManipulator *mpr = sbeam_group->manipulator; + + void *lock; + Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + + if (ibuf) { + sbeam_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f; + sbeam_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f; + + SpaceNode *snode = CTX_wm_space_node(C); + bNode *node = nodeGetActive(snode->edittree); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + PointerRNA nodeptr; + RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeSunBeams, node, &nodeptr); + WM_manipulator_target_property_def_rna(mpr, "offset", &nodeptr, "source", -1); + + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_MODAL, true); + } + else { + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + +void NODE_WGT_backdrop_sun_beams(wmManipulatorGroupType *wgt) +{ + wgt->name = "Sun Beams Widget"; + wgt->idname = "NODE_WGT_sbeam"; + + wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT; + + wgt->poll = WIDGETGROUP_node_sbeam_poll; + wgt->setup = WIDGETGROUP_node_sbeam_setup; + wgt->draw_prepare = WIDGETGROUP_node_sbeam_draw_prepare; + wgt->refresh = WIDGETGROUP_node_sbeam_refresh; +} + +/** \} */ + + + +/* -------------------------------------------------------------------- */ + +/** \name Corner Pin + * \{ */ + +struct NodeCornerPinWidgetGroup { + wmManipulator *manipulators[4]; + + struct { + float dims[2]; + } state; +}; + +static bool WIDGETGROUP_node_corner_pin_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if ((snode->flag & SNODE_BACKDRAW) == 0) { + return false; + } + + if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { + bNode *node = nodeGetActive(snode->edittree); + + if (node && ELEM(node->type, CMP_NODE_CORNERPIN)) { + return true; + } + } + + return false; +} + +static void WIDGETGROUP_node_corner_pin_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + struct NodeCornerPinWidgetGroup *cpin_group = MEM_mallocN(sizeof(struct NodeCornerPinWidgetGroup), __func__); + const wmManipulatorType *wt_grab_3d = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", false); + + for (int i = 0; i < 4; i++) { + cpin_group->manipulators[i] = WM_manipulator_new_ptr(wt_grab_3d, mgroup, NULL); + wmManipulator *mpr = cpin_group->manipulators[i]; + + RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_CROSS_2D); + + mpr->scale_basis = 0.01f; + } + + mgroup->customdata = cpin_group; +} + +static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct NodeCornerPinWidgetGroup *cpin_group = mgroup->customdata; + ARegion *ar = CTX_wm_region(C); + + SpaceNode *snode = CTX_wm_space_node(C); + + float matrix_space[4][4]; + node_manipulator_calc_matrix_space_with_image_dims(snode, ar, cpin_group->state.dims, matrix_space); + + for (int i = 0; i < 4; i++) { + wmManipulator *mpr = cpin_group->manipulators[i]; + copy_m4_m4(mpr->matrix_space, matrix_space); + } +} + +static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct NodeCornerPinWidgetGroup *cpin_group = mgroup->customdata; + + void *lock; + Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + + if (ibuf) { + cpin_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f; + cpin_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f; + + SpaceNode *snode = CTX_wm_space_node(C); + bNode *node = nodeGetActive(snode->edittree); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + int i = 0; + for (bNodeSocket *sock = node->inputs.first; sock && i < 4; sock = sock->next) { + if (sock->type == SOCK_VECTOR) { + wmManipulator *mpr = cpin_group->manipulators[i++]; + + PointerRNA sockptr; + RNA_pointer_create((ID *)snode->edittree, &RNA_NodeSocket, sock, &sockptr); + WM_manipulator_target_property_def_rna(mpr, "offset", &sockptr, "default_value", -1); + + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_MODAL, true); + } + } + } + else { + for (int i = 0; i < 4; i++) { + wmManipulator *mpr = cpin_group->manipulators[i]; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); + } + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + +void NODE_WGT_backdrop_corner_pin(wmManipulatorGroupType *wgt) +{ + wgt->name = "Corner Pin Widget"; + wgt->idname = "NODE_WGT_backdrop_corner_pin"; + + wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT; + + wgt->poll = WIDGETGROUP_node_corner_pin_poll; + wgt->setup = WIDGETGROUP_node_corner_pin_setup; + wgt->draw_prepare = WIDGETGROUP_node_corner_pin_draw_prepare; + wgt->refresh = WIDGETGROUP_node_corner_pin_refresh; +} + +/** \} */ diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 5d0877a1eff..c791b9f6eae 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -559,6 +559,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_ { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + ViewRender *view_render = CTX_data_view_render(C); uiBlock *block = uiLayoutGetBlock(layout); uiBut *but = (uiBut *)but_p; uiLayout *split, *column; @@ -575,7 +576,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_ arg->layout = split; if (ntreetype && ntreetype->foreach_nodeclass) - ntreetype->foreach_nodeclass(scene, arg, node_menu_column_foreach_cb); + ntreetype->foreach_nodeclass(view_render, arg, node_menu_column_foreach_cb); column = uiLayoutColumn(split, false); UI_block_layout_set_current(block, column); diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 2267316d257..e1765e39f7a 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -49,14 +49,15 @@ #include "ED_node.h" #include "ED_render.h" #include "ED_screen.h" -#include "WM_api.h" -#include "WM_types.h" #include "UI_resources.h" #include "UI_view2d.h" #include "RNA_access.h" +#include "WM_api.h" +#include "WM_types.h" + #include "node_intern.h" /* own include */ @@ -381,12 +382,14 @@ static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa)) } -static void node_area_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn) +static void node_area_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *scene, + WorkSpace *workspace) { /* note, ED_area_tag_refresh will re-execute compositor */ SpaceNode *snode = sa->spacedata.first; + ViewRender *view_render = BKE_viewrender_get(scene, workspace); /* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */ - short shader_type = BKE_scene_use_new_shading_nodes(sc->scene) ? snode->shaderfrom : SNODE_SHADER_OBJECT; + short shader_type = BKE_viewrender_use_new_shading_nodes(view_render) ? snode->shaderfrom : SNODE_SHADER_OBJECT; /* preview renders */ switch (wmn->category) { @@ -643,6 +646,14 @@ static void node_main_region_init(wmWindowManager *wm, ARegion *ar) UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); + /* manipulators stay in the background for now - quick patchjob to make sure nodes themselves work */ + if (ar->manipulator_map == NULL) { + ar->manipulator_map = WM_manipulatormap_new_from_type( + &(const struct wmManipulatorMapType_Params){SPACE_NODE, RGN_TYPE_WINDOW}); + } + + WM_manipulatormap_add_handlers(ar, ar->manipulator_map); + /* own keymaps */ keymap = WM_keymap_find(wm->defaultconf, "Node Generic", SPACE_NODE, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); @@ -737,18 +748,32 @@ static void node_header_region_draw(const bContext *C, ARegion *ar) } /* used for header + main region */ -static void node_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void node_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { + wmManipulatorMap *mmap = ar->manipulator_map; + /* context changes */ switch (wmn->category) { case NC_SPACE: - if (wmn->data == ND_SPACE_NODE) - ED_region_tag_redraw(ar); + switch (wmn->data) { + case ND_SPACE_NODE: + ED_region_tag_redraw(ar); + break; + case ND_SPACE_NODE_VIEW: + WM_manipulatormap_tag_refresh(mmap); + break; + } break; case NC_SCREEN: + if (wmn->data == ND_LAYOUTSET || wmn->action == NA_EDITED) { + WM_manipulatormap_tag_refresh(mmap); + } switch (wmn->data) { case ND_SCREENCAST: case ND_ANIMPLAY: + case ND_LAYER: ED_region_tag_redraw(ar); break; } @@ -758,10 +783,20 @@ static void node_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegi ED_region_tag_redraw(ar); break; case NC_SCENE: + ED_region_tag_redraw(ar); + if (wmn->data == ND_RENDER_RESULT) { + WM_manipulatormap_tag_refresh(mmap); + } + break; + case NC_NODE: + ED_region_tag_redraw(ar); + if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { + WM_manipulatormap_tag_refresh(mmap); + } + break; case NC_MATERIAL: case NC_TEXTURE: case NC_WORLD: - case NC_NODE: case NC_LINESTYLE: ED_region_tag_redraw(ar); break; @@ -826,6 +861,17 @@ static int node_context(const bContext *C, const char *member, bContextDataResul return 0; } +static void node_widgets(void) +{ + /* create the widgetmap for the area here */ + wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure( + &(const struct wmManipulatorMapType_Params){SPACE_NODE, RGN_TYPE_WINDOW}); + WM_manipulatorgrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_transform); + WM_manipulatorgrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_crop); + WM_manipulatorgrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_sun_beams); + WM_manipulatorgrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_corner_pin); +} + static void node_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id) { SpaceNode *snode = (SpaceNode *)slink; @@ -916,6 +962,7 @@ void ED_spacetype_node(void) st->refresh = node_area_refresh; st->context = node_context; st->dropboxes = node_dropboxes; + st->manipulators = node_widgets; st->id_remap = node_id_remap; /* regions: main window */ diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index 289d6e715e1..96d27c6fd89 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../imbuf ../../gpu ../../makesdna @@ -37,12 +38,14 @@ set(INC_SYS ) set(SRC + outliner_collections.c outliner_draw.c outliner_edit.c outliner_ops.c outliner_select.c outliner_tools.c outliner_tree.c + outliner_utils.c space_outliner.c outliner_intern.h diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c new file mode 100644 index 00000000000..2f03935c999 --- /dev/null +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -0,0 +1,548 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation, Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_outliner/outliner_collections.c + * \ingroup spoutliner + */ + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" + +#include "BKE_context.h" +#include "BKE_collection.h" +#include "BKE_layer.h" +#include "BKE_main.h" +#include "BKE_report.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + +#include "ED_screen.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "UI_resources.h" + +#include "outliner_intern.h" /* own include */ + +/* -------------------------------------------------------------------- */ + +static LayerCollection *outliner_collection_active(bContext *C) +{ + TODO_LAYER_OPERATORS; + /* consider that we may have overrides or objects active + * leading to no active collections */ + return CTX_data_layer_collection(C); +} + +SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te) +{ + TreeStoreElem *tselem = TREESTORE(te); + + if (tselem->type == TSE_SCENE_COLLECTION) { + return te->directdata; + } + else if (tselem->type == TSE_LAYER_COLLECTION) { + LayerCollection *lc = te->directdata; + return lc->scene_collection; + } + + return NULL; +} + +#if 0 +static CollectionOverride *outliner_override_active(bContext *UNUSED(C)) +{ + TODO_LAYER_OPERATORS; + TODO_LAYER_OVERRIDE; + return NULL; +} +#endif + +/* -------------------------------------------------------------------- */ +/* collection manager operators */ + +/** + * Recursively get the collection for a given index + */ +static SceneCollection *scene_collection_from_index(ListBase *lb, const int number, int *i) +{ + for (SceneCollection *sc = lb->first; sc; sc = sc->next) { + if (*i == number) { + return sc; + } + + (*i)++; + + SceneCollection *sc_nested = scene_collection_from_index(&sc->scene_collections, number, i); + if (sc_nested) { + return sc_nested; + } + } + return NULL; +} + +static int collection_link_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + SceneCollection *sc_master = BKE_collection_master(scene); + SceneCollection *sc; + + int scene_collection_index = RNA_enum_get(op->ptr, "scene_collection"); + if (scene_collection_index == 0) { + sc = sc_master; + } + else { + int index = 1; + sc = scene_collection_from_index(&sc_master->scene_collections, scene_collection_index, &index); + BLI_assert(sc); + } + + BKE_collection_link(sl, sc); + + DEG_relations_tag_update(CTX_data_main(C)); + + /* TODO(sergey): Use proper flag for tagging here. */ + DEG_id_tag_update(&scene->id, 0); + + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + return OPERATOR_FINISHED; +} + +static int collection_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + if (BKE_collection_master(CTX_data_scene(C))->scene_collections.first == NULL) { + RNA_enum_set(op->ptr, "scene_collection", 0); + return collection_link_exec(C, op); + } + else { + return WM_enum_search_invoke(C, op, event); + } +} + +static void collection_scene_collection_itemf_recursive( + EnumPropertyItem *tmp, EnumPropertyItem **item, int *totitem, int *value, SceneCollection *sc) +{ + tmp->value = *value; + tmp->icon = ICON_COLLAPSEMENU; + tmp->identifier = sc->name; + tmp->name = sc->name; + RNA_enum_item_add(item, totitem, tmp); + + (*value)++; + + for (SceneCollection *ncs = sc->scene_collections.first; ncs; ncs = ncs->next) { + collection_scene_collection_itemf_recursive(tmp, item, totitem, value, ncs); + } +} + +static const EnumPropertyItem *collection_scene_collection_itemf( + bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +{ + EnumPropertyItem tmp = {0, "", 0, "", ""}; + EnumPropertyItem *item = NULL; + int value = 0, totitem = 0; + + Scene *scene = CTX_data_scene(C); + SceneCollection *sc = BKE_collection_master(scene); + + collection_scene_collection_itemf_recursive(&tmp, &item, &totitem, &value, sc); + RNA_enum_item_end(&item, &totitem); + *r_free = true; + + return item; +} + +void OUTLINER_OT_collection_link(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Add Collection"; + ot->idname = "OUTLINER_OT_collection_link"; + ot->description = "Link a new collection to the active layer"; + + /* api callbacks */ + ot->exec = collection_link_exec; + ot->invoke = collection_link_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + prop = RNA_def_enum(ot->srna, "scene_collection", DummyRNA_NULL_items, 0, "Scene Collection", ""); + RNA_def_enum_funcs(prop, collection_scene_collection_itemf); + RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE); + ot->prop = prop; +} + +/** + * Returns true if selected element is a collection directly + * linked to the active SceneLayer (not a nested collection) + */ +static int collection_unlink_poll(bContext *C) +{ + LayerCollection *lc = outliner_collection_active(C); + + if (lc == NULL) { + return 0; + } + + SceneLayer *sl = CTX_data_scene_layer(C); + return BLI_findindex(&sl->layer_collections, lc) != -1 ? 1 : 0; +} + +static int collection_unlink_exec(bContext *C, wmOperator *op) +{ + LayerCollection *lc = outliner_collection_active(C); + SpaceOops *soops = CTX_wm_space_outliner(C); + + if (lc == NULL) { + BKE_report(op->reports, RPT_ERROR, "Active element is not a collection"); + return OPERATOR_CANCELLED; + } + + SceneLayer *sl = CTX_data_scene_layer(C); + BKE_collection_unlink(sl, lc); + + if (soops) { + outliner_cleanup_tree(soops); + } + + DEG_relations_tag_update(CTX_data_main(C)); + + /* TODO(sergey): Use proper flag for tagging here. */ + DEG_id_tag_update(&CTX_data_scene(C)->id, 0); + + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_collection_unlink(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Collection"; + ot->idname = "OUTLINER_OT_collection_unlink"; + ot->description = "Unlink collection from the active layer"; + + /* api callbacks */ + ot->exec = collection_unlink_exec; + ot->poll = collection_unlink_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int collection_new_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + + SceneCollection *sc = BKE_collection_add(scene, NULL, NULL); + BKE_collection_link(sl, sc); + + DEG_relations_tag_update(CTX_data_main(C)); + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_collection_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "New Collection"; + ot->idname = "OUTLINER_OT_collection_new"; + ot->description = "Add a new collection to the scene, and link it to the active layer"; + + /* api callbacks */ + ot->exec = collection_new_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** + * Returns true is selected element is a collection + */ +static int collection_override_new_poll(bContext *(C)) +{ +#ifdef TODO_LAYER_OVERRIDE + /* disable for now, since it's not implemented */ + (void) C; + return 0; +#else + return outliner_collection_active(C) ? 1 : 0; +#endif +} + +static int collection_override_new_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + TODO_LAYER_OVERRIDE; + BKE_report(op->reports, RPT_ERROR, "OUTLINER_OT_collections_override_new not implemented yet"); + return OPERATOR_CANCELLED; +} + +/* in the middle of renames remove s */ +void OUTLINER_OT_collection_override_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "New Override"; + ot->idname = "OUTLINER_OT_collection_override_new"; + ot->description = "Add a new override to the active collection"; + + /* api callbacks */ + ot->invoke = collection_override_new_invoke; + ot->poll = collection_override_new_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +struct CollectionDeleteData { + Scene *scene; + SpaceOops *soops; +}; + +static TreeTraversalAction collection_delete_cb(TreeElement *te, void *customdata) +{ + struct CollectionDeleteData *data = customdata; + SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te); + + if (!scene_collection) { + return TRAVERSE_SKIP_CHILDS; + } + + if (scene_collection == BKE_collection_master(data->scene)) { + /* skip - showing warning/error message might be missleading + * when deleting multiple collections, so just do nothing */ + } + else { + BKE_collection_remove(data->scene, scene_collection); + } + + return TRAVERSE_CONTINUE; +} + +static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + SpaceOops *soops = CTX_wm_space_outliner(C); + struct CollectionDeleteData data = {.scene = scene, .soops = soops}; + + TODO_LAYER_OVERRIDE; /* handle overrides */ + outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_delete_cb, &data); + + DEG_relations_tag_update(CTX_data_main(C)); + + /* TODO(sergey): Use proper flag for tagging here. */ + DEG_id_tag_update(&scene->id, 0); + + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_collections_delete(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Delete"; + ot->idname = "OUTLINER_OT_collections_delete"; + ot->description = "Delete selected overrides or collections"; + + /* api callbacks */ + ot->exec = collection_delete_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int collection_select_exec(bContext *C, wmOperator *op) +{ + SceneLayer *sl = CTX_data_scene_layer(C); + const int collection_index = RNA_int_get(op->ptr, "collection_index"); + sl->active_collection = collection_index; + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_collection_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select"; + ot->idname = "OUTLINER_OT_collection_select"; + ot->description = "Change active collection or override"; + + /* api callbacks */ + ot->exec = collection_select_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_int(ot->srna, "collection_index", 0, 0, INT_MAX, "Index", + "Index of collection to select", 0, INT_MAX); +} + +#define ACTION_DISABLE 0 +#define ACTION_ENABLE 1 +#define ACTION_TOGGLE 2 + +static int collection_toggle_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + SceneLayer *scene_layer = CTX_data_scene_layer(C); + int action = RNA_enum_get(op->ptr, "action"); + LayerCollection *layer_collection = CTX_data_layer_collection(C); + + if (layer_collection->flag & COLLECTION_DISABLED) { + if (ELEM(action, ACTION_TOGGLE, ACTION_ENABLE)) { + BKE_collection_enable(scene_layer, layer_collection); + } + else { /* ACTION_DISABLE */ + BKE_reportf(op->reports, RPT_ERROR, "Layer collection %s already disabled", + layer_collection->scene_collection->name); + return OPERATOR_CANCELLED; + } + } + else { + if (ELEM(action, ACTION_TOGGLE, ACTION_DISABLE)) { + BKE_collection_disable(scene_layer, layer_collection); + } + else { /* ACTION_ENABLE */ + BKE_reportf(op->reports, RPT_ERROR, "Layer collection %s already enabled", + layer_collection->scene_collection->name); + return OPERATOR_CANCELLED; + } + } + + DEG_relations_tag_update(bmain); + /* TODO(sergey): Use proper flag for tagging here. */ + DEG_id_tag_update(&scene->id, 0); + + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); + + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_collection_toggle(wmOperatorType *ot) +{ + PropertyRNA *prop; + + static EnumPropertyItem actions_items[] = { + {ACTION_DISABLE, "DISABLE", 0, "Disable", "Disable selected markers"}, + {ACTION_ENABLE, "ENABLE", 0, "Enable", "Enable selected markers"}, + {ACTION_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Toggle Collection"; + ot->idname = "OUTLINER_OT_collection_toggle"; + ot->description = "Deselect collection objects"; + + /* api callbacks */ + ot->exec = collection_toggle_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_int(ot->srna, "collection_index", -1, -1, INT_MAX, "Collection Index", "Index of collection to toggle", 0, INT_MAX); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "action", actions_items, ACTION_TOGGLE, "Action", "Selection action to execute"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); +} + +#undef ACTION_TOGGLE +#undef ACTION_ENABLE +#undef ACTION_DISABLE + +/* -------------------------------------------------------------------- */ + +static int stubs_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + BKE_report(op->reports, RPT_ERROR, "Operator not implemented yet"); + return OPERATOR_CANCELLED; +} + +void OUTLINER_OT_collection_objects_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Objects"; + ot->idname = "OUTLINER_OT_collection_objects_add"; + ot->description = "Add selected objects to collection"; + + /* api callbacks */ + ot->invoke = stubs_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +void OUTLINER_OT_collection_objects_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Object"; + ot->idname = "OUTLINER_OT_collection_objects_remove"; + ot->description = "Remove objects from collection"; + + /* api callbacks */ + ot->invoke = stubs_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +void OUTLINER_OT_collection_objects_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Objects"; + ot->idname = "OUTLINER_OT_collection_objects_select"; + ot->description = "Select collection objects"; + + /* api callbacks */ + ot->invoke = stubs_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +void OUTLINER_OT_collection_objects_deselect(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Deselect Objects"; + ot->idname = "OUTLINER_OT_collection_objects_deselect"; + ot->description = "Deselect collection objects"; + + /* api callbacks */ + ot->invoke = stubs_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index d8d6b09ac6b..c9e2a040af4 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -48,9 +48,9 @@ #include "BKE_context.h" #include "BKE_deform.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_modifier.h" @@ -58,6 +58,9 @@ #include "BKE_scene.h" #include "BKE_object.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "ED_armature.h" #include "ED_keyframing.h" #include "ED_object.h" @@ -66,8 +69,7 @@ #include "WM_api.h" #include "WM_types.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" +#include "GPU_immediate.h" #include "UI_interface.h" #include "UI_interface_icons.h" @@ -172,116 +174,6 @@ static void restrictbutton_recursive_bone(Bone *bone_parent, int flag, bool set_ } -static void restrictbutton_recursive_child(bContext *C, Scene *scene, Object *ob_parent, char flag, - bool state, bool deselect, const char *rnapropname) -{ - Main *bmain = CTX_data_main(C); - Object *ob; - - for (ob = bmain->object.first; ob; ob = ob->id.next) { - if (BKE_object_is_child_recursive(ob_parent, ob)) { - /* only do if child object is selectable */ - if ((flag == OB_RESTRICT_SELECT) || (ob->restrictflag & OB_RESTRICT_SELECT) == 0) { - if (state) { - ob->restrictflag |= flag; - if (deselect) { - ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT); - } - } - else { - ob->restrictflag &= ~flag; - } - } - - if (rnapropname) { - PointerRNA ptr; - PropertyRNA *prop; - ID *id; - bAction *action; - FCurve *fcu; - bool driven, special; - - RNA_id_pointer_create(&ob->id, &ptr); - prop = RNA_struct_find_property(&ptr, rnapropname); - fcu = rna_get_fcurve_context_ui(C, &ptr, prop, 0, NULL, &action, &driven, &special); - - if (fcu && !driven) { - id = ptr.id.data; - if (autokeyframe_cfra_can_key(scene, id)) { - ReportList *reports = CTX_wm_reports(C); - ToolSettings *ts = scene->toolsettings; - eInsertKeyFlags key_flag = ANIM_get_keyframing_flags(scene, 1); - - fcu->flag &= ~FCURVE_SELECTED; - insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)), - fcu->rna_path, fcu->array_index, CFRA, ts->keyframe_type, key_flag); - /* Assuming this is not necessary here, since 'ancestor' object button will do it anyway. */ - /* WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); */ - } - } - } - } - } -} - -static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2) -{ - Scene *scene = (Scene *)poin; - Object *ob = (Object *)poin2; - - if (!common_restrict_check(C, ob)) return; - - /* deselect objects that are invisible */ - if (ob->restrictflag & OB_RESTRICT_VIEW) { - /* Ouch! There is no backwards pointer from Object to Base, - * so have to do loop to find it. */ - ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT); - } - - if (CTX_wm_window(C)->eventstate->ctrl) { - restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_VIEW, - (ob->restrictflag & OB_RESTRICT_VIEW) != 0, true, "hide"); - } - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - -} - -static void restrictbutton_sel_cb(bContext *C, void *poin, void *poin2) -{ - Scene *scene = (Scene *)poin; - Object *ob = (Object *)poin2; - - if (!common_restrict_check(C, ob)) return; - - /* if select restriction has just been turned on */ - if (ob->restrictflag & OB_RESTRICT_SELECT) { - /* Ouch! There is no backwards pointer from Object to Base, - * so have to do loop to find it. */ - ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT); - } - - if (CTX_wm_window(C)->eventstate->ctrl) { - restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_SELECT, - (ob->restrictflag & OB_RESTRICT_SELECT) != 0, true, NULL); - } - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - -} - -static void restrictbutton_rend_cb(bContext *C, void *poin, void *poin2) -{ - Object *ob = (Object *)poin2; - - if (CTX_wm_window(C)->eventstate->ctrl) { - restrictbutton_recursive_child(C, (Scene *)poin, ob, OB_RESTRICT_RENDER, - (ob->restrictflag & OB_RESTRICT_RENDER) != 0, false, "hide_render"); - } - - WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, poin); -} - static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *UNUSED(poin2)) { WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, poin); @@ -291,7 +183,7 @@ static void restrictbutton_modifier_cb(bContext *C, void *UNUSED(poin), void *po { Object *ob = (Object *)poin2; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); } @@ -355,96 +247,38 @@ static void restrictbutton_gp_layer_flag_cb(bContext *C, void *UNUSED(poin), voi WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } -static int group_restrict_flag(Group *gr, int flag) +static void enablebutton_collection_flag_cb(bContext *C, void *poin, void *poin2) { - GroupObject *gob; - -#ifdef USE_GROUP_SELECT - for (gob = gr->gobject.first; gob; gob = gob->next) { - if ((gob->ob->restrictflag & flag) == 0) - return 0; - } - return 1; -#else - /* weak but fast */ - if ((gob = gr->gobject.first)) - if ((gob->ob->restrictflag & flag) == 0) - return 0; - return 1; -#endif -} - -static int group_select_flag(Group *gr) -{ - GroupObject *gob; - -#ifdef USE_GROUP_SELECT - for (gob = gr->gobject.first; gob; gob = gob->next) - if ((gob->ob->flag & SELECT)) - return 1; - - return 0; -#else - /* weak but fast */ - if ((gob = gr->gobject.first)) - if (gob->ob->flag & SELECT) - return 1; - return 0; -#endif -} - -void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag) -{ - Scene *scene = (Scene *)poin; - GroupObject *gob; - Group *gr = (Group *)poin2; + Main *bmain = CTX_data_main(C); + Scene *scene = poin; + LayerCollection *layer_collection = poin2; + SceneLayer *scene_layer = BKE_scene_layer_find_from_collection(scene, layer_collection); - if (group_restrict_flag(gr, flag)) { - for (gob = gr->gobject.first; gob; gob = gob->next) { - if (ID_IS_LINKED(gob->ob)) - continue; + /* We need to toggle the flag since this is called after the flag is already set. */ + layer_collection->flag ^= COLLECTION_DISABLED; - gob->ob->restrictflag &= ~flag; - - if (flag == OB_RESTRICT_VIEW) - if (gob->ob->flag & SELECT) - ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_DESELECT); - } + if (layer_collection->flag & COLLECTION_DISABLED) { + BKE_collection_enable(scene_layer, layer_collection); } else { - for (gob = gr->gobject.first; gob; gob = gob->next) { - if (ID_IS_LINKED(gob->ob)) - continue; - - /* not in editmode */ - if (scene->obedit != gob->ob) { - gob->ob->restrictflag |= flag; - - if (ELEM(flag, OB_RESTRICT_SELECT, OB_RESTRICT_VIEW)) { - if ((gob->ob->flag & SELECT)) { - ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_DESELECT); - } - } - } - } + BKE_collection_disable(scene_layer, layer_collection); } -} -static void restrictbutton_gr_restrict_view(bContext *C, void *poin, void *poin2) -{ - restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_VIEW); - WM_event_add_notifier(C, NC_GROUP, NULL); - DAG_id_type_tag(CTX_data_main(C), ID_OB); -} -static void restrictbutton_gr_restrict_select(bContext *C, void *poin, void *poin2) -{ - restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_SELECT); - WM_event_add_notifier(C, NC_GROUP, NULL); + DEG_relations_tag_update(bmain); + /* TODO(sergey): Use proper flag for tagging here. */ + DEG_id_tag_update(&scene->id, 0); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, NULL); } -static void restrictbutton_gr_restrict_render(bContext *C, void *poin, void *poin2) + +static void restrictbutton_collection_flag_cb(bContext *C, void *poin, void *UNUSED(poin2)) { - restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_RENDER); - WM_event_add_notifier(C, NC_GROUP, NULL); + Scene *scene = poin; + /* hide and deselect bases that are directly influenced by this LayerCollection */ + /* TODO(sergey): Use proper flag for tagging here. */ + DEG_id_tag_update(&scene->id, 0); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, NULL); } static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void *UNUSED(poin2)) @@ -466,6 +300,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) { SpaceOops *soops = CTX_wm_space_outliner(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); BLI_mempool *ts = soops->treestore; TreeStoreElem *tselem = tsep; @@ -527,7 +362,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) BLI_strncpy(newname, ebone->name, sizeof(ebone->name)); BLI_strncpy(ebone->name, oldname, sizeof(ebone->name)); ED_armature_bone_rename(obedit->data, oldname, newname); - WM_event_add_notifier(C, NC_OBJECT | ND_POSE, OBACT); + WM_event_add_notifier(C, NC_OBJECT | ND_POSE, OBACT(sl)); } break; } @@ -539,8 +374,8 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) char newname[sizeof(bone->name)]; /* always make current object active */ - tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, true); - ob = OBACT; + tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NORMAL, true); + ob = OBACT(sl); /* restore bone name */ BLI_strncpy(newname, bone->name, sizeof(bone->name)); @@ -556,8 +391,8 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) char newname[sizeof(pchan->name)]; /* always make current pose-bone active */ - tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, true); - ob = OBACT; + tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NORMAL, true); + ob = OBACT(sl); BLI_assert(ob->type == OB_ARMATURE); @@ -591,6 +426,13 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) } case TSE_R_LAYER: break; + case TSE_SCENE_COLLECTION: + case TSE_LAYER_COLLECTION: + { + SceneCollection *sc = outliner_scene_collection_from_tree_element(te); + BKE_collection_rename(scene, sc, te->name); + break; + } } } tselem->flag &= ~TSE_TEXTBUT; @@ -603,8 +445,8 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar TreeElement *te; TreeStoreElem *tselem; Object *ob = NULL; - Group *gr = NULL; +#if 0 PropertyRNA *object_prop_hide, *object_prop_hide_select, *object_prop_hide_render; /* get RNA properties (once) */ @@ -612,81 +454,17 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar object_prop_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select"); object_prop_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render"); BLI_assert(object_prop_hide && object_prop_hide_select && object_prop_hide_render); +#endif for (te = lb->first; te; te = te->next) { tselem = TREESTORE(te); if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { - /* objects have toggle-able restriction flags */ - if (tselem->type == 0 && te->idcode == ID_OB) { - PointerRNA ptr; - - ob = (Object *)tselem->id; - RNA_pointer_create((ID *)ob, &RNA_Object, ob, &ptr); - - UI_block_emboss_set(block, UI_EMBOSS_NONE); - bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, - &ptr, object_prop_hide, -1, 0, 0, -1, -1, - TIP_("Restrict viewport visibility (Ctrl - Recursive)")); - UI_but_func_set(bt, restrictbutton_view_cb, scene, ob); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - - bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y, - &ptr, object_prop_hide_select, -1, 0, 0, -1, -1, - TIP_("Restrict viewport selection (Ctrl - Recursive)")); - UI_but_func_set(bt, restrictbutton_sel_cb, scene, ob); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - - bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y, - &ptr, object_prop_hide_render, -1, 0, 0, -1, -1, - TIP_("Restrict rendering (Ctrl - Recursive)")); - UI_but_func_set(bt, restrictbutton_rend_cb, scene, ob); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - - UI_block_emboss_set(block, UI_EMBOSS); - - } - if (tselem->type == 0 && te->idcode == ID_GR) { - int restrict_bool; - int but_flag = UI_BUT_DRAG_LOCK; - gr = (Group *)tselem->id; - - if (ID_IS_LINKED(gr)) - but_flag |= UI_BUT_DISABLED; - - UI_block_emboss_set(block, UI_EMBOSS_NONE); - - restrict_bool = group_restrict_flag(gr, OB_RESTRICT_VIEW); - bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Restrict/Allow visibility in the 3D View")); - UI_but_func_set(bt, restrictbutton_gr_restrict_view, scene, gr); - UI_but_flag_enable(bt, but_flag); - - restrict_bool = group_restrict_flag(gr, OB_RESTRICT_SELECT); - bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Restrict/Allow selection in the 3D View")); - UI_but_func_set(bt, restrictbutton_gr_restrict_select, scene, gr); - UI_but_flag_enable(bt, but_flag); - - restrict_bool = group_restrict_flag(gr, OB_RESTRICT_RENDER); - bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Restrict/Allow renderability")); - UI_but_func_set(bt, restrictbutton_gr_restrict_render, scene, gr); - UI_but_flag_enable(bt, but_flag); - - UI_block_emboss_set(block, UI_EMBOSS); - } /* scene render layers and passes have toggle-able flags too! */ - else if (tselem->type == TSE_R_LAYER) { + if (tselem->type == TSE_R_LAYER) { UI_block_emboss_set(block, UI_EMBOSS_NONE); - bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT - 1, + bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, SCENE_LAYER_RENDER, 0, ICON_CHECKBOX_HLT - 1, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, te->directdata, 0, 0, 0, 0, TIP_("Render this RenderLayer")); UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL); @@ -805,6 +583,37 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar UI_block_emboss_set(block, UI_EMBOSS); } + else if (tselem->type == TSE_LAYER_COLLECTION) { + LayerCollection *collection = te->directdata; + + const bool is_enabled = (collection->flag & COLLECTION_DISABLED) == 0; + + UI_block_emboss_set(block, UI_EMBOSS_NONE); + + bt = uiDefIconButBitS(block, UI_BTYPE_BUT_TOGGLE, COLLECTION_DISABLED, 0, + is_enabled ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_ENABLEX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &collection->flag, 0, 0, 0, 0, + TIP_("Enable/Disable collection from depsgraph")); + UI_but_func_set(bt, enablebutton_collection_flag_cb, scene, collection); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + + bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_VISIBLE, 0, ICON_RESTRICT_VIEW_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &collection->flag, 0, 0, 0, 0, + TIP_("Restrict/Allow 3D View visibility of objects in the collection")); + UI_but_func_set(bt, restrictbutton_collection_flag_cb, scene, collection); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + + bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_SELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &collection->flag, 0, 0, 0, 0, + TIP_("Restrict/Allow 3D View selection of objects in the collection")); + UI_but_func_set(bt, restrictbutton_collection_flag_cb, scene, collection); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + + UI_block_emboss_set(block, UI_EMBOSS); + } } if (TSELEM_OPEN(tselem, soops)) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree); @@ -878,18 +687,23 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex) float miny = v2d->cur.ymin; if (miny < v2d->tot.ymin) miny = v2d->tot.ymin; - UI_ThemeColorShadeAlpha(TH_BACK, -15, -200); + glLineWidth(1.0f); - /* draw column separator lines */ - fdrawline((float)sizex, - v2d->cur.ymax, - (float)sizex, - miny); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColorShadeAlpha(TH_BACK, -15, -200); - fdrawline((float)sizex + OL_RNA_COL_SIZEX, - v2d->cur.ymax, - (float)sizex + OL_RNA_COL_SIZEX, - miny); + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, sizex, v2d->cur.ymax); + immVertex2f(pos, sizex, miny); + + immVertex2f(pos, sizex + OL_RNA_COL_SIZEX, v2d->cur.ymax); + immVertex2f(pos, sizex + OL_RNA_COL_SIZEX, miny); + + immEnd(); + + immUnbindProgram(); } static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOops *soops, int sizex, ListBase *lb) @@ -987,7 +801,7 @@ static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon) /* restrict column clip... it has been coded by simply overdrawing, doesnt work for buttons */ if (arg->x >= arg->xmax) { glEnable(GL_BLEND); - UI_icon_draw_aspect(arg->x, arg->y, icon, 1.0f / UI_DPI_FAC, arg->alpha); + UI_icon_draw_alpha(arg->x, arg->y, icon, arg->alpha); glDisable(GL_BLEND); } else { @@ -1047,7 +861,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto arg.xb = x; /* for ui buttons */ arg.yb = y; arg.alpha = alpha; - + /* placement of icons, copied from interface_widgets.c */ aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT; x += 2.0f * aspect; @@ -1055,184 +869,253 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto arg.x = x; arg.y = y; +#define ICON_DRAW(_icon) UI_icon_draw_alpha(x, y, _icon, alpha) + if (tselem->type) { switch (tselem->type) { case TSE_ANIM_DATA: - UI_icon_draw(x, y, ICON_ANIM_DATA); break; // xxx + ICON_DRAW(ICON_ANIM_DATA); /* XXX */ + break; case TSE_NLA: - UI_icon_draw(x, y, ICON_NLA); break; + ICON_DRAW(ICON_NLA); + break; case TSE_NLA_TRACK: - UI_icon_draw(x, y, ICON_NLA); break; // XXX + ICON_DRAW(ICON_NLA); /* XXX */ + break; case TSE_NLA_ACTION: - UI_icon_draw(x, y, ICON_ACTION); break; + ICON_DRAW(ICON_ACTION); + break; case TSE_DRIVER_BASE: - UI_icon_draw(x, y, ICON_DRIVER); break; + ICON_DRAW(ICON_DRIVER); + break; case TSE_DEFGROUP_BASE: - UI_icon_draw(x, y, ICON_GROUP_VERTEX); break; + ICON_DRAW(ICON_GROUP_VERTEX); + break; case TSE_BONE: case TSE_EBONE: - UI_icon_draw(x, y, ICON_BONE_DATA); break; + ICON_DRAW(ICON_BONE_DATA); + break; case TSE_CONSTRAINT_BASE: - UI_icon_draw(x, y, ICON_CONSTRAINT); break; + ICON_DRAW(ICON_CONSTRAINT); + break; case TSE_MODIFIER_BASE: - UI_icon_draw(x, y, ICON_MODIFIER); break; + ICON_DRAW(ICON_MODIFIER); + break; case TSE_LINKED_OB: - UI_icon_draw(x, y, ICON_OBJECT_DATA); break; + ICON_DRAW(ICON_OBJECT_DATA); + break; case TSE_LINKED_PSYS: - UI_icon_draw(x, y, ICON_PARTICLES); break; + ICON_DRAW(ICON_PARTICLES); + break; case TSE_MODIFIER: { Object *ob = (Object *)tselem->id; ModifierData *md = BLI_findlink(&ob->modifiers, tselem->nr); switch ((ModifierType)md->type) { - case eModifierType_Subsurf: - UI_icon_draw(x, y, ICON_MOD_SUBSURF); break; - case eModifierType_Armature: - UI_icon_draw(x, y, ICON_MOD_ARMATURE); break; - case eModifierType_Lattice: - UI_icon_draw(x, y, ICON_MOD_LATTICE); break; - case eModifierType_Curve: - UI_icon_draw(x, y, ICON_MOD_CURVE); break; - case eModifierType_Build: - UI_icon_draw(x, y, ICON_MOD_BUILD); break; - case eModifierType_Mirror: - UI_icon_draw(x, y, ICON_MOD_MIRROR); break; - case eModifierType_Decimate: - UI_icon_draw(x, y, ICON_MOD_DECIM); break; - case eModifierType_Wave: - UI_icon_draw(x, y, ICON_MOD_WAVE); break; - case eModifierType_Hook: - UI_icon_draw(x, y, ICON_HOOK); break; - case eModifierType_Softbody: - UI_icon_draw(x, y, ICON_MOD_SOFT); break; - case eModifierType_Boolean: - UI_icon_draw(x, y, ICON_MOD_BOOLEAN); break; - case eModifierType_ParticleSystem: - UI_icon_draw(x, y, ICON_MOD_PARTICLES); break; + case eModifierType_Subsurf: + ICON_DRAW(ICON_MOD_SUBSURF); + break; + case eModifierType_Armature: + ICON_DRAW(ICON_MOD_ARMATURE); + break; + case eModifierType_Lattice: + ICON_DRAW(ICON_MOD_LATTICE); + break; + case eModifierType_Curve: + ICON_DRAW(ICON_MOD_CURVE); + break; + case eModifierType_Build: + ICON_DRAW(ICON_MOD_BUILD); + break; + case eModifierType_Mirror: + ICON_DRAW(ICON_MOD_MIRROR); + break; + case eModifierType_Decimate: + ICON_DRAW(ICON_MOD_DECIM); + break; + case eModifierType_Wave: + ICON_DRAW(ICON_MOD_WAVE); + break; + case eModifierType_Hook: + ICON_DRAW(ICON_HOOK); + break; + case eModifierType_Softbody: + ICON_DRAW(ICON_MOD_SOFT); + break; + case eModifierType_Boolean: + ICON_DRAW(ICON_MOD_BOOLEAN); + break; + case eModifierType_ParticleSystem: + ICON_DRAW(ICON_MOD_PARTICLES); + break; case eModifierType_ParticleInstance: - UI_icon_draw(x, y, ICON_MOD_PARTICLES); break; + ICON_DRAW(ICON_MOD_PARTICLES); + break; case eModifierType_EdgeSplit: - UI_icon_draw(x, y, ICON_MOD_EDGESPLIT); break; + ICON_DRAW(ICON_MOD_EDGESPLIT); + break; case eModifierType_Array: - UI_icon_draw(x, y, ICON_MOD_ARRAY); break; + ICON_DRAW(ICON_MOD_ARRAY); + break; case eModifierType_UVProject: case eModifierType_UVWarp: /* TODO, get own icon */ - UI_icon_draw(x, y, ICON_MOD_UVPROJECT); break; + ICON_DRAW(ICON_MOD_UVPROJECT); + break; case eModifierType_Displace: - UI_icon_draw(x, y, ICON_MOD_DISPLACE); break; + ICON_DRAW(ICON_MOD_DISPLACE); + break; case eModifierType_Shrinkwrap: - UI_icon_draw(x, y, ICON_MOD_SHRINKWRAP); break; + ICON_DRAW(ICON_MOD_SHRINKWRAP); + break; case eModifierType_Cast: - UI_icon_draw(x, y, ICON_MOD_CAST); break; + ICON_DRAW(ICON_MOD_CAST); + break; case eModifierType_MeshDeform: case eModifierType_SurfaceDeform: - UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; + ICON_DRAW(ICON_MOD_MESHDEFORM); + break; case eModifierType_Bevel: - UI_icon_draw(x, y, ICON_MOD_BEVEL); break; + ICON_DRAW(ICON_MOD_BEVEL); + break; case eModifierType_Smooth: case eModifierType_LaplacianSmooth: case eModifierType_CorrectiveSmooth: - UI_icon_draw(x, y, ICON_MOD_SMOOTH); break; + ICON_DRAW(ICON_MOD_SMOOTH); + break; case eModifierType_SimpleDeform: - UI_icon_draw(x, y, ICON_MOD_SIMPLEDEFORM); break; + ICON_DRAW(ICON_MOD_SIMPLEDEFORM); + break; case eModifierType_Mask: - UI_icon_draw(x, y, ICON_MOD_MASK); break; + ICON_DRAW(ICON_MOD_MASK); + break; case eModifierType_Cloth: - UI_icon_draw(x, y, ICON_MOD_CLOTH); break; + ICON_DRAW(ICON_MOD_CLOTH); + break; case eModifierType_Explode: - UI_icon_draw(x, y, ICON_MOD_EXPLODE); break; + ICON_DRAW(ICON_MOD_EXPLODE); + break; case eModifierType_Collision: case eModifierType_Surface: - UI_icon_draw(x, y, ICON_MOD_PHYSICS); break; + ICON_DRAW(ICON_MOD_PHYSICS); + break; case eModifierType_Fluidsim: - UI_icon_draw(x, y, ICON_MOD_FLUIDSIM); break; + ICON_DRAW(ICON_MOD_FLUIDSIM); + break; case eModifierType_Multires: - UI_icon_draw(x, y, ICON_MOD_MULTIRES); break; + ICON_DRAW(ICON_MOD_MULTIRES); + break; case eModifierType_Smoke: - UI_icon_draw(x, y, ICON_MOD_SMOKE); break; + ICON_DRAW(ICON_MOD_SMOKE); + break; case eModifierType_Solidify: - UI_icon_draw(x, y, ICON_MOD_SOLIDIFY); break; + ICON_DRAW(ICON_MOD_SOLIDIFY); + break; case eModifierType_Screw: - UI_icon_draw(x, y, ICON_MOD_SCREW); break; + ICON_DRAW(ICON_MOD_SCREW); + break; case eModifierType_Remesh: - UI_icon_draw(x, y, ICON_MOD_REMESH); break; + ICON_DRAW(ICON_MOD_REMESH); + break; case eModifierType_WeightVGEdit: case eModifierType_WeightVGMix: case eModifierType_WeightVGProximity: - UI_icon_draw(x, y, ICON_MOD_VERTEX_WEIGHT); break; + ICON_DRAW(ICON_MOD_VERTEX_WEIGHT); + break; case eModifierType_DynamicPaint: - UI_icon_draw(x, y, ICON_MOD_DYNAMICPAINT); break; + ICON_DRAW(ICON_MOD_DYNAMICPAINT); + break; case eModifierType_Ocean: - UI_icon_draw(x, y, ICON_MOD_OCEAN); break; + ICON_DRAW(ICON_MOD_OCEAN); + break; case eModifierType_Warp: - UI_icon_draw(x, y, ICON_MOD_WARP); break; + ICON_DRAW(ICON_MOD_WARP); + break; case eModifierType_Skin: - UI_icon_draw(x, y, ICON_MOD_SKIN); break; + ICON_DRAW(ICON_MOD_SKIN); + break; case eModifierType_Triangulate: - UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break; + ICON_DRAW(ICON_MOD_TRIANGULATE); + break; case eModifierType_MeshCache: - UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */ + ICON_DRAW(ICON_MOD_MESHDEFORM); /* XXX, needs own icon */ + break; case eModifierType_MeshSequenceCache: - UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */ + ICON_DRAW(ICON_MOD_MESHDEFORM); /* XXX, needs own icon */ + break; case eModifierType_Wireframe: - UI_icon_draw(x, y, ICON_MOD_WIREFRAME); break; + ICON_DRAW(ICON_MOD_WIREFRAME); + break; case eModifierType_LaplacianDeform: - UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */ + ICON_DRAW(ICON_MOD_MESHDEFORM); /* XXX, needs own icon */ + break; case eModifierType_DataTransfer: - UI_icon_draw(x, y, ICON_MOD_DATA_TRANSFER); break; + ICON_DRAW(ICON_MOD_DATA_TRANSFER); + break; case eModifierType_NormalEdit: - UI_icon_draw(x, y, ICON_MOD_NORMALEDIT); break; + ICON_DRAW(ICON_MOD_NORMALEDIT); + break; /* Default */ case eModifierType_None: case eModifierType_ShapeKey: case NUM_MODIFIER_TYPES: - UI_icon_draw(x, y, ICON_DOT); break; + ICON_DRAW(ICON_DOT); + break; } break; } case TSE_POSE_BASE: - UI_icon_draw(x, y, ICON_ARMATURE_DATA); break; + ICON_DRAW(ICON_ARMATURE_DATA); + break; case TSE_POSE_CHANNEL: - UI_icon_draw(x, y, ICON_BONE_DATA); break; + ICON_DRAW(ICON_BONE_DATA); + break; case TSE_PROXY: - UI_icon_draw(x, y, ICON_GHOST); break; + ICON_DRAW(ICON_GHOST); + break; case TSE_R_LAYER_BASE: - UI_icon_draw(x, y, ICON_RENDERLAYERS); break; + ICON_DRAW(ICON_RENDERLAYERS); + break; case TSE_R_LAYER: - UI_icon_draw(x, y, ICON_RENDERLAYERS); break; + ICON_DRAW(ICON_RENDERLAYERS); + break; case TSE_LINKED_LAMP: - UI_icon_draw(x, y, ICON_LAMP_DATA); break; + ICON_DRAW(ICON_LAMP_DATA); + break; case TSE_LINKED_MAT: - UI_icon_draw(x, y, ICON_MATERIAL_DATA); break; + ICON_DRAW(ICON_MATERIAL_DATA); + break; case TSE_POSEGRP_BASE: - UI_icon_draw(x, y, ICON_GROUP_BONE); break; + ICON_DRAW(ICON_GROUP_BONE); + break; case TSE_SEQUENCE: if (te->idcode == SEQ_TYPE_MOVIE) - UI_icon_draw(x, y, ICON_SEQUENCE); + ICON_DRAW(ICON_SEQUENCE); else if (te->idcode == SEQ_TYPE_META) - UI_icon_draw(x, y, ICON_DOT); + ICON_DRAW(ICON_DOT); else if (te->idcode == SEQ_TYPE_SCENE) - UI_icon_draw(x, y, ICON_SCENE); + ICON_DRAW(ICON_SCENE); else if (te->idcode == SEQ_TYPE_SOUND_RAM) - UI_icon_draw(x, y, ICON_SOUND); + ICON_DRAW(ICON_SOUND); else if (te->idcode == SEQ_TYPE_IMAGE) - UI_icon_draw(x, y, ICON_IMAGE_COL); + ICON_DRAW(ICON_IMAGE_COL); else - UI_icon_draw(x, y, ICON_PARTICLES); + ICON_DRAW(ICON_PARTICLES); break; case TSE_SEQ_STRIP: - UI_icon_draw(x, y, ICON_LIBRARY_DATA_DIRECT); + ICON_DRAW(ICON_LIBRARY_DATA_DIRECT); break; case TSE_SEQUENCE_DUP: - UI_icon_draw(x, y, ICON_OBJECT_DATA); + ICON_DRAW(ICON_OBJECT_DATA); break; case TSE_RNA_STRUCT: if (RNA_struct_is_ID(te->rnaptr.type)) { arg.id = (ID *)te->rnaptr.data; tselem_draw_icon_uibut(&arg, RNA_struct_ui_icon(te->rnaptr.type)); } - else - UI_icon_draw(x, y, RNA_struct_ui_icon(te->rnaptr.type)); + else { + int icon = RNA_struct_ui_icon(te->rnaptr.type); + ICON_DRAW(icon); + } break; /* Removed the icons from outliner. Need a better structure with Layers, Palettes and Colors */ #if 0 @@ -1241,7 +1124,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto break; #endif default: - UI_icon_draw(x, y, ICON_DOT); break; + ICON_DRAW(ICON_DOT); + break; } } else if (tselem->id) { @@ -1351,17 +1235,18 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto } } } + +#undef ICON_DRAW } -static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SpaceOops *soops, ListBase *lb, int level, - int xmax, int *offsx, int ys) +static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SceneLayer *sl, SpaceOops *soops, + ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac) { TreeElement *te; TreeStoreElem *tselem; eOLDrawState active; for (te = lb->first; te; te = te->next) { - /* exit drawing early */ if ((*offsx) - UI_UNIT_X > xmax) break; @@ -1374,34 +1259,38 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa /* active blocks get white circle */ if (tselem->type == 0) { if (te->idcode == ID_OB) { - active = (OBACT == (Object *)tselem->id) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE; + active = (OBACT(sl) == (Object *)tselem->id) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE; } else if (scene->obedit && scene->obedit->data == tselem->id) { active = OL_DRAWSEL_NORMAL; } else { - active = tree_element_active(C, scene, soops, te, OL_SETSEL_NONE, false); + active = tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NONE, false); } } else { - active = tree_element_type_active(NULL, scene, soops, te, tselem, OL_SETSEL_NONE, false); + active = tree_element_type_active(C, scene, sl, soops, te, tselem, OL_SETSEL_NONE, false); } if (active != OL_DRAWSEL_NONE) { float ufac = UI_UNIT_X / 20.0f; + float color[4] = {1.0f, 1.0f, 1.0f, 0.4f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); - glColor4ub(255, 255, 255, 100); - UI_draw_roundbox( + color[3] *= alpha_fac; + + UI_draw_roundbox_aa( + true, (float) *offsx + 1.0f * ufac, (float)ys + 1.0f * ufac, (float)*offsx + UI_UNIT_X - 1.0f * ufac, (float)ys + UI_UNIT_Y - ufac, - (float)UI_UNIT_Y / 2.0f - ufac); + (float)UI_UNIT_Y / 2.0f - ufac, + color); glEnable(GL_BLEND); /* roundbox disables */ } - tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f); + tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f * alpha_fac); te->xs = *offsx; te->ys = ys; te->xend = (short)*offsx + UI_UNIT_X; @@ -1412,7 +1301,7 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa /* this tree element always has same amount of branches, so don't draw */ if (tselem->type != TSE_R_LAYER) - outliner_draw_iconrow(C, block, scene, soops, &te->subtree, level + 1, xmax, offsx, ys); + outliner_draw_iconrow(C, block, scene, sl, soops, &te->subtree, level + 1, xmax, offsx, ys, alpha_fac); } } @@ -1421,11 +1310,14 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa static void outliner_set_coord_tree_element(TreeElement *te, int startx, int starty) { TreeElement *ten; - - /* store coord and continue, we need coordinates for elements outside view too */ - te->xs = startx; - te->ys = starty; - + + /* closed items may be displayed in row of parent, don't change their coordinate! */ + if ((te->flag & TE_ICONROW) == 0) { + /* store coord and continue, we need coordinates for elements outside view too */ + te->xs = startx; + te->ys = starty; + } + for (ten = te->subtree.first; ten; ten = ten->next) { outliner_set_coord_tree_element(ten, startx + UI_UNIT_X, starty); } @@ -1433,24 +1325,28 @@ static void outliner_set_coord_tree_element(TreeElement *te, int startx, int sta static void outliner_draw_tree_element( - bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ARegion *ar, SpaceOops *soops, - TreeElement *te, int startx, int *starty, TreeElement **te_edit) + bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, SceneLayer *sl, + ARegion *ar, SpaceOops *soops, TreeElement *te, bool draw_grayed_out, + int startx, int *starty, TreeElement **te_edit, TreeElement **te_floating) { - TreeElement *ten; TreeStoreElem *tselem; float ufac = UI_UNIT_X / 20.0f; int offsx = 0; eOLDrawState active = OL_DRAWSEL_NONE; - + float color[4]; tselem = TREESTORE(te); if (*starty + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) { + const float alpha_fac = draw_grayed_out ? 0.5f : 1.0f; + const float alpha = 0.5f * alpha_fac; int xmax = ar->v2d.cur.xmax; - unsigned char alpha = 128; - + if ((tselem->flag & TSE_TEXTBUT) && (*te_edit == NULL)) { *te_edit = te; } + if ((te->drag_data != NULL) && (*te_floating == NULL)) { + *te_floating = te; + } /* icons can be ui buts, we don't want it to overlap with restrict */ if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0) @@ -1458,50 +1354,24 @@ static void outliner_draw_tree_element( glEnable(GL_BLEND); - /* start by highlighting search matches - * we don't expand items when searching in the datablocks but we - * still want to highlight any filter matches. - */ - if ((SEARCHING_OUTLINER(soops) || (soops->outlinevis == SO_DATABLOCKS && soops->search_string[0] != 0)) && - (tselem->flag & TSE_SEARCHMATCH)) - { - char col[4]; - UI_GetThemeColorType4ubv(TH_MATCH, SPACE_OUTLINER, col); - col[3] = alpha; - glColor4ubv((GLubyte *)col); - glRecti(startx, *starty + 1, ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1); - } - /* colors for active/selected data */ if (tselem->type == 0) { - if (te->idcode == ID_SCE) { if (tselem->id == (ID *)scene) { - glColor4ub(255, 255, 255, alpha); - active = OL_DRAWSEL_ACTIVE; - } - } - else if (te->idcode == ID_GR) { - Group *gr = (Group *)tselem->id; - if (group_select_flag(gr)) { - char col[4]; - UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col); - col[3] = alpha; - glColor4ubv((GLubyte *)col); - + rgba_float_args_set(color, 1.0f, 1.0f, 1.0f, alpha); active = OL_DRAWSEL_ACTIVE; } } else if (te->idcode == ID_OB) { Object *ob = (Object *)tselem->id; - if (ob == OBACT || (ob->flag & SELECT)) { + if (ob == OBACT(sl) || (ob->flag & SELECT)) { char col[4] = {0, 0, 0, 0}; /* outliner active ob: always white text, circle color now similar to view3d */ active = OL_DRAWSEL_ACTIVE; - if (ob == OBACT) { + if (ob == OBACT(sl)) { if (ob->flag & SELECT) { UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col); col[3] = alpha; @@ -1513,38 +1383,36 @@ static void outliner_draw_tree_element( UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col); col[3] = alpha; } - - glColor4ubv((GLubyte *)col); + rgba_float_args_set(color, (float)col[0] / 255, (float)col[1] / 255, (float)col[2] / 255, alpha); } } else if (scene->obedit && scene->obedit->data == tselem->id) { - glColor4ub(255, 255, 255, alpha); + rgba_float_args_set(color, 1.0f, 1.0f, 1.0f, alpha); active = OL_DRAWSEL_ACTIVE; } else { - if (tree_element_active(C, scene, soops, te, OL_SETSEL_NONE, false)) { - glColor4ub(220, 220, 255, alpha); + if (tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NONE, false)) { + rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha); active = OL_DRAWSEL_ACTIVE; } } } else { - if (tree_element_type_active(NULL, scene, soops, te, tselem, OL_SETSEL_NONE, false) != OL_DRAWSEL_NONE) { - active = OL_DRAWSEL_ACTIVE; - } - glColor4ub(220, 220, 255, alpha); + active = tree_element_type_active(C, scene, sl, soops, te, tselem, OL_SETSEL_NONE, false); + rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha); } /* active circle */ if (active != OL_DRAWSEL_NONE) { UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox( + UI_draw_roundbox_aa( + true, (float)startx + UI_UNIT_X + 1.0f * ufac, (float)*starty + 1.0f * ufac, (float)startx + 2.0f * UI_UNIT_X - 1.0f * ufac, (float)*starty + UI_UNIT_Y - 1.0f * ufac, - UI_UNIT_Y / 2.0f - 1.0f * ufac); + UI_UNIT_Y / 2.0f - 1.0f * ufac, color); glEnable(GL_BLEND); /* roundbox disables it */ te->flag |= TE_ACTIVE; // for lookup in display hierarchies @@ -1553,56 +1421,64 @@ static void outliner_draw_tree_element( /* open/close icon, only when sublevels, except for scene */ if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) { int icon_x; - icon_x = startx; - + if (tselem->type == 0 && ELEM(te->idcode, ID_OB, ID_SCE)) + icon_x = startx; + else + icon_x = startx + 5 * ufac; + // icons a bit higher if (TSELEM_OPEN(tselem, soops)) - UI_icon_draw((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_DOWN); + UI_icon_draw_alpha((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_DOWN, + alpha_fac); else - UI_icon_draw((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_RIGHT); + UI_icon_draw_alpha((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_RIGHT, + alpha_fac); } offsx += UI_UNIT_X; /* datatype icon */ if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM))) { - - tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, 1.0f); - + tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac); offsx += UI_UNIT_X + 2 * ufac; } else offsx += 2 * ufac; if (tselem->type == 0 && ID_IS_LINKED(tselem->id)) { - glPixelTransferf(GL_ALPHA_SCALE, 0.5f); if (tselem->id->tag & LIB_TAG_MISSING) { - UI_icon_draw((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN); + UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN, + alpha_fac); } else if (tselem->id->tag & LIB_TAG_INDIRECT) { - UI_icon_draw((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT); + UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT, + alpha_fac); } else { - UI_icon_draw((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT); + UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT, + alpha_fac); } - glPixelTransferf(GL_ALPHA_SCALE, 1.0f); offsx += UI_UNIT_X + 2 * ufac; } glDisable(GL_BLEND); /* name */ if ((tselem->flag & TSE_TEXTBUT) == 0) { + unsigned char text_col[4]; + if (active == OL_DRAWSEL_NORMAL) { - UI_ThemeColor(TH_TEXT_HI); + UI_GetThemeColor4ubv(TH_TEXT_HI, text_col); } else if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { - UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.75f); + UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.75f, text_col); + text_col[3] = 255; } else { - UI_ThemeColor(TH_TEXT); + UI_GetThemeColor4ubv(TH_TEXT, text_col); } + text_col[3] *= alpha_fac; - UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name); + UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name, text_col); } offsx += (int)(UI_UNIT_X + UI_fontstyle_string_width(fstyle, te->name)); @@ -1613,24 +1489,33 @@ static void outliner_draw_tree_element( if (tselem->type == 0 && te->idcode == ID_SCE) { /* pass */ } + /* this tree element always has same amount of branches, so don't draw */ else if (tselem->type != TSE_R_LAYER) { - /* this tree element always has same amount of branches, so don't draw */ - int tempx = startx + offsx; - - /* divider */ - UI_ThemeColorShade(TH_BACK, -40); - glRecti(tempx - 10.0f * ufac, - *starty + 4.0f * ufac, - tempx - 8.0f * ufac, - *starty + UI_UNIT_Y - 4.0f * ufac); - + glEnable(GL_BLEND); - glPixelTransferf(GL_ALPHA_SCALE, 0.5); - - outliner_draw_iconrow(C, block, scene, soops, &te->subtree, 0, xmax, &tempx, *starty); - - glPixelTransferf(GL_ALPHA_SCALE, 1.0); + + /* divider */ + { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + unsigned char col[4]; + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + UI_GetThemeColorShade4ubv(TH_BACK, -40, col); + col[3] *= alpha_fac; + + immUniformColor4ubv(col); + immRecti(pos, tempx - 10.0f * ufac, + *starty + 4.0f * ufac, + tempx - 8.0f * ufac, + *starty + UI_UNIT_Y - 4.0f * ufac); + immUnbindProgram(); + } + + outliner_draw_iconrow(C, block, scene, sl, soops, &te->subtree, 0, xmax, &tempx, + *starty, alpha_fac); + glDisable(GL_BLEND); } } @@ -1640,16 +1525,20 @@ static void outliner_draw_tree_element( te->xs = startx; te->ys = *starty; te->xend = startx + offsx; - + if (TSELEM_OPEN(tselem, soops)) { *starty -= UI_UNIT_Y; - for (ten = te->subtree.first; ten; ten = ten->next) { - outliner_draw_tree_element(C, block, fstyle, scene, ar, soops, ten, startx + UI_UNIT_X, starty, te_edit); + for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) { + /* check if element needs to be drawn grayed out, but also gray out + * childs of a grayed out parent (pass on draw_grayed_out to childs) */ + bool draw_childs_grayed_out = draw_grayed_out || (ten->drag_data != NULL); + outliner_draw_tree_element(C, block, fstyle, scene, sl, ar, soops, ten, draw_childs_grayed_out, + startx + UI_UNIT_X, starty, te_edit, te_floating); } } else { - for (ten = te->subtree.first; ten; ten = ten->next) { + for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) { outliner_set_coord_tree_element(ten, startx, *starty); } @@ -1657,115 +1546,277 @@ static void outliner_draw_tree_element( } } -static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx, int *starty) +static void outliner_draw_tree_element_floating( + const ARegion *ar, const TreeElement *te_floating) +{ + const TreeElement *te_insert = te_floating->drag_data->insert_handle; + const int line_width = 2; + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + int coord_y = te_insert->ys; + int coord_x = te_insert->xs; + float col[4]; + + if (te_insert == te_floating) { + /* don't draw anything */ + return; + } + + UI_GetThemeColorShade4fv(TH_BACK, -40, col); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + glEnable(GL_BLEND); + + if (ELEM(te_floating->drag_data->insert_type, TE_INSERT_BEFORE, TE_INSERT_AFTER)) { + if (te_floating->drag_data->insert_type == TE_INSERT_BEFORE) { + coord_y += UI_UNIT_Y; + } + immUniformColor4fv(col); + glLineWidth(line_width); + + immBegin(GWN_PRIM_LINE_STRIP, 2); + immVertex2f(pos, coord_x, coord_y); + immVertex2f(pos, ar->v2d.cur.xmax, coord_y); + immEnd(); + } + else { + BLI_assert(te_floating->drag_data->insert_type == TE_INSERT_INTO); + immUniformColor3fvAlpha(col, col[3] * 0.5f); + + immBegin(GWN_PRIM_TRI_STRIP, 4); + immVertex2f(pos, coord_x, coord_y + UI_UNIT_Y); + immVertex2f(pos, coord_x, coord_y); + immVertex2f(pos, ar->v2d.cur.xmax, coord_y + UI_UNIT_Y); + immVertex2f(pos, ar->v2d.cur.xmax, coord_y); + immEnd(); + } + + glDisable(GL_BLEND); + immUnbindProgram(); +} + +static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soops, ListBase *lb, int startx, + const unsigned char col[4], bool draw_grayed_out, + int *starty) { TreeElement *te; TreeStoreElem *tselem; int y1, y2; - - if (BLI_listbase_is_empty(lb)) return; - + + if (BLI_listbase_is_empty(lb)) { + return; + } + + const unsigned char grayed_alpha = col[3] / 2; + y1 = y2 = *starty; /* for vertical lines between objects */ for (te = lb->first; te; te = te->next) { + bool draw_childs_grayed_out = draw_grayed_out || (te->drag_data != NULL); y2 = *starty; tselem = TREESTORE(te); - + + if (draw_childs_grayed_out) { + immUniformColor3ubvAlpha(col, grayed_alpha); + } + else { + immUniformColor4ubv(col); + } + /* horizontal line? */ if (tselem->type == 0 && (te->idcode == ID_OB || te->idcode == ID_SCE)) - glRecti(startx, *starty, startx + UI_UNIT_X, *starty - 1); + immRecti(pos, startx, *starty, startx + UI_UNIT_X, *starty - 1); *starty -= UI_UNIT_Y; if (TSELEM_OPEN(tselem, soops)) - outliner_draw_hierarchy(soops, &te->subtree, startx + UI_UNIT_X, starty); + outliner_draw_hierarchy_lines_recursive(pos, soops, &te->subtree, startx + UI_UNIT_X, + col, draw_childs_grayed_out, starty); } - + + if (draw_grayed_out) { + immUniformColor3ubvAlpha(col, grayed_alpha); + } + else { + immUniformColor4ubv(col); + } + /* vertical line */ te = lb->last; if (te->parent || lb->first != lb->last) { tselem = TREESTORE(te); - if (tselem->type == 0 && te->idcode == ID_OB) { - - glRecti(startx, y1 + UI_UNIT_Y, startx + 1, y2); - } + if (tselem->type == 0 && te->idcode == ID_OB) + immRecti(pos, startx, y1 + UI_UNIT_Y, startx + 1, y2); } } +static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int startx, int *starty) +{ + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + unsigned char col[4]; + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.4f, col); + col[3] = 255; + + glEnable(GL_BLEND); + outliner_draw_hierarchy_lines_recursive(pos, soops, lb, startx, col, false, starty); + glDisable(GL_BLEND); + + immUnbindProgram(); +} + static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty) { TreeElement *te; TreeStoreElem *tselem; - + for (te = lb->first; te; te = te->next) { tselem = TREESTORE(te); /* selection status */ if (TSELEM_OPEN(tselem, soops)) - if (tselem->type == TSE_RNA_STRUCT) - glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1); + if (tselem->type == TSE_RNA_STRUCT) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immThemeColorShadeAlpha(TH_BACK, -15, -200); + immRecti(pos, 0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1); + immUnbindProgram(); + } *starty -= UI_UNIT_Y; if (TSELEM_OPEN(tselem, soops)) { outliner_draw_struct_marks(ar, soops, &te->subtree, starty); - if (tselem->type == TSE_RNA_STRUCT) - fdrawline(0, (float)*starty + UI_UNIT_Y, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y); + if (tselem->type == TSE_RNA_STRUCT) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immThemeColorShadeAlpha(TH_BACK, -15, -200); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, 0, (float)*starty + UI_UNIT_Y); + immVertex2f(pos, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y); + immEnd(); + + immUnbindProgram(); + } } } } -static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty) +static void outliner_draw_highlights_recursive( + unsigned pos, const ARegion *ar, const SpaceOops *soops, const ListBase *lb, + const float col_selection[4], const float col_highlight[4], const float col_searchmatch[4], + int start_x, int *io_start_y) { - TreeElement *te; - TreeStoreElem *tselem; - - for (te = lb->first; te; te = te->next) { - tselem = TREESTORE(te); - + const bool is_searching = SEARCHING_OUTLINER(soops) || + (soops->outlinevis == SO_DATABLOCKS && soops->search_string[0] != 0); + + for (TreeElement *te = lb->first; te; te = te->next) { + const TreeStoreElem *tselem = TREESTORE(te); + const int start_y = *io_start_y; + /* selection status */ if (tselem->flag & TSE_SELECTED) { - glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1); + immUniformColor4fv(col_selection); + immRecti(pos, 0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1); + } + + /* search match highlights + * we don't expand items when searching in the datablocks but we + * still want to highlight any filter matches. */ + if (is_searching && (tselem->flag & TSE_SEARCHMATCH)) { + immUniformColor4fv(col_searchmatch); + immRecti(pos, start_x, start_y + 1, ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1); + } + + /* mouse hover highlights */ + if ((tselem->flag & TSE_HIGHLIGHTED) || (te->drag_data != NULL)) { + immUniformColor4fv(col_highlight); + immRecti(pos, 0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1); + } + + *io_start_y -= UI_UNIT_Y; + if (TSELEM_OPEN(tselem, soops)) { + outliner_draw_highlights_recursive( + pos, ar, soops, &te->subtree, col_selection, col_highlight, col_searchmatch, + start_x + UI_UNIT_X, io_start_y); } - *starty -= UI_UNIT_Y; - if (TSELEM_OPEN(tselem, soops)) outliner_draw_selection(ar, soops, &te->subtree, starty); } } +static void outliner_draw_highlights(ARegion *ar, SpaceOops *soops, int startx, int *starty) +{ + const float col_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f}; + float col_selection[4], col_searchmatch[4]; + + UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col_selection); + col_selection[3] = 1.0f; /* no alpha */ + UI_GetThemeColor4fv(TH_MATCH, col_searchmatch); + col_searchmatch[3] = 0.5f; + + glEnable(GL_BLEND); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + outliner_draw_highlights_recursive(pos, ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch, + startx, starty); + immUnbindProgram(); + glDisable(GL_BLEND); +} -static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, - SpaceOops *soops, TreeElement **te_edit) +static void outliner_draw_tree( + bContext *C, uiBlock *block, Scene *scene, SceneLayer *sl, ARegion *ar, + SpaceOops *soops, const bool has_restrict_icons, + TreeElement **te_edit) { const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; - TreeElement *te; + TreeElement *te_floating = NULL; int starty, startx; - float col[3]; - + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // only once - + if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) { /* struct marks */ - UI_ThemeColorShadeAlpha(TH_BACK, -15, -200); - //UI_ThemeColorShade(TH_BACK, -20); starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET; outliner_draw_struct_marks(ar, soops, &soops->tree, &starty); } - - /* always draw selection fill before hierarchy */ - UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col); - glColor3fv(col); + + /* draw highlights before hierarchy */ starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET; - outliner_draw_selection(ar, soops, &soops->tree, &starty); - + startx = 0; + outliner_draw_highlights(ar, soops, startx, &starty); + + /* set scissor so tree elements or lines can't overlap restriction icons */ + GLfloat scissor[4] = {0}; + if (has_restrict_icons) { + int mask_x = BLI_rcti_size_x(&ar->v2d.mask) - (int)OL_TOGW + 1; + CLAMP_MIN(mask_x, 0); + + glGetFloatv(GL_SCISSOR_BOX, scissor); + glScissor(ar->winrct.xmin, ar->winrct.ymin, mask_x, ar->winy); + } + // gray hierarchy lines - UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.4f); - starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET; - startx = UI_UNIT_X / 2 - 1.0f; - outliner_draw_hierarchy(soops, &soops->tree, startx, &starty); + starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET; + startx = 6; + outliner_draw_hierarchy_lines(soops, &soops->tree, startx, &starty); + // items themselves starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET; startx = 0; - for (te = soops->tree.first; te; te = te->next) { - outliner_draw_tree_element(C, block, fstyle, scene, ar, soops, te, startx, &starty, te_edit); + for (TreeElement *te = soops->tree.first; te; te = te->next) { + outliner_draw_tree_element(C, block, fstyle, scene, sl, ar, soops, te, te->drag_data != NULL, + startx, &starty, te_edit, &te_floating); + } + if (te_floating && te_floating->drag_data->insert_handle) { + outliner_draw_tree_element_floating(ar, te_floating); + } + + if (has_restrict_icons) { + /* reset scissor */ + glScissor(UNPACK4(scissor)); } } @@ -1774,53 +1825,60 @@ static void outliner_back(ARegion *ar) { int ystart; - UI_ThemeColorShade(TH_BACK, 6); ystart = (int)ar->v2d.tot.ymax; ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET; - - while (ystart + 2 * UI_UNIT_Y > ar->v2d.cur.ymin) { - glRecti(0, ystart, (int)ar->v2d.cur.xmax, ystart + UI_UNIT_Y); - ystart -= 2 * UI_UNIT_Y; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColorShade(TH_BACK, 6); + + const float x1 = 0.0f, x2 = ar->v2d.cur.xmax; + float y1 = ystart, y2; + int tot = (int)floor(ystart - ar->v2d.cur.ymin + 2 * UI_UNIT_Y) / (2 * UI_UNIT_Y); + + if (tot > 0) { + immBegin(GWN_PRIM_TRIS, 6 * tot); + while (tot--) { + y1 -= 2 * UI_UNIT_Y; + y2 = y1 + UI_UNIT_Y; + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y1); + immVertex2f(pos, x2, y2); + + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x1, y2); + } + immEnd(); } + immUnbindProgram(); } static void outliner_draw_restrictcols(ARegion *ar) { - int ystart; - - /* background underneath */ - UI_ThemeColor(TH_BACK); - glRecti((int)(ar->v2d.cur.xmax - OL_TOGW), - (int)(ar->v2d.cur.ymin - 1), (int)ar->v2d.cur.xmax, (int)ar->v2d.cur.ymax); - - UI_ThemeColorShade(TH_BACK, 6); - ystart = (int)ar->v2d.tot.ymax; - ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET; - - while (ystart + 2 * UI_UNIT_Y > ar->v2d.cur.ymin) { - glRecti((int)ar->v2d.cur.xmax - OL_TOGW, ystart, (int)ar->v2d.cur.xmax, ystart + UI_UNIT_Y); - ystart -= 2 * UI_UNIT_Y; - } - - UI_ThemeColorShadeAlpha(TH_BACK, -15, -200); + glLineWidth(1.0f); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColorShadeAlpha(TH_BACK, -15, -200); + immBegin(GWN_PRIM_LINES, 6); /* view */ - sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), - (int)ar->v2d.cur.ymax, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), - (int)ar->v2d.cur.ymin); + immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymax); + immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymin); /* render */ - sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), - (int)ar->v2d.cur.ymax, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), - (int)ar->v2d.cur.ymin); + immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)ar->v2d.cur.ymax); + immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)ar->v2d.cur.ymin); /* render */ - sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), - (int)ar->v2d.cur.ymax, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), - (int)ar->v2d.cur.ymin); + immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)ar->v2d.cur.ymax); + immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)ar->v2d.cur.ymin); + + immEnd(); + immUnbindProgram(); } /* ****************************************************** */ @@ -1830,14 +1888,16 @@ void draw_outliner(const bContext *C) { Main *mainvar = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); ARegion *ar = CTX_wm_region(C); View2D *v2d = &ar->v2d; SpaceOops *soops = CTX_wm_space_outliner(C); uiBlock *block; int sizey = 0, sizex = 0, sizex_rna = 0; TreeElement *te_edit = NULL; + bool has_restrict_icons; - outliner_build_tree(mainvar, scene, soops); // always + outliner_build_tree(mainvar, scene, sl, soops); // always /* get extents of data */ outliner_height(soops, &soops->tree, &sizey); @@ -1857,6 +1917,7 @@ void draw_outliner(const bContext *C) /* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */ sizex = sizex_rna + OL_RNA_COL_SIZEX + 50; + has_restrict_icons = false; } else { /* width must take into account restriction columns (if visible) so that entries will still be visible */ @@ -1868,7 +1929,8 @@ void draw_outliner(const bContext *C) // XXX this isn't that great yet... if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0) sizex += OL_TOGW * 3; - + + has_restrict_icons = !(soops->flag & SO_HIDE_RESTRICTCOLS); } /* adds vertical offset */ @@ -1885,19 +1947,19 @@ void draw_outliner(const bContext *C) /* draw outliner stuff (background, hierarchy lines and names) */ outliner_back(ar); block = UI_block_begin(C, ar, __func__, UI_EMBOSS); - outliner_draw_tree((bContext *)C, block, scene, ar, soops, &te_edit); + outliner_draw_tree((bContext *)C, block, scene, sl, ar, soops, has_restrict_icons, &te_edit); if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) { /* draw rna buttons */ outliner_draw_rnacols(ar, sizex_rna); outliner_draw_rnabuts(block, ar, soops, sizex_rna, &soops->tree); } - else if ((soops->outlinevis == SO_ID_ORPHANS) && !(soops->flag & SO_HIDE_RESTRICTCOLS)) { + else if ((soops->outlinevis == SO_ID_ORPHANS) && has_restrict_icons) { /* draw user toggle columns */ outliner_draw_restrictcols(ar); outliner_draw_userbuts(block, ar, soops, &soops->tree); } - else if (!(soops->flag & SO_HIDE_RESTRICTCOLS)) { + else if (has_restrict_icons) { /* draw restriction columns */ outliner_draw_restrictcols(ar); outliner_draw_restrictbuts(block, scene, ar, soops, &soops->tree); diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 0b001ca9578..5d0befece0d 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -51,9 +51,9 @@ #include "BKE_animsys.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idcode.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" @@ -64,6 +64,8 @@ #include "BKE_material.h" #include "BKE_group.h" +#include "DEG_depsgraph_build.h" + #include "../blenloader/BLO_readfile.h" #include "ED_object.h" @@ -148,8 +150,46 @@ TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2] return NULL; } + /* ************************************************************** */ -/* Click Activated */ + +/* Highlight --------------------------------------------------- */ + +static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + SpaceOops *soops = CTX_wm_space_outliner(C); + const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]); + + TreeElement *hovered_te = outliner_find_item_at_y(soops, &soops->tree, my); + bool changed = false; + + if (!hovered_te || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED)) { + changed = outliner_set_flag(&soops->tree, TSE_HIGHLIGHTED, false); + if (hovered_te) { + hovered_te->store_elem->flag |= TSE_HIGHLIGHTED; + changed = true; + } + } + + if (changed) { + soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */ + ED_region_tag_redraw(ar); + } + + return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); +} + +void OUTLINER_OT_highlight_update(wmOperatorType *ot) +{ + ot->name = "Update Highlight"; + ot->idname = "OUTLINER_OT_highlight_update"; + ot->description = "Update the item highlight based on the current mouse position"; + + ot->invoke = outliner_highlight_update; + + ot->poll = ED_operator_outliner_active; +} /* Toggle Open/Closed ------------------------------------------- */ @@ -216,8 +256,11 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot) /* Rename --------------------------------------------------- */ -static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, ReportList *reports) +static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, TreeStoreElem *tselem, + ReportList *reports) { + bool add_textbut = false; + /* can't rename rna datablocks entries or listbases */ if (ELEM(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE)) { /* do nothing */; @@ -230,6 +273,18 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, else if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) { BKE_report(reports, RPT_WARNING, "Cannot edit sequence name"); } + else if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) { + SceneCollection *master = BKE_collection_master(scene); + + if ((tselem->type == TSE_SCENE_COLLECTION && te->directdata == master) || + (((LayerCollection *)te->directdata)->scene_collection == master)) + { + BKE_report(reports, RPT_WARNING, "Cannot edit name of master collection"); + } + else { + add_textbut = true; + } + } else if (ID_IS_LINKED(tselem->id)) { BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); } @@ -237,34 +292,39 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library"); } else { + add_textbut = true; + } + + if (add_textbut) { tselem->flag |= TSE_TEXTBUT; ED_region_tag_redraw(ar); } } void item_rename_cb( - bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *te, + bContext *C, ReportList *reports, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { ARegion *ar = CTX_wm_region(C); - do_item_rename(ar, te, tselem, reports); + do_item_rename(scene, ar, te, tselem, reports); } -static int do_outliner_item_rename(ReportList *reports, ARegion *ar, TreeElement *te, const float mval[2]) +static int do_outliner_item_rename(const Scene *scene, ReportList *reports, ARegion *ar, TreeElement *te, + const float mval[2]) { if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) { TreeStoreElem *tselem = TREESTORE(te); /* click on name */ if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) { - do_item_rename(ar, te, tselem, reports); + do_item_rename(scene, ar, te, tselem, reports); return 1; } return 0; } for (te = te->subtree.first; te; te = te->next) { - if (do_outliner_item_rename(reports, ar, te, mval)) return 1; + if (do_outliner_item_rename(scene, reports, ar, te, mval)) return 1; } return 0; } @@ -280,7 +340,7 @@ static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *even UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); for (te = soops->tree.first; te; te = te->next) { - if (do_outliner_item_rename(op->reports, ar, te, fmval)) { + if (do_outliner_item_rename(CTX_data_scene(C), op->reports, ar, te, fmval)) { changed = true; break; } @@ -403,7 +463,6 @@ void OUTLINER_OT_id_delete(wmOperatorType *ot) static int outliner_id_remap_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); SpaceOops *soops = CTX_wm_space_outliner(C); const short id_type = (short)RNA_enum_get(op->ptr, "id_type"); @@ -433,7 +492,7 @@ static int outliner_id_remap_exec(bContext *C, wmOperator *op) BKE_main_lib_objects_recalc_all(bmain); /* recreate dependency graph to include new objects */ - DAG_scene_relations_rebuild(bmain, scene); + DEG_relations_tag_update(bmain); /* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */ GPU_materials_free(); @@ -744,17 +803,34 @@ int outliner_has_one_flag(ListBase *lb, short flag, const int curlevel) return 0; } -void outliner_set_flag(ListBase *lb, short flag, short set) +/** + * Set or unset \a flag for all outliner elements in \a lb and sub-trees. + * \return if any flag was modified. + */ +bool outliner_set_flag(ListBase *lb, short flag, short set) { TreeElement *te; TreeStoreElem *tselem; - + bool changed = false; + bool has_flag; + for (te = lb->first; te; te = te->next) { tselem = TREESTORE(te); - if (set == 0) tselem->flag &= ~flag; - else tselem->flag |= flag; - outliner_set_flag(&te->subtree, flag, set); + has_flag = (tselem->flag & flag); + if (set == 0) { + if (has_flag) { + tselem->flag &= ~flag; + changed = true; + } + } + else if (!has_flag) { + tselem->flag |= flag; + changed = true; + } + changed |= outliner_set_flag(&te->subtree, flag, set); } + + return changed; } /* Restriction Columns ------------------------------- */ @@ -782,181 +858,6 @@ int common_restrict_check(bContext *C, Object *ob) } /* =============================================== */ -/* Restriction toggles */ - -/* Toggle Visibility ---------------------------------------- */ - -void object_toggle_visibility_cb( - bContext *C, ReportList *reports, Scene *scene, TreeElement *te, - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Base *base = (Base *)te->directdata; - Object *ob = (Object *)tselem->id; - - if (ID_IS_LINKED(tselem->id)) { - BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); - return; - } - - /* add check for edit mode */ - if (!common_restrict_check(C, ob)) return; - - if (base || (base = BKE_scene_base_find(scene, ob))) { - if ((base->object->restrictflag ^= OB_RESTRICT_VIEW)) { - ED_base_object_select(base, BA_DESELECT); - } - } -} - -void group_toggle_visibility_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Group *group = (Group *)tselem->id; - restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_VIEW); -} - -static int outliner_toggle_visibility_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - SpaceOops *soops = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); - ARegion *ar = CTX_wm_region(C); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_visibility_cb); - - DAG_id_type_tag(bmain, ID_OB); - WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); - ED_region_tag_redraw(ar); - - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_visibility_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Visibility"; - ot->idname = "OUTLINER_OT_visibility_toggle"; - ot->description = "Toggle the visibility of selected items"; - - /* callbacks */ - ot->exec = outliner_toggle_visibility_exec; - ot->poll = ED_operator_outliner_active_no_editobject; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* Toggle Selectability ---------------------------------------- */ - -void object_toggle_selectability_cb( - bContext *UNUSED(C), ReportList *reports, Scene *scene, TreeElement *te, - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Base *base = (Base *)te->directdata; - - if (ID_IS_LINKED(tselem->id)) { - BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); - return; - } - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base) { - base->object->restrictflag ^= OB_RESTRICT_SELECT; - } -} - -void group_toggle_selectability_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Group *group = (Group *)tselem->id; - restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_SELECT); -} - -static int outliner_toggle_selectability_exec(bContext *C, wmOperator *op) -{ - SpaceOops *soops = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); - ARegion *ar = CTX_wm_region(C); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_selectability_cb); - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - ED_region_tag_redraw(ar); - - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_selectability_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Selectability"; - ot->idname = "OUTLINER_OT_selectability_toggle"; - ot->description = "Toggle the selectability"; - - /* callbacks */ - ot->exec = outliner_toggle_selectability_exec; - ot->poll = ED_operator_outliner_active_no_editobject; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* Toggle Renderability ---------------------------------------- */ - -void object_toggle_renderability_cb( - bContext *UNUSED(C), ReportList *reports, Scene *scene, TreeElement *te, - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Base *base = (Base *)te->directdata; - - if (ID_IS_LINKED(tselem->id)) { - BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); - return; - } - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base) { - base->object->restrictflag ^= OB_RESTRICT_RENDER; - } -} - -void group_toggle_renderability_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Group *group = (Group *)tselem->id; - restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_RENDER); -} - -static int outliner_toggle_renderability_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - SpaceOops *soops = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_renderability_cb); - - DAG_id_type_tag(bmain, ID_OB); - WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene); - - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_renderability_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Renderability"; - ot->idname = "OUTLINER_OT_renderability_toggle"; - ot->description = "Toggle the renderability of selected items"; - - /* callbacks */ - ot->exec = outliner_toggle_renderability_exec; - ot->poll = ED_operator_outliner_active; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* =============================================== */ /* Outliner setting toggles */ /* Toggle Expanded (Outliner) ---------------------------------------- */ @@ -1077,14 +978,14 @@ static int outliner_open_back(TreeElement *te) static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceOops *so = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); ARegion *ar = CTX_wm_region(C); View2D *v2d = &ar->v2d; TreeElement *te; int xdelta, ytop; - Object *obact = OBACT; + Object *obact = OBACT(sl); if (!obact) return OPERATOR_CANCELLED; @@ -2002,9 +1903,9 @@ static int parent_drop_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, false, false, NULL); + ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL); @@ -2020,6 +1921,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) Main *bmain = CTX_data_main(C); Scene *scene = NULL; TreeElement *te = NULL; + TreeStoreElem *tselem; char childname[MAX_ID_NAME]; char parname[MAX_ID_NAME]; int partype = 0; @@ -2029,8 +1931,21 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* Find object hovered over */ te = outliner_dropzone_find(soops, fmval, true); + tselem = te ? TREESTORE(te) : NULL; - if (te) { + if (tselem && ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) { + SceneCollection *sc = outliner_scene_collection_from_tree_element(te); + + scene = BKE_scene_find_from_collection(bmain, sc); + BLI_assert(scene); + RNA_string_get(op->ptr, "child", childname); + ob = (Object *)BKE_libblock_find_name(ID_OB, childname); + BKE_collection_object_add(scene, sc, ob); + + DEG_relations_tag_update(bmain); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + } + else if (te) { RNA_string_set(op->ptr, "parent", te->name); /* Identify parent and child */ RNA_string_get(op->ptr, "child", childname); @@ -2062,8 +1977,8 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) } if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) { - if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, false, false, NULL)) { - DAG_relations_tag_update(bmain); + if (ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL)) { + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL); } @@ -2191,7 +2106,7 @@ static int parent_clear_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE ED_object_parent_clear(ob, RNA_enum_get(op->ptr, "type")); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL); return OPERATOR_FINISHED; @@ -2234,8 +2149,6 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) te = outliner_dropzone_find(soops, fmval, false); if (te) { - Base *base; - RNA_string_set(op->ptr, "scene", te->name); scene = (Scene *)BKE_libblock_find_name(ID_SCE, te->name); @@ -2246,19 +2159,29 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_CANCELLED; } - base = ED_object_scene_link(scene, ob); - - if (base == NULL) { + if (BKE_scene_has_object(scene, ob)) { return OPERATOR_CANCELLED; } - if (scene == CTX_data_scene(C)) { - /* when linking to an inactive scene don't touch the layer */ - ob->lay = base->lay; - ED_base_object_select(base, BA_SELECT); + SceneCollection *sc; + if (scene != CTX_data_scene(C)) { + /* when linking to an inactive scene link to the master collection */ + sc = BKE_collection_master(scene); + } + else { + sc = CTX_data_scene_collection(C); + } + + BKE_collection_object_add(scene, sc, ob); + + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + Base *base = BKE_scene_layer_base_find(sl, ob); + if (base) { + ED_object_base_select(base, BA_SELECT); + } } - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene); @@ -2350,7 +2273,6 @@ static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) Main *bmain = CTX_data_main(C); Group *group = NULL; Object *ob = NULL; - Scene *scene = CTX_data_scene(C); SpaceOops *soops = CTX_wm_space_outliner(C); ARegion *ar = CTX_wm_region(C); TreeElement *te = NULL; @@ -2380,7 +2302,7 @@ static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_CANCELLED; } - BKE_group_object_add(group, ob, scene, NULL); + BKE_group_object_add(group, ob); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index ca7dbe4f73c..1edb3c88396 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -37,13 +37,50 @@ /* internal exports only */ struct wmOperatorType; +struct TreeElement; struct TreeStoreElem; +struct Main; struct bContext; struct Scene; +struct SceneLayer; struct ID; struct Object; struct bPoseChannel; struct EditBone; +struct wmKeyConfig; + + +typedef enum TreeElementInsertType { + TE_INSERT_BEFORE, + TE_INSERT_AFTER, + TE_INSERT_INTO, +} TreeElementInsertType; + +typedef enum TreeTraversalAction { + /* Continue traversal regularly, don't skip children. */ + TRAVERSE_CONTINUE = 0, + /* Stop traversal */ + TRAVERSE_BREAK, + /* Continue traversal, but skip childs of traversed element */ + TRAVERSE_SKIP_CHILDS, +} TreeTraversalAction; + +/** + * Callback type for reinserting elements at a different position, used to allow user customizable element order. + * Passing scene right now, may be better to allow some custom data. + */ +typedef void (*TreeElementReinsertFunc)(struct Main *bmain, const struct Scene *scene, + struct TreeElement *insert_element, + struct TreeElement *insert_handle, TreeElementInsertType action); +/** + * Executed on (almost) each mouse move while dragging. It's supposed to give info + * if reinserting insert_element before/after/into insert_handle would be allowed. + * It's allowed to change the reinsert info here for non const pointers. + */ +typedef bool (*TreeElementReinsertPollFunc)(const struct Scene *scene, const struct TreeElement *insert_element, + struct TreeElement **io_insert_handle, TreeElementInsertType *io_action); +typedef TreeTraversalAction (*TreeTraversalFunc)(struct TreeElement *te, void *customdata); + typedef struct TreeElement { struct TreeElement *next, *prev, *parent; @@ -57,18 +94,32 @@ typedef struct TreeElement { const char *name; void *directdata; // Armature Bones, Base, Sequence, Strip... PointerRNA rnaptr; // RNA Pointer -} TreeElement; + + /* callbacks - TODO should be moved into a type (like TreeElementType) */ + TreeElementReinsertFunc reinsert; + TreeElementReinsertPollFunc reinsert_poll; + + struct { + TreeElementInsertType insert_type; + /* the element before/after/into which we may insert the dragged one (NULL to insert at top) */ + struct TreeElement *insert_handle; + } *drag_data; +} TreeElement; #define TREESTORE_ID_TYPE(_id) \ (ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_NT, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \ - ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS) || \ - ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF, ID_PAL)) /* Only in 'blendfile' mode ... :/ */ + ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS, ID_LP) || \ + ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF, ID_PAL, ID_WS)) /* Only in 'blendfile' mode ... :/ */ /* TreeElement->flag */ -#define TE_ACTIVE 1 -#define TE_ICONROW 2 -#define TE_LAZY_CLOSED 4 -#define TE_FREE_NAME 8 +enum { + TE_ACTIVE = (1 << 0), + /* Closed items display their children as icon within the row. TE_ICONROW is for + * these child-items that are visible but only within the row of the closed parent. */ + TE_ICONROW = (1 << 1), + TE_LAZY_CLOSED = (1 << 2), + TE_FREE_NAME = (1 << 3), +}; /* button events */ #define OL_NAMEBUTTON 1 @@ -93,11 +144,12 @@ typedef enum { /* size constants */ #define OL_Y_OFFSET 2 -#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 3.0f) -#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 2.0f) +#define OL_TOG_RESTRICT_ENABLEX (UI_UNIT_X * 3.0f) +#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 2.0f) +#define OL_TOG_RESTRICT_SELECTX UI_UNIT_X #define OL_TOG_RESTRICT_RENDERX UI_UNIT_X -#define OL_TOGW OL_TOG_RESTRICT_VIEWX +#define OL_TOGW OL_TOG_RESTRICT_ENABLEX #define OL_RNA_COLX (UI_UNIT_X * 15) #define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f) @@ -129,15 +181,9 @@ typedef enum { void outliner_free_tree(ListBase *lb); void outliner_cleanup_tree(struct SpaceOops *soops); +void outliner_remove_treestore_element(struct SpaceOops *soops, TreeStoreElem *tselem); -TreeElement *outliner_find_tse(struct SpaceOops *soops, const TreeStoreElem *tse); -TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem); -TreeElement *outliner_find_id(struct SpaceOops *soops, ListBase *lb, const struct ID *id); -TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel *pchan); -TreeElement *outliner_find_editbone(ListBase *lb, const struct EditBone *ebone); -struct ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode); - -void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct SpaceOops *soops); +void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct SceneLayer *sl, struct SpaceOops *soops); /* outliner_draw.c ---------------------------------------------- */ @@ -146,9 +192,9 @@ void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag); /* outliner_select.c -------------------------------------------- */ eOLDrawState tree_element_type_active( - struct bContext *C, struct Scene *scene, struct SpaceOops *soops, + struct bContext *C, struct Scene *scene, struct SceneLayer *sl, struct SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive); -eOLDrawState tree_element_active(struct bContext *C, struct Scene *scene, SpaceOops *soops, +eOLDrawState tree_element_active(struct bContext *C, struct Scene *scene, struct SceneLayer *sl, SpaceOops *soops, TreeElement *te, const eOLSetState set, const bool handle_all_types); void outliner_item_do_activate_from_tree_element( @@ -164,16 +210,16 @@ typedef void (*outliner_operation_cb)( struct TreeElement *, struct TreeStoreElem *, TreeStoreElem *, void *); void outliner_do_object_operation_ex( - struct bContext *C, ReportList *reports, struct Scene *scene, struct SpaceOops *soops, struct ListBase *lb, - outliner_operation_cb operation_cb, bool recurse_selected); + struct bContext *C, struct ReportList *reports, struct Scene *scene, struct SpaceOops *soops, + struct ListBase *lb, outliner_operation_cb operation_cb, bool recurse_selected); void outliner_do_object_operation( - struct bContext *C, ReportList *reports, struct Scene *scene, struct SpaceOops *soops, struct ListBase *lb, - outliner_operation_cb operation_cb); + struct bContext *C, struct ReportList *reports, struct Scene *scene, struct SpaceOops *soops, + struct ListBase *lb, outliner_operation_cb operation_cb); int common_restrict_check(struct bContext *C, struct Object *ob); int outliner_has_one_flag(ListBase *lb, short flag, const int curlevel); -void outliner_set_flag(ListBase *lb, short flag, short set); +bool outliner_set_flag(ListBase *lb, short flag, short set); void object_toggle_visibility_cb( struct bContext *C, struct ReportList *reports, struct Scene *scene, @@ -214,8 +260,11 @@ void id_remap_cb( struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data); TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const bool children); + /* ...................................................... */ +void OUTLINER_OT_highlight_update(struct wmOperatorType *ot); + void OUTLINER_OT_item_activate(struct wmOperatorType *ot); void OUTLINER_OT_item_openclose(struct wmOperatorType *ot); void OUTLINER_OT_item_rename(struct wmOperatorType *ot); @@ -235,10 +284,6 @@ void OUTLINER_OT_expanded_toggle(struct wmOperatorType *ot); void OUTLINER_OT_scroll_page(struct wmOperatorType *ot); -void OUTLINER_OT_renderability_toggle(struct wmOperatorType *ot); -void OUTLINER_OT_selectability_toggle(struct wmOperatorType *ot); -void OUTLINER_OT_visibility_toggle(struct wmOperatorType *ot); - void OUTLINER_OT_keyingset_add_selected(struct wmOperatorType *ot); void OUTLINER_OT_keyingset_remove_selected(struct wmOperatorType *ot); @@ -267,10 +312,41 @@ void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot); void OUTLINER_OT_action_set(struct wmOperatorType *ot); void OUTLINER_OT_constraint_operation(struct wmOperatorType *ot); void OUTLINER_OT_modifier_operation(struct wmOperatorType *ot); +void OUTLINER_OT_collection_operation(struct wmOperatorType *ot); /* ---------------------------------------------------------------- */ /* outliner_ops.c */ void outliner_operatortypes(void); void outliner_keymap(struct wmKeyConfig *keyconf); +/* outliner_collections.c */ + +struct SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te); + +void OUTLINER_OT_collections_delete(struct wmOperatorType *ot); +void OUTLINER_OT_collection_select(struct wmOperatorType *ot); +void OUTLINER_OT_collection_toggle(struct wmOperatorType *ot); +void OUTLINER_OT_collection_link(struct wmOperatorType *ot); +void OUTLINER_OT_collection_unlink(struct wmOperatorType *ot); +void OUTLINER_OT_collection_new(struct wmOperatorType *ot); +void OUTLINER_OT_collection_override_new(struct wmOperatorType *ot); +void OUTLINER_OT_collection_objects_add(struct wmOperatorType *ot); +void OUTLINER_OT_collection_objects_remove(struct wmOperatorType *ot); +void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot); +void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot); + +/* outliner_utils.c ---------------------------------------------- */ + +TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tree, float view_co_y); +TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeElement *parent_te, float view_co_x); +TreeElement *outliner_find_tse(struct SpaceOops *soops, const TreeStoreElem *tse); +TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem); +TreeElement *outliner_find_id(struct SpaceOops *soops, ListBase *lb, const struct ID *id); +TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel *pchan); +TreeElement *outliner_find_editbone(ListBase *lb, const struct EditBone *ebone); +struct ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode); +bool outliner_tree_traverse(const SpaceOops *soops, ListBase *tree, int filter_te_flag, int filter_tselem_flag, + TreeTraversalFunc func, void *customdata); + + #endif /* __OUTLINER_INTERN_H__ */ diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index 776717c8443..aa6a5dba6a7 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -28,25 +28,264 @@ * \ingroup spoutliner */ -#include "DNA_space_types.h" +#include "MEM_guardedalloc.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_main.h" #include "RNA_access.h" +#include "UI_interface.h" +#include "UI_view2d.h" + #include "WM_api.h" #include "WM_types.h" +#include "ED_screen.h" + #include "outliner_intern.h" +enum { + OUTLINER_ITEM_DRAG_CANCEL, + OUTLINER_ITEM_DRAG_CONFIRM, +}; + +static int outliner_item_drag_drop_poll(bContext *C) +{ + SpaceOops *soops = CTX_wm_space_outliner(C); + return ED_operator_outliner_active(C) && + /* Only collection display modes supported for now. Others need more design work */ + ELEM(soops->outlinevis, SO_ACT_LAYER, SO_COLLECTIONS); +} + +static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *ar, const wmEvent *event) +{ + /* note: using EVT_TWEAK_ events to trigger dragging is fine, + * it sends coordinates from where dragging was started */ + const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]); + return outliner_find_item_at_y(soops, &soops->tree, my); +} + +static void outliner_item_drag_end(TreeElement *dragged_te) +{ + MEM_SAFE_FREE(dragged_te->drag_data); +} + +static void outliner_item_drag_get_insert_data( + const SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged, + TreeElement **r_te_insert_handle, TreeElementInsertType *r_insert_type) +{ + TreeElement *te_hovered; + float view_mval[2]; + + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); + te_hovered = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]); + + if (te_hovered) { + /* mouse hovers an element (ignoring x-axis), now find out how to insert the dragged item exactly */ + + if (te_hovered == te_dragged) { + *r_te_insert_handle = te_dragged; + } + else if (te_hovered != te_dragged) { + const float margin = UI_UNIT_Y * (1.0f / 4); + + *r_te_insert_handle = te_hovered; + if (view_mval[1] < (te_hovered->ys + margin)) { + if (TSELEM_OPEN(TREESTORE(te_hovered), soops)) { + /* inserting after a open item means we insert into it, but as first child */ + if (BLI_listbase_is_empty(&te_hovered->subtree)) { + *r_insert_type = TE_INSERT_INTO; + } + else { + *r_insert_type = TE_INSERT_BEFORE; + *r_te_insert_handle = te_hovered->subtree.first; + } + } + else { + *r_insert_type = TE_INSERT_AFTER; + } + } + else if (view_mval[1] > (te_hovered->ys + (3 * margin))) { + *r_insert_type = TE_INSERT_BEFORE; + } + else { + *r_insert_type = TE_INSERT_INTO; + } + } + } + else { + /* mouse doesn't hover any item (ignoring x-axis), so it's either above list bounds or below. */ + + TreeElement *first = soops->tree.first; + TreeElement *last = soops->tree.last; + + if (view_mval[1] < last->ys) { + *r_te_insert_handle = last; + *r_insert_type = TE_INSERT_AFTER; + } + else if (view_mval[1] > (first->ys + UI_UNIT_Y)) { + *r_te_insert_handle = first; + *r_insert_type = TE_INSERT_BEFORE; + } + else { + BLI_assert(0); + } + } +} + +static void outliner_item_drag_handle( + const Scene *scene, SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged) +{ + TreeElement *te_insert_handle; + TreeElementInsertType insert_type; + + outliner_item_drag_get_insert_data(soops, ar, event, te_dragged, &te_insert_handle, &insert_type); + + if (!te_dragged->reinsert_poll && + /* there is no reinsert_poll, so we do some generic checks (same types and reinsert callback is available) */ + (TREESTORE(te_dragged)->type == TREESTORE(te_insert_handle)->type) && + te_dragged->reinsert) + { + /* pass */ + } + else if (te_dragged == te_insert_handle) { + /* nothing will happen anyway, no need to do poll check */ + } + else if (!te_dragged->reinsert_poll || + !te_dragged->reinsert_poll(scene, te_dragged, &te_insert_handle, &insert_type)) + { + te_insert_handle = NULL; + } + te_dragged->drag_data->insert_type = insert_type; + te_dragged->drag_data->insert_handle = te_insert_handle; +} + +static bool outliner_item_drag_drop_apply(Main *bmain, const Scene *scene, TreeElement *dragged_te) +{ + TreeElement *insert_handle = dragged_te->drag_data->insert_handle; + TreeElementInsertType insert_type = dragged_te->drag_data->insert_type; + + if ((insert_handle == dragged_te) || !insert_handle) { + /* No need to do anything */ + } + else if (dragged_te->reinsert) { + BLI_assert(!dragged_te->reinsert_poll || dragged_te->reinsert_poll(scene, dragged_te, &insert_handle, + &insert_type)); + /* call of assert above should not have changed insert_handle and insert_type at this point */ + BLI_assert(dragged_te->drag_data->insert_handle == insert_handle && + dragged_te->drag_data->insert_type == insert_type); + dragged_te->reinsert(bmain, scene, dragged_te, insert_handle, insert_type); + return true; + } + + return false; +} + +static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ARegion *ar = CTX_wm_region(C); + SpaceOops *soops = CTX_wm_space_outliner(C); + TreeElement *te_dragged = op->customdata; + int retval = OPERATOR_RUNNING_MODAL; + bool redraw = false; + bool skip_rebuild = true; + + switch (event->type) { + case EVT_MODAL_MAP: + if (event->val == OUTLINER_ITEM_DRAG_CONFIRM) { + if (outliner_item_drag_drop_apply(bmain, scene, te_dragged)) { + skip_rebuild = false; + } + retval = OPERATOR_FINISHED; + } + else if (event->val == OUTLINER_ITEM_DRAG_CANCEL) { + retval = OPERATOR_CANCELLED; + } + else { + BLI_assert(0); + } + WM_event_add_mousemove(C); /* update highlight */ + outliner_item_drag_end(te_dragged); + redraw = true; + break; + case MOUSEMOVE: + outliner_item_drag_handle(scene, soops, ar, event, te_dragged); + redraw = true; + break; + } + + if (skip_rebuild) { + soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */ + } + if (redraw) { + ED_region_tag_redraw(ar); + } + + return retval; +} + +static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + SpaceOops *soops = CTX_wm_space_outliner(C); + TreeElement *te_dragged = outliner_item_drag_element_find(soops, ar, event); + + if (!te_dragged) { + return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); + } + + op->customdata = te_dragged; + te_dragged->drag_data = MEM_callocN(sizeof(*te_dragged->drag_data), __func__); + /* by default we don't change the item position */ + te_dragged->drag_data->insert_handle = te_dragged; + /* unset highlighted tree element, dragged one will be highlighted instead */ + outliner_set_flag(&soops->tree, TSE_HIGHLIGHTED, false); + + soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */ + ED_region_tag_redraw(ar); + + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; +} + +/** + * Notes about Outliner Item Drag 'n Drop: + * Right now only collections display mode is supported. But ideally all/most modes would support this. There are + * just some open design questions that have to be answered: do we want to allow mixing order of different data types + * (like render-layers and objects)? Would that be a purely visual change or would that have any other effect? ... + */ +static void OUTLINER_OT_item_drag_drop(wmOperatorType *ot) +{ + ot->name = "Drag and Drop Item"; + ot->idname = "OUTLINER_OT_item_drag_drop"; + ot->description = "Change the hierarchical position of an item by repositioning it using drag and drop"; + + ot->invoke = outliner_item_drag_drop_invoke; + ot->modal = outliner_item_drag_drop_modal; + + ot->poll = outliner_item_drag_drop_poll; + + ot->flag = OPTYPE_UNDO; +} + /* ************************** registration **********************************/ void outliner_operatortypes(void) { + WM_operatortype_append(OUTLINER_OT_highlight_update); WM_operatortype_append(OUTLINER_OT_item_activate); WM_operatortype_append(OUTLINER_OT_select_border); WM_operatortype_append(OUTLINER_OT_item_openclose); WM_operatortype_append(OUTLINER_OT_item_rename); + WM_operatortype_append(OUTLINER_OT_item_drag_drop); WM_operatortype_append(OUTLINER_OT_operation); WM_operatortype_append(OUTLINER_OT_scene_operation); WM_operatortype_append(OUTLINER_OT_object_operation); @@ -61,6 +300,7 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_action_set); WM_operatortype_append(OUTLINER_OT_constraint_operation); WM_operatortype_append(OUTLINER_OT_modifier_operation); + WM_operatortype_append(OUTLINER_OT_collection_operation); WM_operatortype_append(OUTLINER_OT_show_one_level); WM_operatortype_append(OUTLINER_OT_show_active); @@ -70,10 +310,6 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_selected_toggle); WM_operatortype_append(OUTLINER_OT_expanded_toggle); - WM_operatortype_append(OUTLINER_OT_renderability_toggle); - WM_operatortype_append(OUTLINER_OT_selectability_toggle); - WM_operatortype_append(OUTLINER_OT_visibility_toggle); - WM_operatortype_append(OUTLINER_OT_keyingset_add_selected); WM_operatortype_append(OUTLINER_OT_keyingset_remove_selected); @@ -87,13 +323,58 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_scene_drop); WM_operatortype_append(OUTLINER_OT_material_drop); WM_operatortype_append(OUTLINER_OT_group_link); + + /* collections */ + WM_operatortype_append(OUTLINER_OT_collections_delete); + WM_operatortype_append(OUTLINER_OT_collection_select); + WM_operatortype_append(OUTLINER_OT_collection_toggle); + WM_operatortype_append(OUTLINER_OT_collection_link); + WM_operatortype_append(OUTLINER_OT_collection_unlink); + WM_operatortype_append(OUTLINER_OT_collection_new); + WM_operatortype_append(OUTLINER_OT_collection_override_new); + WM_operatortype_append(OUTLINER_OT_collection_objects_add); + WM_operatortype_append(OUTLINER_OT_collection_objects_remove); + WM_operatortype_append(OUTLINER_OT_collection_objects_select); + WM_operatortype_append(OUTLINER_OT_collection_objects_deselect); +} + +static wmKeyMap *outliner_item_drag_drop_modal_keymap(wmKeyConfig *keyconf) +{ + static EnumPropertyItem modal_items[] = { + {OUTLINER_ITEM_DRAG_CANCEL, "CANCEL", 0, "Cancel", ""}, + {OUTLINER_ITEM_DRAG_CONFIRM, "CONFIRM", 0, "Confirm/Drop", ""}, + {0, NULL, 0, NULL, NULL} + }; + const char *map_name = "Outliner Item Drap 'n Drop Modal Map"; + + wmKeyMap *keymap = WM_modalkeymap_get(keyconf, map_name); + + /* this function is called for each spacetype, only needs to add map once */ + if (keymap && keymap->modal_items) + return NULL; + + keymap = WM_modalkeymap_add(keyconf, map_name, modal_items); + + /* items for modal map */ + WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, OUTLINER_ITEM_DRAG_CANCEL); + WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, OUTLINER_ITEM_DRAG_CANCEL); + + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, OUTLINER_ITEM_DRAG_CONFIRM); + WM_modalkeymap_add_item(keymap, RETKEY, KM_RELEASE, KM_ANY, 0, OUTLINER_ITEM_DRAG_CONFIRM); + WM_modalkeymap_add_item(keymap, PADENTER, KM_RELEASE, KM_ANY, 0, OUTLINER_ITEM_DRAG_CONFIRM); + + WM_modalkeymap_assign(keymap, "OUTLINER_OT_item_drag_drop"); + + return keymap; } void outliner_keymap(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_find(keyconf, "Outliner", SPACE_OUTLINER, 0); wmKeyMapItem *kmi; - + + WM_keymap_add_item(keymap, "OUTLINER_OT_highlight_update", MOUSEMOVE, KM_ANY, KM_ANY, 0); + WM_keymap_add_item(keymap, "OUTLINER_OT_item_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0); kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, 0, 0); @@ -123,6 +404,8 @@ void outliner_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "OUTLINER_OT_item_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "OUTLINER_OT_operation", RIGHTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "OUTLINER_OT_item_drag_drop", EVT_TWEAK_L, KM_ANY, 0, 0); + WM_keymap_add_item(keymap, "OUTLINER_OT_show_hierarchy", HOMEKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "OUTLINER_OT_show_active", PERIODKEY, KM_PRESS, 0, 0); @@ -140,11 +423,6 @@ void outliner_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "OUTLINER_OT_selected_toggle", AKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "OUTLINER_OT_expanded_toggle", AKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_verify_item(keymap, "OUTLINER_OT_renderability_toggle", RKEY, KM_PRESS, 0, 0); - WM_keymap_verify_item(keymap, "OUTLINER_OT_selectability_toggle", SKEY, KM_PRESS, 0, 0); - WM_keymap_verify_item(keymap, "OUTLINER_OT_visibility_toggle", VKEY, KM_PRESS, 0, 0); - - /* keying sets - only for databrowse */ WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_add_selected", KKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_remove_selected", KKEY, KM_PRESS, KM_ALT, 0); @@ -154,5 +432,7 @@ void outliner_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_add_selected", DKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_delete_selected", DKEY, KM_PRESS, KM_ALT, 0); + + outliner_item_drag_drop_modal_keymap(keyconf); } diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 9f79b575966..f2aec1cfa52 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -44,12 +44,14 @@ #include "BLI_listbase.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_object.h" +#include "BKE_layer.h" #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_armature.h" +#include "DEG_depsgraph.h" + #include "ED_armature.h" #include "ED_object.h" #include "ED_screen.h" @@ -68,61 +70,12 @@ #include "outliner_intern.h" -/* ****************************************************** */ -/* Outliner Selection (gray-blue highlight for rows) */ - -static int outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *selecting) -{ - TreeElement *te; - TreeStoreElem *tselem; - bool changed = false; - - for (te = lb->first; te && *index >= 0; te = te->next, (*index)--) { - tselem = TREESTORE(te); - - /* if we've encountered the right item, set its 'Outliner' selection status */ - if (*index == 0) { - /* this should be the last one, so no need to do anything with index */ - if ((te->flag & TE_ICONROW) == 0) { - /* -1 value means toggle testing for now... */ - if (*selecting == -1) { - if (tselem->flag & TSE_SELECTED) - *selecting = 0; - else - *selecting = 1; - } - - /* set selection */ - if (*selecting) - tselem->flag |= TSE_SELECTED; - else - tselem->flag &= ~TSE_SELECTED; - - changed |= true; - } - } - else if (TSELEM_OPEN(tselem, soops)) { - /* Only try selecting sub-elements if we haven't hit the right element yet - * - * Hack warning: - * Index must be reduced before supplying it to the sub-tree to try to do - * selection, however, we need to increment it again for the next loop to - * function correctly - */ - (*index)--; - changed |= outliner_select(soops, &te->subtree, index, selecting); - (*index)++; - } - } - - return changed; -} /* ****************************************************** */ /* Outliner Element Selection/Activation on Click */ static eOLDrawState tree_element_active_renderlayer( - bContext *C, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) + bContext *C, Scene *UNUSED(scene), SceneLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) { Scene *sce; @@ -132,11 +85,11 @@ static eOLDrawState tree_element_active_renderlayer( sce = (Scene *)tselem->id; if (set != OL_SETSEL_NONE) { - sce->r.actlay = tselem->nr; + sce->active_layer = tselem->nr; WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, sce); } else { - return sce->r.actlay == tselem->nr; + return sce->active_layer == tselem->nr; } return OL_DRAWSEL_NONE; } @@ -146,14 +99,14 @@ static eOLDrawState tree_element_active_renderlayer( * CTRL+LMB: Select/Deselect object and all cildren * CTRL+SHIFT+LMB: Add/Remove object and all children */ -static void do_outliner_object_select_recursive(Scene *scene, Object *ob_parent, bool select) +static void do_outliner_object_select_recursive(SceneLayer *sl, Object *ob_parent, bool select) { Base *base; - for (base = FIRSTBASE; base; base = base->next) { + for (base = FIRSTBASE(sl); base; base = base->next) { Object *ob = base->object; - if ((((ob->restrictflag & OB_RESTRICT_VIEW) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) { - ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT); + if ((((base->flag & BASE_VISIBLED) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) { + ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); } } } @@ -184,7 +137,7 @@ static void do_outliner_ebone_select_recursive(bArmature *arm, EditBone *ebone_p } static eOLDrawState tree_element_set_active_object( - bContext *C, Scene *scene, SpaceOops *soops, + bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *soops, TreeElement *te, const eOLSetState set, bool recursive) { TreeStoreElem *tselem = TREESTORE(te); @@ -198,7 +151,7 @@ static eOLDrawState tree_element_set_active_object( } else { ob = (Object *)outliner_search_back(soops, te, ID_OB); - if (ob == OBACT) { + if (ob == OBACT(sl)) { return OL_DRAWSEL_NONE; } } @@ -208,34 +161,34 @@ static eOLDrawState tree_element_set_active_object( sce = (Scene *)outliner_search_back(soops, te, ID_SCE); if (sce && scene != sce) { - ED_screen_set_scene(C, CTX_wm_screen(C), sce); + WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce); scene = sce; } /* find associated base in current scene */ - base = BKE_scene_base_find(scene, ob); + base = BKE_scene_layer_base_find(sl, ob); if (base) { if (set == OL_SETSEL_EXTEND) { /* swap select */ - if (base->flag & SELECT) - ED_base_object_select(base, BA_DESELECT); + if (base->flag & BASE_SELECTED) + ED_object_base_select(base, BA_DESELECT); else - ED_base_object_select(base, BA_SELECT); + ED_object_base_select(base, BA_SELECT); } else { /* deleselect all */ - BKE_scene_base_deselect_all(scene); - ED_base_object_select(base, BA_SELECT); + BKE_scene_layer_base_deselect_all(sl); + ED_object_base_select(base, BA_SELECT); } if (recursive) { /* Recursive select/deselect for Object hierarchies */ - do_outliner_object_select_recursive(scene, ob, (ob->flag & SELECT) != 0); + do_outliner_object_select_recursive(sl, ob, (ob->flag & SELECT) != 0); } - if (C) { - ED_base_object_activate(C, base); /* adds notifier */ + if (set != OL_SETSEL_NONE) { + ED_object_base_activate(C, base); /* adds notifier */ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } } @@ -247,7 +200,7 @@ static eOLDrawState tree_element_set_active_object( } static eOLDrawState tree_element_active_material( - bContext *C, Scene *scene, SpaceOops *soops, + bContext *C, Scene *UNUSED(scene), SceneLayer *sl, SpaceOops *soops, TreeElement *te, const eOLSetState set) { TreeElement *tes; @@ -256,7 +209,7 @@ static eOLDrawState tree_element_active_material( /* we search for the object parent */ ob = (Object *)outliner_search_back(soops, te, ID_OB); // note: ob->matbits can be NULL when a local object points to a library mesh. - if (ob == NULL || ob != OBACT || ob->matbits == NULL) { + if (ob == NULL || ob != OBACT(sl) || ob->matbits == NULL) { return OL_DRAWSEL_NONE; /* just paranoia */ } @@ -293,19 +246,19 @@ static eOLDrawState tree_element_active_material( /* Tagging object for update seems a bit stupid here, but looks like we have to do it * for render views to update. See T42973. * Note that RNA material update does it too, see e.g. rna_MaterialSlot_update(). */ - DAG_id_tag_update((ID *)ob, OB_RECALC_OB); + DEG_id_tag_update((ID *)ob, OB_RECALC_OB); WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL); } return OL_DRAWSEL_NONE; } static eOLDrawState tree_element_active_texture( - bContext *C, Scene *scene, SpaceOops *UNUSED(soops), + bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *UNUSED(soops), TreeElement *te, const eOLSetState set) { TreeElement *tep; TreeStoreElem /* *tselem,*/ *tselemp; - Object *ob = OBACT; + Object *ob = OBACT(sl); SpaceButs *sbuts = NULL; if (ob == NULL) { @@ -387,14 +340,14 @@ static eOLDrawState tree_element_active_texture( static eOLDrawState tree_element_active_lamp( - bContext *UNUSED(C), Scene *scene, SpaceOops *soops, + bContext *UNUSED(C), Scene *UNUSED(scene), SceneLayer *sl, SpaceOops *soops, TreeElement *te, const eOLSetState set) { Object *ob; /* we search for the object parent */ ob = (Object *)outliner_search_back(soops, te, ID_OB); - if (ob == NULL || ob != OBACT) { + if (ob == NULL || ob != OBACT(sl)) { /* just paranoia */ return OL_DRAWSEL_NONE; } @@ -410,7 +363,7 @@ static eOLDrawState tree_element_active_lamp( } static eOLDrawState tree_element_active_camera( - bContext *UNUSED(C), Scene *scene, SpaceOops *soops, + bContext *UNUSED(C), Scene *scene, SceneLayer *UNUSED(sl), SpaceOops *soops, TreeElement *te, const eOLSetState set) { Object *ob = (Object *)outliner_search_back(soops, te, ID_OB); @@ -423,7 +376,7 @@ static eOLDrawState tree_element_active_camera( } static eOLDrawState tree_element_active_world( - bContext *C, Scene *scene, SpaceOops *UNUSED(soops), + bContext *C, Scene *scene, SceneLayer *UNUSED(sl), SpaceOops *UNUSED(soops), TreeElement *te, const eOLSetState set) { TreeElement *tep; @@ -440,7 +393,7 @@ static eOLDrawState tree_element_active_world( if (set != OL_SETSEL_NONE) { /* make new scene active */ if (sce && scene != sce) { - ED_screen_set_scene(C, CTX_wm_screen(C), sce); + WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce); } } @@ -456,7 +409,7 @@ static eOLDrawState tree_element_active_world( } static eOLDrawState tree_element_active_defgroup( - bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) + bContext *C, SceneLayer *sl, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) { Object *ob; @@ -466,21 +419,20 @@ static eOLDrawState tree_element_active_defgroup( BLI_assert(te->index + 1 >= 0); ob->actdef = te->index + 1; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob); } else { - if (ob == OBACT) { + if (ob == OBACT(sl)) if (ob->actdef == te->index + 1) { return OL_DRAWSEL_NORMAL; } - } } return OL_DRAWSEL_NONE; } static eOLDrawState tree_element_active_posegroup( - bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) + bContext *C, Scene *UNUSED(scene), SceneLayer *sl, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) { Object *ob = (Object *)tselem->id; @@ -491,7 +443,7 @@ static eOLDrawState tree_element_active_posegroup( } } else { - if (ob == OBACT && ob->pose) { + if (ob == OBACT(sl) && ob->pose) { if (ob->pose->active_group == te->index + 1) { return OL_DRAWSEL_NORMAL; } @@ -501,7 +453,7 @@ static eOLDrawState tree_element_active_posegroup( } static eOLDrawState tree_element_active_posechannel( - bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive) + bContext *C, Scene *UNUSED(scene), SceneLayer *sl, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive) { Object *ob = (Object *)tselem->id; bArmature *arm = ob->data; @@ -535,7 +487,7 @@ static eOLDrawState tree_element_active_posechannel( } } else { - if (ob == OBACT && ob->pose) { + if (ob == OBACT(sl) && ob->pose) { if (pchan->bone->flag & BONE_SELECTED) { return OL_DRAWSEL_NORMAL; } @@ -545,14 +497,14 @@ static eOLDrawState tree_element_active_posechannel( } static eOLDrawState tree_element_active_bone( - bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive) + bContext *C, SceneLayer *sl, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive) { bArmature *arm = (bArmature *)tselem->id; Bone *bone = te->directdata; if (set != OL_SETSEL_NONE) { if (!(bone->flag & BONE_HIDDEN_P)) { - Object *ob = OBACT; + Object *ob = OBACT(sl); if (ob) { if (set != OL_SETSEL_EXTEND) { /* single select forces all other bones to get unselected */ @@ -581,7 +533,7 @@ static eOLDrawState tree_element_active_bone( } } else { - Object *ob = OBACT; + Object *ob = OBACT(sl); if (ob && ob->data == arm) { if (bone->flag & BONE_SELECTED) { @@ -654,7 +606,7 @@ static eOLDrawState tree_element_active_ebone( } static eOLDrawState tree_element_active_modifier( - bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set) + bContext *C, Scene *UNUSED(scene), SceneLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set) { if (set != OL_SETSEL_NONE) { Object *ob = (Object *)tselem->id; @@ -682,7 +634,7 @@ static eOLDrawState tree_element_active_psys( } static int tree_element_active_constraint( - bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set) + bContext *C, Scene *UNUSED(scene), SceneLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set) { if (set != OL_SETSEL_NONE) { Object *ob = (Object *)tselem->id; @@ -695,7 +647,7 @@ static int tree_element_active_constraint( } static eOLDrawState tree_element_active_text( - bContext *UNUSED(C), Scene *UNUSED(scene), SpaceOops *UNUSED(soops), + bContext *UNUSED(C), Scene *UNUSED(scene), SceneLayer *UNUSED(sl), SpaceOops *UNUSED(soops), TreeElement *UNUSED(te), int UNUSED(set)) { // XXX removed @@ -703,10 +655,10 @@ static eOLDrawState tree_element_active_text( } static eOLDrawState tree_element_active_pose( - bContext *C, Scene *scene, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set) + bContext *C, Scene *scene, SceneLayer *sl, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set) { Object *ob = (Object *)tselem->id; - Base *base = BKE_scene_base_find(scene, ob); + Base *base = BKE_scene_layer_base_find(sl, ob); if (base == NULL) { /* Armature not instantiated in current scene (e.g. inside an appended group...). */ @@ -792,7 +744,7 @@ static eOLDrawState tree_element_active_sequence_dup( } static eOLDrawState tree_element_active_keymap_item( - bContext *UNUSED(C), TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set) + bContext *UNUSED(C), Scene *UNUSED(scene), SceneLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set) { wmKeyMapItem *kmi = te->directdata; @@ -808,84 +760,116 @@ static eOLDrawState tree_element_active_keymap_item( return OL_DRAWSEL_NONE; } +static eOLDrawState tree_element_active_collection( + bContext *C, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) +{ + if (set == OL_SETSEL_NONE) { + LayerCollection *active = CTX_data_layer_collection(C); + + /* sometimes the renderlayer has no LayerCollection at all */ + if (active == NULL) { + return OL_DRAWSEL_NONE; + } + + if ((tselem->type == TSE_SCENE_COLLECTION && active->scene_collection == te->directdata) || + (tselem->type == TSE_LAYER_COLLECTION && active == te->directdata)) + { + return OL_DRAWSEL_NORMAL; + } + } + /* don't allow selecting a scene collection, it can have multiple layer collection + * instances (which one would the user want to be selected then?) */ + else if (tselem->type == TSE_LAYER_COLLECTION) { + SceneLayer *sl = CTX_data_scene_layer(C); + LayerCollection *lc = te->directdata; + const int collection_index = BKE_layer_collection_findindex(sl, lc); + + BLI_assert(collection_index >= 0); + sl->active_collection = collection_index; + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + } + + return OL_DRAWSEL_NONE; +} + /* ---------------------------------------------- */ /* generic call for ID data check or make/check active in UI */ -eOLDrawState tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, +eOLDrawState tree_element_active(bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *soops, TreeElement *te, const eOLSetState set, const bool handle_all_types) { switch (te->idcode) { /* Note: ID_OB only if handle_all_type is true, else objects are handled specially to allow multiple - * selection. See do_outliner_item_activate_from_cursor. */ + * selection. See do_outliner_item_activate. */ case ID_OB: if (handle_all_types) { - return tree_element_set_active_object(C, scene, soops, te, set, false); + return tree_element_set_active_object(C, scene, sl, soops, te, set, false); } break; case ID_MA: - return tree_element_active_material(C, scene, soops, te, set); + return tree_element_active_material(C, scene, sl, soops, te, set); case ID_WO: - return tree_element_active_world(C, scene, soops, te, set); + return tree_element_active_world(C, scene, sl, soops, te, set); case ID_LA: - return tree_element_active_lamp(C, scene, soops, te, set); + return tree_element_active_lamp(C, scene, sl, soops, te, set); case ID_TE: - return tree_element_active_texture(C, scene, soops, te, set); + return tree_element_active_texture(C, scene, sl, soops, te, set); case ID_TXT: - return tree_element_active_text(C, scene, soops, te, set); + return tree_element_active_text(C, scene, sl, soops, te, set); case ID_CA: - return tree_element_active_camera(C, scene, soops, te, set); + return tree_element_active_camera(C, scene, sl, soops, te, set); } return OL_DRAWSEL_NONE; } /** * Generic call for non-id data to make/check active in UI - * - * \note Context can be NULL when ``(set == OL_SETSEL_NONE)`` */ eOLDrawState tree_element_type_active( - bContext *C, Scene *scene, SpaceOops *soops, + bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive) { switch (tselem->type) { case TSE_DEFGROUP: - return tree_element_active_defgroup(C, scene, te, tselem, set); + return tree_element_active_defgroup(C, sl, te, tselem, set); case TSE_BONE: - return tree_element_active_bone(C, scene, te, tselem, set, recursive); + return tree_element_active_bone(C, sl, te, tselem, set, recursive); case TSE_EBONE: return tree_element_active_ebone(C, scene, te, tselem, set, recursive); case TSE_MODIFIER: - return tree_element_active_modifier(C, te, tselem, set); + return tree_element_active_modifier(C, scene, sl, te, tselem, set); case TSE_LINKED_OB: if (set != OL_SETSEL_NONE) { - tree_element_set_active_object(C, scene, soops, te, set, false); + tree_element_set_active_object(C, scene, sl, soops, te, set, false); } - else if (tselem->id == (ID *)OBACT) { + else if (tselem->id == (ID *)OBACT(sl)) { return OL_DRAWSEL_NORMAL; } break; case TSE_LINKED_PSYS: return tree_element_active_psys(C, scene, te, tselem, set); case TSE_POSE_BASE: - return tree_element_active_pose(C, scene, te, tselem, set); + return tree_element_active_pose(C, scene, sl, te, tselem, set); case TSE_POSE_CHANNEL: - return tree_element_active_posechannel(C, scene, te, tselem, set, recursive); + return tree_element_active_posechannel(C, scene, sl, te, tselem, set, recursive); case TSE_CONSTRAINT: - return tree_element_active_constraint(C, te, tselem, set); + return tree_element_active_constraint(C, scene, sl, te, tselem, set); case TSE_R_LAYER: - return tree_element_active_renderlayer(C, te, tselem, set); + return tree_element_active_renderlayer(C, scene, sl, te, tselem, set); case TSE_POSEGRP: - return tree_element_active_posegroup(C, scene, te, tselem, set); + return tree_element_active_posegroup(C, scene, sl, te, tselem, set); case TSE_SEQUENCE: return tree_element_active_sequence(C, scene, te, tselem, set); case TSE_SEQUENCE_DUP: return tree_element_active_sequence_dup(scene, te, tselem, set); case TSE_KEYMAP_ITEM: - return tree_element_active_keymap_item(C, te, tselem, set); + return tree_element_active_keymap_item(C, scene, sl, te, tselem, set); case TSE_GP_LAYER: - //return tree_element_active_gplayer(C, scene, te, tselem, set); + //return tree_element_active_gplayer(C, scene, s, te, tselem, set); break; - + case TSE_SCENE_COLLECTION: + case TSE_LAYER_COLLECTION: + return tree_element_active_collection(C, te, tselem, set); } return OL_DRAWSEL_NONE; } @@ -899,16 +883,16 @@ eOLDrawState tree_element_type_active( * Needed to run from operators accessed from a menu. */ static void do_outliner_item_activate_tree_element( - bContext *C, Scene *scene, SpaceOops *soops, + bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, - bool extend, bool recursive) + const bool extend, const bool recursive) { /* always makes active object, except for some specific types. * Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want * to switch out of edit mode (see T48328 for details). */ - if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE)) { + if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE, TSE_LAYER_COLLECTION)) { tree_element_set_active_object( - C, scene, soops, te, + C, scene, sl, soops, te, (extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL, recursive && tselem->type == 0); } @@ -917,7 +901,7 @@ static void do_outliner_item_activate_tree_element( /* editmode? */ if (te->idcode == ID_SCE) { if (scene != (Scene *)tselem->id) { - ED_screen_set_scene(C, CTX_wm_screen(C), (Scene *)tselem->id); + WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), (Scene *)tselem->id); } } else if (te->idcode == ID_GR) { @@ -934,83 +918,79 @@ static void do_outliner_item_activate_tree_element( } for (gob = gr->gobject.first; gob; gob = gob->next) { - ED_base_object_select(BKE_scene_base_find(scene, gob->ob), sel); + ED_object_base_select(BKE_scene_layer_base_find(sl, gob->ob), sel); } } else { - BKE_scene_base_deselect_all(scene); + BKE_scene_layer_base_deselect_all(sl); for (gob = gr->gobject.first; gob; gob = gob->next) { - if ((gob->ob->flag & SELECT) == 0) - ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_SELECT); + Base *base = BKE_scene_layer_base_find(sl, gob->ob); + /* Object may not be in this scene */ + if (base != NULL) { + if ((base->flag & BASE_SELECTED) == 0) { + ED_object_base_select(base, BA_SELECT); + } + } } } - + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } else if (ELEM(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) { WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL); } else { // rest of types - tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, false); + tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NORMAL, false); } } else { - tree_element_type_active( - C, scene, soops, te, tselem, - extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL, - recursive); + tree_element_type_active(C, scene, sl, soops, te, tselem, + extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL, + recursive); } } /** - * Activates tree items, also handles clicking on arrows. + * \param extend: Don't deselect other items, only modify \a te. + * \param toggle: Select \a te when not selected, deselect when selected. */ -static bool do_outliner_item_activate_from_cursor( - bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, - TreeElement *te, bool extend, bool recursive, const float mval[2]) +static void outliner_item_select(SpaceOops *soops, const TreeElement *te, const bool extend, const bool toggle) { - if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) { - TreeStoreElem *tselem = TREESTORE(te); - bool openclose = false; - - /* open close icon */ - if ((te->flag & TE_ICONROW) == 0) { // hidden icon, no open/close - if (mval[0] > te->xs && mval[0] < te->xs + UI_UNIT_X) - openclose = true; - } - - if (openclose) { - /* all below close/open? */ - if (extend) { - tselem->flag &= ~TSE_CLOSED; - outliner_set_flag(&te->subtree, TSE_CLOSED, !outliner_has_one_flag(&te->subtree, TSE_CLOSED, 1)); - } - else { - if (tselem->flag & TSE_CLOSED) tselem->flag &= ~TSE_CLOSED; - else tselem->flag |= TSE_CLOSED; - - } - - return true; - } - /* name and first icon */ - else if (mval[0] > te->xs + UI_UNIT_X && mval[0] < te->xend) { - do_outliner_item_activate_tree_element( - C, scene, soops, - te, tselem, - extend, recursive); - return true; - } + TreeStoreElem *tselem = TREESTORE(te); + const short new_flag = toggle ? (tselem->flag ^ TSE_SELECTED) : (tselem->flag | TSE_SELECTED); + + if (extend == false) { + outliner_set_flag(&soops->tree, TSE_SELECTED, false); } - - for (te = te->subtree.first; te; te = te->next) { - if (do_outliner_item_activate_from_cursor(C, scene, ar, soops, te, extend, recursive, mval)) { - return true; - } + tselem->flag = new_flag; +} + +static void outliner_item_toggle_closed(TreeElement *te, const bool toggle_children) +{ + TreeStoreElem *tselem = TREESTORE(te); + if (toggle_children) { + tselem->flag &= ~TSE_CLOSED; + + const bool all_opened = !outliner_has_one_flag(&te->subtree, TSE_CLOSED, 1); + outliner_set_flag(&te->subtree, TSE_CLOSED, all_opened); + } + else { + tselem->flag ^= TSE_CLOSED; } - return false; +} + +static bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_co_x) +{ + return ((te->flag & TE_ICONROW) == 0) && (view_co_x > te->xs) && (view_co_x < te->xs + UI_UNIT_X); +} + +static bool outliner_is_co_within_restrict_columns(const SpaceOops *soops, const ARegion *ar, float view_co_x) +{ + return (!ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF) && + !(soops->flag & SO_HIDE_RESTRICTCOLS) && + (view_co_x > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX)); } /** @@ -1024,10 +1004,11 @@ void outliner_item_do_activate_from_tree_element( bool extend, bool recursive) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); SpaceOops *soops = CTX_wm_space_outliner(C); do_outliner_item_activate_tree_element( - C, scene, soops, + C, scene, sl, soops, te, tselem, extend, recursive); } @@ -1041,56 +1022,52 @@ int outliner_item_do_activate_from_cursor( bContext *C, const int mval[2], bool extend, bool recursive) { - Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); TreeElement *te; - float fmval[2]; + float view_mval[2]; + bool changed = false, rebuild_tree = false; - UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &fmval[0], &fmval[1]); + UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]); - if (!ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF) && - !(soops->flag & SO_HIDE_RESTRICTCOLS) && - (fmval[0] > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX)) - { + if (outliner_is_co_within_restrict_columns(soops, ar, view_mval[0])) { return OPERATOR_CANCELLED; } - for (te = soops->tree.first; te; te = te->next) { - if (do_outliner_item_activate_from_cursor(C, scene, ar, soops, te, extend, recursive, fmval)) { - break; - } + if (!(te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]))) { + /* skip */ } - - if (te) { - ED_undo_push(C, "Outliner click event"); + else if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) { + outliner_item_toggle_closed(te, extend); + changed = true; + rebuild_tree = true; } else { - short selecting = -1; - int row; - - /* get row number - 100 here is just a dummy value since we don't need the column */ - UI_view2d_listview_view_to_cell(&ar->v2d, 1000, UI_UNIT_Y, 0.0f, OL_Y_OFFSET, - fmval[0], fmval[1], NULL, &row); - - /* select relevant row */ - if (outliner_select(soops, &soops->tree, &row, &selecting)) { - + Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + /* the row may also contain children, if one is hovered we want this instead of current te */ + TreeElement *activate_te = outliner_find_item_at_x_in_row(soops, te, view_mval[0]); + TreeStoreElem *activate_tselem = TREESTORE(activate_te); + + outliner_item_select(soops, activate_te, extend, extend); + do_outliner_item_activate_tree_element(C, scene, sl, soops, activate_te, activate_tselem, extend, recursive); + changed = true; + } + + if (changed) { + if (!rebuild_tree) { + /* only needs to redraw, no rebuild */ soops->storeflag |= SO_TREESTORE_REDRAW; - - /* no need for undo push here, only changing outliner data which is - * scene level - campbell */ - /* ED_undo_push(C, "Outliner selection event"); */ } + ED_undo_push(C, "Outliner selection change"); + ED_region_tag_redraw(ar); } - - ED_region_tag_redraw(ar); return OPERATOR_FINISHED; } /* event can enterkey, then it opens/closes */ -static int outliner_item_activate(bContext *C, wmOperator *op, const wmEvent *event) +static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bool extend = RNA_boolean_get(op->ptr, "extend"); bool recursive = RNA_boolean_get(op->ptr, "recursive"); @@ -1103,7 +1080,7 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot) ot->idname = "OUTLINER_OT_item_activate"; ot->description = "Handle mouse clicks to activate/select items"; - ot->invoke = outliner_item_activate; + ot->invoke = outliner_item_activate_invoke; ot->poll = ED_operator_outliner_active; diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index cf9deeaedf8..79122de70dd 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -53,9 +53,9 @@ #include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_constraint.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_group.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" @@ -64,8 +64,12 @@ #include "BKE_scene.h" #include "BKE_sequencer.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "ED_armature.h" #include "ED_object.h" +#include "ED_scene.h" #include "ED_screen.h" #include "ED_sequencer.h" #include "ED_util.h" @@ -308,7 +312,7 @@ static bool scene_cb(bContext *C, eOutliner_PropSceneOps event, TreeElement *UNU Scene *scene = (Scene *)tselem->id; if (event == OL_SCENE_OP_DELETE) { - if (ED_screen_delete_scene(C, scene)) { + if (ED_scene_delete(C, CTX_data_main(C), CTX_wm_window(C), scene)) { WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene); } else { @@ -359,15 +363,15 @@ void OUTLINER_OT_scene_operation(wmOperatorType *ot) /* ******************************************** */ static void object_select_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te, + bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { - Base *base = (Base *)te->directdata; - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base && ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0)) { - base->flag |= SELECT; - base->object->flag |= SELECT; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = (Object *)tselem->id; + Base *base = BKE_scene_layer_base_find(sl, ob); + + if (base && ((base->flag & BASE_VISIBLED) != 0)) { + base->flag |= BASE_SELECTED; } } @@ -381,15 +385,15 @@ static void object_select_hierarchy_cb( } static void object_deselect_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te, + bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { - Base *base = (Base *)te->directdata; - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = (Object *)tselem->id; + Base *base = BKE_scene_layer_base_find(sl, ob); + if (base) { - base->flag &= ~SELECT; - base->object->flag &= ~SELECT; + base->flag &= ~BASE_SELECTED; } } @@ -397,30 +401,27 @@ static void object_delete_cb( bContext *C, ReportList *reports, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem, void *user_data) { - Base *base = (Base *)te->directdata; - - if (base == NULL) - base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base) { + Object *ob = (Object *)tselem->id; + if (ob) { Main *bmain = CTX_data_main(C); - if (base->object->id.tag & LIB_TAG_INDIRECT) { - BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2); + if (ob->id.tag & LIB_TAG_INDIRECT) { + BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2); return; } - else if (BKE_library_ID_is_indirectly_used(bmain, base->object) && - ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) + else if (BKE_library_ID_is_indirectly_used(bmain, ob) && + ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) { BKE_reportf(reports, RPT_WARNING, "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user", - base->object->id.name + 2, scene->id.name + 2); + ob->id.name + 2, scene->id.name + 2); return; } // check also library later - if (scene->obedit == base->object) + if (scene->obedit == ob) ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); - ED_base_object_free_and_unlink(CTX_data_main(C), scene, base); + ED_object_base_free_and_unlink(CTX_data_main(C), scene, ob); /* leave for ED_outliner_id_unref to handle */ #if 0 te->directdata = NULL; @@ -518,22 +519,25 @@ static void singleuser_world_cb( } static void group_linkobs2scene_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), + bContext *C, ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { + SceneLayer *sl = CTX_data_scene_layer(C); + SceneCollection *sc = CTX_data_scene_collection(C); Group *group = (Group *)tselem->id; GroupObject *gob; Base *base; for (gob = group->gobject.first; gob; gob = gob->next) { - base = BKE_scene_base_find(scene, gob->ob); + base = BKE_scene_layer_base_find(sl, gob->ob); if (!base) { /* link to scene */ - base = BKE_scene_base_add(scene, gob->ob); + BKE_collection_object_add(scene, sc, gob->ob); + base = BKE_scene_layer_base_find(sl, gob->ob); id_us_plus(&gob->ob->id); } - base->object->flag |= SELECT; - base->flag |= SELECT; + + base->flag |= BASE_SELECTED; } } @@ -566,7 +570,7 @@ void outliner_do_object_operation_ex( // when objects selected in other scenes... dunno if that should be allowed Scene *scene_owner = (Scene *)outliner_search_back(soops, te, ID_SCE); if (scene_owner && scene_act != scene_owner) { - ED_screen_set_scene(C, CTX_wm_screen(C), scene_owner); + WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), scene_owner); } /* important to use 'scene_owner' not scene_act else deleting objects can crash. * only use 'scene_act' when 'scene_owner' is NULL, which can happen when the @@ -653,6 +657,14 @@ typedef enum eOutliner_PropModifierOps { OL_MODIFIER_OP_DELETE } eOutliner_PropModifierOps; +typedef enum eOutliner_PropCollectionOps { + OL_COLLECTION_OP_OBJECTS_ADD = 1, + OL_COLLECTION_OP_OBJECTS_REMOVE, + OL_COLLECTION_OP_COLLECTION_NEW, + OL_COLLECTION_OP_COLLECTION_DEL, + OL_COLLECTION_OP_COLLECTION_UNLINK, +} eOutliner_PropCollectionOps; + static void pchan_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg)) { bPoseChannel *pchan = (bPoseChannel *)te->directdata; @@ -788,12 +800,12 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem if (event == OL_MODIFIER_OP_TOGVIS) { md->mode ^= eModifierMode_Realtime; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); } else if (event == OL_MODIFIER_OP_TOGREN) { md->mode ^= eModifierMode_Render; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); } else if (event == OL_MODIFIER_OP_DELETE) { @@ -803,6 +815,63 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem } } +static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *Carg) +{ + bContext *C = (bContext *)Carg; + Scene *scene = CTX_data_scene(C); + LayerCollection *lc = te->directdata; + SceneCollection *sc = lc->scene_collection; + + if (event == OL_COLLECTION_OP_OBJECTS_ADD) { + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) + { + BKE_collection_object_add(scene, sc, ob); + } + CTX_DATA_END; + + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + } + else if (event == OL_COLLECTION_OP_OBJECTS_REMOVE) { + Main *bmain = CTX_data_main(C); + + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) + { + BKE_collection_object_remove(bmain, scene, sc, ob, true); + } + CTX_DATA_END; + + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + te->store_elem->flag &= ~TSE_SELECTED; + } + else if (event == OL_COLLECTION_OP_COLLECTION_NEW) { + BKE_collection_add(scene, sc, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + } + else if (event == OL_COLLECTION_OP_COLLECTION_UNLINK) { + SceneLayer *sl = CTX_data_scene_layer(C); + + if (BLI_findindex(&sl->layer_collections, lc) == -1) { + /* we can't unlink if the layer collection wasn't directly linked */ + TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */ + } + else { + BKE_collection_unlink(sl, lc); + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + } + } + else if (event == OL_COLLECTION_OP_COLLECTION_DEL) { + if (BKE_collection_remove(scene, sc)) { + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + } + else { + /* we can't remove the master collection */ + TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */ + } + } +} + static void outliner_do_data_operation(SpaceOops *soops, int type, int event, ListBase *lb, void (*operation_cb)(int, TreeElement *, TreeStoreElem *, void *), void *arg) @@ -827,12 +896,13 @@ static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *s { Base *child_base, *base_next; Object *parent; + SceneLayer *scene_layer = CTX_data_scene_layer(C); if (!base) { return NULL; } - for (child_base = scene->base.first; child_base; child_base = base_next) { + for (child_base = scene_layer->object_bases.first; child_base; child_base = base_next) { base_next = child_base->next; for (parent = child_base->object->parent; parent && (parent != base->object); parent = parent->parent); if (parent) { @@ -855,7 +925,7 @@ static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *s base->object->id.name + 2, scene->id.name + 2); return base_next; } - ED_base_object_free_and_unlink(CTX_data_main(C), scene, base); + ED_object_base_free_and_unlink(CTX_data_main(C), scene, base->object); return base_next; } @@ -863,11 +933,12 @@ static void object_delete_hierarchy_cb( bContext *C, ReportList *reports, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { + SceneLayer *sl = CTX_data_scene_layer(C); Base *base = (Base *)te->directdata; Object *obedit = scene->obedit; if (!base) { - base = BKE_scene_base_find(scene, (Object *)tselem->id); + base = BKE_scene_layer_base_find(sl, (Object *)tselem->id); } if (base) { /* Check also library later. */ @@ -922,6 +993,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + wmWindow *win = CTX_wm_window(C); SpaceOops *soops = CTX_wm_space_outliner(C); int event; const char *str = NULL; @@ -936,7 +1008,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) Scene *sce = scene; // to be able to delete, scenes are set... outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_select_cb); if (scene != sce) { - ED_screen_set_scene(C, CTX_wm_screen(C), sce); + WM_window_change_active_scene(bmain, C, win, sce); } str = "Select Objects"; @@ -946,8 +1018,8 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) Scene *sce = scene; // to be able to delete, scenes are set... outliner_do_object_operation_ex(C, op->reports, scene, soops, &soops->tree, object_select_hierarchy_cb, false); if (scene != sce) { - ED_screen_set_scene(C, CTX_wm_screen(C), sce); - } + WM_window_change_active_scene(bmain, C, win, sce); + } str = "Select Object Hierarchy"; WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } @@ -966,7 +1038,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) * cleanup tree here to prevent such cases. */ outliner_cleanup_tree(soops); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); str = "Delete Objects"; WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } @@ -976,7 +1048,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) /* XXX: See OL_OP_DELETE comment above. */ outliner_cleanup_tree(soops); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); str = "Delete Object Hierarchy"; WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } @@ -988,21 +1060,6 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb); str = "Localized Objects"; } - else if (event == OL_OP_TOGVIS) { - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_visibility_cb); - str = "Toggle Visibility"; - WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); - } - else if (event == OL_OP_TOGSEL) { - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_selectability_cb); - str = "Toggle Selectability"; - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - } - else if (event == OL_OP_TOGREN) { - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_renderability_cb); - str = "Toggle Renderability"; - WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene); - } else if (event == OL_OP_RENAME) { outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb); str = "Rename Object"; @@ -1090,7 +1147,7 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op) case OL_GROUPOP_INSTANCE: outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_instance_cb, NULL); /* works without this except if you try render right after, see: 22027 */ - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); break; case OL_GROUPOP_DELETE: outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL); @@ -1098,15 +1155,6 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op) case OL_GROUPOP_REMAP: outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL); break; - case OL_GROUPOP_TOGVIS: - outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_visibility_cb, NULL); - break; - case OL_GROUPOP_TOGSEL: - outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_selectability_cb, NULL); - break; - case OL_GROUPOP_TOGREN: - outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_renderability_cb, NULL); - break; case OL_GROUPOP_RENAME: outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL); break; @@ -1628,7 +1676,7 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op) /* update dependencies */ if (updateDeps) { /* rebuild depsgraph for the new deps */ - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); } return OPERATOR_FINISHED; @@ -1746,6 +1794,52 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot) /* ******************** */ +static EnumPropertyItem prop_collection_op_types[] = { + {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"}, + {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"}, + {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"}, + {OL_COLLECTION_OP_COLLECTION_UNLINK, "COLLECTION_UNLINK", ICON_UNLINKED, "Unlink", "Unlink collection"}, + {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"}, + {0, NULL, 0, NULL, NULL} +}; + +static int outliner_collection_operation_exec(bContext *C, wmOperator *op) +{ + SpaceOops *soops = CTX_wm_space_outliner(C); + int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0; + eOutliner_PropCollectionOps event; + + event = RNA_enum_get(op->ptr, "type"); + set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel); + + outliner_do_data_operation(soops, datalevel, event, &soops->tree, collection_cb, C); + + outliner_cleanup_tree(soops); + + ED_undo_push(C, "Collection operation"); + + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_collection_operation(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Outliner Collection Operation"; + ot->idname = "OUTLINER_OT_collection_operation"; + ot->description = ""; + + /* callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = outliner_collection_operation_exec; + ot->poll = ED_operator_outliner_active; + + ot->flag = 0; + + ot->prop = RNA_def_enum(ot->srna, "type", prop_collection_op_types, 0, "Collection Operation", ""); +} + +/* ******************** */ + // XXX: select linked is for RNA structs only static const EnumPropertyItem prop_data_op_types[] = { {OL_DOP_SELECT, "SELECT", 0, "Select", ""}, @@ -1920,6 +2014,9 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop else if (datalevel == TSE_MODIFIER) { WM_operator_name_call(C, "OUTLINER_OT_modifier_operation", WM_OP_INVOKE_REGION_WIN, NULL); } + else if (datalevel == TSE_LAYER_COLLECTION) { + WM_operator_name_call(C, "OUTLINER_OT_collection_operation", WM_OP_INVOKE_REGION_WIN, NULL); + } else { WM_operator_name_call(C, "OUTLINER_OT_data_operation", WM_OP_INVOKE_REGION_WIN, NULL); } diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index cf77afa32c4..eda4faab93f 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -46,6 +46,7 @@ #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meta_types.h" +#include "DNA_lightprobe_types.h" #include "DNA_particle_types.h" #include "DNA_scene_types.h" #include "DNA_world_types.h" @@ -63,12 +64,15 @@ #include "BKE_fcurve.h" #include "BKE_main.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_modifier.h" #include "BKE_sequencer.h" #include "BKE_idcode.h" #include "BKE_outliner_treehash.h" +#include "DEG_depsgraph_build.h" + #include "ED_armature.h" #include "ED_screen.h" @@ -83,6 +87,9 @@ # include "BLI_math_base.h" /* M_PI */ #endif +/* prototypes */ +static void outliner_make_hierarchy(ListBase *lb); + /* ********************************************************* */ /* Persistent Data */ @@ -199,105 +206,6 @@ void outliner_cleanup_tree(SpaceOops *soops) outliner_storage_cleanup(soops); } -/* Find specific item from the treestore */ -TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem) -{ - TreeElement *te, *tes; - for (te = lb->first; te; te = te->next) { - if (te->store_elem == store_elem) return te; - tes = outliner_find_tree_element(&te->subtree, store_elem); - if (tes) return tes; - } - return NULL; -} - -/* tse is not in the treestore, we use its contents to find a match */ -TreeElement *outliner_find_tse(SpaceOops *soops, const TreeStoreElem *tse) -{ - TreeStoreElem *tselem; - - if (tse->id == NULL) return NULL; - - /* check if 'tse' is in treestore */ - tselem = BKE_outliner_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id); - if (tselem) - return outliner_find_tree_element(&soops->tree, tselem); - - return NULL; -} - -/* Find treestore that refers to given ID */ -TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, const ID *id) -{ - for (TreeElement *te = lb->first; te; te = te->next) { - TreeStoreElem *tselem = TREESTORE(te); - if (tselem->type == 0) { - if (tselem->id == id) { - return te; - } - /* only deeper on scene or object */ - if (ELEM(te->idcode, ID_OB, ID_SCE) || - ((soops->outlinevis == SO_GROUPS) && (te->idcode == ID_GR))) - { - TreeElement *tes = outliner_find_id(soops, &te->subtree, id); - if (tes) { - return tes; - } - } - } - } - return NULL; -} - -TreeElement *outliner_find_posechannel(ListBase *lb, const bPoseChannel *pchan) -{ - for (TreeElement *te = lb->first; te; te = te->next) { - if (te->directdata == pchan) { - return te; - } - - TreeStoreElem *tselem = TREESTORE(te); - if (ELEM(tselem->type, TSE_POSE_BASE, TSE_POSE_CHANNEL)) { - TreeElement *tes = outliner_find_posechannel(&te->subtree, pchan); - if (tes) { - return tes; - } - } - } - return NULL; -} - -TreeElement *outliner_find_editbone(ListBase *lb, const EditBone *ebone) -{ - for (TreeElement *te = lb->first; te; te = te->next) { - if (te->directdata == ebone) { - return te; - } - - TreeStoreElem *tselem = TREESTORE(te); - if (ELEM(tselem->type, 0, TSE_EBONE)) { - TreeElement *tes = outliner_find_editbone(&te->subtree, ebone); - if (tes) { - return tes; - } - } - } - return NULL; -} - -ID *outliner_search_back(SpaceOops *UNUSED(soops), TreeElement *te, short idcode) -{ - TreeStoreElem *tselem; - te = te->parent; - - while (te) { - tselem = TREESTORE(te); - if (tselem->type == 0 && te->idcode == idcode) return tselem->id; - te = te->parent; - } - return NULL; -} - /* ********************************************************* */ @@ -326,7 +234,7 @@ static void outliner_add_bone(SpaceOops *soops, ListBase *lb, ID *id, Bone *curB #define LOG2I(x) (int)(log(x) / M_LN2) -static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, SceneRenderLayer *srl) +static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, SceneLayer *scene_layer) { TreeStoreElem *tselem = NULL; TreeElement *te = NULL; @@ -336,7 +244,7 @@ static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, Sc te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_COMBINED)); te->name = IFACE_("Combined"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; /* save cpu cycles, but we add the first to invoke an open/close triangle */ tselem = TREESTORE(tenla); @@ -345,71 +253,71 @@ static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, Sc te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_Z)); te->name = IFACE_("Z"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_VECTOR)); te->name = IFACE_("Vector"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_NORMAL)); te->name = IFACE_("Normal"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_UV)); te->name = IFACE_("UV"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_MIST)); te->name = IFACE_("Mist"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDEXOB)); te->name = IFACE_("Index Object"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDEXMA)); te->name = IFACE_("Index Material"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_RGBA)); te->name = IFACE_("Color"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_DIFFUSE)); te->name = IFACE_("Diffuse"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_SPEC)); te->name = IFACE_("Specular"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_SHADOW)); te->name = IFACE_("Shadow"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_AO)); te->name = IFACE_("AO"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_REFLECT)); te->name = IFACE_("Reflection"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_REFRACT)); te->name = IFACE_("Refraction"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDIRECT)); te->name = IFACE_("Indirect"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_ENVIRONMENT)); te->name = IFACE_("Environment"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_EMIT)); te->name = IFACE_("Emit"); - te->directdata = &srl->passflag; + te->directdata = &scene_layer->passflag; } #undef LOG2I @@ -424,19 +332,19 @@ static bool outliner_animdata_test(AnimData *adt) #ifdef WITH_FREESTYLE static void outliner_add_line_styles(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te) { - SceneRenderLayer *srl; + SceneLayer *scene_layer; FreestyleLineSet *lineset; - for (srl = sce->r.layers.first; srl; srl = srl->next) { - for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { + for (scene_layer = sce->render_layers.first; scene_layer; scene_layer = scene_layer->next) { + for (lineset = scene_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) { FreestyleLineStyle *linestyle = lineset->linestyle; if (linestyle) { linestyle->id.tag |= LIB_TAG_DOIT; } } } - for (srl = sce->r.layers.first; srl; srl = srl->next) { - for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { + for (scene_layer = sce->render_layers.first; scene_layer; scene_layer = scene_layer->next) { + for (lineset = scene_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) { FreestyleLineStyle *linestyle = lineset->linestyle; if (linestyle) { if (!(linestyle->id.tag & LIB_TAG_DOIT)) @@ -451,22 +359,16 @@ static void outliner_add_line_styles(SpaceOops *soops, ListBase *lb, Scene *sce, static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te) { - SceneRenderLayer *srl; + SceneLayer *scene_layer; TreeElement *tenla = outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0); int a; tenla->name = IFACE_("RenderLayers"); - for (a = 0, srl = sce->r.layers.first; srl; srl = srl->next, a++) { + for (a = 0, scene_layer = sce->render_layers.first; scene_layer; scene_layer = scene_layer->next, a++) { TreeElement *tenlay = outliner_add_element(soops, &tenla->subtree, sce, te, TSE_R_LAYER, a); - tenlay->name = srl->name; - tenlay->directdata = &srl->layflag; - - if (srl->light_override) - outliner_add_element(soops, &tenlay->subtree, srl->light_override, tenlay, TSE_LINKED_LAMP, 0); - if (srl->mat_override) - outliner_add_element(soops, &tenlay->subtree, srl->mat_override, tenlay, TSE_LINKED_MAT, 0); - - outliner_add_passes(soops, tenlay, &sce->id, srl); + tenlay->name = scene_layer->name; + tenlay->directdata = &scene_layer->flag; + outliner_add_passes(soops, tenlay, &sce->id, scene_layer); } // TODO: move this to the front? @@ -478,17 +380,62 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s outliner_add_element(soops, lb, sce->world, te, 0, 0); #ifdef WITH_FREESTYLE - if (STREQ(sce->r.engine, RE_engine_id_BLENDER_RENDER) && (sce->r.mode & R_EDGE_FRS)) + if (STREQ(sce->view_render->engine_id, RE_engine_id_BLENDER_RENDER) && (sce->r.mode & R_EDGE_FRS)) outliner_add_line_styles(soops, lb, sce, te); #endif } +static void outliner_object_reorder( + Main *UNUSED(bmain), const Scene *scene, + TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action) +{ + TreeStoreElem *tselem_insert = TREESTORE(insert_element); + Object *ob = (Object *)tselem_insert->id; + SceneCollection *sc = outliner_scene_collection_from_tree_element(insert_handle); + SceneCollection *sc_ob_parent = NULL; + + BLI_assert(action == TE_INSERT_INTO); + UNUSED_VARS_NDEBUG(action); + + /* find parent scene-collection of object */ + if (insert_element->parent) { + for (TreeElement *te_ob_parent = insert_element->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) { + if (ELEM(TREESTORE(te_ob_parent)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) { + sc_ob_parent = outliner_scene_collection_from_tree_element(te_ob_parent); + break; + } + } + } + else { + sc_ob_parent = BKE_collection_master(scene); + } + BKE_collection_object_move(scene, sc, sc_ob_parent, ob); +} + +static bool outliner_object_reorder_poll( + const Scene *UNUSED(scene), const TreeElement *insert_element, + TreeElement **io_insert_handle, TreeElementInsertType *io_action) +{ + TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle); + if (ELEM(tselem_handle->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION) && + (insert_element->parent != *io_insert_handle)) + { + *io_action = TE_INSERT_INTO; + return true; + } + + return false; +} + // can be inlined if necessary static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, Object *ob) { + te->reinsert = outliner_object_reorder; + te->reinsert_poll = outliner_object_reorder_poll; + if (outliner_animdata_test(ob->adt)) outliner_add_element(soops, &te->subtree, ob, te, TSE_ANIM_DATA, 0); - + outliner_add_element(soops, &te->subtree, ob->poselib, te, 0, 0); // XXX FIXME.. add a special type for this if (ob->proxy && !ID_IS_LINKED(ob)) @@ -778,6 +725,14 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor outliner_add_element(soops, &te->subtree, spk, te, TSE_ANIM_DATA, 0); break; } + case ID_LP: + { + LightProbe *prb = (LightProbe *)id; + + if (outliner_animdata_test(prb->adt)) + outliner_add_element(soops, &te->subtree, prb, te, TSE_ANIM_DATA, 0); + break; + } case ID_WO: { World *wrld = (World *)id; @@ -905,8 +860,8 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i id = TREESTORE(parent)->id; } - /* One exception */ - if (type == TSE_ID_BASE) { + /* exceptions */ + if (ELEM(type, TSE_ID_BASE, TSE_LAYER_COLLECTION)) { /* pass */ } else if (id == NULL) { @@ -943,6 +898,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i else if (type == TSE_GP_LAYER) { /* pass */ } + else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) { + /* pass */ + } else if (type == TSE_ID_BASE) { /* pass */ } @@ -1244,6 +1202,15 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i return te; } +/** + * \note Really only removes \a tselem, not it's TreeElement instance or any children. + */ +void outliner_remove_treestore_element(SpaceOops *soops, TreeStoreElem *tselem) +{ + BKE_outliner_treehash_remove_element(soops->treehash, tselem); + BLI_mempool_free(soops->treestore, tselem); +} + /* ======================================================= */ /* Sequencer mode tree building */ @@ -1381,6 +1348,141 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops) } } +static void outliner_layer_collections_reorder( + Main *bmain, const Scene *scene, + TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action) +{ + LayerCollection *lc_insert = insert_element->directdata; + LayerCollection *lc_handle = insert_handle->directdata; + + if (action == TE_INSERT_BEFORE) { + BKE_layer_collection_move_above(scene, lc_handle, lc_insert); + } + else if (action == TE_INSERT_AFTER) { + BKE_layer_collection_move_below(scene, lc_handle, lc_insert); + } + else if (action == TE_INSERT_INTO) { + BKE_layer_collection_move_into(scene, lc_handle, lc_insert); + } + else { + BLI_assert(0); + } + + DEG_relations_tag_update(bmain); +} +static bool outliner_layer_collections_reorder_poll( + const Scene *UNUSED(scene), const TreeElement *UNUSED(insert_element), + TreeElement **io_insert_handle, TreeElementInsertType *UNUSED(io_action)) +{ + const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle); + return ELEM(tselem_handle->type, TSE_LAYER_COLLECTION); +} + +static void outliner_add_layer_collections_recursive( + SpaceOops *soops, ListBase *tree, ListBase *layer_collections, TreeElement *parent_ten) +{ + for (LayerCollection *collection = layer_collections->first; collection; collection = collection->next) { + TreeElement *ten = outliner_add_element(soops, tree, collection, parent_ten, TSE_LAYER_COLLECTION, 0); + + ten->name = collection->scene_collection->name; + ten->directdata = collection; + ten->reinsert = outliner_layer_collections_reorder; + ten->reinsert_poll = outliner_layer_collections_reorder_poll; + + outliner_add_layer_collections_recursive(soops, &ten->subtree, &collection->layer_collections, ten); + for (LinkData *link = collection->object_bases.first; link; link = link->next) { + Base *base = (Base *)link->data; + TreeElement *te_object = outliner_add_element(soops, &ten->subtree, base->object, ten, 0, 0); + te_object->directdata = base; + } + outliner_make_hierarchy(&ten->subtree); + } +} +static void outliner_add_collections_act_layer(SpaceOops *soops, SceneLayer *layer) +{ + outliner_add_layer_collections_recursive(soops, &soops->tree, &layer->layer_collections, NULL); +} + +static void outliner_scene_collections_reorder( + Main *bmain, const Scene *scene, + TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action) +{ + SceneCollection *sc_insert = insert_element->directdata; + SceneCollection *sc_handle = insert_handle->directdata; + + BLI_assert((action == TE_INSERT_INTO) || (sc_handle != BKE_collection_master(scene))); + if (action == TE_INSERT_BEFORE) { + BKE_collection_move_above(scene, sc_handle, sc_insert); + } + else if (action == TE_INSERT_AFTER) { + BKE_collection_move_below(scene, sc_handle, sc_insert); + } + else if (action == TE_INSERT_INTO) { + BKE_collection_move_into(scene, sc_handle, sc_insert); + } + else { + BLI_assert(0); + } + + DEG_relations_tag_update(bmain); +} +static bool outliner_scene_collections_reorder_poll( + const Scene *scene, const TreeElement *UNUSED(insert_element), + TreeElement **io_insert_handle, TreeElementInsertType *io_action) +{ + const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle); + SceneCollection *sc_master = BKE_collection_master(scene); + SceneCollection *sc_handle = (*io_insert_handle)->directdata; + + if (!ELEM(tselem_handle->type, TSE_SCENE_COLLECTION)) { + return false; + } + + if (sc_handle == sc_master) { + /* exception: Can't insert before/after master selection, has to be one of its childs */ + TreeElement *te_master = *io_insert_handle; + if (*io_action == TE_INSERT_BEFORE) { + /* can't go higher than master collection, insert into it */ + *io_action = TE_INSERT_INTO; + } + else if (*io_action == TE_INSERT_AFTER) { + *io_insert_handle = te_master->subtree.last; + } + } + return true; +} + +static void outliner_add_scene_collection_objects( + SpaceOops *soops, ListBase *tree, SceneCollection *collection, TreeElement *parent) +{ + for (LinkData *link = collection->objects.first; link; link = link->next) { + outliner_add_element(soops, tree, link->data, parent, 0, 0); + } + outliner_make_hierarchy(tree); +} + +static void outliner_add_scene_collections_recursive( + SpaceOops *soops, ListBase *tree, ListBase *scene_collections, TreeElement *parent_ten) +{ + for (SceneCollection *collection = scene_collections->first; collection; collection = collection->next) { + TreeElement *ten = outliner_add_element(soops, tree, collection, parent_ten, TSE_SCENE_COLLECTION, 0); + + ten->name = collection->name; + ten->directdata = collection; + ten->reinsert = outliner_scene_collections_reorder; + ten->reinsert_poll = outliner_scene_collections_reorder_poll; + + outliner_add_scene_collections_recursive(soops, &ten->subtree, &collection->scene_collections, ten); + outliner_add_scene_collection_objects(soops, &ten->subtree, collection, ten); + } +} +static void outliner_add_collections_master(SpaceOops *soops, Scene *scene) +{ + SceneCollection *master = BKE_collection_master(scene); + outliner_add_scene_collections_recursive(soops, &soops->tree, &master->scene_collections, NULL); + outliner_add_scene_collection_objects(soops, &soops->tree, master, NULL); +} + /* ======================================================= */ /* Generic Tree Building helpers - order these are called is top to bottom */ @@ -1494,18 +1596,15 @@ static void outliner_sort(ListBase *lb) { TreeElement *te; TreeStoreElem *tselem; - int totelem = 0; te = lb->last; if (te == NULL) return; tselem = TREESTORE(te); - + /* sorting rules; only object lists, ID lists, or deformgroups */ - if ( ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || (tselem->type == 0 && te->idcode == ID_OB)) { - - /* count first */ - for (te = lb->first; te; te = te->next) totelem++; - + if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || (tselem->type == 0 && te->idcode == ID_OB)) { + int totelem = BLI_listbase_count(lb); + if (totelem > 1) { tTreeSort *tear = MEM_mallocN(totelem * sizeof(tTreeSort), "tree sort array"); tTreeSort *tp = tear; @@ -1630,9 +1729,8 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb) /* Main entry point for building the tree data-structure that the outliner represents */ // TODO: split each mode into its own function? -void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) +void outliner_build_tree(Main *mainvar, Scene *scene, SceneLayer *sl, SpaceOops *soops) { - Base *base; TreeElement *te = NULL, *ten; TreeStoreElem *tselem; int show_opened = !soops->treestore || !BLI_mempool_count(soops->treestore); /* on first view, we open scenes */ @@ -1713,31 +1811,42 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) tselem = TREESTORE(te); if (sce == scene && show_opened) tselem->flag &= ~TSE_CLOSED; - - for (base = sce->base.first; base; base = base->next) { - ten = outliner_add_element(soops, &te->subtree, base->object, te, 0, 0); - ten->directdata = base; + + FOREACH_SCENE_OBJECT(scene, ob) + { + outliner_add_element(soops, &te->subtree, ob, te, 0, 0); } + FOREACH_SCENE_OBJECT_END + outliner_make_hierarchy(&te->subtree); + /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */ - for (base = sce->base.first; base; base = base->next) base->object->id.newid = NULL; + FOREACH_SCENE_OBJECT(scene, ob) + { + ob->id.newid = NULL; + } + FOREACH_SCENE_OBJECT_END } } else if (soops->outlinevis == SO_CUR_SCENE) { outliner_add_scene_contents(soops, &soops->tree, scene, NULL); - - for (base = scene->base.first; base; base = base->next) { - ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); - ten->directdata = base; + + FOREACH_SCENE_OBJECT(scene, ob) + { + outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0); } + FOREACH_SCENE_OBJECT_END outliner_make_hierarchy(&soops->tree); } else if (soops->outlinevis == SO_VISIBLE) { - for (base = scene->base.first; base; base = base->next) { - if (base->lay & scene->lay) - outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); + FOREACH_VISIBLE_BASE(sl, base) + { + ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); + ten->directdata = base; + } + FOREACH_VISIBLE_BASE_END outliner_make_hierarchy(&soops->tree); } else if (soops->outlinevis == SO_GROUPS) { @@ -1749,8 +1858,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) te = outliner_add_element(soops, &soops->tree, group, NULL, 0, 0); for (go = group->gobject.first; go; go = go->next) { - ten = outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0); - ten->directdata = NULL; /* eh, why? */ + outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0); } outliner_make_hierarchy(&te->subtree); /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */ @@ -1759,26 +1867,25 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) } } else if (soops->outlinevis == SO_SAME_TYPE) { - Object *ob = OBACT; - if (ob) { - for (base = scene->base.first; base; base = base->next) { - if (base->object->type == ob->type) { - ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); - ten->directdata = base; + Object *ob_active = OBACT(sl); + if (ob_active) { + FOREACH_SCENE_OBJECT(scene, ob) + { + if (ob->type == ob_active->type) { + outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0); } } + FOREACH_SCENE_OBJECT_END outliner_make_hierarchy(&soops->tree); } } else if (soops->outlinevis == SO_SELECTED) { - for (base = scene->base.first; base; base = base->next) { - if (base->lay & scene->lay) { - if (base->flag & SELECT) { - ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); - ten->directdata = base; - } - } + FOREACH_SELECTED_BASE(sl, base) + { + ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); + ten->directdata = base; } + FOREACH_SELECTED_BASE_END outliner_make_hierarchy(&soops->tree); } else if (soops->outlinevis == SO_SEQUENCE) { @@ -1832,9 +1939,15 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) else if (soops->outlinevis == SO_ID_ORPHANS) { outliner_add_orphaned_datablocks(mainvar, soops); } + else if (soops->outlinevis == SO_ACT_LAYER) { + outliner_add_collections_act_layer(soops, sl); + } + else if (soops->outlinevis == SO_COLLECTIONS) { + outliner_add_collections_master(soops, scene); + } else { - ten = outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0); - if (ten) ten->directdata = BASACT; + ten = outliner_add_element(soops, &soops->tree, OBACT(sl), NULL, 0, 0); + ten->directdata = BASACT(sl); } if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) { diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c new file mode 100644 index 00000000000..d3f7fd7055e --- /dev/null +++ b/source/blender/editors/space_outliner/outliner_utils.c @@ -0,0 +1,233 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_outliner/outliner_utils.c + * \ingroup spoutliner + */ + +#include "BLI_utildefines.h" + +#include "DNA_action_types.h" +#include "DNA_space_types.h" + +#include "BKE_outliner_treehash.h" + +#include "ED_armature.h" + +#include "UI_interface.h" + +#include "outliner_intern.h" + +/** + * Try to find an item under y-coordinate \a view_co_y (view-space). + * \note Recursive + */ +TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tree, float view_co_y) +{ + for (TreeElement *te_iter = tree->first; te_iter; te_iter = te_iter->next) { + if (view_co_y < (te_iter->ys + UI_UNIT_Y)) { + if (view_co_y >= te_iter->ys) { + /* co_y is inside this element */ + return te_iter; + } + else if (TSELEM_OPEN(te_iter->store_elem, soops)) { + /* co_y is lower than current element, possibly inside children */ + TreeElement *te_sub = outliner_find_item_at_y(soops, &te_iter->subtree, view_co_y); + if (te_sub) { + return te_sub; + } + } + } + } + + return NULL; +} + +/** + * Collapsed items can show their children as click-able icons. This function tries to find + * such an icon that represents the child item at x-coordinate \a view_co_x (view-space). + * + * \return a hovered child item or \a parent_te (if no hovered child found). + */ +TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeElement *parent_te, float view_co_x) +{ + if (!TSELEM_OPEN(TREESTORE(parent_te), soops)) { /* if parent_te is opened, it doesn't show childs in row */ + /* no recursion, items can only display their direct children in the row */ + for (TreeElement *child_te = parent_te->subtree.first; + child_te && view_co_x >= child_te->xs; /* don't look further if co_x is smaller than child position*/ + child_te = child_te->next) + { + if ((child_te->flag & TE_ICONROW) && (view_co_x > child_te->xs) && (view_co_x < child_te->xend)) { + return child_te; + } + } + } + + /* return parent if no child is hovered */ + return (TreeElement *)parent_te; +} + +/* Find specific item from the treestore */ +TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem) +{ + TreeElement *te, *tes; + for (te = lb->first; te; te = te->next) { + if (te->store_elem == store_elem) return te; + tes = outliner_find_tree_element(&te->subtree, store_elem); + if (tes) return tes; + } + return NULL; +} + +/* tse is not in the treestore, we use its contents to find a match */ +TreeElement *outliner_find_tse(SpaceOops *soops, const TreeStoreElem *tse) +{ + TreeStoreElem *tselem; + + if (tse->id == NULL) return NULL; + + /* check if 'tse' is in treestore */ + tselem = BKE_outliner_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id); + if (tselem) + return outliner_find_tree_element(&soops->tree, tselem); + + return NULL; +} + +/* Find treestore that refers to given ID */ +TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, const ID *id) +{ + for (TreeElement *te = lb->first; te; te = te->next) { + TreeStoreElem *tselem = TREESTORE(te); + if (tselem->type == 0) { + if (tselem->id == id) { + return te; + } + /* only deeper on scene or object */ + if (ELEM(te->idcode, ID_OB, ID_SCE) || + ((soops->outlinevis == SO_GROUPS) && (te->idcode == ID_GR))) + { + TreeElement *tes = outliner_find_id(soops, &te->subtree, id); + if (tes) { + return tes; + } + } + } + } + return NULL; +} + +TreeElement *outliner_find_posechannel(ListBase *lb, const bPoseChannel *pchan) +{ + for (TreeElement *te = lb->first; te; te = te->next) { + if (te->directdata == pchan) { + return te; + } + + TreeStoreElem *tselem = TREESTORE(te); + if (ELEM(tselem->type, TSE_POSE_BASE, TSE_POSE_CHANNEL)) { + TreeElement *tes = outliner_find_posechannel(&te->subtree, pchan); + if (tes) { + return tes; + } + } + } + return NULL; +} + +TreeElement *outliner_find_editbone(ListBase *lb, const EditBone *ebone) +{ + for (TreeElement *te = lb->first; te; te = te->next) { + if (te->directdata == ebone) { + return te; + } + + TreeStoreElem *tselem = TREESTORE(te); + if (ELEM(tselem->type, 0, TSE_EBONE)) { + TreeElement *tes = outliner_find_editbone(&te->subtree, ebone); + if (tes) { + return tes; + } + } + } + return NULL; +} + +ID *outliner_search_back(SpaceOops *UNUSED(soops), TreeElement *te, short idcode) +{ + TreeStoreElem *tselem; + te = te->parent; + + while (te) { + tselem = TREESTORE(te); + if (tselem->type == 0 && te->idcode == idcode) return tselem->id; + te = te->parent; + } + return NULL; +} + +/** + * Iterate over all tree elements (pre-order traversal), executing \a func callback for + * each tree element matching the optional filters. + * + * \param filter_te_flag: If not 0, only TreeElements with this flag will be visited. + * \param filter_tselem_flag: Same as \a filter_te_flag, but for the TreeStoreElem. + * \param func: Custom callback to execute for each visited item. + */ +bool outliner_tree_traverse(const SpaceOops *soops, ListBase *tree, int filter_te_flag, int filter_tselem_flag, + TreeTraversalFunc func, void *customdata) +{ + for (TreeElement *te = tree->first, *te_next; te; te = te_next) { + TreeTraversalAction func_retval = TRAVERSE_CONTINUE; + /* in case te is freed in callback */ + TreeStoreElem *tselem = TREESTORE(te); + ListBase subtree = te->subtree; + te_next = te->next; + + if (filter_te_flag && (te->flag & filter_te_flag) == 0) { + /* skip */ + } + else if (filter_tselem_flag && (tselem->flag & filter_tselem_flag) == 0) { + /* skip */ + } + else { + func_retval = func(te, customdata); + } + /* Don't access te or tselem from now on! Might've been freed... */ + + if (func_retval == TRAVERSE_BREAK) { + return false; + } + + if (func_retval == TRAVERSE_SKIP_CHILDS) { + /* skip */ + } + else if (!outliner_tree_traverse(soops, &subtree, filter_te_flag, filter_tselem_flag, func, customdata)) { + return false; + } + } + + return true; +} diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 759ef4e78e4..229d999eb9e 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -39,6 +39,7 @@ #include "BLI_mempool.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_screen.h" #include "BKE_scene.h" #include "BKE_outliner_treehash.h" @@ -102,10 +103,14 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e if (GS(id->name) == ID_OB) { /* Ensure item under cursor is valid drop target */ TreeElement *te = outliner_dropzone_find(soops, fmval, true); + TreeStoreElem *tselem = te ? TREESTORE(te) : NULL; - if (te && te->idcode == ID_OB && TREESTORE(te)->type == 0) { + if (!te) { + /* pass */ + } + else if (te->idcode == ID_OB && tselem->type == 0) { Scene *scene; - ID *te_id = TREESTORE(te)->id; + ID *te_id = tselem->id; /* check if dropping self or parent */ if (te_id == id || (Object *)te_id == ((Object *)id)->parent) @@ -118,10 +123,23 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e * element for object it means that all displayed objects belong to * active scene and parenting them is allowed (sergey) */ - if (!scene || BKE_scene_base_find(scene, (Object *)id)) { + if (!scene) { return 1; + } else { + for (SceneLayer *scene_layer = scene->render_layers.first; + scene_layer; + scene_layer = scene_layer->next) + { + if (BKE_scene_layer_base_find(scene_layer, (Object *)id)) { + return 1; + } + } } } + else if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) { + /* support adding object from different scene to collection */ + return 1; + } } } return 0; @@ -292,7 +310,9 @@ static void outliner_main_region_free(ARegion *UNUSED(ar)) } -static void outliner_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void outliner_main_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -308,6 +328,7 @@ static void outliner_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(s case ND_RENDER_OPTIONS: case ND_SEQUENCER: case ND_LAYER: + case ND_LAYER_CONTENT: case ND_WORLD: ED_region_tag_redraw(ar); break; @@ -392,6 +413,11 @@ static void outliner_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(s if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) ED_region_tag_redraw(ar); break; + case NC_SCREEN: + if (ELEM(wmn->data, ND_LAYER)) { + ED_region_tag_redraw(ar); + } + break; } } @@ -414,7 +440,9 @@ static void outliner_header_region_free(ARegion *UNUSED(ar)) { } -static void outliner_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void outliner_header_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c index 4228635ccd6..fb8de02d3bd 100644 --- a/source/blender/editors/space_script/space_script.c +++ b/source/blender/editors/space_script/space_script.c @@ -176,7 +176,9 @@ static void script_header_region_draw(const bContext *C, ARegion *ar) ED_region_header(C, ar); } -static void script_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn)) +static void script_main_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), + wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene)) { /* context changes */ // XXX - Todo, need the ScriptSpace accessible to get the python script to run. diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt index 6dce962ee02..6b8108a1265 100644 --- a/source/blender/editors/space_sequencer/CMakeLists.txt +++ b/source/blender/editors/space_sequencer/CMakeLists.txt @@ -54,7 +54,7 @@ set(SRC ) if(WITH_AUDASPACE) - add_definitions(${AUDASPACE_DEFINITIONS}) + add_definitions(-DWITH_AUDASPACE) list(APPEND INC_SYS ${AUDASPACE_C_INCLUDE_DIRS} diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 258cbdfaffd..0b6bacfbe68 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -69,7 +69,7 @@ #include "BKE_sound.h" #ifdef WITH_AUDASPACE -# include AUD_SEQUENCE_H +# include <AUD_Sequence.h> #endif /* own include */ diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 160aa157189..01b7c8793ba 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -56,10 +56,11 @@ #include "IMB_colormanagement.h" #include "IMB_imbuf.h" -#include "BIF_gl.h" #include "BIF_glutil.h" -#include "GPU_basic_shader.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" #include "ED_anim_api.h" #include "ED_gpencil.h" @@ -191,25 +192,35 @@ void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3]) } } -static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequence *seq, float x1, float y1, float x2, float y2, float stepsize) +static void drawseqwave(View2D *v2d, const bContext *C, SpaceSeq *sseq, Scene *scene, Sequence *seq, + float x1, float y1, float x2, float y2, float stepsize, unsigned int pos) { /* * x1 is the starting x value to draw the wave, * x2 the end x value, same for y1 and y2 * stepsize is width of a pixel. */ + + /* offset x1 and x2 values, to match view min/max, if strip is out of bounds */ + int x1_offset = max_ff(v2d->cur.xmin, x1); + int x2_offset = min_ff(v2d->cur.xmax + 1.0f, x2); + if (seq->sound && ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM))) { - int i, j, pos; - int length = floor((x2 - x1) / stepsize) + 1; - float ymid = (y1 + y2) / 2; - float yscale = (y2 - y1) / 2; + int i, j, p; + int length = floor((x2_offset - x1_offset) / stepsize) + 1; + float ymid = (y1 + y2) / 2.0f; + float yscale = (y2 - y1) / 2.0f; float samplestep; float startsample, endsample; float value1, value2; bSound *sound = seq->sound; SoundWaveform *waveform; - + + if (length < 2) { + return; + } + if (!sound->spinlock) { sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); BLI_spin_init(sound->spinlock); @@ -242,21 +253,27 @@ static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequenc endsample = ceil((seq->startofs + seq->anim_startofs + seq->enddisp - seq->startdisp) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND); samplestep = (endsample - startsample) * stepsize / (x2 - x1); - if (length > floor((waveform->length - startsample) / samplestep)) - length = floor((waveform->length - startsample) / samplestep); + length = min_ii(floor((waveform->length - startsample) / samplestep), length); + + if (length < 2) { + return; + } + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f); - glColor4f(1.0f, 1.0f, 1.0f, 0.5); glEnable(GL_BLEND); - glBegin(GL_TRIANGLE_STRIP); + + immBegin(GWN_PRIM_TRI_STRIP, length * 2); + for (i = 0; i < length; i++) { - float sampleoffset = startsample + i * samplestep; - pos = sampleoffset; + float sampleoffset = startsample + ((x1_offset - x1) / stepsize + i) * samplestep; + p = sampleoffset; - value1 = waveform->data[pos * 3]; - value2 = waveform->data[pos * 3 + 1]; + value1 = waveform->data[p * 3]; + value2 = waveform->data[p * 3 + 1]; if (samplestep > 1.0f) { - for (j = pos + 1; (j < waveform->length) && (j < pos + samplestep); j++) { + for (j = p + 1; (j < waveform->length) && (j < p + samplestep); j++) { if (value1 > waveform->data[j * 3]) value1 = waveform->data[j * 3]; @@ -266,34 +283,20 @@ static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequenc } else { /* use simple linear interpolation */ - float f = sampleoffset - pos; - value1 = (1.0f - f) * value1 + f * waveform->data[pos * 3 + 3]; - value2 = (1.0f - f) * value2 + f * waveform->data[pos * 3 + 4]; + float f = sampleoffset - p; + value1 = (1.0f - f) * value1 + f * waveform->data[p * 3 + 3]; + value2 = (1.0f - f) * value2 + f * waveform->data[p * 3 + 4]; } - glVertex2f(x1 + i * stepsize, ymid + value1 * yscale); - glVertex2f(x1 + i * stepsize, ymid + value2 * yscale); + immVertex2f(pos, x1_offset + i * stepsize, ymid + value1 * yscale); + immVertex2f(pos, x1_offset + i * stepsize, ymid + value2 * yscale); } - glEnd(); - glDisable(GL_BLEND); - } -} -static void drawmeta_stipple(int value) -{ - if (value) { - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_HALFTONE); - - glEnable(GL_LINE_STIPPLE); - glLineStipple(1, 0x8888); - } - else { - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - glDisable(GL_LINE_STIPPLE); + immEnd(); + + glDisable(GL_BLEND); } } - static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, float x2, float y2) { /* note: this used to use SEQ_BEGIN/SEQ_END, but it messes up the @@ -326,9 +329,6 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if (seqm->flag & SEQ_MUTE) - drawmeta_stipple(1); - for (seq = seqbase->first; seq; seq = seq->next) { chan_min = min_ii(chan_min, seq->machine); chan_max = max_ii(chan_max, seq->machine); @@ -339,6 +339,10 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, col[3] = 196; /* alpha, used for all meta children */ + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + for (seq = seqbase->first; seq; seq = seq->next) { const int startdisp = seq->startdisp + offset; const int enddisp = seq->enddisp + offset; @@ -349,12 +353,16 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, float x2_chan = enddisp; float y1_chan, y2_chan; - if ((seqm->flag & SEQ_MUTE) == 0 && (seq->flag & SEQ_MUTE)) - drawmeta_stipple(1); - color3ubv_from_seq(scene, seq, col); - glColor4ubv(col); + if ((seqm->flag & SEQ_MUTE) || (seq->flag & SEQ_MUTE)) { + col[3] = 64; + } + else { + col[3] = 196; + } + + immUniformColor4ubv(col); /* clamp within parent sequence strip bounds */ if (x1_chan < x1) x1_chan = x1; @@ -363,20 +371,12 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, y1_chan = y1 + y_chan + (draw_height * SEQ_STRIP_OFSBOTTOM); y2_chan = y1 + y_chan + (draw_height * SEQ_STRIP_OFSTOP); - glRectf(x1_chan, y1_chan, x2_chan, y2_chan); - - UI_GetColorPtrShade3ubv(col, col, -30); - glColor4ubv(col); - fdrawbox(x1_chan, y1_chan, x2_chan, y2_chan); - - if ((seqm->flag & SEQ_MUTE) == 0 && (seq->flag & SEQ_MUTE)) - drawmeta_stipple(0); + immRectf(pos, x1_chan, y1_chan, x2_chan, y2_chan); } } - if (seqm->flag & SEQ_MUTE) - drawmeta_stipple(0); - + immUnbindProgram(); + glDisable(GL_BLEND); } @@ -392,7 +392,7 @@ static float draw_seq_handle_size_get_clamped(Sequence *seq, const float pixelx) } /* draw a handle, for each end of a sequence strip */ -static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_clamped, const short direction) +static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_clamped, const short direction, unsigned int pos) { float v1[2], v2[2], v3[2], rx1 = 0, rx2 = 0; //for triangles and rect float x1, x2, y1, y2; @@ -434,21 +434,31 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if (seq->flag & whichsel) glColor4ub(0, 0, 0, 80); - else if (seq->flag & SELECT) glColor4ub(255, 255, 255, 30); - else glColor4ub(0, 0, 0, 22); - - glRectf(rx1, y1, rx2, y2); - - if (seq->flag & whichsel) glColor4ub(255, 255, 255, 200); - else glColor4ub(0, 0, 0, 50); + if (seq->flag & whichsel) { + immUniformColor4ub(0, 0, 0, 80); + } + else if (seq->flag & SELECT) { + immUniformColor4ub(255, 255, 255, 30); + } + else { + immUniformColor4ub(0, 0, 0, 22); + } - glEnable(GL_POLYGON_SMOOTH); - glBegin(GL_TRIANGLES); - glVertex2fv(v1); glVertex2fv(v2); glVertex2fv(v3); - glEnd(); + immRectf(pos, rx1, y1, rx2, y2); - glDisable(GL_POLYGON_SMOOTH); + if (seq->flag & whichsel) { + immUniformColor4ub(255, 255, 255, 200); + } + else { + immUniformColor4ub(0, 0, 0, 50); + } + + immBegin(GWN_PRIM_TRIS, 3); + immVertex2fv(pos, v1); + immVertex2fv(pos, v2); + immVertex2fv(pos, v3); + immEnd(); + glDisable(GL_BLEND); } @@ -587,67 +597,10 @@ static void draw_seq_text(View2D *v2d, SpaceSeq *sseq, Sequence *seq, float x1, UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col); } -/* draws a shaded strip, made from gradient + flat color + gradient */ -void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2) +static void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq, unsigned int pos) { - float ymid1, ymid2; - - if (seq->flag & SEQ_MUTE) { - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_HALFTONE); - } - - ymid1 = (y2 - y1) * 0.25f + y1; - ymid2 = (y2 - y1) * 0.65f + y1; - - glBegin(GL_QUADS); - - if (seq->flag & SEQ_INVALID_EFFECT) { col[0] = 255; col[1] = 0; col[2] = 255; } - else if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, -50); - /* else UI_GetColorPtrShade3ubv(col, col, 0); */ /* DO NOTHING */ - - glColor3ubv(col); - - glVertex2f(x1, y1); - glVertex2f(x2, y1); - - if (seq->flag & SEQ_INVALID_EFFECT) { col[0] = 255; col[1] = 0; col[2] = 255; } - else if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 5); - else UI_GetColorPtrShade3ubv(col, col, -5); - - glColor3ubv((GLubyte *)col); - - glVertex2f(x2, ymid1); - glVertex2f(x1, ymid1); - - glEnd(); - - glRectf(x1, ymid1, x2, ymid2); - - glBegin(GL_QUADS); - - glVertex2f(x1, ymid2); - glVertex2f(x2, ymid2); - - if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, -15); - else UI_GetColorPtrShade3ubv(col, col, 25); - - glColor3ubv((GLubyte *)col); - - glVertex2f(x2, y2); - glVertex2f(x1, y2); - - glEnd(); - - if (seq->flag & SEQ_MUTE) { - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } -} - -void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq) -{ - float x1, x2, y1, y2, pixely, a; - unsigned char col[3], blendcol[3]; + float x1, x2, y1, y2, pixely; + unsigned char col[4], blendcol[3]; View2D *v2d = &ar->v2d; x1 = seq->startdisp; @@ -661,90 +614,82 @@ void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq) if (pixely <= 0) return; /* can happen when the view is split/resized */ blendcol[0] = blendcol[1] = blendcol[2] = 120; - - if (seq->startofs) { + + if (seq->startofs || seq->endofs) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); color3ubv_from_seq(scene, seq, col); - + if (seq->flag & SELECT) { - UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40); - glColor4ub(col[0], col[1], col[2], 170); + UI_GetColorPtrShade3ubv(col, col, -50); + } + + if (seq->flag & SEQ_MUTE) { + col[3] = 64; } else { - UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0); - glColor4ub(col[0], col[1], col[2], 110); + if (seq->flag & SELECT) { + col[3] = 170; + } + else { + col[3] = 80; + } } - - glRectf((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1); - - if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255); - else glColor4ub(col[0], col[1], col[2], 160); - - fdrawbox((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1); //outline - - glDisable(GL_BLEND); + } + + if (seq->startofs) { + immUniformColor4ubv(col); + immRectf(pos, (float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1); + + immUniformColor3ubvAlpha(col, col[3] + 50); + + imm_draw_box_wire_2d(pos, (float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1); /* outline */ } if (seq->endofs) { + immUniformColor4ubv(col); + immRectf(pos, x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); + + immUniformColor3ubvAlpha(col, col[3] + 50); + + imm_draw_box_wire_2d(pos, x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); /* outline */ + } + + if (seq->startofs || seq->endofs) { + glDisable(GL_BLEND); + } + + if (seq->startstill || seq->endstill) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - + color3ubv_from_seq(scene, seq, col); - - if (seq->flag & SELECT) { - UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40); - glColor4ub(col[0], col[1], col[2], 170); + UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5f, 60); + + if (seq->flag & SEQ_MUTE) { + col[3] = 96; } else { - UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0); - glColor4ub(col[0], col[1], col[2], 110); + if (seq->flag & SELECT) { + col[3] = 255; + } + else { + col[3] = 170; + } } - - glRectf(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); - - if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255); - else glColor4ub(col[0], col[1], col[2], 160); - - fdrawbox(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); //outline - - glDisable(GL_BLEND); + + immUniformColor4ubv(col); } + if (seq->startstill) { - color3ubv_from_seq(scene, seq, col); - UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40); - glColor3ubv((GLubyte *)col); - - draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2); - - /* feint pinstripes, helps see exactly which is extended and which isn't, - * especially when the extension is very small */ - if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24); - else UI_GetColorPtrShade3ubv(col, col, -16); - - glColor3ubv((GLubyte *)col); - - for (a = y1; a < y2; a += pixely * 2.0f) { - fdrawline(x1, a, (float)(seq->start), a); - } + immRectf(pos, x1, y1, (float)(seq->start), y2); } if (seq->endstill) { - color3ubv_from_seq(scene, seq, col); - UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40); - glColor3ubv((GLubyte *)col); - - draw_shadedstrip(seq, col, (float)(seq->start + seq->len), y1, x2, y2); - - /* feint pinstripes, helps see exactly which is extended and which isn't, - * especially when the extension is very small */ - if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, 24); - else UI_GetColorPtrShade3ubv(col, col, -16); - - glColor3ubv((GLubyte *)col); - - for (a = y1; a < y2; a += pixely * 2.0f) { - fdrawline((float)(seq->start + seq->len), a, x2, a); - } + immRectf(pos, (float)(seq->start + seq->len), y1, x2, y2); + } + + if (seq->startstill || seq->endstill) { + glDisable(GL_BLEND); } } @@ -758,7 +703,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg { View2D *v2d = &ar->v2d; float x1, x2, y1, y2; - unsigned char col[3], background_col[3], is_single_image; + unsigned char col[4], background_col[4], is_single_image; const float handsize_clamped = draw_seq_handle_size_get_clamped(seq, pixelx); /* we need to know if this is a single image/color or not for drawing */ @@ -770,72 +715,105 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg x2 = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp; y2 = seq->machine + SEQ_STRIP_OFSTOP; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* get the correct color per strip type*/ //color3ubv_from_seq(scene, seq, col); color3ubv_from_seq(scene, seq, background_col); - + + if (seq->flag & SEQ_MUTE) { + background_col[3] = 128; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + else { + background_col[3] = 255; + } + + if (seq->flag & SELECT) { + UI_GetColorPtrShade3ubv(background_col, background_col, -50); + } + + immUniformColor4ubv(background_col); + /* draw the main strip body */ if (is_single_image) { /* single image */ - draw_shadedstrip(seq, background_col, - BKE_sequence_tx_get_final_left(seq, false), y1, - BKE_sequence_tx_get_final_right(seq, false), y2); + immRectf(pos, BKE_sequence_tx_get_final_left(seq, false), y1, + BKE_sequence_tx_get_final_right(seq, false), y2); } else { /* normal operation */ - draw_shadedstrip(seq, background_col, x1, y1, x2, y2); + immRectf(pos, x1, y1, x2, y2); + } + + if (seq->flag & SEQ_MUTE) { + glDisable(GL_BLEND); } if (!is_single_image) { if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) { - draw_sequence_extensions(scene, ar, seq); + draw_sequence_extensions(scene, ar, seq, pos); } } - draw_seq_handle(v2d, seq, handsize_clamped, SEQ_LEFTHANDLE); - draw_seq_handle(v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE); - - /* draw the strip outline */ + draw_seq_handle(v2d, seq, handsize_clamped, SEQ_LEFTHANDLE, pos); + draw_seq_handle(v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE, pos); + x1 = seq->startdisp; x2 = seq->enddisp; /* draw sound wave */ if (seq->type == SEQ_TYPE_SOUND_RAM) { if (!(sseq->flag & SEQ_NO_WAVEFORMS)) { - drawseqwave(C, sseq, scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx); + drawseqwave(v2d, C, sseq, scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx, pos); } } + immUnbindProgram(); + /* draw lock */ if (seq->flag & SEQ_LOCK) { - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); glEnable(GL_BLEND); - /* light stripes */ - glColor4ub(255, 255, 255, 32); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_DIAG_STRIPES); - glRectf(x1, y1, x2, y2); + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES); + + immUniform4f("color1", 1.0f, 1.0f, 1.0f, 0.125f); + immUniform4f("color2", 0.0f, 0.0f, 0.0f, 0.125f); + immUniform1i("size1", 8); + immUniform1i("size2", 8); + + immRectf(pos, x1, y1, x2, y2); - /* dark stripes */ - glColor4ub(0, 0, 0, 32); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_DIAG_STRIPES_SWAP); - glRectf(x1, y1, x2, y2); + immUnbindProgram(); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); glDisable(GL_BLEND); } if (!BKE_sequence_is_valid_check(seq)) { - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); + glEnable(GL_BLEND); + + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES); + + immUniform4f("color1", 1.0f, 0.0f, 0.0f, 1.0f); + immUniform4f("color2", 0.0f, 0.0f, 0.0f, 0.0f); + immUniform1i("size1", 8); + immUniform1i("size2", 8); - /* panic! */ - glColor4ub(255, 0, 0, 255); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_DIAG_STRIPES); - glRectf(x1, y1, x2, y2); + immRectf(pos, x1, y1, x2, y2); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + immUnbindProgram(); + + glDisable(GL_BLEND); } color3ubv_from_seq(scene, seq, col); + + /* draw the strip outline */ + color3ubv_from_seq(scene, seq, col); if ((G.moving & G_TRANSFORM_SEQ) && (seq->flag & SELECT)) { if (seq->flag & SEQ_OVERLAP) { col[0] = 255; col[1] = col[2] = 40; @@ -852,19 +830,27 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg drawmeta_contents(scene, seq, x1, y1, x2, y2); } + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + /* TODO: add back stippled line for muted strips? */ + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + if (seq->flag & SEQ_MUTE) { - glEnable(GL_LINE_STIPPLE); - glLineStipple(1, 0x8888); + col[3] = 96; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + immUniformColor4ubv(col); } - - glColor3ubv((GLubyte *)col); - - UI_draw_roundbox_shade_x(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0); - - if (seq->flag & SEQ_MUTE) { - glDisable(GL_LINE_STIPPLE); + else { + immUniformColor3ubv(col); } - + + imm_draw_box_wire_2d(pos, x1, y1, x2, y2); /* outline */ + + immUnbindProgram(); + /* calculate if seq is long enough to print a name */ x1 = seq->startdisp + handsize_clamped; x2 = seq->enddisp - handsize_clamped; @@ -1048,33 +1034,39 @@ static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, cons glLineWidth(1.0f); /* border */ - setlinestyle(3); + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - glBegin(GL_LINE_LOOP); - glVertex2f(x1 - 0.5f, y1 - 0.5f); - glVertex2f(x1 - 0.5f, y2 + 0.5f); - glVertex2f(x2 + 0.5f, y2 + 0.5f); - glVertex2f(x2 + 0.5f, y1 - 0.5f); - glEnd(); + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniformThemeColor(TH_BACK); + immUniform1i("num_colors", 0); /* Simple dashes. */ + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + + imm_draw_box_wire_2d(shdr_pos, x1 - 0.5f, y1 - 0.5f, x2 + 0.5f, y2 + 0.5f); /* safety border */ if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) { + immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f); + UI_draw_safe_areas( - x1, x2, y1, y2, + shdr_pos, x1, x2, y1, y2, scene->safe_areas.title, scene->safe_areas.action); if (sseq->flag & SEQ_SHOW_SAFE_CENTER) { UI_draw_safe_areas( - x1, x2, y1, y2, + shdr_pos, x1, x2, y1, y2, scene->safe_areas.title_center, scene->safe_areas.action_center); } } - setlinestyle(0); + immUnbindProgram(); } /* draws checkerboard background for transparent content */ @@ -1089,11 +1081,7 @@ static void sequencer_draw_background( /* only draw alpha for main buffer */ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { if ((sseq->flag & SEQ_USE_ALPHA) && !draw_overlay) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax); - glColor4f(1.0, 1.0, 1.0, 1.0); + imm_draw_box_checker_2d(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax); } } } @@ -1135,9 +1123,6 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq glClear(GL_COLOR_BUFFER_BIT); } - /* without this colors can flicker from previous opengl state */ - glColor4ub(255, 255, 255, 255); - /* only initialize the preview if a render is in progress */ if (G.is_rendering) return; @@ -1152,15 +1137,16 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq if ((ibuf == NULL) || (ibuf->rect == NULL && ibuf->rect_float == NULL)) { - /* gpencil can also be drawn without a valid imbuf */ - if ((draw_gpencil && is_imbuf) && !draw_overlay) { - sequencer_display_size(scene, sseq, viewrect); + sequencer_display_size(scene, sseq, viewrect); - sequencer_draw_background(sseq, v2d, viewrect, false); - sequencer_draw_borders(sseq, v2d, scene); + sequencer_draw_background(sseq, v2d, viewrect, false); + sequencer_draw_borders(sseq, v2d, scene); + /* gpencil can also be drawn without a valid imbuf */ + if ((draw_gpencil && is_imbuf) && !draw_overlay) { sequencer_draw_gpencil(C); } + return; } @@ -1229,6 +1215,18 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq sequencer_draw_background(sseq, v2d, viewrect, draw_overlay); } + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + /* Format needs to be created prior to any immBindProgram call. + * Do it here because OCIO binds it's own shader. + */ + Gwn_VertFormat *imm_format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(imm_format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int texCoord = GWN_vertformat_attr_add(imm_format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + if (scope) { IMB_freeImBuf(ibuf); ibuf = scope; @@ -1301,9 +1299,12 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq } } - glColor4f(1.0, 1.0, 1.0, 1.0); + if (draw_backdrop) { + /* XXX: need to load identity projection too? */ + gpuPushMatrix(); + gpuLoadIdentity(); + } - GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR); glGenTextures(1, (GLuint *)&texid); glBindTexture(GL_TEXTURE_2D, texid); @@ -1316,15 +1317,13 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer); - if (draw_backdrop) { - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); + if (!glsl_used) { + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); + immUniformColor3f(1.0f, 1.0f, 1.0f); + immUniform1i("image", GL_TEXTURE0); } - glBegin(GL_QUADS); + + immBegin(GWN_PRIM_TRI_FAN, 4); if (draw_overlay) { if (sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) { @@ -1334,16 +1333,30 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq tot_clip.xmax = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmax); tot_clip.ymax = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymax); - glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmin, tot_clip.ymin); - glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmin, tot_clip.ymax); - glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmax, tot_clip.ymax); - glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmax, tot_clip.ymin); + immAttrib2f(texCoord, scene->ed->over_border.xmin, scene->ed->over_border.ymin); + immVertex2f(pos, tot_clip.xmin, tot_clip.ymin); + + immAttrib2f(texCoord, scene->ed->over_border.xmin, scene->ed->over_border.ymax); + immVertex2f(pos, tot_clip.xmin, tot_clip.ymax); + + immAttrib2f(texCoord, scene->ed->over_border.xmax, scene->ed->over_border.ymax); + immVertex2f(pos, tot_clip.xmax, tot_clip.ymax); + + immAttrib2f(texCoord, scene->ed->over_border.xmax, scene->ed->over_border.ymin); + immVertex2f(pos, tot_clip.xmax, tot_clip.ymin); } else if (sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) { - glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin); - glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax); - glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax); - glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin); + immAttrib2f(texCoord, 0.0f, 0.0f); + immVertex2f(pos, v2d->tot.xmin, v2d->tot.ymin); + + immAttrib2f(texCoord, 0.0f, 1.0f); + immVertex2f(pos, v2d->tot.xmin, v2d->tot.ymax); + + immAttrib2f(texCoord, 1.0f, 1.0f); + immVertex2f(pos, v2d->tot.xmax, v2d->tot.ymax); + + immAttrib2f(texCoord, 1.0f, 0.0f); + immVertex2f(pos, v2d->tot.xmax, v2d->tot.ymin); } } else if (draw_backdrop) { @@ -1362,25 +1375,46 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq imagey = aspect / image_aspect; } - glTexCoord2f(0.0f, 0.0f); glVertex2f(-imagex, -imagey); - glTexCoord2f(0.0f, 1.0f); glVertex2f(-imagex, imagey); - glTexCoord2f(1.0f, 1.0f); glVertex2f(imagex, imagey); - glTexCoord2f(1.0f, 0.0f); glVertex2f(imagex, -imagey); + immAttrib2f(texCoord, 0.0f, 0.0f); + immVertex2f(pos, -imagex, -imagey); + + immAttrib2f(texCoord, 0.0f, 1.0f); + immVertex2f(pos, -imagex, imagey); + + immAttrib2f(texCoord, 1.0f, 1.0f); + immVertex2f(pos, imagex, imagey); + + immAttrib2f(texCoord, 1.0f, 0.0f); + immVertex2f(pos, imagex, -imagey); } else { draw_metadata = ((sseq->flag & SEQ_SHOW_METADATA) != 0); - glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin); - glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax); - glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax); - glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin); + immAttrib2f(texCoord, 0.0f, 0.0f); + immVertex2f(pos, v2d->tot.xmin, v2d->tot.ymin); + + immAttrib2f(texCoord, 0.0f, 1.0f); + immVertex2f(pos, v2d->tot.xmin, v2d->tot.ymax); + + immAttrib2f(texCoord, 1.0f, 1.0f); + immVertex2f(pos, v2d->tot.xmax, v2d->tot.ymax); + + immAttrib2f(texCoord, 1.0f, 0.0f); + immVertex2f(pos, v2d->tot.xmax, v2d->tot.ymin); } - glEnd(); + + immEnd(); glBindTexture(GL_TEXTURE_2D, 0); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) + + if (!glsl_used) { + immUnbindProgram(); + } + + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) { glDisable(GL_BLEND); + } + glDeleteTextures(1, &texid); if (glsl_used) @@ -1397,10 +1431,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq } if (draw_backdrop) { - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); + gpuPopMatrix(); return; } @@ -1474,42 +1505,42 @@ void drawprefetchseqspace(Scene *scene, ARegion *UNUSED(ar), SpaceSeq *sseq) static void draw_seq_backdrop(View2D *v2d) { int i; - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* darker gray overlay over the view backdrop */ - UI_ThemeColorShade(TH_BACK, -20); - glRectf(v2d->cur.xmin, -1.0, v2d->cur.xmax, 1.0); + immUniformThemeColorShade(TH_BACK, -20); + immRectf(pos, v2d->cur.xmin, -1.0, v2d->cur.xmax, 1.0); /* Alternating horizontal stripes */ i = max_ii(1, ((int)v2d->cur.ymin) - 1); - glBegin(GL_QUADS); while (i < v2d->cur.ymax) { - if (((int)i) & 1) - UI_ThemeColorShade(TH_BACK, -15); - else - UI_ThemeColorShade(TH_BACK, -25); - - glVertex2f(v2d->cur.xmax, i); - glVertex2f(v2d->cur.xmin, i); - glVertex2f(v2d->cur.xmin, i + 1); - glVertex2f(v2d->cur.xmax, i + 1); + if (i & 1) { + immUniformThemeColorShade(TH_BACK, -15); + } + else { + immUniformThemeColorShade(TH_BACK, -25); + } + + immRectf(pos, v2d->cur.xmin, i, v2d->cur.xmax, i + 1); - i += 1.0; + i++; } - glEnd(); - + /* Darker lines separating the horizontal bands */ i = max_ii(1, ((int)v2d->cur.ymin) - 1); - UI_ThemeColor(TH_GRID); - - glBegin(GL_LINES); - while (i < v2d->cur.ymax) { - glVertex2f(v2d->cur.xmax, i); - glVertex2f(v2d->cur.xmin, i); - - i += 1.0; + int line_ct = (int)v2d->cur.ymax - i + 1; + immUniformThemeColor(TH_GRID); + immBegin(GWN_PRIM_LINES, line_ct * 2); + while (line_ct--) { + immVertex2f(pos, v2d->cur.xmax, i); + immVertex2f(pos, v2d->cur.xmin, i); } - glEnd(); + immEnd(); + + immUnbindProgram(); } /* draw the contents of the sequencer strips view */ @@ -1525,7 +1556,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar) /* loop through twice, first unselected, then selected */ for (j = 0; j < 2; j++) { Sequence *seq; - int outline_tint = (j) ? -60 : -150; /* highlighting around strip edges indicating selection */ + int outline_tint = (j) ? 40 : -40; /* highlighting around strip edges indicating selection */ /* loop through strips, checking for those that are visible */ for (seq = ed->seqbasep->first; seq; seq = seq->next) { @@ -1553,8 +1584,15 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar) if (special_seq_update) { const Sequence *seq = special_seq_update; glEnable(GL_BLEND); - glColor4ub(255, 255, 255, 48); - glRectf(seq->startdisp, seq->machine + SEQ_STRIP_OFSBOTTOM, seq->enddisp, seq->machine + SEQ_STRIP_OFSTOP); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4ub(255, 255, 255, 48); + immRectf(pos, seq->startdisp, seq->machine + SEQ_STRIP_OFSBOTTOM, seq->enddisp, seq->machine + SEQ_STRIP_OFSTOP); + + immUnbindProgram(); + glDisable(GL_BLEND); } } @@ -1566,36 +1604,56 @@ static void seq_draw_sfra_efra(Scene *scene, View2D *v2d) const int frame_end = PEFRA + 1; glEnable(GL_BLEND); - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* draw darkened area outside of active timeline * frame range used is preview range or scene range */ - UI_ThemeColorShadeAlpha(TH_BACK, -25, -100); + immUniformThemeColorShadeAlpha(TH_BACK, -25, -100); if (frame_sta < frame_end) { - glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)frame_sta, v2d->cur.ymax); - glRectf((float)frame_end, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)frame_sta, v2d->cur.ymax); + immRectf(pos, (float)frame_end, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); } else { - glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); } - UI_ThemeColorShade(TH_BACK, -60); + immUniformThemeColorShade(TH_BACK, -60); + /* thin lines where the actual frames are */ - fdrawline(frame_sta, v2d->cur.ymin, frame_sta, v2d->cur.ymax); - fdrawline(frame_end, v2d->cur.ymin, frame_end, v2d->cur.ymax); + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, frame_sta, v2d->cur.ymin); + immVertex2f(pos, frame_sta, v2d->cur.ymax); + + immVertex2f(pos, frame_end, v2d->cur.ymin); + immVertex2f(pos, frame_end, v2d->cur.ymax); + + immEnd(); if (ed && !BLI_listbase_is_empty(&ed->metastack)) { MetaStack *ms = ed->metastack.last; - glColor4ub(255, 255, 255, 8); - glRectf(ms->disp_range[0], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax); + immUniformColor4ub(255, 255, 255, 8); + immRectf(pos, ms->disp_range[0], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax); + + immUniformThemeColorShade(TH_BACK, -40); - UI_ThemeColorShade(TH_BACK, -40); + immBegin(GWN_PRIM_LINES, 4); - fdrawline(ms->disp_range[0], v2d->cur.ymin, ms->disp_range[0], v2d->cur.ymax); - fdrawline(ms->disp_range[1], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax); + immVertex2f(pos, ms->disp_range[0], v2d->cur.ymin); + immVertex2f(pos, ms->disp_range[0], v2d->cur.ymax); + + immVertex2f(pos, ms->disp_range[1], v2d->cur.ymin); + immVertex2f(pos, ms->disp_range[1], v2d->cur.ymax); + + immEnd(); } + immUnbindProgram(); + glDisable(GL_BLEND); } @@ -1669,16 +1727,20 @@ void draw_timeline_seq(const bContext *C, ARegion *ar) /* overlap playhead */ if (scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) { int cfra_over = (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) ? scene->ed->over_cfra : scene->r.cfra + scene->ed->over_ofs; - glColor3f(0.2, 0.2, 0.2); - // glRectf(cfra_over, v2d->cur.ymin, scene->ed->over_ofs + scene->r.cfra + 1, v2d->cur.ymax); - glBegin(GL_LINES); - glVertex2f(cfra_over, v2d->cur.ymin); - glVertex2f(cfra_over, v2d->cur.ymax); - glEnd(); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3f(0.2f, 0.2f, 0.2f); + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, cfra_over, v2d->cur.ymin); + immVertex2f(pos, cfra_over, v2d->cur.ymax); + immEnd(); + + immUnbindProgram(); } - + /* callback */ ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index f0c67ac3294..a8a5bc6e96b 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -1256,7 +1256,6 @@ typedef struct SlipData { int num_seq; bool slow; int slow_offset; /* offset at the point where offset was turned on */ - void *draw_handle; NumInput num_input; } SlipData; @@ -1291,21 +1290,6 @@ static void transseq_restore(TransSeq *ts, Sequence *seq) seq->len = ts->len; } -static void draw_slip_extensions(const bContext *C, ARegion *ar, void *data) -{ - Scene *scene = CTX_data_scene(C); - SlipData *td = data; - int i; - - for (i = 0; i < td->num_seq; i++) { - Sequence *seq = td->seq_array[i]; - - if ((seq->type != SEQ_TYPE_META) && td->trim[i]) { - draw_sequence_extensions(scene, ar, seq); - } - } -} - static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim) { Sequence *seq; @@ -1354,7 +1338,6 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve SlipData *data; Scene *scene = CTX_data_scene(C); Editing *ed = BKE_sequencer_editing_get(scene, false); - ARegion *ar = CTX_wm_region(C); float mouseloc[2]; int num_seq, i; View2D *v2d = UI_view2d_fromcontext(C); @@ -1384,8 +1367,6 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve transseq_backup(data->ts + i, data->seq_array[i]); } - data->draw_handle = ED_region_draw_cb_activate(ar->type, draw_slip_extensions, data, REGION_DRAW_POST_VIEW); - UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]); copy_v2_v2_int(data->init_mouse, event->mval); @@ -1527,7 +1508,6 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even Scene *scene = CTX_data_scene(C); SlipData *data = (SlipData *)op->customdata; ScrArea *sa = CTX_wm_area(C); - ARegion *ar = CTX_wm_region(C); const bool has_numInput = hasNumInput(&data->num_input); bool handled = true; @@ -1585,7 +1565,6 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even case RETKEY: case SPACEKEY: { - ED_region_draw_cb_exit(ar->type, data->draw_handle); MEM_freeN(data->seq_array); MEM_freeN(data->trim); MEM_freeN(data->ts); @@ -1614,8 +1593,6 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even BKE_sequence_calc(scene, seq); } - ED_region_draw_cb_exit(ar->type, data->draw_handle); - MEM_freeN(data->seq_array); MEM_freeN(data->ts); MEM_freeN(data->trim); diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 730cc117287..7ce2f73cbef 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -56,8 +56,6 @@ struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa); void draw_timeline_seq(const struct bContext *C, struct ARegion *ar); void draw_image_seq(const struct bContext *C, struct Scene *scene, struct ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, bool draw_overlay, bool draw_backdrop); void color3ubv_from_seq(struct Scene *curscene, struct Sequence *seq, unsigned char col[3]); -void draw_shadedstrip(struct Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2); -void draw_sequence_extensions(struct Scene *scene, struct ARegion *ar, struct Sequence *seq); void sequencer_special_update_set(Sequence *seq); diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index f1d0f23f8af..da16ac5acaa 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -337,7 +337,9 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl) return (SpaceLink *)sseqn; } -static void sequencer_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) +static void sequencer_listener( + bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { /* context changes */ switch (wmn->category) { @@ -491,7 +493,9 @@ static void sequencer_main_region_draw(const bContext *C, ARegion *ar) draw_timeline_seq(C, ar); } -static void sequencer_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void sequencer_main_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -597,7 +601,9 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *ar) } } -static void sequencer_preview_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void sequencer_preview_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -663,7 +669,9 @@ static void sequencer_buttons_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, NULL, -1, true); } -static void sequencer_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void sequencer_buttons_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index fcb46ced750..539fe1c53bd 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -125,7 +125,8 @@ static SpaceLink *text_duplicate(SpaceLink *sl) return (SpaceLink *)stextn; } -static void text_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) +static void text_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { SpaceText *st = sa->spacedata.first; diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 70b5feac280..fcb675abcf2 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -49,6 +49,8 @@ #include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_immediate.h" + #include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -123,38 +125,38 @@ static void txt_format_text(SpaceText *st) #endif /* Sets the current drawing color based on the format character specified */ -static void format_draw_color(char formatchar) +static void format_draw_color(const TextDrawContext *tdc, char formatchar) { switch (formatchar) { case FMT_TYPE_WHITESPACE: break; case FMT_TYPE_SYMBOL: - UI_ThemeColor(TH_SYNTAX_S); + UI_FontThemeColor(tdc->font_id, TH_SYNTAX_S); break; case FMT_TYPE_COMMENT: - UI_ThemeColor(TH_SYNTAX_C); + UI_FontThemeColor(tdc->font_id, TH_SYNTAX_C); break; case FMT_TYPE_NUMERAL: - UI_ThemeColor(TH_SYNTAX_N); + UI_FontThemeColor(tdc->font_id, TH_SYNTAX_N); break; case FMT_TYPE_STRING: - UI_ThemeColor(TH_SYNTAX_L); + UI_FontThemeColor(tdc->font_id, TH_SYNTAX_L); break; case FMT_TYPE_DIRECTIVE: - UI_ThemeColor(TH_SYNTAX_D); + UI_FontThemeColor(tdc->font_id, TH_SYNTAX_D); break; case FMT_TYPE_SPECIAL: - UI_ThemeColor(TH_SYNTAX_V); + UI_FontThemeColor(tdc->font_id, TH_SYNTAX_V); break; case FMT_TYPE_RESERVED: - UI_ThemeColor(TH_SYNTAX_R); + UI_FontThemeColor(tdc->font_id, TH_SYNTAX_R); break; case FMT_TYPE_KEYWORD: - UI_ThemeColor(TH_SYNTAX_B); + UI_FontThemeColor(tdc->font_id, TH_SYNTAX_B); break; case FMT_TYPE_DEFAULT: default: - UI_ThemeColor(TH_TEXT); + UI_FontThemeColor(tdc->font_id, TH_TEXT); break; } } @@ -429,7 +431,7 @@ static int text_draw_wrapped( /* Draw the visible portion of text on the overshot line */ for (a = fstart, ma = mstart; ma < mend; a++, ma += BLI_str_utf8_size_safe(str + ma)) { if (use_syntax) { - if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]); + if (fmt_prev != format[a]) format_draw_color(tdc, fmt_prev = format[a]); } x += text_font_draw_character_utf8(tdc, x, y, str + ma); fpos++; @@ -452,7 +454,7 @@ static int text_draw_wrapped( /* Draw the remaining text */ for (a = fstart, ma = mstart; str[ma] && y > clip_min_y; a++, ma += BLI_str_utf8_size_safe(str + ma)) { if (use_syntax) { - if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]); + if (fmt_prev != format[a]) format_draw_color(tdc, fmt_prev = format[a]); } x += text_font_draw_character_utf8(tdc, x, y, str + ma); @@ -505,7 +507,7 @@ static void text_draw( char fmt_prev = 0xff; for (a = 0; a < amount; a++) { - if (format[a] != fmt_prev) format_draw_color(fmt_prev = format[a]); + if (format[a] != fmt_prev) format_draw_color(tdc, fmt_prev = format[a]); x += text_font_draw_character_utf8(tdc, x, y, in + str_shift); str_shift += BLI_str_utf8_size_safe(in + str_shift); } @@ -906,22 +908,23 @@ static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back) { bTheme *btheme = UI_GetTheme(); uiWidgetColors wcol = btheme->tui.wcol_scroll; - unsigned char col[4]; + float col[4]; float rad; - - UI_ThemeColor(TH_BACK); - glRecti(back->xmin, back->ymin, back->xmax, back->ymax); + + /* background so highlights don't go behind the scrollbar */ + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_BACK); + immRecti(pos, back->xmin, back->ymin, back->xmax, back->ymax); + immUnbindProgram(); UI_draw_widget_scroll(&wcol, scroll, &st->txtbar, (st->flags & ST_SCROLL_SELECT) ? UI_SCROLL_PRESSED : 0); UI_draw_roundbox_corner_set(UI_CNR_ALL); rad = 0.4f * min_ii(BLI_rcti_size_x(&st->txtscroll), BLI_rcti_size_y(&st->txtscroll)); - UI_GetThemeColor3ubv(TH_HILITE, col); - col[3] = 48; - glColor4ubv(col); - glEnable(GL_BLEND); - UI_draw_roundbox(st->txtscroll.xmin + 1, st->txtscroll.ymin, st->txtscroll.xmax - 1, st->txtscroll.ymax, rad); - glDisable(GL_BLEND); + UI_GetThemeColor3fv(TH_HILITE, col); + col[3] = 0.18f; + UI_draw_roundbox_aa(true, st->txtscroll.xmin + 1, st->txtscroll.ymin, st->txtscroll.xmax - 1, st->txtscroll.ymax, rad, col); } /*********************** draw documentation *******************************/ @@ -963,26 +966,32 @@ static void draw_documentation(const SpaceText *st, ARegion *ar) boxh = (DOC_HEIGHT + 1) * (st->lheight_dpi + TXT_LINE_SPACING); /* Draw panel */ - UI_ThemeColor(TH_BACK); - glRecti(x, y, x + boxw, y - boxh); - UI_ThemeColor(TH_SHADE1); - glBegin(GL_LINE_LOOP); - glVertex2i(x, y); - glVertex2i(x + boxw, y); - glVertex2i(x + boxw, y - boxh); - glVertex2i(x, y - boxh); - glEnd(); - glBegin(GL_LINE_LOOP); - glVertex2i(x + boxw - 10, y - 7); - glVertex2i(x + boxw - 4, y - 7); - glVertex2i(x + boxw - 7, y - 2); - glEnd(); - glBegin(GL_LINE_LOOP); - glVertex2i(x + boxw - 10, y - boxh + 7); - glVertex2i(x + boxw - 4, y - boxh + 7); - glVertex2i(x + boxw - 7, y - boxh + 2); - glEnd(); - UI_ThemeColor(TH_TEXT); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColor(TH_BACK); + immRecti(pos, x, y, x + boxw, y - boxh); + immUniformThemeColor(TH_SHADE1); + immBegin(GWN_PRIM_LINE_LOOP, 4); + immVertex2i(pos, x, y); + immVertex2i(pos, x + boxw, y); + immVertex2i(pos, x + boxw, y - boxh); + immVertex2i(pos, x, y - boxh); + immEnd(); + immBegin(GWN_PRIM_LINE_LOOP, 3); + immVertex2i(pos, x + boxw - 10, y - 7); + immVertex2i(pos, x + boxw - 4, y - 7); + immVertex2i(pos, x + boxw - 7, y - 2); + immEnd(); + immBegin(GWN_PRIM_LINE_LOOP, 3); + immVertex2i(pos, x + boxw - 10, y - boxh + 7); + immVertex2i(pos, x + boxw - 4, y - boxh + 7); + immVertex2i(pos, x + boxw - 7, y - boxh + 2); + immEnd(); + + immUnbindProgram(); + + UI_FontThemeColor(tdc.font_id, TH_TEXT); i = 0; br = DOC_WIDTH; lines = 0; // XXX -doc_scroll; for (p = docs; *p; p++) { @@ -1009,11 +1018,6 @@ static void draw_documentation(const SpaceText *st, ARegion *ar) } if (lines >= DOC_HEIGHT) break; } - - if (0 /* XXX doc_scroll*/ /* > 0 && lines < DOC_HEIGHT */) { - // XXX doc_scroll--; - draw_documentation(st, ar); - } } #endif @@ -1061,10 +1065,15 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc /* not needed but stands out nicer */ UI_draw_box_shadow(220, x, y - boxh, x + boxw, y); - UI_ThemeColor(TH_SHADE1); - glRecti(x - 1, y + 1, x + boxw + 1, y - boxh - 1); - UI_ThemeColorShade(TH_BACK, 16); - glRecti(x, y, x + boxw, y - boxh); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColor(TH_SHADE1); + immRecti(pos, x - 1, y + 1, x + boxw + 1, y - boxh - 1); + immUniformThemeColorShade(TH_BACK, 16); + immRecti(pos, x, y, x + boxw, y - boxh); + + immUnbindProgram(); /* Set the top 'item' of the visible list */ for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ; @@ -1079,11 +1088,16 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc w = st->cwidth * text_get_char_pos(st, str, len); if (item == sel) { - UI_ThemeColor(TH_SHADE2); - glRecti(x + margin_x, y - 3, x + margin_x + w, y + lheight - 3); + unsigned int posi = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColor(TH_SHADE2); + immRecti(posi, x + margin_x, y - 3, x + margin_x + w, y + lheight - 3); + + immUnbindProgram(); } - format_draw_color(item->type); + format_draw_color(tdc, item->type); text_draw(st, tdc, str, 0, 0, x + margin_x, y - 1, NULL); if (item == last) break; @@ -1092,42 +1106,57 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc /*********************** draw cursor ************************/ -static void draw_cursor(SpaceText *st, ARegion *ar) +static void draw_text_decoration(SpaceText *st, ARegion *ar) { Text *text = st->text; int vcurl, vcurc, vsell, vselc, hidden = 0; int x, y, w, i; + int offl, offc; const int lheight = st->lheight_dpi + TXT_LINE_SPACING; + /* Convert to view space character coordinates to determine if cursor is hidden */ + wrap_offset(st, ar, text->sell, text->selc, &offl, &offc); + vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl; + vselc = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc; + + if (vselc < 0) { + vselc = 0; + hidden = 1; + } + + if (text->curl == text->sell && text->curc == text->selc && !st->line_hlight && hidden) { + /* Nothing to draw here */ + return; + } + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* Draw the selection */ if (text->curl != text->sell || text->curc != text->selc) { - int offl, offc; /* Convert all to view space character coordinates */ wrap_offset(st, ar, text->curl, text->curc, &offl, &offc); vcurl = txt_get_span(text->lines.first, text->curl) - st->top + offl; vcurc = text_get_char_pos(st, text->curl->line, text->curc) - st->left + offc; - wrap_offset(st, ar, text->sell, text->selc, &offl, &offc); - vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl; - vselc = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc; if (vcurc < 0) { vcurc = 0; } - if (vselc < 0) { - vselc = 0; - hidden = 1; - } - - UI_ThemeColor(TH_SHADE2); + + immUniformThemeColor(TH_SHADE2); + x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; y = ar->winy; if (vcurl == vsell) { y -= vcurl * lheight; - if (vcurc < vselc) - glRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight); - else - glRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight); + + if (vcurc < vselc) { + immRecti(pos, x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight); + } + else { + immRecti(pos, x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight); + } } else { int froml, fromc, tol, toc; @@ -1143,35 +1172,24 @@ static void draw_cursor(SpaceText *st, ARegion *ar) y -= froml * lheight; - glRecti(x + fromc * st->cwidth - 1, y, ar->winx, y - lheight); + immRecti(pos, x + fromc * st->cwidth - 1, y, ar->winx, y - lheight); y -= lheight; + for (i = froml + 1; i < tol; i++) { - glRecti(x - 4, y, ar->winx, y - lheight); + immRecti(pos, x - 4, y, ar->winx, y - lheight); y -= lheight; } - glRecti(x - 4, y, x + toc * st->cwidth, y - lheight); + immRecti(pos, x - 4, y, x + toc * st->cwidth, y - lheight); y -= lheight; } } - else { - int offl, offc; - wrap_offset(st, ar, text->sell, text->selc, &offl, &offc); - vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl; - vselc = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc; - - if (vselc < 0) { - vselc = 0; - hidden = 1; - } - } if (st->line_hlight) { int x1, x2, y1, y2; if (st->wordwrap) { int visible_lines = text_get_visible_lines(st, ar, text->sell->line); - int offl, offc; wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc); @@ -1187,36 +1205,38 @@ static void draw_cursor(SpaceText *st, ARegion *ar) x1 = 0; // st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; x2 = x1 + ar->winx; - glColor4ub(255, 255, 255, 32); - + immUniformColor4ub(255, 255, 255, 32); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - glRecti(x1 - 4, y1, x2, y2); + immRecti(pos, x1 - 4, y1, x2, y2); glDisable(GL_BLEND); } } - + if (!hidden) { /* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */ x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; x += vselc * st->cwidth; y = ar->winy - vsell * lheight; - + + immUniformThemeColor(TH_HILITE); + if (st->overwrite) { char ch = text->sell->line[text->selc]; - + y += TXT_LINE_SPACING; w = st->cwidth; if (ch == '\t') w *= st->tabnumber - (vselc + st->left) % st->tabnumber; - - UI_ThemeColor(TH_HILITE); - glRecti(x, y - lheight - 1, x + w, y - lheight + 1); + + immRecti(pos, x, y - lheight - 1, x + w, y - lheight + 1); } else { - UI_ThemeColor(TH_HILITE); - glRecti(x - 1, y, x + 1, y - lheight); + immRecti(pos, x - 1, y, x + 1, y - lheight); } } + + immUnbindProgram(); } /******************* draw matching brackets *********************/ @@ -1317,7 +1337,7 @@ static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegi if (!endl || endc == -1) return; - UI_ThemeColor(TH_HILITE); + UI_FontThemeColor(tdc->font_id, TH_HILITE); x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; y = ar->winy - st->lheight_dpi; @@ -1422,8 +1442,11 @@ void draw_text_main(SpaceText *st, ARegion *ar) if (st->showlinenrs) { x = TXT_OFFSET + TEXTXLOC; - UI_ThemeColor(TH_GRID); - glRecti((TXT_OFFSET - 12), 0, (TXT_OFFSET - 5) + TEXTXLOC, ar->winy - 2); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_GRID); + immRecti(pos, (TXT_OFFSET - 12), 0, (TXT_OFFSET - 5) + TEXTXLOC, ar->winy - 2); + immUnbindProgram(); } else { st->linenrs_tot = 0; /* not used */ @@ -1432,11 +1455,11 @@ void draw_text_main(SpaceText *st, ARegion *ar) y = ar->winy - st->lheight_dpi; winx = ar->winx - TXT_SCROLL_WIDTH; - /* draw cursor */ - draw_cursor(st, ar); + /* draw cursor, margin, selection and highlight */ + draw_text_decoration(st, ar); /* draw the text */ - UI_ThemeColor(TH_TEXT); + UI_FontThemeColor(tdc.font_id, TH_TEXT); for (i = 0; y > clip_min_y && i < st->viewlines && tmp; i++, tmp = tmp->next) { if (st->showsyntax && !tmp->format) @@ -1444,16 +1467,20 @@ void draw_text_main(SpaceText *st, ARegion *ar) if (st->showlinenrs && !wrap_skip) { /* draw line number */ - if (tmp == text->curl) - UI_ThemeColor(TH_HILITE); - else - UI_ThemeColor(TH_TEXT); + if (tmp == text->curl) { + UI_FontThemeColor(tdc.font_id, TH_HILITE); + } + else { + UI_FontThemeColor(tdc.font_id, TH_TEXT); + } BLI_snprintf(linenr, sizeof(linenr), "%*d", st->linenrs_tot, i + linecount + 1); /* itoa(i + linecount + 1, linenr, 10); */ /* not ansi-c :/ */ text_font_draw(&tdc, TXT_OFFSET - 7, y, linenr); - UI_ThemeColor(TH_TEXT); + if (tmp == text->curl) { + UI_FontThemeColor(tdc.font_id, TH_TEXT); + } } if (st->wordwrap) { @@ -1474,15 +1501,24 @@ void draw_text_main(SpaceText *st, ARegion *ar) margin_column_x = x + st->cwidth * (st->margin_column - st->left); if (margin_column_x >= x) { - /* same color as line number background */ - UI_ThemeColor(TH_GRID); - - setlinestyle(1); - glBegin(GL_LINES); - glVertex2i(margin_column_x, 0); - glVertex2i(margin_column_x, ar->winy - 2); - glEnd(); - setlinestyle(0); + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniformThemeColor(TH_GRID); /* same color as line number background */ + immUniform1f("dash_width", 2.0f); + immUniform1f("dash_factor", 0.5f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2i(shdr_pos, margin_column_x, 0); + immVertex2i(shdr_pos, margin_column_x, ar->winy - 2); + immEnd(); + immUnbindProgram(); } } diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 4f0d2c93970..772cd6bd419 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -694,7 +694,7 @@ static int text_refresh_pyconstraints_exec(bContext *UNUSED(C), wmOperator *UNUS } if (update) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } #endif diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index f29d2b30ffe..b9a35de6779 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -60,7 +60,6 @@ #include "WM_types.h" #include "BIF_gl.h" -#include "BIF_glutil.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -69,6 +68,9 @@ #include "ED_space_api.h" #include "ED_markers.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" + #include "time_intern.h" /* ************************ main time area region *********************** */ @@ -80,28 +82,42 @@ static void time_draw_sfra_efra(Scene *scene, View2D *v2d) */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); - + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); + if (PSFRA < PEFRA) { - glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax); - glRectf((float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax); + immRectf(pos, (float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); } else { - glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); } + glDisable(GL_BLEND); - UI_ThemeColorShade(TH_BACK, -60); /* thin lines where the actual frames are */ - fdrawline((float)PSFRA, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax); - fdrawline((float)PEFRA, v2d->cur.ymin, (float)PEFRA, v2d->cur.ymax); + immUniformThemeColorShade(TH_BACK, -60); + + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, (float)PSFRA, v2d->cur.ymin); + immVertex2f(pos, (float)PSFRA, v2d->cur.ymax); + + immVertex2f(pos, (float)PEFRA, v2d->cur.ymin); + immVertex2f(pos, (float)PEFRA, v2d->cur.ymax); + + immEnd(); + immUnbindProgram(); } static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) { PTCacheID *pid; ListBase pidlist; - SpaceTimeCache *stc = stime->caches.first; const float cache_draw_height = (4.0f * UI_DPI_FAC * U.pixelsize); float yoffs = 0.f; @@ -110,12 +126,13 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* iterate over pointcaches on the active object, * add spacetimecache and vertex array for each */ for (pid = pidlist.first; pid; pid = pid->next) { - float col[4], *fp; - int i, sta = pid->cache->startframe, end = pid->cache->endframe; - int len = (end - sta + 1) * 4; + float col[4]; switch (pid->type) { case PTCACHE_TYPE_SOFTBODY: @@ -142,43 +159,9 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) if (pid->cache->cached_frames == NULL) continue; - /* make sure we have stc with correct array length */ - if (stc == NULL || MEM_allocN_len(stc->array) != len * 2 * sizeof(float)) { - if (stc) { - MEM_freeN(stc->array); - } - else { - stc = MEM_callocN(sizeof(SpaceTimeCache), "spacetimecache"); - BLI_addtail(&stime->caches, stc); - } - - stc->array = MEM_callocN(len * 2 * sizeof(float), "SpaceTimeCache array"); - } - - /* fill the vertex array with a quad for each cached frame */ - for (i = sta, fp = stc->array; i <= end; i++) { - if (pid->cache->cached_frames[i - sta]) { - fp[0] = (float)i - 0.5f; - fp[1] = 0.0; - fp += 2; - - fp[0] = (float)i - 0.5f; - fp[1] = 1.0; - fp += 2; - - fp[0] = (float)i + 0.5f; - fp[1] = 1.0; - fp += 2; - - fp[0] = (float)i + 0.5f; - fp[1] = 0.0; - fp += 2; - } - } - - glPushMatrix(); - glTranslatef(0.0, (float)V2D_SCROLL_HEIGHT + yoffs, 0.0); - glScalef(1.0, cache_draw_height, 0.0); + gpuPushMatrix(); + gpuTranslate2f(0.0, (float)V2D_SCROLL_HEIGHT + yoffs); + gpuScale2f(1.0, cache_draw_height); switch (pid->type) { case PTCACHE_TYPE_SOFTBODY: @@ -212,12 +195,15 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) BLI_assert(0); break; } - glColor4fv(col); - + + const int sta = pid->cache->startframe, end = pid->cache->endframe; + const int len = (end - sta + 1) * 6; + glEnable(GL_BLEND); - - glRectf((float)sta, 0.0, (float)end, 1.0); - + + immUniformColor4fv(col); + immRectf(pos, (float)sta, 0.0, (float)end, 1.0); + col[3] = 0.4f; if (pid->cache->flag & PTCACHE_BAKED) { col[0] -= 0.4f; col[1] -= 0.4f; col[2] -= 0.4f; @@ -225,52 +211,38 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) else if (pid->cache->flag & PTCACHE_OUTDATED) { col[0] += 0.4f; col[1] += 0.4f; col[2] += 0.4f; } - glColor4fv(col); - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, stc->array); - glDrawArrays(GL_QUADS, 0, (fp - stc->array) / 2); - glDisableClientState(GL_VERTEX_ARRAY); - - glDisable(GL_BLEND); - - glPopMatrix(); - - yoffs += cache_draw_height; - stc = stc->next; - } + immUniformColor4fv(col); - BLI_freelistN(&pidlist); + if (len > 0) { + immBeginAtMost(GWN_PRIM_TRIS, len); - /* free excessive caches */ - while (stc) { - SpaceTimeCache *tmp = stc->next; - BLI_remlink(&stime->caches, stc); - MEM_freeN(stc->array); - MEM_freeN(stc); - stc = tmp; - } -} + /* draw a quad for each cached frame */ + for (int i = sta; i <= end; i++) { + if (pid->cache->cached_frames[i - sta]) { + immVertex2f(pos, (float)i - 0.5f, 0.0f); + immVertex2f(pos, (float)i - 0.5f, 1.0f); + immVertex2f(pos, (float)i + 0.5f, 1.0f); -static void time_cache_free(SpaceTime *stime) -{ - SpaceTimeCache *stc; - - for (stc = stime->caches.first; stc; stc = stc->next) { - if (stc->array) { - MEM_freeN(stc->array); - stc->array = NULL; + immVertex2f(pos, (float)i - 0.5f, 0.0f); + immVertex2f(pos, (float)i + 0.5f, 1.0f); + immVertex2f(pos, (float)i + 0.5f, 0.0f); + } + } + + immEnd(); } + + glDisable(GL_BLEND); + + gpuPopMatrix(); + + yoffs += cache_draw_height; } - - BLI_freelistN(&stime->caches); -} -static void time_cache_refresh(SpaceTime *stime) -{ - /* Free previous caches to indicate full refresh */ - time_cache_free(stime); + immUnbindProgram(); + + BLI_freelistN(&pidlist); } /* helper function - find actkeycolumn that occurs on cframe, or the nearest one if not found */ @@ -296,7 +268,7 @@ static ActKeyColumn *time_cfra_find_ak(ActKeyColumn *ak, float cframe) } /* helper for time_draw_keyframes() */ -static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel) +static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel, const unsigned char color[3]) { bDopeSheet ads = {NULL}; DLRBT_Tree keys; @@ -341,21 +313,40 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel) * the first visible keyframe (last one can then be easily checked) * - draw within a single GL block to be faster */ - glBegin(GL_LINES); - for (ak = time_cfra_find_ak(keys.root, v2d->cur.xmin); - (ak) && (ak->cfra <= v2d->cur.xmax); - ak = ak->next) - { - glVertex2f(ak->cfra, ymin); - glVertex2f(ak->cfra, ymax); + + ActKeyColumn *link; + int max_len = 0; + + ak = time_cfra_find_ak(keys.root, v2d->cur.xmin); + + for (link = ak; link; link = link->next) { + max_len++; } - glEnd(); // GL_LINES - + + if (max_len > 0) { + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3ubv(color); + + immBeginAtMost(GWN_PRIM_LINES, max_len * 2); + + for (; (ak) && (ak->cfra <= v2d->cur.xmax); ak = ak->next) { + immVertex2f(pos, ak->cfra, ymin); + immVertex2f(pos, ak->cfra, ymax); + } + + immEnd(); + immUnbindProgram(); + } + /* free temp stuff */ BLI_dlrbTree_free(&keys); } -static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, bool onlysel) +static void time_draw_caches_keyframes(Main *bmain, SceneLayer *sl, View2D *v2d, bool onlysel, const unsigned char color[3]) { CacheFile *cache_file; @@ -366,7 +357,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b cache_file->draw_flag &= ~CACHEFILE_KEYFRAME_DRAWN; } - for (Base *base = scene->base.first; base; base = base->next) { + for (Base *base = sl->object_bases.first; base; base = base->next) { Object *ob = base->object; ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache); @@ -382,7 +373,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN; - time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel); + time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel, color); } for (bConstraint *con = ob->constraints.first; con; con = con->next) { @@ -400,7 +391,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN; - time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel); + time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel, color); } } } @@ -409,24 +400,27 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b static void time_draw_keyframes(const bContext *C, ARegion *ar) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob = CTX_data_active_object(C); View2D *v2d = &ar->v2d; bool onlysel = ((scene->flag & SCE_KEYS_NO_SELONLY) == 0); + unsigned char color[3]; /* set this for all keyframe lines once and for all */ glLineWidth(1.0); /* draw cache files keyframes (if available) */ - UI_ThemeColor(TH_TIME_KEYFRAME); - time_draw_caches_keyframes(CTX_data_main(C), scene, v2d, onlysel); + UI_GetThemeColor3ubv(TH_TIME_KEYFRAME, color); + time_draw_caches_keyframes(CTX_data_main(C), sl, v2d, onlysel, color); /* draw grease pencil keyframes (if available) */ - UI_ThemeColor(TH_TIME_GP_KEYFRAME); + UI_GetThemeColor3ubv(TH_TIME_GP_KEYFRAME, color); + if (scene->gpd) { - time_draw_idblock_keyframes(v2d, (ID *)scene->gpd, onlysel); + time_draw_idblock_keyframes(v2d, (ID *)scene->gpd, onlysel, color); } if (ob && ob->gpd) { - time_draw_idblock_keyframes(v2d, (ID *)ob->gpd, onlysel); + time_draw_idblock_keyframes(v2d, (ID *)ob->gpd, onlysel, color); } /* draw scene keyframes first @@ -435,8 +429,8 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar) */ if (onlysel == 0) { /* set draw color */ - UI_ThemeColorShade(TH_TIME_KEYFRAME, -50); - time_draw_idblock_keyframes(v2d, (ID *)scene, onlysel); + UI_GetThemeColorShade3ubv(TH_TIME_KEYFRAME, -50, color); + time_draw_idblock_keyframes(v2d, (ID *)scene, onlysel, color); } /* draw keyframes from selected objects @@ -444,11 +438,11 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar) * OR the onlysel flag was set, which means that only active object's keyframes should * be considered */ - UI_ThemeColor(TH_TIME_KEYFRAME); - + UI_GetThemeColor3ubv(TH_TIME_KEYFRAME, color); + if (ob && ((ob->mode == OB_MODE_POSE) || onlysel)) { /* draw keyframes for active object only */ - time_draw_idblock_keyframes(v2d, (ID *)ob, onlysel); + time_draw_idblock_keyframes(v2d, (ID *)ob, onlysel, color); } else { bool active_done = false; @@ -457,7 +451,7 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar) CTX_DATA_BEGIN (C, Object *, obsel, selected_objects) { /* last arg is 0, since onlysel doesn't apply here... */ - time_draw_idblock_keyframes(v2d, (ID *)obsel, 0); + time_draw_idblock_keyframes(v2d, (ID *)obsel, 0, color); /* if this object is the active one, set flag so that we don't draw again */ if (obsel == ob) @@ -467,24 +461,15 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar) /* if active object hasn't been done yet, draw it... */ if (ob && (active_done == 0)) - time_draw_idblock_keyframes(v2d, (ID *)ob, 0); + time_draw_idblock_keyframes(v2d, (ID *)ob, 0, color); } } /* ---------------- */ -static void time_refresh(const bContext *UNUSED(C), ScrArea *sa) -{ - /* find the main timeline region and refresh cache display*/ - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar) { - SpaceTime *stime = (SpaceTime *)sa->spacedata.first; - time_cache_refresh(stime); - } -} - /* editor level listener */ -static void time_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) +static void time_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { /* mainly for updating cache display */ @@ -625,7 +610,9 @@ static void time_main_region_draw(const bContext *C, ARegion *ar) UI_view2d_scrollers_free(scrollers); } -static void time_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void time_main_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -654,6 +641,11 @@ static void time_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), if (wmn->data == ND_DATA) ED_region_tag_redraw(ar); break; + case NC_SCREEN: + if (ELEM(wmn->data, ND_LAYER)) { + ED_region_tag_redraw(ar); + } + break; } } @@ -670,7 +662,9 @@ static void time_header_region_draw(const bContext *C, ARegion *ar) ED_region_header(C, ar); } -static void time_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void time_header_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -754,13 +748,6 @@ static SpaceLink *time_new(const bContext *C) return (SpaceLink *)stime; } -/* not spacelink itself */ -static void time_free(SpaceLink *sl) -{ - SpaceTime *stime = (SpaceTime *)sl; - - time_cache_free(stime); -} /* spacetype; init callback in ED_area_initialize() */ /* init is called to (re)initialize an existing editor (file read, screen changes) */ /* validate spacedata, add own area level handlers */ @@ -768,8 +755,6 @@ static void time_init(wmWindowManager *UNUSED(wm), ScrArea *sa) { SpaceTime *stime = (SpaceTime *)sa->spacedata.first; - time_cache_free(stime); - /* enable all cache display */ stime->cache_display |= TIME_CACHE_DISPLAY; stime->cache_display |= (TIME_CACHE_SOFTBODY | TIME_CACHE_PARTICLES); @@ -798,13 +783,11 @@ void ED_spacetype_time(void) strncpy(st->name, "Timeline", BKE_ST_MAXNAME); st->new = time_new; - st->free = time_free; st->init = time_init; st->duplicate = time_duplicate; st->operatortypes = time_operatortypes; st->keymap = NULL; st->listener = time_listener; - st->refresh = time_refresh; /* regions: main window */ art = MEM_callocN(sizeof(ARegionType), "spacetype time region"); diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c index aeba4a86f3e..f640fe63f93 100644 --- a/source/blender/editors/space_userpref/space_userpref.c +++ b/source/blender/editors/space_userpref/space_userpref.c @@ -136,12 +136,16 @@ static void userpref_header_region_draw(const bContext *C, ARegion *ar) ED_region_header(C, ar); } -static void userpref_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn)) +static void userpref_main_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), + wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene)) { /* context changes */ } -static void userpref_header_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn)) +static void userpref_header_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), + wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene)) { /* context changes */ #if 0 diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index a5c60248bf1..de8380aa8bb 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -25,6 +25,7 @@ set(INC ../../blenlib ../../blentranslation ../../bmesh + ../../draw ../../gpu ../../imbuf ../../makesdna @@ -52,11 +53,18 @@ set(SRC view3d_buttons.c view3d_camera_control.c view3d_draw.c + view3d_draw_legacy.c view3d_edit.c view3d_fly.c view3d_walk.c view3d_header.c view3d_iterators.c + view3d_manipulator_armature.c + view3d_manipulator_camera.c + view3d_manipulator_empty.c + view3d_manipulator_forcefield.c + view3d_manipulator_lamp.c + view3d_manipulator_ruler.c view3d_ops.c view3d_project.c view3d_ruler.c @@ -94,8 +102,4 @@ if(WITH_MOD_SMOKE) add_definitions(-DWITH_SMOKE) endif() -if(WITH_LEGACY_DEPSGRAPH) - add_definitions(-DWITH_LEGACY_DEPSGRAPH) -endif() - blender_add_lib(bf_editor_space_view3d "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c index f0e65f84205..66355a50478 100644 --- a/source/blender/editors/space_view3d/drawanimviz.c +++ b/source/blender/editors/space_view3d/drawanimviz.c @@ -49,7 +49,8 @@ #include "BKE_animsys.h" #include "BKE_action.h" -#include "BIF_gl.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" #include "ED_keyframes_draw.h" @@ -71,8 +72,8 @@ void draw_motion_paths_init(View3D *v3d, ARegion *ar) if (v3d->zbuf) glDisable(GL_DEPTH_TEST); - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); + gpuPushMatrix(); + gpuLoadMatrix(rv3d->viewmat); } /* set color @@ -86,10 +87,11 @@ void draw_motion_paths_init(View3D *v3d, ARegion *ar) * - User selected color for next frames */ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short sel, int sfra, int efra, - float prev_color[3], float frame_color[3], float next_color[3]) + float prev_color[3], float frame_color[3], float next_color[3], unsigned color) { int frame = sfra + i; int blend_base = (abs(frame - CFRA) == 1) ? TH_CFRAME : TH_BACK; /* "bleed" cframe color to ease color blending */ + unsigned char ubcolor[3]; #define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max - min)) + min) float intensity; /* how faint */ @@ -97,7 +99,7 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short if (frame < CFRA) { if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { /* Custom color: previous frames color is darker than current frame */ - glColor3fv(prev_color); + rgb_float_to_uchar(ubcolor, prev_color); } else { /* black - before cfra */ @@ -109,13 +111,14 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short /* intensity = 0.8f; */ intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f); } - UI_ThemeColorBlend(TH_WIRE, blend_base, intensity); + + UI_GetThemeColorBlend3ubv(TH_WIRE, blend_base, intensity, ubcolor); } } else if (frame > CFRA) { if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { /* Custom color: next frames color is equal to user selected color */ - glColor3fv(next_color); + rgb_float_to_uchar(ubcolor, next_color); } else { /* blue - after cfra */ @@ -127,13 +130,14 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short /* intensity = 0.8f; */ intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f); } - UI_ThemeColorBlend(TH_BONE_POSE, blend_base, intensity); + + UI_GetThemeColorBlend3ubv(TH_BONE_POSE, blend_base, intensity, ubcolor); } } else { if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { /* Custom color: current frame color is slightly darker than user selected color */ - glColor3fv(frame_color); + rgb_float_to_uchar(ubcolor, frame_color); } else { /* green - on cfra */ @@ -143,9 +147,12 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short else { intensity = 0.99f; } - UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10); + UI_GetThemeColorBlendShade3ubv(TH_CFRAME, TH_BACK, intensity, 10, ubcolor); } } + + immAttrib3ubv(color, ubcolor); + #undef SET_INTENSITY } @@ -231,42 +238,65 @@ void draw_motion_path_instance(Scene *scene, /* set line thickness */ glLineWidth(mpath->line_thickness); - glBegin(GL_LINE_STRIP); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); + + immBegin(GWN_PRIM_LINE_STRIP, len); + for (i = 0, mpv = mpv_start; i < len; i++, mpv++) { short sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT); + /* Set color */ - set_motion_path_color(scene, mpath, i, sel, sfra, efra, prev_color, frame_color, next_color); + set_motion_path_color(scene, mpath, i, sel, sfra, efra, prev_color, frame_color, next_color, color); + /* draw a vertex with this color */ - glVertex3fv(mpv->co); + immVertex3fv(pos, mpv->co); } - glEnd(); + immEnd(); + + immUnbindProgram(); + /* back to old line thickness */ glLineWidth(old_width); } + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + /* Point must be bigger than line thickness */ glPointSize(mpath->line_thickness + 1.0); - /* draw little black point at each frame - * NOTE: this is not really visible/noticeable - */ - glBegin(GL_POINTS); - for (i = 0, mpv = mpv_start; i < len; i++, mpv++) - glVertex3fv(mpv->co); - glEnd(); - + /* draw little black point at each frame */ + immUniformColor3ub(0, 0, 0); + + immBegin(GWN_PRIM_POINTS, len); + + for (i = 0, mpv = mpv_start; i < len; i++, mpv++) { + immVertex3fv(pos, mpv->co); + } + + immEnd(); + /* Draw little white dots at each framestep value or replace with custom color */ if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { - glColor4fv(mpath->color); + immUniformColor3fv(mpath->color); } else { - UI_ThemeColor(TH_TEXT_HI); + immUniformThemeColor(TH_TEXT_HI); } - glBegin(GL_POINTS); - for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) - glVertex3fv(mpv->co); - glEnd(); + + immBegin(GWN_PRIM_POINTS, (len + stepsize - 1) / stepsize); + + for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) { + immVertex3fv(pos, mpv->co); + } + + immEnd(); /* Draw big green dot where the current frame is * NOTE: this is only done when keyframes are shown, since this adds similar types of clutter @@ -274,16 +304,18 @@ void draw_motion_path_instance(Scene *scene, if ((avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) && (sfra < CFRA) && (CFRA <= efra)) { - UI_ThemeColor(TH_CFRAME); - glPointSize(mpath->line_thickness + 5.0); - glBegin(GL_POINTS); + immUniformThemeColor(TH_CFRAME); + + immBegin(GWN_PRIM_POINTS, 1); + mpv = mpv_start + (CFRA - sfra); - glVertex3fv(mpv->co); - glEnd(); - - UI_ThemeColor(TH_TEXT_HI); + immVertex3fv(pos, mpv->co); + + immEnd(); } + + immUnbindProgram(); /* XXX, this isn't up to date but probably should be kept so. */ invert_m4_m4(ob->imat, ob->obmat); @@ -353,24 +385,28 @@ void draw_motion_path_instance(Scene *scene, UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col); col[3] = 255; - /* if custom, point must be bigger than line */ - if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { - glPointSize(mpath->line_thickness + 3.0); - } - else { - glPointSize(4.0f); - } - glColor3ubv(col); + /* point must be bigger than line */ + glPointSize(mpath->line_thickness + 3.0); + + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(col); - glBegin(GL_POINTS); + immBeginAtMost(GWN_PRIM_POINTS, len); + for (i = 0, mpv = mpv_start; i < len; i++, mpv++) { int frame = sfra + i; float mframe = (float)(frame); - if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) - glVertex3fv(mpv->co); + if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) { + immVertex3fv(pos, mpv->co); + } } - glEnd(); + + immEnd(); + + immUnbindProgram(); /* Draw frame numbers of keyframes */ if (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) { @@ -398,5 +434,5 @@ void draw_motion_path_instance(Scene *scene, void draw_motion_paths_cleanup(View3D *v3d) { if (v3d->zbuf) glEnable(GL_DEPTH_TEST); - glPopMatrix(); + gpuPopMatrix(); } diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 5208013b6fe..f04b8c0cdad 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -54,15 +54,20 @@ #include "BKE_modifier.h" #include "BKE_nla.h" #include "BKE_curve.h" +#include "BKE_context.h" +#include "DEG_depsgraph.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "ED_armature.h" #include "ED_keyframes_draw.h" #include "GPU_basic_shader.h" +#include "GPU_batch.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" #include "UI_resources.h" @@ -74,8 +79,10 @@ /* global here is reset before drawing each bone */ static ThemeWireColor *bcolor = NULL; +static float fcolor[4] = {0.0f}; +static bool flat_color; -/* values of colCode for set_pchan_glcolor */ +/* values of colCode for set_pchan_color */ enum { PCHAN_COLOR_NORMAL = 0, /* normal drawing */ PCHAN_COLOR_SOLID, /* specific case where "solid" color is needed */ @@ -128,7 +135,7 @@ static void set_pchan_colorset(Object *ob, bPoseChannel *pchan) } } -/* This function is for brightening/darkening a given color (like UI_ThemeColorShade()) */ +/* This function is for brightening/darkening a given color (like UI_GetThemeColorShade3ubv()) */ static void cp_shade_color3ub(unsigned char cp[3], const int offset) { int r, g, b; @@ -146,13 +153,13 @@ static void cp_shade_color3ub(unsigned char cp[3], const int offset) } /* This function sets the gl-color for coloring a certain bone (based on bcolor) */ -static bool set_pchan_glColor(short colCode, int boneflag, short constflag) +static bool set_pchan_color(short colCode, int boneflag, short constflag) { switch (colCode) { case PCHAN_COLOR_NORMAL: { if (bcolor) { - unsigned char cp[3]; + unsigned char cp[4] = {255}; if (boneflag & BONE_DRAW_ACTIVE) { copy_v3_v3_char((char *)cp, bcolor->active); @@ -169,20 +176,20 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) cp_shade_color3ub(cp, -50); } - glColor3ubv(cp); + rgb_uchar_to_float(fcolor, cp); } else { if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) { - UI_ThemeColor(TH_BONE_POSE_ACTIVE); + UI_GetThemeColor4fv(TH_BONE_POSE_ACTIVE, fcolor); } else if (boneflag & BONE_DRAW_ACTIVE) { - UI_ThemeColorBlend(TH_WIRE, TH_BONE_POSE, 0.15f); /* unselected active */ + UI_GetThemeColorBlendShade4fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, fcolor); } else if (boneflag & BONE_SELECTED) { - UI_ThemeColor(TH_BONE_POSE); + UI_GetThemeColor4fv(TH_BONE_POSE, fcolor); } else { - UI_ThemeColor(TH_WIRE); + UI_GetThemeColor4fv(TH_WIRE, fcolor); } } @@ -191,21 +198,25 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) case PCHAN_COLOR_SOLID: { if (bcolor) { - glColor3ubv((unsigned char *)bcolor->solid); + rgb_uchar_to_float(fcolor, (unsigned char *)bcolor->solid); + } + else { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); } - else - UI_ThemeColor(TH_BONE_SOLID); return true; } case PCHAN_COLOR_CONSTS: { if ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) { - if (constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80); - else if (constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80); - else if (constflag & PCHAN_HAS_SPLINEIK) glColor4ub(200, 255, 0, 80); - else if (constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80); - + unsigned char cp[4]; + if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 80); + else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 80); + else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 80); + else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 80); + + rgba_uchar_to_float(fcolor, cp); + return true; } return false; @@ -213,7 +224,7 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) case PCHAN_COLOR_SPHEREBONE_BASE: { if (bcolor) { - unsigned char cp[3]; + unsigned char cp[4] = {255}; if (boneflag & BONE_DRAW_ACTIVE) { copy_v3_v3_char((char *)cp, bcolor->active); @@ -225,12 +236,18 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) copy_v3_v3_char((char *)cp, bcolor->solid); } - glColor3ubv(cp); + rgb_uchar_to_float(fcolor, cp); } else { - if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40); - else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE); - else UI_ThemeColor(TH_BONE_SOLID); + if (boneflag & BONE_DRAW_ACTIVE) { + UI_GetThemeColorShade4fv(TH_BONE_POSE, 40, fcolor); + } + else if (boneflag & BONE_SELECTED) { + UI_GetThemeColor4fv(TH_BONE_POSE, fcolor); + } + else { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + } } return true; @@ -238,7 +255,7 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) case PCHAN_COLOR_SPHEREBONE_END: { if (bcolor) { - unsigned char cp[3]; + unsigned char cp[4] = {255}; if (boneflag & BONE_DRAW_ACTIVE) { copy_v3_v3_char((char *)cp, bcolor->active); @@ -253,12 +270,18 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) cp_shade_color3ub(cp, -30); } - glColor3ubv(cp); + rgb_uchar_to_float(fcolor, cp); } else { - if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 10); - else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_BONE_POSE, -30); - else UI_ThemeColorShade(TH_BONE_SOLID, -30); + if (boneflag & BONE_DRAW_ACTIVE) { + UI_GetThemeColorShade4fv(TH_BONE_POSE, 10, fcolor); + } + else if (boneflag & BONE_SELECTED) { + UI_GetThemeColorShade4fv(TH_BONE_POSE, -30, fcolor); + } + else { + UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor); + } } break; } @@ -266,19 +289,24 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) { /* inner part in background color or constraint */ if ((constflag) && ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS))) { - if (constflag & PCHAN_HAS_TARGET) glColor3ub(255, 150, 0); - else if (constflag & PCHAN_HAS_IK) glColor3ub(255, 255, 0); - else if (constflag & PCHAN_HAS_SPLINEIK) glColor3ub(200, 255, 0); - else if (constflag & PCHAN_HAS_CONST) glColor3ub(0, 255, 120); - else if (constflag) UI_ThemeColor(TH_BONE_POSE); /* PCHAN_HAS_ACTION */ + unsigned char cp[4]; + if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 255); + else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 255); + else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 255); + else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 255); + else if (constflag) UI_GetThemeColor4ubv(TH_BONE_POSE, cp); /* PCHAN_HAS_ACTION */ + + rgb_uchar_to_float(fcolor, cp); } else { if (bcolor) { const char *cp = bcolor->solid; - glColor4ub(cp[0], cp[1], cp[2], 204); + rgb_uchar_to_float(fcolor, (unsigned char *)cp); + fcolor[3] = 204.f / 255.f; + } + else { + UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor); } - else - UI_ThemeColorShade(TH_BACK, -30); } return true; @@ -288,26 +316,37 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) return false; } -static void set_ebone_glColor(const unsigned int boneflag) +static void set_ebone_color(const unsigned int boneflag) { if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) { - UI_ThemeColor(TH_EDGE_SELECT); + UI_GetThemeColor4fv(TH_EDGE_SELECT, fcolor); } else if (boneflag & BONE_DRAW_ACTIVE) { - UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f); /* unselected active */ + UI_GetThemeColorBlendShade4fv(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f, 0, fcolor); } else if (boneflag & BONE_SELECTED) { - UI_ThemeColorShade(TH_EDGE_SELECT, -20); + UI_GetThemeColorShade4fv(TH_EDGE_SELECT, -20, fcolor); } else { - UI_ThemeColor(TH_WIRE_EDIT); + UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor); } } /* *************** Armature drawing, helper calls for parts ******************* */ +static void add_solid_flat_triangle(Gwn_VertBuf *vbo, unsigned int *vertex, unsigned int pos, unsigned int nor, + const float p1[3], const float p2[3], const float p3[3], const float n[3]) +{ + GWN_vertbuf_attr_set(vbo, nor, *vertex, n); + GWN_vertbuf_attr_set(vbo, pos, (*vertex)++, p1); + GWN_vertbuf_attr_set(vbo, nor, *vertex, n); + GWN_vertbuf_attr_set(vbo, pos, (*vertex)++, p2); + GWN_vertbuf_attr_set(vbo, nor, *vertex, n); + GWN_vertbuf_attr_set(vbo, pos, (*vertex)++, p3); +} + /* half the cube, in Y */ -static const float cube[8][3] = { +static const float cube_vert[8][3] = { {-1.0, 0.0, -1.0}, {-1.0, 0.0, 1.0}, {-1.0, 1.0, 1.0}, @@ -318,128 +357,184 @@ static const float cube[8][3] = { { 1.0, 1.0, -1.0}, }; +static const float cube_wire[24] = { + 0, 1, 1, 2, 2, 3, 3, 0, + 4, 5, 5, 6, 6, 7, 7, 4, + 0, 4, 1, 5, 2, 6, 3, 7, +}; + static void drawsolidcube_size(float xsize, float ysize, float zsize) { - static GLuint displist = 0; - float n[3] = {0.0f}; - - glScalef(xsize, ysize, zsize); - - if (displist == 0) { - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); + static Gwn_VertFormat format = {0}; + static Gwn_VertBuf vbo = {{0}}; + static Gwn_Batch batch = {{0}}; + const float light_vec[3] = {0.0f, 0.0f, 1.0f}; + + if (format.attrib_ct == 0) { + unsigned int i = 0; + float n[3] = {0.0f}; + /* Vertex format */ + unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + /* Vertices */ + GWN_vertbuf_init_with_format(&vbo, &format); + GWN_vertbuf_data_alloc(&vbo, 36); - glBegin(GL_QUADS); n[0] = -1.0; - glNormal3fv(n); - glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[1], cube_vert[2], n); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[2], cube_vert[3], cube_vert[0], n); n[0] = 0; n[1] = -1.0; - glNormal3fv(n); - glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[4], cube_vert[5], n); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[5], cube_vert[1], cube_vert[0], n); n[1] = 0; n[0] = 1.0; - glNormal3fv(n); - glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[4], cube_vert[7], cube_vert[6], n); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[6], cube_vert[5], cube_vert[4], n); n[0] = 0; n[1] = 1.0; - glNormal3fv(n); - glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[7], cube_vert[3], cube_vert[2], n); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[2], cube_vert[6], cube_vert[7], n); n[1] = 0; n[2] = 1.0; - glNormal3fv(n); - glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[1], cube_vert[5], cube_vert[6], n); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[6], cube_vert[2], cube_vert[1], n); n[2] = -1.0; - glNormal3fv(n); - glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]); - glEnd(); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[7], cube_vert[4], cube_vert[0], n); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[3], cube_vert[7], n); - glEndList(); + GWN_batch_init(&batch, GWN_PRIM_TRIS, &vbo, NULL); } - glCallList(displist); + gpuPushMatrix(); + gpuScale3f(xsize, ysize, zsize); + + if (flat_color) { + GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR); + } + else { + /* TODO replace with good default lighting shader ? */ + GWN_batch_program_set_builtin(&batch, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_3fv(&batch, "light", light_vec); + } + GWN_batch_uniform_4fv(&batch, "color", fcolor); + GWN_batch_draw(&batch); + + gpuPopMatrix(); } static void drawcube_size(float xsize, float ysize, float zsize) { - static GLuint displist = 0; - - if (displist == 0) { - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - glBegin(GL_LINE_STRIP); - glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]); - glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); - glVertex3fv(cube[7]); glVertex3fv(cube[4]); - glEnd(); - - glBegin(GL_LINES); - glVertex3fv(cube[1]); glVertex3fv(cube[5]); - glVertex3fv(cube[2]); glVertex3fv(cube[6]); - glVertex3fv(cube[3]); glVertex3fv(cube[7]); - glEnd(); - - glEndList(); + static Gwn_VertFormat format = {0}; + static Gwn_VertBuf vbo = {{0}}; + static Gwn_IndexBufBuilder elb = {0}; + static Gwn_IndexBuf el = {0}; + static Gwn_Batch batch = {{0}}; + + if (format.attrib_ct == 0) { + /* Vertex format */ + unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + /* Elements */ + GWN_indexbuf_init(&elb, GWN_PRIM_LINES, 12, 8); + for (int i = 0; i < 12; ++i) { + GWN_indexbuf_add_line_verts(&elb, cube_wire[i * 2], cube_wire[i * 2 + 1]); + } + GWN_indexbuf_build_in_place(&elb, &el); + + /* Vertices */ + GWN_vertbuf_init_with_format(&vbo, &format); + GWN_vertbuf_data_alloc(&vbo, 8); + for (int i = 0; i < 8; ++i) { + GWN_vertbuf_attr_set(&vbo, pos, i, cube_vert[i]); + } + + GWN_batch_init(&batch, GWN_PRIM_LINES, &vbo, &el); + GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR); } - glScalef(xsize, ysize, zsize); - glCallList(displist); - + gpuPushMatrix(); + gpuScale3f(xsize, ysize, zsize); + + GWN_batch_program_use_begin(&batch); + GWN_batch_uniform_4fv(&batch, "color", fcolor); + GWN_batch_draw(&batch); + + gpuPopMatrix(); } static void draw_bonevert(void) { - static GLuint displist = 0; - - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - glPushMatrix(); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - gluDisk(qobj, 0.0, 0.05, 16, 1); - - glRotatef(90, 0, 1, 0); - gluDisk(qobj, 0.0, 0.05, 16, 1); - - glRotatef(90, 1, 0, 0); - gluDisk(qobj, 0.0, 0.05, 16, 1); - - gluDeleteQuadric(qobj); - - glPopMatrix(); - glEndList(); + static Gwn_VertFormat format = {0}; + static Gwn_VertBuf vbo = {{0}}; + static Gwn_Batch batch = {{0}}; + + if (format.attrib_ct == 0) { + /* Vertex format */ + unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + /* Vertices */ + GWN_vertbuf_init_with_format(&vbo, &format); + GWN_vertbuf_data_alloc(&vbo, 96); + for (int i = 0; i < 16; ++i) { + float vert[3] = {0.f, 0.f, 0.f}; + const float r = 0.05f; + + vert[0] = r * cosf(2 * M_PI * i / 16.f); + vert[1] = r * sinf(2 * M_PI * i / 16.f); + GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 0, vert); + vert[0] = r * cosf(2 * M_PI * (i + 1) / 16.f); + vert[1] = r * sinf(2 * M_PI * (i + 1) / 16.f); + GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 1, vert); + + vert[0] = 0.f; + vert[1] = r * cosf(2 * M_PI * i / 16.f); + vert[2] = r * sinf(2 * M_PI * i / 16.f); + GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 2, vert); + vert[1] = r * cosf(2 * M_PI * (i + 1) / 16.f); + vert[2] = r * sinf(2 * M_PI * (i + 1) / 16.f); + GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 3, vert); + + vert[1] = 0.f; + vert[0] = r * cosf(2 * M_PI * i / 16.f); + vert[2] = r * sinf(2 * M_PI * i / 16.f); + GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 4, vert); + vert[0] = r * cosf(2 * M_PI * (i + 1) / 16.f); + vert[2] = r * sinf(2 * M_PI * (i + 1) / 16.f); + GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 5, vert); + } + + GWN_batch_init(&batch, GWN_PRIM_LINES, &vbo, NULL); + GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR); } - glCallList(displist); + GWN_batch_program_use_begin(&batch); + GWN_batch_uniform_4fv(&batch, "color", fcolor); + GWN_batch_draw(&batch); } static void draw_bonevert_solid(void) { - static GLuint displist = 0; - - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_FILL); - /* Draw tips of a bone */ - gluSphere(qobj, 0.05, 8, 5); - gluDeleteQuadric(qobj); - - glEndList(); + Gwn_Batch *batch = GPU_batch_preset_sphere(0); + const float light_vec[3] = {0.0f, 0.0f, 1.0f}; + + gpuPushMatrix(); + gpuScaleUniform(0.05); + + if (flat_color) { + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); } + else { + /* TODO replace with good default lighting shader ? */ + GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_3fv(batch, "light", light_vec); + } + GWN_batch_uniform_4fv(batch, "color", fcolor); + GWN_batch_draw(batch); - glCallList(displist); + gpuPopMatrix(); } static const float bone_octahedral_verts[6][3] = { @@ -451,8 +546,11 @@ static const float bone_octahedral_verts[6][3] = { { 0.0f, 1.0f, 0.0f} }; -static const unsigned int bone_octahedral_wire_sides[8] = {0, 1, 5, 3, 0, 4, 5, 2}; -static const unsigned int bone_octahedral_wire_square[8] = {1, 2, 3, 4, 1}; +static const unsigned int bone_octahedral_wire[24] = { + 0, 1, 1, 5, 5, 3, 3, 0, + 0, 4, 4, 5, 5, 2, 2, 0, + 1, 2, 2, 3, 3, 4, 4, 1, +}; static const unsigned int bone_octahedral_solid_tris[8][3] = { {2, 1, 0}, /* bottom */ @@ -480,70 +578,78 @@ static const float bone_octahedral_solid_normals[8][3] = { static void draw_bone_octahedral(void) { - static GLuint displist = 0; - - if (displist == 0) { - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - /* Section 1, sides */ - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, bone_octahedral_verts); - glDrawElements(GL_LINE_LOOP, - sizeof(bone_octahedral_wire_sides) / sizeof(*bone_octahedral_wire_sides), - GL_UNSIGNED_INT, - bone_octahedral_wire_sides); - - /* Section 1, square */ - glDrawElements(GL_LINE_LOOP, - sizeof(bone_octahedral_wire_square) / sizeof(*bone_octahedral_wire_square), - GL_UNSIGNED_INT, - bone_octahedral_wire_square); - glDisableClientState(GL_VERTEX_ARRAY); - - glEndList(); + static Gwn_VertFormat format = {0}; + static Gwn_VertBuf vbo = {{0}}; + static Gwn_IndexBufBuilder elb = {0}; + static Gwn_IndexBuf el = {0}; + static Gwn_Batch batch = {{0}}; + + if (format.attrib_ct == 0) { + /* Vertex format */ + unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + /* Elements */ + GWN_indexbuf_init(&elb, GWN_PRIM_LINES, 12, 6); + for (int i = 0; i < 12; ++i) { + GWN_indexbuf_add_line_verts(&elb, bone_octahedral_wire[i * 2], bone_octahedral_wire[i * 2 + 1]); + } + GWN_indexbuf_build_in_place(&elb, &el); + + /* Vertices */ + GWN_vertbuf_init_with_format(&vbo, &format); + GWN_vertbuf_data_alloc(&vbo, 6); + for (int i = 0; i < 6; ++i) { + GWN_vertbuf_attr_set(&vbo, pos, i, bone_octahedral_verts[i]); + } + + GWN_batch_init(&batch, GWN_PRIM_LINES, &vbo, &el); + GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR); } - glCallList(displist); -} + GWN_batch_program_use_begin(&batch); + GWN_batch_uniform_4fv(&batch, "color", fcolor); + GWN_batch_draw(&batch); +} static void draw_bone_solid_octahedral(void) { - static GLuint displist = 0; - - if (displist == 0) { - int i; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - -#if 1 - glBegin(GL_TRIANGLES); - for (i = 0; i < 8; i++) { - glNormal3fv(bone_octahedral_solid_normals[i]); - glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][0]]); - glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][1]]); - glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][2]]); - } - - glEnd(); - -#else /* not working because each vert needs a different normal */ - glEnableClientState(GL_NORMAL_ARRAY); - glEnableClientState(GL_VERTEX_ARRAY); - glNormalPointer(GL_FLOAT, 0, bone_octahedral_solid_normals); - glVertexPointer(3, GL_FLOAT, 0, bone_octahedral_verts); - glDrawElements(GL_TRIANGLES, sizeof(bone_octahedral_solid_tris) / sizeof(unsigned int), - GL_UNSIGNED_INT, bone_octahedral_solid_tris); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); -#endif + static Gwn_VertFormat format = {0}; + static Gwn_VertBuf vbo = {{0}}; + static Gwn_Batch batch = {{0}}; + const float light_vec[3] = {0.0f, 0.0f, 1.0f}; + + if (format.attrib_ct == 0) { + unsigned int v_idx = 0; + /* Vertex format */ + unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + /* Vertices */ + GWN_vertbuf_init_with_format(&vbo, &format); + GWN_vertbuf_data_alloc(&vbo, 24); + + for (int i = 0; i < 8; i++) { + add_solid_flat_triangle(&vbo, &v_idx, pos, nor, + bone_octahedral_verts[bone_octahedral_solid_tris[i][0]], + bone_octahedral_verts[bone_octahedral_solid_tris[i][1]], + bone_octahedral_verts[bone_octahedral_solid_tris[i][2]], + bone_octahedral_solid_normals[i]); + } - glEndList(); + GWN_batch_init(&batch, GWN_PRIM_TRIS, &vbo, NULL); } - glCallList(displist); -} + if (flat_color) { + GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR); + } + else { + /* TODO replace with good default lighting shader ? */ + GWN_batch_program_set_builtin(&batch, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_3fv(&batch, "light", light_vec); + } + GWN_batch_uniform_4fv(&batch, "color", fcolor); + GWN_batch_draw(&batch); +} /* *************** Armature drawing, bones ******************* */ @@ -557,15 +663,20 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag, if (dt <= OB_WIRE) { if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColor(TH_VERTEX); + if (boneflag & BONE_ROOTSEL) { + UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + } + else { + UI_GetThemeColor4fv(TH_VERTEX, fcolor); + } } } else { if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0); - else - UI_ThemeColor(TH_BONE_SOLID); + set_pchan_color(PCHAN_COLOR_SOLID, boneflag, 0); + else { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + } } if (dt > OB_WIRE) @@ -580,24 +691,29 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag, if (dt <= OB_WIRE) { if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColor(TH_VERTEX); + if (boneflag & BONE_TIPSEL) { + UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + } + else { + UI_GetThemeColor4fv(TH_VERTEX, fcolor); + } } } else { if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0); - else - UI_ThemeColor(TH_BONE_SOLID); + set_pchan_color(PCHAN_COLOR_SOLID, boneflag, 0); + else { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + } } - glTranslatef(0.0f, 1.0f, 0.0f); + gpuPushMatrix(); + gpuTranslate2f(0.0f, 1.0f); if (dt > OB_WIRE) draw_bonevert_solid(); else draw_bonevert(); - glTranslatef(0.0f, -1.0f, 0.0f); - + gpuPopMatrix(); } /* 16 values of sin function (still same result!) */ @@ -696,8 +812,13 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann //mul_v3_fl(dirvec, head); cross_v3_v3v3(norvec, dirvec, imat[2]); - - glBegin(GL_QUAD_STRIP); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immBegin(GWN_PRIM_TRI_STRIP, 66); + immUniformColor4ub(255, 255, 255, 50); for (a = 0; a < 16; a++) { vec[0] = -si[a] * dirvec[0] + co[a] * norvec[0]; @@ -707,10 +828,8 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann madd_v3_v3v3fl(vec1, headvec, vec, head); madd_v3_v3v3fl(vec2, headvec, vec, head + dist); - glColor4ub(255, 255, 255, 50); - glVertex3fv(vec1); - //glColor4ub(255, 255, 255, 0); - glVertex3fv(vec2); + immVertex3fv(pos, vec1); + immVertex3fv(pos, vec2); } for (a = 15; a >= 0; a--) { @@ -721,10 +840,8 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann madd_v3_v3v3fl(vec1, tailvec, vec, tail); madd_v3_v3v3fl(vec2, tailvec, vec, tail + dist); - //glColor4ub(255, 255, 255, 50); - glVertex3fv(vec1); - //glColor4ub(255, 255, 255, 0); - glVertex3fv(vec2); + immVertex3fv(pos, vec1); + immVertex3fv(pos, vec2); } /* make it cyclic... */ @@ -735,12 +852,11 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann madd_v3_v3v3fl(vec1, headvec, vec, head); madd_v3_v3v3fl(vec2, headvec, vec, head + dist); - //glColor4ub(255, 255, 255, 50); - glVertex3fv(vec1); - //glColor4ub(255, 255, 255, 0); - glVertex3fv(vec2); + immVertex3fv(pos, vec1); + immVertex3fv(pos, vec2); - glEnd(); + immEnd(); + immUnbindProgram(); } } @@ -752,6 +868,11 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4], { float head, tail /*, length*/; float *headvec, *tailvec, dirvec[3]; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* figure out the sizes of spheres */ if (ebone) { @@ -780,35 +901,49 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4], /* sphere root color */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColor(TH_VERTEX); + if (boneflag & BONE_ROOTSEL) { + UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + } + else { + UI_GetThemeColor4fv(TH_VERTEX, fcolor); + } } else if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); - + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); + + immUniformColor4fv(fcolor); + /* Draw root point if we are not connected */ if ((boneflag & BONE_CONNECTED) == 0) { if (id != -1) GPU_select_load_id(id | BONESEL_ROOT); - drawcircball(GL_LINE_LOOP, headvec, head, imat); + imm_drawcircball(headvec, head, imat, pos); } /* Draw tip point */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColor(TH_VERTEX); + if (boneflag & BONE_TIPSEL) { + UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + } + else { + UI_GetThemeColor4fv(TH_VERTEX, fcolor); + } } if (id != -1) GPU_select_load_id(id | BONESEL_TIP); - drawcircball(GL_LINE_LOOP, tailvec, tail, imat); + imm_drawcircball(tailvec, tail, imat, pos); /* base */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT); - else UI_ThemeColor(TH_WIRE_EDIT); + if (boneflag & BONE_SELECTED) { + UI_GetThemeColor4fv(TH_SELECT, fcolor); + } + else { + UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor); + } } sub_v3_v3v3(dirvec, tailvec, headvec); @@ -834,34 +969,40 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4], if (id != -1) GPU_select_load_id(id | BONESEL_BONE); - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, 4); add_v3_v3v3(vec, headvec, norvech); - glVertex3fv(vec); + immVertex3fv(pos, vec); add_v3_v3v3(vec, tailvec, norvect); - glVertex3fv(vec); + immVertex3fv(pos, vec); sub_v3_v3v3(vec, headvec, norvech); - glVertex3fv(vec); + immVertex3fv(pos, vec); sub_v3_v3v3(vec, tailvec, norvect); - glVertex3fv(vec); + immVertex3fv(pos, vec); - glEnd(); + immEnd(); } + + immUnbindProgram(); } /* does wire only for outline selecting */ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone) { - GLUquadricObj *qobj; + Gwn_Batch *sphere = GPU_batch_preset_sphere(1); float head, tail, length; - float fac1, fac2; - - glPushMatrix(); - qobj = gluNewQuadric(); + float fac1, fac2, size1, size2; + const float light_vec[3] = {0.0f, 0.0f, 1.0f}; + + /* dt is always OB_SOlID */ + GWN_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_3fv(sphere, "light", light_vec); + + gpuPushMatrix(); /* figure out the sizes of spheres */ if (ebone) { @@ -882,110 +1023,124 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co } /* move to z-axis space */ - glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); + gpuRotateAxis(-90.0f, 'X'); - if (dt == OB_SOLID) { - /* set up solid drawing */ - GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); - - gluQuadricDrawStyle(qobj, GLU_FILL); - } - else { - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - } - /* sphere root color */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColorShade(TH_BONE_SOLID, -30); + if (boneflag & BONE_ROOTSEL) + UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + else + UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor); } else if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_END, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_SPHEREBONE_END, boneflag, constflag); else if (dt == OB_SOLID) - UI_ThemeColorShade(TH_BONE_SOLID, -30); + UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor); /* Draw root point if we are not connected */ if ((boneflag & BONE_CONNECTED) == 0) { if (id != -1) GPU_select_load_id(id | BONESEL_ROOT); - gluSphere(qobj, head, 16, 10); + gpuPushMatrix(); + gpuScaleUniform(head); + GWN_batch_uniform_4fv(sphere, "color", fcolor); + GWN_batch_draw(sphere); + gpuPopMatrix(); } /* Draw tip point */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColorShade(TH_BONE_SOLID, -30); + if (boneflag & BONE_TIPSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + else UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor); } if (id != -1) GPU_select_load_id(id | BONESEL_TIP); - glTranslatef(0.0f, 0.0f, length); - gluSphere(qobj, tail, 16, 10); - glTranslatef(0.0f, 0.0f, -length); + gpuTranslate3f(0.0f, 0.0f, length); + + gpuPushMatrix(); + gpuScaleUniform(tail); + GWN_batch_program_use_begin(sphere); /* hack to make the following uniforms stick */ + GWN_batch_uniform_4fv(sphere, "color", fcolor); + GWN_batch_draw(sphere); + gpuPopMatrix(); + + gpuTranslate3f(0.0f, 0.0f, -length); /* base */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT); - else UI_ThemeColor(TH_BONE_SOLID); + if (boneflag & BONE_SELECTED) UI_GetThemeColor4fv(TH_SELECT, fcolor); + else UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); } else if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_BASE, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_SPHEREBONE_BASE, boneflag, constflag); else if (dt == OB_SOLID) - UI_ThemeColor(TH_BONE_SOLID); + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + + GWN_batch_program_use_begin(sphere); /* hack to make the following uniforms stick */ + GWN_batch_uniform_4fv(sphere, "color", fcolor); fac1 = (length - head) / length; fac2 = (length - tail) / length; if (length > (head + tail)) { + size1 = fac2 * tail + (1.0f - fac2) * head; + size2 = fac1 * head + (1.0f - fac1) * tail; + if (id != -1) GPU_select_load_id(id | BONESEL_BONE); + /* draw sphere on extrema */ + gpuPushMatrix(); + gpuTranslate3f(0.0f, 0.0f, length - tail); + gpuScaleUniform(size1); + + GWN_batch_draw(sphere); + gpuPopMatrix(); + + gpuPushMatrix(); + gpuTranslate3f(0.0f, 0.0f, head); + gpuScaleUniform(size2); + + GWN_batch_draw(sphere); + gpuPopMatrix(); + + /* draw cynlinder between spheres */ glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -1.0f); - - glTranslatef(0.0f, 0.0f, head); - gluCylinder(qobj, fac1 * head + (1.0f - fac1) * tail, fac2 * tail + (1.0f - fac2) * head, length - head - tail, 16, 1); - glTranslatef(0.0f, 0.0f, -head); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_SIMPLE_LIGHTING); + immUniformColor4fv(fcolor); + immUniform3fv("light", light_vec); + + gpuTranslate3f(0.0f, 0.0f, head); + imm_draw_cylinder_fill_normal_3d(pos, nor, size2, size1, length - head - tail, 16, 1); + + immUnbindProgram(); glDisable(GL_POLYGON_OFFSET_FILL); - - /* draw sphere on extrema */ - glTranslatef(0.0f, 0.0f, length - tail); - gluSphere(qobj, fac2 * tail + (1.0f - fac2) * head, 16, 10); - glTranslatef(0.0f, 0.0f, -length + tail); - - glTranslatef(0.0f, 0.0f, head); - gluSphere(qobj, fac1 * head + (1.0f - fac1) * tail, 16, 10); } else { + size1 = fac1 * head + (1.0f - fac1) * tail; + /* 1 sphere in center */ - glTranslatef(0.0f, 0.0f, (head + length - tail) / 2.0f); - gluSphere(qobj, fac1 * head + (1.0f - fac1) * tail, 16, 10); - } - - /* restore */ - if (dt == OB_SOLID) { - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + gpuTranslate3f(0.0f, 0.0f, (head + length - tail) / 2.0f); + + gpuScaleUniform(size1); + GWN_batch_draw(sphere); } - glPopMatrix(); - gluDeleteQuadric(qobj); + gpuPopMatrix(); } -static GLubyte bm_dot6[] = {0x0, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x0}; -static GLubyte bm_dot8[] = {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C}; - -static GLubyte bm_dot5[] = {0x0, 0x0, 0x10, 0x38, 0x7c, 0x38, 0x10, 0x0}; -static GLubyte bm_dot7[] = {0x0, 0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38}; - - static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone) { - /* call this once, avoid constant changing */ - BLI_assert(glaGetOneInt(GL_UNPACK_ALIGNMENT) == 1); - float length; if (pchan) @@ -993,103 +1148,119 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned else length = ebone->length; - glPushMatrix(); - glScalef(length, length, length); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + gpuPushMatrix(); + gpuScaleUniform(length); /* this chunk not in object mode */ if (armflag & (ARM_EDITMODE | ARM_POSEMODE)) { glLineWidth(4.0f); - if (G.f & G_PICKSEL) { - /* no bitmap in selection mode, crashes 3d cards... - * instead draw a solid point the same size */ - glPointSize(8.0f); - } + glPointSize(8.0f); if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); else if (armflag & ARM_EDITMODE) { - UI_ThemeColor(TH_WIRE_EDIT); + UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor); } - + + /* line */ + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(fcolor); + + if (id != -1) + GPU_select_load_id(id | BONESEL_BONE); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 1.0f, 0.0f); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR); + immUniformColor4fv(fcolor); + /* Draw root point if we are not connected */ if ((boneflag & BONE_CONNECTED) == 0) { - if (G.f & G_PICKSEL) { + if (G.f & G_PICKSEL) GPU_select_load_id(id | BONESEL_ROOT); - glBegin(GL_POINTS); - glVertex3f(0.0f, 0.0f, 0.0f); - glEnd(); - } - else { - glRasterPos3f(0.0f, 0.0f, 0.0f); - glBitmap(8, 8, 4, 4, 0, 0, bm_dot8); - } + + immBegin(GWN_PRIM_POINTS, 1); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immEnd(); } - - if (id != -1) - GPU_select_load_id((GLuint) id | BONESEL_BONE); - - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, 1.0f, 0.0f); - glEnd(); - + /* tip */ - if (G.f & G_PICKSEL) { - /* no bitmap in selection mode, crashes 3d cards... */ + if (G.f & G_PICKSEL) GPU_select_load_id(id | BONESEL_TIP); - glBegin(GL_POINTS); - glVertex3f(0.0f, 1.0f, 0.0f); - glEnd(); - } - else { - glRasterPos3f(0.0f, 1.0f, 0.0f); - glBitmap(8, 8, 4, 4, 0, 0, bm_dot7); - } - + + immBegin(GWN_PRIM_POINTS, 1); + immVertex3f(pos, 0.0f, 1.0f, 0.0f); + immEnd(); + + immUnbindProgram(); + + /* further we send no names */ if (id != -1) GPU_select_load_id(id & 0xFFFF); /* object tag, for bordersel optim */ if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_LINEBONE, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_LINEBONE, boneflag, constflag); } - - glLineWidth(2.0); - + + /* Now draw the inner color */ + glLineWidth(2.0f); + glPointSize(5.0f); + + /* line */ + if (armflag & ARM_EDITMODE) { + if (boneflag & BONE_SELECTED) UI_GetThemeColor4fv(TH_EDGE_SELECT, fcolor); + else UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor); + } + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(fcolor); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 1.0f, 0.0f); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR); + /*Draw root point if we are not connected */ if ((boneflag & BONE_CONNECTED) == 0) { - if ((G.f & G_PICKSEL) == 0) { - /* no bitmap in selection mode, crashes 3d cards... */ - if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColor(TH_VERTEX); - } - glRasterPos3f(0.0f, 0.0f, 0.0f); - glBitmap(8, 8, 4, 4, 0, 0, bm_dot6); + if (armflag & ARM_EDITMODE) { + if (boneflag & BONE_ROOTSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + else UI_GetThemeColor4fv(TH_VERTEX, fcolor); } + immUniformColor4fv(fcolor); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immEnd(); } - - if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_EDGE_SELECT); - else UI_ThemeColorShade(TH_BACK, -30); - } - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, 1.0f, 0.0f); - glEnd(); - + /* tip */ if ((G.f & G_PICKSEL) == 0) { /* no bitmap in selection mode, crashes 3d cards... */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColor(TH_VERTEX); + if (boneflag & BONE_TIPSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + else UI_GetThemeColor4fv(TH_VERTEX, fcolor); } - glRasterPos3f(0.0f, 1.0f, 0.0f); - glBitmap(8, 8, 4, 4, 0, 0, bm_dot5); + immUniformColor4fv(fcolor); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3f(pos, 0.0f, 1.0f, 0.0f); + immEnd(); } - - glPopMatrix(); + + immUnbindProgram(); + + gpuPopMatrix(); } /* A partial copy of b_bone_spline_setup(), with just the parts for previewing editmode curve settings @@ -1188,18 +1359,16 @@ static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, EditBone *ebo } for (a = 0; a < segments; a++) { - glPushMatrix(); - glMultMatrixf(bbone[a].mat); + gpuPushMatrix(); + gpuMultMatrix(bbone[a].mat); if (dt == OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth); else drawcube_size(xwidth, dlen, zwidth); - glPopMatrix(); + gpuPopMatrix(); } } else { - glPushMatrix(); if (dt == OB_SOLID) drawsolidcube_size(xwidth, length, zwidth); else drawcube_size(xwidth, length, zwidth); - glPopMatrix(); } } @@ -1222,26 +1391,27 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl /* draw points only if... */ if (armflag & ARM_EDITMODE) { /* move to unitspace */ - glPushMatrix(); - glScalef(length, length, length); + gpuPushMatrix(); + gpuScaleUniform(length); draw_bone_points(dt, armflag, boneflag, id); - glPopMatrix(); + gpuPopMatrix(); length *= 0.95f; /* make vertices visible */ } /* colors for modes */ if (armflag & ARM_POSEMODE) { if (dt <= OB_WIRE) - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); else - set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag); } else if (armflag & ARM_EDITMODE) { if (dt == OB_WIRE) { - set_ebone_glColor(boneflag); + set_ebone_color(boneflag); + } + else { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); } - else - UI_ThemeColor(TH_BONE_SOLID); } if (id != -1) { @@ -1250,33 +1420,31 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl /* set up solid drawing */ if (dt > OB_WIRE) { - GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); - if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag); - else - UI_ThemeColor(TH_BONE_SOLID); + set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag); + else { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + } + flat_color = false; draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth); - - /* disable solid drawing */ - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); } else { /* wire */ if (armflag & ARM_POSEMODE) { if (constflag && ((G.f & G_PICKSEL) == 0)) { /* set constraint colors */ - if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) { + if (set_pchan_color(PCHAN_COLOR_CONSTS, boneflag, constflag)) { glEnable(GL_BLEND); + flat_color = true; draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth); glDisable(GL_BLEND); } /* restore colors */ - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); } } @@ -1286,33 +1454,41 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float length, int segments) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(fcolor); + if ((segments > 1) && (pchan)) { float dlen = length / (float)segments; Mat4 *bbone = bbones; int a; - + for (a = 0; a < segments; a++, bbone++) { - glPushMatrix(); - glMultMatrixf(bbone->mat); - - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, dlen, 0.0f); - glEnd(); /* GL_LINES */ - - glPopMatrix(); + gpuPushMatrix(); + gpuMultMatrix(bbone->mat); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immVertex3f(pos, 0.0f, dlen, 0.0f); + immEnd(); + + gpuPopMatrix(); } } else { - glPushMatrix(); - - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, length, 0.0f); - glEnd(); - - glPopMatrix(); + gpuPushMatrix(); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immVertex3f(pos, 0.0f, length, 0.0f); + immEnd(); + + gpuPopMatrix(); } + + immUnbindProgram(); } static void draw_wire_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, @@ -1338,10 +1514,11 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons /* draw points only if... */ if (armflag & ARM_EDITMODE) { /* move to unitspace */ - glPushMatrix(); - glScalef(length, length, length); + gpuPushMatrix(); + gpuScaleUniform(length); + flat_color = true; draw_bone_points(dt, armflag, boneflag, id); - glPopMatrix(); + gpuPopMatrix(); length *= 0.95f; /* make vertices visible */ } @@ -1359,10 +1536,10 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons /* colors for modes */ if (armflag & ARM_POSEMODE) { - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); } else if (armflag & ARM_EDITMODE) { - set_ebone_glColor(boneflag); + set_ebone_color(boneflag); } /* draw normal */ @@ -1372,23 +1549,23 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons static void draw_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, float length) { - /* Draw a 3d octahedral bone, we use normalized space based on length, - * for display-lists */ - - glScalef(length, length, length); + /* Draw a 3d octahedral bone, we use normalized space based on length */ + gpuScaleUniform(length); /* set up solid drawing */ if (dt > OB_WIRE) { - GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); - UI_ThemeColor(TH_BONE_SOLID); + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + flat_color = false; } + else + flat_color = true; /* colors for posemode */ if (armflag & ARM_POSEMODE) { if (dt <= OB_WIRE) - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); else - set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag); } @@ -1403,12 +1580,12 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag if (dt <= OB_WIRE) { /* colors */ if (armflag & ARM_EDITMODE) { - set_ebone_glColor(boneflag); + set_ebone_color(boneflag); } else if (armflag & ARM_POSEMODE) { if (constflag && ((G.f & G_PICKSEL) == 0)) { /* draw constraint colors */ - if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) { + if (set_pchan_color(PCHAN_COLOR_CONSTS, boneflag, constflag)) { glEnable(GL_BLEND); draw_bone_solid_octahedral(); @@ -1417,7 +1594,7 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag } /* restore colors */ - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); } } draw_bone_octahedral(); @@ -1425,35 +1602,33 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag else { /* solid */ if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag); else - UI_ThemeColor(TH_BONE_SOLID); - draw_bone_solid_octahedral(); - } + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); - /* disable solid drawing */ - if (dt > OB_WIRE) { - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + draw_bone_solid_octahedral(); } } -static void draw_custom_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, - const short dt, int armflag, int boneflag, unsigned int id, float length) +static void draw_custom_bone( + const struct EvaluationContext *eval_ctx, + Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Object *ob, + const short dt, int armflag, int boneflag, unsigned int id, float length) { if (ob == NULL) return; - glScalef(length, length, length); + gpuScaleUniform(length); /* colors for posemode */ if (armflag & ARM_POSEMODE) { - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, 0); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, 0); } if (id != -1) { GPU_select_load_id((GLuint) id | BONESEL_BONE); } - - draw_object_instance(scene, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE); + + draw_object_instance(eval_ctx, scene, sl, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE, fcolor); } @@ -1461,7 +1636,20 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp) { bConstraint *con; bPoseChannel *parchan; - + + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniformColor4fv(fcolor); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + for (con = pchan->constraints.first; con; con = con->next) { if (con->enforce == 0.0f) continue; @@ -1471,47 +1659,45 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp) { bKinematicConstraint *data = (bKinematicConstraint *)con->data; int segcount = 0; + float ik_tip[3]; /* if only_temp, only draw if it is a temporary ik-chain */ if ((only_temp) && !(data->flag & CONSTRAINT_IK_TEMP)) continue; - - setlinestyle(3); - glBegin(GL_LINES); - + /* exclude tip from chain? */ if ((data->flag & CONSTRAINT_IK_TIP) == 0) parchan = pchan->parent; else parchan = pchan; - glVertex3fv(parchan->pose_tail); + copy_v3_v3(ik_tip, parchan->pose_tail); /* Find the chain's root */ while (parchan->parent) { segcount++; - if (segcount == data->rootbone || segcount > 255) { - break; /* 255 is weak */ - } + /* FIXME: revise the breaking conditions */ + if (segcount == data->rootbone || segcount > 255) break; /* 255 is weak */ parchan = parchan->parent; } - if (parchan) - glVertex3fv(parchan->pose_head); + + if (parchan) { + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(shdr_pos, ik_tip); + immVertex3fv(shdr_pos, parchan->pose_head); + immEnd(); + } - glEnd(); - setlinestyle(0); break; } case CONSTRAINT_TYPE_SPLINEIK: { bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; int segcount = 0; - - setlinestyle(3); - glBegin(GL_LINES); + float ik_tip[3]; parchan = pchan; - glVertex3fv(parchan->pose_tail); + copy_v3_v3(ik_tip, parchan->pose_tail); /* Find the chain's root */ while (parchan->parent) { @@ -1521,18 +1707,21 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp) parchan = parchan->parent; } /* Only draw line in case our chain is more than one bone long! */ - if (parchan != pchan) /* XXX revise the breaking conditions to only stop at the tail? */ - glVertex3fv(parchan->pose_head); - - glEnd(); - setlinestyle(0); + if (parchan != pchan) { /* XXX revise the breaking conditions to only stop at the tail? */ + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(shdr_pos, ik_tip); + immVertex3fv(shdr_pos, parchan->pose_head); + immEnd(); + } break; } } } + + immUnbindProgram(); } -static void bgl_sphere_project(float ax, float az) +static void imm_sphere_project(unsigned int pos, float ax, float az) { float dir[3], sine, q3; @@ -1543,11 +1732,13 @@ static void bgl_sphere_project(float ax, float az) dir[1] = 1.0f - 2.0f * sine; dir[2] = ax * q3; - glVertex3fv(dir); + immVertex3fv(pos, dir); } -static void draw_dof_ellipse(float ax, float az) +static void draw_dof_ellipse(unsigned int pos, float ax, float az) { + const int n = 16; + const int tri = n * n - 2 * n + 1; /* Yay fancy math ! */ const float staticSine[16] = { 0.0f, 0.104528463268f, 0.207911690818f, 0.309016994375f, 0.406736643076f, 0.5f, 0.587785252292f, 0.669130606359f, @@ -1556,15 +1747,15 @@ static void draw_dof_ellipse(float ax, float az) 0.994521895368f, 1.0f }; - int i, j, n = 16; + int i, j; float x, z, px, pz; glEnable(GL_BLEND); glDepthMask(0); - glColor4ub(70, 70, 70, 50); + immUniformColor4ub(70, 70, 70, 50); - glBegin(GL_QUADS); + immBegin(GWN_PRIM_TRIS, tri * 3); pz = 0.0f; for (i = 1; i < n; i++) { z = staticSine[i]; @@ -1574,36 +1765,35 @@ static void draw_dof_ellipse(float ax, float az) x = staticSine[j]; if (j == n - i) { - glEnd(); - glBegin(GL_TRIANGLES); - bgl_sphere_project(ax * px, az * z); - bgl_sphere_project(ax * px, az * pz); - bgl_sphere_project(ax * x, az * pz); - glEnd(); - glBegin(GL_QUADS); + imm_sphere_project(pos, ax * px, az * z); + imm_sphere_project(pos, ax * px, az * pz); + imm_sphere_project(pos, ax * x, az * pz); } else { - bgl_sphere_project(ax * x, az * z); - bgl_sphere_project(ax * x, az * pz); - bgl_sphere_project(ax * px, az * pz); - bgl_sphere_project(ax * px, az * z); + imm_sphere_project(pos, ax * x, az * z); + imm_sphere_project(pos, ax * x, az * pz); + imm_sphere_project(pos, ax * px, az * pz); + + imm_sphere_project(pos, ax * px, az * pz); + imm_sphere_project(pos, ax * px, az * z); + imm_sphere_project(pos, ax * x, az * z); } px = x; } pz = z; } - glEnd(); + immEnd(); glDisable(GL_BLEND); glDepthMask(1); - glColor3ub(0, 0, 0); + immUniformColor3ub(0, 0, 0); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, n); for (i = 0; i < n; i++) - bgl_sphere_project(staticSine[n - i - 1] * ax, staticSine[i] * az); - glEnd(); + imm_sphere_project(pos, staticSine[n - i - 1] * ax, staticSine[i] * az); + immEnd(); } static void draw_pose_dofs(Object *ob) @@ -1611,7 +1801,12 @@ static void draw_pose_dofs(Object *ob) bArmature *arm = ob->data; bPoseChannel *pchan; Bone *bone; - + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { bone = pchan->bone; @@ -1625,54 +1820,55 @@ static void draw_pose_dofs(Object *ob) int a, i; /* in parent-bone pose, but own restspace */ - glPushMatrix(); + gpuPushMatrix(); copy_v3_v3(posetrans, pchan->pose_mat[3]); - glTranslate3fv(posetrans); + gpuTranslate3fv(posetrans); if (pchan->parent) { copy_m4_m4(mat, pchan->parent->pose_mat); mat[3][0] = mat[3][1] = mat[3][2] = 0.0f; - glMultMatrixf(mat); + gpuMultMatrix(mat); } copy_m4_m3(mat, pchan->bone->bone_mat); - glMultMatrixf(mat); + gpuMultMatrix(mat); scale = bone->length * pchan->size[1]; - glScalef(scale, scale, scale); + gpuScaleUniform(scale); - if (pchan->ikflag & BONE_IK_XLIMIT) { - if (pchan->ikflag & BONE_IK_ZLIMIT) { - float amin[3], amax[3]; - - for (i = 0; i < 3; i++) { - /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */ - amin[i] = sinf(pchan->limitmin[i] * 0.5f); - amax[i] = sinf(pchan->limitmax[i] * 0.5f); - } - - glScalef(1.0f, -1.0f, 1.0f); - if ((amin[0] != 0.0f) && (amin[2] != 0.0f)) - draw_dof_ellipse(amin[0], amin[2]); - if ((amin[0] != 0.0f) && (amax[2] != 0.0f)) - draw_dof_ellipse(amin[0], amax[2]); - if ((amax[0] != 0.0f) && (amin[2] != 0.0f)) - draw_dof_ellipse(amax[0], amin[2]); - if ((amax[0] != 0.0f) && (amax[2] != 0.0f)) - draw_dof_ellipse(amax[0], amax[2]); - glScalef(1.0f, -1.0f, 1.0f); + if (((pchan->ikflag & BONE_IK_XLIMIT) != 0) && + ((pchan->ikflag & BONE_IK_ZLIMIT) != 0)) + { + float amin[3], amax[3]; + + for (i = 0; i < 3; i++) { + /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */ + amin[i] = sinf(pchan->limitmin[i] * 0.5f); + amax[i] = sinf(pchan->limitmax[i] * 0.5f); } + + gpuScale3f(1.0f, -1.0f, 1.0f); + if ((amin[0] != 0.0f) && (amin[2] != 0.0f)) + draw_dof_ellipse(pos, amin[0], amin[2]); + if ((amin[0] != 0.0f) && (amax[2] != 0.0f)) + draw_dof_ellipse(pos, amin[0], amax[2]); + if ((amax[0] != 0.0f) && (amin[2] != 0.0f)) + draw_dof_ellipse(pos, amax[0], amin[2]); + if ((amax[0] != 0.0f) && (amax[2] != 0.0f)) + draw_dof_ellipse(pos, amax[0], amax[2]); + gpuScale3f(1.0f, -1.0f, 1.0f); /* XXX same as above, is this intentional? */ } /* arcs */ if (pchan->ikflag & BONE_IK_ZLIMIT) { /* OpenGL requires rotations in degrees; so we're taking the average angle here */ theta = RAD2DEGF(0.5f * (pchan->limitmin[2] + pchan->limitmax[2])); - glRotatef(theta, 0.0f, 0.0f, 1.0f); + gpuPushMatrix(); + gpuRotateAxis(theta, 'Z'); - glColor3ub(50, 50, 255); /* blue, Z axis limit */ - glBegin(GL_LINE_STRIP); + immUniformColor3ub(50, 50, 255); /* blue, Z axis limit */ + immBegin(GWN_PRIM_LINE_STRIP, 33); for (a = -16; a <= 16; a++) { /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */ float fac = ((float)a) / 16.0f * 0.5f; @@ -1683,20 +1879,21 @@ static void draw_pose_dofs(Object *ob) corner[i][0] = sinf(phi); corner[i][1] = cosf(phi); corner[i][2] = 0.0f; - glVertex3fv(corner[i]); + immVertex3fv(pos, corner[i]); } - glEnd(); + immEnd(); - glRotatef(-theta, 0.0f, 0.0f, 1.0f); + gpuPopMatrix(); } if (pchan->ikflag & BONE_IK_XLIMIT) { /* OpenGL requires rotations in degrees; so we're taking the average angle here */ theta = RAD2DEGF(0.5f * (pchan->limitmin[0] + pchan->limitmax[0])); - glRotatef(theta, 1.0f, 0.0f, 0.0f); + gpuPushMatrix(); + gpuRotateAxis(theta, 'X'); - glColor3ub(255, 50, 50); /* Red, X axis limit */ - glBegin(GL_LINE_STRIP); + immUniformColor3ub(255, 50, 50); /* Red, X axis limit */ + immBegin(GWN_PRIM_LINE_STRIP, 33); for (a = -16; a <= 16; a++) { /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */ float fac = ((float)a) / 16.0f * 0.5f; @@ -1706,21 +1903,23 @@ static void draw_pose_dofs(Object *ob) corner[i][0] = 0.0f; corner[i][1] = sinf(phi); corner[i][2] = cosf(phi); - glVertex3fv(corner[i]); + immVertex3fv(pos, corner[i]); } - glEnd(); + immEnd(); - glRotatef(-theta, 1.0f, 0.0f, 0.0f); + gpuPopMatrix(); } /* out of cone, out of bone */ - glPopMatrix(); + gpuPopMatrix(); } } } } } } + + immUnbindProgram(); } static void bone_matrix_translate_y(float mat[4][4], float y) @@ -1733,9 +1932,10 @@ static void bone_matrix_translate_y(float mat[4][4], float y) } /* assumes object is Armature with pose */ -static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, - const short dt, const unsigned char ob_wire_col[4], - const bool do_const_color, const bool is_outline) +static void draw_pose_bones( + const struct EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, + const short dt, const unsigned char ob_wire_col[4], + const bool do_const_color, const bool is_outline) { RegionView3D *rv3d = ar->regiondata; Object *ob = base->object; @@ -1756,7 +1956,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* being set below */ arm->layer_used = 0; - + + rgba_uchar_to_float(fcolor, ob_wire_col); + /* precalc inverse matrix for drawing screen aligned */ if (arm->drawtype == ARM_ENVELOPE) { /* precalc inverse matrix for drawing screen aligned */ @@ -1805,7 +2007,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* if solid we draw that first, with selection codes, but without names, axes etc */ if (dt > OB_WIRE) { if (arm->flag & ARM_POSEMODE) - index = base->selcol; + index = base->object->select_color; for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { bone = pchan->bone; @@ -1817,13 +2019,13 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, { if (bone->layer & arm->layer) { const bool use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM); - glPushMatrix(); + gpuPushMatrix(); if (use_custom && pchan->custom_tx) { - glMultMatrixf(pchan->custom_tx->pose_mat); + gpuMultMatrix(pchan->custom_tx->pose_mat); } else { - glMultMatrixf(pchan->pose_mat); + gpuMultMatrix(pchan->pose_mat); } /* catch exception for bone with hidden parent */ @@ -1858,7 +2060,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, glDisable(GL_CULL_FACE); } - draw_custom_bone(scene, v3d, rv3d, pchan->custom, + draw_custom_bone(eval_ctx, scene, sl, v3d, rv3d, pchan->custom, OB_SOLID, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan)); } } @@ -1885,7 +2087,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } } - glPopMatrix(); + gpuPopMatrix(); } } @@ -1913,7 +2115,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, (draw_wire || (dt <= OB_WIRE)) ) { if (arm->flag & ARM_POSEMODE) - index = base->selcol; + index = base->object->select_color; /* only draw custom bone shapes that need to be drawn as wires */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { @@ -1926,13 +2128,13 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (bone->layer & arm->layer) { if (pchan->custom) { if ((dt < OB_SOLID) || (bone->flag & BONE_DRAWWIRE)) { - glPushMatrix(); + gpuPushMatrix(); if (pchan->custom_tx) { - glMultMatrixf(pchan->custom_tx->pose_mat); + gpuMultMatrix(pchan->custom_tx->pose_mat); } else { - glMultMatrixf(pchan->pose_mat); + gpuMultMatrix(pchan->pose_mat); } /* prepare colors */ @@ -1942,7 +2144,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, else if (arm->flag & ARM_POSEMODE) set_pchan_colorset(ob, pchan); else { - glColor3ubv(ob_wire_col); + rgba_uchar_to_float(fcolor, ob_wire_col); } /* catch exception for bone with hidden parent */ @@ -1954,10 +2156,10 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (bone == arm->act_bone) flag |= BONE_DRAW_ACTIVE; - draw_custom_bone(scene, v3d, rv3d, pchan->custom, + draw_custom_bone(eval_ctx, scene, sl, v3d, rv3d, pchan->custom, OB_WIRE, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan)); - glPopMatrix(); + gpuPopMatrix(); } } } @@ -1979,7 +2181,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* draw line check first. we do selection indices */ if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) { if (arm->flag & ARM_POSEMODE) - index = base->selcol; + index = base->object->select_color; } /* if solid && posemode, we draw again with polygonoffset */ else if ((dt > OB_WIRE) && (arm->flag & ARM_POSEMODE)) { @@ -1988,7 +2190,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, else { /* and we use selection indices if not done yet */ if (arm->flag & ARM_POSEMODE) - index = base->selcol; + index = base->object->select_color; } if (is_cull_enabled == false) { @@ -2011,16 +2213,30 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, * - only if V3D_HIDE_HELPLINES is enabled... */ if ((do_dashed & DASH_HELP_LINES) && ((bone->flag & BONE_CONNECTED) == 0)) { + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniformColor4fv(fcolor); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + if (arm->flag & ARM_POSEMODE) { GPU_select_load_id(index & 0xFFFF); /* object tag, for bordersel optim */ - UI_ThemeColor(TH_WIRE); + immUniformThemeColor(TH_WIRE); } - setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(pchan->pose_head); - glVertex3fv(pchan->parent->pose_tail); - glEnd(); - setlinestyle(0); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(shdr_pos, pchan->parent->pose_tail); + immVertex3fv(shdr_pos, pchan->pose_head); + immEnd(); + + immUnbindProgram(); } /* Draw a line to IK root bone @@ -2029,8 +2245,11 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (arm->flag & ARM_POSEMODE) { if (constflag & PCHAN_HAS_IK) { if (bone->flag & BONE_SELECTED) { - if (constflag & PCHAN_HAS_TARGET) glColor3ub(200, 120, 0); - else glColor3ub(200, 200, 50); /* add theme! */ + if (constflag & PCHAN_HAS_TARGET) { + rgba_float_args_set(fcolor, 200.f / 255.f, 120.f / 255.f, 0.f / 255.f, 1.0f); + } + /* add theme! */ + else rgba_float_args_set(fcolor, 200.f / 255.f, 200.f / 255.f, 50.f / 255.f, 1.0f); GPU_select_load_id(index & 0xFFFF); pchan_draw_IK_root_lines(pchan, !(do_dashed & DASH_HELP_LINES)); @@ -2038,8 +2257,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } else if (constflag & PCHAN_HAS_SPLINEIK) { if (bone->flag & BONE_SELECTED) { - glColor3ub(150, 200, 50); /* add theme! */ - + /* add theme! */ + rgba_float_args_set(fcolor, 150.f / 255.f, 200.f / 255.f, 50.f / 255.f, 1.0f); + GPU_select_load_id(index & 0xFFFF); pchan_draw_IK_root_lines(pchan, !(do_dashed & DASH_HELP_LINES)); } @@ -2047,9 +2267,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } } - glPushMatrix(); + gpuPushMatrix(); if (arm->drawtype != ARM_ENVELOPE) - glMultMatrixf(pchan->pose_mat); + gpuMultMatrix(pchan->pose_mat); /* catch exception for bone with hidden parent */ flag = bone->flag; @@ -2086,7 +2306,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, else draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->length); - glPopMatrix(); + gpuPopMatrix(); } } @@ -2106,7 +2326,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* draw DoFs */ if (arm->flag & ARM_POSEMODE) { - if (((base->flag & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) { + if (((base->flag_legacy & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) { draw_pose_dofs(ob); } } @@ -2114,26 +2334,17 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* finally names and axes */ if ((arm->flag & (ARM_DRAWNAMES | ARM_DRAWAXES)) && (is_outline == 0) && - ((base->flag & OB_FROMDUPLI) == 0)) + ((base->flag_legacy & OB_FROMDUPLI) == 0)) { /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */ if ((G.f & G_PICKSEL) == 0) { float vec[3]; unsigned char col[4]; - if (do_const_color) { - /* so we can draw bone names in current const color */ - float tcol[4]; - glGetFloatv(GL_CURRENT_COLOR, tcol); - rgb_float_to_uchar(col, tcol); - col[3] = 255; - } - else { - col[0] = ob_wire_col[0]; - col[1] = ob_wire_col[1]; - col[2] = ob_wire_col[2]; - col[3] = 255; - } + col[0] = ob_wire_col[0]; + col[1] = ob_wire_col[1]; + col[2] = ob_wire_col[2]; + col[3] = 255; if (v3d->zbuf) glDisable(GL_DEPTH_TEST); @@ -2156,18 +2367,16 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* Draw additional axes on the bone tail */ if ((arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE)) { - glPushMatrix(); + gpuPushMatrix(); copy_m4_m4(bmat, pchan->pose_mat); bone_matrix_translate_y(bmat, pchan->bone->length); - glMultMatrixf(bmat); + gpuMultMatrix(bmat); - glColor3ubv(col); - float viewmat_pchan[4][4]; mul_m4_m4m4(viewmat_pchan, rv3d->viewmatob, bmat); - drawaxes(viewmat_pchan, pchan->bone->length * 0.25f, OB_ARROWS); + drawaxes(viewmat_pchan, pchan->bone->length * 0.25f, OB_ARROWS, col); - glPopMatrix(); + gpuPopMatrix(); } } } @@ -2233,9 +2442,9 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) for (eBone = arm->edbo->first, index = 0; eBone; eBone = eBone->next, index++) { if (eBone->layer & arm->layer) { if ((eBone->flag & BONE_HIDDEN_A) == 0) { - glPushMatrix(); + gpuPushMatrix(); get_matrix_editbone(eBone, bmat); - glMultMatrixf(bmat); + gpuMultMatrix(bmat); /* catch exception for bone with hidden parent */ flag = eBone->flag; @@ -2257,7 +2466,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length); } - glPopMatrix(); + gpuPopMatrix(); } } } @@ -2295,9 +2504,9 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) draw_sphere_bone_wire(smat, imat, arm->flag, flag, 0, index, NULL, eBone); } else { - glPushMatrix(); + gpuPushMatrix(); get_matrix_editbone(eBone, bmat); - glMultMatrixf(bmat); + gpuMultMatrix(bmat); if (arm->drawtype == ARM_LINE) draw_line_bone(arm->flag, flag, 0, index, NULL, eBone); @@ -2308,21 +2517,32 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) else draw_bone(OB_WIRE, arm->flag, flag, 0, index, eBone->length); - glPopMatrix(); + gpuPopMatrix(); } /* offset to parent */ if (eBone->parent) { - UI_ThemeColor(TH_WIRE_EDIT); + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + GPU_select_load_id(-1); /* -1 here is OK! */ - setlinestyle(3); - - glBegin(GL_LINES); - glVertex3fv(eBone->parent->tail); - glVertex3fv(eBone->head); - glEnd(); - - setlinestyle(0); + + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniformThemeColor(TH_WIRE_EDIT); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(shdr_pos, eBone->parent->tail); + immVertex3fv(shdr_pos, eBone->head); + immEnd(); + + immUnbindProgram(); } } } @@ -2364,18 +2584,16 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) } /* Draw additional axes */ if (arm->flag & ARM_DRAWAXES) { - glPushMatrix(); + gpuPushMatrix(); get_matrix_editbone(eBone, bmat); bone_matrix_translate_y(bmat, eBone->length); - glMultMatrixf(bmat); - - glColor3ubv(col); + gpuMultMatrix(bmat); float viewmat_ebone[4][4]; mul_m4_m4m4(viewmat_ebone, rv3d->viewmatob, bmat); - drawaxes(viewmat_ebone, eBone->length * 0.25f, OB_ARROWS); + drawaxes(viewmat_ebone, eBone->length * 0.25f, OB_ARROWS, col); - glPopMatrix(); + gpuPopMatrix(); } } @@ -2448,7 +2666,8 @@ static void ghost_poses_tag_unselected(Object *ob, short unset) /* draw ghosts that occur within a frame range * note: object should be in posemode */ -static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +static void draw_ghost_poses_range( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base) { Object *ob = base->object; AnimData *adt = BKE_animdata_from_id(&ob->id); @@ -2456,6 +2675,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base bPose *posen, *poseo; float start, end, stepsize, range, colfac; int cfrao, flago; + unsigned char col[4]; start = (float)arm->ghostsf; end = (float)arm->ghostef; @@ -2488,11 +2708,11 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base /* draw from first frame of range to last */ for (CFRA = (int)start; CFRA <= end; CFRA += (int)stepsize) { colfac = (end - (float)CFRA) / range; - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac))); + UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col); BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL); - BKE_pose_where_is(scene, ob); - draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false); + BKE_pose_where_is(eval_ctx, scene, ob); + draw_pose_bones(eval_ctx, scene, sl, v3d, ar, base, OB_WIRE, col, true, false); } glDisable(GL_BLEND); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); @@ -2514,7 +2734,9 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base /* draw ghosts on keyframes in action within range * - object should be in posemode */ -static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +static void draw_ghost_poses_keys( + const struct EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, + View3D *v3d, ARegion *ar, Base *base) { Object *ob = base->object; AnimData *adt = BKE_animdata_from_id(&ob->id); @@ -2525,6 +2747,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base * ActKeyColumn *ak, *akn; float start, end, range, colfac, i; int cfrao, flago; + unsigned char col[4]; start = (float)arm->ghostsf; end = (float)arm->ghostef; @@ -2566,13 +2789,13 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base * /* draw from first frame of range to last */ for (ak = keys.first, i = 0; ak; ak = ak->next, i++) { colfac = i / range; - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac))); + UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col); CFRA = (int)ak->cfra; BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL); - BKE_pose_where_is(scene, ob); - draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false); + BKE_pose_where_is(eval_ctx, scene, ob); + draw_pose_bones(eval_ctx, scene, sl, v3d, ar, base, OB_WIRE, col, true, false); } glDisable(GL_BLEND); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); @@ -2595,7 +2818,9 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base * /* draw ghosts around current frame * - object is supposed to be armature in posemode */ -static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +static void draw_ghost_poses( + const struct EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, + View3D *v3d, ARegion *ar, Base *base) { Object *ob = base->object; AnimData *adt = BKE_animdata_from_id(&ob->id); @@ -2603,7 +2828,8 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) bPose *posen, *poseo; float cur, start, end, stepsize, range, colfac, actframe, ctime; int cfrao, flago; - + unsigned char col[4]; + /* pre conditions, get an action with sufficient frames */ if (ELEM(NULL, adt, adt->action)) return; @@ -2640,7 +2866,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) for (cur = stepsize; cur < range; cur += stepsize) { ctime = cur - (float)fmod(cfrao, stepsize); /* ensures consistent stepping */ colfac = ctime / range; - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac))); + UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col); /* only within action range */ if (actframe + ctime >= start && actframe + ctime <= end) { @@ -2648,14 +2874,14 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) if (CFRA != cfrao) { BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL); - BKE_pose_where_is(scene, ob); - draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false); + BKE_pose_where_is(eval_ctx, scene, ob); + draw_pose_bones(eval_ctx, scene, sl, v3d, ar, base, OB_WIRE, col, true, false); } } ctime = cur + (float)fmod((float)cfrao, stepsize) - stepsize + 1.0f; /* ensures consistent stepping */ colfac = ctime / range; - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac))); + UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col); /* only within action range */ if ((actframe - ctime >= start) && (actframe - ctime <= end)) { @@ -2663,8 +2889,8 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) if (CFRA != cfrao) { BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL); - BKE_pose_where_is(scene, ob); - draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false); + BKE_pose_where_is(eval_ctx, scene, ob); + draw_pose_bones(eval_ctx, scene, sl, v3d, ar, base, OB_WIRE, col, true, false); } } } @@ -2689,9 +2915,10 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) /* called from drawobject.c, return true if nothing was drawn * (ob_wire_col == NULL) when drawing ghost */ -bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4], - const bool is_outline) +bool draw_armature( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, + const short dt, const short dflag, const unsigned char ob_wire_col[4], + const bool is_outline) { Object *ob = base->object; bArmature *arm = ob->data; @@ -2700,11 +2927,7 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (v3d->flag2 & V3D_RENDER_OVERRIDE) return true; - /* needed for 'draw_line_bone' which draws pixel. */ - if (arm->drawtype == ARM_LINE) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - } - +#if 0 /* Not used until lighting is properly reimplemented */ if (dt > OB_WIRE) { /* we use color for solid lighting */ if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) { @@ -2719,7 +2942,8 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); /* only for lighting... */ } } - +#endif + /* arm->flag is being used to detect mode... */ /* editmode? */ if (arm->edbo) { @@ -2736,7 +2960,7 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } /* drawing posemode selection indices or colors only in these cases */ - if (!(base->flag & OB_FROMDUPLI)) { + if (!(base->flag_legacy & OB_FROMDUPLI)) { if (G.f & G_PICKSEL) { #if 0 /* nifty but actually confusing to allow bone selection out of posemode */ @@ -2752,31 +2976,28 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } else if (ob->mode & OB_MODE_POSE) { if (arm->ghosttype == ARM_GHOST_RANGE) { - draw_ghost_poses_range(scene, v3d, ar, base); + draw_ghost_poses_range(eval_ctx, scene, sl, v3d, ar, base); } else if (arm->ghosttype == ARM_GHOST_KEYS) { - draw_ghost_poses_keys(scene, v3d, ar, base); + draw_ghost_poses_keys(eval_ctx, scene, sl, v3d, ar, base); } else if (arm->ghosttype == ARM_GHOST_CUR) { if (arm->ghostep) - draw_ghost_poses(scene, v3d, ar, base); + draw_ghost_poses(eval_ctx, scene, sl, v3d, ar, base); } if ((dflag & DRAW_SCENESET) == 0) { - if (ob == OBACT) + if (ob == OBACT(sl)) arm->flag |= ARM_POSEMODE; - else if (OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) { - if (ob == modifiers_isDeformedByArmature(OBACT)) + else if (OBACT(sl) && (OBACT(sl)->mode & OB_MODE_WEIGHT_PAINT)) { + if (ob == modifiers_isDeformedByArmature(OBACT(sl))) arm->flag |= ARM_POSEMODE; } draw_pose_paths(scene, v3d, ar, ob); } } } - draw_pose_bones(scene, v3d, ar, base, dt, ob_wire_col, (dflag & DRAW_CONSTCOLOR), is_outline); + draw_pose_bones(eval_ctx, scene, sl, v3d, ar, base, dt, ob_wire_col, (dflag & DRAW_CONSTCOLOR), is_outline); arm->flag &= ~ARM_POSEMODE; - - if (ob->mode & OB_MODE_POSE) - UI_ThemeColor(TH_WIRE); /* restore, for extra draw stuff */ } else { retval = true; @@ -2785,9 +3006,5 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* restore */ glFrontFace(GL_CCW); - if (arm->drawtype == ARM_LINE) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - } - return retval; } diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index bbbf8c633bd..719fb6f764f 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -55,7 +55,6 @@ #include "BKE_editmesh.h" #include "BKE_scene.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "UI_resources.h" @@ -64,6 +63,7 @@ #include "GPU_material.h" #include "GPU_basic_shader.h" #include "GPU_shader.h" +#include "GPU_matrix.h" #include "RE_engine.h" @@ -77,20 +77,6 @@ typedef struct drawMeshFaceSelect_userData { BLI_bitmap *edge_flags; /* pairs of edge options (visible, select) */ } drawMeshFaceSelect_userData; -typedef struct drawEMTFMapped_userData { - BMEditMesh *em; - bool has_mcol; - int cd_poly_tex_offset; - const MPoly *mpoly; - const MTexPoly *mtexpoly; -} drawEMTFMapped_userData; - -typedef struct drawTFace_userData { - const Mesh *me; - const MPoly *mpoly; - const MTexPoly *mtexpoly; -} drawTFace_userData; - /**************************** Face Select Mode *******************************/ /* mainly to be less confusing */ @@ -213,562 +199,6 @@ void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm, bool d /***************************** Texture Drawing ******************************/ -static Material *give_current_material_or_def(Object *ob, int matnr) -{ - extern Material defmaterial; /* render module abuse... */ - Material *ma = give_current_material(ob, matnr); - - return ma ? ma : &defmaterial; -} - -/* Icky globals, fix with userdata parameter */ - -static struct TextureDrawState { - Object *ob; - Image *stencil; /* texture painting stencil */ - Image *canvas; /* texture painting canvas, for image mode */ - bool use_game_mat; - int is_lit, is_tex; - int color_profile; - bool use_backface_culling; - bool two_sided_lighting; - unsigned char obcol[4]; - bool is_texpaint; - bool texpaint_material; /* use material slots for texture painting */ -} Gtexdraw = {NULL, NULL, NULL, false, 0, 0, 0, false, false, {0, 0, 0, 0}, false, false}; - -static bool set_draw_settings_cached( - int clearcache, MTexPoly *texface, Material *ma, - const struct TextureDrawState *gtexdraw) -{ - static Material *c_ma; - static int c_textured; - static MTexPoly c_texface; - static int c_backculled; - static bool c_badtex; - static int c_lit; - static int c_has_texface; - - int backculled = 1; - int alphablend = GPU_BLEND_SOLID; - int textured = 0; - int lit = 0; - int has_texface = texface != NULL; - bool need_set_tpage = false; - bool texpaint = ((gtexdraw->ob->mode & OB_MODE_TEXTURE_PAINT) != 0); - - Image *ima = NULL; - - if (ma != NULL) { - if (ma->mode & MA_TRANSP) { - alphablend = GPU_BLEND_ALPHA; - } - } - - if (clearcache) { - c_textured = c_lit = c_backculled = -1; - memset(&c_texface, 0, sizeof(c_texface)); - c_badtex = false; - c_has_texface = -1; - c_ma = NULL; - } - else { - textured = gtexdraw->is_tex; - } - - /* convert number of lights into boolean */ - if (gtexdraw->is_lit) { - lit = 1; - } - - backculled = gtexdraw->use_backface_culling; - if (ma) { - if (ma->mode & MA_SHLESS) lit = 0; - if (gtexdraw->use_game_mat) { - backculled = backculled || (ma->game.flag & GEMAT_BACKCULL); - alphablend = ma->game.alpha_blend; - } - } - - if (texface && !texpaint) { - textured = textured && (texface->tpage); - - /* no material, render alpha if texture has depth=32 */ - if (!ma && BKE_image_has_alpha(texface->tpage)) - alphablend = GPU_BLEND_ALPHA; - } - else if (texpaint) { - if (gtexdraw->texpaint_material) - ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL; - else - ima = gtexdraw->canvas; - } - else - textured = 0; - - if (backculled != c_backculled) { - if (backculled) glEnable(GL_CULL_FACE); - else glDisable(GL_CULL_FACE); - - c_backculled = backculled; - } - - /* need to re-set tpage if textured flag changed or existsment of texface changed.. */ - need_set_tpage = textured != c_textured || has_texface != c_has_texface; - /* ..or if settings inside texface were changed (if texface was used) */ - need_set_tpage |= (texpaint && c_ma != ma) || (texface && memcmp(&c_texface, texface, sizeof(c_texface))); - - if (need_set_tpage) { - if (textured) { - if (texpaint) { - c_badtex = false; - if (GPU_verify_image(ima, NULL, GL_TEXTURE_2D, 0, 1, 0, false)) { - glEnable(GL_TEXTURE_2D); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE); - - glActiveTexture(GL_TEXTURE1); - glEnable(GL_TEXTURE_2D); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); - glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); - glActiveTexture(GL_TEXTURE0); - } - else { - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glActiveTexture(GL_TEXTURE0); - - c_badtex = true; - GPU_clear_tpage(true); - glDisable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } - } - else { - c_badtex = !GPU_set_tpage(texface, !texpaint, alphablend); - } - } - else { - GPU_set_tpage(NULL, 0, 0); - c_badtex = false; - } - c_textured = textured; - c_has_texface = has_texface; - if (texface) - memcpy(&c_texface, texface, sizeof(c_texface)); - } - - if (c_badtex) lit = 0; - if (lit != c_lit || ma != c_ma || textured != c_textured) { - int options = GPU_SHADER_USE_COLOR; - - if (c_textured && !c_badtex) { - options |= GPU_SHADER_TEXTURE_2D; - } - if (gtexdraw->two_sided_lighting) { - options |= GPU_SHADER_TWO_SIDED; - } - - if (lit) { - options |= GPU_SHADER_LIGHTING; - if (!ma) - ma = give_current_material_or_def(NULL, 0); /* default material */ - - float specular[3]; - mul_v3_v3fl(specular, &ma->specr, ma->spec); - - GPU_basic_shader_colors(NULL, specular, ma->har, 1.0f); - } - - GPU_basic_shader_bind(options); - - c_lit = lit; - c_ma = ma; - } - - return c_badtex; -} - -static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) -{ - unsigned char obcol[4]; - bool is_tex, solidtex; - Mesh *me = ob->data; - ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; - - /* XXX scene->obedit warning */ - - /* texture draw is abused for mask selection mode, do this so wire draw - * with face selection in weight paint is not lit. */ - if ((v3d->drawtype <= OB_WIRE) && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT))) { - solidtex = false; - Gtexdraw.is_lit = 0; - } - else if ((ob->mode & OB_MODE_TEXTURE_PAINT) && BKE_scene_use_new_shading_nodes(scene)) { - solidtex = true; - if (v3d->flag2 & V3D_SHADELESS_TEX) - Gtexdraw.is_lit = 0; - else - Gtexdraw.is_lit = -1; - } - else if ((v3d->drawtype == OB_SOLID) || - ((ob->mode & OB_MODE_EDIT) && (v3d->drawtype != OB_TEXTURE))) - { - /* draw with default lights in solid draw mode and edit mode */ - solidtex = true; - Gtexdraw.is_lit = -1; - } - else { - /* draw with lights in the scene otherwise */ - solidtex = false; - if (v3d->flag2 & V3D_SHADELESS_TEX) { - Gtexdraw.is_lit = 0; - } - else { - Gtexdraw.is_lit = GPU_scene_object_lights( - scene, ob, v3d->localvd ? v3d->localvd->lay : v3d->lay, - rv3d->viewmat, !rv3d->is_persp); - } - } - - rgba_float_to_uchar(obcol, ob->col); - - if (solidtex || v3d->drawtype == OB_TEXTURE) is_tex = true; - else is_tex = false; - - Gtexdraw.ob = ob; - Gtexdraw.stencil = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? imapaint->stencil : NULL; - Gtexdraw.is_texpaint = (ob->mode == OB_MODE_TEXTURE_PAINT); - Gtexdraw.texpaint_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL); - Gtexdraw.canvas = (Gtexdraw.texpaint_material) ? NULL : imapaint->canvas; - Gtexdraw.is_tex = is_tex; - - /* naughty multitexturing hacks to quickly support stencil + shading + alpha blending - * in new texpaint code. The better solution here would be to support GLSL */ - if (Gtexdraw.is_texpaint) { - glActiveTexture(GL_TEXTURE1); - glEnable(GL_TEXTURE_2D); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); - - /* load the stencil texture here */ - if (Gtexdraw.stencil != NULL) { - glActiveTexture(GL_TEXTURE2); - if (GPU_verify_image(Gtexdraw.stencil, NULL, GL_TEXTURE_2D, false, false, false, false)) { - float col[4] = {imapaint->stencil_col[0], imapaint->stencil_col[1], imapaint->stencil_col[2], 1.0f}; - glEnable(GL_TEXTURE_2D); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, col); - if ((imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) == 0) { - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_ONE_MINUS_SRC_COLOR); - } - else { - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); - } - } - } - glActiveTexture(GL_TEXTURE0); - } - - Gtexdraw.color_profile = BKE_scene_check_color_management_enabled(scene); - Gtexdraw.use_game_mat = (RE_engines_find(scene->r.engine)->flag & RE_GAME) != 0; - Gtexdraw.use_backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0; - Gtexdraw.two_sided_lighting = (me->flag & ME_TWOSIDED); - - memcpy(Gtexdraw.obcol, obcol, sizeof(obcol)); - set_draw_settings_cached(1, NULL, NULL, &Gtexdraw); - glCullFace(GL_BACK); -} - -static void draw_textured_end(void) -{ - if (Gtexdraw.ob->mode & OB_MODE_TEXTURE_PAINT) { - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glBindTexture(GL_TEXTURE_2D, 0); - - if (Gtexdraw.stencil != NULL) { - glActiveTexture(GL_TEXTURE2); - glDisable(GL_TEXTURE_2D); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glBindTexture(GL_TEXTURE_2D, 0); - } - glActiveTexture(GL_TEXTURE0); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - /* manual reset, since we don't use tpage */ - glBindTexture(GL_TEXTURE_2D, 0); - /* force switch off textures */ - GPU_clear_tpage(true); - } - else { - /* switch off textures */ - GPU_set_tpage(NULL, 0, 0); - } - - glDisable(GL_CULL_FACE); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - - /* XXX, bad patch - GPU_default_lights() calls - * glLightfv(GL_POSITION, ...) which - * is transformed by the current matrix... we - * need to make sure that matrix is identity. - * - * It would be better if drawmesh.c kept track - * of and restored the light settings it changed. - * - zr - */ - glPushMatrix(); - glLoadIdentity(); - GPU_default_lights(); - glPopMatrix(); -} - -static DMDrawOption draw_tface__set_draw_legacy(MTexPoly *mtexpoly, const bool has_mcol, int matnr) -{ - Material *ma = give_current_material(Gtexdraw.ob, matnr + 1); - bool invalidtexture = false; - - if (ma && (ma->game.flag & GEMAT_INVISIBLE)) - return DM_DRAW_OPTION_SKIP; - - invalidtexture = set_draw_settings_cached(0, mtexpoly, ma, &Gtexdraw); - - if (mtexpoly && invalidtexture) { - glColor3ub(0xFF, 0x00, 0xFF); - return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */ - } - else if (!has_mcol) { - if (mtexpoly) { - glColor3f(1.0, 1.0, 1.0); - } - else { - if (ma) { - if (ma->shade_flag & MA_OBCOLOR) { - glColor3ubv(Gtexdraw.obcol); - } - else { - float col[3]; - if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r); - else copy_v3_v3(col, &ma->r); - - glColor3fv(col); - } - } - else { - glColor3f(1.0, 1.0, 1.0); - } - } - return DM_DRAW_OPTION_NORMAL; /* normal drawing (no mcols anyway, no need to turn off) */ - } - else { - return DM_DRAW_OPTION_NORMAL; /* Set color from mcol */ - } -} - -static DMDrawOption draw_tface__set_draw(MTexPoly *mtexpoly, const bool UNUSED(has_mcol), int matnr) -{ - Material *ma = give_current_material(Gtexdraw.ob, matnr + 1); - - if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return DM_DRAW_OPTION_SKIP; - - if (mtexpoly || Gtexdraw.is_texpaint) - set_draw_settings_cached(0, mtexpoly, ma, &Gtexdraw); - - /* always use color from mcol, as set in update_tface_color_layer */ - return DM_DRAW_OPTION_NORMAL; -} - -static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol) -{ - const MPoly *mp = dm->getPolyArray(dm); - const int mpoly_num = dm->getNumPolys(dm); - MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY); - MLoopCol *finalCol; - int i, j; - MLoopCol *mloopcol = NULL; - - /* cache material values to avoid a lot of lookups */ - Material *ma = NULL; - short mat_nr_prev = -1; - enum { - COPY_CALC, - COPY_ORIG, - COPY_PREV, - } copy_mode = COPY_CALC; - - if (use_mcol) { - mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL); - if (!mloopcol) - mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL); - } - - if (CustomData_has_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL)) { - finalCol = CustomData_get_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL); - } - else { - finalCol = MEM_mallocN(sizeof(MLoopCol) * dm->numLoopData, "add_tface_color_layer"); - CustomData_add_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL, CD_ASSIGN, finalCol, dm->numLoopData); - } - - for (i = mpoly_num; i--; mp++) { - const short mat_nr = mp->mat_nr; - - if (UNLIKELY(mat_nr_prev != mat_nr)) { - ma = give_current_material(Gtexdraw.ob, mat_nr + 1); - copy_mode = COPY_CALC; - mat_nr_prev = mat_nr; - } - - /* avoid lookups */ - if (copy_mode == COPY_ORIG) { - memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop); - } - else if (copy_mode == COPY_PREV) { - int loop_index = mp->loopstart; - const MLoopCol *lcol_prev = &finalCol[(mp - 1)->loopstart]; - for (j = 0; j < mp->totloop; j++, loop_index++) { - finalCol[loop_index] = *lcol_prev; - } - } - - /* (copy_mode == COPY_CALC) */ - else if (ma && (ma->game.flag & GEMAT_INVISIBLE)) { - if (mloopcol) { - memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop); - copy_mode = COPY_ORIG; - } - else { - memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop); - copy_mode = COPY_PREV; - } - } - else if (mtexpoly && set_draw_settings_cached(0, mtexpoly, ma, &Gtexdraw)) { - int loop_index = mp->loopstart; - for (j = 0; j < mp->totloop; j++, loop_index++) { - finalCol[loop_index].r = 255; - finalCol[loop_index].g = 0; - finalCol[loop_index].b = 255; - finalCol[loop_index].a = 255; - } - copy_mode = COPY_PREV; - } - else if (ma && (ma->shade_flag & MA_OBCOLOR)) { - int loop_index = mp->loopstart; - for (j = 0; j < mp->totloop; j++, loop_index++) { - copy_v3_v3_uchar(&finalCol[loop_index].r, Gtexdraw.obcol); - finalCol[loop_index].a = 255; - } - copy_mode = COPY_PREV; - } - else { - if (mloopcol) { - memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop); - copy_mode = COPY_ORIG; - } - else if (mtexpoly) { - memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop); - copy_mode = COPY_PREV; - } - else { - float col[3]; - - if (ma) { - int loop_index = mp->loopstart; - MLoopCol lcol; - - if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r); - else copy_v3_v3(col, &ma->r); - rgb_float_to_uchar((unsigned char *)&lcol.r, col); - lcol.a = 255; - - for (j = 0; j < mp->totloop; j++, loop_index++) { - finalCol[loop_index] = lcol; - } - } - else { - memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop); - } - copy_mode = COPY_PREV; - } - } - } - - dm->dirty |= DM_DIRTY_MCOL_UPDATE_DRAW; -} - -static DMDrawOption draw_tface_mapped__set_draw(void *userData, int origindex, int UNUSED(mat_nr)) -{ - const Mesh *me = ((drawTFace_userData *)userData)->me; - - /* array checked for NULL before calling */ - MPoly *mpoly = &me->mpoly[origindex]; - - BLI_assert(origindex >= 0 && origindex < me->totpoly); - - if (mpoly->flag & ME_HIDE) { - return DM_DRAW_OPTION_SKIP; - } - else { - MTexPoly *tpoly = (me->mtpoly) ? &me->mtpoly[origindex] : NULL; - int matnr = mpoly->mat_nr; - - return draw_tface__set_draw(tpoly, (me->mloopcol != NULL), matnr); - } -} - -static DMDrawOption draw_em_tf_mapped__set_draw(void *userData, int origindex, int mat_nr) -{ - drawEMTFMapped_userData *data = userData; - BMEditMesh *em = data->em; - BMFace *efa; - - if (UNLIKELY(origindex >= em->bm->totface)) - return DM_DRAW_OPTION_NORMAL; - - efa = BM_face_at_index(em->bm, origindex); - - if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - return DM_DRAW_OPTION_SKIP; - } - else { - MTexPoly *mtexpoly = (data->cd_poly_tex_offset != -1) ? - BM_ELEM_CD_GET_VOID_P(efa, data->cd_poly_tex_offset) : NULL; - int matnr = (mat_nr != -1) ? mat_nr : efa->mat_nr; - - return draw_tface__set_draw_legacy(mtexpoly, data->has_mcol, matnr); - } -} - /* when face select is on, use face hidden flag */ static DMDrawOption wpaint__setSolidDrawOptions_facemask(void *userData, int index) { @@ -779,288 +209,6 @@ static DMDrawOption wpaint__setSolidDrawOptions_facemask(void *userData, int ind return DM_DRAW_OPTION_NORMAL; } -static void draw_mesh_text(Scene *scene, Object *ob, int glsl) -{ - Mesh *me = ob->data; - DerivedMesh *ddm; - MPoly *mp, *mface = me->mpoly; - MTexPoly *mtpoly = me->mtpoly; - MLoopUV *mloopuv = me->mloopuv; - MLoopUV *luv; - MLoopCol *mloopcol = me->mloopcol; /* why does mcol exist? */ - MLoopCol *lcol; - - bProperty *prop = BKE_bproperty_object_get(ob, "Text"); - GPUVertexAttribs gattribs; - int a, totpoly = me->totpoly; - - /* fake values to pass to GPU_render_text() */ - MCol tmp_mcol[4] = {{0}}; - MCol *tmp_mcol_pt = mloopcol ? tmp_mcol : NULL; - - /* don't draw without tfaces */ - if (!mtpoly || !mloopuv) - return; - - /* don't draw when editing */ - if (ob->mode & OB_MODE_EDIT) - return; - else if (ob == OBACT) - if (BKE_paint_select_elem_test(ob)) - return; - - ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); - - for (a = 0, mp = mface; a < totpoly; a++, mtpoly++, mp++) { - short matnr = mp->mat_nr; - const bool mf_smooth = (mp->flag & ME_SMOOTH) != 0; - Material *mat = (me->mat) ? me->mat[matnr] : NULL; - int mode = mat ? mat->game.flag : GEMAT_INVISIBLE; - - - if (!(mode & GEMAT_INVISIBLE) && (mode & GEMAT_TEXT) && mp->totloop >= 3) { - /* get the polygon as a tri/quad */ - int mp_vi[4]; - float v_quad_data[4][3]; - const float *v_quad[4]; - const float *uv_quad[4]; - char string[MAX_PROPSTRING]; - int characters, i, glattrib = -1, badtex = 0; - - - /* TEXFACE */ - if (glsl) { - GPU_object_material_bind(matnr + 1, &gattribs); - - for (i = 0; i < gattribs.totlayer; i++) { - if (gattribs.layer[i].type == CD_MTFACE) { - glattrib = gattribs.layer[i].glindex; - break; - } - } - } - else { - badtex = set_draw_settings_cached(0, mtpoly, mat, &Gtexdraw); - if (badtex) { - continue; - } - } - - mp_vi[0] = me->mloop[mp->loopstart + 0].v; - mp_vi[1] = me->mloop[mp->loopstart + 1].v; - mp_vi[2] = me->mloop[mp->loopstart + 2].v; - mp_vi[3] = (mp->totloop >= 4) ? me->mloop[mp->loopstart + 3].v : 0; - - /* UV */ - luv = &mloopuv[mp->loopstart]; - uv_quad[0] = luv->uv; luv++; - uv_quad[1] = luv->uv; luv++; - uv_quad[2] = luv->uv; luv++; - if (mp->totloop >= 4) { - uv_quad[3] = luv->uv; - } - else { - uv_quad[3] = NULL; - } - - - /* COLOR */ - if (mloopcol) { - unsigned int totloop_clamp = min_ii(4, mp->totloop); - unsigned int j; - lcol = &mloopcol[mp->loopstart]; - - for (j = 0; j < totloop_clamp; j++, lcol++) { - MESH_MLOOPCOL_TO_MCOL(lcol, &tmp_mcol[j]); - } - } - - /* LOCATION */ - ddm->getVertCo(ddm, mp_vi[0], v_quad_data[0]); - ddm->getVertCo(ddm, mp_vi[1], v_quad_data[1]); - ddm->getVertCo(ddm, mp_vi[2], v_quad_data[2]); - if (mp->totloop >= 4) { - ddm->getVertCo(ddm, mp_vi[3], v_quad_data[3]); - } - - v_quad[0] = v_quad_data[0]; - v_quad[1] = v_quad_data[1]; - v_quad[2] = v_quad_data[2]; - if (mp->totloop >= 4) { - v_quad[3] = v_quad_data[2]; - } - else { - v_quad[3] = NULL; - } - - - /* The BM_FONT handling is in the gpu module, shared with the - * game engine, was duplicated previously */ - - BKE_bproperty_set_valstr(prop, string); - characters = strlen(string); - - if (!BKE_image_has_ibuf(mtpoly->tpage, NULL)) - characters = 0; - - if (!mf_smooth) { - float nor[3]; - - normal_tri_v3(nor, v_quad[0], v_quad[1], v_quad[2]); - - glNormal3fv(nor); - } - - GPU_render_text( - mtpoly, mode, string, characters, - (unsigned int *)tmp_mcol_pt, - v_quad, uv_quad, - glattrib); - } - } - - ddm->release(ddm); -} - -static int compareDrawOptions(void *userData, int cur_index, int next_index) -{ - drawTFace_userData *data = userData; - - if (data->mpoly && data->mpoly[cur_index].mat_nr != data->mpoly[next_index].mat_nr) - return 0; - - if (data->mtexpoly && data->mtexpoly[cur_index].tpage != data->mtexpoly[next_index].tpage) - return 0; - - return 1; -} - - -static int compareDrawOptionsEm(void *userData, int cur_index, int next_index) -{ - drawEMTFMapped_userData *data = userData; - - if (data->mpoly && data->mpoly[cur_index].mat_nr != data->mpoly[next_index].mat_nr) - return 0; - - if (data->mtexpoly && data->mtexpoly[cur_index].tpage != data->mtexpoly[next_index].tpage) - return 0; - - return 1; -} - -static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d, - Object *ob, DerivedMesh *dm, const int draw_flags) -{ - Mesh *me = ob->data; - - /* correct for negative scale */ - if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW); - else glFrontFace(GL_CCW); - - /* draw the textured mesh */ - draw_textured_begin(scene, v3d, rv3d, ob); - - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - - if (ob->mode & OB_MODE_EDIT) { - drawEMTFMapped_userData data; - - data.em = me->edit_btmesh; - data.has_mcol = CustomData_has_layer(&me->edit_btmesh->bm->ldata, CD_MLOOPCOL); - data.cd_poly_tex_offset = CustomData_get_offset(&me->edit_btmesh->bm->pdata, CD_MTEXPOLY); - - data.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY); - data.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY); - - dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data, 0); - } - else { - DMDrawFlag dm_draw_flag; - drawTFace_userData userData; - - if (ob->mode & OB_MODE_TEXTURE_PAINT) { - dm_draw_flag = DM_DRAW_USE_TEXPAINT_UV; - } - else { - dm_draw_flag = DM_DRAW_USE_ACTIVE_UV; - } - - if (ob == OBACT) { - if (ob->mode & OB_MODE_WEIGHT_PAINT) { - dm_draw_flag |= DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH | DM_DRAW_SKIP_HIDDEN; - } - else if (ob->mode & OB_MODE_SCULPT) { - dm_draw_flag |= DM_DRAW_SKIP_HIDDEN | DM_DRAW_USE_COLORS; - } - else if ((ob->mode & OB_MODE_TEXTURE_PAINT) == 0) { - dm_draw_flag |= DM_DRAW_USE_COLORS; - } - } - else { - if ((ob->mode & OB_MODE_TEXTURE_PAINT) == 0) { - dm_draw_flag |= DM_DRAW_USE_COLORS; - } - } - - - userData.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY); - userData.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY); - - if (draw_flags & DRAW_FACE_SELECT) { - userData.me = me; - - dm->drawMappedFacesTex( - dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, compareDrawOptions, - &userData, dm_draw_flag); - } - else { - userData.me = NULL; - - /* if ((ob->mode & OB_MODE_ALL_PAINT) == 0) */ { - - /* Note: this isn't efficient and runs on every redraw, - * its needed so material colors are used for vertex colors. - * In the future we will likely remove 'texface' so, just avoid running this where possible, - * (when vertex paint or weight paint are used). - * - * Note 2: We disable optimization for now since it causes T48788 - * and it is now too close to release to do something smarter. - * - * TODO(sergey): Find some real solution here. - */ - - update_tface_color_layer(dm, !(ob->mode & OB_MODE_TEXTURE_PAINT)); - } - - dm->drawFacesTex( - dm, draw_tface__set_draw, compareDrawOptions, - &userData, dm_draw_flag); - } - } - - /* draw game engine text hack */ - if (rv3d->rflag & RV3D_IS_GAME_ENGINE) { - if (BKE_bproperty_object_get(ob, "Text")) { - draw_mesh_text(scene, ob, 0); - } - } - - draw_textured_end(); - - /* draw edges and selected faces over textured mesh */ - if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT)) { - bool draw_select_edges = (ob->mode & OB_MODE_TEXTURE_PAINT) == 0; - draw_mesh_face_select(rv3d, me, dm, draw_select_edges); - } - - /* reset from negative scale correction */ - glFrontFace(GL_CCW); - - /* in editmode, the blend mode needs to be set in case it was ADD */ - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -} - /************************** NEW SHADING NODES ********************************/ typedef struct TexMatCallback { @@ -1072,187 +220,11 @@ typedef struct TexMatCallback { bool two_sided_lighting; } TexMatCallback; -static void tex_mat_set_material_cb(void *UNUSED(userData), int mat_nr, void *attribs) -{ - /* all we have to do here is simply enable the GLSL material, but note - * that the GLSL code will give different result depending on the drawtype, - * in texture draw mode it will output the active texture node, in material - * draw mode it will show the full material. */ - GPU_object_material_bind(mat_nr, attribs); -} - -static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs) -{ - /* texture draw mode without GLSL */ - TexMatCallback *data = (TexMatCallback *)userData; - GPUVertexAttribs *gattribs = attribs; - Image *ima; - ImageUser *iuser; - bNode *node; - - /* draw image texture if we find one */ - if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node, NULL)) { - /* get openl texture */ - int mipmap = 1; - int bindcode = (ima) ? GPU_verify_image(ima, iuser, GL_TEXTURE_2D, 0, 0, mipmap, false) : 0; - - if (bindcode) { - NodeTexBase *texbase = node->storage; - - /* disable existing material */ - GPU_object_material_unbind(); - - /* bind texture */ - glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); - - glMatrixMode(GL_TEXTURE); - glLoadMatrixf(texbase->tex_mapping.mat); - glMatrixMode(GL_MODELVIEW); - - /* use active UV texture layer */ - memset(gattribs, 0, sizeof(*gattribs)); - - gattribs->layer[0].type = CD_MTFACE; - gattribs->layer[0].name[0] = '\0'; - gattribs->layer[0].gltexco = 1; - gattribs->totlayer = 1; - - /* bind material */ - float diffuse[3] = {1.0f, 1.0f, 1.0f}; - - int options = GPU_SHADER_TEXTURE_2D; - if (!data->shadeless) - options |= GPU_SHADER_LIGHTING; - if (data->two_sided_lighting) - options |= GPU_SHADER_TWO_SIDED; - - GPU_basic_shader_colors(diffuse, NULL, 0, 1.0f); - GPU_basic_shader_bind(options); - - return; - } - } - - /* disable texture material */ - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - - if (data->shadeless) { - glColor3f(1.0f, 1.0f, 1.0f); - memset(gattribs, 0, sizeof(*gattribs)); - } - else { - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - - /* enable solid material */ - GPU_object_material_bind(mat_nr, attribs); - } -} - -static bool tex_mat_set_face_mesh_cb(void *userData, int index) -{ - /* faceselect mode face hiding */ - TexMatCallback *data = (TexMatCallback *)userData; - Mesh *me = (Mesh *)data->me; - MPoly *mp = &me->mpoly[index]; - - return !(mp->flag & ME_HIDE); -} - -static bool tex_mat_set_face_editmesh_cb(void *userData, int index) -{ - /* editmode face hiding */ - TexMatCallback *data = (TexMatCallback *)userData; - Mesh *me = (Mesh *)data->me; - BMEditMesh *em = me->edit_btmesh; - BMFace *efa; - - if (UNLIKELY(index >= em->bm->totface)) - return DM_DRAW_OPTION_NORMAL; - - efa = BM_face_at_index(em->bm, index); - - return !BM_elem_flag_test(efa, BM_ELEM_HIDDEN); -} - -void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, +void draw_mesh_textured(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, const int draw_flags) { - /* if not cycles, or preview-modifiers, or drawing matcaps */ - if ((draw_flags & DRAW_MODIFIERS_PREVIEW) || - (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) || - (BKE_scene_use_new_shading_nodes(scene) == false) || - ((ob->mode & OB_MODE_TEXTURE_PAINT) && ELEM(v3d->drawtype, OB_TEXTURE, OB_SOLID))) - { - draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags); - return; - } - else if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) { - draw_mesh_paint(v3d, rv3d, ob, dm, draw_flags); - return; - } - - /* set opengl state for negative scale & color */ - if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW); - else glFrontFace(GL_CCW); - - Mesh *me = ob->data; - - bool shadeless = ((v3d->flag2 & V3D_SHADELESS_TEX) && - ((v3d->drawtype == OB_TEXTURE) || (ob->mode & OB_MODE_TEXTURE_PAINT))); - bool two_sided_lighting = (me->flag & ME_TWOSIDED) != 0; - - TexMatCallback data = {scene, ob, me, dm, shadeless, two_sided_lighting}; - bool (*set_face_cb)(void *, int); - bool picking = (G.f & G_PICKSEL) != 0; - - /* face hiding callback depending on mode */ - if (ob == scene->obedit) - set_face_cb = tex_mat_set_face_editmesh_cb; - else if (draw_flags & DRAW_FACE_SELECT) - set_face_cb = tex_mat_set_face_mesh_cb; - else - set_face_cb = NULL; - - /* test if we can use glsl */ - const int drawtype = view3d_effective_drawtype(v3d); - bool glsl = (drawtype == OB_MATERIAL) && !picking; - - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); - - if (glsl || picking) { - /* draw glsl or solid */ - dm->drawMappedFacesMat(dm, - tex_mat_set_material_cb, - set_face_cb, &data); - } - else { - /* draw textured */ - dm->drawMappedFacesMat(dm, - tex_mat_set_texture_cb, - set_face_cb, &data); - } - - GPU_end_object_materials(); - - /* reset opengl state */ - GPU_end_object_materials(); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - - glBindTexture(GL_TEXTURE_2D, 0); - - glFrontFace(GL_CCW); - - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - - /* faceselect mode drawing over textured mesh */ - if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT)) { - bool draw_select_edges = (ob->mode & OB_MODE_TEXTURE_PAINT) == 0; - draw_mesh_face_select(rv3d, ob->data, dm, draw_select_edges); - } + UNUSED_VARS(scene, sl, v3d, rv3d, ob, dm, draw_flags); + return; } /* Vertex Paint and Weight Paint */ @@ -1299,13 +271,6 @@ void draw_mesh_paint_vcolor_faces(DerivedMesh *dm, const bool use_light, flags |= DM_DRAW_NEED_NORMALS; } - /* Don't show alpha in wire mode. */ - const bool show_alpha = use_light; - if (show_alpha) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - if (me->mloopcol) { dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data, DM_DRAW_USE_COLORS | flags); @@ -1315,10 +280,6 @@ void draw_mesh_paint_vcolor_faces(DerivedMesh *dm, const bool use_light, dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data, flags); } - if (show_alpha) { - glDisable(GL_BLEND); - } - if (use_light) { draw_mesh_paint_light_end(); } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index d7e3b78cdc3..eaf699d8385 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -54,6 +54,7 @@ #include "BKE_camera.h" #include "BKE_colortools.h" #include "BKE_constraint.h" /* for the get_constraint_target function */ +#include "BKE_context.h" #include "BKE_curve.h" #include "BKE_DerivedMesh.h" #include "BKE_deform.h" @@ -62,6 +63,7 @@ #include "BKE_global.h" #include "BKE_image.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -80,6 +82,8 @@ #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" + #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -90,6 +94,10 @@ #include "GPU_select.h" #include "GPU_basic_shader.h" #include "GPU_shader.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_batch.h" +#include "GPU_matrix.h" #include "ED_mesh.h" #include "ED_particle.h" @@ -105,6 +113,13 @@ #include "view3d_intern.h" /* bad level include */ +#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */ + +/* prototypes */ +static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos); + +// #define USE_MESH_DM_SELECT + /* Workaround for sequencer scene render mode. * * Strips doesn't use DAG to update objects or so, which @@ -129,6 +144,7 @@ typedef struct drawDMVerts_userData { BMVert *eve_act; char sel; + unsigned int pos, color; /* cached theme values */ unsigned char th_editmesh_active[4]; @@ -181,6 +197,7 @@ typedef struct drawDMFacesSel_userData { } drawDMFacesSel_userData; typedef struct drawDMNormal_userData { + unsigned int pos; BMesh *bm; int uniform_scale; float normalsize; @@ -189,6 +206,7 @@ typedef struct drawDMNormal_userData { } drawDMNormal_userData; typedef struct drawMVertOffset_userData { + unsigned int pos, col; MVert *mvert; int offset; } drawMVertOffset_userData; @@ -196,9 +214,11 @@ typedef struct drawMVertOffset_userData { typedef struct drawDMLayer_userData { BMesh *bm; int cd_layer_offset; + unsigned int pos, col; } drawDMLayer_userData; typedef struct drawBMOffset_userData { + unsigned int pos, col; BMesh *bm; int offset; } drawBMOffset_userData; @@ -206,25 +226,23 @@ typedef struct drawBMOffset_userData { typedef struct drawBMSelect_userData { BMesh *bm; bool select; + unsigned int pos; } drawBMSelect_userData; -static void draw_bounding_volume(Object *ob, char type); -static void drawcube_size(float size); -static void drawcircle_size(float size); -static void draw_empty_sphere(float size); -static void draw_empty_cone(float size); -static void draw_box(const float vec[8][3], bool solid); +static void drawcube_size(float size, unsigned pos); +static void drawcircle_size(float size, unsigned pos); +static void draw_empty_sphere(float size, unsigned pos); +static void draw_empty_cone(float size, unsigned pos); -static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac) +static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac, float r_col[3]) { - float col_wire[3], col_bg[3], col[3]; + float col_wire[3], col_bg[3]; rgb_uchar_to_float(col_wire, ob_wire_col); UI_GetThemeColor3fv(theme_id, col_bg); - interp_v3_v3v3(col, col_bg, col_wire, fac); - glColor3fv(col); + interp_v3_v3v3(r_col, col_bg, col_wire, fac); } int view3d_effective_drawtype(const struct View3D *v3d) @@ -296,13 +314,13 @@ static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt) /* check for glsl drawing */ -bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) +bool draw_glsl_material(Scene *scene, SceneLayer *sl, Object *ob, View3D *v3d, const char dt) { if (G.f & G_PICKSEL) return false; if (!check_object_draw_texture(scene, v3d, dt)) return false; - if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT)) + if (ob == OBACT(sl) && (ob && ob->mode & OB_MODE_WEIGHT_PAINT)) return false; if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) @@ -318,7 +336,7 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) static bool check_alpha_pass(Base *base) { - if (base->flag & OB_FROMDUPLI) + if (base->flag_legacy & OB_FROMDUPLI) return false; if (G.f & G_PICKSEL) @@ -414,9 +432,9 @@ static const float cosval[CIRCLE_RESOL] = { * \param viewmat_local_unit is typically the 'rv3d->viewmatob' * copied into a 3x3 matrix and normalized. */ -static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3], float size, int axis) +static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3], float size, int axis, unsigned pos) { - int line_type; + Gwn_PrimType line_type = GWN_PRIM_LINES; float buffer[4][3]; int n = 0; @@ -429,8 +447,6 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3] switch (axis) { case 0: /* x axis */ - line_type = GL_LINES; - /* bottom left to top right */ negate_v3_v3(v1, dx); sub_v3_v3(v1, dy); @@ -450,8 +466,6 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3] break; case 1: /* y axis */ - line_type = GL_LINES; - /* bottom left to top right */ mul_v3_fl(dx, 0.75f); negate_v3_v3(v1, dx); @@ -472,7 +486,7 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3] break; case 2: /* z axis */ - line_type = GL_LINE_STRIP; + line_type = GWN_PRIM_LINE_STRIP; /* start at top left */ negate_v3_v3(v1, dx); @@ -501,54 +515,60 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3] return; } + immBegin(line_type, n); for (int i = 0; i < n; i++) { mul_transposed_m3_v3((float (*)[3])viewmat_local_unit, buffer[i]); add_v3_v3(buffer[i], c); + immVertex3fv(pos, buffer[i]); } + immEnd(); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, buffer); - glDrawArrays(line_type, 0, n); - glDisableClientState(GL_VERTEX_ARRAY); + /* TODO: recode this function for clarity once we're not in a hurry to modernize GL usage */ } -void drawaxes(const float viewmat_local[4][4], float size, char drawtype) +void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const unsigned char color[4]) { int axis; float v1[3] = {0.0, 0.0, 0.0}; float v2[3] = {0.0, 0.0, 0.0}; float v3[3] = {0.0, 0.0, 0.0}; - glLineWidth(1); + glLineWidth(1.0f); - switch (drawtype) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + if (color) { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4ubv(color); + } + else { + immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY); + } + switch (drawtype) { case OB_PLAINAXES: + immBegin(GWN_PRIM_LINES, 6); for (axis = 0; axis < 3; axis++) { - glBegin(GL_LINES); - v1[axis] = size; v2[axis] = -size; - glVertex3fv(v1); - glVertex3fv(v2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); /* reset v1 & v2 to zero */ v1[axis] = v2[axis] = 0.0f; - - glEnd(); } + immEnd(); break; - case OB_SINGLE_ARROW: - glBegin(GL_LINES); + case OB_SINGLE_ARROW: + immBegin(GWN_PRIM_LINES, 2); /* in positive z direction only */ v1[2] = size; - glVertex3fv(v1); - glVertex3fv(v2); - glEnd(); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + immEnd(); /* square pyramid */ - glBegin(GL_TRIANGLES); + immBegin(GWN_PRIM_TRIS, 12); v2[0] = size * 0.035f; v2[1] = size * 0.035f; v3[0] = size * -0.035f; v3[1] = size * 0.035f; @@ -564,28 +584,27 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype) v3[0] = -v3[0]; } - glVertex3fv(v1); - glVertex3fv(v2); - glVertex3fv(v3); - + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + immVertex3fv(pos, v3); } - glEnd(); - + immEnd(); break; + case OB_CUBE: - drawcube_size(size); + drawcube_size(size, pos); break; case OB_CIRCLE: - drawcircle_size(size); + drawcircle_size(size, pos); break; case OB_EMPTY_SPHERE: - draw_empty_sphere(size); + draw_empty_sphere(size, pos); break; case OB_EMPTY_CONE: - draw_empty_cone(size); + draw_empty_cone(size, pos); break; case OB_ARROWS: @@ -599,34 +618,34 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype) for (axis = 0; axis < 3; axis++) { const int arrow_axis = (axis == 0) ? 1 : 0; - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, 6); v2[axis] = size; - glVertex3fv(v1); - glVertex3fv(v2); - + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + v1[axis] = size * 0.85f; v1[arrow_axis] = -size * 0.08f; - glVertex3fv(v1); - glVertex3fv(v2); - + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + v1[arrow_axis] = size * 0.08f; - glVertex3fv(v1); - glVertex3fv(v2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); - glEnd(); - - v2[axis] += size * 0.125f; + immEnd(); - draw_xyz_wire(viewmat_local_unit, v2, size, axis); + v2[axis] += size * 0.125f; + draw_xyz_wire(viewmat_local_unit, v2, size, axis, pos); /* reset v1 & v2 to zero */ v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f; } - break; } } + + immUnbindProgram(); } @@ -634,38 +653,39 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype) static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4], eStereoViews sview) { Image *ima = ob->data; - ImBuf *ibuf; - ImageUser iuser = *ob->iuser; - /* Support multi-view */ - if (ima && (sview == STEREO_RIGHT_ID)) { - iuser.multiview_eye = sview; - iuser.flag |= IMA_SHOW_STEREO; - BKE_image_multiview_index(ima, &iuser); - } + const float ob_alpha = ob->col[3]; + float ima_x, ima_y; - ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); + int bindcode = 0; - if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) { - IMB_rect_from_float(ibuf); - } + if (ima) { + ImageUser iuser = *ob->iuser; + + /* Support multi-view */ + if (ima && (sview == STEREO_RIGHT_ID)) { + iuser.multiview_eye = sview; + iuser.flag |= IMA_SHOW_STEREO; + BKE_image_multiview_index(ima, &iuser); + } - int ima_x, ima_y; + if (ob_alpha > 0.0f) { + bindcode = GPU_verify_image(ima, &iuser, GL_TEXTURE_2D, 0, false, false, false); + /* don't bother drawing the image if alpha = 0 */ + } - /* Get the buffer dimensions so we can fallback to fake ones */ - if (ibuf && ibuf->rect) { - ima_x = ibuf->x; - ima_y = ibuf->y; + int w, h; + BKE_image_get_size(ima, &iuser, &w, &h); + ima_x = w; + ima_y = h; } else { - ima_x = 1; - ima_y = 1; + /* if no image, make it a 1x1 empty square, honor scale & offset */ + ima_x = ima_y = 1.0f; } - float sca_x = 1.0f; - float sca_y = 1.0f; - /* Get the image aspect even if the buffer is invalid */ + float sca_x = 1.0f, sca_y = 1.0f; if (ima) { if (ima->aspx > ima->aspy) { sca_y = ima->aspy / ima->aspx; @@ -675,61 +695,98 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char } } - /* Calculate the scale center based on object's origin */ - float ofs_x = ob->ima_ofs[0] * ima_x; - float ofs_y = ob->ima_ofs[1] * ima_y; + float scale_x; + float scale_y; + { + const float scale_x_inv = ima_x * sca_x; + const float scale_y_inv = ima_y * sca_y; + if (scale_x_inv > scale_y_inv) { + scale_x = ob->empty_drawsize; + scale_y = ob->empty_drawsize * (scale_y_inv / scale_x_inv); + } + else { + scale_x = ob->empty_drawsize * (scale_x_inv / scale_y_inv); + scale_y = ob->empty_drawsize; + } + } - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); + const float ofs_x = ob->ima_ofs[0] * scale_x; + const float ofs_y = ob->ima_ofs[1] * scale_y; - /* Calculate Image scale */ - float scale = ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y); + const rctf rect = { + .xmin = ofs_x, + .xmax = ofs_x + scale_x, + .ymin = ofs_y, + .ymax = ofs_y + scale_y, + }; - /* Set the object scale */ - glScalef(scale * sca_x, scale * sca_y, 1.0f); + bool use_blend = false; - if (ibuf && ibuf->rect) { - const bool use_clip = (U.glalphaclip != 1.0f); - int zoomfilter = (U.gameflags & USER_DISABLE_MIPMAP) ? GL_NEAREST : GL_LINEAR; - /* Setup GL params */ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (bindcode) { + use_blend = ob_alpha < 1.0f || BKE_image_has_alpha(ima); - if (use_clip) { - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, U.glalphaclip); + if (use_blend) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - /* Use the object color and alpha */ - glColor4fv(ob->col); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA); + immUniform1f("alpha", ob_alpha); + immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ - /* Draw the Image on the screen */ - glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_RGBA, GL_UNSIGNED_BYTE, zoomfilter, ibuf->rect); + immBegin(GWN_PRIM_TRI_FAN, 4); + immAttrib2f(texCoord, 0.0f, 0.0f); + immVertex2f(pos, rect.xmin, rect.ymin); - glDisable(GL_BLEND); + immAttrib2f(texCoord, 1.0f, 0.0f); + immVertex2f(pos, rect.xmax, rect.ymin); - if (use_clip) { - glDisable(GL_ALPHA_TEST); - glAlphaFunc(GL_ALWAYS, 0.0f); - } + immAttrib2f(texCoord, 1.0f, 1.0f); + immVertex2f(pos, rect.xmax, rect.ymax); + + immAttrib2f(texCoord, 0.0f, 1.0f); + immVertex2f(pos, rect.xmin, rect.ymax); + immEnd(); + + immUnbindProgram(); + + glBindTexture(GL_TEXTURE_2D, 0); /* necessary? */ } - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(ob_wire_col); + /* Draw the image outline */ + glLineWidth(1.5f); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + const bool picking = dflag & DRAW_CONSTCOLOR; + if (picking) { + /* TODO: deal with picking separately, use this function just to draw */ + immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY); + if (use_blend) { + glDisable(GL_BLEND); + } + + imm_draw_box_wire_2d(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); } + else { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(ob_wire_col); + glEnable(GL_LINE_SMOOTH); - /* Calculate the outline vertex positions */ - glBegin(GL_LINE_LOOP); - glVertex2f(ofs_x, ofs_y); - glVertex2f(ofs_x + ima_x, ofs_y); - glVertex2f(ofs_x + ima_x, ofs_y + ima_y); - glVertex2f(ofs_x, ofs_y + ima_y); - glEnd(); + if (!use_blend) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } - /* Reset GL settings */ - glPopMatrix(); + imm_draw_box_wire_2d(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - BKE_image_release_ibuf(ima, ibuf, NULL); + glDisable(GL_LINE_SMOOTH); + glDisable(GL_BLEND); + } + + immUnbindProgram(); } static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, const float tmat[4][4]) @@ -747,62 +804,65 @@ static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3 } } -void drawcircball(int mode, const float cent[3], float rad, const float tmat[4][4]) +void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos) { float verts[CIRCLE_RESOL][3]; circball_array_fill(verts, cent, rad, tmat); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, verts); - glDrawArrays(mode, 0, CIRCLE_RESOL); - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(GWN_PRIM_LINE_LOOP, CIRCLE_RESOL); + for (int i = 0; i < CIRCLE_RESOL; ++i) { + immVertex3fv(pos, verts[i]); + } + immEnd(); } /* circle for object centers, special_color is for library or ob users */ -static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, bool special_color) +static void drawcentercircle(View3D *v3d, RegionView3D *UNUSED(rv3d), const float co[3], int selstate, bool special_color) { - const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f; - float verts[CIRCLE_RESOL][3]; + const float outlineWidth = 1.0f * U.pixelsize; + const float size = U.obcenter_dia * U.pixelsize + outlineWidth; + + if (v3d->zbuf) { + glDisable(GL_DEPTH_TEST); + /* TODO(merwin): fit things like this into plates/buffers design */ + } - /* using glDepthFunc guarantees that it does write z values, - * but not checks for it, so centers remain visible independent of draw order */ - if (v3d->zbuf) glDepthFunc(GL_ALWAYS); - /* write to near buffer always */ - glDepthRange(0.0, 0.0); glEnable(GL_BLEND); - + GPU_enable_program_point_size(); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); + immUniform1f("size", size); + if (special_color) { - if (selstate == ACTIVE || selstate == SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155); - else glColor4ub(0x55, 0xCC, 0xCC, 155); + if (selstate == ACTIVE || selstate == SELECT) immUniformColor4ub(0x88, 0xFF, 0xFF, 155); + else immUniformColor4ub(0x55, 0xCC, 0xCC, 155); } else { - if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80); - else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80); - else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80); + if (selstate == ACTIVE) immUniformThemeColorShadeAlpha(TH_ACTIVE, 0, -80); + else if (selstate == SELECT) immUniformThemeColorShadeAlpha(TH_SELECT, 0, -80); + else if (selstate == DESELECT) immUniformThemeColorShadeAlpha(TH_TRANSFORM, 0, -80); } - circball_array_fill(verts, co, size, rv3d->viewinv); - - /* enable vertex array */ - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, verts); - - /* 1. draw filled, blended polygon */ - glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL); + /* set up outline */ + float outlineColor[4]; + UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, outlineColor); + immUniform4fv("outlineColor", outlineColor); + immUniform1f("outlineWidth", outlineWidth); - /* 2. draw outline */ - glLineWidth(1); - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30); - glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, co); + immEnd(); - /* finish up */ - glDisableClientState(GL_VERTEX_ARRAY); + immUnbindProgram(); - glDepthRange(0.0, 1.0); + GPU_disable_program_point_size(); glDisable(GL_BLEND); - if (v3d->zbuf) glDepthFunc(GL_LEQUAL); + if (v3d->zbuf) { + glEnable(GL_DEPTH_TEST); + } } /* *********** text drawing for object/particles/armature ************* */ @@ -893,36 +953,30 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write) if (tot) { int col_pack_prev = 0; -#if 0 - bglMats mats; /* ZBuffer depth vars */ - double ux, uy, uz; - float depth; - - if (v3d->zbuf) - bgl_get_mats(&mats); -#endif if (rv3d->rflag & RV3D_CLIPPING) { ED_view3d_clipping_disable(); } - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); + float original_proj[4][4]; + gpuGetProjectionMatrix(original_proj); wmOrtho2_region_pixelspace(ar); - glLoadIdentity(); + + gpuPushMatrix(); + gpuLoadIdentity(); if (depth_write) { if (v3d->zbuf) glDisable(GL_DEPTH_TEST); } else { - glDepthMask(0); + glDepthMask(GL_FALSE); } + const int font_id = BLF_default(); + for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) { if (vos->sco[0] != IS_CLIPPED) { if (col_pack_prev != vos->col.pack) { - glColor3ubv(vos->col.ub); + BLF_color3ubv(font_id, vos->col.ub); col_pack_prev = vos->col.pack; } @@ -941,13 +995,11 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write) if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } else { - glDepthMask(1); + glDepthMask(GL_TRUE); } - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + gpuPopMatrix(); + gpuLoadProjectionMatrix(original_proj); if (rv3d->rflag & RV3D_CLIPPING) { ED_view3d_clipping_enable(); @@ -971,9 +1023,9 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write) /* draws a cube given the scaling of the cube, assuming that * all required matrices have been set (used for drawing empties) */ -static void drawcube_size(float size) +static void drawcube_size(float size, unsigned pos) { - const GLfloat pos[8][3] = { + const float verts[8][3] = { {-size, -size, -size}, {-size, -size, size}, {-size, size, -size}, @@ -986,13 +1038,21 @@ static void drawcube_size(float size) const GLubyte indices[24] = {0,1,1,3,3,2,2,0,0,4,4,5,5,7,7,6,6,4,1,5,3,7,2,6}; +#if 0 glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, pos); + glVertexPointer(3, GL_FLOAT, 0, verts); glDrawRangeElements(GL_LINES, 0, 7, 24, GL_UNSIGNED_BYTE, indices); glDisableClientState(GL_VERTEX_ARRAY); +#else + immBegin(GWN_PRIM_LINES, 24); + for (int i = 0; i < 24; ++i) { + immVertex3fv(pos, verts[indices[i]]); + } + immEnd(); +#endif } -static void drawshadbuflimits(Lamp *la, float mat[4][4]) +static void drawshadbuflimits(const Lamp *la, const float mat[4][4], unsigned pos) { float sta[3], end[3], lavec[3]; @@ -1002,16 +1062,16 @@ static void drawshadbuflimits(Lamp *la, float mat[4][4]) madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta); madd_v3_v3v3fl(end, mat[3], lavec, la->clipend); - glBegin(GL_LINES); - glVertex3fv(sta); - glVertex3fv(end); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, sta); + immVertex3fv(pos, end); + immEnd(); - glPointSize(3.0); - glBegin(GL_POINTS); - glVertex3fv(sta); - glVertex3fv(end); - glEnd(); + glPointSize(3.0f); + immBegin(GWN_PRIM_POINTS, 2); + immVertex3fv(pos, sta); + immVertex3fv(pos, end); + immEnd(); } static void spotvolume(float lvec[3], float vvec[3], const float inp) @@ -1077,62 +1137,63 @@ static void spotvolume(float lvec[3], float vvec[3], const float inp) mul_m3_v3(mat2, vvec); } -static void draw_spot_cone(Lamp *la, float x, float z) +static void draw_spot_cone(Lamp *la, float x, float z, unsigned pos) { z = fabsf(z); - glBegin(GL_TRIANGLE_FAN); - glVertex3f(0.0f, 0.0f, -x); + const bool square = (la->mode & LA_SQUARE); + + immBegin(GWN_PRIM_TRI_FAN, square ? 6 : 34); + immVertex3f(pos, 0.0f, 0.0f, -x); - if (la->mode & LA_SQUARE) { - glVertex3f(z, z, 0); - glVertex3f(-z, z, 0); - glVertex3f(-z, -z, 0); - glVertex3f(z, -z, 0); - glVertex3f(z, z, 0); + if (square) { + immVertex3f(pos, z, z, 0); + immVertex3f(pos, -z, z, 0); + immVertex3f(pos, -z, -z, 0); + immVertex3f(pos, z, -z, 0); + immVertex3f(pos, z, z, 0); } else { for (int a = 0; a < 33; a++) { float angle = a * M_PI * 2 / (33 - 1); - glVertex3f(z * cosf(angle), z * sinf(angle), 0); + immVertex3f(pos, z * cosf(angle), z * sinf(angle), 0.0f); } } - glEnd(); + immEnd(); } -static void draw_transp_spot_volume(Lamp *la, float x, float z) +static void draw_transp_spot_volume(Lamp *la, float x, float z, unsigned pos) { glEnable(GL_CULL_FACE); glEnable(GL_BLEND); - glDepthMask(0); + glDepthMask(GL_FALSE); /* draw backside darkening */ glCullFace(GL_FRONT); glBlendFunc(GL_ZERO, GL_SRC_ALPHA); - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); - draw_spot_cone(la, x, z); + draw_spot_cone(la, x, z, pos); /* draw front side lighting */ glCullFace(GL_BACK); glBlendFunc(GL_ONE, GL_ONE); - glColor4f(0.2f, 0.2f, 0.2f, 1.0f); + immUniformColor3f(0.2f, 0.2f, 0.2f); - draw_spot_cone(la, x, z); + draw_spot_cone(la, x, z, pos); /* restore state */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); - glDepthMask(1); + glDepthMask(GL_TRUE); glDisable(GL_CULL_FACE); - glCullFace(GL_BACK); } #ifdef WITH_GAMEENGINE -static void draw_transp_sun_volume(Lamp *la) +static void draw_transp_sun_volume(Lamp *la, unsigned pos) { float box[8][3]; @@ -1145,50 +1206,46 @@ static void draw_transp_sun_volume(Lamp *la) box[1][2] = box[2][2] = box[5][2] = box[6][2] = -la->clipsta; /* draw edges */ - draw_box(box, false); + imm_draw_box(box, false, pos); /* draw faces */ glEnable(GL_CULL_FACE); glEnable(GL_BLEND); - glDepthMask(0); + glDepthMask(GL_FALSE); /* draw backside darkening */ glCullFace(GL_FRONT); glBlendFunc(GL_ZERO, GL_SRC_ALPHA); - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); - draw_box(box, true); + imm_draw_box(box, true, pos); /* draw front side lighting */ glCullFace(GL_BACK); glBlendFunc(GL_ONE, GL_ONE); - glColor4f(0.2f, 0.2f, 0.2f, 1.0f); + immUniformColor3f(0.2f, 0.2f, 0.2f); - draw_box(box, true); + imm_draw_box(box, true, pos); /* restore state */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); - glDepthMask(1); + glDepthMask(GL_TRUE); glDisable(GL_CULL_FACE); - glCullFace(GL_BACK); } #endif -static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, - const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact) +void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact) { Object *ob = base->object; const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]); Lamp *la = ob->data; float vec[3], lvec[3], vvec[3], circrad; - float lampsize; float imat[4][4]; - unsigned char curcol[4]; - unsigned char col[4]; /* cone can't be drawn for duplicated lamps, because duplilist would be freed */ /* the moment of view3d_draw_transp() call */ const bool is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object); @@ -1196,7 +1253,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, !(G.f & G_PICKSEL) && (la->type == LA_SPOT) && (la->mode & LA_SHOW_CONE) && - !(base->flag & OB_FROMDUPLI) && + !(base->flag_legacy & OB_FROMDUPLI) && !is_view); #ifdef WITH_GAMEENGINE @@ -1208,7 +1265,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, ((la->mode & LA_SHAD_BUF) || (la->mode & LA_SHAD_RAY)) && (la->mode & LA_SHOW_SHADOW_BOX) && - !(base->flag & OB_FROMDUPLI) && + !(base->flag_legacy & OB_FROMDUPLI) && !is_view); #else const bool drawshadowbox = false; @@ -1216,118 +1273,159 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, if ((drawcone || drawshadowbox) && !v3d->transp) { /* in this case we need to draw delayed */ - ED_view3d_after_add(v3d->xray ? &v3d->afterdraw_xraytransp : &v3d->afterdraw_transp, base, dflag); + ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag); return; } - + /* we first draw only the screen aligned & fixed scale stuff */ - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); + gpuPushMatrix(); + gpuLoadMatrix(rv3d->viewmat); /* lets calculate the scale: */ - lampsize = pixsize * ((float)U.obcenter_dia * 0.5f); + const float lampsize_px = U.obcenter_dia; + const float lampsize = pixsize * lampsize_px * 0.5f; /* and view aligned matrix: */ copy_m4_m4(imat, rv3d->viewinv); normalize_v3(imat[0]); normalize_v3(imat[1]); + const unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + /* lamp center */ copy_v3_v3(vec, ob->obmat[3]); + float curcol[4]; if ((dflag & DRAW_CONSTCOLOR) == 0) { /* for AA effects */ - curcol[0] = ob_wire_col[0]; - curcol[1] = ob_wire_col[1]; - curcol[2] = ob_wire_col[2]; - curcol[3] = 154; - glColor4ubv(curcol); + rgb_uchar_to_float(curcol, ob_wire_col); + curcol[3] = 0.6f; + /* TODO: pay attention to GL_BLEND */ } - glLineWidth(1); + glLineWidth(1.0f); + setlinestyle(3); if (lampsize > 0.0f) { + const float outlineWidth = 1.5f * U.pixelsize; + const float lampdot_size = lampsize_px * U.pixelsize + outlineWidth; + /* Inner Circle */ if ((dflag & DRAW_CONSTCOLOR) == 0) { + const float *color = curcol; if (ob->id.us > 1) { - if (is_obact || (ob->flag & SELECT)) { - glColor4ub(0x88, 0xFF, 0xFF, 155); + if (is_obact || ((base->flag & BASE_SELECTED) != 0)) { + static const float active_color[4] = {0.533f, 1.0f, 1.0f, 1.0f}; + color = active_color; } else { - glColor4ub(0x77, 0xCC, 0xCC, 155); + static const float inactive_color[4] = {0.467f, 0.8f, 0.8f, 1.0f}; + color = inactive_color; } } + + GPU_enable_program_point_size(); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); + immUniform1f("size", lampdot_size); + immUniform1f("outlineWidth", outlineWidth); + immUniformColor3fvAlpha(color, 0.3f); + immUniform4fv("outlineColor", color); + + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, vec); + immEnd(); + + immUnbindProgram(); + + glDisable(GL_BLEND); + GPU_disable_program_point_size(); } - - /* Inner Circle */ - glEnable(GL_BLEND); - drawcircball(GL_LINE_LOOP, vec, lampsize, imat); - glDisable(GL_BLEND); - drawcircball(GL_POLYGON, vec, lampsize, imat); - + else { + /* CONSTCOLOR in effect */ + /* TODO: separate picking from drawing */ + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR); + /* color doesn't matter, so don't set */ + glPointSize(lampdot_size); + + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, vec); + immEnd(); + + immUnbindProgram(); + } + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + /* TODO(merwin): short term, use DEPTH_ONLY for picking + * long term, separate picking from drawing + */ + /* restore */ if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (ob->id.us > 1) - glColor4ubv(curcol); + immUniformColor4fv(curcol); } /* Outer circle */ circrad = 3.0f * lampsize; - setlinestyle(3); - drawcircball(GL_LINE_LOOP, vec, circrad, imat); + imm_drawcircball(vec, circrad, imat, pos); /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */ if (la->type != LA_HEMI) { if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) { - drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f * pixsize, imat); + imm_drawcircball(vec, circrad + 3.0f * pixsize, imat, pos); } } } else { - setlinestyle(3); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if ((dflag & DRAW_CONSTCOLOR) == 0) { + immUniformColor4fv(curcol); + } circrad = 0.0f; } - + /* draw the pretty sun rays */ if (la->type == LA_SUN) { float v1[3], v2[3], mat[3][3]; short axis; - + /* setup a 45 degree rotation matrix */ axis_angle_normalized_to_mat3_ex(mat, imat[2], M_SQRT1_2, M_SQRT1_2); /* vectors */ mul_v3_v3fl(v1, imat[0], circrad * 1.2f); mul_v3_v3fl(v2, imat[0], circrad * 2.5f); - + /* center */ - glTranslate3fv(vec); - + gpuPushMatrix(); + gpuTranslate3fv(vec); + setlinestyle(3); - - glBegin(GL_LINES); + + immBegin(GWN_PRIM_LINES, 16); for (axis = 0; axis < 8; axis++) { - glVertex3fv(v1); - glVertex3fv(v2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); mul_m3_v3(mat, v1); mul_m3_v3(mat, v2); } - glEnd(); - - glTranslatef(-vec[0], -vec[1], -vec[2]); + immEnd(); + gpuPopMatrix(); } - + if (la->type == LA_LOCAL) { if (la->mode & LA_SPHERE) { - drawcircball(GL_LINE_LOOP, vec, la->dist, imat); + imm_drawcircball(vec, la->dist, imat, pos); } } - - glPopMatrix(); /* back in object space */ + + gpuPopMatrix(); /* back in object space */ zero_v3(vec); - + if (is_view) { /* skip drawing extra info */ } @@ -1359,24 +1457,18 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, {z_abs, -z_abs, x}, {-z_abs, z_abs, x}, }; - const unsigned char indices[] = { - 0, 1, 3, - 0, 3, 2, - 0, 2, 4, - 0, 1, 4, - }; - /* Draw call: - * activate and specify pointer to vertex array */ - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vertices); - /* draw the pyramid */ - glDrawElements(GL_LINE_STRIP, 12, GL_UNSIGNED_BYTE, indices); - - /* deactivate vertex arrays after drawing */ - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(GWN_PRIM_LINES, 16); + for (int i = 1; i <= 4; ++i) { + immVertex3fv(pos, vertices[0]); /* apex to corner */ + immVertex3fv(pos, vertices[i]); + int next_i = (i == 4) ? 1 : (i + 1); + immVertex3fv(pos, vertices[i]); /* corner to next corner */ + immVertex3fv(pos, vertices[next_i]); + } + immEnd(); - glTranslatef(0.0f, 0.0f, x); + gpuTranslate3f(0.0f, 0.0f, x); /* draw the square representing spotbl */ if (la->type == LA_SPOT) { @@ -1386,22 +1478,21 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, * previously it adjusted to always to show it but that seems * confusing because it doesn't show the actual blend size */ if (blend != 0.0f && blend != z_abs) { - fdrawbox(blend, -blend, -blend, blend); + imm_draw_box_wire_3d(pos, blend, -blend, -blend, blend); } } } else { - /* draw the angled sides of the cone */ - glBegin(GL_LINE_STRIP); - glVertex3fv(vvec); - glVertex3fv(vec); - glVertex3fv(lvec); - glEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex3fv(pos, vvec); + immVertex3fv(pos, vec); + immVertex3fv(pos, lvec); + immEnd(); /* draw the circle at the end of the cone */ - glTranslatef(0.0f, 0.0f, x); - circ(0.0f, 0.0f, z_abs); + gpuTranslate3f(0.0f, 0.0f, x); + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, z_abs, 32); /* draw the circle representing spotbl */ if (la->type == LA_SPOT) { @@ -1411,17 +1502,17 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, * previously it adjusted to always to show it but that seems * confusing because it doesn't show the actual blend size */ if (blend != 0.0f && blend != z_abs) { - circ(0.0f, 0.0f, blend); + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, blend, 32); } } } if (drawcone) - draw_transp_spot_volume(la, x, z); + draw_transp_spot_volume(la, x, z, pos); /* draw clip start, useful for wide cones where its not obvious where the start is */ - glTranslatef(0.0, 0.0, -x); /* reverse translation above */ - glBegin(GL_LINES); + gpuTranslate3f(0.0f, 0.0f, -x); /* reverse translation above */ + immBegin(GWN_PRIM_LINES, 2); if (la->type == LA_SPOT && (la->mode & LA_SHAD_BUF)) { float lvec_clip[3]; float vvec_clip[3]; @@ -1430,41 +1521,40 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac); interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac); - glVertex3fv(lvec_clip); - glVertex3fv(vvec_clip); + immVertex3fv(pos, lvec_clip); + immVertex3fv(pos, vvec_clip); } /* Else, draw spot direction (using distance as end limit, same as for Area lamp). */ else { - glVertex3f(0.0, 0.0, -circrad); - glVertex3f(0.0, 0.0, -la->dist); + immVertex3f(pos, 0.0f, 0.0f, -circrad); + immVertex3f(pos, 0.0f, 0.0f, -la->dist); } - glEnd(); + immEnd(); } else if (ELEM(la->type, LA_HEMI, LA_SUN)) { - /* draw the line from the circle along the dist */ - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, 2); vec[2] = -circrad; - glVertex3fv(vec); + immVertex3fv(pos, vec); vec[2] = -la->dist; - glVertex3fv(vec); - glEnd(); - + immVertex3fv(pos, vec); + immEnd(); + if (la->type == LA_HEMI) { /* draw the hemisphere curves */ short axis, steps, dir; float outdist, zdist, mul; zero_v3(vec); - outdist = 0.14; mul = 1.4; dir = 1; - + outdist = 0.14f; mul = 1.4f; dir = 1; + setlinestyle(4); /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */ for (axis = 0; axis < 4; axis++) { - float v[3] = {0.0, 0.0, 0.0}; - zdist = 0.02; - - glBegin(GL_LINE_STRIP); - + float v[3] = {0.0f, 0.0f, 0.0f}; + zdist = 0.02f; + + immBegin(GWN_PRIM_LINE_STRIP, 6); + for (steps = 0; steps < 6; steps++) { if (axis == 0 || axis == 1) { /* x axis up, x axis down */ /* make the arcs start at the edge of the energy circle */ @@ -1477,13 +1567,13 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, } v[2] = v[2] - steps * zdist; - - glVertex3fv(v); - + + immVertex3fv(pos, v); + zdist = zdist * mul; } - - glEnd(); + + immEnd(); /* flip the direction */ dir = -dir; } @@ -1491,96 +1581,92 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, #ifdef WITH_GAMEENGINE if (drawshadowbox) { - draw_transp_sun_volume(la); + draw_transp_sun_volume(la, pos); } #endif - } else if (la->type == LA_AREA) { setlinestyle(3); if (la->area_shape == LA_AREA_SQUARE) - fdrawbox(-la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f); + imm_draw_box_wire_3d(pos, -la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f); else if (la->area_shape == LA_AREA_RECT) - fdrawbox(-la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f); + imm_draw_box_wire_3d(pos, -la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f); - glBegin(GL_LINES); - glVertex3f(0.0, 0.0, -circrad); - glVertex3f(0.0, 0.0, -la->dist); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 0.0f, -circrad); + immVertex3f(pos, 0.0f, 0.0f, -la->dist); + immEnd(); } - + /* and back to viewspace */ - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); + gpuPushMatrix(); + gpuLoadMatrix(rv3d->viewmat); copy_v3_v3(vec, ob->obmat[3]); setlinestyle(0); - + if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == false)) { - drawshadbuflimits(la, ob->obmat); + drawshadbuflimits(la, ob->obmat, pos); } - + if ((dflag & DRAW_CONSTCOLOR) == 0) { - UI_GetThemeColor4ubv(TH_LAMP, col); - glColor4ubv(col); + immUniformThemeColor(TH_LAMP); } glEnable(GL_BLEND); - + if (vec[2] > 0) vec[2] -= circrad; else vec[2] += circrad; - - glBegin(GL_LINES); - glVertex3fv(vec); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, vec); vec[2] = 0; - glVertex3fv(vec); - glEnd(); - - glPointSize(2.0); - glBegin(GL_POINTS); - glVertex3fv(vec); - glEnd(); - + immVertex3fv(pos, vec); + immEnd(); + + glPointSize(2.0f); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, vec); + immEnd(); + glDisable(GL_BLEND); - - if ((dflag & DRAW_CONSTCOLOR) == 0) { - /* restore for drawing extra stuff */ - glColor3ubv(ob_wire_col); - } - /* and finally back to org object space! */ - glPopMatrix(); + + immUnbindProgram(); + gpuPopMatrix(); } -static void draw_limit_line(float sta, float end, const short dflag, const unsigned char col[3]) +static void draw_limit_line(float sta, float end, const short dflag, const unsigned char col[3], unsigned pos) { - glBegin(GL_LINES); - glVertex3f(0.0, 0.0, -sta); - glVertex3f(0.0, 0.0, -end); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 0.0f, -sta); + immVertex3f(pos, 0.0f, 0.0f, -end); + immEnd(); if (!(dflag & DRAW_PICKING)) { - glPointSize(3.0); - glBegin(GL_POINTS); + glPointSize(3.0f); + /* would like smooth round points here, but that means binding another shader... + * if it's really desired, pull these points into their own function to be called after */ + immBegin(GWN_PRIM_POINTS, 2); if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(col); + immUniformColor3ubv(col); } - glVertex3f(0.0, 0.0, -sta); - glVertex3f(0.0, 0.0, -end); - glEnd(); + immVertex3f(pos, 0.0f, 0.0f, -sta); + immVertex3f(pos, 0.0f, 0.0f, -end); + immEnd(); } } /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */ /* qdn: now also enabled for Blender to set focus point for defocus composite node */ -static void draw_focus_cross(float dist, float size) +static void draw_focus_cross(float dist, float size, unsigned pos) { - glBegin(GL_LINES); - glVertex3f(-size, 0.0f, -dist); - glVertex3f(size, 0.0f, -dist); - glVertex3f(0.0f, -size, -dist); - glVertex3f(0.0f, size, -dist); - glEnd(); + immBegin(GWN_PRIM_LINES, 4); + immVertex3f(pos, -size, 0.0f, -dist); + immVertex3f(pos, size, 0.0f, -dist); + immVertex3f(pos, 0.0f, -size, -dist); + immVertex3f(pos, 0.0f, size, -dist); + immEnd(); } #ifdef VIEW3D_CAMERA_BORDER_HACK @@ -1590,26 +1676,6 @@ bool view3d_camera_border_hack_test = false; /* ****************** draw clip data *************** */ -static void draw_bundle_sphere(void) -{ - static GLuint displist = 0; - - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_FILL); - gluSphere(qobj, 0.05, 8, 8); - gluDeleteQuadric(qobj); - - glEndList(); - } - - glCallList(displist); -} - static void draw_viewport_object_reconstruction( Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip, MovieTrackingObject *tracking_object, @@ -1635,7 +1701,7 @@ static void draw_viewport_object_reconstruction( if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) mul_v3_fl(camera_size, tracking_object->scale); - glPushMatrix(); + gpuPushMatrix(); if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { /* current ogl matrix is translated in camera space, bundles should @@ -1643,8 +1709,8 @@ static void draw_viewport_object_reconstruction( * from current ogl matrix */ invert_m4_m4(imat, base->object->obmat); - glMultMatrixf(imat); - glMultMatrixf(mat); + gpuMultMatrix(imat); + gpuMultMatrix(mat); } else { float obmat[4][4]; @@ -1653,7 +1719,7 @@ static void draw_viewport_object_reconstruction( BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, obmat); invert_m4_m4(imat, obmat); - glMultMatrixf(imat); + gpuMultMatrix(imat); } for (track = tracksbase->first; track; track = track->next) { @@ -1666,66 +1732,93 @@ static void draw_viewport_object_reconstruction( continue; if (dflag & DRAW_PICKING) - GPU_select_load_id(base->selcol + (tracknr << 16)); + GPU_select_load_id(base->object->select_color + (tracknr << 16)); - glPushMatrix(); - glTranslate3fv(track->bundle_pos); - glScalef(v3d->bundle_size / 0.05f / camera_size[0], - v3d->bundle_size / 0.05f / camera_size[1], - v3d->bundle_size / 0.05f / camera_size[2]); + gpuPushMatrix(); + gpuTranslate3fv(track->bundle_pos); + gpuScale3f(v3d->bundle_size / 0.05f / camera_size[0], + v3d->bundle_size / 0.05f / camera_size[1], + v3d->bundle_size / 0.05f / camera_size[2]); const int v3d_drawtype = view3d_effective_drawtype(v3d); if (v3d_drawtype == OB_WIRE) { + unsigned char color[4]; + const unsigned char *color_ptr = NULL; if ((dflag & DRAW_CONSTCOLOR) == 0) { if (selected && (track->flag & TRACK_CUSTOMCOLOR) == 0) { - glColor3ubv(ob_wire_col); + color_ptr = ob_wire_col; } else { - glColor3fv(track->color); + rgba_float_to_uchar(color, track->color); + color_ptr = color; } } - drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype); + drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype, color_ptr); } else if (v3d_drawtype > OB_WIRE) { if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) { + Gwn_Batch *batch; + + gpuScaleUniform(0.05f); + /* selection outline */ if (selected) { + batch = GPU_batch_preset_sphere_wire(1); + if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(ob_wire_col); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + GWN_batch_uniform_4f(batch, "color", + ob_wire_col[0] / 255.f, + ob_wire_col[1] / 255.f, + ob_wire_col[2] / 255.f, 1.0f); + } + else { + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_DEPTH_ONLY); } - glLineWidth(2.0f); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - draw_bundle_sphere(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + GWN_batch_draw(batch); } + batch = GPU_batch_preset_sphere(0); + if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color); - else UI_ThemeColor(TH_BUNDLE_SOLID); + const float light[3] = {0.0f, 0.0f, 1.0f}; + float col[3]; + GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_3fv(batch, "light", light); + + if (track->flag & TRACK_CUSTOMCOLOR) copy_v3_v3(col, track->color); + else UI_GetThemeColor3fv(TH_BUNDLE_SOLID, col); + GWN_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f); + } + else { + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_DEPTH_ONLY); } - draw_bundle_sphere(); + GWN_batch_draw(batch); } else { + unsigned char color[4]; + const unsigned char *color_ptr = NULL; if ((dflag & DRAW_CONSTCOLOR) == 0) { if (selected) { - glColor3ubv(ob_wire_col); + color_ptr = ob_wire_col; } else { - if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color); - else UI_ThemeColor(TH_WIRE); + if (track->flag & TRACK_CUSTOMCOLOR) rgba_float_to_uchar(color, track->color); + else UI_GetThemeColor4ubv(TH_WIRE, color); + + color_ptr = color; } } - drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype); + drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype, color_ptr); } } - glPopMatrix(); + gpuPopMatrix(); if ((dflag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) { float pos[3]; @@ -1745,22 +1838,27 @@ static void draw_viewport_object_reconstruction( MovieTrackingReconstruction *reconstruction; reconstruction = BKE_tracking_object_get_reconstruction(tracking, tracking_object); - if (reconstruction->camnr) { + if (reconstruction->camnr >= 2) { MovieReconstructedCamera *camera = reconstruction->cameras; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_CAMERA_PATH); - UI_ThemeColor(TH_CAMERA_PATH); glLineWidth(2.0f); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, reconstruction->camnr); for (int a = 0; a < reconstruction->camnr; a++, camera++) { - glVertex3fv(camera->mat[3]); + immVertex3fv(pos, camera->mat[3]); } - glEnd(); + immEnd(); + + immUnbindProgram(); } } } - glPopMatrix(); + gpuPopMatrix(); *global_track_index = tracknr; } @@ -1795,67 +1893,65 @@ static void draw_viewport_reconstruction( /* restore */ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(ob_wire_col); - } - if (dflag & DRAW_PICKING) - GPU_select_load_id(base->selcol); + GPU_select_load_id(base->object->select_color); } -static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], const GLenum mode) +/* camera frame */ +static void drawcamera_frame(float vec[4][3], bool filled, unsigned pos) { - glBegin(mode); - glVertex3fv(near_plane[0]); - glVertex3fv(far_plane[0]); - glVertex3fv(far_plane[1]); - glVertex3fv(near_plane[1]); - glEnd(); - - glBegin(mode); - glVertex3fv(near_plane[1]); - glVertex3fv(far_plane[1]); - glVertex3fv(far_plane[2]); - glVertex3fv(near_plane[2]); - glEnd(); - - glBegin(mode); - glVertex3fv(near_plane[2]); - glVertex3fv(far_plane[2]); - glVertex3fv(far_plane[3]); - glVertex3fv(near_plane[3]); - glEnd(); - - glBegin(mode); - glVertex3fv(far_plane[3]); - glVertex3fv(near_plane[3]); - glVertex3fv(near_plane[0]); - glVertex3fv(far_plane[0]); - glEnd(); + immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, 4); + immVertex3fv(pos, vec[0]); + immVertex3fv(pos, vec[1]); + immVertex3fv(pos, vec[2]); + immVertex3fv(pos, vec[3]); + immEnd(); } -/* camera frame */ -static void drawcamera_frame(float vec[4][3], const GLenum mode) +/* center point to camera frame */ +static void drawcamera_framelines(float vec[4][3], float origin[3], unsigned pos) { - glBegin(mode); - glVertex3fv(vec[0]); - glVertex3fv(vec[1]); - glVertex3fv(vec[2]); - glVertex3fv(vec[3]); - glEnd(); + immBegin(GWN_PRIM_LINES, 8); + immVertex3fv(pos, origin); + immVertex3fv(pos, vec[0]); + immVertex3fv(pos, origin); + immVertex3fv(pos, vec[1]); + immVertex3fv(pos, origin); + immVertex3fv(pos, vec[2]); + immVertex3fv(pos, origin); + immVertex3fv(pos, vec[3]); + immEnd(); } -/* center point to camera frame */ -static void drawcamera_framelines(float vec[4][3], float origin[3]) +static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], bool filled, unsigned pos) { - glBegin(GL_LINE_STRIP); - glVertex3fv(vec[1]); - glVertex3fv(origin); - glVertex3fv(vec[0]); - glVertex3fv(vec[3]); - glVertex3fv(origin); - glVertex3fv(vec[2]); - glEnd(); + drawcamera_frame(near_plane, filled, pos); + drawcamera_frame(far_plane, filled, pos); + + if (filled) { + immBegin(GWN_PRIM_TRI_STRIP, 10); + + immVertex3fv(pos, near_plane[0]); + immVertex3fv(pos, far_plane[0]); + immVertex3fv(pos, near_plane[1]); + immVertex3fv(pos, far_plane[1]); + immVertex3fv(pos, near_plane[2]); + immVertex3fv(pos, far_plane[2]); + immVertex3fv(pos, near_plane[3]); + immVertex3fv(pos, far_plane[3]); + immVertex3fv(pos, near_plane[0]); + immVertex3fv(pos, far_plane[0]); + + immEnd(); + } + else { + immBegin(GWN_PRIM_LINES, 8); + for (int i = 0; i < 4; ++i) { + immVertex3fv(pos, near_plane[i]); + immVertex3fv(pos, far_plane[i]); + } + immEnd(); + } } static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob) @@ -1867,7 +1963,7 @@ static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob) static void drawcamera_stereo3d( Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const Camera *cam, - float vec[4][3], float drawsize, const float scale[3]) + float vec[4][3], float drawsize, const float scale[3], unsigned pos) { float obmat[4][4]; float vec_lr[2][4][3]; @@ -1883,15 +1979,15 @@ static void drawcamera_stereo3d( zero_v3(tvec); - glPushMatrix(); + /* caller bound GPU_SHADER_3D_UNIFORM_COLOR, passed in pos attribute ID */ for (int i = 0; i < 2; i++) { ob = BKE_camera_multiview_render(scene, ob, names[i]); cam_lr[i] = ob->data; - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); BKE_camera_multiview_model_matrix(&scene->r, ob, names[i], obmat); - glMultMatrixf(obmat); + gpuMultMatrix(obmat); copy_m3_m3(vec_lr[i], vec); copy_v3_v3(vec_lr[i][3], vec[3]); @@ -1908,10 +2004,10 @@ static void drawcamera_stereo3d( if (is_stereo3d_cameras) { /* camera frame */ - drawcamera_frame(vec_lr[i], GL_LINE_LOOP); + drawcamera_frame(vec_lr[i], false, pos); /* center point to camera frame */ - drawcamera_framelines(vec_lr[i], tvec); + drawcamera_framelines(vec_lr[i], tvec, pos); } /* connecting line */ @@ -1925,21 +2021,20 @@ static void drawcamera_stereo3d( } } - /* the remaining drawing takes place in the view space */ - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); if (is_stereo3d_cameras) { /* draw connecting lines */ - GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); - GPU_basic_shader_line_stipple(2, 0xAAAA); + glLineStipple(2, 0xAAAA); + glEnable(GL_LINE_STIPPLE); - glBegin(GL_LINES); - glVertex3fv(origin[0]); - glVertex3fv(origin[1]); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, origin[0]); + immVertex3fv(pos, origin[1]); + immEnd(); - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); + glDisable(GL_LINE_STIPPLE); } /* draw convergence plane */ @@ -1964,21 +2059,21 @@ static void drawcamera_stereo3d( add_v3_v3(local_plane[i], axis_center); } - glColor3f(0.0f, 0.0f, 0.0f); + immUniformColor3f(0.0f, 0.0f, 0.0f); /* camera frame */ - drawcamera_frame(local_plane, GL_LINE_LOOP); + drawcamera_frame(local_plane, false, pos); if (v3d->stereo3d_convergence_alpha > 0.0f) { glEnable(GL_BLEND); - glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */ - glColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha); + immUniformColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha); - drawcamera_frame(local_plane, GL_QUADS); + drawcamera_frame(local_plane, true, pos); glDisable(GL_BLEND); - glDepthMask(1); /* restore write in zbuffer */ + glDepthMask(GL_TRUE); /* restore write in zbuffer */ } } @@ -2003,37 +2098,31 @@ static void drawcamera_stereo3d( } /* camera frame */ - glColor3f(0.0f, 0.0f, 0.0f); + immUniformColor3f(0.0f, 0.0f, 0.0f); - drawcamera_frame(near_plane, GL_LINE_LOOP); - drawcamera_frame(far_plane, GL_LINE_LOOP); - drawcamera_volume(near_plane, far_plane, GL_LINE_LOOP); + drawcamera_volume(near_plane, far_plane, false, pos); if (v3d->stereo3d_volume_alpha > 0.0f) { glEnable(GL_BLEND); - glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */ if (i == 0) - glColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha); + immUniformColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha); else - glColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha); + immUniformColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha); - drawcamera_frame(near_plane, GL_QUADS); - drawcamera_frame(far_plane, GL_QUADS); - drawcamera_volume(near_plane, far_plane, GL_QUADS); + drawcamera_volume(near_plane, far_plane, true, pos); glDisable(GL_BLEND); - glDepthMask(1); /* restore write in zbuffer */ + glDepthMask(GL_TRUE); /* restore write in zbuffer */ } } } - - glPopMatrix(); } /* flag similar to draw_object() */ -static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dflag, const unsigned char ob_wire_col[4]) +void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, + const short dflag, const unsigned char ob_wire_col[4]) { /* a standing up pyramid with (0,0,0) as top */ Camera *cam; @@ -2096,8 +2185,12 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale, asp, shift, &drawsize, vec); - glDisable(GL_CULL_FACE); - glLineWidth(1); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) { + immUniformColor3ubv(ob_wire_col); + } + glLineWidth(1.0f); /* camera frame */ if (!is_stereo3d_cameras) { @@ -2106,27 +2199,29 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base float obmat[4][4]; bool is_left = v3d->multiview_eye == STEREO_LEFT_ID; - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); + gpuPushMatrix(); + gpuLoadMatrix(rv3d->viewmat); BKE_camera_multiview_model_matrix(&scene->r, ob, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, obmat); - glMultMatrixf(obmat); + gpuMultMatrix(obmat); - drawcamera_frame(vec, GL_LINE_LOOP); - glPopMatrix(); + drawcamera_frame(vec, false, pos); + gpuPopMatrix(); } else { - drawcamera_frame(vec, GL_LINE_LOOP); + drawcamera_frame(vec, false, pos); } } - if (is_view) + if (is_view) { + immUnbindProgram(); return; + } zero_v3(tvec); /* center point to camera frame */ if (!is_stereo3d_cameras) - drawcamera_framelines(vec, tvec); + drawcamera_framelines(vec, tvec, pos); /* arrow on top */ tvec[2] = vec[1][2]; /* copy the depth */ @@ -2135,22 +2230,25 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base * for active cameras. We actually draw both outline+filled * for active cameras so the wire can be seen side-on */ for (int i = 0; i < 2; i++) { - if (i == 0) glBegin(GL_LINE_LOOP); - else if (i == 1 && is_active) glBegin(GL_TRIANGLES); + if (i == 0) immBegin(GWN_PRIM_LINE_LOOP, 3); + else if (i == 1 && is_active) { + glDisable(GL_CULL_FACE); /* TODO: declarative state tracking */ + immBegin(GWN_PRIM_TRIS, 3); + } else break; tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]); tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]); - glVertex3fv(tvec); /* left */ + immVertex3fv(pos, tvec); /* left */ tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]); - glVertex3fv(tvec); /* right */ + immVertex3fv(pos, tvec); /* right */ tvec[0] = shift[0]; tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]); - glVertex3fv(tvec); /* top */ + immVertex3fv(pos, tvec); /* top */ - glEnd(); + immEnd(); } if ((dflag & DRAW_SCENESET) == 0) { @@ -2161,16 +2259,15 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base copy_m4_m4(nobmat, ob->obmat); normalize_m4(nobmat); - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); - glMultMatrixf(nobmat); + gpuLoadMatrix(rv3d->viewmat); + gpuMultMatrix(nobmat); if (cam->flag & CAM_SHOWLIMITS) { const unsigned char col[3] = {128, 128, 60}, col_hi[3] = {255, 255, 120}; - draw_limit_line(cam->clipsta, cam->clipend, dflag, (is_active ? col_hi : col)); + draw_limit_line(cam->clipsta, cam->clipend, dflag, (is_active ? col_hi : col), pos); /* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */ - draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize); + draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize, pos); } if (cam->flag & CAM_SHOWMIST) { @@ -2179,69 +2276,79 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base if (world) { draw_limit_line(world->miststa, world->miststa + world->mistdist, - dflag, (is_active ? col_hi : col)); + dflag, (is_active ? col_hi : col), pos); } } - glPopMatrix(); } } /* stereo cameras drawing */ if (is_stereo3d) { - drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale); + drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale, pos); } + + immUnbindProgram(); } /* flag similar to draw_object() */ -static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d), - Object *UNUSED(ob), int UNUSED(flag)) +void drawspeaker(const unsigned char ob_wire_col[3]) { - float vec[3]; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); - glEnable(GL_BLEND); - glLineWidth(1); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + if (ob_wire_col) { + immUniformColor3ubv(ob_wire_col); + } + + glLineWidth(1.0f); + + const int segments = 16; for (int j = 0; j < 3; j++) { - vec[2] = 0.25f * j - 0.125f; + float z = 0.25f * j - 0.125f; - glBegin(GL_LINE_LOOP); - for (int i = 0; i < 16; i++) { - vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f); - vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f); - glVertex3fv(vec); + immBegin(GWN_PRIM_LINE_LOOP, segments); + for (int i = 0; i < segments; i++) { + float x = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f); + float y = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f); + immVertex3f(pos, x, y, z); } - glEnd(); + immEnd(); } for (int j = 0; j < 4; j++) { - vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f; - vec[1] = ((j % 2) * (j - 2)) * 0.5f; - glBegin(GL_LINE_STRIP); + float x = (((j + 1) % 2) * (j - 1)) * 0.5f; + float y = ((j % 2) * (j - 2)) * 0.5f; + immBegin(GWN_PRIM_LINE_STRIP, 3); for (int i = 0; i < 3; i++) { if (i == 1) { - vec[0] *= 0.5f; - vec[1] *= 0.5f; + x *= 0.5f; + y *= 0.5f; } - vec[2] = 0.25f * i - 0.125f; - glVertex3fv(vec); + float z = 0.25f * i - 0.125f; + immVertex3f(pos, x, y, z); } - glEnd(); + immEnd(); } - glDisable(GL_BLEND); + immUnbindProgram(); } -static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel) +static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel, + unsigned int pos, unsigned int color) { BPoint *bp = lt->def; const float *co = dl ? dl->verts : NULL; + float active_color[4], draw_color[4]; - const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX; - UI_ThemeColor(color); + UI_GetThemeColor4fv(sel ? TH_VERTEX_SELECT : TH_VERTEX, draw_color); + UI_GetThemeColor4fv(TH_ACTIVE_VERT, active_color); glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - glBegin(GL_POINTS); + immBeginAtMost(GWN_PRIM_POINTS, lt->pntsw * lt->pntsv * lt->pntsu); for (int w = 0; w < lt->pntsw; w++) { int wxt = (w == 0 || w == lt->pntsw - 1); @@ -2253,12 +2360,12 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short s if (bp->hide == 0) { /* check for active BPoint and ensure selected */ if ((bp == actbp) && (bp->f1 & SELECT)) { - UI_ThemeColor(TH_ACTIVE_VERT); - glVertex3fv(dl ? co : bp->vec); - UI_ThemeColor(color); + immAttrib4fv(color, active_color); + immVertex3fv(pos, dl ? co : bp->vec); } else if ((bp->f1 & SELECT) == sel) { - glVertex3fv(dl ? co : bp->vec); + immAttrib4fv(color, draw_color); + immVertex3fv(pos, dl ? co : bp->vec); } } } @@ -2266,32 +2373,32 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short s } } - glEnd(); + immEnd(); } -static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol) +static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol, + unsigned int pos, unsigned int color) { int index = ((w * lt->pntsv + v) * lt->pntsu) + u; if (actdef_wcol) { float col[3]; MDeformWeight *mdw = defvert_find_index(lt->dvert + index, actdef_wcol - 1); - weight_to_rgb(col, mdw ? mdw->weight : 0.0f); - glColor3fv(col); - + immAttrib3fv(color, col); } if (dl) { - glVertex3fv(&dl->verts[index * 3]); + immVertex3fv(pos, &dl->verts[index * 3]); } else { - glVertex3fv(lt->def[index].vec); + immVertex3fv(pos, lt->def[index].vec); } } #ifdef SEQUENCER_DAG_WORKAROUND -static void ensure_curve_cache(Scene *scene, Object *object) +static void ensure_curve_cache( + const EvaluationContext *eval_ctx, Scene *scene, Object *object) { bool need_recalc = object->curve_cache == NULL; /* Render thread might have freed the curve cache if the @@ -2320,13 +2427,13 @@ static void ensure_curve_cache(Scene *scene, Object *object) case OB_CURVE: case OB_SURF: case OB_FONT: - BKE_displist_make_curveTypes(scene, object, false); + BKE_displist_make_curveTypes(eval_ctx, scene, object, false); break; case OB_MBALL: - BKE_displist_make_mball(G.main->eval_ctx, scene, object); + BKE_displist_make_mball(eval_ctx, scene, object); break; case OB_LATTICE: - BKE_lattice_modifiers_calc(scene, object); + BKE_lattice_modifiers_calc(eval_ctx, scene, object); break; } } @@ -2334,7 +2441,7 @@ static void ensure_curve_cache(Scene *scene, Object *object) #endif /* lattice color is hardcoded, now also shows weightgroup values in edit mode */ -static void drawlattice(View3D *v3d, Object *ob) +static void drawlattice(View3D *v3d, Object *ob, const short dflag, const unsigned char ob_wire_col[4]) { Lattice *lt = ob->data; DispList *dl; @@ -2347,15 +2454,37 @@ static void drawlattice(View3D *v3d, Object *ob) if (is_edit) { lt = lt->editlatt->latt; - UI_ThemeColor(TH_WIRE_EDIT); - if (ob->defbase.first && lt->dvert) { actdef_wcol = ob->actdef; } } - glLineWidth(1); - glBegin(GL_LINES); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int color, pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + if (actdef_wcol) { + color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); + } + else { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + if (is_edit) { + immUniformThemeColor(TH_WIRE_EDIT); + } + else { + if ((dflag & DRAW_CONSTCOLOR) == 0) { + immUniformColor3ubv(ob_wire_col); + } + else { + immUniformColor3f(0.0f, 0.0f, 0.0f); + } + } + } + + glLineWidth(1.0f); + immBeginAtMost(GWN_PRIM_LINES, lt->pntsw * lt->pntsv * lt->pntsu * 6); + for (w = 0; w < lt->pntsw; w++) { int wxt = (w == 0 || w == lt->pntsw - 1); for (v = 0; v < lt->pntsv; v++) { @@ -2364,30 +2493,40 @@ static void drawlattice(View3D *v3d, Object *ob) int uxt = (u == 0 || u == lt->pntsu - 1); if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) { - drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol); - drawlattice__point(lt, dl, u, v, w, actdef_wcol); + drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol, pos, color); + drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color); } if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) { - drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol); - drawlattice__point(lt, dl, u, v, w, actdef_wcol); + drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol, pos, color); + drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color); } if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) { - drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol); - drawlattice__point(lt, dl, u, v, w, actdef_wcol); + drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol, pos, color); + drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color); } } } } - glEnd(); + + immEnd(); + immUnbindProgram(); if (is_edit) { BPoint *actbp = BKE_lattice_active_point_get(lt); if (v3d->zbuf) glDisable(GL_DEPTH_TEST); - - lattice_draw_verts(lt, dl, actbp, 0); - lattice_draw_verts(lt, dl, actbp, 1); - + + Gwn_VertFormat *v_format = immVertexFormat(); + unsigned int v_pos = GWN_vertformat_attr_add(v_format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int v_color = GWN_vertformat_attr_add(v_format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); + + lattice_draw_verts(lt, dl, actbp, 0, v_pos, v_color); + lattice_draw_verts(lt, dl, actbp, 1, v_pos, v_color); + + immUnbindProgram(); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } } @@ -2401,6 +2540,7 @@ typedef struct drawDMVertSel_userData { int active; unsigned char *col[3]; /* (base, sel, act) */ char sel_prev; + unsigned int pos, color; } drawDMVertSel_userData; static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3], @@ -2412,17 +2552,18 @@ static void drawSelectedVertices__mapFunc(void *userData, int index, const float if (!(mv->flag & ME_HIDE)) { const char sel = (index == data->active) ? 2 : (mv->flag & SELECT); if (sel != data->sel_prev) { - glColor3ubv(data->col[sel]); + immAttrib3ubv(data->color, data->col[sel]); data->sel_prev = sel; } - glVertex3fv(co); + immVertex3fv(data->pos, co); } } static void drawSelectedVertices(DerivedMesh *dm, Mesh *me) { drawDMVertSel_userData data; + Gwn_VertFormat *format = immVertexFormat(); /* TODO define selected color */ unsigned char base_col[3] = {0x0, 0x0, 0x0}; @@ -2437,9 +2578,18 @@ static void drawSelectedVertices(DerivedMesh *dm, Mesh *me) data.col[1] = sel_col; data.col[2] = act_col; - glBegin(GL_POINTS); + data.color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + if (dm->getNumVerts(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + immBeginAtMost(GWN_PRIM_POINTS, dm->getNumVerts(dm)); dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } /* ************** DRAW MESH ****************** */ @@ -2486,25 +2636,34 @@ static void draw_dm_face_normals__mapFunc(void *userData, int index, const float copy_v3_v3(n, no); } - glVertex3fv(cent); - glVertex3f(cent[0] + n[0] * data->normalsize, - cent[1] + n[1] * data->normalsize, - cent[2] + n[2] * data->normalsize); + immVertex3fv(data->pos, cent); + immVertex3f(data->pos, cent[0] + n[0] * data->normalsize, + cent[1] + n[1] * data->normalsize, + cent[2] + n[2] * data->normalsize); } } -static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm) +static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id) { + Gwn_VertFormat *format = immVertexFormat(); drawDMNormal_userData data; data.bm = em->bm; data.normalsize = scene->toolsettings->normalsize; + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); calcDrawDMNormalScale(ob, &data); - glBegin(GL_LINES); + if (dm->getNumPolys(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(theme_id); + + immBeginAtMost(GWN_PRIM_LINES, dm->getNumPolys(dm) * 2); dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL); - glEnd(); + immEnd(); + + immUnbindProgram(); } static void draw_dm_face_centers__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3])) @@ -2515,16 +2674,28 @@ static void draw_dm_face_centers__mapFunc(void *userData, int index, const float if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && (BM_elem_flag_test(efa, BM_ELEM_SELECT) == data->select)) { - glVertex3fv(cent); + immVertex3fv(data->pos, cent); } } -static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, bool select) +static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, bool select, const unsigned char fcol[3]) { - drawBMSelect_userData data = {em->bm, select}; + Gwn_VertFormat *format = immVertexFormat(); + + drawBMSelect_userData data; + data.bm = em->bm; + data.select = select; + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + if (dm->getNumPolys(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(fcol); - glBegin(GL_POINTS); + immBeginAtMost(GWN_PRIM_POINTS, dm->getNumPolys(dm)); dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]) @@ -2551,71 +2722,83 @@ static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float copy_v3_v3(n, no); } - glVertex3fv(co); - glVertex3f(co[0] + n[0] * data->normalsize, - co[1] + n[1] * data->normalsize, - co[2] + n[2] * data->normalsize); + immVertex3fv(data->pos, co); + immVertex3f(data->pos, co[0] + n[0] * data->normalsize, + co[1] + n[1] * data->normalsize, + co[2] + n[2] * data->normalsize); } } -static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm) +static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id) { drawDMNormal_userData data; + Gwn_VertFormat *format = immVertexFormat(); data.bm = em->bm; data.normalsize = scene->toolsettings->normalsize; + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); calcDrawDMNormalScale(ob, &data); - glBegin(GL_LINES); + if (dm->getNumVerts(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(theme_id); + + immBeginAtMost(GWN_PRIM_LINES, dm->getNumVerts(dm) * 2); dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL); - glEnd(); + immEnd(); + + immUnbindProgram(); } -/* Draw verts with color set based on selection */ -static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3], - const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) +static void draw_dm_verts_skin_root__mapFunc(void *userData, int index, const float co[3], + const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) { drawDMVerts_userData *data = userData; BMVert *eve = BM_vert_at_index(data->bm, index); if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) { /* skin nodes: draw a red circle around the root node(s) */ - if (data->cd_vskin_offset != -1) { - const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset); - if (vs->flag & MVERT_SKIN_ROOT) { - float radius = (vs->radius[0] + vs->radius[1]) * 0.5f; - glEnd(); - - glColor4ubv(data->th_skin_root); - drawcircball(GL_LINES, co, radius, data->imat); - - glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex); - glBegin(GL_POINTS); - } + const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset); + if (vs->flag & MVERT_SKIN_ROOT) { + float radius = (vs->radius[0] + vs->radius[1]) * 0.5f; + imm_drawcircball(co, radius, data->imat, data->pos); } + } +} + +/* Draw verts with color set based on selection */ +static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3], + const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) +{ + drawDMVerts_userData *data = userData; + BMVert *eve = BM_vert_at_index(data->bm, index); + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) { /* draw active in a different color - no need to stop/start point drawing for this :D */ if (eve == data->eve_act) { - glColor4ubv(data->th_editmesh_active); - glVertex3fv(co); - - /* back to regular vertex color */ - glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex); + immAttrib4ubv(data->color, data->th_editmesh_active); + immVertex3fv(data->pos, co); } else { - glVertex3fv(co); + immAttrib4ubv(data->color, data->sel ? data->th_vertex_select : data->th_vertex); + immVertex3fv(data->pos, co); } } } static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVert *eve_act, - RegionView3D *rv3d) + RegionView3D *rv3d, const unsigned char col[4]) { + Gwn_VertFormat *format = immVertexFormat(); + drawDMVerts_userData data; data.sel = sel; data.eve_act = eve_act; data.bm = em->bm; + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); /* Cache theme values */ UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, data.th_editmesh_active); @@ -2623,16 +2806,37 @@ static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVer UI_GetThemeColor4ubv(TH_VERTEX, data.th_vertex); UI_GetThemeColor4ubv(TH_SKIN_ROOT, data.th_skin_root); - /* For skin root drawing */ - data.cd_vskin_offset = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN); + /* Set correct alpha */ + data.th_editmesh_active[3] = data.th_vertex_select[3] = data.th_vertex[3] = data.th_skin_root[3] = col[3]; + /* view-aligned matrix */ mul_m4_m4m4(data.imat, rv3d->viewmat, em->ob->obmat); invert_m4(data.imat); + if (dm->getNumVerts(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - glBegin(GL_POINTS); + + immBeginAtMost(GWN_PRIM_POINTS, dm->getNumVerts(dm)); dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); + + /* For skin root drawing */ + data.cd_vskin_offset = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN); + + if (data.cd_vskin_offset != -1) { + data.pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4ubv(data.th_skin_root); + + dm->foreachMappedVert(dm, draw_dm_verts_skin_root__mapFunc, &data, DM_FOREACH_NOP); + + immUnbindProgram(); + } } /* Draw edges with color set based on selection */ @@ -2938,24 +3142,32 @@ static void draw_dm_loop_normals__mapFunc(void *userData, int vertex_index, int } mul_v3_fl(vec, data->normalsize); add_v3_v3(vec, co); - glVertex3fv(co); - glVertex3fv(vec); + immVertex3fv(data->pos, co); + immVertex3fv(data->pos, vec); } } } -static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm) +static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id) { drawDMNormal_userData data; data.bm = em->bm; data.normalsize = scene->toolsettings->normalsize; + data.pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + if (dm->getNumLoops(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(theme_id); calcDrawDMNormalScale(ob, &data); - glBegin(GL_LINES); + immBeginAtMost(GWN_PRIM_LINES, dm->getNumLoops(dm) * 2); dm->foreachMappedLoop(dm, draw_dm_loop_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL); - glEnd(); + immEnd(); + + immUnbindProgram(); } /* Draw faces with color set based on selection @@ -3072,7 +3284,7 @@ static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm) data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE); if (data.cd_layer_offset != -1) { - glLineWidth(3.0); + glLineWidth(3.0f); dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, &data); } } @@ -3102,8 +3314,10 @@ static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { const float bweight = BM_ELEM_CD_GET_FLOAT(eve, data->cd_layer_offset); if (bweight != 0.0f) { - UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_BEVEL, bweight); - glVertex3fv(co); + unsigned char col[3]; + UI_GetThemeColorBlend3ubv(TH_VERTEX, TH_VERTEX_BEVEL, bweight, col); + immAttrib3ubv(data->col, col); + immVertex3fv(data->pos, co); } } } @@ -3117,11 +3331,21 @@ static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm) data.bm = em->bm; data.cd_layer_offset = CustomData_get_offset(&em->bm->vdata, CD_BWEIGHT); + /* is that ever true? */ if (data.cd_layer_offset != -1) { - glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2); - glBegin(GL_POINTS); + Gwn_VertFormat *format = immVertexFormat(); + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2.0f); + + immBeginAtMost(GWN_PRIM_POINTS, dm->getNumVerts(dm)); dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } } else { @@ -3131,7 +3355,7 @@ static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm) data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT); if (data.cd_layer_offset != -1) { - glLineWidth(3.0); + glLineWidth(3.0f); dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, &data); } } @@ -3152,7 +3376,7 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, { ToolSettings *ts = scene->toolsettings; - if (v3d->zbuf) glDepthMask(0); /* disable write in zbuffer, zbuf select */ + if (v3d->zbuf) glDepthMask(GL_FALSE); /* disable write in zbuffer, zbuf select */ for (int sel = 0; sel < 2; sel++) { unsigned char col[4], fcol[4]; @@ -3182,15 +3406,12 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, } if (ts->selectmode & SCE_SELECT_VERTEX) { - glPointSize(size); - glColor4ubv(col); - draw_dm_verts(em, cageDM, sel, eve_act, rv3d); + draw_dm_verts(em, cageDM, sel, eve_act, rv3d, col); } if (check_ob_drawface_dot(scene, v3d, obedit->dt)) { glPointSize(fsize); - glColor4ubv(fcol); - draw_dm_face_centers(em, cageDM, sel); + draw_dm_face_centers(em, cageDM, sel, fcol); } if (pass == 0) { @@ -3200,7 +3421,7 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, } } - if (v3d->zbuf) glDepthMask(1); + if (v3d->zbuf) glDepthMask(GL_TRUE); } static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d, @@ -3307,11 +3528,9 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe if (me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_EDGEANG)) { BoundBox bb; - bglMats mats = {{0}}; const rcti rect = {0, ar->winx, 0, ar->winy}; - view3d_get_transformation(ar, ar->regiondata, em->ob, &mats); - ED_view3d_clipping_calc(&bb, clip_planes, &mats, &rect); + ED_view3d_clipping_calc(&bb, clip_planes, ar, em->ob, &rect); } if (me->drawflag & ME_DRAWEXTRA_EDGELEN) { @@ -3675,7 +3894,7 @@ static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index) } } -static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, +static void draw_em_fancy(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const char dt) { @@ -3684,7 +3903,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, const bool use_occlude_wire = (dt > OB_WIRE) && (v3d->flag2 & V3D_OCCLUDE_WIRE); bool use_depth_offset = false; - glLineWidth(1); + glLineWidth(1.0f); BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); @@ -3693,7 +3912,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, draw_mesh_paint_weight_faces(finalDM, true, draw_em_fancy__setFaceOpts, me->edit_btmesh); ED_view3d_polygon_offset(rv3d, 1.0); - glDepthMask(0); + glDepthMask(GL_FALSE); use_depth_offset = true; } else { @@ -3713,7 +3932,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } else if (check_object_draw_texture(scene, v3d, dt)) { - if (draw_glsl_material(scene, ob, v3d, dt)) { + if (draw_glsl_material(scene, sl, ob, v3d, dt)) { glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); finalDM->drawMappedFacesGLSL(finalDM, GPU_object_material_bind, @@ -3723,7 +3942,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, glFrontFace(GL_CCW); } else { - draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0); + draw_mesh_textured(scene, sl, v3d, rv3d, ob, finalDM, 0); } } else { @@ -3740,7 +3959,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, UI_ThemeColor(TH_WIRE_EDIT); ED_view3d_polygon_offset(rv3d, 1.0); - glDepthMask(0); + glDepthMask(GL_FALSE); use_depth_offset = true; } else { @@ -3790,7 +4009,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #endif glEnable(GL_BLEND); - glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */ /* don't draw unselected faces, only selected, this is MUCH nicer when texturing */ if (check_object_draw_texture(scene, v3d, dt)) @@ -3806,7 +4025,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #endif glDisable(GL_BLEND); - glDepthMask(1); /* restore write in zbuffer */ + glDepthMask(GL_TRUE); /* restore write in zbuffer */ } else if (efa_act) { /* even if draw faces is off it would be nice to draw the stipple face @@ -3821,7 +4040,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3); glEnable(GL_BLEND); - glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */ #ifdef WITH_FREESTYLE draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act); @@ -3830,7 +4049,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #endif glDisable(GL_BLEND); - glDepthMask(1); /* restore write in zbuffer */ + glDepthMask(GL_TRUE); /* restore write in zbuffer */ } /* here starts all fancy draw-extra over */ @@ -3844,7 +4063,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, else { if (me->drawflag & ME_DRAWSEAMS) { UI_ThemeColor(TH_EDGE_SEAM); - glLineWidth(2); + glLineWidth(2.0f); draw_dm_edges_seams(em, cageDM); @@ -3853,7 +4072,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, if (me->drawflag & ME_DRAWSHARP) { UI_ThemeColor(TH_EDGE_SHARP); - glLineWidth(2); + glLineWidth(2.0f); draw_dm_edges_sharp(em, cageDM); @@ -3863,7 +4082,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #ifdef WITH_FREESTYLE if (me->drawflag & ME_DRAW_FREESTYLE_EDGE && CustomData_has_layer(&em->bm->edata, CD_FREESTYLE_EDGE)) { UI_ThemeColor(TH_FREESTYLE_EDGE_MARK); - glLineWidth(2); + glLineWidth(2.0f); draw_dm_edges_freestyle(em, cageDM); @@ -3878,7 +4097,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, draw_dm_bweights(em, scene, cageDM); } - glLineWidth(1); + glLineWidth(1.0f); draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act); } @@ -3886,16 +4105,13 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act, rv3d); if (me->drawflag & ME_DRAWNORMALS) { - UI_ThemeColor(TH_NORMAL); - draw_dm_face_normals(em, scene, ob, cageDM); + draw_dm_face_normals(em, scene, ob, cageDM, TH_NORMAL); } if (me->drawflag & ME_DRAW_VNORMALS) { - UI_ThemeColor(TH_VNORMAL); - draw_dm_vert_normals(em, scene, ob, cageDM); + draw_dm_vert_normals(em, scene, ob, cageDM, TH_VNORMAL); } if (me->drawflag & ME_DRAW_LNORMALS) { - UI_ThemeColor(TH_LNORMAL); - draw_dm_loop_normals(em, scene, ob, cageDM); + draw_dm_loop_normals(em, scene, ob, cageDM, TH_LNORMAL); } if ((me->drawflag & (ME_DRAWEXTRA_EDGELEN | @@ -3916,7 +4132,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, } if (use_depth_offset) { - glDepthMask(1); + glDepthMask(GL_TRUE); ED_view3d_polygon_offset(rv3d, 0.0); GPU_object_material_unbind(); } @@ -3927,15 +4143,97 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #endif } +static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *UNUSED(ar), View3D *UNUSED(v3d), + Object *UNUSED(ob), Mesh *me, BMEditMesh *UNUSED(em), DerivedMesh *UNUSED(cageDM), DerivedMesh *UNUSED(finalDM), const char UNUSED(dt)) +{ + /* for now... something simple! */ + Gwn_Batch *surface = DRW_mesh_batch_cache_get_all_triangles(me); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + glEnable(GL_BLEND); + + /* disable depth writes for transparent surface, so it doesn't interfere with itself */ + glDepthMask(GL_FALSE); + + GWN_batch_program_set_builtin(surface, GPU_SHADER_3D_UNIFORM_COLOR); + GWN_batch_uniform_4f(surface, "color", 1.0f, 0.5f, 0.0f, 0.5f); + GWN_batch_draw(surface); + +#if 0 /* until I understand finalDM better */ + if (finalDM != cageDM) { + puts("finalDM != cageDM"); + Gwn_Batch *finalSurface = MBC_get_all_triangles(finalDM); + GWN_batch_program_set_builtin(finalSurface, GPU_SHADER_3D_UNIFORM_COLOR); + GWN_batch_uniform_4f(finalSurface, "color", 0.0f, 0.0f, 0.0f, 0.05f); + GWN_batch_draw(finalSurface); + } +#endif + + glDepthMask(GL_TRUE); + + /* now write surface depth so other objects won't poke through + * NOTE: does not help as much as desired + * TODO: draw edit object last to avoid this mess + */ + GWN_batch_program_set_builtin(surface, GPU_SHADER_3D_DEPTH_ONLY); + GWN_batch_draw(surface); + + if (GLEW_VERSION_3_2) { +#if 0 + Gwn_Batch *overlay = DRW_mesh_batch_cache_get_overlay_edges(me); + GWN_batch_program_set_builtin(overlay, GPU_SHADER_EDGES_OVERLAY); + GWN_batch_uniform_2f(overlay, "viewportSize", ar->winx, ar->winy); + GWN_batch_draw(overlay); +#endif + +#if 0 /* TODO: use this SIMPLE variant for pure triangle meshes */ + GWN_batch_program_set_builtin(surface, GPU_SHADER_EDGES_OVERLAY_SIMPLE); + /* use these defaults: + * const float edgeColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + * GWN_batch_uniform_4f(surface, "fillColor", edgeColor[0], edgeColor[1], edgeColor[2], 0.0f); + * GWN_batch_uniform_4fv(surface, "outlineColor", edgeColor); + * GWN_batch_uniform_1f(surface, "outlineWidth", 1.0f); + */ + GWN_batch_uniform_2f(surface, "viewportSize", ar->winx, ar->winy); + GWN_batch_draw(surface); +#endif + } + else { + Gwn_Batch *edges = DRW_mesh_batch_cache_get_all_edges(me); + GWN_batch_program_set_builtin(edges, GPU_SHADER_3D_UNIFORM_COLOR); + GWN_batch_uniform_4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f); + glEnable(GL_LINE_SMOOTH); + glLineWidth(1.5f); + GWN_batch_draw(edges); + glDisable(GL_LINE_SMOOTH); + } + +#if 0 /* looks good even without points */ + Gwn_Batch *verts = MBC_get_all_verts(me); + glEnable(GL_BLEND); + + GWN_batch_program_set_builtin(verts, GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + GWN_batch_uniform_4f(verts, "color", 0.0f, 0.0f, 0.0f, 1.0f); + GWN_batch_uniform_1f(verts, "size", UI_GetThemeValuef(TH_VERTEX_SIZE) * 1.5f); + GWN_batch_draw(verts); + + glDisable(GL_BLEND); +#endif +} + /* Mesh drawing routines */ -static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) +void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm, const unsigned char ob_wire_col[4]) /* LEGACY */ { if ((v3d->transp == false) && /* not when we draw the transparent pass */ (ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */ { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); - glDepthMask(0); + glDepthMask(GL_FALSE); + + if (ob_wire_col) glColor4ubv(ob_wire_col); /* if transparent, we cannot draw the edges for solid select... edges * have no material info. GPU_object_material_visible will skip the @@ -3949,7 +4247,49 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) dm->drawEdges(dm, 0, 1); } - glDepthMask(1); + glDepthMask(GL_TRUE); + } +} + +static void draw_mesh_object_outline_new(View3D *v3d, RegionView3D *rv3d, Object *ob, Mesh *me, const bool is_active) +{ + if ((v3d->transp == false) && /* not when we draw the transparent pass */ + (ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */ + { + glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); + glDepthMask(GL_FALSE); + + float outline_color[4]; + UI_GetThemeColor4fv((is_active ? TH_ACTIVE : TH_SELECT), outline_color); + +#if 1 /* new version that draws only silhouette edges */ + Gwn_Batch *fancy_edges = DRW_mesh_batch_cache_get_fancy_edges(me); + + if (rv3d->persp == RV3D_ORTHO) { + GWN_batch_program_set_builtin(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_ORTHO); + /* set eye vector, transformed to object coords */ + float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */ + mul_m3_v3(gpuGetNormalMatrixInverse(NULL), eye); + GWN_batch_uniform_3fv(fancy_edges, "eye", eye); + } + else { + GWN_batch_program_set_builtin(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_PERSP); + } + + GWN_batch_uniform_1b(fancy_edges, "drawFront", false); + GWN_batch_uniform_1b(fancy_edges, "drawBack", false); + GWN_batch_uniform_1b(fancy_edges, "drawSilhouette", true); + GWN_batch_uniform_4fv(fancy_edges, "silhouetteColor", outline_color); + + GWN_batch_draw(fancy_edges); +#else /* alternate version that matches look of old viewport (but more efficient) */ + Gwn_Batch *batch = MBC_get_all_edges(dm); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + GWN_batch_uniform_4fv(batch, "color", outline_color); + GWN_batch_draw(batch); +#endif + + glDepthMask(GL_TRUE); } } @@ -3959,19 +4299,20 @@ static bool object_is_halo(Scene *scene, Object *ob) return (ma && (ma->material_type == MA_TYPE_HALO) && !BKE_scene_use_new_shading_nodes(scene)); } -static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, - const char dt, const unsigned char ob_wire_col[4], const short dflag) +static void draw_mesh_fancy( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const unsigned char ob_wire_col[4], const short dflag) { #ifdef WITH_GAMEENGINE - Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, scene) : base->object; + Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, sl) : base->object; #else Object *ob = base->object; #endif Mesh *me = ob->data; eWireDrawMode draw_wire = OBDRAW_WIRE_OFF; bool /* no_verts,*/ no_edges, no_faces; - DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); - const bool is_obact = (ob == OBACT); + DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, scene->customdata_mask); + const bool is_obact = (ob == OBACT(sl)); int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0; if (!dm) @@ -4007,12 +4348,12 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if (dt == OB_BOUNDBOX) { if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0) - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } else if ((no_faces && no_edges) || ((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob))) { - glPointSize(1.5); + glPointSize(1.5f); dm->drawVerts(dm); } else if ((dt == OB_WIRE) || no_faces) { @@ -4025,19 +4366,19 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) && (draw_wire == OBDRAW_WIRE_OFF)) { - draw_mesh_object_outline(v3d, ob, dm); + draw_mesh_object_outline(v3d, ob, dm, ob_wire_col); } - if (draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) { + if (draw_glsl_material(scene, sl, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) { Paint *p; glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); - if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene))) { + if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene, sl))) { GPUVertexAttribs gattribs; float planes[4][4]; float (*fpl)[4] = NULL; @@ -4045,7 +4386,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if (ob->sculpt->partial_redraw) { if (ar->do_draw & RGN_DRAW_PARTIAL) { - ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob); + ED_sculpt_redraw_planes_get(planes, ar, ob); fpl = planes; ob->sculpt->partial_redraw = 0; } @@ -4070,7 +4411,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D draw_mesh_face_select(rv3d, me, dm, false); } else { - draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags); + draw_mesh_textured(scene, sl, v3d, rv3d, ob, dm, draw_flags); } if (draw_loose && !(draw_flags & DRAW_FACE_SELECT)) { @@ -4096,11 +4437,11 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D /* draw outline */ if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { - draw_mesh_object_outline(v3d, ob, dm); + draw_mesh_object_outline(v3d, ob, dm, ob_wire_col); } /* materials arent compatible with vertex colors */ @@ -4120,23 +4461,23 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { - draw_mesh_object_outline(v3d, ob, dm); + draw_mesh_object_outline(v3d, ob, dm, ob_wire_col); } glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); - if (ob->sculpt && (p = BKE_paint_get_active(scene))) { + if (ob->sculpt && (p = BKE_paint_get_active(scene, sl))) { float planes[4][4]; float (*fpl)[4] = NULL; const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING); if (ob->sculpt->partial_redraw) { if (ar->do_draw & RGN_DRAW_PARTIAL) { - ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob); + ED_sculpt_redraw_planes_get(planes, ar, ob); fpl = planes; ob->sculpt->partial_redraw = 0; } @@ -4177,7 +4518,9 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if ((dflag & DRAW_CONSTCOLOR) == 0) { if (is_obact && (ob->mode & OB_MODE_PARTICLE_EDIT)) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.15f); + float color[3]; + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.15f, color); + glColor3fv(color); } else { glColor3ubv(ob_wire_col); @@ -4195,14 +4538,14 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D */ if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) { ED_view3d_polygon_offset(rv3d, 1.0); - glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, selected edge wires show better */ } glLineWidth(1.0f); dm->drawEdges(dm, ((dt == OB_WIRE) || no_faces), (ob->dtx & OB_DRAW_ALL_EDGES) != 0); if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) { - glDepthMask(1); + glDepthMask(GL_TRUE); ED_view3d_polygon_offset(rv3d, 0.0); } } @@ -4221,8 +4564,9 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } /* returns true if nothing was drawn, for detecting to draw an object center */ -static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, - const char dt, const unsigned char ob_wire_col[4], const short dflag) +static bool draw_mesh_object( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const unsigned char ob_wire_col[4], const short dflag) { Object *ob = base->object; Object *obedit = scene->obedit; @@ -4233,7 +4577,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 /* If we are drawing shadows and any of the materials don't cast a shadow, * then don't draw the object */ if (v3d->flag2 & V3D_RENDER_SHADOW) { - for (int i = 1; i <= ob->totcol; ++i) { + for (int i = 0; i < ob->totcol; ++i) { Material *ma = give_current_material(ob, i); if (ma && !(ma->mode2 & MA_CASTSHADOW)) { return true; @@ -4262,7 +4606,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 } else { cageDM = editbmesh_get_derived_cage_and_final( - scene, ob, em, scene->customdata_mask, + eval_ctx, scene, ob, em, scene->customdata_mask, &finalDM); } @@ -4275,13 +4619,13 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 if (use_material) { if (dt > OB_WIRE) { - const bool glsl = draw_glsl_material(scene, ob, v3d, dt); + const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL); } } - draw_em_fancy(scene, ar, v3d, ob, em, cageDM, finalDM, dt); + draw_em_fancy(scene, sl, ar, v3d, ob, em, cageDM, finalDM, dt); if (use_material) { GPU_end_object_materials(); @@ -4294,16 +4638,16 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 /* ob->bb was set by derived mesh system, do NULL check just to be sure */ if (me->totpoly <= 4 || (!ob->bb || ED_view3d_boundbox_clip(rv3d, ob->bb))) { if (dt > OB_WIRE) { - const bool glsl = draw_glsl_material(scene, ob, v3d, dt); + const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); if (dt == OB_SOLID || glsl) { const bool check_alpha = check_alpha_pass(base); - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, (check_alpha) ? &do_alpha_after : NULL); } } - draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); + draw_mesh_fancy(eval_ctx, scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); GPU_end_object_materials(); @@ -4311,7 +4655,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 } } - if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag_legacy & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* GPU_begin_object_materials checked if this is needed */ if (do_alpha_after) { if (ob->dtx & OB_DRAWXRAY) { @@ -4335,18 +4679,551 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 return retval; } +static void make_color_variations(const unsigned char base_ubyte[4], float low[4], float med[4], float high[4], const bool other_obedit) +{ + /* original idea: nice variations (lighter & darker shades) of base color + * current implementation uses input color as high; med & low get closer to background color + */ + + float bg[3]; + UI_GetThemeColor3fv(TH_BACK, bg); + + float base[4]; + rgba_uchar_to_float(base, base_ubyte); + + if (other_obedit) { + /* this object should fade away so user can focus on the object being edited */ + interp_v3_v3v3(low, bg, base, 0.1f); + interp_v3_v3v3(med, bg, base, 0.2f); + interp_v3_v3v3(high, bg, base, 0.25f); + } + else { + interp_v3_v3v3(low, bg, base, 0.333f); + interp_v3_v3v3(med, bg, base, 0.667f); + copy_v3_v3(high, base); + } + + /* use original alpha */ + low[3] = base[3]; + med[3] = base[3]; + high[3] = base[3]; +} + +static void draw_mesh_fancy_new(EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const unsigned char ob_wire_col[4], const short dflag, const bool other_obedit) +{ + if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) { + /* too complicated! use existing methods */ + /* TODO: move this into a separate depth pre-pass */ + draw_mesh_fancy(eval_ctx, scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); + return; + } + +#ifdef WITH_GAMEENGINE + Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, sl) : base->object; +#else + Object *ob = base->object; +#endif + Mesh *me = ob->data; + eWireDrawMode draw_wire = OBDRAW_WIRE_OFF; /* could be bool draw_wire_overlay */ + bool no_edges, no_faces; + DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, scene->customdata_mask); + const bool is_obact = (ob == OBACT(sl)); + int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0; + + if (!dm) + return; + + const bool solid = dt >= OB_SOLID; + if (solid) { + DM_update_materials(dm, ob); + } + + /* Check to draw dynamic paint colors (or weights from WeightVG modifiers). + * Note: Last "preview-active" modifier in stack will win! */ + if (DM_get_loop_data_layer(dm, CD_PREVIEW_MLOOPCOL) && modifiers_isPreview(ob)) + draw_flags |= DRAW_MODIFIERS_PREVIEW; + + /* Unwanted combination */ + if (draw_flags & DRAW_FACE_SELECT) { + draw_wire = OBDRAW_WIRE_OFF; + } + else if (ob->dtx & OB_DRAWWIRE) { + draw_wire = OBDRAW_WIRE_ON; + } + + /* check polys instead of tessfaces because of dyntopo where tessfaces don't exist */ + if (dm->type == DM_TYPE_CCGDM) { + no_edges = !subsurf_has_edges(dm); + no_faces = !subsurf_has_faces(dm); + } + else { + no_edges = (dm->getNumEdges(dm) == 0); + no_faces = (dm->getNumPolys(dm) == 0); + } + + if (solid) { + /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */ + glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + } + + if (dt == OB_BOUNDBOX) { + if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0) + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); + } + else if ((no_faces && no_edges) || + ((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob))) + { + glPointSize(1.5f); + // dm->drawVerts(dm); + // TODO: draw smooth round points as a batch + } + else if ((dt == OB_WIRE) || no_faces) { + draw_wire = OBDRAW_WIRE_ON; + + /* enable depth for wireframes */ + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glLineWidth(1.0f); + +#if 1 /* fancy wireframes */ + + Gwn_Batch *fancy_edges = DRW_mesh_batch_cache_get_fancy_edges(me); + + if (rv3d->persp == RV3D_ORTHO) { + GWN_batch_program_set_builtin(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_ORTHO); + /* set eye vector, transformed to object coords */ + float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */ + mul_m3_v3(gpuGetNormalMatrixInverse(NULL), eye); + GWN_batch_uniform_3fv(fancy_edges, "eye", eye); + } + else { + GWN_batch_program_set_builtin(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_PERSP); + } + + float frontColor[4]; + float backColor[4]; + float outlineColor[4]; + make_color_variations(ob_wire_col, backColor, frontColor, outlineColor, other_obedit); + + GWN_batch_uniform_4fv(fancy_edges, "frontColor", frontColor); + GWN_batch_uniform_4fv(fancy_edges, "backColor", backColor); + GWN_batch_uniform_1b(fancy_edges, "drawFront", true); + GWN_batch_uniform_1b(fancy_edges, "drawBack", true); /* false here = backface cull */ + GWN_batch_uniform_1b(fancy_edges, "drawSilhouette", false); + + GWN_batch_draw(fancy_edges); + + /* extra oomph for the silhouette contours */ + glLineWidth(2.0f); + GWN_batch_program_use_begin(fancy_edges); /* hack to make the following uniforms stick */ + GWN_batch_uniform_1b(fancy_edges, "drawFront", false); + GWN_batch_uniform_1b(fancy_edges, "drawBack", false); + GWN_batch_uniform_1b(fancy_edges, "drawSilhouette", true); + GWN_batch_uniform_4fv(fancy_edges, "silhouetteColor", outlineColor); + + GWN_batch_draw(fancy_edges); + +#else /* simple wireframes */ + + Gwn_Batch *batch = MBC_get_all_edges(dm); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + + float color[4]; + rgba_uchar_to_float(color, ob_wire_col); + + GWN_batch_uniform_4fv(batch, "color", color); + + GWN_batch_draw(batch); +#endif + } + else if (((is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) || + check_object_draw_texture(scene, v3d, dt)) + { + bool draw_loose = true; + + if ((v3d->flag & V3D_SELECT_OUTLINE) && + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && + (base->flag & BASE_SELECTED) && + !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) && + (draw_wire == OBDRAW_WIRE_OFF)) + { + draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT(sl))); + } + + if (draw_glsl_material(scene, sl, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) { + Paint *p; + + glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + + if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene, sl))) { + GPUVertexAttribs gattribs; + float planes[4][4]; + float (*fpl)[4] = NULL; + const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING); + + if (ob->sculpt->partial_redraw) { + if (ar->do_draw & RGN_DRAW_PARTIAL) { + ED_sculpt_redraw_planes_get(planes, ar, ob); + fpl = planes; + ob->sculpt->partial_redraw = 0; + } + } + + GPU_object_material_bind(1, &gattribs); + dm->drawFacesSolid(dm, fpl, fast, NULL); + draw_loose = false; + } + else + dm->drawFacesGLSL(dm, GPU_object_material_bind); + + GPU_object_material_unbind(); + + glFrontFace(GL_CCW); + + if (draw_flags & DRAW_FACE_SELECT) + draw_mesh_face_select(rv3d, me, dm, false); + } + else { + draw_mesh_textured(scene, sl, v3d, rv3d, ob, dm, draw_flags); + } + + if (draw_loose && !(draw_flags & DRAW_FACE_SELECT)) { + if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + if ((dflag & DRAW_CONSTCOLOR) == 0) { + glColor3ubv(ob_wire_col); + } + glLineWidth(1.0f); + dm->drawLooseEdges(dm); + } + } + } + else if (dt == OB_SOLID) { + if (draw_flags & DRAW_MODIFIERS_PREVIEW) { + /* for object selection draws no shade */ + if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) { + /* TODO: draw basic faces with GPU_SHADER_3D_DEPTH_ONLY */ + } + else { + const float specular[3] = {0.47f, 0.47f, 0.47f}; + + /* draw outline */ + /* TODO: move this into a separate pass */ + if ((v3d->flag & V3D_SELECT_OUTLINE) && + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && + (base->flag & BASE_SELECTED) && + (draw_wire == OBDRAW_WIRE_OFF) && + (ob->sculpt == NULL)) + { + draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT(sl))); + } + + /* materials arent compatible with vertex colors */ + GPU_end_object_materials(); + + /* set default specular */ + GPU_basic_shader_colors(NULL, specular, 35, 1.0f); + GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); + + dm->drawMappedFaces(dm, NULL, NULL, NULL, NULL, DM_DRAW_USE_COLORS | DM_DRAW_NEED_NORMALS); + + GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + } + } + else { + Paint *p; + + if ((v3d->flag & V3D_SELECT_OUTLINE) && + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && + (base->flag & BASE_SELECTED) && + (draw_wire == OBDRAW_WIRE_OFF) && + (ob->sculpt == NULL)) + { + /* TODO: move this into a separate pass */ + draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT(sl))); + } + + glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + + if (ob->sculpt && (p = BKE_paint_get_active(scene, sl))) { + float planes[4][4]; + float (*fpl)[4] = NULL; + const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING); + + if (ob->sculpt->partial_redraw) { + if (ar->do_draw & RGN_DRAW_PARTIAL) { + ED_sculpt_redraw_planes_get(planes, ar, ob); + fpl = planes; + ob->sculpt->partial_redraw = 0; + } + } + + dm->drawFacesSolid(dm, fpl, fast, GPU_object_material_bind); + } + else + dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind); + + glFrontFace(GL_CCW); + + GPU_object_material_unbind(); + + if (!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + if ((dflag & DRAW_CONSTCOLOR) == 0) { + glColor3ubv(ob_wire_col); + } + glLineWidth(1.0f); + dm->drawLooseEdges(dm); + } + } + } + else if (dt == OB_PAINT) { + draw_mesh_paint(v3d, rv3d, ob, dm, draw_flags); + + /* since we already draw wire as wp guide, don't draw over the top */ + draw_wire = OBDRAW_WIRE_OFF; + } + + if ((draw_wire != OBDRAW_WIRE_OFF) && /* draw extra wire */ + /* when overriding with render only, don't bother */ + (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_SOLID) == 0)) // <-- is this "== 0" in the right spot??? + { + /* When using wireframe object draw in particle edit mode + * the mesh gets in the way of seeing the particles, fade the wire color + * with the background. */ + + if ((dflag & DRAW_CONSTCOLOR) == 0) { + /* TODO: + * Batch_UniformColor4ubv(ob_wire_col); + */ + } + + /* If drawing wire and drawtype is not OB_WIRE then we are + * overlaying the wires. + * + * No need for polygon offset because new technique is AWESOME. + */ +#if 0 + glLineWidth(1.0f); + dm->drawEdges(dm, ((dt == OB_WIRE) || no_faces), (ob->dtx & OB_DRAW_ALL_EDGES) != 0); +#else + /* something */ +#endif + } + +#if 0 // (merwin) what is this for? + if (is_obact && BKE_paint_select_vert_test(ob)) { + const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) != 0; + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + if (!use_depth) glDisable(GL_DEPTH_TEST); + else ED_view3d_polygon_offset(rv3d, 1.0); + drawSelectedVertices(dm, ob->data); + if (!use_depth) glEnable(GL_DEPTH_TEST); + else ED_view3d_polygon_offset(rv3d, 0.0); + } +#endif + + dm->release(dm); +} + +static bool UNUSED_FUNCTION(draw_mesh_object_new)(const bContext *C, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const unsigned char ob_wire_col[4], const short dflag) +{ + EvaluationContext eval_ctx; + Object *ob = base->object; + Object *obedit = scene->obedit; + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + bool do_alpha_after = false, drawlinked = false, retval = false; + + CTX_data_eval_ctx(C, &eval_ctx); + + if (v3d->flag2 & V3D_RENDER_SHADOW) { + /* TODO: handle shadow pass separately */ + return true; + } + + if (obedit && ob != obedit && ob->data == obedit->data) { + if (BKE_key_from_object(ob) || BKE_key_from_object(obedit)) {} + else if (ob->modifiers.first || obedit->modifiers.first) {} + else drawlinked = true; + } + + /* backface culling */ + const bool solid = dt > OB_WIRE; + const bool cullBackface = solid && (v3d->flag2 & V3D_BACKFACE_CULLING); + if (cullBackface) { + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + } + + if (ob == obedit || drawlinked) { + DerivedMesh *finalDM, *cageDM; + + if (obedit != ob) { + /* linked to the edit object */ + finalDM = cageDM = editbmesh_get_derived_base( + ob, em, scene->customdata_mask); + } + else { + cageDM = editbmesh_get_derived_cage_and_final( + &eval_ctx, scene, ob, em, scene->customdata_mask, + &finalDM); + } + + const bool use_material = solid && ((me->drawflag & ME_DRAWEIGHT) == 0); + +#if 0 // why update if not being used? + DM_update_materials(finalDM, ob); + if (cageDM != finalDM) { + DM_update_materials(cageDM, ob); + } +#endif // moved to below + + if (use_material) { + DM_update_materials(finalDM, ob); + if (cageDM != finalDM) { + DM_update_materials(cageDM, ob); + } + + const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); + + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL); + } + + draw_em_fancy_new(scene, ar, v3d, ob, me, em, cageDM, finalDM, dt); + + if (use_material) { + GPU_end_object_materials(); + } + + if (obedit != ob) + finalDM->release(finalDM); + } + else { + /* ob->bb was set by derived mesh system, do NULL check just to be sure */ + if (me->totpoly <= 4 || (!ob->bb || ED_view3d_boundbox_clip(rv3d, ob->bb))) { + if (solid) { + const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); + + if (dt == OB_SOLID || glsl) { + const bool check_alpha = check_alpha_pass(base); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, + (check_alpha) ? &do_alpha_after : NULL); + } + } + + const bool other_obedit = obedit && (obedit != ob); + + draw_mesh_fancy_new(&eval_ctx, scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag, other_obedit); + + GPU_end_object_materials(); + + if (me->totvert == 0) retval = true; + } + } + + if (cullBackface) + glDisable(GL_CULL_FACE); + + return retval; +} + /* ************** DRAW DISPLIST ****************** */ +static void drawDispListVerts(Gwn_PrimType prim_type, const void *data, unsigned int vert_ct, const unsigned char wire_col[3]) +{ + Gwn_VertFormat format = {0}; + unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vert_ct); + + GWN_vertbuf_attr_fill(vbo, pos_id, data); + + Gwn_Batch *batch = GWN_batch_create_ex(prim_type, vbo, NULL, GWN_BATCH_OWNS_VBO); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + if (wire_col) { + GWN_batch_uniform_4f(batch, "color", wire_col[0] / 255.0f, wire_col[1] / 255.0f, wire_col[2] / 255.0f, 1.0f); + } + GWN_batch_draw(batch); + GWN_batch_discard(batch); +} + +/* convert dispList with elem indices to batch, only support triangles and quads + * XXX : This is a huge perf issue. We should cache the resulting batches inside the object instead. + * But new viewport will do it anyway + * TODO implement flat drawing */ +static void drawDispListElem( + bool quads, bool UNUSED(smooth), bool ndata_is_single, + const float *data, const float *ndata, unsigned int data_len, + const int *elem, unsigned int elem_len, const unsigned char wire_col[3]) +{ + Gwn_VertFormat format = {0}; + int i; + const int *idx = elem; + unsigned int pos_id, nor_id; + + pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + if (ndata) { + if (ndata_is_single) { + /* pass */ + } + else { + nor_id = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + } + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, (quads) ? elem_len * 2 : elem_len, 0xffffffff); + + if (quads) { + for (i = elem_len; i; --i, idx += 4) { + GWN_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]); + GWN_indexbuf_add_tri_verts(&elb, idx[0], idx[2], idx[3]); + } + } + else { + for (i = elem_len; i; --i, idx += 3) { + GWN_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]); + } + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, data_len); + + GWN_vertbuf_attr_fill(vbo, pos_id, data); + + if (ndata) { + if (ndata_is_single) { + /* TODO: something like glNormal for a single value */ + } + else { + GWN_vertbuf_attr_fill(vbo, nor_id, ndata); + } + } + + Gwn_Batch *batch = GWN_batch_create_ex( + GWN_PRIM_TRIS, vbo, GWN_indexbuf_build(&elb), GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX); + GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING); + if (wire_col) { + GWN_batch_uniform_4f(batch, "color", wire_col[0] / 255.0f, wire_col[1] / 255.0f, wire_col[2] / 255.0f, 1.0f); + } + GWN_batch_uniform_4f(batch, "color", 0.8f, 0.8f, 0.8f, 1.0f); + GWN_batch_uniform_3f(batch, "light", 0.0f, 0.0f, 1.0f); + GWN_batch_draw(batch); + GWN_batch_discard(batch); +} /** * \param dl_type_mask Only draw types matching this mask. * \return true when nothing was drawn */ -static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask) +static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask, const unsigned char wire_col[3]) { if (dlbase == NULL) return true; - glEnableClientState(GL_VERTEX_ARRAY); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); for (DispList *dl = dlbase->first; dl; dl = dl->next) { @@ -4357,83 +5234,76 @@ static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask) if ((dl_type_mask & (1 << dl->type)) == 0) { continue; } - + const float *data = dl->verts; int parts; switch (dl->type) { case DL_SEGM: - - glVertexPointer(3, GL_FLOAT, 0, data); - for (parts = 0; parts < dl->parts; parts++) - glDrawArrays(GL_LINE_STRIP, parts * dl->nr, dl->nr); - + drawDispListVerts(GWN_PRIM_LINE_STRIP, data + (parts * dl->nr * 3), dl->nr, wire_col); break; - case DL_POLY: - - glVertexPointer(3, GL_FLOAT, 0, data); + case DL_POLY: for (parts = 0; parts < dl->parts; parts++) - glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr); - + drawDispListVerts(GWN_PRIM_LINE_LOOP, data + (parts * dl->nr * 3), dl->nr, wire_col); break; - case DL_SURF: - - glVertexPointer(3, GL_FLOAT, 0, data); + case DL_SURF: for (parts = 0; parts < dl->parts; parts++) { if (dl->flag & DL_CYCL_U) - glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr); + drawDispListVerts(GWN_PRIM_LINE_LOOP, data + (parts * dl->nr * 3), dl->nr, wire_col); else - glDrawArrays(GL_LINE_STRIP, parts * dl->nr, dl->nr); + drawDispListVerts(GWN_PRIM_LINE_STRIP, data + (parts * dl->nr * 3), dl->nr, wire_col); } + float *data_aligned = MEM_mallocN(sizeof(float) * 3 * dl->parts, "aligned data"); for (int nr = 0; nr < dl->nr; nr++) { int ofs = 3 * dl->nr; + int idx = 0; data = (dl->verts) + 3 * nr; parts = dl->parts; - if (dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP); - else glBegin(GL_LINE_STRIP); - while (parts--) { - glVertex3fv(data); + copy_v3_v3(data_aligned + idx, data); data += ofs; + idx += 3; } - glEnd(); -#if 0 - /* (ton) this code crashes for me when resolv is 86 or higher... no clue */ - glVertexPointer(3, GL_FLOAT, sizeof(float) * 3 * dl->nr, data + 3 * nr); - if (dl->flag & DL_CYCL_V) - glDrawArrays(GL_LINE_LOOP, 0, dl->parts); - else - glDrawArrays(GL_LINE_STRIP, 0, dl->parts); -#endif + if (dl->flag & DL_CYCL_V) + drawDispListVerts(GWN_PRIM_LINE_LOOP, data_aligned, dl->parts, wire_col); + else + drawDispListVerts(GWN_PRIM_LINE_STRIP, data_aligned, dl->parts, wire_col); } + + if (data_aligned) + MEM_freeN(data_aligned); + break; case DL_INDEX3: - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index); + drawDispListElem( + false, true, false, + dl->verts, NULL, dl->nr, + dl->index, dl->parts, wire_col); break; case DL_INDEX4: - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - glDrawElements(GL_QUADS, 4 * dl->parts, GL_UNSIGNED_INT, dl->index); + drawDispListElem( + true, true, false, + dl->verts, NULL, dl->nr, + dl->index, dl->parts, wire_col); break; } } - glDisableClientState(GL_VERTEX_ARRAY); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); return false; } -static bool drawDispListwire(ListBase *dlbase, const short ob_type) +static bool drawDispListwire(ListBase *dlbase, const short ob_type, const unsigned char wire_col[3]) { unsigned int dl_mask = 0xffffffff; @@ -4442,27 +5312,25 @@ static bool drawDispListwire(ListBase *dlbase, const short ob_type) dl_mask &= ~((1 << DL_INDEX3) | (1 << DL_INDEX4)); } - return drawDispListwire_ex(dlbase, dl_mask); + return drawDispListwire_ex(dlbase, dl_mask, wire_col); } static bool index3_nors_incr = true; -static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, +static void drawDispListsolid(ListBase *lb, Object *ob, const short UNUSED(dflag), const unsigned char ob_wire_col[4], const bool use_glsl) { GPUVertexAttribs gattribs; if (lb == NULL) return; - glEnableClientState(GL_VERTEX_ARRAY); - /* track current material, -1 for none (needed for lines) */ short col = -1; DispList *dl = lb->first; while (dl) { const float *data = dl->verts; - const float *ndata = dl->nors; + //const float *ndata = dl->nors; switch (dl->type) { case DL_SEGM: @@ -4472,15 +5340,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, col = -1; } - if ((dflag & DRAW_CONSTCOLOR) == 0) - glColor3ubv(ob_wire_col); - - // glVertexPointer(3, GL_FLOAT, 0, dl->verts); - // glDrawArrays(GL_LINE_STRIP, 0, dl->nr); - glBegin(GL_LINE_STRIP); - for (int nr = dl->nr; nr; nr--, data += 3) - glVertex3fv(data); - glEnd(); + drawDispListVerts(GWN_PRIM_LINE_STRIP, data, dl->nr, ob_wire_col); } break; case DL_POLY: @@ -4490,14 +5350,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, col = -1; } - /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */ - //glVertexPointer(3, GL_FLOAT, 0, dl->verts); - //glDrawArrays(GL_LINE_LOOP, 0, dl->nr); - - glBegin(GL_LINE_LOOP); - for (int nr = dl->nr; nr; nr--, data += 3) - glVertex3fv(data); - glEnd(); + drawDispListVerts(GWN_PRIM_LINE_LOOP, data, dl->nr, ob_wire_col); } break; case DL_SURF: @@ -4507,15 +5360,12 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, GPU_object_material_bind(dl->col + 1, use_glsl ? &gattribs : NULL); col = dl->col; } - /* FLAT/SMOOTH shading for surfaces */ - glShadeModel((dl->rt & CU_SMOOTH) ? GL_SMOOTH : GL_FLAT); + const unsigned int verts_len = dl->nr * dl->parts; - glEnableClientState(GL_NORMAL_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - glNormalPointer(GL_FLOAT, 0, dl->nors); - glDrawElements(GL_QUADS, 4 * dl->totindex, GL_UNSIGNED_INT, dl->index); - glDisableClientState(GL_NORMAL_ARRAY); - glShadeModel(GL_SMOOTH); + drawDispListElem( + true, (dl->rt & CU_SMOOTH) != 0, false, + dl->verts, dl->nors, verts_len, + dl->index, dl->totindex, ob_wire_col); } break; @@ -4525,8 +5375,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, col = dl->col; } - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - +#if 0 /* for polys only one normal needed */ if (index3_nors_incr) { glEnableClientState(GL_NORMAL_ARRAY); @@ -4534,11 +5383,17 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, } else glNormal3fv(ndata); +#endif + /* special case, 'nors' is a single value */ + drawDispListElem( + false, (dl->rt & CU_SMOOTH) != 0, true, + dl->verts, dl->nors, dl->nr, + dl->index, dl->parts, ob_wire_col); - glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index); - +#if 0 if (index3_nors_incr) glDisableClientState(GL_NORMAL_ARRAY); +#endif break; @@ -4548,18 +5403,16 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, col = dl->col; } - glEnableClientState(GL_NORMAL_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - glNormalPointer(GL_FLOAT, 0, dl->nors); - glDrawElements(GL_QUADS, 4 * dl->parts, GL_UNSIGNED_INT, dl->index); - glDisableClientState(GL_NORMAL_ARRAY); + drawDispListElem( + true, true, false, + dl->verts, dl->nors, dl->nr, + dl->index, dl->parts, ob_wire_col); break; } dl = dl->next; } - glDisableClientState(GL_VERTEX_ARRAY); glFrontFace(GL_CCW); if (col != -1) { @@ -4574,7 +5427,7 @@ static void drawCurveDMWired(Object *ob) } /* return true when nothing was drawn */ -static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt) +static bool drawCurveDerivedMesh(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt) { Object *ob = base->object; DerivedMesh *dm = ob->derivedFinal; @@ -4588,8 +5441,8 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); if (dt > OB_WIRE && dm->getNumPolys(dm)) { - bool glsl = draw_glsl_material(scene, ob, v3d, dt); - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL); if (!glsl) dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind); @@ -4610,7 +5463,7 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, * Only called by #drawDispList * \return true when nothing was drawn */ -static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool drawDispList_nobackface(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; @@ -4640,10 +5493,10 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 if (!render_only) { /* when we have faces, only draw loose-wire */ if (has_faces) { - drawDispListwire_ex(lb, (1 << DL_SEGM)); + drawDispListwire_ex(lb, (1 << DL_SEGM), ob_wire_col); } else { - drawDispListwire(lb, ob->type); + drawDispListwire(lb, ob->type, ob_wire_col); } } @@ -4651,26 +5504,26 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 /* pass */ } else { - if (draw_glsl_material(scene, ob, v3d, dt)) { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); + if (draw_glsl_material(scene, sl, ob, v3d, dt)) { + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 1, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, true); GPU_end_object_materials(); } else { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 0, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, false); GPU_end_object_materials(); } if (cu->editnurb && cu->bevobj == NULL && cu->taperobj == NULL && cu->ext1 == 0.0f && cu->ext2 == 0.0f) { - cpack(0); - drawDispListwire(lb, ob->type); + unsigned char col[4] = {0, 0, 0, 0}; + drawDispListwire(lb, ob->type, col); } } index3_nors_incr = true; } else { if (!render_only || BKE_displist_has_faces(lb)) { - return drawDispListwire(lb, ob->type); + return drawDispListwire(lb, ob->type, ob_wire_col); } } break; @@ -4686,19 +5539,19 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 if (dl->nors == NULL) BKE_displist_normals_add(lb); - if (draw_glsl_material(scene, ob, v3d, dt)) { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); + if (draw_glsl_material(scene, sl, ob, v3d, dt)) { + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 1, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, true); GPU_end_object_materials(); } else { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 0, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, false); GPU_end_object_materials(); } } else { - return drawDispListwire(lb, ob->type); + return drawDispListwire(lb, ob->type, ob_wire_col); } break; case OB_MBALL: @@ -4711,19 +5564,19 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 if (solid) { - if (draw_glsl_material(scene, ob, v3d, dt)) { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); + if (draw_glsl_material(scene, sl, ob, v3d, dt)) { + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 1, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, true); GPU_end_object_materials(); } else { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 0, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, false); GPU_end_object_materials(); } } else { - return drawDispListwire(lb, ob->type); + return drawDispListwire(lb, ob->type, ob_wire_col); } } break; @@ -4731,8 +5584,9 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 return false; } -static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const char dt, const short dflag, const unsigned char ob_wire_col[4]) +static bool drawDispList( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { bool retval; @@ -4744,10 +5598,10 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba } #ifdef SEQUENCER_DAG_WORKAROUND - ensure_curve_cache(scene, base->object); + ensure_curve_cache(eval_ctx, scene, base->object); #endif - if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == false) { + if (drawCurveDerivedMesh(scene, sl, v3d, rv3d, base, dt) == false) { retval = false; } else { @@ -4763,7 +5617,7 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba glFrontFace(mode); - retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + retval = drawDispList_nobackface(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); if (mode != GL_CCW) { glFrontFace(GL_CCW); @@ -4778,16 +5632,63 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba } /* *********** drawing for particles ************* */ -static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int select) +/* stride : offset size in bytes + * col[4] : the color to use when *color is NULL, can be also NULL */ +static void draw_vertex_array(Gwn_PrimType prim_type, const float *vert, const float *nor, const float *color, int stride, int vert_ct, float col[4]) +{ + Gwn_VertFormat format = {0}; + unsigned int pos_id, nor_id, col_id; + pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + if (nor) nor_id = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + if (color) col_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vert_ct); + + if (stride == 0) { + GWN_vertbuf_attr_fill(vbo, pos_id, vert); + if (nor) GWN_vertbuf_attr_fill(vbo, nor_id, nor); + if (color) GWN_vertbuf_attr_fill(vbo, col_id, color); + } + else { + GWN_vertbuf_attr_fill_stride(vbo, pos_id, stride, vert); + if (nor) GWN_vertbuf_attr_fill_stride(vbo, nor_id, stride, nor); + if (color) GWN_vertbuf_attr_fill_stride(vbo, col_id, stride, color); + } + + Gwn_Batch *batch = GWN_batch_create_ex(prim_type, vbo, NULL, GWN_BATCH_OWNS_VBO); + if (nor && color) { + GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR); + GWN_batch_uniform_3f(batch, "light", 0.0f, 0.0f, 1.0f); + } + else if (nor) { + GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_3f(batch, "light", 0.0f, 0.0f, 1.0f); + if (col) GWN_batch_uniform_4fv(batch, "color", col); + } + else if (color) { + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_SMOOTH_COLOR); + } + else { + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + if (col) GWN_batch_uniform_4fv(batch, "color", col); + } + GWN_batch_draw(batch); + GWN_batch_discard(batch); +} + +static void draw_particle_arrays_new(int draw_as, int ob_dt, int select, + const float *vert, const float *nor, const float *color, + int totpoint, float col[4]) { /* draw created data arrays */ switch (draw_as) { case PART_DRAW_AXIS: case PART_DRAW_CROSS: - glDrawArrays(GL_LINES, 0, 6 * totpoint); + draw_vertex_array(GWN_PRIM_LINES, vert, nor, color, 0, 6 * totpoint, col); break; case PART_DRAW_LINE: - glDrawArrays(GL_LINES, 0, 2 * totpoint); + draw_vertex_array(GWN_PRIM_LINES, vert, nor, color, 0, 2 * totpoint, col); break; case PART_DRAW_BB: if (ob_dt <= OB_WIRE || select) @@ -4795,15 +5696,16 @@ static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int selec else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glDrawArrays(GL_QUADS, 0, 4 * totpoint); + draw_vertex_array(GWN_PRIM_TRIS, vert, nor, color, 0, 6 * totpoint, col); break; default: - glDrawArrays(GL_POINTS, 0, totpoint); + draw_vertex_array(GWN_PRIM_POINTS, vert, nor, color, 0, totpoint, col); break; } } static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize, - float imat[4][4], const float draw_line[2], ParticleBillboardData *bb, ParticleDrawData *pdd) + float imat[4][4], const float draw_line[2], ParticleBillboardData *bb, ParticleDrawData *pdd, + unsigned int pos) { float vec[3], vec2[3]; float *vd = NULL; @@ -4913,24 +5815,19 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix } case PART_DRAW_CIRC: { - drawcircball(GL_LINE_LOOP, state->co, pixsize, imat); + imm_drawcircball(state->co, pixsize, imat, pos); break; } case PART_DRAW_BB: { float xvec[3], yvec[3], zvec[3], bb_center[3]; - if (cd) { - cd[0] = cd[3] = cd[6] = cd[9] = ma_col[0]; - cd[1] = cd[4] = cd[7] = cd[10] = ma_col[1]; - cd[2] = cd[5] = cd[8] = cd[11] = ma_col[2]; - pdd->cd += 12; - } copy_v3_v3(bb->vec, state->co); copy_v3_v3(bb->vel, state->vel); psys_make_billboard(bb, xvec, yvec, zvec, bb_center); - + + /* First tri */ add_v3_v3v3(pdd->vd, bb_center, xvec); add_v3_v3(pdd->vd, yvec); pdd->vd += 3; @@ -4940,13 +5837,24 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix sub_v3_v3v3(pdd->vd, bb_center, xvec); sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3; + /* Second tri */ + add_v3_v3v3(pdd->vd, bb_center, xvec); + add_v3_v3(pdd->vd, yvec); pdd->vd += 3; + + sub_v3_v3v3(pdd->vd, bb_center, xvec); + sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3; + add_v3_v3v3(pdd->vd, bb_center, xvec); sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3; - copy_v3_v3(pdd->nd, zvec); pdd->nd += 3; - copy_v3_v3(pdd->nd, zvec); pdd->nd += 3; - copy_v3_v3(pdd->nd, zvec); pdd->nd += 3; - copy_v3_v3(pdd->nd, zvec); pdd->nd += 3; + if (cd) { + for (int i = 0; i < 6; i++, cd += 3, pdd->cd += 3) { + copy_v3_v3(cd, ma_col); + } + } + for (int i = 0; i < 6; i++, pdd->nd += 3) { + copy_v3_v3(pdd->nd, zvec); + } break; } } @@ -4954,7 +5862,8 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d, ParticleKey *state, int draw_as, float imat[4][4], ParticleBillboardData *bb, ParticleDrawData *pdd, - const float ct, const float pa_size, const float r_tilt, const float pixsize_scale) + const float ct, const float pa_size, const float r_tilt, const float pixsize_scale, + unsigned int pos) { ParticleSettings *part = psys->part; float pixsize; @@ -4985,7 +5894,7 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d, pixsize = ED_view3d_pixel_size(rv3d, state->co) * pixsize_scale; - draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd); + draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd, pos); } /* unified drawing of all new particle systems draw types except dupli ob & group * mostly tries to use vertex arrays for speed @@ -4998,9 +5907,10 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d, * 6. draw the arrays * 7. clean up */ -static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d, - Base *base, ParticleSystem *psys, - const char ob_dt, const short dflag) +static void draw_new_particle_system( + const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d, + Base *base, ParticleSystem *psys, + const char ob_dt, const short dflag) { Object *ob = base->object; ParticleEditSettings *pset = PE_settings(scene); @@ -5018,10 +5928,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv float cfra; float ma_col[3] = {0.0f, 0.0f, 0.0f}; int a, totpart, totpoint = 0, totve = 0, drawn, draw_as, totchild = 0; - bool select = (ob->flag & SELECT) != 0, create_cdata = false, need_v = false; + bool select = (base->flag & BASE_SELECTED) != 0, create_cdata = false, need_v = false; GLint polygonmode[2]; char numstr[32]; unsigned char tcol[4] = {0, 0, 0, 255}; + unsigned int pos; /* 1. */ if (part == NULL || !psys_check_enabled(ob, psys, G.is_rendering)) @@ -5030,7 +5941,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if (pars == NULL) return; /* don't draw normal paths in edit mode */ - if (psys_in_edit_mode(scene, psys) && (pset->flag & PE_DRAW_PART) == 0) + if (psys_in_edit_mode(eval_ctx->scene_layer, psys) && (pset->flag & PE_DRAW_PART) == 0) return; if (part->draw_as == PART_DRAW_REND) @@ -5048,6 +5959,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv curvemapping_changed_all(psys->part->roughcurve); /* 2. */ + sim.eval_ctx = eval_ctx; sim.scene = scene; sim.ob = ob; sim.psys = psys; @@ -5083,16 +5995,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv copy_v3_v3(ma_col, &ma->r); } - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(tcol); - } - timestep = psys_get_timestep(&sim); - if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) { + if ((ob->flag & OB_FROMGROUP) != 0) { float mat[4][4]; mul_m4_m4m4(mat, ob->obmat, psys->imat); - glMultMatrixf(mat); + gpuMultMatrix(mat); } /* needed for text display */ @@ -5212,7 +6120,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv tot_vec_size *= 2; break; case PART_DRAW_BB: - tot_vec_size *= 4; + tot_vec_size *= 6; /* New OGL only understands tris, no choice here. */ create_ndata = 1; break; } @@ -5266,6 +6174,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv totpoint = pdd->totpoint; /* draw data is up to date */ } else { + if ((draw_as == PART_DRAW_CIRC) || (part->draw & PART_DRAW_SIZE)) { + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + imm_cpack(0xFFFFFF); + } for (a = 0, pa = pars; a < totpart + totchild; a++, pa++) { /* setup per particle individual stuff */ if (a < totpart) { @@ -5336,7 +6249,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv draw_particle_data(psys, rv3d, &state, draw_as, imat, &bb, psys->pdd, - ct, pa_size, r_tilt, pixsize_scale); + ct, pa_size, r_tilt, pixsize_scale, pos); totpoint++; drawn = 1; @@ -5348,7 +6261,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv draw_particle_data(psys, rv3d, &state, draw_as, imat, &bb, psys->pdd, - pa_time, pa_size, r_tilt, pixsize_scale); + pa_time, pa_size, r_tilt, pixsize_scale, pos); totpoint++; drawn = 1; @@ -5370,7 +6283,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if (part->draw & PART_DRAW_SIZE) { setlinestyle(3); - drawcircball(GL_LINE_LOOP, state.co, pa_size, imat); + imm_drawcircball(state.co, pa_size, imat, pos); setlinestyle(0); } @@ -5407,31 +6320,19 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv } } } + if ((draw_as == PART_DRAW_CIRC) || (part->draw & PART_DRAW_SIZE)) { + immUnbindProgram(); + } } } /* 6. */ glGetIntegerv(GL_POLYGON_MODE, polygonmode); - glEnableClientState(GL_VERTEX_ARRAY); if (draw_as == PART_DRAW_PATH) { ParticleCacheKey **cache, *path; float *cdata2 = NULL; - /* setup gl flags */ - if (1) { //ob_dt > OB_WIRE) { - glEnableClientState(GL_NORMAL_ARRAY); - - if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (part->draw_col == PART_DRAW_COL_MAT) - glEnableClientState(GL_COLOR_ARRAY); - } - - // XXX test - GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f); - GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); - } - if (totchild && (part->draw & PART_DRAW_PARENT) == 0) totpart = 0; else if (psys->pathcache == NULL) @@ -5442,41 +6343,28 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { path = cache[a]; if (path->segments > 0) { - glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co); - - if (1) { //ob_dt > OB_WIRE) { - glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel); - if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (part->draw_col == PART_DRAW_COL_MAT) { - glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col); - } - } + if (((dflag & DRAW_CONSTCOLOR) == 0) && (part->draw_col == PART_DRAW_COL_MAT)) { + draw_vertex_array(GWN_PRIM_LINE_STRIP, path->co, path->vel, path->col, sizeof(ParticleCacheKey), path->segments + 1, NULL); + } + else { + float color[4]; + rgba_uchar_to_float(color, tcol); + draw_vertex_array(GWN_PRIM_LINE_STRIP, path->co, path->vel, NULL, sizeof(ParticleCacheKey), path->segments + 1, color); } - - glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1); } } if (part->type == PART_HAIR) { if (part->draw & PART_DRAW_GUIDE_HAIRS) { DerivedMesh *hair_dm = psys->hair_out_dm; - - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - + for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { if (pa->totkey > 1) { HairKey *hkey = pa->hair; - glVertexPointer(3, GL_FLOAT, sizeof(HairKey), hkey->world_co); - -#if 0 /* XXX use proper theme color here */ - UI_ThemeColor(TH_NORMAL); -#else - glColor3f(0.58f, 0.67f, 1.0f); -#endif - - glDrawArrays(GL_LINE_STRIP, 0, pa->totkey); + /* XXX use proper theme color here */ + float color[4] = {0.58f, 0.67f, 1.0f, 1.0f}; + draw_vertex_array(GWN_PRIM_LINE_STRIP, hkey->world_co, NULL, NULL, sizeof(HairKey), pa->totkey, color); } } @@ -5484,30 +6372,36 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv MVert *mvert = hair_dm->getVertArray(hair_dm); int i; - glColor3f(0.9f, 0.4f, 0.4f); - - glBegin(GL_LINES); + unsigned int pos_id = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3f(0.9f, 0.4f, 0.4f); + + unsigned int count = 0; for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { - for (i = 1; i < pa->totkey; ++i) { - float v1[3], v2[3]; - - copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co); - copy_v3_v3(v2, mvert[pa->hair_index + i].co); - - mul_m4_v3(ob->obmat, v1); - mul_m4_v3(ob->obmat, v2); - - glVertex3fv(v1); - glVertex3fv(v2); + count += MAX2(pa->totkey - 1, 0); + } + + if (count > 0) { + immBegin(GWN_PRIM_LINES, count * 2); + for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { + for (i = 1; i < pa->totkey; ++i) { + float v1[3], v2[3]; + + copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co); + copy_v3_v3(v2, mvert[pa->hair_index + i].co); + + mul_m4_v3(ob->obmat, v1); + mul_m4_v3(ob->obmat, v2); + + immVertex3fv(pos_id, v1); + immVertex3fv(pos_id, v2); + } } + immEnd(); } - glEnd(); + + immUnbindProgram(); } - - glEnableClientState(GL_NORMAL_ARRAY); - if ((dflag & DRAW_CONSTCOLOR) == 0) - if (part->draw_col == PART_DRAW_COL_MAT) - glEnableClientState(GL_COLOR_ARRAY); } if (part->draw & PART_DRAW_HAIR_GRID) { @@ -5518,64 +6412,69 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv int *res = clmd->hair_grid_res; int i; - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - + unsigned int pos_id = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); if (select) - UI_ThemeColor(TH_ACTIVE); + immUniformThemeColor(TH_ACTIVE); else - UI_ThemeColor(TH_WIRE); - glBegin(GL_LINES); - glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmin[2]); - glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmin[2]); - glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmin[2]); - glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmin[2]); + immUniformThemeColor(TH_WIRE); + + immBegin(GWN_PRIM_LINES, 24); + immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]); + immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]); + immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]); + immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]); - glVertex3f(gmin[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmin[1], gmax[2]); - glVertex3f(gmax[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmax[1], gmax[2]); - glVertex3f(gmax[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmax[1], gmax[2]); - glVertex3f(gmin[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmin[1], gmax[2]); + immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]); + immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]); + immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]); + immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]); - glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmax[2]); - glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmax[2]); - glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmax[2]); - glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmax[2]); - glEnd(); + immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]); + immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]); + immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]); + immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]); + immEnd(); if (select) - UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -100); + immUniformThemeColorShadeAlpha(TH_ACTIVE, 0, -100); else - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -100); - glEnable(GL_BLEND); - glBegin(GL_LINES); - for (i = 1; i < res[0] - 1; ++i) { - float f = interpf(gmax[0], gmin[0], (float)i / (float)(res[0] - 1)); - glVertex3f(f, gmin[1], gmin[2]); glVertex3f(f, gmax[1], gmin[2]); - glVertex3f(f, gmax[1], gmin[2]); glVertex3f(f, gmax[1], gmax[2]); - glVertex3f(f, gmax[1], gmax[2]); glVertex3f(f, gmin[1], gmax[2]); - glVertex3f(f, gmin[1], gmax[2]); glVertex3f(f, gmin[1], gmin[2]); - } - for (i = 1; i < res[1] - 1; ++i) { - float f = interpf(gmax[1], gmin[1], (float)i / (float)(res[1] - 1)); - glVertex3f(gmin[0], f, gmin[2]); glVertex3f(gmax[0], f, gmin[2]); - glVertex3f(gmax[0], f, gmin[2]); glVertex3f(gmax[0], f, gmax[2]); - glVertex3f(gmax[0], f, gmax[2]); glVertex3f(gmin[0], f, gmax[2]); - glVertex3f(gmin[0], f, gmax[2]); glVertex3f(gmin[0], f, gmin[2]); - } - for (i = 1; i < res[2] - 1; ++i) { - float f = interpf(gmax[2], gmin[2], (float)i / (float)(res[2] - 1)); - glVertex3f(gmin[0], gmin[1], f); glVertex3f(gmax[0], gmin[1], f); - glVertex3f(gmax[0], gmin[1], f); glVertex3f(gmax[0], gmax[1], f); - glVertex3f(gmax[0], gmax[1], f); glVertex3f(gmin[0], gmax[1], f); - glVertex3f(gmin[0], gmax[1], f); glVertex3f(gmin[0], gmin[1], f); + immUniformThemeColorShadeAlpha(TH_WIRE, 0, -100); + + int count = 0; + count += MAX2(0, res[0] - 2) * 8; + count += MAX2(0, res[1] - 2) * 8; + count += MAX2(0, res[2] - 2) * 8; + + if (count >= 2) { + glEnable(GL_BLEND); + immBegin(GWN_PRIM_LINES, count); + for (i = 1; i < res[0] - 1; ++i) { + float f = interpf(gmax[0], gmin[0], (float)i / (float)(res[0] - 1)); + immVertex3f(pos_id, f, gmin[1], gmin[2]); immVertex3f(pos_id, f, gmax[1], gmin[2]); + immVertex3f(pos_id, f, gmax[1], gmin[2]); immVertex3f(pos_id, f, gmax[1], gmax[2]); + immVertex3f(pos_id, f, gmax[1], gmax[2]); immVertex3f(pos_id, f, gmin[1], gmax[2]); + immVertex3f(pos_id, f, gmin[1], gmax[2]); immVertex3f(pos_id, f, gmin[1], gmin[2]); + } + for (i = 1; i < res[1] - 1; ++i) { + float f = interpf(gmax[1], gmin[1], (float)i / (float)(res[1] - 1)); + immVertex3f(pos_id, gmin[0], f, gmin[2]); immVertex3f(pos_id, gmax[0], f, gmin[2]); + immVertex3f(pos_id, gmax[0], f, gmin[2]); immVertex3f(pos_id, gmax[0], f, gmax[2]); + immVertex3f(pos_id, gmax[0], f, gmax[2]); immVertex3f(pos_id, gmin[0], f, gmax[2]); + immVertex3f(pos_id, gmin[0], f, gmax[2]); immVertex3f(pos_id, gmin[0], f, gmin[2]); + } + for (i = 1; i < res[2] - 1; ++i) { + float f = interpf(gmax[2], gmin[2], (float)i / (float)(res[2] - 1)); + immVertex3f(pos_id, gmin[0], gmin[1], f); immVertex3f(pos_id, gmax[0], gmin[1], f); + immVertex3f(pos_id, gmax[0], gmin[1], f); immVertex3f(pos_id, gmax[0], gmax[1], f); + immVertex3f(pos_id, gmax[0], gmax[1], f); immVertex3f(pos_id, gmin[0], gmax[1], f); + immVertex3f(pos_id, gmin[0], gmax[1], f); immVertex3f(pos_id, gmin[0], gmin[1], f); + } + immEnd(); + glDisable(GL_BLEND); } - glEnd(); - glDisable(GL_BLEND); - - glEnableClientState(GL_NORMAL_ARRAY); - if ((dflag & DRAW_CONSTCOLOR) == 0) - if (part->draw_col == PART_DRAW_COL_MAT) - glEnableClientState(GL_COLOR_ARRAY); + + immUnbindProgram(); } } } @@ -5584,27 +6483,17 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv cache = psys->childcache; for (a = 0; a < totchild; a++) { path = cache[a]; - glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co); - if (1) { //ob_dt > OB_WIRE) { - glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel); - if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (part->draw_col == PART_DRAW_COL_MAT) { - glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col); - } - } + if (((dflag & DRAW_CONSTCOLOR) == 0) && (part->draw_col == PART_DRAW_COL_MAT)) { + draw_vertex_array(GWN_PRIM_LINE_STRIP, path->co, path->vel, path->col, sizeof(ParticleCacheKey), path->segments + 1, NULL); + } + else { + float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + draw_vertex_array(GWN_PRIM_LINE_STRIP, path->co, path->vel, NULL, sizeof(ParticleCacheKey), path->segments + 1, color); } - - glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1); } /* restore & clean up */ - if (1) { //ob_dt > OB_WIRE) { - if (part->draw_col == PART_DRAW_COL_MAT) - glDisableClientState(GL_COLOR_ARRAY); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } - if (cdata2) { MEM_freeN(cdata2); cdata2 = NULL; @@ -5624,19 +6513,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv } } else if (pdd && ELEM(draw_as, 0, PART_DRAW_CIRC) == 0) { - glDisableClientState(GL_COLOR_ARRAY); - /* enable point data array */ if (pdd->vdata) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, pdd->vdata); - } - else - glDisableClientState(GL_VERTEX_ARRAY); - - if ((dflag & DRAW_CONSTCOLOR) == 0) { if (select) { - UI_ThemeColor(TH_ACTIVE); + float color[4]; + UI_GetThemeColor4fv(TH_ACTIVE, color); if (part->draw_size) glPointSize(part->draw_size + 2); @@ -5645,48 +6526,39 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glLineWidth(3.0); - draw_particle_arrays(draw_as, totpoint, ob_dt, 1); + draw_particle_arrays_new(draw_as, ob_dt, 1, pdd->vdata, NULL, NULL, totpoint, color); } - /* restore from select */ - glColor3fv(ma_col); - } - - glPointSize(part->draw_size ? part->draw_size : 2.0); - glLineWidth(1.0); + glPointSize(part->draw_size ? part->draw_size : 2.0); + glLineWidth(1.0); - /* enable other data arrays */ - /* billboards are drawn this way */ - if (pdd->ndata && ob_dt > OB_WIRE) { - glEnableClientState(GL_NORMAL_ARRAY); - glNormalPointer(GL_FLOAT, 0, pdd->ndata); - GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f); - GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); - } - - if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (pdd->cdata) { - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(3, GL_FLOAT, 0, pdd->cdata); +#if 0 + /* enable other data arrays */ + /* billboards are drawn this way */ + if (pdd->ndata && ob_dt > OB_WIRE) { + GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f); + GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); } + if ((dflag & DRAW_CONSTCOLOR) == 0) { + if (pdd->cdata) { + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(3, GL_FLOAT, 0, pdd->cdata); + } + } +#endif + + draw_particle_arrays_new(draw_as, ob_dt, 0, pdd->vdata, pdd->ndata, pdd->cdata, totpoint, NULL); } - draw_particle_arrays(draw_as, totpoint, ob_dt, 0); pdd->flag |= PARTICLE_DRAW_DATA_UPDATED; pdd->totpoint = totpoint; } if (pdd && pdd->vedata) { - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glDisableClientState(GL_COLOR_ARRAY); - cpack(0xC0C0C0); - } - - glVertexPointer(3, GL_FLOAT, 0, pdd->vedata); - - glDrawArrays(GL_LINES, 0, 2 * totve); + float color[4] = {0.75f, 0.75f, 0.75f, 1.0f}; + draw_vertex_array(GWN_PRIM_LINES, pdd->vedata, NULL, NULL, 0, 2 * totve, color); } glPolygonMode(GL_FRONT, polygonmode[0]); @@ -5695,9 +6567,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv /* 7. */ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); if (states) MEM_freeN(states); @@ -5720,32 +6589,28 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pdd->ma_col = NULL; } - if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) { - glLoadMatrixf(rv3d->viewmat); + if ((ob->flag & OB_FROMGROUP) != 0) { + gpuLoadMatrix(rv3d->viewmat); } } -static void draw_update_ptcache_edit(Scene *scene, Object *ob, PTCacheEdit *edit) +static void draw_update_ptcache_edit( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, Object *ob, PTCacheEdit *edit) { if (edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED) - PE_update_object(scene, ob, 0); + PE_update_object(eval_ctx, scene, sl, ob, 0); /* create path and child path cache if it doesn't exist already */ - if (edit->pathcache == NULL) - psys_cache_edit_paths(scene, ob, edit, CFRA, G.is_rendering); + if (edit->pathcache == NULL) { + psys_cache_edit_paths(eval_ctx, scene, ob, edit, CFRA, G.is_rendering); + } } static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) { - ParticleCacheKey **cache, *path, *pkey; - PTCacheEditPoint *point; - PTCacheEditKey *key; ParticleEditSettings *pset = PE_settings(scene); - int i, k, totpoint = edit->totpoint, timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : 0; - int totkeys = 1; - float sel_col[3]; - float nosel_col[3]; - float *pathcol = NULL, *pcol; + const int totpoint = edit->totpoint; + const bool timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : false; if (edit->pathcache == NULL) return; @@ -5757,50 +6622,71 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) glDisable(GL_DEPTH_TEST); /* get selection theme colors */ + float sel_col[3], nosel_col[3]; UI_GetThemeColor3fv(TH_VERTEX_SELECT, sel_col); UI_GetThemeColor3fv(TH_VERTEX, nosel_col); /* draw paths */ - totkeys = (*edit->pathcache)->segments + 1; + const int totkeys = (*edit->pathcache)->segments + 1; glEnable(GL_BLEND); - pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data"); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); + float *pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data"); if (pset->brushtype == PE_BRUSH_WEIGHT) glLineWidth(2.0f); - cache = edit->pathcache; + ParticleCacheKey **cache = edit->pathcache; + PTCacheEditPoint *point; + int i; + for (i = 0, point = edit->points; i < totpoint; i++, point++) { - path = cache[i]; - glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co); + ParticleCacheKey *path = cache[i]; + + Gwn_VertFormat format = {0}; + unsigned int pos_id, col_id, col_comp; + + col_comp = ((point->flag & PEP_HIDE) || timed) ? 4 : 3; + + pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + col_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, col_comp, GWN_FETCH_FLOAT); + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, path->segments + 1); + + GWN_vertbuf_attr_fill_stride(vbo, pos_id, sizeof(ParticleCacheKey), path->co); + + float *pcol = pathcol; if (point->flag & PEP_HIDE) { - for (k = 0, pcol = pathcol; k < totkeys; k++, pcol += 4) { + for (int k = 0; k < totkeys; k++, pcol += 4) { copy_v3_v3(pcol, path->col); pcol[3] = 0.25f; } - glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol); + GWN_vertbuf_attr_fill(vbo, col_id, pathcol); } else if (timed) { - for (k = 0, pcol = pathcol, pkey = path; k < totkeys; k++, pkey++, pcol += 4) { + ParticleCacheKey *pkey = path; + for (int k = 0; k < totkeys; k++, pkey++, pcol += 4) { copy_v3_v3(pcol, pkey->col); pcol[3] = 1.0f - fabsf((float)(CFRA) -pkey->time) / (float)pset->fade_frames; } - glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol); + GWN_vertbuf_attr_fill(vbo, col_id, pathcol); + } + else { + /* FIXME: shader wants 4 color components but the cache only contains ParticleCacheKey + * So alpha is random */ + GWN_vertbuf_attr_fill_stride(vbo, col_id, sizeof(ParticleCacheKey), path->col); } - else - glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col); - glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1); + Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_LINE_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_SMOOTH_COLOR); + GWN_batch_draw(batch); + GWN_batch_discard(batch); } - if (pathcol) { MEM_freeN(pathcol); pathcol = pcol = NULL; } - + if (pathcol) { MEM_freeN(pathcol); pathcol = NULL; } /* draw edit vertices */ if (pset->selectmode != SCE_SELECT_PATH) { @@ -5811,6 +6697,10 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) float *cd = NULL, *cdata = NULL; int totkeys_visible = 0; + Gwn_VertFormat format = {0}; + unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int col_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, (timed ? 4 : 3), GWN_FETCH_FLOAT); + for (i = 0, point = edit->points; i < totpoint; i++, point++) if (!(point->flag & PEP_HIDE)) totkeys_visible += point->totkey; @@ -5825,7 +6715,8 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) if (point->flag & PEP_HIDE) continue; - for (k = 0, key = point->keys; k < point->totkey; k++, key++) { + PTCacheEditKey *key = point->keys; + for (int k = 0; k < point->totkey; k++, key++) { if (pd) { copy_v3_v3(pd, key->co); pd += 3; @@ -5850,14 +6741,20 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) if (point->flag & PEP_HIDE || point->totkey == 0) continue; + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, point->totkey); + if (point->keys->flag & PEK_USE_WCO) - glVertexPointer(3, GL_FLOAT, sizeof(PTCacheEditKey), point->keys->world_co); + GWN_vertbuf_attr_fill_stride(vbo, pos_id, sizeof(PTCacheEditKey), point->keys->world_co); else - glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), pd); + GWN_vertbuf_attr_fill(vbo, pos_id, pd); - glColorPointer((timed ? 4 : 3), GL_FLOAT, (timed ? 4 : 3) * sizeof(float), cd); + GWN_vertbuf_attr_fill(vbo, col_id, cd); - glDrawArrays(GL_POINTS, 0, point->totkey); + Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_SMOOTH_COLOR); + GWN_batch_draw(batch); + GWN_batch_discard(batch); pd += pd ? 3 * point->totkey : 0; cd += (timed ? 4 : 3) * point->totkey; @@ -5866,23 +6763,30 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) if (cdata) { MEM_freeN(cdata); cd = cdata = NULL; } } else if (pset->selectmode == SCE_SELECT_END) { - glBegin(GL_POINTS); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int col_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + immBeginAtMost(GWN_PRIM_POINTS, totpoint); for (i = 0, point = edit->points; i < totpoint; i++, point++) { if ((point->flag & PEP_HIDE) == 0 && point->totkey) { - key = point->keys + point->totkey - 1; - glColor3fv((key->flag & PEK_SELECT) ? sel_col : nosel_col); + PTCacheEditKey *key = point->keys + point->totkey - 1; + if ((key->flag & PEK_SELECT) != 0) { + immAttrib3fv(col_id, sel_col); + } + else { + immAttrib3fv(col_id, nosel_col); + } /* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/ - glVertex3fv((key->flag & PEK_USE_WCO) ? key->world_co : key->co); + immVertex3fv(pos_id, (key->flag & PEK_USE_WCO) ? key->world_co : key->co); } } - glEnd(); + immEnd(); + immUnbindProgram(); } } glDisable(GL_BLEND); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } @@ -5895,130 +6799,137 @@ static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, flo float tw = itw * drw_size; float th = ith * drw_size; - glBegin(GL_LINES); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + immBegin(GWN_PRIM_LINES, 30); - glColor4ub(0x7F, 0x00, 0x00, 155); + immAttrib4ub(col, 0x7F, 0x00, 0x00, 155); root[1] = root[2] = 0.0f; root[0] = -drw_size; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); + immVertex3fv(pos, root); tip[1] = tip[2] = 0.0f; tip[0] = drw_size; mul_m3_v3(tr, tip); add_v3_v3(tip, com); - glVertex3fv(tip); + immVertex3fv(pos, tip); root[1] = 0.0f; root[2] = tw; root[0] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[1] = 0.0f; root[2] = -tw; root[0] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[1] = tw; root[2] = 0.0f; root[0] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[1] = -tw; root[2] = 0.0f; root[0] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); - glColor4ub(0x00, 0x7F, 0x00, 155); + immAttrib4ub(col, 0x00, 0x7F, 0x00, 155); root[0] = root[2] = 0.0f; root[1] = -drw_size; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); + immVertex3fv(pos, root); tip[0] = tip[2] = 0.0f; tip[1] = drw_size; mul_m3_v3(tr, tip); add_v3_v3(tip, com); - glVertex3fv(tip); + immVertex3fv(pos, tip); root[0] = 0.0f; root[2] = tw; root[1] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = 0.0f; root[2] = -tw; root[1] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = tw; root[2] = 0.0f; root[1] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = -tw; root[2] = 0.0f; root[1] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); - glColor4ub(0x00, 0x00, 0x7F, 155); + immAttrib4ub(col, 0x00, 0x00, 0x7F, 155); root[0] = root[1] = 0.0f; root[2] = -drw_size; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); + immVertex3fv(pos, root); tip[0] = tip[1] = 0.0f; tip[2] = drw_size; mul_m3_v3(tr, tip); add_v3_v3(tip, com); - glVertex3fv(tip); + immVertex3fv(pos, tip); root[0] = 0.0f; root[1] = tw; root[2] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = 0.0f; root[1] = -tw; root[2] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = tw; root[1] = 0.0f; root[2] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = -tw; root[1] = 0.0f; root[2] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); - glEnd(); + immEnd(); + + immUnbindProgram(); } /* place to add drawers */ @@ -6027,7 +6938,7 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles) { if (nu->hide || hide_handles) return; - if (nu->type == CU_BEZIER) { + if (nu->type == CU_BEZIER && nu->pntsu > 0) { const float *fp; @@ -6040,9 +6951,14 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles) UI_GetThemeColor3ubv(basecol + a, handle_cols[a]); } + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + glLineWidth(1.0f); - glBegin(GL_LINES); + immBeginAtMost(GWN_PRIM_LINES, nu->pntsu * 4); BezTriple *bezt = nu->bezt; int a = nu->pntsu; @@ -6051,33 +6967,35 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles) if ((bezt->f2 & SELECT) == sel) { fp = bezt->vec[0]; - glColor3ubv(handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); - glVertex3fv(fp); - glVertex3fv(fp + 3); + immAttrib3ubv(col, handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); + immVertex3fv(pos, fp); + immVertex3fv(pos, fp + 3); - glColor3ubv(handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]); - glVertex3fv(fp + 3); - glVertex3fv(fp + 6); + immAttrib3ubv(col, handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]); + immVertex3fv(pos, fp + 3); + immVertex3fv(pos, fp + 6); } else if ((bezt->f1 & SELECT) == sel) { fp = bezt->vec[0]; - glColor3ubv(handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); - glVertex3fv(fp); - glVertex3fv(fp + 3); + immAttrib3ubv(col, handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); + immVertex3fv(pos, fp); + immVertex3fv(pos, fp + 3); } else if ((bezt->f3 & SELECT) == sel) { fp = bezt->vec[1]; - glColor3ubv(handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]); - glVertex3fv(fp); - glVertex3fv(fp + 3); + immAttrib3ubv(col, handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]); + immVertex3fv(pos, fp); + immVertex3fv(pos, fp + 3); } } bezt++; } - glEnd(); + immEnd(); + + immUnbindProgram(); #undef TH_HANDLE_COL_TOT @@ -6088,153 +7006,196 @@ static void drawhandlesN_active(Nurb *nu) { if (nu->hide) return; - UI_ThemeColor(TH_ACTIVE_SPLINE); - glLineWidth(2); - - glBegin(GL_LINES); + if (nu->type == CU_BEZIER && nu->pntsu > 0) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_ACTIVE_SPLINE); + glLineWidth(2.0f); - if (nu->type == CU_BEZIER) { + immBeginAtMost(GWN_PRIM_LINES, nu->pntsu * 4); BezTriple *bezt = nu->bezt; int a = nu->pntsu; while (a--) { if (bezt->hide == 0) { const float *fp = bezt->vec[0]; - glVertex3fv(fp); - glVertex3fv(fp + 3); + immVertex3fv(pos, fp); + immVertex3fv(pos, fp + 3); - glVertex3fv(fp + 3); - glVertex3fv(fp + 6); + immVertex3fv(pos, fp + 3); + immVertex3fv(pos, fp + 6); } bezt++; } + immEnd(); + immUnbindProgram(); } - glEnd(); - - glColor3ub(0, 0, 0); } -static void drawvertsN(Nurb *nu, const char sel, const bool hide_handles, const void *vert) +static void drawvertsN(const Nurb *nurb, const bool hide_handles, const void *vert) { - if (nu->hide) return; + const Nurb *nu; + + // just quick guesstimate of how many verts to draw + int count = 0; + for (nu = nurb; nu; nu = nu->next) { + if (!nu->hide) { + if (nu->type == CU_BEZIER) { + count += nu->pntsu * 3; + } + else { + count += nu->pntsu * nu->pntsv; + } + } + } + if (count == 0) return; - const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); - UI_ThemeColor(color); + unsigned char vert_color[3]; + unsigned char vert_color_select[3]; + unsigned char vert_color_active[3]; + UI_GetThemeColor3ubv(TH_VERTEX, vert_color); + UI_GetThemeColor3ubv(TH_VERTEX_SELECT, vert_color_select); + UI_GetThemeColor3ubv(TH_ACTIVE_VERT, vert_color_active); glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + immBeginAtMost(GWN_PRIM_POINTS, count); - glBegin(GL_POINTS); - - if (nu->type == CU_BEZIER) { + for (nu = nurb; nu; nu = nu->next) { - BezTriple *bezt = nu->bezt; - int a = nu->pntsu; - while (a--) { - if (bezt->hide == 0) { - if (sel == 1 && bezt == vert) { - UI_ThemeColor(TH_ACTIVE_VERT); + if (nu->hide) continue; - if (bezt->f2 & SELECT) glVertex3fv(bezt->vec[1]); - if (!hide_handles) { - if (bezt->f1 & SELECT) glVertex3fv(bezt->vec[0]); - if (bezt->f3 & SELECT) glVertex3fv(bezt->vec[2]); - } + if (nu->type == CU_BEZIER) { - UI_ThemeColor(color); - } - else if (hide_handles) { - if ((bezt->f2 & SELECT) == sel) glVertex3fv(bezt->vec[1]); - } - else { - if ((bezt->f1 & SELECT) == sel) glVertex3fv(bezt->vec[0]); - if ((bezt->f2 & SELECT) == sel) glVertex3fv(bezt->vec[1]); - if ((bezt->f3 & SELECT) == sel) glVertex3fv(bezt->vec[2]); + const BezTriple *bezt = nu->bezt; + int a = nu->pntsu; + while (a--) { + if (bezt->hide == 0) { + if (bezt == vert) { + immAttrib3ubv(color, bezt->f2 & SELECT ? vert_color_active : vert_color); + immVertex3fv(pos, bezt->vec[1]); + if (!hide_handles) { + immAttrib3ubv(color, bezt->f1 & SELECT ? vert_color_active : vert_color); + immVertex3fv(pos, bezt->vec[0]); + immAttrib3ubv(color, bezt->f3 & SELECT ? vert_color_active : vert_color); + immVertex3fv(pos, bezt->vec[2]); + } + } + else { + immAttrib3ubv(color, bezt->f2 & SELECT ? vert_color_select : vert_color); + immVertex3fv(pos, bezt->vec[1]); + if (!hide_handles) { + immAttrib3ubv(color, bezt->f1 & SELECT ? vert_color_select : vert_color); + immVertex3fv(pos, bezt->vec[0]); + immAttrib3ubv(color, bezt->f3 & SELECT ? vert_color_select : vert_color); + immVertex3fv(pos, bezt->vec[2]); + } + } } + bezt++; } - bezt++; } - } - else { - BPoint *bp = nu->bp; - int a = nu->pntsu * nu->pntsv; - while (a--) { - if (bp->hide == 0) { - if (bp == vert) { - UI_ThemeColor(TH_ACTIVE_VERT); - glVertex3fv(bp->vec); - UI_ThemeColor(color); - } - else { - if ((bp->f1 & SELECT) == sel) glVertex3fv(bp->vec); + else { + const BPoint *bp = nu->bp; + int a = nu->pntsu * nu->pntsv; + while (a--) { + if (bp->hide == 0) { + if (bp == vert) { + immAttrib3ubv(color, vert_color_active); + } + else { + immAttrib3ubv(color, bp->f1 & SELECT ? vert_color_select : vert_color); + } + immVertex3fv(pos, bp->vec); } + bp++; } - bp++; } } - - glEnd(); + + immEnd(); + immUnbindProgram(); } static void editnurb_draw_active_poly(Nurb *nu) { - UI_ThemeColor(TH_ACTIVE_SPLINE); - glLineWidth(2); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_ACTIVE_SPLINE); + + glLineWidth(2.0f); BPoint *bp = nu->bp; for (int b = 0; b < nu->pntsv; b++) { - if (nu->flagu & 1) glBegin(GL_LINE_LOOP); - else glBegin(GL_LINE_STRIP); + if (nu->pntsu >= 2) { + if (nu->flagu & 1) immBegin(GWN_PRIM_LINE_LOOP, nu->pntsu); + else immBegin(GWN_PRIM_LINE_STRIP, nu->pntsu); - for (int a = 0; a < nu->pntsu; a++, bp++) { - glVertex3fv(bp->vec); - } + for (int a = 0; a < nu->pntsu; a++, bp++) { + immVertex3fv(pos, bp->vec); + } - glEnd(); + immEnd(); + } } - glColor3ub(0, 0, 0); + immUnbindProgram(); } static void editnurb_draw_active_nurbs(Nurb *nu) { - UI_ThemeColor(TH_ACTIVE_SPLINE); - glLineWidth(2); - - glBegin(GL_LINES); - BPoint *bp = nu->bp; - for (int b = 0; b < nu->pntsv; b++) { - BPoint *bp1 = bp; - bp++; + if (nu->pntsv > 0) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_ACTIVE_SPLINE); - for (int a = nu->pntsu - 1; a > 0; a--, bp++) { - if (bp->hide == 0 && bp1->hide == 0) { - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); - } - bp1 = bp; - } - } + glLineWidth(2.0f); + // just quick guesstimate of how many verts to draw + int count = (nu->pntsu - 1) * nu->pntsv * 2; + if (nu->pntsv > 1) count += (nu->pntsv - 1) * nu->pntsu * 2; + if (count < 2) return; - if (nu->pntsv > 1) { /* surface */ + immBeginAtMost(GWN_PRIM_LINES, count); + BPoint *bp = nu->bp; + for (int b = 0; b < nu->pntsv; b++) { + BPoint *bp1 = bp; + bp++; - int ofs = nu->pntsu; - for (int b = 0; b < nu->pntsu; b++) { - BPoint *bp1 = nu->bp + b; - bp = bp1 + ofs; - for (int a = nu->pntsv - 1; a > 0; a--, bp += ofs) { + for (int a = nu->pntsu - 1; a > 0; a--, bp++) { if (bp->hide == 0 && bp1->hide == 0) { - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } bp1 = bp; } } - } - glEnd(); + if (nu->pntsv > 1) { /* surface */ + int ofs = nu->pntsu; + for (int b = 0; b < nu->pntsu; b++) { + BPoint *bp1 = nu->bp + b; + bp = bp1 + ofs; + for (int a = nu->pntsv - 1; a > 0; a--, bp += ofs) { + if (bp->hide == 0 && bp1->hide == 0) { + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); + } + bp1 = bp; + } + } + } + + immEnd(); - glColor3ub(0, 0, 0); + immUnbindProgram(); + } } static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) @@ -6242,6 +7203,9 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) BPoint *bp, *bp1; int a, b; Curve *cu = ob->data; + Gwn_VertFormat *format; + unsigned int pos, col; + unsigned char color[3]; int index = 0; Nurb *nu = nurb; @@ -6249,35 +7213,55 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) if (nu->hide == 0) { switch (nu->type) { case CU_POLY: + { if (!sel && index == cu->actnu) { /* we should draw active spline highlight below everything */ editnurb_draw_active_poly(nu); } - glLineWidth(1); + format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + glLineWidth(1.0f); - UI_ThemeColor(TH_NURB_ULINE); + immUniformThemeColor(TH_NURB_ULINE); bp = nu->bp; for (b = 0; b < nu->pntsv; b++) { - if (nu->flagu & 1) glBegin(GL_LINE_LOOP); - else glBegin(GL_LINE_STRIP); + if (nu->pntsu >= 2) { + if (nu->flagu & 1) immBegin(GWN_PRIM_LINE_LOOP, nu->pntsu); + else immBegin(GWN_PRIM_LINE_STRIP, nu->pntsu); - for (a = 0; a < nu->pntsu; a++, bp++) { - glVertex3fv(bp->vec); - } + for (a = 0; a < nu->pntsu; a++, bp++) { + immVertex3fv(pos, bp->vec); + } - glEnd(); + immEnd(); + } } + immUnbindProgram(); break; + } case CU_NURBS: + { if (!sel && index == cu->actnu) { /* we should draw active spline highlight below everything */ editnurb_draw_active_nurbs(nu); } - glLineWidth(1); + format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + // just quick guesstimate of how many verts to draw + int count = (nu->pntsu - 1) * nu->pntsv * 2; + if (nu->pntsv > 1) count += (nu->pntsv - 1) * nu->pntsu * 2; + if (count < 2) return; - glBegin(GL_LINES); + glLineWidth(1.0f); + + immBeginAtMost(GWN_PRIM_LINES, count); bp = nu->bp; for (b = 0; b < nu->pntsv; b++) { @@ -6287,10 +7271,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) if (bp->hide == 0 && bp1->hide == 0) { if (sel) { if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) { - UI_ThemeColor(TH_NURB_SEL_ULINE); - - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + UI_GetThemeColor3ubv(TH_NURB_SEL_ULINE, color); + immAttrib3ubv(col, color); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } } else { @@ -6298,10 +7282,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) /* pass */ } else { - UI_ThemeColor(TH_NURB_ULINE); - - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + UI_GetThemeColor3ubv(TH_NURB_ULINE, color); + immAttrib3ubv(col, color); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } } } @@ -6318,10 +7302,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) if (bp->hide == 0 && bp1->hide == 0) { if (sel) { if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) { - UI_ThemeColor(TH_NURB_SEL_VLINE); - - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + UI_GetThemeColor3ubv(TH_NURB_SEL_VLINE, color); + immAttrib3ubv(col, color); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } } else { @@ -6329,10 +7313,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) /* pass */ } else { - UI_ThemeColor(TH_NURB_VLINE); - - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + UI_GetThemeColor3ubv(TH_NURB_VLINE, color); + immAttrib3ubv(col, color); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } } } @@ -6340,9 +7324,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) } } } - - glEnd(); + immEnd(); + immUnbindProgram(); break; + } } } @@ -6352,8 +7337,9 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) } static void draw_editnurb( - Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, - const char dt, const short dflag, const unsigned char ob_wire_col[4]) + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, + View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, + const char dt, const short dflag, const unsigned char UNUSED(ob_wire_col[4])) { ToolSettings *ts = scene->toolsettings; Object *ob = base->object; @@ -6365,9 +7351,8 @@ static void draw_editnurb( /* DispList */ UI_GetThemeColor3ubv(TH_WIRE_EDIT, wire_col); - glColor3ubv(wire_col); - drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, wire_col); /* for shadows only show solid faces */ if (v3d->flag2 & V3D_RENDER_SHADOW) @@ -6391,79 +7376,110 @@ static void draw_editnurb( for (nu = nurb; nu; nu = nu->next) { if (nu->type == CU_BEZIER && (cu->drawflag & CU_HIDE_HANDLES) == 0) drawhandlesN(nu, 1, hide_handles); - drawvertsN(nu, 0, hide_handles, NULL); } if (v3d->zbuf) glDepthFunc(GL_LEQUAL); - glColor3ubv(wire_col); - /* direction vectors for 3d curve paths * when at its lowest, don't render normals */ if ((cu->flag & CU_3D) && (ts->normalsize > 0.0015f) && (cu->drawflag & CU_HIDE_NORMALS) == 0) { BevList *bl; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_WIRE_EDIT); + glLineWidth(1.0f); + + int count = 0; + int count_used = 0; for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) { - BevPoint *bevp = bl->bevpoints; int nr = bl->nr; int skip = nu->resolu / 16; - + +#if 0 while (nr-- > 0) { /* accounts for empty bevel lists */ - const float fac = bevp->radius * ts->normalsize; - float vec_a[3]; /* Offset perpendicular to the curve */ - float vec_b[3]; /* Delta along the curve */ + count += 4; + nr -= skip; + } +#else + /* Same as loop above */ + count += 4 * max_ii((nr + max_ii(skip - 1, 0)) / (skip + 1), 0); +#endif + } - vec_a[0] = fac; - vec_a[1] = 0.0f; - vec_a[2] = 0.0f; - - mul_qt_v3(bevp->quat, vec_a); - madd_v3_v3fl(vec_a, bevp->dir, -fac); + if (count > 2) { + immBegin(GWN_PRIM_LINES, count); + for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) { + BevPoint *bevp = bl->bevpoints; + int nr = bl->nr; + int skip = nu->resolu / 16; - reflect_v3_v3v3(vec_b, vec_a, bevp->dir); - negate_v3(vec_b); + while (nr-- > 0) { /* accounts for empty bevel lists */ + const float fac = bevp->radius * ts->normalsize; + float vec_a[3]; /* Offset perpendicular to the curve */ + float vec_b[3]; /* Delta along the curve */ - add_v3_v3(vec_a, bevp->vec); - add_v3_v3(vec_b, bevp->vec); + vec_a[0] = fac; + vec_a[1] = 0.0f; + vec_a[2] = 0.0f; + + mul_qt_v3(bevp->quat, vec_a); + madd_v3_v3fl(vec_a, bevp->dir, -fac); - glBegin(GL_LINE_STRIP); - glVertex3fv(vec_a); - glVertex3fv(bevp->vec); - glVertex3fv(vec_b); - glEnd(); - - bevp += skip + 1; - nr -= skip; + reflect_v3_v3v3(vec_b, vec_a, bevp->dir); + negate_v3(vec_b); + + add_v3_v3(vec_a, bevp->vec); + add_v3_v3(vec_b, bevp->vec); + + immVertex3fv(pos, vec_a); + immVertex3fv(pos, bevp->vec); + immVertex3fv(pos, bevp->vec); + immVertex3fv(pos, vec_b); + + bevp += skip + 1; + nr -= skip; + count_used += 4; + } } + BLI_assert(count == count_used); + UNUSED_VARS_NDEBUG(count_used); + + immEnd(); } + immUnbindProgram(); } - if (v3d->zbuf) glDepthFunc(GL_ALWAYS); - - for (nu = nurb; nu; nu = nu->next) { - drawvertsN(nu, 1, hide_handles, vert); - } - - if (v3d->zbuf) glDepthFunc(GL_LEQUAL); + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); + + drawvertsN(nurb, hide_handles, vert); + + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } static void draw_editfont_textcurs(RegionView3D *rv3d, float textcurs[4][2]) { - cpack(0); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); ED_view3d_polygon_offset(rv3d, -1.0); set_inverted_drawing(1); - glBegin(GL_QUADS); - glVertex2fv(textcurs[0]); - glVertex2fv(textcurs[1]); - glVertex2fv(textcurs[2]); - glVertex2fv(textcurs[3]); - glEnd(); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + imm_cpack(0); + immBegin(GWN_PRIM_TRI_FAN, 4); + immVertex2fv(pos, textcurs[0]); + immVertex2fv(pos, textcurs[1]); + immVertex2fv(pos, textcurs[2]); + immVertex2fv(pos, textcurs[3]); + immEnd(); set_inverted_drawing(0); ED_view3d_polygon_offset(rv3d, 0.0); + immUnbindProgram(); } -static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const char dt, const short dflag, const unsigned char ob_wire_col[4]) +static void draw_editfont( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; Curve *cu = ob->data; @@ -6473,17 +7489,19 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b draw_editfont_textcurs(rv3d, ef->textcurs); if (cu->flag & CU_FAST) { - cpack(0xFFFFFF); + imm_cpack(0xFFFFFF); set_inverted_drawing(1); - drawDispList(scene, v3d, rv3d, base, OB_WIRE, dflag, ob_wire_col); + drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, OB_WIRE, dflag, ob_wire_col); set_inverted_drawing(0); } else { - drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } if (cu->linewidth != 0.0f) { - UI_ThemeColor(TH_WIRE_EDIT); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_WIRE_EDIT); copy_v3_v3(vec1, ob->orig); copy_v3_v3(vec2, ob->orig); vec1[0] += cu->linewidth; @@ -6491,31 +7509,35 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b vec1[1] += cu->linedist * cu->fsize; vec2[1] -= cu->lines * cu->linedist * cu->fsize; setlinestyle(3); - glBegin(GL_LINES); - glVertex2fv(vec1); - glVertex2fv(vec2); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(pos, vec1); + immVertex2fv(pos, vec2); + immEnd(); setlinestyle(0); + immUnbindProgram(); } setlinestyle(3); for (int i = 0; i < cu->totbox; i++) { if (cu->tb[i].w != 0.0f) { - UI_ThemeColor(i == (cu->actbox - 1) ? TH_ACTIVE : TH_WIRE); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(i == (cu->actbox - 1) ? TH_ACTIVE : TH_WIRE); vec1[0] = cu->xof + cu->tb[i].x; vec1[1] = cu->yof + cu->tb[i].y + cu->fsize; vec1[2] = 0.001; - glBegin(GL_LINE_STRIP); - glVertex3fv(vec1); + immBegin(GWN_PRIM_LINE_STRIP, 5); + immVertex3fv(pos, vec1); vec1[0] += cu->tb[i].w; - glVertex3fv(vec1); + immVertex3fv(pos, vec1); vec1[1] -= cu->tb[i].h; - glVertex3fv(vec1); + immVertex3fv(pos, vec1); vec1[0] -= cu->tb[i].w; - glVertex3fv(vec1); + immVertex3fv(pos, vec1); vec1[1] += cu->tb[i].h; - glVertex3fv(vec1); - glEnd(); + immVertex3fv(pos, vec1); + immEnd(); + immUnbindProgram(); } } setlinestyle(0); @@ -6524,7 +7546,9 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b if (ef->selboxes && ef->selboxes_len) { float selboxw; - cpack(0xffffff); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + imm_cpack(0xffffff); set_inverted_drawing(1); for (int i = 0; i < ef->selboxes_len; i++) { EditFontSelBox *sb = &ef->selboxes[i]; @@ -6543,20 +7567,20 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b /* fill in xy below */ tvec[2] = 0.001; - glBegin(GL_QUADS); + immBegin(GWN_PRIM_TRI_FAN, 4); if (sb->rot == 0.0f) { copy_v2_fl2(tvec, sb->x, sb->y); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, sb->x + selboxw, sb->y); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, sb->x + selboxw, sb->y + sb->h); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, sb->x, sb->y + sb->h); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); } else { float mat[2][2]; @@ -6564,84 +7588,87 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b angle_to_mat2(mat, sb->rot); copy_v2_fl2(tvec, sb->x, sb->y); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, selboxw, 0.0f); mul_m2v2(mat, tvec); add_v2_v2(tvec, &sb->x); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, selboxw, sb->h); mul_m2v2(mat, tvec); add_v2_v2(tvec, &sb->x); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, 0.0f, sb->h); mul_m2v2(mat, tvec); add_v2_v2(tvec, &sb->x); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); } - glEnd(); + immEnd(); } set_inverted_drawing(0); + immUnbindProgram(); } } /* draw a sphere for use as an empty drawtype */ -static void draw_empty_sphere(float size) -{ - static GLuint displist = 0; - - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - glPushMatrix(); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - gluDisk(qobj, 0.0, 1, 16, 1); - - glRotatef(90, 0, 1, 0); - gluDisk(qobj, 0.0, 1, 16, 1); - - glRotatef(90, 1, 0, 0); - gluDisk(qobj, 0.0, 1, 16, 1); - - gluDeleteQuadric(qobj); - - glPopMatrix(); - glEndList(); - } - - glScalef(size, size, size); - glCallList(displist); - glScalef(1.0f / size, 1.0f / size, 1.0f / size); +static void draw_empty_sphere(float size, unsigned pos) +{ +#define NSEGMENTS 16 + /* a single ring of vertices */ + float p[NSEGMENTS][2]; + for (int i = 0; i < NSEGMENTS; ++i) { + float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); + p[i][0] = size * cosf(angle); + p[i][1] = size * sinf(angle); + } + + immBegin(GWN_PRIM_LINE_LOOP, NSEGMENTS); + for (int i = 0; i < NSEGMENTS; ++i) + immVertex3f(pos, p[i][0], p[i][1], 0.0f); + immEnd(); + immBegin(GWN_PRIM_LINE_LOOP, NSEGMENTS); + for (int i = 0; i < NSEGMENTS; ++i) + immVertex3f(pos, p[i][0], 0.0f, p[i][1]); + immEnd(); + immBegin(GWN_PRIM_LINE_LOOP, NSEGMENTS); + for (int i = 0; i < NSEGMENTS; ++i) + immVertex3f(pos, 0.0f, p[i][0], p[i][1]); + immEnd(); +#undef NSEGMENTS } /* draw a cone for use as an empty drawtype */ -static void draw_empty_cone(float size) +static void draw_empty_cone(float size, unsigned pos) { - const float radius = size; +#define NSEGMENTS 8 + /* a single ring of vertices */ + float p[NSEGMENTS][2]; + for (int i = 0; i < NSEGMENTS; ++i) { + float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); + p[i][0] = size * cosf(angle); + p[i][1] = size * sinf(angle); + } - GLUquadricObj *qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - - glPushMatrix(); - - glScalef(radius, size * 2.0f, radius); - glRotatef(-90.0, 1.0, 0.0, 0.0); - gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1); + /* cone sides */ + immBegin(GWN_PRIM_LINES, NSEGMENTS * 2); + for (int i = 0; i < NSEGMENTS; ++i) { + immVertex3f(pos, 0.0f, 2.0f * size, 0.0f); + immVertex3f(pos, p[i][0], 0.0f, p[i][1]); + } + immEnd(); - glPopMatrix(); - - gluDeleteQuadric(qobj); + /* end ring */ + immBegin(GWN_PRIM_LINE_LOOP, NSEGMENTS); + for (int i = 0; i < NSEGMENTS; ++i) + immVertex3f(pos, p[i][0], 0.0f, p[i][1]); + immEnd(); +#undef NSEGMENTS } -static void drawspiral(const float cent[3], float rad, float tmat[4][4], int start) +static void drawspiral(unsigned int pos, const float cent[3], float rad, float tmat[4][4], int start) { float vec[3], vx[3], vy[3]; const float tot_inv = 1.0f / (float)CIRCLE_RESOL; @@ -6657,11 +7684,11 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta mul_v3_v3fl(vx, tmat[0], rad); mul_v3_v3fl(vy, tmat[1], rad); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, CIRCLE_RESOL + 1); if (inverse == 0) { copy_v3_v3(vec, cent); - glVertex3fv(vec); + immVertex3fv(pos, vec); for (a = 0; a < CIRCLE_RESOL; a++) { if (a + start >= CIRCLE_RESOL) @@ -6675,7 +7702,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta vec[1] = cent[1] + (x * vx[1] + y * vy[1]); vec[2] = cent[2] + (x * vx[2] + y * vy[2]); - glVertex3fv(vec); + immVertex3fv(pos, vec); } } else { @@ -6687,7 +7714,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta vec[1] = cent[1] + (x * vx[1] + y * vy[1]); vec[2] = cent[2] + (x * vx[2] + y * vy[2]); - glVertex3fv(vec); + immVertex3fv(pos, vec); for (a = 0; a < CIRCLE_RESOL; a++) { if (a + start >= CIRCLE_RESOL) @@ -6700,79 +7727,79 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta vec[0] = cent[0] + (x * vx[0] + y * vy[0]); vec[1] = cent[1] + (x * vx[1] + y * vy[1]); vec[2] = cent[2] + (x * vx[2] + y * vy[2]); - glVertex3fv(vec); + immVertex3fv(pos, vec); } } - glEnd(); + immEnd(); } /* draws a circle on x-z plane given the scaling of the circle, assuming that * all required matrices have been set (used for drawing empties) */ -static void drawcircle_size(float size) +static void drawcircle_size(float size, unsigned pos) { - glBegin(GL_LINE_LOOP); + immBegin(GWN_PRIM_LINE_LOOP, CIRCLE_RESOL); /* coordinates are: cos(degrees * 11.25) = x, sin(degrees * 11.25) = y, 0.0f = z */ for (short degrees = 0; degrees < CIRCLE_RESOL; degrees++) { float x = cosval[degrees]; float y = sinval[degrees]; - - glVertex3f(x * size, 0.0f, y * size); + + immVertex3f(pos, x * size, 0.0f, y * size); } - - glEnd(); + immEnd(); } /* needs fixing if non-identity matrix used */ -static void drawtube(const float vec[3], float radius, float height, float tmat[4][4]) +static void imm_drawtube(const float vec[3], float radius, float height, float tmat[4][4], unsigned pos) { float cur[3]; - drawcircball(GL_LINE_LOOP, vec, radius, tmat); + imm_drawcircball(vec, radius, tmat, pos); copy_v3_v3(cur, vec); cur[2] += height; - drawcircball(GL_LINE_LOOP, cur, radius, tmat); + imm_drawcircball(cur, radius, tmat, pos); - glBegin(GL_LINES); - glVertex3f(vec[0] + radius, vec[1], vec[2]); - glVertex3f(cur[0] + radius, cur[1], cur[2]); - glVertex3f(vec[0] - radius, vec[1], vec[2]); - glVertex3f(cur[0] - radius, cur[1], cur[2]); - glVertex3f(vec[0], vec[1] + radius, vec[2]); - glVertex3f(cur[0], cur[1] + radius, cur[2]); - glVertex3f(vec[0], vec[1] - radius, vec[2]); - glVertex3f(cur[0], cur[1] - radius, cur[2]); - glEnd(); + immBegin(GWN_PRIM_LINES, 8); + immVertex3f(pos, vec[0] + radius, vec[1], vec[2]); + immVertex3f(pos, cur[0] + radius, cur[1], cur[2]); + immVertex3f(pos, vec[0] - radius, vec[1], vec[2]); + immVertex3f(pos, cur[0] - radius, cur[1], cur[2]); + immVertex3f(pos, vec[0], vec[1] + radius, vec[2]); + immVertex3f(pos, cur[0], cur[1] + radius, cur[2]); + immVertex3f(pos, vec[0], vec[1] - radius, vec[2]); + immVertex3f(pos, cur[0], cur[1] - radius, cur[2]); + immEnd(); } /* needs fixing if non-identity matrix used */ -static void drawcone(const float vec[3], float radius, float height, float tmat[4][4]) +static void imm_drawcone(const float vec[3], float radius, float height, float tmat[4][4], unsigned pos) { float cur[3]; copy_v3_v3(cur, vec); cur[2] += height; - drawcircball(GL_LINE_LOOP, cur, radius, tmat); + imm_drawcircball(cur, radius, tmat, pos); - glBegin(GL_LINES); - glVertex3f(vec[0], vec[1], vec[2]); - glVertex3f(cur[0] + radius, cur[1], cur[2]); - glVertex3f(vec[0], vec[1], vec[2]); - glVertex3f(cur[0] - radius, cur[1], cur[2]); - glVertex3f(vec[0], vec[1], vec[2]); - glVertex3f(cur[0], cur[1] + radius, cur[2]); - glVertex3f(vec[0], vec[1], vec[2]); - glVertex3f(cur[0], cur[1] - radius, cur[2]); - glEnd(); + immBegin(GWN_PRIM_LINES, 8); + immVertex3f(pos, vec[0], vec[1], vec[2]); + immVertex3f(pos, cur[0] + radius, cur[1], cur[2]); + immVertex3f(pos, vec[0], vec[1], vec[2]); + immVertex3f(pos, cur[0] - radius, cur[1], cur[2]); + immVertex3f(pos, vec[0], vec[1], vec[2]); + immVertex3f(pos, cur[0], cur[1] + radius, cur[2]); + immVertex3f(pos, vec[0], vec[1], vec[2]); + immVertex3f(pos, cur[0], cur[1] - radius, cur[2]); + immEnd(); } /* return true if nothing was drawn */ -static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const char dt, const short dflag, const unsigned char ob_wire_col[4]) +static bool drawmball( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; MetaElem *ml; @@ -6785,15 +7812,13 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, if ((G.f & G_PICKSEL) == 0) { unsigned char wire_col[4]; UI_GetThemeColor4ubv(TH_WIRE_EDIT, wire_col); - glColor3ubv(wire_col); - - drawDispList(scene, v3d, rv3d, base, dt, dflag, wire_col); + drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, wire_col); } ml = mb->editelems->first; } else { - if ((base->flag & OB_FROMDUPLI) == 0) { - drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + if ((base->flag_legacy & OB_FROMDUPLI) == 0) { + drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } ml = mb->elems.first; } @@ -6810,20 +7835,25 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, normalize_v3(imat[0]); normalize_v3(imat[1]); +#if 0 /* no purpose? */ if (mb->editelems == NULL) { if ((dflag & DRAW_CONSTCOLOR) == 0) { glColor3ubv(ob_wire_col); } } - +#endif + glLineWidth(1.0f); + const unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + while (ml) { /* draw radius */ if (mb->editelems) { if ((dflag & DRAW_CONSTCOLOR) == 0) { - if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) cpack(0xA0A0F0); - else cpack(0x3030A0); + if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) imm_cpack(0xA0A0F0); + else imm_cpack(0x3030A0); } if (G.f & G_PICKSEL) { @@ -6831,24 +7861,26 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, GPU_select_load_id(code++); } } - drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat); + imm_drawcircball(&(ml->x), ml->rad, imat, pos); /* draw stiffness */ if (mb->editelems) { if ((dflag & DRAW_CONSTCOLOR) == 0) { - if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) cpack(0xA0F0A0); - else cpack(0x30A030); + if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) imm_cpack(0xA0F0A0); + else imm_cpack(0x30A030); } if (G.f & G_PICKSEL) { ml->selcol2 = code; GPU_select_load_id(code++); } - drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad * atanf(ml->s) / (float)M_PI_2, imat); + imm_drawcircball(&(ml->x), ml->rad * atanf(ml->s) / (float)M_PI_2, imat, pos); } ml = ml->next; } + + immUnbindProgram(); return false; } @@ -6858,6 +7890,7 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, PartDeflect *pd = ob->pd; float imat[4][4], tmat[4][4]; float vec[3] = {0.0, 0.0, 0.0}; + float draw_color[3] = {0.0f, 0.0f, 0.0f}; /* scale size of circle etc with the empty drawsize */ const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f; @@ -6867,35 +7900,53 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, normalize_v3(imat[0]); /* we don't do this because field doesnt scale either... apart from wind! */ normalize_v3(imat[1]); #endif + + const unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3fv(draw_color); if (pd->forcefield == PFIELD_WIND) { float force_val = pd->f_strength; if ((dflag & DRAW_CONSTCOLOR) == 0) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color); + immUniformColor3fv(draw_color); } unit_m4(tmat); force_val *= 0.1f; - drawcircball(GL_LINE_LOOP, vec, size, tmat); + imm_drawcircball(vec, size, tmat, pos); vec[2] = 0.5f * force_val; - drawcircball(GL_LINE_LOOP, vec, size, tmat); + imm_drawcircball(vec, size, tmat, pos); vec[2] = 1.0f * force_val; - drawcircball(GL_LINE_LOOP, vec, size, tmat); + imm_drawcircball(vec, size, tmat, pos); vec[2] = 1.5f * force_val; - drawcircball(GL_LINE_LOOP, vec, size, tmat); + imm_drawcircball(vec, size, tmat, pos); vec[2] = 0.0f; /* reset vec for max dist circle */ - } else if (pd->forcefield == PFIELD_FORCE) { float ffall_val = pd->f_power; - if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); - drawcircball(GL_LINE_LOOP, vec, size, imat); - if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(1.5f, ffall_val)); - drawcircball(GL_LINE_LOOP, vec, size * 1.5f, imat); - if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(2.0f, ffall_val)); - drawcircball(GL_LINE_LOOP, vec, size * 2.0f, imat); + if ((dflag & DRAW_CONSTCOLOR) == 0) { + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color); + immUniformColor3fv(draw_color); + } + + imm_drawcircball(vec, size, imat, pos); + + if ((dflag & DRAW_CONSTCOLOR) == 0) { + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(1.5f, ffall_val), draw_color); + immUniformColor3fv(draw_color); + } + + imm_drawcircball(vec, size * 1.5f, imat, pos); + + if ((dflag & DRAW_CONSTCOLOR) == 0) { + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(2.0f, ffall_val), draw_color); + immUniformColor3fv(draw_color); + } + + imm_drawcircball(vec, size * 2.0f, imat, pos); } else if (pd->forcefield == PFIELD_VORTEX) { float force_val = pd->f_strength; @@ -6903,16 +7954,17 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, unit_m4(tmat); if ((dflag & DRAW_CONSTCOLOR) == 0) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f); + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f, draw_color); + immUniformColor3fv(draw_color); } if (force_val < 0) { - drawspiral(vec, size, tmat, 1); - drawspiral(vec, size, tmat, 16); + drawspiral(pos, vec, size, tmat, 1); + drawspiral(pos, vec, size, tmat, 16); } else { - drawspiral(vec, size, tmat, -1); - drawspiral(vec, size, tmat, -16); + drawspiral(pos, vec, size, tmat, -1); + drawspiral(pos, vec, size, tmat, -16); } } else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) { @@ -6922,18 +7974,19 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, float mindist = pd->f_strength; if ((dflag & DRAW_CONSTCOLOR) == 0) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color); + immUniformColor3fv(draw_color); } /* path end */ setlinestyle(3); where_on_path(ob, 1.0f, guidevec1, guidevec2, NULL, NULL, NULL); - drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat); + imm_drawcircball(guidevec1, mindist, imat, pos); /* path beginning */ setlinestyle(0); where_on_path(ob, 0.0f, guidevec1, guidevec2, NULL, NULL, NULL); - drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat); + imm_drawcircball(guidevec1, mindist, imat, pos); copy_v3_v3(vec, guidevec1); /* max center */ } @@ -6942,16 +7995,19 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, setlinestyle(3); if ((dflag & DRAW_CONSTCOLOR) == 0) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color); + immUniformColor3fv(draw_color); } if (pd->falloff == PFIELD_FALL_SPHERE) { /* as last, guide curve alters it */ - if (pd->flag & PFIELD_USEMAX) - drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat); + if ((pd->flag & PFIELD_USEMAX) != 0) { + imm_drawcircball(vec, pd->maxdist, imat, pos); + } - if (pd->flag & PFIELD_USEMIN) - drawcircball(GL_LINE_LOOP, vec, pd->mindist, imat); + if ((pd->flag & PFIELD_USEMIN) != 0) { + imm_drawcircball(vec, pd->mindist, imat, pos); + } } else if (pd->falloff == PFIELD_FALL_TUBE) { float radius, distance; @@ -6964,16 +8020,18 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, vec[2] = distance; distance = (pd->flag & PFIELD_POSZ) ? -distance : -2.0f * distance; - if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) - drawtube(vec, radius, distance, tmat); + if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { + imm_drawtube(vec, radius, distance, tmat, pos); + } radius = (pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f; distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f; vec[2] = distance; distance = (pd->flag & PFIELD_POSZ) ? -distance : -2.0f * distance; - if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) - drawtube(vec, radius, distance, tmat); + if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { + imm_drawtube(vec, radius, distance, tmat, pos); + } } else if (pd->falloff == PFIELD_FALL_CONE) { float radius, distance; @@ -6984,46 +8042,54 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f; if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { - drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat); + imm_drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat, pos); if ((pd->flag & PFIELD_POSZ) == 0) - drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat); + imm_drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat, pos); } radius = DEG2RADF((pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f); distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f; if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { - drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat); + imm_drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat, pos); if ((pd->flag & PFIELD_POSZ) == 0) - drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat); + imm_drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat, pos); } } setlinestyle(0); + + immUnbindProgram(); } -static void draw_box(const float vec[8][3], bool solid) +static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vec); - if (solid) { - const GLubyte indices[24] = {0,1,2,3,7,6,5,4,4,5,1,0,3,2,6,7,3,7,4,0,1,5,6,2}; - glDrawRangeElements(GL_QUADS, 0, 7, 24, GL_UNSIGNED_BYTE, indices); + /* Adpated from "Optimizing Triangle Strips for Fast Rendering" by F. Evans, S. Skiena and A. Varshney + * (http://www.cs.umd.edu/gvil/papers/av_ts.pdf). */ + static const GLubyte tris_strip_indices[14] = {0,1,3,2,6,1,5,0,4,3,7,6,4,5}; + immBegin(GWN_PRIM_TRI_STRIP, 14); + for (int i = 0; i < 14; ++i) { + immVertex3fv(pos, vec[tris_strip_indices[i]]); + } + immEnd(); } else { - const GLubyte indices[24] = {0,1,1,2,2,3,3,0,0,4,4,5,5,6,6,7,7,4,1,5,2,6,3,7}; - glDrawRangeElements(GL_LINES, 0, 7, 24, GL_UNSIGNED_BYTE, indices); + static const GLubyte line_indices[24] = {0,1,1,2,2,3,3,0,0,4,4,5,5,6,6,7,7,4,1,5,2,6,3,7}; + immBegin(GWN_PRIM_LINES, 24); + for (int i = 0; i < 24; ++i) { + immVertex3fv(pos, vec[line_indices[i]]); + } + immEnd(); } - glDisableClientState(GL_VERTEX_ARRAY); } -static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin) +static void imm_draw_bb(BoundBox *bb, char type, bool around_origin, const unsigned char ob_wire_col[4]) { float size[3], cent[3]; - GLUquadricObj *qobj = gluNewQuadric(); - - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); + Gwn_Batch *sphere = GPU_batch_preset_sphere_wire(0); + GWN_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) GWN_batch_uniform_4f(sphere, "color", ob_wire_col[0] / 255.0f, ob_wire_col[1] / 255.0f, ob_wire_col[2] / 255.0f, 1.0f); BKE_boundbox_calc_size_aabb(bb, size); @@ -7034,40 +8100,51 @@ static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin) BKE_boundbox_calc_center_aabb(bb, cent); } - glPushMatrix(); + gpuPushMatrix(); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + if (type == OB_BOUND_SPHERE) { float scale = MAX3(size[0], size[1], size[2]); - glTranslate3fv(cent); - glScalef(scale, scale, scale); - gluSphere(qobj, 1.0, 8, 5); + gpuTranslate3fv(cent); + gpuRotateAxis(90, 'X'); + gpuScaleUniform(scale); + GWN_batch_draw(sphere); } else if (type == OB_BOUND_CYLINDER) { float radius = size[0] > size[1] ? size[0] : size[1]; - glTranslatef(cent[0], cent[1], cent[2] - size[2]); - glScalef(radius, radius, 2.0f * size[2]); - gluCylinder(qobj, 1.0, 1.0, 1.0, 8, 1); + gpuTranslate3f(cent[0], cent[1], cent[2] - size[2]); + gpuScale3f(radius, radius, 2.0f * size[2]); + imm_draw_cylinder_wire_3d(pos, 1.0f, 1.0f, 1.0f, 8, 1); } else if (type == OB_BOUND_CONE) { float radius = size[0] > size[1] ? size[0] : size[1]; - glTranslatef(cent[0], cent[1], cent[2] - size[2]); - glScalef(radius, radius, 2.0f * size[2]); - gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1); + gpuTranslate3f(cent[0], cent[1], cent[2] - size[2]); + gpuScale3f(radius, radius, 2.0f * size[2]); + imm_draw_cylinder_wire_3d(pos, 1.0f, 0.0f, 1.0f, 8, 1); + } else if (type == OB_BOUND_CAPSULE) { float radius = size[0] > size[1] ? size[0] : size[1]; float length = size[2] > radius ? 2.0f * (size[2] - radius) : 0.0f; - glTranslatef(cent[0], cent[1], cent[2] - length * 0.5f); - gluCylinder(qobj, radius, radius, length, 8, 1); - gluSphere(qobj, radius, 8, 4); - glTranslatef(0.0, 0.0, length); - gluSphere(qobj, radius, 8, 4); + gpuTranslate3f(cent[0], cent[1], cent[2] - length * 0.5f); + imm_draw_cylinder_wire_3d(pos, radius, radius, length, 8, 1); + + gpuRotateAxis(90, 'X'); + gpuScaleUniform(radius); + GWN_batch_draw(sphere); + + gpuTranslate3f(0.0f, length / radius, 0.0f); + GWN_batch_draw(sphere); } - glPopMatrix(); - - gluDeleteQuadric(qobj); + + gpuPopMatrix(); + immUnbindProgram(); } -static void draw_bounding_volume(Object *ob, char type) +void draw_bounding_volume(Object *ob, char type, const unsigned char ob_wire_col[4]) { BoundBox bb_local; BoundBox *bb = NULL; @@ -7097,12 +8174,16 @@ static void draw_bounding_volume(Object *ob, char type) if (bb == NULL) return; - + if (ob->gameflag & OB_BOUNDS) { /* bounds need to be drawn around origin for game engine */ if (type == OB_BOUND_BOX) { float vec[8][3], size[3]; - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + BKE_boundbox_calc_size_aabb(bb, size); vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = -size[0]; @@ -7112,21 +8193,31 @@ static void draw_bounding_volume(Object *ob, char type) vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2]; vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2]; - draw_box(vec, false); + imm_draw_box(vec, false, pos); + + immUnbindProgram(); } else { - draw_bb_quadric(bb, type, true); + imm_draw_bb(bb, type, true, ob_wire_col); } } else { - if (type == OB_BOUND_BOX) - draw_box(bb->vec, false); + if (type == OB_BOUND_BOX) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + + imm_draw_box(bb->vec, false, pos); + + immUnbindProgram(); + } else - draw_bb_quadric(bb, type, false); + imm_draw_bb(bb, type, false, ob_wire_col); } + } -static void drawtexspace(Object *ob) +static void drawtexspace(Object *ob, const unsigned char ob_wire_col[3]) { float vec[8][3], loc[3], size[3]; @@ -7156,26 +8247,38 @@ static void drawtexspace(Object *ob) setlinestyle(2); - draw_box(vec, false); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + if (ob_wire_col) { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(ob_wire_col); + } + else { + immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY); + } + + imm_draw_box(vec, false, pos); + + immUnbindProgram(); setlinestyle(0); } /* draws wire outline */ static void draw_object_selected_outline( - Scene *scene, View3D *v3d, ARegion *ar, Base *base, + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, const unsigned char ob_wire_col[4]) { RegionView3D *rv3d = ar->regiondata; Object *ob = base->object; - glDepthMask(0); + glDepthMask(GL_FALSE); if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { bool has_faces = false; #ifdef SEQUENCER_DAG_WORKAROUND - ensure_curve_cache(scene, ob); + ensure_curve_cache(eval_ctx, scene, ob); #endif DerivedMesh *dm = ob->derivedFinal; @@ -7193,46 +8296,41 @@ static void draw_object_selected_outline( if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->bb)) { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); if (dm) { - draw_mesh_object_outline(v3d, ob, dm); + draw_mesh_object_outline(v3d, ob, dm, ob_wire_col); } else { /* only draw 'solid' parts of the display list as wire. */ - drawDispListwire_ex(&ob->curve_cache->disp, (DL_INDEX3 | DL_INDEX4 | DL_SURF)); + drawDispListwire_ex(&ob->curve_cache->disp, (DL_INDEX3 | DL_INDEX4 | DL_SURF), ob_wire_col); } } } else if (ob->type == OB_MBALL) { if (BKE_mball_is_basis(ob)) { - if ((base->flag & OB_FROMDUPLI) == 0) { + if ((base->flag_legacy & OB_FROMDUPLI) == 0) { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); - drawDispListwire(&ob->curve_cache->disp, ob->type); + drawDispListwire(&ob->curve_cache->disp, ob->type, ob_wire_col); } } } else if (ob->type == OB_ARMATURE) { - if (!(ob->mode & OB_MODE_POSE && base == scene->basact)) { + if (!(ob->mode & OB_MODE_POSE && base == sl->basact)) { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); - draw_armature(scene, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true); + draw_armature(eval_ctx, scene, sl, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true); } } - glDepthMask(1); + glDepthMask(GL_TRUE); } static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const unsigned char ob_wire_col[4]) { if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL)) { - - if (scene->obedit == ob) { - UI_ThemeColor(TH_WIRE_EDIT); - } - else { - glColor3ubv(ob_wire_col); - } + unsigned char wire_edit_col[4]; + UI_GetThemeColor4ubv(TH_WIRE_EDIT, wire_edit_col); ED_view3d_polygon_offset(rv3d, 1.0); - glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */ - glLineWidth(1); + glDepthMask(GL_FALSE); /* disable write in zbuffer, selected edge wires show better */ + glLineWidth(1.0f); if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { if (ED_view3d_boundbox_clip(rv3d, ob->bb)) { @@ -7241,23 +8339,23 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const drawCurveDMWired(ob); } else { - drawDispListwire(&ob->curve_cache->disp, ob->type); + drawDispListwire(&ob->curve_cache->disp, ob->type, (scene->obedit == ob) ? wire_edit_col : ob_wire_col); } } } else if (ob->type == OB_MBALL) { if (BKE_mball_is_basis(ob)) { - drawDispListwire(&ob->curve_cache->disp, ob->type); + drawDispListwire(&ob->curve_cache->disp, ob->type, (scene->obedit == ob) ? wire_edit_col : ob_wire_col); } } - glDepthMask(1); + glDepthMask(GL_TRUE); ED_view3d_polygon_offset(rv3d, 0.0); } } /* should be called in view space */ -static void draw_hooks(Object *ob) +static void draw_hooks(Object *ob, unsigned int pos) { for (ModifierData *md = ob->modifiers.first; md; md = md->next) { if (md->type == eModifierType_Hook) { @@ -7268,17 +8366,17 @@ static void draw_hooks(Object *ob) if (hmd->object) { setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(hmd->object->obmat[3]); - glVertex3fv(vec); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, hmd->object->obmat[3]); + immVertex3fv(pos, vec); + immEnd(); setlinestyle(0); } - glPointSize(3.0); - glBegin(GL_POINTS); - glVertex3fv(vec); - glEnd(); + glPointSize(3.0f); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, vec); + immEnd(); } } } @@ -7289,9 +8387,16 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data, const char *axis_str[3] = {"px", "py", "pz"}; float mat[4][4]; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + eul_to_mat4(mat, &data->axX); glLineWidth(4.0f); setlinestyle(2); + + immBegin(GWN_PRIM_LINES, 6); for (int axis = 0; axis < 3; axis++) { float dir[3] = {0, 0, 0}; float v[3]; @@ -7299,12 +8404,10 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data, copy_v3_v3(v, &data->pivX); dir[axis] = 1.0f; - glBegin(GL_LINES); mul_m4_v3(mat, dir); add_v3_v3(v, dir); - glVertex3fv(&data->pivX); - glVertex3fv(v); - glEnd(); + immVertex3fv(pos, &data->pivX); + immVertex3fv(pos, v); /* when const color is set wirecolor is NULL - we could get the current color but * with selection and group instancing its not needed to draw the text */ @@ -7312,11 +8415,15 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data, view3d_cached_text_draw_add(v, axis_str[axis], 2, 0, V3D_CACHE_TEXT_ASCII, ob_wire_col); } } + immEnd(); setlinestyle(0); + glLineWidth(1.0f); + + immUnbindProgram(); } -static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_col[4]) +void draw_object_wire_color(Scene *scene, SceneLayer *sl, Base *base, unsigned char r_ob_wire_col[4]) { Object *ob = base->object; int colindex = 0; @@ -7330,23 +8437,23 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_ if ((scene->obedit == NULL) && (G.moving & G_TRANSFORM_OBJ) && - (base->flag & (SELECT + BA_WAS_SEL))) + ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) { theme_id = TH_TRANSFORM; } else { /* Sets the 'colindex' */ if (ID_IS_LINKED(ob)) { - colindex = (base->flag & (SELECT + BA_WAS_SEL)) ? 2 : 1; + colindex = ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) ? 2 : 1; } /* Sets the 'theme_id' or fallback to wire */ else { - if (ob->flag & OB_FROMGROUP) { - if (base->flag & (SELECT + BA_WAS_SEL)) { + if ((ob->flag & OB_FROMGROUP) != 0) { + if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) { /* uses darker active color for non-active + selected */ theme_id = TH_GROUP_ACTIVE; - if (scene->basact != base) { + if (sl->basact != base) { theme_shade = -32; } } @@ -7355,8 +8462,8 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_ } } else { - if (base->flag & (SELECT + BA_WAS_SEL)) { - theme_id = scene->basact == base ? TH_ACTIVE : TH_SELECT; + if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) { + theme_id = sl->basact == base ? TH_ACTIVE : TH_SELECT; } else { if (ob->type == OB_LAMP) theme_id = TH_LAMP; @@ -7410,10 +8517,11 @@ static void draw_object_matcap_check(View3D *v3d, Object *ob) v3d->flag2 |= V3D_SHOW_SOLID_MATCAP; } -static void draw_rigidbody_shape(Object *ob) +void draw_rigidbody_shape(Object *ob, const unsigned char ob_wire_col[4]) { BoundBox *bb = NULL; float size[3], vec[8][3]; + unsigned int pos; if (ob->type == OB_MESH) { bb = BKE_mesh_boundbox_get(ob); @@ -7426,6 +8534,10 @@ static void draw_rigidbody_shape(Object *ob) case RB_SHAPE_BOX: BKE_boundbox_calc_size_aabb(bb, size); + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = -size[0]; vec[4][0] = vec[5][0] = vec[6][0] = vec[7][0] = +size[0]; vec[0][1] = vec[1][1] = vec[4][1] = vec[5][1] = -size[1]; @@ -7433,19 +8545,20 @@ static void draw_rigidbody_shape(Object *ob) vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2]; vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2]; - draw_box(vec, false); + imm_draw_box(vec, false, pos); + immUnbindProgram(); break; case RB_SHAPE_SPHERE: - draw_bb_quadric(bb, OB_BOUND_SPHERE, true); + imm_draw_bb(bb, OB_BOUND_SPHERE, true, ob_wire_col); break; case RB_SHAPE_CONE: - draw_bb_quadric(bb, OB_BOUND_CONE, true); + imm_draw_bb(bb, OB_BOUND_CONE, true, ob_wire_col); break; case RB_SHAPE_CYLINDER: - draw_bb_quadric(bb, OB_BOUND_CYLINDER, true); + imm_draw_bb(bb, OB_BOUND_CYLINDER, true, ob_wire_col); break; case RB_SHAPE_CAPSULE: - draw_bb_quadric(bb, OB_BOUND_CAPSULE, true); + imm_draw_bb(bb, OB_BOUND_CAPSULE, true, ob_wire_col); break; } } @@ -7454,17 +8567,18 @@ static void draw_rigidbody_shape(Object *ob) * main object drawing function, draws in selection * \param dflag (draw flag) can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET */ -void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag) +void draw_object( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, + Base *base, const short dflag) { ModifierData *md = NULL; Object *ob = base->object; Curve *cu; RegionView3D *rv3d = ar->regiondata; - unsigned int col = 0; unsigned char _ob_wire_col[4]; /* dont initialize this */ const unsigned char *ob_wire_col = NULL; /* dont initialize this, use NULL crashes as a way to find invalid use */ bool zbufoff = false, is_paint = false, empty_object = false; - const bool is_obact = (ob == OBACT); + const bool is_obact = (ob == OBACT(sl)); const bool render_override = (v3d->flag2 & V3D_RENDER_OVERRIDE) != 0; const bool is_picking = (G.f & G_PICKSEL) != 0; const bool has_particles = (ob->particlesystem.first != NULL); @@ -7504,7 +8618,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } } - if (((base->flag & OB_FROMDUPLI) == 0) && + if (((base->flag_legacy & OB_FROMDUPLI) == 0) && (md = modifiers_findByType(ob, eModifierType_Smoke)) && (modifier_isEnabled(scene, md, eModifierMode_Realtime))) { @@ -7528,7 +8642,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* xray delay? */ - if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag_legacy & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* don't do xray in particle mode, need the z-buffer */ if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) { /* xray and transp are set when it is drawing the 2nd/3rd pass */ @@ -7581,10 +8695,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short ED_view3d_project_base(ar, base); - draw_object_wire_color(scene, base, _ob_wire_col); + draw_object_wire_color(scene, sl, base, _ob_wire_col); ob_wire_col = _ob_wire_col; - glColor3ubv(ob_wire_col); + //glColor3ubv(ob_wire_col); } /* maximum drawtype */ @@ -7636,15 +8750,22 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* draw outline for selected objects, mesh does itself */ if ((v3d->flag & V3D_SELECT_OUTLINE) && !render_override && ob->type != OB_MESH) { if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (dflag & DRAW_SCENESET) == 0) { - if (!(ob->dtx & OB_DRAWWIRE) && (ob->flag & SELECT) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) { - draw_object_selected_outline(scene, v3d, ar, base, ob_wire_col); + if (!(ob->dtx & OB_DRAWWIRE) && (base->flag & BASE_SELECTED) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) { + draw_object_selected_outline(eval_ctx, scene, sl, v3d, ar, base, ob_wire_col); } } } + /* TODO Viewport: draw only for selection */ + if ((dflag & DRAW_PICKING) == 0) { + if ((dt == OB_BOUNDBOX) || ELEM(ob->type, OB_EMPTY, OB_LAMP, OB_CAMERA, OB_SPEAKER)) { + goto afterdraw; + } + } + switch (ob->type) { case OB_MESH: - empty_object = draw_mesh_object(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); + empty_object = draw_mesh_object(eval_ctx, scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); if ((dflag & DRAW_CONSTCOLOR) == 0) { /* mesh draws wire itself */ dtx &= ~OB_DRAWWIRE; @@ -7654,18 +8775,18 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short case OB_FONT: cu = ob->data; if (cu->editfont) { - draw_editfont(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + draw_editfont(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } else if (dt == OB_BOUNDBOX) { if ((render_override && v3d->drawtype >= OB_WIRE) == 0) { #ifdef SEQUENCER_DAG_WORKAROUND - ensure_curve_cache(scene, base->object); + ensure_curve_cache(eval_ctx, scene, base->object); #endif - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } } else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) { - empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + empty_object = drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } break; @@ -7675,18 +8796,18 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (cu->editnurb) { ListBase *nurbs = BKE_curve_editNurbs_get(cu); - draw_editnurb(scene, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col); + draw_editnurb(eval_ctx, scene, sl, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col); } else if (dt == OB_BOUNDBOX) { if ((render_override && (v3d->drawtype >= OB_WIRE)) == 0) { #ifdef SEQUENCER_DAG_WORKAROUND - ensure_curve_cache(scene, base->object); + ensure_curve_cache(eval_ctx, scene, base->object); #endif - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } } else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) { - empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + empty_object = drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } break; case OB_MBALL: @@ -7694,17 +8815,17 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short MetaBall *mb = ob->data; if (mb->editelems) - drawmball(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + drawmball(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); else if (dt == OB_BOUNDBOX) { if ((render_override && (v3d->drawtype >= OB_WIRE)) == 0) { #ifdef SEQUENCER_DAG_WORKAROUND - ensure_curve_cache(scene, base->object); + ensure_curve_cache(eval_ctx, scene, base->object); #endif - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } } else - empty_object = drawmball(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + empty_object = drawmball(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); break; } case OB_EMPTY: @@ -7713,7 +8834,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short draw_empty_image(ob, dflag, ob_wire_col, v3d->multiview_eye); } else { - drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype); + drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, ob_wire_col); } } break; @@ -7731,7 +8852,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short break; case OB_SPEAKER: if (!render_override) - drawspeaker(scene, v3d, rv3d, ob, dflag); + drawspeaker(ob_wire_col); break; case OB_LATTICE: if (!render_override) { @@ -7739,13 +8860,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((dt == OB_BOUNDBOX) && (ob->mode & OB_MODE_EDIT)) dt = OB_WIRE; if (dt == OB_BOUNDBOX) { - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } else { #ifdef SEQUENCER_DAG_WORKAROUND - ensure_curve_cache(scene, ob); + ensure_curve_cache(eval_ctx, scene, ob); #endif - drawlattice(v3d, ob); + drawlattice(v3d, ob, dflag, ob_wire_col); } } break; @@ -7755,21 +8876,33 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((dt == OB_BOUNDBOX) && (ob->mode & (OB_MODE_EDIT | OB_MODE_POSE))) dt = OB_WIRE; if (dt == OB_BOUNDBOX) { - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } else { + unsigned char arm_col[4]; glLineWidth(1.0f); - empty_object = draw_armature(scene, v3d, ar, base, dt, dflag, ob_wire_col, false); + + if (ob_wire_col == NULL) { + float fcol[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + rgba_float_to_uchar(arm_col, fcol); + } + else + copy_v4_v4_uchar(arm_col, ob_wire_col); + + empty_object = draw_armature(eval_ctx, scene, sl, v3d, ar, base, dt, dflag, arm_col, false); } } break; default: if (!render_override) { - drawaxes(rv3d->viewmatob, 1.0, OB_ARROWS); + drawaxes(rv3d->viewmatob, 1.0, OB_ARROWS, ob_wire_col); } break; } + /* TODO Viewport: some elements are being drawn for object selection only */ +afterdraw: + if (!render_override) { if (ob->soft /*&& dflag & OB_SBMOTION*/) { float mrt[3][3], msc[3][3], mtr[3][3]; @@ -7778,12 +8911,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((sb = ob->soft)) { if (sb->solverflags & SBSO_ESTIMATEIPO) { - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); copy_m3_m3(msc, sb->lscale); copy_m3_m3(mrt, sb->lrot); mul_m3_m3m3(mtr, mrt, msc); ob_draw_RE_motion(sb->lcom, mtr, tipw, tiph, drawsize); - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); } } } @@ -7800,35 +8933,28 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short { ParticleSystem *psys; - if ((dflag & DRAW_CONSTCOLOR) == 0) { - /* for visibility, also while wpaint */ - if (col || (ob->flag & SELECT)) { - cpack(0xFFFFFF); - } - } //glDepthMask(GL_FALSE); - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); view3d_cached_text_draw_begin(); for (psys = ob->particlesystem.first; psys; psys = psys->next) { /* run this so that possible child particles get cached */ if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) { - PTCacheEdit *edit = PE_create_current(scene, ob); + PTCacheEdit *edit = PE_create_current(eval_ctx, scene, ob); if (edit && edit->psys == psys) - draw_update_ptcache_edit(scene, ob, edit); + draw_update_ptcache_edit(eval_ctx, scene, sl, ob, edit); } - draw_new_particle_system(scene, v3d, rv3d, base, psys, dt, dflag); + draw_new_particle_system(eval_ctx, scene, v3d, rv3d, base, psys, dt, dflag); } invert_m4_m4(ob->imat, ob->obmat); view3d_cached_text_draw_end(v3d, ar, 0); - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); //glDepthMask(GL_TRUE); - if (col) cpack(col); } /* draw edit particles last so that they can draw over child particles */ @@ -7837,12 +8963,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short { if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) { - PTCacheEdit *edit = PE_create_current(scene, ob); + PTCacheEdit *edit = PE_create_current(eval_ctx, scene, ob); if (edit) { - glLoadMatrixf(rv3d->viewmat); - draw_update_ptcache_edit(scene, ob, edit); + gpuLoadMatrix(rv3d->viewmat); + draw_update_ptcache_edit(eval_ctx, scene, sl, ob, edit); draw_ptcache_edit(scene, v3d, edit); - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); } } } @@ -7850,21 +8976,25 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* draw code for smoke, only draw domains */ if (smd && smd->domain) { SmokeDomainSettings *sds = smd->domain; + const bool show_smoke = (CFRA >= sds->point_cache[0]->startframe); float viewnormal[3]; - glLoadMatrixf(rv3d->viewmat); - glMultMatrixf(ob->obmat); + gpuLoadMatrix(rv3d->viewmat); + gpuMultMatrix(ob->obmat); if (!render_override) { BoundBox bb; float p0[3], p1[3]; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); /* draw max domain bounds */ if ((sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN)) { VECSUBFAC(p0, sds->p0, sds->cell_size, sds->adapt_res); VECADDFAC(p1, sds->p1, sds->cell_size, sds->adapt_res); BKE_boundbox_init_from_minmax(&bb, p0, p1); - draw_box(bb.vec, false); + imm_draw_box(bb.vec, false, pos); } /* draw a single voxel to hint the user about the resolution of the fluid */ @@ -7878,11 +9008,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } BKE_boundbox_init_from_minmax(&bb, p0, p1); - draw_box(bb.vec, false); + imm_draw_box(bb.vec, false, pos); + + immUnbindProgram(); } /* don't show smoke before simulation starts, this could be made an option in the future */ - if (sds->fluid && CFRA >= sds->point_cache[0]->startframe) { + if (sds->fluid && show_smoke) { float p0[3], p1[3]; /* get view vector */ @@ -7934,29 +9066,37 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((ob->gameflag & OB_BOUNDS) && (ob->mode == OB_MODE_OBJECT)) { if (ob->boundtype != ob->collision_boundtype || (dtx & OB_DRAWBOUNDOX) == 0) { setlinestyle(2); - draw_bounding_volume(ob, ob->collision_boundtype); + draw_bounding_volume(ob, ob->collision_boundtype, ob_wire_col); setlinestyle(0); } } if (ob->rigidbody_object) { - draw_rigidbody_shape(ob); + draw_rigidbody_shape(ob, ob_wire_col); } /* draw extra: after normal draw because of makeDispList */ if (dtx && (G.f & G_RENDER_OGL) == 0) { if (dtx & OB_AXIS) { - drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS); + if ((dflag & DRAW_CONSTCOLOR) == 0) { + /* prevent random colors being used */ + drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS, ob_wire_col); + } + else { + drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS, NULL); + } } if (dtx & OB_DRAWBOUNDOX) { - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } if (dtx & OB_TEXSPACE) { if ((dflag & DRAW_CONSTCOLOR) == 0) { /* prevent random colors being used */ - glColor3ubv(ob_wire_col); + drawtexspace(ob, ob_wire_col); + } + else { + drawtexspace(ob, NULL); } - drawtexspace(ob); } if (dtx & OB_DRAWNAME) { /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */ @@ -7983,16 +9123,21 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short { float imat[4][4], vec[3] = {0.0f, 0.0f, 0.0f}; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + invert_m4_m4(imat, rv3d->viewmatob); if ((dflag & DRAW_CONSTCOLOR) == 0) { /* prevent random colors being used */ - glColor3ubv(ob_wire_col); + immUniformColor3ubv(ob_wire_col); } setlinestyle(2); - drawcircball(GL_LINE_LOOP, vec, ob->inertia, imat); + imm_drawcircball(vec, ob->inertia, imat, pos); setlinestyle(0); + + immUnbindProgram(); } } @@ -8002,13 +9147,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* return warning, clear temp flag */ v3d->flag2 &= ~V3D_SHOW_SOLID_MATCAP; - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); if (zbufoff) { glDisable(GL_DEPTH_TEST); } - if ((base->flag & OB_FROMDUPLI) || render_override) { + if ((base->flag_legacy & OB_FROMDUPLI) || render_override) { ED_view3d_clear_mats_rv3d(rv3d); return; } @@ -8022,7 +9167,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } else if (is_obact) do_draw_center = ACTIVE; - else if (base->flag & SELECT) + else if (base->flag & BASE_SELECTED) do_draw_center = SELECT; else if (empty_object || (v3d->flag & V3D_DRAW_CENTERS)) do_draw_center = DESELECT; @@ -8033,10 +9178,15 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((base->sx != IS_CLIPPED) && (U.obcenter_dia != 0.0)) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR); + /* TODO: short term, use DEPTH_ONLY shader or set appropriate color */ + /* TODO: long term, solve picking & selection problem better */ glPointSize(U.obcenter_dia); - glBegin(GL_POINTS); - glVertex3fv(ob->obmat[3]); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, ob->obmat[3]); + immEnd(); + immUnbindProgram(); } } else if ((dflag & DRAW_CONSTCOLOR) == 0) { @@ -8057,18 +9207,24 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short ListBase *list; RigidBodyCon *rbc = ob->rigidbody_constraint; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(ob_wire_col); + /* draw hook center and offset line */ if (ob != scene->obedit) - draw_hooks(ob); + draw_hooks(ob, pos); /* help lines and so */ - if (ob != scene->obedit && ob->parent && (ob->parent->lay & v3d->lay)) { - setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(ob->obmat[3]); - glVertex3fv(ob->orig); - glEnd(); - setlinestyle(0); + if (ob != scene->obedit && ob->parent) { + if (BKE_object_is_visible(ob->parent)) { + setlinestyle(3); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, ob->obmat[3]); + immVertex3fv(pos, ob->orig); + immEnd(); + setlinestyle(0); + } } /* Drawing the constraint lines */ @@ -8081,7 +9237,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short UI_GetThemeColor3ubv(TH_GRID, col1); UI_make_axis_color(col1, col2, 'Z'); - glColor3ubv(col2); + immUniformColor3ubv(col2); cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); @@ -8106,10 +9262,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (camob) { setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(camob->obmat[3]); - glVertex3fv(ob->obmat[3]); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, camob->obmat[3]); + immVertex3fv(pos, ob->obmat[3]); + immEnd(); setlinestyle(0); } } @@ -8125,15 +9281,15 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short for (ct = targets.first; ct; ct = ct->next) { /* calculate target's matrix */ if (cti->get_target_matrix) - cti->get_target_matrix(curcon, cob, ct, BKE_scene_frame_get(scene)); + cti->get_target_matrix(eval_ctx, curcon, cob, ct, BKE_scene_frame_get(scene)); else unit_m4(ct->matrix); setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(ct->matrix[3]); - glVertex3fv(ob->obmat[3]); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, ct->matrix[3]); + immVertex3fv(pos, ob->obmat[3]); + immEnd(); setlinestyle(0); } @@ -8146,21 +9302,24 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short BKE_constraints_clear_evalob(cob); } /* draw rigid body constraint lines */ - if (rbc) { - UI_ThemeColor(TH_WIRE); + if (rbc && (rbc->ob1 || rbc->ob2)) { + immUniformThemeColor(TH_WIRE); + setlinestyle(3); - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, ((int)((bool)rbc->ob1) + (int)((bool)rbc->ob2)) * 2); if (rbc->ob1) { - glVertex3fv(ob->obmat[3]); - glVertex3fv(rbc->ob1->obmat[3]); + immVertex3fv(pos, ob->obmat[3]); + immVertex3fv(pos, rbc->ob1->obmat[3]); } if (rbc->ob2) { - glVertex3fv(ob->obmat[3]); - glVertex3fv(rbc->ob2->obmat[3]); + immVertex3fv(pos, ob->obmat[3]); + immVertex3fv(pos, rbc->ob2->obmat[3]); } - glEnd(); + immEnd(); setlinestyle(0); } + + immUnbindProgram(); } ED_view3d_clear_mats_rv3d(rv3d); @@ -8171,10 +9330,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short * Drawing for selection picking, * caller must have called 'GPU_select_load_id(base->selcode)' first. */ -void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag) +void draw_object_select( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, + Base *base, const short dflag) { BLI_assert(dflag & DRAW_PICKING && dflag & DRAW_CONSTCOLOR); - draw_object(scene, ar, v3d, base, dflag); + draw_object(eval_ctx, scene, sl, ar, v3d, base, dflag); /* we draw duplicators for selection too */ if ((base->object->transflag & OB_DUPLI)) { @@ -8182,13 +9343,11 @@ void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, cons DupliObject *dob; Base tbase; - tbase.flag = OB_FROMDUPLI; - lb = object_duplilist(G.main->eval_ctx, scene, base->object); + tbase.flag_legacy = OB_FROMDUPLI; + lb = object_duplilist(eval_ctx, scene, base->object); for (dob = lb->first; dob; dob = dob->next) { float omat[4][4]; - char dt; - short dtx; tbase.object = dob->ob; copy_m4_m4(omat, dob->ob->obmat); @@ -8196,10 +9355,10 @@ void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, cons /* extra service: draw the duplicator in drawtype of parent */ /* MIN2 for the drawtype to allow bounding box objects in groups for lods */ - dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); - dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx; + char dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); + short dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx; - draw_object(scene, ar, v3d, &tbase, dflag); + draw_object(eval_ctx, scene, sl, ar, v3d, &tbase, dflag); tbase.object->dt = dt; tbase.object->dtx = dtx; @@ -8212,6 +9371,7 @@ void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, cons /* ***************** BACKBUF SEL (BBS) ********* */ +#ifdef USE_MESH_DM_SELECT static void bbs_obmode_mesh_verts__mapFunc(void *userData, int index, const float co[3], const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) { @@ -8219,8 +9379,10 @@ static void bbs_obmode_mesh_verts__mapFunc(void *userData, int index, const floa MVert *mv = &data->mvert[index]; if (!(mv->flag & ME_HIDE)) { - GPU_select_index_set(data->offset + index); - glVertex3fv(co); + int selcol; + GPU_select_index_get(data->offset + index, &selcol); + immAttrib1u(data->col, selcol); + immVertex3fv(data->pos, co); } } @@ -8231,12 +9393,36 @@ static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *dm, int offset) MVert *mvert = me->mvert; data.mvert = mvert; data.offset = offset; + + const int imm_len = dm->getNumVerts(dm); + + if (imm_len == 0) return; + + Gwn_VertFormat *format = immVertexFormat(); + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - glBegin(GL_POINTS); + + immBeginAtMost(GWN_PRIM_POINTS, imm_len); dm->foreachMappedVert(dm, bbs_obmode_mesh_verts__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } +#else +static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *UNUSED(dm), int offset) +{ + Mesh *me = ob->data; + Gwn_Batch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); +} +#endif +#ifdef USE_MESH_DM_SELECT static void bbs_mesh_verts__mapFunc(void *userData, int index, const float co[3], const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) { @@ -8244,97 +9430,223 @@ static void bbs_mesh_verts__mapFunc(void *userData, int index, const float co[3] BMVert *eve = BM_vert_at_index(data->bm, index); if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - GPU_select_index_set(data->offset + index); - glVertex3fv(co); + int selcol; + GPU_select_index_get(data->offset + index, &selcol); + immAttrib1u(data->col, selcol); + immVertex3fv(data->pos, co); } } static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset) { - drawBMOffset_userData data = {em->bm, offset}; + drawBMOffset_userData data; + data.bm = em->bm; + data.offset = offset; + Gwn_VertFormat *format = immVertexFormat(); + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - glBegin(GL_POINTS); + + immBeginAtMost(GWN_PRIM_POINTS, em->bm->totvert); dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } +#else +static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset) +{ + Mesh *me = em->ob->data; + Gwn_Batch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); +} +#endif -static DMDrawOption bbs_mesh_wire__setDrawOptions(void *userData, int index) +#ifdef USE_MESH_DM_SELECT +static void bbs_mesh_wire__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3]) { drawBMOffset_userData *data = userData; BMEdge *eed = BM_edge_at_index(data->bm, index); if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { - GPU_select_index_set(data->offset + index); - return DM_DRAW_OPTION_NORMAL; - } - else { - return DM_DRAW_OPTION_SKIP; + int selcol; + GPU_select_index_get(data->offset + index, &selcol); + immAttrib1u(data->col, selcol); + immVertex3fv(data->pos, v0co); + immVertex3fv(data->pos, v1co); } } + static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset) { - drawBMOffset_userData data = {em->bm, offset}; - dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, &data); + drawBMOffset_userData data; + data.bm = em->bm; + data.offset = offset; + + Gwn_VertFormat *format = immVertexFormat(); + + const int imm_len = dm->getNumEdges(dm) * 2; + + if (imm_len == 0) return; + + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + immBeginAtMost(GWN_PRIM_LINES, imm_len); + dm->foreachMappedEdge(dm, bbs_mesh_wire__mapFunc, &data); + immEnd(); + + immUnbindProgram(); } +#else +static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset) +{ + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); -/** - * dont set #GPU_framebuffer_index_set. just use to mask other - */ -static DMDrawOption bbs_mesh_mask__setSolidDrawOptions(void *userData, int index) + Mesh *me = em->ob->data; + Gwn_Batch *batch = DRW_mesh_batch_cache_get_edges_with_select_id(me, offset); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); +} +#endif + +#ifdef USE_MESH_DM_SELECT +static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *dm, const bool use_select) { - BMFace *efa = BM_face_at_index(userData, index); - - if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - return DM_DRAW_OPTION_NORMAL; + UNUSED_VARS(dm); + + drawBMOffset_userData data; + data.bm = em->bm; + + const int tri_len = em->tottri; + const int imm_len = tri_len * 3; + const char hflag_skip = use_select ? BM_ELEM_HIDDEN : (BM_ELEM_HIDDEN | BM_ELEM_SELECT); + + if (imm_len == 0) return; + + Gwn_VertFormat *format = immVertexFormat(); + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + + immBeginAtMost(GWN_PRIM_TRIS, imm_len); + + if (use_select == false) { + int selcol; + GPU_select_index_get(0, &selcol); + immAttrib1u(data.col, selcol); } - else { - return DM_DRAW_OPTION_SKIP; + + int index = 0; + while (index < tri_len) { + const BMFace *f = em->looptris[index][0]->f; + const int ntris = f->len - 2; + if (!BM_elem_flag_test(f, hflag_skip)) { + if (use_select) { + int selcol; + GPU_select_index_get(BM_elem_index_get(f) + 1, &selcol); + immAttrib1u(data.col, selcol); + } + for (int t = 0; t < ntris; t++) { + immVertex3fv(data.pos, em->looptris[index][0]->v->co); + immVertex3fv(data.pos, em->looptris[index][1]->v->co); + immVertex3fv(data.pos, em->looptris[index][2]->v->co); + index++; + } + } + else { + index += ntris; + } } -} + immEnd(); -static DMDrawOption bbs_mesh_solid__setSolidDrawOptions(void *userData, int index) + immUnbindProgram(); +} +#else +static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *UNUSED(dm), const bool use_select) { - BMFace *efa = BM_face_at_index(userData, index); + Mesh *me = em->ob->data; + Gwn_Batch *batch; - if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - GPU_select_index_set(index + 1); - return DM_DRAW_OPTION_NORMAL; + if (use_select) { + batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true, 1); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); } else { - return DM_DRAW_OPTION_SKIP; + int selcol; + GPU_select_index_get(0, &selcol); + batch = DRW_mesh_batch_cache_get_triangles_with_select_mask(me, true); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32); + GWN_batch_uniform_1i(batch, "color", selcol); + GWN_batch_draw(batch); } } +#endif +#ifdef USE_MESH_DM_SELECT static void bbs_mesh_solid__drawCenter(void *userData, int index, const float cent[3], const float UNUSED(no[3])) { + drawBMOffset_userData *data = (drawBMOffset_userData *)userData; BMFace *efa = BM_face_at_index(userData, index); if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - GPU_select_index_set(index + 1); - - glVertex3fv(cent); + int selcol; + GPU_select_index_get(index + 1, &selcol); + immAttrib1u(data->col, selcol); + immVertex3fv(data->pos, cent); } } +static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *dm) +{ + drawBMOffset_userData data; /* don't use offset */ + data.bm = em->bm; + Gwn_VertFormat *format = immVertexFormat(); + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + + glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE)); + + immBeginAtMost(GWN_PRIM_POINTS, em->bm->totface); + dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, &data, DM_FOREACH_NOP); + immEnd(); + + immUnbindProgram(); +} +#else +static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *UNUSED(dm)) +{ + Mesh *me = em->ob->data; + Gwn_Batch *batch = DRW_mesh_batch_cache_get_facedots_with_select_id(me, 1); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); +} +#endif + /* two options, facecolors or black */ static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob, DerivedMesh *dm, bool use_faceselect) { - cpack(0); - if (use_faceselect) { - dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, NULL, NULL, em->bm, DM_DRAW_SKIP_HIDDEN | DM_DRAW_SELECT_USE_EDITMODE); + bbs_mesh_face(em, dm, true); if (check_ob_drawface_dot(scene, v3d, ob->dt)) { - glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE)); - - glBegin(GL_POINTS); - dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, em->bm, DM_FOREACH_NOP); - glEnd(); + bbs_mesh_face_dot(em, dm); } - } else { - dm->drawMappedFaces(dm, bbs_mesh_mask__setSolidDrawOptions, NULL, NULL, em->bm, DM_DRAW_SKIP_SELECT | DM_DRAW_SKIP_HIDDEN | DM_DRAW_SELECT_USE_EDITMODE); + bbs_mesh_face(em, dm, false); } } @@ -8349,7 +9661,6 @@ static DMDrawOption bbs_mesh_solid_hide__setDrawOpts(void *userData, int index) Mesh *me = userData; if (!(me->mpoly[index].flag & ME_HIDE)) { - GPU_select_index_set(index + 1); return DM_DRAW_OPTION_NORMAL; } else { @@ -8357,6 +9668,7 @@ static DMDrawOption bbs_mesh_solid_hide__setDrawOpts(void *userData, int index) } } +#ifdef USE_MESH_DM_SELECT /* must have called GPU_framebuffer_index_set beforehand */ static DMDrawOption bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index) { @@ -8370,11 +9682,10 @@ static DMDrawOption bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index) } } -static void bbs_mesh_solid_verts(Scene *scene, Object *ob) +static void bbs_mesh_solid_verts(const EvaluationContext *eval_ctx, Scene *scene, Object *ob) { Mesh *me = ob->data; - DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); - glColor3ub(0, 0, 0); + DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, scene->customdata_mask); DM_update_materials(dm, ob); @@ -8390,29 +9701,53 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob) bm_vertoffs = me->totvert + 1; dm->release(dm); } - -static void bbs_mesh_solid_faces(Scene *scene, Object *ob) +#else +static void bbs_mesh_solid_verts(const EvaluationContext *UNUSED(eval_ctx), Scene *UNUSED(scene), Object *ob) { - DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); Mesh *me = ob->data; - - glColor3ub(0, 0, 0); - DM_update_materials(dm, ob); + /* Only draw faces to mask out verts, we don't want their selection ID's. */ + const int G_f_orig = G.f; + G.f &= ~G_BACKBUFSEL; - if ((me->editflag & ME_EDIT_PAINT_FACE_SEL)) - dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, NULL, NULL, me, DM_DRAW_SKIP_HIDDEN); - else - dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, NULL, NULL, me, 0); + { + int selcol; + Gwn_Batch *batch; + GPU_select_index_get(0, &selcol); + batch = DRW_mesh_batch_cache_get_triangles_with_select_mask(me, true); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32); + GWN_batch_uniform_1i(batch, "color", selcol); + GWN_batch_draw(batch); + } - dm->release(dm); + G.f |= (G_f_orig & G_BACKBUFSEL); + + bbs_obmode_mesh_verts(ob, NULL, 1); + bm_vertoffs = me->totvert + 1; } +#endif -void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) +static void bbs_mesh_solid_faces(Scene *scene, Object *ob) +{ + Mesh *me = ob->data; + UNUSED_VARS(scene, bbs_mesh_solid_hide__setDrawOpts, bbs_mesh_solid__setDrawOpts); + Gwn_Batch *batch; + if ((me->editflag & ME_EDIT_PAINT_FACE_SEL)) { + batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true, 1); + } + else { + batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, false, 1); + } + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); +} + +void draw_object_backbufsel( + const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) { ToolSettings *ts = scene->toolsettings; - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); @@ -8423,7 +9758,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec Mesh *me = ob->data; BMEditMesh *em = me->edit_btmesh; - DerivedMesh *dm = editbmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH); + DerivedMesh *dm = editbmesh_get_derived_cage(eval_ctx, scene, ob, em, CD_MASK_BAREMESH); BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); @@ -8460,7 +9795,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec /* currently vertex select supports weight paint and vertex paint*/ ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) { - bbs_mesh_solid_verts(scene, ob); + bbs_mesh_solid_verts(eval_ctx, scene, ob); } else { bbs_mesh_solid_faces(scene, ob); @@ -8472,7 +9807,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec break; } - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); } @@ -8480,8 +9815,9 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec /* assumes all matrices/etc set OK */ /* helper function for drawing object instances - meshes */ -static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, - Object *ob, const short dt, int outline) +static void draw_object_mesh_instance( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, + Object *ob, const short dt, int outline, const unsigned char ob_wire_col[4]) { Mesh *me = ob->data; DerivedMesh *dm = NULL, *edm = NULL; @@ -8491,11 +9827,12 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r DM_update_materials(edm, ob); } else { - dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH); DM_update_materials(dm, ob); } if (dt <= OB_WIRE) { + glColor4ubv(ob_wire_col); if (dm) dm->drawEdges(dm, 1, 0); else if (edm) @@ -8503,11 +9840,11 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r } else { if (outline) - draw_mesh_object_outline(v3d, ob, dm ? dm : edm); + draw_mesh_object_outline(v3d, ob, dm ? dm : edm, ob_wire_col); if (dm) { - bool glsl = draw_glsl_material(scene, ob, v3d, dt); - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL); } glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); @@ -8526,23 +9863,153 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r if (dm) dm->release(dm); } -void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline) +void draw_object_instance(const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline, const float wire_col[4]) { if (ob == NULL) return; + unsigned char bcol[4]; + rgba_float_to_uchar(bcol, wire_col); + switch (ob->type) { case OB_MESH: - draw_object_mesh_instance(scene, v3d, rv3d, ob, dt, outline); + draw_object_mesh_instance(eval_ctx, scene, sl, v3d, rv3d, ob, dt, outline, bcol); break; case OB_EMPTY: if (ob->empty_drawtype == OB_EMPTY_IMAGE) { - /* CONSTCOLOR == no wire outline */ - draw_empty_image(ob, DRAW_CONSTCOLOR, NULL, v3d->multiview_eye); + draw_empty_image(ob, 0, bcol, v3d->multiview_eye); } else { - drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype); + drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, bcol); } break; } } + +void ED_draw_object_facemap( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, const float col[4], const int facemap) +{ + DerivedMesh *dm = NULL; + + /* happens on undo */ + if (ob->type != OB_MESH || !ob->data) + return; + + /* Temporary, happens on undo, would resolve but will eventually move away from DM. */ + if (ob->derivedFinal == NULL) { + return; + } + + dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH); + if (!dm || !CustomData_has_layer(&dm->polyData, CD_FACEMAP)) + return; + + + glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + +#if 0 + DM_update_materials(dm, ob); + + /* add polygon offset so we draw above the original surface */ + glPolygonOffset(1.0, 1.0); + + GPU_facemap_setup(dm); + + glColor4fv(col); + + gpuPushAttrib(GL_ENABLE_BIT); + glEnable(GL_BLEND); + glDisable(GL_LIGHTING); + + /* always draw using backface culling */ + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + if (dm->drawObject->facemapindices) { + glDrawElements(GL_TRIANGLES, dm->drawObject->facemap_count[facemap] * 3, GL_UNSIGNED_INT, + (int *)NULL + dm->drawObject->facemap_start[facemap] * 3); + } + gpuPopAttrib(); + + GPU_buffers_unbind(); + + glPolygonOffset(0.0, 0.0); + +#else + + /* Just to create the data to pass to immediate mode, grr! */ + Mesh *me = ob->data; + const int *facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP); + if (facemap_data) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(col); + + /* XXX, alpha isn't working yet, not sure why. */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + MVert *mvert; + + MPoly *mpoly; + int mpoly_len; + + MLoop *mloop; + int mloop_len; + + if (dm && CustomData_has_layer(&dm->polyData, CD_FACEMAP)) { + mvert = dm->getVertArray(dm); + mpoly = dm->getPolyArray(dm); + mloop = dm->getLoopArray(dm); + + mpoly_len = dm->getNumPolys(dm); + mloop_len = dm->getNumLoops(dm); + + facemap_data = CustomData_get_layer(&dm->polyData, CD_FACEMAP); + } + else { + mvert = me->mvert; + mpoly = me->mpoly; + mloop = me->mloop; + + mpoly_len = me->totpoly; + mloop_len = me->totloop; + + facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP); + } + + /* use gawain immediate mode fore now */ + const int looptris_len = poly_to_tri_count(mpoly_len, mloop_len); + immBeginAtMost(GWN_PRIM_TRIS, looptris_len * 3); + + MPoly *mp; + int i; + for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) { + if (facemap_data[i] == facemap) { + /* Weak, fan-fill, use until we have derived-mesh replaced. */ + const MLoop *ml_start = &mloop[mp->loopstart]; + const MLoop *ml_a = ml_start + 1; + const MLoop *ml_b = ml_start + 2; + for (int j = 2; j < mp->totloop; j++) { + immVertex3fv(pos, mvert[ml_start->v].co); + immVertex3fv(pos, mvert[ml_a->v].co); + immVertex3fv(pos, mvert[ml_b->v].co); + + ml_a++; + ml_b++; + } + } + } + immEnd(); + + immUnbindProgram(); + + glDisable(GL_BLEND); + } +#endif + + dm->release(dm); +} + diff --git a/source/blender/editors/space_view3d/drawsimdebug.c b/source/blender/editors/space_view3d/drawsimdebug.c index 3f23d4aa09a..14708ca67bc 100644 --- a/source/blender/editors/space_view3d/drawsimdebug.c +++ b/source/blender/editors/space_view3d/drawsimdebug.c @@ -40,102 +40,137 @@ #include "BKE_effect.h" -#include "view3d_intern.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" -#include "BIF_gl.h" +#include "view3d_intern.h" static void draw_sim_debug_elements(SimDebugData *debug_data, float imat[4][4]) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + /* count element types */ GHashIterator iter; + int num_dots = 0; + int num_circles = 0; + int num_lines = 0; + int num_vectors = 0; + for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { + SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); + switch (elem->type) { + case SIM_DEBUG_ELEM_DOT: ++num_dots; break; + case SIM_DEBUG_ELEM_CIRCLE: ++num_circles; break; + case SIM_DEBUG_ELEM_LINE: ++num_lines; break; + case SIM_DEBUG_ELEM_VECTOR: ++num_vectors; break; + } + } /**** dots ****/ glPointSize(3.0f); - glBegin(GL_POINTS); + immBegin(GWN_PRIM_POINTS, num_dots); for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); if (elem->type != SIM_DEBUG_ELEM_DOT) continue; - glColor3f(elem->color[0], elem->color[1], elem->color[2]); - glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]); + immAttrib3fv(color, elem->color); + immVertex3fv(pos, elem->v1); } - glEnd(); + immEnd(); /**** circles ****/ { - float circle[16][2] = { +#define CIRCLERES 16 + float circle[CIRCLERES][2] = { {0.000000, 1.000000}, {0.382683, 0.923880}, {0.707107, 0.707107}, {0.923880, 0.382683}, {1.000000, -0.000000}, {0.923880, -0.382683}, {0.707107, -0.707107}, {0.382683, -0.923880}, {-0.000000, -1.000000}, {-0.382683, -0.923880}, {-0.707107, -0.707107}, {-0.923879, -0.382684}, {-1.000000, 0.000000}, {-0.923879, 0.382684}, {-0.707107, 0.707107}, {-0.382683, 0.923880} }; + + immBegin(GWN_PRIM_LINES, num_circles * CIRCLERES * 2); + for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); float radius = elem->v2[0]; - float co[3]; + float co[3], nco[3]; int i; if (elem->type != SIM_DEBUG_ELEM_CIRCLE) continue; - glColor3f(elem->color[0], elem->color[1], elem->color[2]); - glBegin(GL_LINE_LOOP); - for (i = 0; i < 16; ++i) { - co[0] = radius * circle[i][0]; - co[1] = radius * circle[i][1]; - co[2] = 0.0f; - mul_mat3_m4_v3(imat, co); - add_v3_v3(co, elem->v1); + immAttrib3fv(color, elem->color); + zero_v3(co); + for (i = 0; i <= CIRCLERES; ++i) { + int ni = i % CIRCLERES; + nco[0] = radius * circle[ni][0]; + nco[1] = radius * circle[ni][1]; + nco[2] = 0.0f; + mul_mat3_m4_v3(imat, nco); + add_v3_v3(nco, elem->v1); - glVertex3f(co[0], co[1], co[2]); + if (i > 0) { + immVertex3fv(pos, co); + immVertex3fv(pos, nco); + } + + copy_v3_v3(co, nco); } - glEnd(); } + + immEnd(); +#undef CIRCLERES } /**** lines ****/ - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, num_lines * 2); for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); if (elem->type != SIM_DEBUG_ELEM_LINE) continue; - glColor3f(elem->color[0], elem->color[1], elem->color[2]); - glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]); - glVertex3f(elem->v2[0], elem->v2[1], elem->v2[2]); + immAttrib3fv(color, elem->color); + immVertex3fv(pos, elem->v1); + immVertex3fv(pos, elem->v2); } - glEnd(); + immEnd(); /**** vectors ****/ glPointSize(2.0f); - glBegin(GL_POINTS); + immBegin(GWN_PRIM_POINTS, num_vectors); for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); if (elem->type != SIM_DEBUG_ELEM_VECTOR) continue; - glColor3f(elem->color[0], elem->color[1], elem->color[2]); - glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]); + immAttrib3fv(color, elem->color); + immVertex3fv(pos, elem->v1); } - glEnd(); + immEnd(); - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, num_vectors * 2); for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); float t[3]; if (elem->type != SIM_DEBUG_ELEM_VECTOR) continue; - glColor3f(elem->color[0], elem->color[1], elem->color[2]); - glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]); + immAttrib3fv(color, elem->color); + immVertex3fv(pos, elem->v1); add_v3_v3v3(t, elem->v1, elem->v2); - glVertex3f(t[0], t[1], t[2]); + immVertex3fv(pos, t); } - glEnd(); + immEnd(); + + immUnbindProgram(); /**** strings ****/ @@ -163,18 +198,12 @@ void draw_sim_debug_data(Scene *UNUSED(scene), View3D *v3d, ARegion *ar) invert_m4_m4(imat, rv3d->viewmatob); -// glDepthMask(GL_FALSE); -// glEnable(GL_BLEND); - - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); + gpuPushMatrix(); + gpuLoadMatrix(rv3d->viewmat); view3d_cached_text_draw_begin(); draw_sim_debug_elements(_sim_debug_data, imat); view3d_cached_text_draw_end(v3d, ar, false); - glPopMatrix(); - -// glDepthMask(GL_TRUE); -// glDisable(GL_BLEND); + gpuPopMatrix(); } diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index c076bfb4aa4..3a80624acd9 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -48,7 +48,6 @@ #include "BIF_gl.h" -#include "GPU_debug.h" #include "GPU_shader.h" #include "GPU_texture.h" @@ -160,7 +159,7 @@ static GPUTexture *create_field_texture(SmokeDomainSettings *sds) default: return NULL; } - return GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, field); + return GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1, GPU_R8, field, NULL); } typedef struct VolumeSlicer { diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 996506a9cf7..e1e78fd8ff1 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -43,22 +43,27 @@ #include "BLI_utildefines.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" +#include "BKE_curve.h" #include "BKE_icons.h" +#include "BKE_lattice.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_mball.h" +#include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_workspace.h" #include "ED_space_api.h" #include "ED_screen.h" +#include "ED_transform.h" #include "GPU_compositing.h" #include "GPU_framebuffer.h" #include "GPU_material.h" - -#include "BIF_gl.h" +#include "GPU_viewport.h" +#include "GPU_matrix.h" #include "WM_api.h" #include "WM_types.h" @@ -250,7 +255,7 @@ void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d) /* we have to multiply instead of loading viewmatob to make * it work with duplis using displists, otherwise it will * override the dupli-matrix */ - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); } #ifdef DEBUG @@ -304,7 +309,7 @@ void ED_view3d_shade_update(Main *bmain, Scene *scene, View3D *v3d, ScrArea *sa) } else if (scene->obedit != NULL && scene->obedit->type == OB_MESH) { /* Tag mesh to load edit data. */ - DAG_id_tag_update(scene->obedit->data, 0); + DEG_id_tag_update(scene->obedit->data, 0); } } @@ -340,9 +345,10 @@ static SpaceLink *view3d_new(const bContext *C) v3d->near = 0.01f; v3d->far = 1000.0f; - v3d->twflag |= U.tw_flag & V3D_USE_MANIPULATOR; + v3d->twflag |= U.manipulator_flag & V3D_MANIPULATOR_DRAW; v3d->twtype = V3D_MANIP_TRANSLATE; v3d->around = V3D_AROUND_CENTER_MEAN; + v3d->custom_orientation_index = -1; v3d->bundle_size = 0.2f; v3d->bundle_drawtype = OB_PLAINAXES; @@ -404,17 +410,6 @@ static SpaceLink *view3d_new(const bContext *C) static void view3d_free(SpaceLink *sl) { View3D *vd = (View3D *) sl; - BGpic *bgpic; - - for (bgpic = vd->bgpicbase.first; bgpic; bgpic = bgpic->next) { - if (bgpic->source == V3D_BGPIC_IMAGE) { - id_us_min((ID *)bgpic->ima); - } - else if (bgpic->source == V3D_BGPIC_MOVIE) { - id_us_min((ID *)bgpic->clip); - } - } - BLI_freelistN(&vd->bgpicbase); if (vd->localvd) MEM_freeN(vd->localvd); @@ -445,7 +440,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) { View3D *v3do = (View3D *)sl; View3D *v3dn = MEM_dupallocN(sl); - BGpic *bgpic; /* clear or remove stuff from old */ @@ -462,16 +456,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) v3dn->defmaterial = NULL; - BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase); - for (bgpic = v3dn->bgpicbase.first; bgpic; bgpic = bgpic->next) { - if (bgpic->source == V3D_BGPIC_IMAGE) { - id_us_plus((ID *)bgpic->ima); - } - else if (bgpic->source == V3D_BGPIC_MOVIE) { - id_us_plus((ID *)bgpic->clip); - } - } - v3dn->properties_storage = NULL; if (v3dn->fx_settings.dof) v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof); @@ -487,6 +471,13 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar) ListBase *lb; wmKeyMap *keymap; + if (ar->manipulator_map == NULL) { + ar->manipulator_map = WM_manipulatormap_new_from_type( + &(const struct wmManipulatorMapType_Params) {SPACE_VIEW3D, RGN_TYPE_WINDOW}); + } + + WM_manipulatormap_add_handlers(ar, ar->manipulator_map); + /* object ops. */ /* important to be before Pose keymap since they can both be enabled at once */ @@ -582,6 +573,12 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar) GPU_fx_compositor_destroy(rv3d->compositor); rv3d->compositor = NULL; } + + if (rv3d->viewport) { + GPU_viewport_free(rv3d->viewport); + MEM_freeN(rv3d->viewport); + rv3d->viewport = NULL; + } } static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) @@ -712,6 +709,26 @@ static void view3d_dropboxes(void) WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy); } +static void view3d_widgets(void) +{ + wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure( + &(const struct wmManipulatorMapType_Params){SPACE_VIEW3D, RGN_TYPE_WINDOW}); + + WM_manipulatorgrouptype_append_and_link(mmap_type, TRANSFORM_WGT_manipulator); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_spot); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_area); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_target); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_force_field); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera_view); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_empty_image); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_armature_spline); + + WM_manipulatorgrouptype_append(VIEW3D_WGT_xform_cage); + + WM_manipulatorgrouptype_append(VIEW3D_WGT_ruler); + WM_manipulatortype_append(VIEW3D_WT_ruler_item); +} /* type callback, not region itself */ @@ -739,6 +756,10 @@ static void view3d_main_region_free(ARegion *ar) if (rv3d->compositor) { GPU_fx_compositor_destroy(rv3d->compositor); } + if (rv3d->viewport) { + GPU_viewport_free(rv3d->viewport); + MEM_freeN(rv3d->viewport); + } MEM_freeN(rv3d); ar->regiondata = NULL; @@ -763,32 +784,22 @@ static void *view3d_main_region_duplicate(void *poin) new->sms = NULL; new->smooth_timer = NULL; new->compositor = NULL; + new->viewport = NULL; return new; } return NULL; } -static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene) +static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene)) { wmWindow *win = wmn->wm->winactive; - ScrArea *sa; unsigned int lay_used = 0; - Base *base; if (!win) return; - base = scene->base.first; - while (base) { - lay_used |= base->lay & ((1 << 20) - 1); /* ignore localview */ - - if (lay_used == (1 << 20) - 1) - break; - - base = base->next; - } - - for (sa = win->screen->areabase.first; sa; sa = sa->next) { + const bScreen *screen = WM_window_get_active_screen(win); + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { if (sa->spacetype == SPACE_VIEW3D) { if (BLI_findindex(&sa->regionbase, ar) != -1) { View3D *v3d = sa->spacedata.first; @@ -799,13 +810,21 @@ static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene } } -static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *wmn) +static void view3d_main_region_listener( + bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar, + wmNotifier *wmn, const Scene *scene) { - Scene *scene = sc->scene; View3D *v3d = sa->spacedata.first; - + RegionView3D *rv3d = ar->regiondata; + wmManipulatorMap *mmap = ar->manipulator_map; + /* context changes */ switch (wmn->category) { + case NC_WM: + if (ELEM(wmn->data, ND_UNDO)) { + WM_manipulatormap_tag_refresh(mmap); + } + break; case NC_ANIMATION: switch (wmn->data) { case ND_KEYFRAME_PROP: @@ -825,21 +844,32 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w break; case NC_SCENE: switch (wmn->data) { + case ND_SCENEBROWSE: case ND_LAYER_CONTENT: if (wmn->reference) view3d_recalc_used_layers(ar, wmn, wmn->reference); ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); + break; + case ND_LAYER: + if (wmn->reference) { + BKE_screen_view3d_sync(v3d, wmn->reference); + } + ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); break; - case ND_FRAME: - case ND_TRANSFORM: case ND_OB_ACTIVE: case ND_OB_SELECT: + DEG_id_tag_update((ID *)&scene->id, DEG_TAG_COPY_ON_WRITE); + ATTR_FALLTHROUGH; + case ND_FRAME: + case ND_TRANSFORM: case ND_OB_VISIBLE: - case ND_LAYER: case ND_RENDER_OPTIONS: case ND_MARKERS: case ND_MODE: ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); break; case ND_WORLD: /* handled by space_view3d_listener() for v3d access */ @@ -847,7 +877,6 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_DRAW_RENDER_VIEWPORT: { if (v3d->camera && (scene == wmn->reference)) { - RegionView3D *rv3d = ar->regiondata; if (rv3d->persp == RV3D_CAMOB) { ED_region_tag_redraw(ar); } @@ -872,6 +901,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_POINTCACHE: case ND_LOD: ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); break; } switch (wmn->action) { @@ -882,9 +912,30 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w break; case NC_GEOM: switch (wmn->data) { + case ND_SELECT: + { + WM_manipulatormap_tag_refresh(mmap); + + if (scene->obedit) { + Object *ob = scene->obedit; + switch (ob->type) { + case OB_MESH: + BKE_mesh_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_SELECT); + break; + // case OB_FONT: /* handled by text_update_edited */ + case OB_CURVE: + case OB_SURF: + BKE_curve_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_SELECT); + break; + case OB_LATTICE: + BKE_lattice_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_SELECT); + break; + } + } + ATTR_FALLTHROUGH; + } case ND_DATA: case ND_VERTEX_GROUP: - case ND_SELECT: ED_region_tag_redraw(ar); break; } @@ -899,7 +950,6 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_DRAW_RENDER_VIEWPORT: { if (v3d->camera && (v3d->camera->data == wmn->reference)) { - RegionView3D *rv3d = ar->regiondata; if (rv3d->persp == RV3D_CAMOB) { ED_region_tag_redraw(ar); } @@ -928,21 +978,13 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w switch (wmn->data) { case ND_SHADING: case ND_NODES: - { -#ifdef WITH_LEGACY_DEPSGRAPH - Object *ob = OBACT; - if ((v3d->drawtype == OB_MATERIAL) || - (ob && (ob->mode == OB_MODE_TEXTURE_PAINT)) || - (v3d->drawtype == OB_TEXTURE && - (scene->gm.matmode == GAME_MAT_GLSL || - BKE_scene_use_new_shading_nodes(scene))) || - !DEG_depsgraph_use_legacy()) -#endif - { - ED_region_tag_redraw(ar); - } + /* TODO(sergey) This is a bit too much updates, but needed to + * have proper material drivers update in the viewport. + * + * How to solve? + */ + ED_region_tag_redraw(ar); break; - } case ND_SHADING_DRAW: case ND_SHADING_LINKS: ED_region_tag_redraw(ar); @@ -954,20 +996,23 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_WORLD_DRAW: /* handled by space_view3d_listener() for v3d access */ break; + case ND_WORLD: + /* Needed for updating world materials */ + ED_region_tag_redraw(ar); + break; } break; case NC_LAMP: switch (wmn->data) { case ND_LIGHTING: - if ((v3d->drawtype == OB_MATERIAL) || - (v3d->drawtype == OB_TEXTURE && (scene->gm.matmode == GAME_MAT_GLSL)) || - !DEG_depsgraph_use_legacy()) - { - ED_region_tag_redraw(ar); - } + /* TODO(sergey): This is a bit too much, but needed to + * handle updates from new depsgraph. + */ + ED_region_tag_redraw(ar); break; case ND_LIGHTING_DRAW: ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); break; } break; @@ -987,10 +1032,10 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case NC_SPACE: if (wmn->data == ND_SPACE_VIEW3D) { if (wmn->subtype == NS_VIEW3D_GPU) { - RegionView3D *rv3d = ar->regiondata; rv3d->rflag |= RV3D_GPULIGHT_UPDATE; } ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); } break; case NC_ID: @@ -1003,15 +1048,13 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_SKETCH: ED_region_tag_redraw(ar); break; - case ND_SCREENBROWSE: - case ND_SCREENDELETE: - case ND_SCREENSET: - /* screen was changed, need to update used layers due to NC_SCENE|ND_LAYER_CONTENT */ - /* updates used layers only for View3D in active screen */ - if (wmn->reference) { - bScreen *sc_ref = wmn->reference; - view3d_recalc_used_layers(ar, wmn, sc_ref->scene); - } + case ND_LAYOUTBROWSE: + case ND_LAYOUTDELETE: + case ND_LAYOUTSET: + WM_manipulatormap_tag_refresh(mmap); + ED_region_tag_redraw(ar); + break; + case ND_LAYER: ED_region_tag_redraw(ar); break; } @@ -1028,7 +1071,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w /* concept is to retrieve cursor type context-less */ static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar)) { - Scene *scene = win->screen->scene; + const Scene *scene = WM_window_get_active_scene(win); if (scene->obedit) { WM_cursor_set(win, CURSOR_EDIT); @@ -1053,7 +1096,9 @@ static void view3d_header_region_draw(const bContext *C, ARegion *ar) ED_region_header(C, ar); } -static void view3d_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void view3d_header_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -1099,7 +1144,9 @@ static void view3d_buttons_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, NULL, -1, true); } -static void view3d_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void view3d_buttons_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -1205,7 +1252,9 @@ static void view3d_tools_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, CTX_data_mode_string(C), -1, true); } -static void view3d_props_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void view3d_props_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -1225,7 +1274,9 @@ static void view3d_props_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa } /* area (not region) level listener */ -static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNotifier *wmn) +static void space_view3d_listener( + bScreen *UNUSED(sc), ScrArea *sa, struct wmNotifier *wmn, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { View3D *v3d = sa->spacedata.first; @@ -1260,8 +1311,6 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot } const char *view3d_context_dir[] = { - "selected_objects", "selected_bases", "selected_editable_objects", - "selected_editable_bases", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases", "active_base", "active_object", NULL }; @@ -1272,109 +1321,27 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes if (CTX_data_dir(member)) { CTX_data_dir_set(result, view3d_context_dir); } - else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool selected_objects = CTX_data_equals(member, "selected_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (selected_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (0 == BKE_object_is_libdata(base->object)) { - if (selected_editable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool visible_objects = CTX_data_equals(member, "visible_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (base->lay & lay) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (visible_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool selectable_objects = CTX_data_equals(member, "selectable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (base->lay & lay) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) { - if (selectable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } else if (CTX_data_equals(member, "active_base")) { - View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - if (scene->basact && (scene->basact->lay & lay)) { - Object *ob = scene->basact->object; + SceneLayer *sl = CTX_data_scene_layer(C); + if (sl->basact) { + Object *ob = sl->basact->object; /* if hidden but in edit mode, we still display, can happen with animation */ - if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) - CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact); + if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT)) { + CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, sl->basact); + } } return 1; } else if (CTX_data_equals(member, "active_object")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - if (scene->basact && (scene->basact->lay & lay)) { - Object *ob = scene->basact->object; - if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) - CTX_data_id_pointer_set(result, &scene->basact->object->id); + SceneLayer *sl = CTX_data_scene_layer(C); + if (sl->basact) { + Object *ob = sl->basact->object; + /* if hidden but in edit mode, we still display, can happen with animation */ + if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) { + CTX_data_id_pointer_set(result, &ob->id); + } } return 1; @@ -1424,21 +1391,6 @@ static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_i v3d->ob_centre_bone[0] = '\0'; } } - - if (ELEM(GS(old_id->name), ID_IM, ID_MC)) { - for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { - if ((ID *)bgpic->ima == old_id) { - bgpic->ima = (Image *)new_id; - id_us_min(old_id); - id_us_plus(new_id); - } - if ((ID *)bgpic->clip == old_id) { - bgpic->clip = (MovieClip *)new_id; - id_us_min(old_id); - id_us_plus(new_id); - } - } - } } if (is_local) { @@ -1464,6 +1416,7 @@ void ED_spacetype_view3d(void) st->operatortypes = view3d_operatortypes; st->keymap = view3d_keymap; st->dropboxes = view3d_dropboxes; + st->manipulators = view3d_widgets; st->context = view3d_context; st->id_remap = view3d_id_remap; diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 0c67776693d..ac808487dd2 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -55,13 +55,14 @@ #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_customdata.h" -#include "BKE_depsgraph.h" #include "BKE_screen.h" #include "BKE_editmesh.h" #include "BKE_deform.h" #include "BKE_object.h" #include "BKE_object_deform.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -776,18 +777,18 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event) return; } else { - Scene *scene = CTX_data_scene(C); - Object *ob = scene->basact->object; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = sl->basact->object; ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); } } static int view3d_panel_vgroup_poll(const bContext *C, PanelType *UNUSED(pt)) { - Scene *scene = CTX_data_scene(C); - Object *ob = OBACT; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = OBACT(sl); if (ob && (BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob))) { @@ -805,7 +806,8 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) { uiBlock *block = uiLayoutAbsoluteBlock(pa->layout); Scene *scene = CTX_data_scene(C); - Object *ob = scene->basact->object; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = sl->basact->object; MDeformVert *dv; @@ -1095,9 +1097,9 @@ static void v3d_editmetaball_buts(uiLayout *layout, Object *ob) static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event) { - Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); View3D *v3d = CTX_wm_view3d(C); - Object *ob = OBACT; + Object *ob = OBACT(sl); switch (event) { @@ -1108,7 +1110,7 @@ static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event case B_OBJECTPANELMEDIAN: if (ob) { v3d_editvertex_buts(NULL, v3d, ob, 1.0); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } break; } @@ -1119,16 +1121,17 @@ static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event static int view3d_panel_transform_poll(const bContext *C, PanelType *UNUSED(pt)) { - Scene *scene = CTX_data_scene(C); - return (scene->basact != NULL); + SceneLayer *sl = CTX_data_scene_layer(C); + return (sl->basact != NULL); } static void view3d_panel_transform(const bContext *C, Panel *pa) { uiBlock *block; Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); - Object *ob = scene->basact->object; + Object *ob = sl->basact->object; uiLayout *col; block = uiLayoutGetBlock(pa->layout); diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c index f717f1c0a43..9b07593e576 100644 --- a/source/blender/editors/space_view3d/view3d_camera_control.c +++ b/source/blender/editors/space_view3d/view3d_camera_control.c @@ -54,8 +54,9 @@ #include "BLI_utildefines.h" #include "BKE_object.h" +#include "BKE_context.h" -#include "BKE_depsgraph.h" /* for object updating */ +#include "DEG_depsgraph.h" #include "ED_screen.h" @@ -137,10 +138,13 @@ Object *ED_view3d_cameracontrol_object_get(View3DCameraControl *vctrl) * the view for first-person style navigation. */ struct View3DCameraControl *ED_view3d_cameracontrol_acquire( - Scene *scene, View3D *v3d, RegionView3D *rv3d, + const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d, const bool use_parent_root) { View3DCameraControl *vctrl; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); vctrl = MEM_callocN(sizeof(View3DCameraControl), __func__); @@ -177,7 +181,7 @@ struct View3DCameraControl *ED_view3d_cameracontrol_acquire( /* store the original camera loc and rot */ vctrl->obtfm = BKE_object_tfm_backup(ob_back); - BKE_object_where_is_calc(scene, v3d->camera); + BKE_object_where_is_calc(&eval_ctx, scene, v3d->camera); negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]); rv3d->dist = 0.0; @@ -242,7 +246,7 @@ void ED_view3d_cameracontrol_update( ob_update = v3d->camera->parent; while (ob_update) { - DAG_id_tag_update(&ob_update->id, OB_RECALC_OB); + DEG_id_tag_update(&ob_update->id, OB_RECALC_OB); ob_update = ob_update->parent; } @@ -264,7 +268,7 @@ void ED_view3d_cameracontrol_update( BKE_object_apply_mat4(v3d->camera, view_mat, true, true); - DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); + DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); copy_v3_v3(v3d->camera->size, size_back); @@ -299,7 +303,7 @@ void ED_view3d_cameracontrol_release( /* store the original camera loc and rot */ BKE_object_tfm_restore(ob_back, vctrl->obtfm); - DAG_id_tag_update(&ob_back->id, OB_RECALC_OB); + DEG_id_tag_update(&ob_back->id, OB_RECALC_OB); } else { /* Non Camera we need to reset the view back to the original location bacause the user canceled*/ @@ -311,7 +315,7 @@ void ED_view3d_cameracontrol_release( rv3d->dist = vctrl->dist_backup; } else if (vctrl->persp_backup == RV3D_CAMOB) { /* camera */ - DAG_id_tag_update((ID *)view3d_cameracontrol_object(vctrl), OB_RECALC_OB); + DEG_id_tag_update((ID *)view3d_cameracontrol_object(vctrl), OB_RECALC_OB); /* always, is set to zero otherwise */ copy_v3_v3(rv3d->ofs, vctrl->ofs_backup); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 56508ea989a..475e9cd07bf 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -28,948 +28,282 @@ * \ingroup spview3d */ -#include <string.h> -#include <stdio.h> #include <math.h> -#include "DNA_armature_types.h" -#include "DNA_camera_types.h" -#include "DNA_customdata_types.h" -#include "DNA_object_types.h" -#include "DNA_group_types.h" -#include "DNA_mesh_types.h" -#include "DNA_key_types.h" -#include "DNA_lamp_types.h" -#include "DNA_scene_types.h" -#include "DNA_world_types.h" -#include "DNA_brush_types.h" - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" +#include "BLI_listbase.h" #include "BLI_math.h" -#include "BLI_jitter.h" -#include "BLI_utildefines.h" -#include "BLI_endian_switch.h" +#include "BLI_rect.h" +#include "BLI_string.h" #include "BLI_threads.h" +#include "BLI_jitter.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" -#include "BKE_anim.h" #include "BKE_camera.h" #include "BKE_context.h" -#include "BKE_customdata.h" -#include "BKE_DerivedMesh.h" -#include "BKE_image.h" +#include "BKE_global.h" #include "BKE_key.h" -#include "BKE_main.h" +#include "BKE_scene.h" #include "BKE_object.h" -#include "BKE_global.h" #include "BKE_paint.h" -#include "BKE_scene.h" -#include "BKE_screen.h" #include "BKE_unit.h" -#include "BKE_movieclip.h" - -#include "RE_engine.h" -#include "IMB_imbuf_types.h" -#include "IMB_imbuf.h" -#include "IMB_colormanagement.h" +#include "BLF_api.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" +#include "BLT_translation.h" -#include "WM_api.h" +#include "DNA_armature_types.h" +#include "DNA_brush_types.h" +#include "DNA_camera_types.h" +#include "DNA_key_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_view3d_types.h" +#include "DNA_windowmanager_types.h" -#include "BLF_api.h" -#include "BLT_translation.h" +#include "DRW_engine.h" #include "ED_armature.h" #include "ED_keyframing.h" #include "ED_gpencil.h" #include "ED_screen.h" -#include "ED_space_api.h" -#include "ED_screen_types.h" #include "ED_transform.h" -#include "UI_interface.h" -#include "UI_interface_icons.h" -#include "UI_resources.h" +#include "DEG_depsgraph_query.h" #include "GPU_draw.h" -#include "GPU_framebuffer.h" +#include "GPU_matrix.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" #include "GPU_material.h" +#include "GPU_viewport.h" #include "GPU_compositing.h" -#include "GPU_extensions.h" -#include "GPU_select.h" - -#include "view3d_intern.h" /* own include */ - -/* prototypes */ -static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d); -static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect); -static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar, - float winmat[4][4], const char *viewname); - -/* handy utility for drawing shapes in the viewport for arbitrary code. - * could add lines and points too */ -// #define DEBUG_DRAW -#ifdef DEBUG_DRAW -static void bl_debug_draw(void); -/* add these locally when using these functions for testing */ -extern void bl_debug_draw_quad_clear(void); -extern void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]); -extern void bl_debug_draw_edge_add(const float v0[3], const float v1[3]); -extern void bl_debug_color_set(const unsigned int col); -#endif - -void circf(float x, float y, float rad) -{ - GLUquadricObj *qobj = gluNewQuadric(); - - gluQuadricDrawStyle(qobj, GLU_FILL); - - glPushMatrix(); - - glTranslatef(x, y, 0.0); - - gluDisk(qobj, 0.0, rad, 32, 1); - - glPopMatrix(); - - gluDeleteQuadric(qobj); -} - -void circ(float x, float y, float rad) -{ - GLUquadricObj *qobj = gluNewQuadric(); - - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - - glPushMatrix(); - - glTranslatef(x, y, 0.0); - - gluDisk(qobj, 0.0, rad, 32, 1); - - glPopMatrix(); - - gluDeleteQuadric(qobj); -} - -/* ********* custom clipping *********** */ - -static void view3d_draw_clipping(RegionView3D *rv3d) -{ - BoundBox *bb = rv3d->clipbb; - - if (bb) { - const unsigned int clipping_index[6][4] = { - {0, 1, 2, 3}, - {0, 4, 5, 1}, - {4, 7, 6, 5}, - {7, 3, 2, 6}, - {1, 5, 6, 2}, - {7, 4, 0, 3} - }; - - /* fill in zero alpha for rendering & re-projection [#31530] */ - unsigned char col[4]; - UI_GetThemeColor4ubv(TH_V3D_CLIPPING_BORDER, col); - glColor4ubv(col); - - glEnable(GL_BLEND); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, bb->vec); - glDrawElements(GL_QUADS, sizeof(clipping_index) / sizeof(unsigned int), GL_UNSIGNED_INT, clipping_index); - glDisableClientState(GL_VERTEX_ARRAY); - glDisable(GL_BLEND); - } -} +#include "MEM_guardedalloc.h" -void ED_view3d_clipping_set(RegionView3D *rv3d) -{ - double plane[4]; - const unsigned int tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6; - unsigned int a; - - for (a = 0; a < tot; a++) { - copy_v4db_v4fl(plane, rv3d->clip[a]); - glClipPlane(GL_CLIP_PLANE0 + a, plane); - glEnable(GL_CLIP_PLANE0 + a); - } -} +#include "UI_interface.h" +#include "UI_resources.h" -/* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */ -void ED_view3d_clipping_disable(void) -{ - unsigned int a; +#include "RE_engine.h" - for (a = 0; a < 6; a++) { - glDisable(GL_CLIP_PLANE0 + a); - } -} -void ED_view3d_clipping_enable(void) -{ - unsigned int a; +#include "WM_api.h" +#include "WM_types.h" - for (a = 0; a < 6; a++) { - glEnable(GL_CLIP_PLANE0 + a); - } -} +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" -static bool view3d_clipping_test(const float co[3], const float clip[6][4]) -{ - if (plane_point_side_v3(clip[0], co) > 0.0f) - if (plane_point_side_v3(clip[1], co) > 0.0f) - if (plane_point_side_v3(clip[2], co) > 0.0f) - if (plane_point_side_v3(clip[3], co) > 0.0f) - return false; +#include "view3d_intern.h" /* own include */ - return true; -} +/* ******************** general functions ***************** */ -/* for 'local' ED_view3d_clipping_local must run first - * then all comparisons can be done in localspace */ -bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local) +static bool use_depth_doit(Scene *scene, View3D *v3d) { - return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip); -} - -/* ********* end custom clipping *********** */ - - -static void drawgrid_draw(ARegion *ar, double wx, double wy, double x, double y, double dx) -{ - double verts[2][2]; - - x += (wx); - y += (wy); - - /* set fixed 'Y' */ - verts[0][1] = 0.0f; - verts[1][1] = (double)ar->winy; + if (v3d->drawtype > OB_WIRE) + return true; - /* iter over 'X' */ - verts[0][0] = verts[1][0] = x - dx * floor(x / dx); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_DOUBLE, 0, verts); - - while (verts[0][0] < ar->winx) { - glDrawArrays(GL_LINES, 0, 2); - verts[0][0] = verts[1][0] = verts[0][0] + dx; - } - - /* set fixed 'X' */ - verts[0][0] = 0.0f; - verts[1][0] = (double)ar->winx; - - /* iter over 'Y' */ - verts[0][1] = verts[1][1] = y - dx * floor(y / dx); - while (verts[0][1] < ar->winy) { - glDrawArrays(GL_LINES, 0, 2); - verts[0][1] = verts[1][1] = verts[0][1] + dx; + /* special case (depth for wire color) */ + if (v3d->drawtype <= OB_WIRE) { + if (scene->obedit && scene->obedit->type == OB_MESH) { + Mesh *me = scene->obedit->data; + if (me->drawflag & ME_DRAWEIGHT) { + return true; + } + } } - - glDisableClientState(GL_VERTEX_ARRAY); + return false; } -#define GRID_MIN_PX_D 6.0 -#define GRID_MIN_PX_F 6.0f - -static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit) +/** + * \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore + */ +void ED_view3d_update_viewmat( + const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar, + float viewmat[4][4], float winmat[4][4], const rcti *rect) { - /* extern short bgpicmode; */ RegionView3D *rv3d = ar->regiondata; - double wx, wy, x, y, fw, fx, fy, dx; - double vec4[4]; - unsigned char col[3], col2[3]; - - fx = rv3d->persmat[3][0]; - fy = rv3d->persmat[3][1]; - fw = rv3d->persmat[3][3]; - - wx = (ar->winx / 2.0); /* because of rounding errors, grid at wrong location */ - wy = (ar->winy / 2.0); - - x = (wx) * fx / fw; - y = (wy) * fy / fw; - - vec4[0] = vec4[1] = v3d->grid; - - vec4[2] = 0.0; - vec4[3] = 1.0; - mul_m4_v4d(rv3d->persmat, vec4); - fx = vec4[0]; - fy = vec4[1]; - fw = vec4[3]; - - dx = fabs(x - (wx) * fx / fw); - if (dx == 0) dx = fabs(y - (wy) * fy / fw); - - glLineWidth(1.0f); - glDepthMask(GL_FALSE); /* disable write in zbuffer */ - - /* check zoom out */ - UI_ThemeColor(TH_GRID); - - if (unit->system) { - /* Use GRID_MIN_PX * 2 for units because very very small grid - * items are less useful when dealing with units */ - const void *usys; - int len, i; - double dx_scalar; - float blend_fac; - bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len); - - if (usys) { - i = len; - while (i--) { - double scalar = bUnit_GetScaler(usys, i); - - dx_scalar = dx * scalar / (double)unit->scale_length; - if (dx_scalar < (GRID_MIN_PX_D * 2.0)) - continue; + /* setup window matrices */ + if (winmat) + copy_m4_m4(rv3d->winmat, winmat); + else + view3d_winmatrix_set(ar, v3d, rect); - /* Store the smallest drawn grid size units name so users know how big each grid cell is */ - if (*grid_unit == NULL) { - *grid_unit = bUnit_GetNameDisplay(usys, i); - rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length); - } - blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar); + /* setup view matrix */ + if (viewmat) + copy_m4_m4(rv3d->viewmat, viewmat); + else + view3d_viewmatrix_set(eval_ctx, scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */ - /* tweak to have the fade a bit nicer */ - blend_fac = (blend_fac * blend_fac) * 2.0f; - CLAMP(blend_fac, 0.3f, 1.0f); + /* update utility matrices */ + mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); + invert_m4_m4(rv3d->persinv, rv3d->persmat); + invert_m4_m4(rv3d->viewinv, rv3d->viewmat); + /* calculate GLSL view dependent values */ - UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, blend_fac); + /* store window coordinates scaling/offset */ + if (rv3d->persp == RV3D_CAMOB && v3d->camera) { + rctf cameraborder; + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false); + rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder); + rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder); - drawgrid_draw(ar, wx, wy, x, y, dx_scalar); - } - } + rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx; + rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy; } else { - const double sublines = v3d->gridsubdiv; - const float sublines_fl = v3d->gridsubdiv; - - if (dx < GRID_MIN_PX_D) { - rv3d->gridview *= sublines_fl; - dx *= sublines; - - if (dx < GRID_MIN_PX_D) { - rv3d->gridview *= sublines_fl; - dx *= sublines; - - if (dx < GRID_MIN_PX_D) { - rv3d->gridview *= sublines_fl; - dx *= sublines; - if (dx < GRID_MIN_PX_D) { - /* pass */ - } - else { - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, dx); - } - } - else { /* start blending out */ - UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); - drawgrid_draw(ar, wx, wy, x, y, dx); - - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, sublines * dx); - } - } - else { /* start blending out (GRID_MIN_PX < dx < (GRID_MIN_PX * 10)) */ - UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); - drawgrid_draw(ar, wx, wy, x, y, dx); - - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, sublines * dx); - } - } - else { - if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */ - rv3d->gridview /= sublines_fl; - dx /= sublines; - if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */ - rv3d->gridview /= sublines_fl; - dx /= sublines; - if (dx > (GRID_MIN_PX_D * 10.0)) { - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, dx); - } - else { - UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); - drawgrid_draw(ar, wx, wy, x, y, dx); - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, dx * sublines); - } - } - else { - UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); - drawgrid_draw(ar, wx, wy, x, y, dx); - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, dx * sublines); - } - } - else { - UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); - drawgrid_draw(ar, wx, wy, x, y, dx); - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, dx * sublines); - } - } + rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f; + rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f; } + /* calculate pixelsize factor once, is used for lamps and obcenters */ + { + /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' + * because of float point precision problems at large values [#23908] */ + float v1[3], v2[3]; + float len_px, len_sc; - x += (wx); - y += (wy); - UI_GetThemeColor3ubv(TH_GRID, col); - - setlinestyle(0); - - /* center cross */ - /* horizontal line */ - if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) - UI_make_axis_color(col, col2, 'Y'); - else UI_make_axis_color(col, col2, 'X'); - glColor3ubv(col2); - - fdrawline(0.0, y, (float)ar->winx, y); - - /* vertical line */ - if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) - UI_make_axis_color(col, col2, 'Y'); - else UI_make_axis_color(col, col2, 'Z'); - glColor3ubv(col2); - - fdrawline(x, 0.0, x, (float)ar->winy); - - glDepthMask(GL_TRUE); /* enable write in zbuffer */ -} -#undef GRID_MIN_PX + v1[0] = rv3d->persmat[0][0]; + v1[1] = rv3d->persmat[1][0]; + v1[2] = rv3d->persmat[2][0]; -/** could move this elsewhere, but tied into #ED_view3d_grid_scale */ -float ED_scene_grid_scale(Scene *scene, const char **grid_unit) -{ - /* apply units */ - if (scene->unit.system) { - const void *usys; - int len; + v2[0] = rv3d->persmat[0][1]; + v2[1] = rv3d->persmat[1][1]; + v2[2] = rv3d->persmat[2][1]; - bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len); + len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2))); + len_sc = (float)MAX2(ar->winx, ar->winy); - if (usys) { - int i = bUnit_GetBaseUnit(usys); - if (grid_unit) - *grid_unit = bUnit_GetNameDisplay(usys, i); - return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length; - } + rv3d->pixsize = len_px / len_sc; } - - return 1.0f; -} - -float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) -{ - return v3d->grid * ED_scene_grid_scale(scene, grid_unit); } -static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth) +static void view3d_main_region_setup_view( + const EvaluationContext *eval_ctx, Scene *scene, + View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect) { - float grid, grid_scale; - unsigned char col_grid[3]; - const int gridlines = v3d->gridlines / 2; - - if (v3d->gridlines < 3) return; - - /* use 'grid_scale' instead of 'v3d->grid' from now on */ - grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit); - grid = gridlines * grid_scale; - - if (!write_depth) - glDepthMask(GL_FALSE); - - UI_GetThemeColor3ubv(TH_GRID, col_grid); - - glLineWidth(1); - - /* draw the Y axis and/or grid lines */ - if (v3d->gridflag & V3D_SHOW_FLOOR) { - const int sublines = v3d->gridsubdiv; - float vert[4][3] = {{0.0f}}; - unsigned char col_bg[3]; - unsigned char col_grid_emphasise[3], col_grid_light[3]; - int a; - int prev_emphasise = -1; - - UI_GetThemeColor3ubv(TH_BACK, col_bg); - - /* emphasise division lines lighter instead of darker, if background is darker than grid */ - UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10); - UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise, - (((col_grid[0] + col_grid[1] + col_grid[2]) + 30) > - (col_bg[0] + col_bg[1] + col_bg[2])) ? 20 : -10); - - /* set fixed axis */ - vert[0][0] = vert[2][1] = grid; - vert[1][0] = vert[3][1] = -grid; - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vert); - - for (a = -gridlines; a <= gridlines; a++) { - const float line = a * grid_scale; - const int is_emphasise = (a % sublines) == 0; - - if (is_emphasise != prev_emphasise) { - glColor3ubv(is_emphasise ? col_grid_emphasise : col_grid_light); - prev_emphasise = is_emphasise; - } - - /* set variable axis */ - vert[0][1] = vert[1][1] = vert[2][0] = vert[3][0] = line; + RegionView3D *rv3d = ar->regiondata; - glDrawArrays(GL_LINES, 0, 4); - } + ED_view3d_update_viewmat(eval_ctx, scene, v3d, ar, viewmat, winmat, rect); - glDisableClientState(GL_VERTEX_ARRAY); - } - - /* draw the Z axis line */ - /* check for the 'show Z axis' preference */ - if (v3d->gridflag & (V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) { - glBegin(GL_LINES); - int axis; - for (axis = 0; axis < 3; axis++) { - if (v3d->gridflag & (V3D_SHOW_X << axis)) { - float vert[3]; - unsigned char tcol[3]; - - UI_make_axis_color(col_grid, tcol, 'X' + axis); - glColor3ubv(tcol); - - zero_v3(vert); - vert[axis] = grid; - glVertex3fv(vert); - vert[axis] = -grid; - glVertex3fv(vert); - } - } - glEnd(); - } - - glDepthMask(GL_TRUE); + /* set for opengl */ + gpuLoadProjectionMatrix(rv3d->winmat); + gpuLoadMatrix(rv3d->viewmat); } - -static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d) +static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d) { - int co[2]; - - /* we don't want the clipping for cursor */ - if (ED_view3d_project_int_global(ar, ED_view3d_cursor3d_get(scene, v3d), co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - const float f5 = 0.25f * U.widget_unit; - const float f10 = 0.5f * U.widget_unit; - const float f20 = U.widget_unit; - - glLineWidth(1); - setlinestyle(0); - cpack(0xFF); - circ((float)co[0], (float)co[1], f10); - setlinestyle(4); - cpack(0xFFFFFF); - circ((float)co[0], (float)co[1], f10); - setlinestyle(0); - - UI_ThemeColor(TH_VIEW_OVERLAY); - sdrawline(co[0] - f20, co[1], co[0] - f5, co[1]); - sdrawline(co[0] + f5, co[1], co[0] + f20, co[1]); - sdrawline(co[0], co[1] - f20, co[0], co[1] - f5); - sdrawline(co[0], co[1] + f5, co[0], co[1] + f20); + if ((scene->r.scemode & R_MULTIVIEW) == 0) { + return false; } -} - -/* Draw a live substitute of the view icon, which is always shown - * colors copied from transform_manipulator.c, we should keep these matching. */ -static void draw_view_axis(RegionView3D *rv3d, rcti *rect) -{ - const float k = U.rvisize * U.pixelsize; /* axis size */ - const float toll = 0.5; /* used to see when view is quasi-orthogonal */ - float startx = k + 1.0f; /* axis center in screen coordinates, x=y */ - float starty = k + 1.0f; - float ydisp = 0.0; /* vertical displacement to allow obj info text */ - int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */ - float vec[3]; - float dx, dy; - - int axis_order[3] = {0, 1, 2}; - int axis_i; - startx += rect->xmin; - starty += rect->ymin; - - axis_sort_v3(rv3d->viewinv[2], axis_order); - - /* thickness of lines is proportional to k */ - glLineWidth(2); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - for (axis_i = 0; axis_i < 3; axis_i++) { - int i = axis_order[axis_i]; - const char axis_text[2] = {'x' + i, '\0'}; - - zero_v3(vec); - vec[i] = 1.0f; - mul_qt_v3(rv3d->viewquat, vec); - dx = vec[0] * k; - dy = vec[1] * k; - - UI_ThemeColorShadeAlpha(TH_AXIS_X + i, 0, bright); - glBegin(GL_LINES); - glVertex2f(startx, starty + ydisp); - glVertex2f(startx + dx, starty + dy + ydisp); - glEnd(); - - if (fabsf(dx) > toll || fabsf(dy) > toll) { - BLF_draw_default_ascii(startx + dx + 2, starty + dy + ydisp + 2, 0.0f, axis_text, 1); - - /* BLF_draw_default disables blending */ - glEnable(GL_BLEND); - } + if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) { + return false; } - glDisable(GL_BLEND); -} - -#ifdef WITH_INPUT_NDOF -/* draw center and axis of rotation for ongoing 3D mouse navigation */ -static void draw_rotation_guide(RegionView3D *rv3d) -{ - float o[3]; /* center of rotation */ - float end[3]; /* endpoints for drawing */ - - float color[4] = {0.0f, 0.4235f, 1.0f, 1.0f}; /* bright blue so it matches device LEDs */ - - negate_v3_v3(o, rv3d->ofs); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glPointSize(5); - glEnable(GL_POINT_SMOOTH); - glDepthMask(0); /* don't overwrite zbuf */ - - if (rv3d->rot_angle != 0.0f) { - /* -- draw rotation axis -- */ - float scaled_axis[3]; - const float scale = rv3d->dist; - mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale); - - - glBegin(GL_LINE_STRIP); - color[3] = 0.0f; /* more transparent toward the ends */ - glColor4fv(color); - add_v3_v3v3(end, o, scaled_axis); - glVertex3fv(end); - -#if 0 - color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */ - /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */ -#endif - - color[3] = 0.5f; /* more opaque toward the center */ - glColor4fv(color); - glVertex3fv(o); - - color[3] = 0.0f; - glColor4fv(color); - sub_v3_v3v3(end, o, scaled_axis); - glVertex3fv(end); - glEnd(); - - /* -- draw ring around rotation center -- */ - { -#define ROT_AXIS_DETAIL 13 - - const float s = 0.05f * scale; - const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL); - float angle; - int i; - - float q[4]; /* rotate ring so it's perpendicular to axis */ - const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f; - if (!upright) { - const float up[3] = {0.0f, 0.0f, 1.0f}; - float vis_angle, vis_axis[3]; - - cross_v3_v3v3(vis_axis, up, rv3d->rot_axis); - vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis)); - axis_angle_to_quat(q, vis_axis, vis_angle); + switch (v3d->stereo3d_camera) { + case STEREO_MONO_ID: + return false; + break; + case STEREO_3D_ID: + /* win will be NULL when calling this from the selection or draw loop. */ + if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) { + return false; } - - color[3] = 0.25f; /* somewhat faint */ - glColor4fv(color); - glBegin(GL_LINE_LOOP); - for (i = 0, angle = 0.0f; i < ROT_AXIS_DETAIL; ++i, angle += step) { - float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f}; - - if (!upright) { - mul_qt_v3(q, p); - } - - add_v3_v3(p, o); - glVertex3fv(p); + if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) && + !BKE_scene_multiview_is_stereo3d(&scene->r)) + { + return false; } - glEnd(); - -#undef ROT_AXIS_DETAIL - } - - color[3] = 1.0f; /* solid dot */ - } - else - color[3] = 0.5f; /* see-through dot */ - - /* -- draw rotation center -- */ - glColor4fv(color); - glBegin(GL_POINTS); - glVertex3fv(o); - glEnd(); - -#if 0 - /* find screen coordinates for rotation center, then draw pretty icon */ - mul_m4_v3(rv3d->persinv, rot_center); - UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN); - /* ^^ just playing around, does not work */ -#endif - - glDisable(GL_BLEND); - glDisable(GL_POINT_SMOOTH); - glDepthMask(1); -} -#endif /* WITH_INPUT_NDOF */ - -static void draw_view_icon(RegionView3D *rv3d, rcti *rect) -{ - BIFIconID icon; - - if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) - icon = ICON_AXIS_TOP; - else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) - icon = ICON_AXIS_FRONT; - else if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) - icon = ICON_AXIS_SIDE; - else return; - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - UI_icon_draw(5.0 + rect->xmin, 5.0 + rect->ymin, icon); - - glDisable(GL_BLEND); -} - -static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d) -{ - const char *name = NULL; - - switch (rv3d->view) { - case RV3D_VIEW_FRONT: - if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho"); - else name = IFACE_("Front Persp"); - break; - case RV3D_VIEW_BACK: - if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho"); - else name = IFACE_("Back Persp"); - break; - case RV3D_VIEW_TOP: - if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho"); - else name = IFACE_("Top Persp"); - break; - case RV3D_VIEW_BOTTOM: - if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho"); - else name = IFACE_("Bottom Persp"); - break; - case RV3D_VIEW_RIGHT: - if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho"); - else name = IFACE_("Right Persp"); break; - case RV3D_VIEW_LEFT: - if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho"); - else name = IFACE_("Left Persp"); - break; - + /* We always need the stereo calculation for left and right cameras. */ + case STEREO_LEFT_ID: + case STEREO_RIGHT_ID: default: - if (rv3d->persp == RV3D_CAMOB) { - if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) { - Camera *cam; - cam = v3d->camera->data; - if (cam->type == CAM_PERSP) { - name = IFACE_("Camera Persp"); - } - else if (cam->type == CAM_ORTHO) { - name = IFACE_("Camera Ortho"); - } - else { - BLI_assert(cam->type == CAM_PANO); - name = IFACE_("Camera Pano"); - } - } - else { - name = IFACE_("Object as Camera"); - } - } - else { - name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp"); - } break; } - - return name; + return true; } -static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect) -{ - RegionView3D *rv3d = ar->regiondata; - const char *name = view3d_get_name(v3d, rv3d); - /* increase size for unicode languages (Chinese in utf-8...) */ -#ifdef WITH_INTERNATIONAL - char tmpstr[96]; -#else - char tmpstr[32]; -#endif - if (v3d->localvd) { - BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name); - name = tmpstr; - } +/* setup the view and win matrices for the multiview cameras + * + * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called + * we have no winmatrix (i.e., projection matrix) defined at that time. + * Since the camera and the camera shift are needed for the winmat calculation + * we do a small hack to replace it temporarily so we don't need to change the + * view3d)main_region_setup_view() code to account for that. + */ +static void view3d_stereo3d_setup( + const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect) +{ + bool is_left; + const char *names[2] = { STEREO_LEFT_NAME, STEREO_RIGHT_NAME }; + const char *viewname; - UI_ThemeColor(TH_TEXT_HI); -#ifdef WITH_INTERNATIONAL - BLF_draw_default(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr)); -#else - BLF_draw_default_ascii(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr)); -#endif -} + /* show only left or right camera */ + if (v3d->stereo3d_camera != STEREO_3D_ID) + v3d->multiview_eye = v3d->stereo3d_camera; -/* draw info beside axes in bottom left-corner: - * framenum, object name, bone name (if available), marker name (if available) - */ + is_left = v3d->multiview_eye == STEREO_LEFT_ID; + viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID]; -static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) -{ - const int cfra = CFRA; - const char *msg_pin = " (Pinned)"; - const char *msg_sep = " : "; + /* update the viewport matrices with the new camera */ + if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { + Camera *data; + float viewmat[4][4]; + float shiftx; - char info[300]; - const char *markern; - char *s = info; - short offset = 1.5f * UI_UNIT_X + rect->xmin; + data = (Camera *)v3d->camera->data; + shiftx = data->shiftx; - s += sprintf(s, "(%d)", cfra); + BLI_lock_thread(LOCK_VIEW3D); + data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname); - /* - * info can contain: - * - a frame (7 + 2) - * - 3 object names (MAX_NAME) - * - 2 BREAD_CRUMB_SEPARATORs (6) - * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room! - * - a marker name (MAX_NAME + 3) - */ + BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, NULL, rect); - /* get name of marker on current frame (if available) */ - markern = BKE_scene_find_marker_name(scene, cfra); - - /* check if there is an object */ - if (ob) { - *s++ = ' '; - s += BLI_strcpy_rlen(s, ob->id.name + 2); + data->shiftx = shiftx; + BLI_unlock_thread(LOCK_VIEW3D); + } + else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ + float viewmat[4][4]; + Object *view_ob = v3d->camera; + Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); - /* name(s) to display depends on type of object */ - if (ob->type == OB_ARMATURE) { - bArmature *arm = ob->data; - - /* show name of active bone too (if possible) */ - if (arm->edbo) { - if (arm->act_edbone) { - s += BLI_strcpy_rlen(s, msg_sep); - s += BLI_strcpy_rlen(s, arm->act_edbone->name); - } - } - else if (ob->mode & OB_MODE_POSE) { - if (arm->act_bone) { + BLI_lock_thread(LOCK_VIEW3D); + v3d->camera = camera; - if (arm->act_bone->layer & arm->layer) { - s += BLI_strcpy_rlen(s, msg_sep); - s += BLI_strcpy_rlen(s, arm->act_bone->name); - } - } - } - } - else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) { - Key *key = NULL; - KeyBlock *kb = NULL; + BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, NULL, rect); - /* try to display active bone and active shapekey too (if they exist) */ + v3d->camera = view_ob; + BLI_unlock_thread(LOCK_VIEW3D); + } +} - if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) { - Object *armobj = BKE_object_pose_armature_get(ob); - if (armobj && armobj->mode & OB_MODE_POSE) { - bArmature *arm = armobj->data; - if (arm->act_bone) { - if (arm->act_bone->layer & arm->layer) { - s += BLI_strcpy_rlen(s, msg_sep); - s += BLI_strcpy_rlen(s, arm->act_bone->name); - } - } - } - } +/** + * Set the correct matrices + */ +void ED_view3d_draw_setup_view( + wmWindow *win, const EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d, + float viewmat[4][4], float winmat[4][4], const rcti *rect) +{ + RegionView3D *rv3d = ar->regiondata; - key = BKE_key_from_object(ob); - if (key) { - kb = BLI_findlink(&key->block, ob->shapenr - 1); - if (kb) { - s += BLI_strcpy_rlen(s, msg_sep); - s += BLI_strcpy_rlen(s, kb->name); - if (ob->shapeflag & OB_SHAPE_LOCK) { - s += BLI_strcpy_rlen(s, IFACE_(msg_pin)); - } - } - } - } - - /* color depends on whether there is a keyframe */ - if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) - UI_ThemeColor(TH_TIME_KEYFRAME); - else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) - UI_ThemeColor(TH_TIME_GP_KEYFRAME); - else - UI_ThemeColor(TH_TEXT_HI); + /* Setup the view matrix. */ + if (view3d_stereo3d_active(win, scene, v3d, rv3d)) { + view3d_stereo3d_setup(eval_ctx, scene, v3d, ar, rect); } else { - /* no object */ - if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra)) - UI_ThemeColor(TH_TIME_GP_KEYFRAME); - else - UI_ThemeColor(TH_TEXT_HI); + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, rect); } - - if (markern) { - s += sprintf(s, " <%s>", markern); - } - - if (U.uiflag & USER_SHOW_ROTVIEWICON) - offset = U.widget_unit + (U.rvisize * 2) + rect->xmin; - - BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info)); } +/* ******************** view border ***************** */ + static void view3d_camera_border( const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d, rctf *r_viewborder, const bool no_shift, const bool no_zoom) @@ -1023,7 +357,7 @@ void ED_view3d_calc_camera_border( view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, no_shift, false); } -static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float fac) +static void drawviewborder_grid3(uint shdr_pos, float x1, float x2, float y1, float y2, float fac) { float x3, y3, x4, y4; @@ -1032,29 +366,33 @@ static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float f x4 = x1 + (1.0f - fac) * (x2 - x1); y4 = y1 + (1.0f - fac) * (y2 - y1); - glBegin(GL_LINES); - glVertex2f(x1, y3); - glVertex2f(x2, y3); + immBegin(GWN_PRIM_LINES, 8); + + immVertex2f(shdr_pos, x1, y3); + immVertex2f(shdr_pos, x2, y3); - glVertex2f(x1, y4); - glVertex2f(x2, y4); + immVertex2f(shdr_pos, x1, y4); + immVertex2f(shdr_pos, x2, y4); - glVertex2f(x3, y1); - glVertex2f(x3, y2); + immVertex2f(shdr_pos, x3, y1); + immVertex2f(shdr_pos, x3, y2); - glVertex2f(x4, y1); - glVertex2f(x4, y2); - glEnd(); + immVertex2f(shdr_pos, x4, y1); + immVertex2f(shdr_pos, x4, y2); + + immEnd(); } /* harmonious triangle */ -static void drawviewborder_triangle(float x1, float x2, float y1, float y2, const char golden, const char dir) +static void drawviewborder_triangle( + uint shdr_pos, float x1, float x2, float y1, float y2, const char golden, const char dir) { float ofs; float w = x2 - x1; float h = y2 - y1; - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, 6); + if (w > h) { if (golden) { ofs = w * (1.0f - (1.0f / 1.61803399f)); @@ -1064,14 +402,14 @@ static void drawviewborder_triangle(float x1, float x2, float y1, float y2, cons } if (dir == 'B') SWAP(float, y1, y2); - glVertex2f(x1, y1); - glVertex2f(x2, y2); + immVertex2f(shdr_pos, x1, y1); + immVertex2f(shdr_pos, x2, y2); - glVertex2f(x2, y1); - glVertex2f(x1 + (w - ofs), y2); + immVertex2f(shdr_pos, x2, y1); + immVertex2f(shdr_pos, x1 + (w - ofs), y2); - glVertex2f(x1, y2); - glVertex2f(x1 + ofs, y1); + immVertex2f(shdr_pos, x1, y2); + immVertex2f(shdr_pos, x1 + ofs, y1); } else { if (golden) { @@ -1082,16 +420,17 @@ static void drawviewborder_triangle(float x1, float x2, float y1, float y2, cons } if (dir == 'B') SWAP(float, x1, x2); - glVertex2f(x1, y1); - glVertex2f(x2, y2); + immVertex2f(shdr_pos, x1, y1); + immVertex2f(shdr_pos, x2, y2); - glVertex2f(x2, y1); - glVertex2f(x1, y1 + ofs); + immVertex2f(shdr_pos, x2, y1); + immVertex2f(shdr_pos, x1, y1 + ofs); - glVertex2f(x1, y2); - glVertex2f(x2, y1 + (h - ofs)); + immVertex2f(shdr_pos, x1, y2); + immVertex2f(shdr_pos, x2, y1 + (h - ofs)); } - glEnd(); + + immEnd(); } static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) @@ -1128,58 +467,76 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) y1i = (int)(y1 - 1.0001f); x2i = (int)(x2 + (1.0f - 0.0001f)); y2i = (int)(y2 + (1.0f - 0.0001f)); - - /* passepartout, specified in camera edit buttons */ - if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) { - const float winx = (ar->winx + 1); - const float winy = (ar->winy + 1); - if (ca->passepartalpha == 1.0f) { - glColor3f(0, 0, 0); + uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + /* First, solid lines. */ + { + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* passepartout, specified in camera edit buttons */ + if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) { + const float winx = (ar->winx + 1); + const float winy = (ar->winy + 1); + + float alpha = 1.0f; + + if (ca->passepartalpha != 1.0f) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + alpha = ca->passepartalpha; + } + + immUniformColor4f(0.0f, 0.0f, 0.0f, alpha); + + if (x1i > 0.0f) + immRectf(shdr_pos, 0.0f, winy, x1i, 0.0f); + if (x2i < winx) + immRectf(shdr_pos, x2i, winy, winx, 0.0f); + if (y2i < winy) + immRectf(shdr_pos, x1i, winy, x2i, y2i); + if (y2i > 0.0f) + immRectf(shdr_pos, x1i, y1i, x2i, 0.0f); + + glDisable(GL_BLEND); } - else { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glColor4f(0, 0, 0, ca->passepartalpha); + + immUniformThemeColor(TH_BACK); + imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i); + +#ifdef VIEW3D_CAMERA_BORDER_HACK + if (view3d_camera_border_hack_test == true) { + immUniformColor3ubv(view3d_camera_border_hack_col); + imm_draw_box_wire_2d(shdr_pos, x1i + 1, y1i + 1, x2i - 1, y2i - 1); + view3d_camera_border_hack_test = false; } +#endif - if (x1i > 0.0f) - glRectf(0.0, winy, x1i, 0.0); - if (x2i < winx) - glRectf(x2i, winy, winx, 0.0); - if (y2i < winy) - glRectf(x1i, winy, x2i, y2i); - if (y2i > 0.0f) - glRectf(x1i, y1i, x2i, 0.0); - - glDisable(GL_BLEND); + immUnbindProgram(); } - setlinestyle(0); + /* And now, the dashed lines! */ + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - UI_ThemeColor(TH_BACK); - - fdrawbox(x1i, y1i, x2i, y2i); + { + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); -#ifdef VIEW3D_CAMERA_BORDER_HACK - if (view3d_camera_border_hack_test == true) { - glColor3ubv(view3d_camera_border_hack_col); - fdrawbox(x1i + 1, y1i + 1, x2i - 1, y2i - 1); - view3d_camera_border_hack_test = false; - } -#endif + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); - setlinestyle(3); + /* outer line not to confuse with object selection */ + if (v3d->flag2 & V3D_LOCK_CAMERA) { + immUniformThemeColor(TH_REDALERT); + imm_draw_box_wire_2d(shdr_pos, x1i - 1, y1i - 1, x2i + 1, y2i + 1); + } - /* outer line not to confuse with object selecton */ - if (v3d->flag2 & V3D_LOCK_CAMERA) { - UI_ThemeColor(TH_REDALERT); - fdrawbox(x1i - 1, y1i - 1, x2i + 1, y2i + 1); + immUniformThemeColor(TH_VIEW_OVERLAY); + imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i); } - UI_ThemeColor(TH_VIEW_OVERLAY); - fdrawbox(x1i, y1i, x2i, y2i); - /* border */ if (scene->r.mode & R_BORDER) { float x3, y3, x4, y4; @@ -1189,82 +546,76 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) x4 = floorf(x1 + (scene->r.border.xmax * (x2 - x1))) + (U.pixelsize - 1); y4 = floorf(y1 + (scene->r.border.ymax * (y2 - y1))) + (U.pixelsize - 1); - cpack(0x4040FF); - sdrawbox(x3, y3, x4, y4); + immUniformColor3f(1.0f, 0.25f, 0.25f); + imm_draw_box_wire_2d(shdr_pos, x3, y3, x4, y4); } /* safety border */ if (ca) { + immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f); + if (ca->dtx & CAM_DTX_CENTER) { float x3, y3; - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - x3 = x1 + 0.5f * (x2 - x1); y3 = y1 + 0.5f * (y2 - y1); - glBegin(GL_LINES); - glVertex2f(x1, y3); - glVertex2f(x2, y3); + immBegin(GWN_PRIM_LINES, 4); - glVertex2f(x3, y1); - glVertex2f(x3, y2); - glEnd(); + immVertex2f(shdr_pos, x1, y3); + immVertex2f(shdr_pos, x2, y3); + + immVertex2f(shdr_pos, x3, y1); + immVertex2f(shdr_pos, x3, y2); + + immEnd(); } if (ca->dtx & CAM_DTX_CENTER_DIAG) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); + immBegin(GWN_PRIM_LINES, 4); - glBegin(GL_LINES); - glVertex2f(x1, y1); - glVertex2f(x2, y2); + immVertex2f(shdr_pos, x1, y1); + immVertex2f(shdr_pos, x2, y2); - glVertex2f(x1, y2); - glVertex2f(x2, y1); - glEnd(); + immVertex2f(shdr_pos, x1, y2); + immVertex2f(shdr_pos, x2, y1); + + immEnd(); } if (ca->dtx & CAM_DTX_THIRDS) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_grid3(x1, x2, y1, y2, 1.0f / 3.0f); + drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f / 3.0f); } if (ca->dtx & CAM_DTX_GOLDEN) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_grid3(x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f)); + drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f)); } if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_triangle(x1, x2, y1, y2, 0, 'A'); + drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'A'); } if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_triangle(x1, x2, y1, y2, 0, 'B'); + drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'B'); } if (ca->dtx & CAM_DTX_HARMONY_TRI_A) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_triangle(x1, x2, y1, y2, 1, 'A'); + drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'A'); } if (ca->dtx & CAM_DTX_HARMONY_TRI_B) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_triangle(x1, x2, y1, y2, 1, 'B'); + drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'B'); } if (ca->flag & CAM_SHOW_SAFE_MARGINS) { UI_draw_safe_areas( - x1, x2, y1, y2, - scene->safe_areas.title, - scene->safe_areas.action); + shdr_pos, x1, x2, y1, y2, + scene->safe_areas.title, scene->safe_areas.action); if (ca->flag & CAM_SHOW_SAFE_CENTER) { UI_draw_safe_areas( - x1, x2, y1, y2, - scene->safe_areas.title_center, - scene->safe_areas.action_center); + shdr_pos, x1, x2, y1, y2, + scene->safe_areas.title_center, scene->safe_areas.action_center); } } @@ -1300,1776 +651,1294 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) } /* draw */ - UI_ThemeColorShade(TH_VIEW_OVERLAY, 100); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f); + immUniformThemeColorShade(TH_VIEW_OVERLAY, 100); + + /* TODO Was using UI_draw_roundbox_4fv(false, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color). + * We'll probably need a new imm_draw_line_roundbox_dashed dor that - though in practice the + * 2.0f round corner effect was nearly not visible anyway... */ + imm_draw_box_wire_2d(shdr_pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); } } - setlinestyle(0); + immUnbindProgram(); + /* end dashed lines */ /* camera name - draw in highlighted text color */ if (ca && (ca->flag & CAM_SHOWNAME)) { - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); BLF_draw_default( x1i, y1i - (0.7f * U.widget_unit), 0.0f, v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2); } } -/* *********************** backdraw for selection *************** */ +static void drawrenderborder(ARegion *ar, View3D *v3d) +{ + /* use the same program for everything */ + uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + glLineWidth(1.0f); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniform4f("color", 1.0f, 0.25f, 0.25f, 1.0f); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + + imm_draw_box_wire_2d(shdr_pos, + v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy, + v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy); + + immUnbindProgram(); +} -static void backdrawview3d(Scene *scene, wmWindow *win, ARegion *ar, View3D *v3d) +void ED_view3d_draw_depth( + const EvaluationContext *eval_ctx, struct Depsgraph *graph, + ARegion *ar, View3D *v3d, bool alphaoverride) { + struct bThemeState theme_state; + Scene *scene = DEG_get_evaluated_scene(graph); RegionView3D *rv3d = ar->regiondata; - struct Base *base = scene->basact; - int multisample_enabled; - BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); + short zbuf = v3d->zbuf; + short flag = v3d->flag; + float glalphaclip = U.glalphaclip; + int obcenter_dia = U.obcenter_dia; + /* temp set drawtype to solid */ + /* Setting these temporarily is not nice */ + v3d->flag &= ~V3D_SELECT_OUTLINE; + U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */ + U.obcenter_dia = 0; - if (base && (base->object->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) || - BKE_paint_select_face_test(base->object))) - { - /* do nothing */ - } - /* texture paint mode sampling */ - else if (base && (base->object->mode & OB_MODE_TEXTURE_PAINT) && - (v3d->drawtype > OB_WIRE)) - { - /* do nothing */ - } - else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) && - V3D_IS_ZBUF(v3d)) - { - /* do nothing */ - } - else if (scene->obedit && - V3D_IS_ZBUF(v3d)) - { - /* do nothing */ - } - else { - v3d->flag &= ~V3D_INVALID_BACKBUF; - return; - } + /* Tools may request depth outside of regular drawing code. */ + UI_Theme_Store(&theme_state); + UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); - if (!(v3d->flag & V3D_INVALID_BACKBUF)) - return; + ED_view3d_draw_setup_view(NULL, eval_ctx, scene, ar, v3d, NULL, NULL, NULL); -#if 0 - if (test) { - if (qtest()) { - addafterqueue(ar->win, BACKBUFDRAW, 1); - return; - } - } -#endif + glClear(GL_DEPTH_BUFFER_BIT); - if (v3d->drawtype > OB_WIRE) v3d->zbuf = true; - - /* dithering and AA break color coding, so disable */ - glDisable(GL_DITHER); - - multisample_enabled = glIsEnabled(GL_MULTISAMPLE); - if (multisample_enabled) - glDisable(GL_MULTISAMPLE); - - if (win->multisamples != USER_MULTISAMPLE_NONE) { - /* for multisample we use an offscreen FBO. multisample drawing can fail - * with color coded selection drawing, and reading back depths from such - * a buffer can also cause a few seconds freeze on OS X / NVidia. */ - int w = BLI_rcti_size_x(&ar->winrct); - int h = BLI_rcti_size_y(&ar->winrct); - char error[256]; - - if (rv3d->gpuoffscreen) { - if (GPU_offscreen_width(rv3d->gpuoffscreen) != w || - GPU_offscreen_height(rv3d->gpuoffscreen) != h) - { - GPU_offscreen_free(rv3d->gpuoffscreen); - rv3d->gpuoffscreen = NULL; - } - } + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_set(rv3d); + } + /* get surface depth without bias */ + rv3d->rflag |= RV3D_ZOFFSET_DISABLED; - if (!rv3d->gpuoffscreen) { - rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error); + v3d->zbuf = true; + glEnable(GL_DEPTH_TEST); - if (!rv3d->gpuoffscreen) - fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error); - } +#ifdef WITH_OPENGL_LEGACY + if (IS_VIEWPORT_LEGACY(vc->v3d)) { + /* temp, calls into view3d_draw_legacy.c */ + ED_view3d_draw_depth_loop(scene, ar, v3d); } - - if (rv3d->gpuoffscreen) - GPU_offscreen_bind(rv3d->gpuoffscreen, true); else - glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct)); - - glClearColor(0.0, 0.0, 0.0, 0.0); - if (v3d->zbuf) { - glEnable(GL_DEPTH_TEST); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +#endif /* WITH_OPENGL_LEGACY */ + { + DRW_draw_depth_loop(graph, ar, v3d); } - else { - glClear(GL_COLOR_BUFFER_BIT); - glDisable(GL_DEPTH_TEST); + + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_disable(); } - - if (rv3d->rflag & RV3D_CLIPPING) - ED_view3d_clipping_set(rv3d); - - G.f |= G_BACKBUFSEL; - - if (base && (base->lay & v3d->lay)) - draw_object_backbufsel(scene, v3d, rv3d, base->object); - - if (rv3d->gpuoffscreen) - GPU_offscreen_unbind(rv3d->gpuoffscreen, true); - else - ar->swap = 0; /* mark invalid backbuf for wm draw */ + rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED; - v3d->flag &= ~V3D_INVALID_BACKBUF; + v3d->zbuf = zbuf; + if (!v3d->zbuf) glDisable(GL_DEPTH_TEST); - G.f &= ~G_BACKBUFSEL; - v3d->zbuf = false; - glDisable(GL_DEPTH_TEST); - glEnable(GL_DITHER); - if (multisample_enabled) - glEnable(GL_MULTISAMPLE); + U.glalphaclip = glalphaclip; + v3d->flag = flag; + U.obcenter_dia = obcenter_dia; - if (rv3d->rflag & RV3D_CLIPPING) - ED_view3d_clipping_disable(); + UI_Theme_Restore(&theme_state); } -void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data) +/* ******************** background plates ***************** */ + +static void view3d_draw_background_gradient(void) { - RegionView3D *rv3d = ar->regiondata; + /* TODO: finish 2D API & draw background with that */ - if (rv3d->gpuoffscreen) { - GPU_offscreen_bind(rv3d->gpuoffscreen, true); - glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); - glReadPixels(x, y, w, h, format, type, data); - GPU_offscreen_unbind(rv3d->gpuoffscreen, true); - } - else { - glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); - } -} + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + unsigned char col_hi[3], col_lo[3]; -/* XXX depth reading exception, for code not using gpu offscreen */ -static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data) -{ + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); - glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); -} + UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo); + UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi); -void ED_view3d_backbuf_validate(ViewContext *vc) -{ - if (vc->v3d->flag & V3D_INVALID_BACKBUF) - backdrawview3d(vc->scene, vc->win, vc->ar, vc->v3d); + immBegin(GWN_PRIM_TRI_FAN, 4); + immAttrib3ubv(color, col_lo); + immVertex2f(pos, -1.0f, -1.0f); + immVertex2f(pos, 1.0f, -1.0f); + + immAttrib3ubv(color, col_hi); + immVertex2f(pos, 1.0f, 1.0f); + immVertex2f(pos, -1.0f, 1.0f); + immEnd(); + + immUnbindProgram(); } -/** - * allow for small values [0.5 - 2.5], - * and large values, FLT_MAX by clamping by the area size - */ -int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) +static void view3d_draw_background_none(void) { - return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); + UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); } -/* samples a single pixel (copied from vpaint) */ -unsigned int ED_view3d_backbuf_sample(ViewContext *vc, int x, int y) +static void view3d_draw_background_world(Scene *scene, RegionView3D *rv3d) { - unsigned int col; - - if (x >= vc->ar->winx || y >= vc->ar->winy) { - return 0; - } + if (scene->world) { + GPUMaterial *gpumat = GPU_material_world(scene, scene->world); - ED_view3d_backbuf_validate(vc); + /* calculate full shader for background */ + GPU_material_bind(gpumat, 1, 1, 1.0f, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac); + + if (GPU_material_bound(gpumat)) { + /* TODO viewport (dfelinto): GPU_material_bind relies on immediate mode, + * we can't get rid of the following code without a bigger refactor + * or we dropping this functionality. */ + + glBegin(GL_TRIANGLE_STRIP); + glVertex2f(-1.0f, -1.0f); + glVertex2f(1.0f, -1.0f); + glVertex2f(-1.0f, 1.0f); + glVertex2f(1.0f, 1.0f); + glEnd(); - view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); - glReadBuffer(GL_BACK); - - if (ENDIAN_ORDER == B_ENDIAN) { - BLI_endian_switch_uint32(&col); + GPU_material_unbind(gpumat); + return; + } } - - return GPU_select_to_index(col); -} -/* reads full rect, converts indices */ -ImBuf *ED_view3d_backbuf_read(ViewContext *vc, int xmin, int ymin, int xmax, int ymax) -{ - struct ImBuf *ibuf_clip; - /* clip */ - const rcti clip = { - max_ii(xmin, 0), min_ii(xmax, vc->ar->winx - 1), - max_ii(ymin, 0), min_ii(ymax, vc->ar->winy - 1)}; - const int size_clip[2] = { - BLI_rcti_size_x(&clip) + 1, - BLI_rcti_size_y(&clip) + 1}; - - if (UNLIKELY((clip.xmin > clip.xmax) || - (clip.ymin > clip.ymax))) - { - return NULL; - } + /* if any of the above fails */ + view3d_draw_background_none(); +} - ibuf_clip = IMB_allocImBuf(size_clip[0], size_clip[1], 32, IB_rect); +/* ******************** other elements ***************** */ - ED_view3d_backbuf_validate(vc); - view3d_opengl_read_pixels(vc->ar, clip.xmin, clip.ymin, size_clip[0], size_clip[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf_clip->rect); +#define DEBUG_GRID 0 - glReadBuffer(GL_BACK); +static void gridline_range(double x0, double dx, double max, int *r_first, int *r_count) +{ + /* determine range of gridlines that appear in this Area -- similar calc but separate ranges for x & y + * x0 is gridline 0, the axis in screen space + * Area covers [0 .. max) pixels */ - if (ENDIAN_ORDER == B_ENDIAN) { - IMB_convert_rgba_to_abgr(ibuf_clip); - } + int first = (int)ceil(-x0 / dx); + int last = (int)floor((max - x0) / dx); - GPU_select_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]); - - if ((clip.xmin == xmin) && - (clip.xmax == xmax) && - (clip.ymin == ymin) && - (clip.ymax == ymax)) - { - return ibuf_clip; + if (first <= last) { + *r_first = first; + *r_count = last - first + 1; } else { - /* put clipped result into a non-clipped buffer */ - struct ImBuf *ibuf_full; - const int size[2] = { - (xmax - xmin + 1), - (ymax - ymin + 1)}; - - ibuf_full = IMB_allocImBuf(size[0], size[1], 32, IB_rect); - - IMB_rectcpy( - ibuf_full, ibuf_clip, - clip.xmin - xmin, clip.ymin - ymin, - 0, 0, - size_clip[0], size_clip[1]); - IMB_freeImBuf(ibuf_clip); - return ibuf_full; + *r_first = 0; + *r_count = 0; } + +#if DEBUG_GRID + printf(" first %d * dx = %f\n", first, x0 + first * dx); + printf(" last %d * dx = %f\n", last, x0 + last * dx); + printf(" count = %d\n", *count_out); +#endif } -/* smart function to sample a rect spiralling outside, nice for backbuf selection */ -unsigned int ED_view3d_backbuf_sample_rect( - ViewContext *vc, const int mval[2], int size, - unsigned int min, unsigned int max, float *r_dist) +static int gridline_count(ARegion *ar, double x0, double y0, double dx) { - struct ImBuf *buf; - const unsigned int *bufmin, *bufmax, *tbuf; - int minx, miny; - int a, b, rc, nr, amount, dirvec[4][2]; - unsigned int index = 0; + /* x0 & y0 establish the "phase" of the grid within this 2D region + * dx is the frequency, shared by x & y directions + * pass in dx of smallest (highest precision) grid we want to draw */ - amount = (size - 1) / 2; +#if DEBUG_GRID + printf(" %s(%f, %f, dx:%f)\n", __FUNCTION__, x0, y0, dx); +#endif - minx = mval[0] - (amount + 1); - miny = mval[1] - (amount + 1); - buf = ED_view3d_backbuf_read(vc, minx, miny, minx + size - 1, miny + size - 1); - if (!buf) return 0; + int first, x_ct, y_ct; - rc = 0; - - dirvec[0][0] = 1; dirvec[0][1] = 0; - dirvec[1][0] = 0; dirvec[1][1] = -size; - dirvec[2][0] = -1; dirvec[2][1] = 0; - dirvec[3][0] = 0; dirvec[3][1] = size; - - bufmin = buf->rect; - tbuf = buf->rect; - bufmax = buf->rect + size * size; - tbuf += amount * size + amount; - - for (nr = 1; nr <= size; nr++) { - - for (a = 0; a < 2; a++) { - for (b = 0; b < nr; b++) { - if (*tbuf && *tbuf >= min && *tbuf < max) { - /* we got a hit */ - - /* get x,y pixel coords from the offset - * (manhatten distance in keeping with other screen-based selection) */ - *r_dist = (float)( - abs(((int)(tbuf - buf->rect) % size) - (size / 2)) + - abs(((int)(tbuf - buf->rect) / size) - (size / 2))); - - /* indices start at 1 here */ - index = (*tbuf - min) + 1; - goto exit; - } - - tbuf += (dirvec[rc][0] + dirvec[rc][1]); - - if (tbuf < bufmin || tbuf >= bufmax) { - goto exit; - } - } - rc++; - rc &= 3; - } - } + gridline_range(x0, dx, ar->winx, &first, &x_ct); + gridline_range(y0, dx, ar->winy, &first, &y_ct); -exit: - IMB_freeImBuf(buf); - return index; -} + int total_ct = x_ct + y_ct; +#if DEBUG_GRID + printf(" %d + %d = %d gridlines\n", x_ct, y_ct, total_ct); +#endif -/* ************************************************************* */ + return total_ct; +} -static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser) +static bool drawgrid_draw(ARegion *ar, double x0, double y0, double dx, int skip_mod, unsigned pos, unsigned col, GLubyte col_value[3]) { - if (BKE_image_is_stereo(ima)) { - iuser->flag |= IMA_SHOW_STEREO; + /* skip every skip_mod lines relative to each axis; they will be overlaid by another drawgrid_draw + * always skip exact x0 & y0 axes; they will be drawn later in color + * + * set grid color once, just before the first line is drawn + * it's harmless to set same color for every line, or every vertex + * but if no lines are drawn, color must not be set! */ - if ((scene->r.scemode & R_MULTIVIEW) == 0) { - iuser->multiview_eye = STEREO_LEFT_ID; - } - else if (v3d->stereo3d_camera != STEREO_3D_ID) { - /* show only left or right camera */ - iuser->multiview_eye = v3d->stereo3d_camera; - } +#if DEBUG_GRID + printf(" %s(%f, %f, dx:%f, skip_mod:%d)\n", __FUNCTION__, x0, y0, dx, skip_mod); +#endif - BKE_image_multiview_index(ima, iuser); - } - else { - iuser->flag &= ~IMA_SHOW_STEREO; - } -} + const float x_max = (float)ar->winx; + const float y_max = (float)ar->winy; -static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, - const bool do_foreground, const bool do_camera_frame) -{ - RegionView3D *rv3d = ar->regiondata; - BGpic *bgpic; - int fg_flag = do_foreground ? V3D_BGPIC_FOREGROUND : 0; + int first, ct; + int x_ct = 0, y_ct = 0; /* count of lines actually drawn */ + int lines_skipped_for_next_unit = 0; - for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { - bgpic->iuser.scene = scene; /* Needed for render results. */ + /* draw vertical lines */ + gridline_range(x0, dx, x_max, &first, &ct); - if ((bgpic->flag & V3D_BGPIC_FOREGROUND) != fg_flag) + for (int i = first; i < first + ct; ++i) { + if (i == 0) + continue; + else if (skip_mod && (i % skip_mod) == 0) { + ++lines_skipped_for_next_unit; continue; + } - if ((bgpic->view == 0) || /* zero for any */ - (bgpic->view & (1 << rv3d->view)) || /* check agaist flags */ - (rv3d->persp == RV3D_CAMOB && bgpic->view == (1 << RV3D_VIEW_CAMERA))) - { - float image_aspect[2]; - float fac, asp, zoomx, zoomy; - float x1, y1, x2, y2, centx, centy; - - ImBuf *ibuf = NULL, *freeibuf, *releaseibuf; - void *lock; - rctf clip_rect; - - Image *ima = NULL; - MovieClip *clip = NULL; - - /* disable individual images */ - if ((bgpic->flag & V3D_BGPIC_DISABLED)) - continue; - - freeibuf = NULL; - releaseibuf = NULL; - if (bgpic->source == V3D_BGPIC_IMAGE) { - ima = bgpic->ima; - if (ima == NULL) - continue; - BKE_image_user_frame_calc(&bgpic->iuser, CFRA, 0); - if (ima->source == IMA_SRC_SEQUENCE && !(bgpic->iuser.flag & IMA_USER_FRAME_IN_RANGE)) { - ibuf = NULL; /* frame is out of range, dont show */ - } - else { - view3d_stereo_bgpic_setup(scene, v3d, ima, &bgpic->iuser); - ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, &lock); - releaseibuf = ibuf; - } + if (x_ct == 0) + immAttrib3ub(col, col_value[0], col_value[1], col_value[2]); - image_aspect[0] = ima->aspx; - image_aspect[1] = ima->aspy; - } - else if (bgpic->source == V3D_BGPIC_MOVIE) { - /* TODO: skip drawing when out of frame range (as image sequences do above) */ + float x = (float)(x0 + i * dx); + immVertex2f(pos, x, 0.0f); + immVertex2f(pos, x, y_max); + ++x_ct; + } - if (bgpic->flag & V3D_BGPIC_CAMERACLIP) { - if (scene->camera) - clip = BKE_object_movieclip_get(scene, scene->camera, true); - } - else { - clip = bgpic->clip; - } + /* draw horizontal lines */ + gridline_range(y0, dx, y_max, &first, &ct); - if (clip == NULL) - continue; + for (int i = first; i < first + ct; ++i) { + if (i == 0) + continue; + else if (skip_mod && (i % skip_mod) == 0) { + ++lines_skipped_for_next_unit; + continue; + } - BKE_movieclip_user_set_frame(&bgpic->cuser, CFRA); - ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser); + if (x_ct + y_ct == 0) + immAttrib3ub(col, col_value[0], col_value[1], col_value[2]); - image_aspect[0] = clip->aspx; - image_aspect[1] = clip->aspy; + float y = (float)(y0 + i * dx); + immVertex2f(pos, 0.0f, y); + immVertex2f(pos, x_max, y); + ++y_ct; + } - /* working with ibuf from image and clip has got different workflow now. - * ibuf acquired from clip is referenced by cache system and should - * be dereferenced after usage. */ - freeibuf = ibuf; - } - else { - /* perhaps when loading future files... */ - BLI_assert(0); - copy_v2_fl(image_aspect, 1.0f); - } +#if DEBUG_GRID + int total_ct = x_ct + y_ct; + printf(" %d + %d = %d gridlines drawn, %d skipped for next unit\n", x_ct, y_ct, total_ct, lines_skipped_for_next_unit); +#endif - if (ibuf == NULL) - continue; + return lines_skipped_for_next_unit > 0; +} - if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */ - if (freeibuf) - IMB_freeImBuf(freeibuf); - if (releaseibuf) - BKE_image_release_ibuf(ima, releaseibuf, lock); +#define GRID_MIN_PX_D 6.0 +#define GRID_MIN_PX_F 6.0f - continue; - } +static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit) +{ + RegionView3D *rv3d = ar->regiondata; - if (ibuf->rect == NULL) - IMB_rect_from_float(ibuf); +#if DEBUG_GRID + printf("%s width %d, height %d\n", __FUNCTION__, ar->winx, ar->winy); +#endif - if (rv3d->persp == RV3D_CAMOB) { + double fx = rv3d->persmat[3][0]; + double fy = rv3d->persmat[3][1]; + double fw = rv3d->persmat[3][3]; - if (do_camera_frame) { - rctf vb; - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false); - x1 = vb.xmin; - y1 = vb.ymin; - x2 = vb.xmax; - y2 = vb.ymax; - } - else { - x1 = ar->winrct.xmin; - y1 = ar->winrct.ymin; - x2 = ar->winrct.xmax; - y2 = ar->winrct.ymax; - } + const double wx = 0.5 * ar->winx; /* use double precision to avoid rounding errors */ + const double wy = 0.5 * ar->winy; - /* apply offset last - camera offset is different to offset in blender units */ - /* so this has some sane way of working - this matches camera's shift _exactly_ */ - { - const float max_dim = max_ff(x2 - x1, y2 - y1); - const float xof_scale = bgpic->xof * max_dim; - const float yof_scale = bgpic->yof * max_dim; - - x1 += xof_scale; - y1 += yof_scale; - x2 += xof_scale; - y2 += yof_scale; - } + double x = wx * fx / fw; + double y = wy * fy / fw; - centx = (x1 + x2) / 2.0f; - centy = (y1 + y2) / 2.0f; + double vec4[4] = { v3d->grid, v3d->grid, 0.0, 1.0 }; + mul_m4_v4d(rv3d->persmat, vec4); + fx = vec4[0]; + fy = vec4[1]; + fw = vec4[3]; - /* aspect correction */ - if (bgpic->flag & V3D_BGPIC_CAMERA_ASPECT) { - /* apply aspect from clip */ - const float w_src = ibuf->x * image_aspect[0]; - const float h_src = ibuf->y * image_aspect[1]; + double dx = fabs(x - wx * fx / fw); + if (dx == 0) dx = fabs(y - wy * fy / fw); - /* destination aspect is already applied from the camera frame */ - const float w_dst = x1 - x2; - const float h_dst = y1 - y2; + x += wx; + y += wy; - const float asp_src = w_src / h_src; - const float asp_dst = w_dst / h_dst; + /* now x, y, and dx have their final values + * (x,y) is the world origin (0,0,0) mapped to Area-relative screen space + * dx is the distance in pixels between grid lines -- same for horiz or vert grid lines */ - if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) { - if ((asp_src > asp_dst) == ((bgpic->flag & V3D_BGPIC_CAMERA_CROP) != 0)) { - /* fit X */ - const float div = asp_src / asp_dst; - x1 = ((x1 - centx) * div) + centx; - x2 = ((x2 - centx) * div) + centx; - } - else { - /* fit Y */ - const float div = asp_dst / asp_src; - y1 = ((y1 - centy) * div) + centy; - y2 = ((y2 - centy) * div) + centy; - } - } - } - } - else { - float tvec[3]; - float sco[2]; - const float mval_f[2] = {1.0f, 0.0f}; - const float co_zero[3] = {0}; - float zfac; - - /* calc window coord */ - zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL); - ED_view3d_win_to_delta(ar, mval_f, tvec, zfac); - fac = max_ff(fabsf(tvec[0]), max_ff(fabsf(tvec[1]), fabsf(tvec[2]))); /* largest abs axis */ - fac = 1.0f / fac; - - asp = (float)ibuf->y / (float)ibuf->x; - - zero_v3(tvec); - ED_view3d_project_float_v2_m4(ar, tvec, sco, rv3d->persmat); - - x1 = sco[0] + fac * (bgpic->xof - bgpic->size); - y1 = sco[1] + asp * fac * (bgpic->yof - bgpic->size); - x2 = sco[0] + fac * (bgpic->xof + bgpic->size); - y2 = sco[1] + asp * fac * (bgpic->yof + bgpic->size); - - centx = (x1 + x2) / 2.0f; - centy = (y1 + y2) / 2.0f; - } - - /* complete clip? */ - BLI_rctf_init(&clip_rect, x1, x2, y1, y2); - if (bgpic->rotation) { - BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation); - } + glLineWidth(1.0f); - if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) { - if (freeibuf) - IMB_freeImBuf(freeibuf); - if (releaseibuf) - BKE_image_release_ibuf(ima, releaseibuf, lock); +#if 0 /* TODO: write to UI/widget depth buffer, not scene depth */ + glDepthMask(GL_FALSE); /* disable write in zbuffer */ +#endif - continue; - } + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); - zoomx = (x2 - x1) / ibuf->x; - zoomy = (y2 - y1) / ibuf->y; + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); - /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */ - if (zoomx < 1.0f || zoomy < 1.0f) { - float tzoom = min_ff(zoomx, zoomy); - int mip = 0; + unsigned char col[3], col2[3]; + UI_GetThemeColor3ubv(TH_GRID, col); - if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) { - IMB_remakemipmap(ibuf, 0); - ibuf->userflags &= ~IB_MIPMAP_INVALID; - } - else if (ibuf->mipmap[0] == NULL) - IMB_makemipmap(ibuf, 0); - - while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) { - tzoom *= 2.0f; - zoomx *= 2.0f; - zoomy *= 2.0f; - mip++; - } - if (mip > 0) - ibuf = ibuf->mipmap[mip - 1]; - } + if (unit->system) { + const void *usys; + int len; - if (v3d->zbuf) glDisable(GL_DEPTH_TEST); - glDepthMask(0); + bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + bool first = true; - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - ED_region_pixelspace(ar); + if (usys) { + int i = len; + while (i--) { + double scalar = bUnit_GetScaler(usys, i); - glTranslatef(centx, centy, 0.0); - glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f); + double dx_scalar = dx * scalar / (double)unit->scale_length; + if (dx_scalar < (GRID_MIN_PX_D * 2.0)) { + /* very very small grid items are less useful when dealing with units */ + continue; + } - if (bgpic->flag & V3D_BGPIC_FLIP_X) { - zoomx *= -1.0f; - x1 = x2; - } - if (bgpic->flag & V3D_BGPIC_FLIP_Y) { - zoomy *= -1.0f; - y1 = y2; - } - glPixelZoom(zoomx, zoomy); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend); + if (first) { + first = false; - /* could not use glaDrawPixelsAuto because it could fallback to - * glaDrawPixelsSafe in some cases, which will end up in missing - * alpha transparency for the background image (sergey) - */ - glaDrawPixelsTex(x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect); + /* Store the smallest drawn grid size units name so users know how big each grid cell is */ + *grid_unit = bUnit_GetNameDisplay(usys, i); + rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length); - glPixelZoom(1.0, 1.0); - glPixelTransferf(GL_ALPHA_SCALE, 1.0f); + int gridline_ct = gridline_count(ar, x, y, dx_scalar); + if (gridline_ct == 0) + goto drawgrid_cleanup; /* nothing to draw */ - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + immBegin(GWN_PRIM_LINES, gridline_ct * 2); + } - glDisable(GL_BLEND); + float blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar); + /* tweak to have the fade a bit nicer */ + blend_fac = (blend_fac * blend_fac) * 2.0f; + CLAMP(blend_fac, 0.3f, 1.0f); - glDepthMask(1); - if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, blend_fac, col2); - if (freeibuf) - IMB_freeImBuf(freeibuf); - if (releaseibuf) - BKE_image_release_ibuf(ima, releaseibuf, lock); + const int skip_mod = (i == 0) ? 0 : (int)round(bUnit_GetScaler(usys, i - 1) / scalar); +#if DEBUG_GRID + printf("%s %f, ", bUnit_GetNameDisplay(usys, i), scalar); + if (i > 0) + printf("next unit is %d times larger\n", skip_mod); + else + printf("largest unit\n"); +#endif + if (!drawgrid_draw(ar, x, y, dx_scalar, skip_mod, pos, color, col2)) + break; + } } } -} + else { + const double sublines = v3d->gridsubdiv; + const float sublines_fl = v3d->gridsubdiv; -static void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d, - const bool do_foreground, const bool do_camera_frame) -{ - RegionView3D *rv3d = ar->regiondata; + int grids_to_draw = 2; /* first the faint fine grid, then the bold coarse grid */ - if ((v3d->flag & V3D_DISPBGPICS) == 0) - return; + if (dx < GRID_MIN_PX_D) { + rv3d->gridview *= sublines_fl; + dx *= sublines; + if (dx < GRID_MIN_PX_D) { + rv3d->gridview *= sublines_fl; + dx *= sublines; + if (dx < GRID_MIN_PX_D) { + rv3d->gridview *= sublines_fl; + dx *= sublines; + grids_to_draw = (dx < GRID_MIN_PX_D) ? 0 : 1; + } + } + } + else { + if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */ + rv3d->gridview /= sublines_fl; + dx /= sublines; + if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */ + rv3d->gridview /= sublines_fl; + dx /= sublines; + if (dx > (GRID_MIN_PX_D * 10.0)) { + grids_to_draw = 1; + } + } + } + } - /* disabled - mango request, since footage /w only render is quite useful - * and this option is easy to disable all background images at once */ -#if 0 - if (v3d->flag2 & V3D_RENDER_OVERRIDE) - return; -#endif + int gridline_ct = gridline_count(ar, x, y, dx); + if (gridline_ct == 0) + goto drawgrid_cleanup; /* nothing to draw */ - if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) { - if (rv3d->persp == RV3D_CAMOB) { - view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame); + immBegin(GWN_PRIM_LINES, gridline_ct * 2); + + if (grids_to_draw == 2) { + UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0), col2); + if (drawgrid_draw(ar, x, y, dx, v3d->gridsubdiv, pos, color, col2)) + drawgrid_draw(ar, x, y, dx * sublines, 0, pos, color, col); + } + else if (grids_to_draw == 1) { + drawgrid_draw(ar, x, y, dx, 0, pos, color, col); } } - else { - view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame); + + /* draw visible axes */ + /* horizontal line */ + if (0 <= y && y < ar->winy) { + UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT) ? 'Y' : 'X'); + immAttrib3ub(color, col2[0], col2[1], col2[2]); + immVertex2f(pos, 0.0f, y); + immVertex2f(pos, (float)ar->winx, y); + } + + /* vertical line */ + if (0 <= x && x < ar->winx) { + UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM) ? 'Y' : 'Z'); + immAttrib3ub(color, col2[0], col2[1], col2[2]); + immVertex2f(pos, x, 0.0f); + immVertex2f(pos, x, (float)ar->winy); } -} -/* ****************** View3d afterdraw *************** */ + immEnd(); -typedef struct View3DAfter { - struct View3DAfter *next, *prev; - struct Base *base; - short dflag; -} View3DAfter; +drawgrid_cleanup: + immUnbindProgram(); -/* temp storage of Objects that need to be drawn as last */ -void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag) -{ - View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after"); - BLI_assert((base->flag & OB_FROMDUPLI) == 0); - BLI_addtail(lb, v3da); - v3da->base = base; - v3da->dflag = dflag; +#if 0 /* depth write is left enabled above */ + glDepthMask(GL_TRUE); /* enable write in zbuffer */ +#endif } -/* disables write in zbuffer and draws it over */ -static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d) -{ - View3DAfter *v3da; - - glDepthMask(GL_FALSE); - v3d->transp = true; - - while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) { - draw_object(scene, ar, v3d, v3da->base, v3da->dflag); - MEM_freeN(v3da); - } - v3d->transp = false; - - glDepthMask(GL_TRUE); - -} +#undef DEBUG_GRID +#undef GRID_MIN_PX_D +#undef GRID_MIN_PX_F -/* clears zbuffer and draws it over */ -static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear) +static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth) { - View3DAfter *v3da; + /* draw only if there is something to draw */ + if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) { + /* draw how many lines? + * trunc(v3d->gridlines / 2) * 4 + * + 2 for xy axes (possibly with special colors) + * + 1 for z axis (the only line not in xy plane) + * even v3d->gridlines are honored, odd rounded down */ + const int gridlines = v3d->gridlines / 2; + const float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit); + const float grid = gridlines * grid_scale; - if (*clear && v3d->zbuf) { - glClear(GL_DEPTH_BUFFER_BIT); - *clear = false; - } + const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) && gridlines >= 1; - v3d->xray = true; - while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { - draw_object(scene, ar, v3d, v3da->base, v3da->dflag); - MEM_freeN(v3da); - } - v3d->xray = false; -} + bool show_axis_x = v3d->gridflag & V3D_SHOW_X; + bool show_axis_y = v3d->gridflag & V3D_SHOW_Y; + bool show_axis_z = v3d->gridflag & V3D_SHOW_Z; + unsigned char col_grid[3], col_axis[3]; -/* clears zbuffer and draws it over */ -static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, const bool clear) -{ - View3DAfter *v3da; + glLineWidth(1.0f); - if (clear && v3d->zbuf) - glClear(GL_DEPTH_BUFFER_BIT); + UI_GetThemeColor3ubv(TH_GRID, col_grid); - v3d->xray = true; - v3d->transp = true; - - glDepthMask(GL_FALSE); + if (!write_depth) + glDepthMask(GL_FALSE); - while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) { - draw_object(scene, ar, v3d, v3da->base, v3da->dflag); - MEM_freeN(v3da); - } + if (show_floor) { + const unsigned vertex_ct = 2 * (gridlines * 4 + 2); + const int sublines = v3d->gridsubdiv; - v3d->transp = false; - v3d->xray = false; + unsigned char col_bg[3], col_grid_emphasise[3], col_grid_light[3]; - glDepthMask(GL_TRUE); -} + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); -/* clears zbuffer and draws it over, - * note that in the select version we don't care about transparent flag as with regular drawing */ -static void view3d_draw_xray_select(Scene *scene, ARegion *ar, View3D *v3d, bool *clear) -{ - /* Not ideal, but we need to read from the previous depths before clearing - * otherwise we could have a function to load the depths after drawing. - * - * Clearing the depth buffer isn't all that common between drawing objects so accept this for now. - */ - if (U.gpu_select_pick_deph) { - GPU_select_load_id(-1); - } + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); - View3DAfter *v3da; - if (*clear && v3d->zbuf) { - glClear(GL_DEPTH_BUFFER_BIT); - *clear = false; - } + immBegin(GWN_PRIM_LINES, vertex_ct); - v3d->xray = true; - while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { - if (GPU_select_load_id(v3da->base->selcol)) { - draw_object_select(scene, ar, v3d, v3da->base, v3da->dflag); - } - MEM_freeN(v3da); - } - v3d->xray = false; -} + /* draw normal grid lines */ + UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10); -/* *********************** */ + for (int a = 1; a <= gridlines; a++) { + /* skip emphasised divider lines */ + if (a % sublines != 0) { + const float line = a * grid_scale; -/* - * In most cases call draw_dupli_objects, - * draw_dupli_objects_color was added because when drawing set dupli's - * we need to force the color - */ + immAttrib3ubv(color, col_grid_light); -#if 0 -int dupli_ob_sort(void *arg1, void *arg2) -{ - void *p1 = ((DupliObject *)arg1)->ob; - void *p2 = ((DupliObject *)arg2)->ob; - int val = 0; - if (p1 < p2) val = -1; - else if (p1 > p2) val = 1; - return val; -} -#endif + immVertex2f(pos, -grid, -line); + immVertex2f(pos, +grid, -line); + immVertex2f(pos, -grid, +line); + immVertex2f(pos, +grid, +line); + immVertex2f(pos, -line, -grid); + immVertex2f(pos, -line, +grid); + immVertex2f(pos, +line, -grid); + immVertex2f(pos, +line, +grid); + } + } -static DupliObject *dupli_step(DupliObject *dob) -{ - while (dob && dob->no_draw) - dob = dob->next; - return dob; -} + /* draw emphasised grid lines */ + UI_GetThemeColor3ubv(TH_BACK, col_bg); + /* emphasise division lines lighter instead of darker, if background is darker than grid */ + UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise, + (col_grid[0] + col_grid[1] + col_grid[2] + 30 > + col_bg[0] + col_bg[1] + col_bg[2]) ? 20 : -10); -static void draw_dupli_objects_color( - Scene *scene, ARegion *ar, View3D *v3d, Base *base, - const short dflag, const int color) -{ - RegionView3D *rv3d = ar->regiondata; - ListBase *lb; - LodLevel *savedlod; - DupliObject *dob_prev = NULL, *dob, *dob_next = NULL; - Base tbase = {NULL}; - BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */ - GLuint displist = 0; - unsigned char color_rgb[3]; - const short dflag_dupli = dflag | DRAW_CONSTCOLOR; - short transflag; - bool use_displist = false; /* -1 is initialize */ - char dt; - short dtx; - DupliApplyData *apply_data; - - if (base->object->restrictflag & OB_RESTRICT_VIEW) return; - if ((base->object->restrictflag & OB_RESTRICT_RENDER) && (v3d->flag2 & V3D_RENDER_OVERRIDE)) return; - - if (dflag & DRAW_CONSTCOLOR) { - BLI_assert(color == TH_UNDEFINED); - } - else { - UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb); - } + if (sublines <= gridlines) { + immAttrib3ubv(color, col_grid_emphasise); + + for (int a = sublines; a <= gridlines; a += sublines) { + const float line = a * grid_scale; + + immVertex2f(pos, -grid, -line); + immVertex2f(pos, +grid, -line); + immVertex2f(pos, -grid, +line); + immVertex2f(pos, +grid, +line); - tbase.flag = OB_FROMDUPLI | base->flag; - lb = object_duplilist(G.main->eval_ctx, scene, base->object); - // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */ + immVertex2f(pos, -line, -grid); + immVertex2f(pos, -line, +grid); + immVertex2f(pos, +line, -grid); + immVertex2f(pos, +line, +grid); + } + } - apply_data = duplilist_apply(base->object, scene, lb); + /* draw X axis */ + if (show_axis_x) { + show_axis_x = false; /* drawing now, won't need to draw later */ + UI_make_axis_color(col_grid, col_axis, 'X'); + immAttrib3ubv(color, col_axis); + } + else + immAttrib3ubv(color, col_grid_emphasise); - dob = dupli_step(lb->first); - if (dob) dob_next = dupli_step(dob->next); + immVertex2f(pos, -grid, 0.0f); + immVertex2f(pos, +grid, 0.0f); - for (; dob; dob_prev = dob, dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) { - bool testbb = false; + /* draw Y axis */ + if (show_axis_y) { + show_axis_y = false; /* drawing now, won't need to draw later */ + UI_make_axis_color(col_grid, col_axis, 'Y'); + immAttrib3ubv(color, col_axis); + } + else + immAttrib3ubv(color, col_grid_emphasise); - tbase.object = dob->ob; + immVertex2f(pos, 0.0f, -grid); + immVertex2f(pos, 0.0f, +grid); - /* Make sure lod is updated from dupli's position */ - savedlod = dob->ob->currentlod; + immEnd(); + immUnbindProgram(); -#ifdef WITH_GAMEENGINE - if (rv3d->rflag & RV3D_IS_GAME_ENGINE) { - BKE_object_lod_update(dob->ob, rv3d->viewinv[3]); + /* done with XY plane */ } -#endif - /* extra service: draw the duplicator in drawtype of parent, minimum taken - * to allow e.g. boundbox box objects in groups for LOD */ - dt = tbase.object->dt; - tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); + if (show_axis_x || show_axis_y || show_axis_z) { + /* draw axis lines -- sometimes grid floor is off, other times we still need to draw the Z axis */ - /* inherit draw extra, but not if a boundbox under the assumption that this - * is intended to speed up drawing, and drawing extra (especially wire) can - * slow it down too much */ - dtx = tbase.object->dtx; - if (tbase.object->dt != OB_BOUNDBOX) - tbase.object->dtx = base->object->dtx; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); - /* negative scale flag has to propagate */ - transflag = tbase.object->transflag; + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + immBegin(GWN_PRIM_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2); - if (is_negative_m4(dob->mat)) - tbase.object->transflag |= OB_NEG_SCALE; - else - tbase.object->transflag &= ~OB_NEG_SCALE; - - /* should move outside the loop but possible color is set in draw_object still */ - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(color_rgb); - } - - /* generate displist, test for new object */ - if (dob_prev && dob_prev->ob != dob->ob) { - if (use_displist == true) - glDeleteLists(displist, 1); - - use_displist = false; - } - - if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) { - bb = *bb_tmp; /* must make a copy */ - testbb = true; - } + if (show_axis_x) { + UI_make_axis_color(col_grid, col_axis, 'X'); + immAttrib3ubv(color, col_axis); + immVertex3f(pos, -grid, 0.0f, 0.0f); + immVertex3f(pos, +grid, 0.0f, 0.0f); + } - if (!testbb || ED_view3d_boundbox_clip_ex(rv3d, &bb, dob->mat)) { - /* generate displist */ - if (use_displist == false) { - - /* note, since this was added, its checked (dob->type == OB_DUPLIGROUP) - * however this is very slow, it was probably needed for the NLA - * offset feature (used in group-duplicate.blend but no longer works in 2.5) - * so for now it should be ok to - campbell */ - - if ( /* if this is the last no need to make a displist */ - (dob_next == NULL || dob_next->ob != dob->ob) || - /* lamp drawing messes with matrices, could be handled smarter... but this works */ - (dob->ob->type == OB_LAMP) || - (dob->type == OB_DUPLIGROUP && dob->animated) || - !bb_tmp || - draw_glsl_material(scene, dob->ob, v3d, dt) || - check_object_draw_texture(scene, v3d, dt) || - (v3d->flag2 & V3D_SOLID_MATCAP) != 0) - { - // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2); - use_displist = false; - } - else { - // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name + 2); - - /* disable boundbox check for list creation */ - BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 1); - /* need this for next part of code */ - unit_m4(dob->ob->obmat); /* obmat gets restored */ - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - draw_object(scene, ar, v3d, &tbase, dflag_dupli); - glEndList(); - - use_displist = true; - BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 0); - } + if (show_axis_y) { + UI_make_axis_color(col_grid, col_axis, 'Y'); + immAttrib3ubv(color, col_axis); + immVertex3f(pos, 0.0f, -grid, 0.0f); + immVertex3f(pos, 0.0f, +grid, 0.0f); } - - if (use_displist) { - glPushMatrix(); - glMultMatrixf(dob->mat); - glCallList(displist); - glPopMatrix(); - } - else { - copy_m4_m4(dob->ob->obmat, dob->mat); - GPU_begin_dupli_object(dob); - draw_object(scene, ar, v3d, &tbase, dflag_dupli); - GPU_end_dupli_object(); + + if (show_axis_z) { + UI_make_axis_color(col_grid, col_axis, 'Z'); + immAttrib3ubv(color, col_axis); + immVertex3f(pos, 0.0f, 0.0f, -grid); + immVertex3f(pos, 0.0f, 0.0f, +grid); } + + immEnd(); + immUnbindProgram(); } - - tbase.object->dt = dt; - tbase.object->dtx = dtx; - tbase.object->transflag = transflag; - tbase.object->currentlod = savedlod; + + if (!write_depth) + glDepthMask(GL_TRUE); } +} + +/** could move this elsewhere, but tied into #ED_view3d_grid_scale */ +float ED_scene_grid_scale(Scene *scene, const char **grid_unit) +{ + /* apply units */ + if (scene->unit.system) { + const void *usys; + int len; + + bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len); - if (apply_data) { - duplilist_restore(lb, apply_data); - duplilist_free_apply_data(apply_data); + if (usys) { + int i = bUnit_GetBaseUnit(usys); + if (grid_unit) + *grid_unit = bUnit_GetNameDisplay(usys, i); + return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length; + } } - free_object_duplilist(lb); - - if (use_displist) - glDeleteLists(displist, 1); + return 1.0f; } -static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base) +float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) { - /* define the color here so draw_dupli_objects_color can be called - * from the set loop */ - - int color = (base->flag & SELECT) ? TH_SELECT : TH_WIRE; - /* debug */ - if (base->object->dup_group && base->object->dup_group->id.us < 1) - color = TH_REDALERT; - - draw_dupli_objects_color(scene, ar, v3d, base, 0, color); + return v3d->grid * ED_scene_grid_scale(scene, grid_unit); } -/* XXX warning, not using gpu offscreen here */ -void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) +static bool is_cursor_visible(Scene *scene, SceneLayer *sl) { - int x, y, w, h; - rcti r; - /* clamp rect by region */ + Object *ob = OBACT(sl); - r.xmin = 0; - r.xmax = ar->winx - 1; - r.ymin = 0; - r.ymax = ar->winy - 1; + /* don't draw cursor in paint modes, but with a few exceptions */ + if (ob && ob->mode & OB_MODE_ALL_PAINT) { + /* exception: object is in weight paint and has deforming armature in pose mode */ + if (ob->mode & OB_MODE_WEIGHT_PAINT) { + if (BKE_object_pose_armature_get(ob) != NULL) { + return true; + } + } + /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */ + else if (ob->mode & OB_MODE_TEXTURE_PAINT) { + const Paint *p = BKE_paint_get_active(scene, sl); - /* Constrain rect to depth bounds */ - BLI_rcti_isect(&r, rect, rect); + if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) { + if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) { + return true; + } + } + } - /* assign values to compare with the ViewDepths */ - x = rect->xmin; - y = rect->ymin; + /* no exception met? then don't draw cursor! */ + return false; + } - w = BLI_rcti_size_x(rect); - h = BLI_rcti_size_y(rect); + return true; +} - if (w <= 0 || h <= 0) { - if (d->depths) - MEM_freeN(d->depths); - d->depths = NULL; +static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d) +{ + int co[2]; - d->damaged = false; - } - else if (d->w != w || - d->h != h || - d->x != x || - d->y != y || - d->depths == NULL - ) - { - d->x = x; - d->y = y; - d->w = w; - d->h = h; + /* we don't want the clipping for cursor */ + if (ED_view3d_project_int_global(ar, ED_view3d_cursor3d_get(scene, v3d), co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + const float f5 = 0.25f * U.widget_unit; + const float f10 = 0.5f * U.widget_unit; + const float f20 = U.widget_unit; + + glLineWidth(1.0f); - if (d->depths) - MEM_freeN(d->depths); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); - d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset"); - - d->damaged = true; - } + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); - if (d->damaged) { - /* XXX using special function here, it doesn't use the gpu offscreen system */ - view3d_opengl_read_Z_pixels(ar, d->x, d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); - glGetDoublev(GL_DEPTH_RANGE, d->depth_range); - d->damaged = false; - } -} + const int segments = 16; -/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */ -void ED_view3d_depth_update(ARegion *ar) -{ - RegionView3D *rv3d = ar->regiondata; - - /* Create storage for, and, if necessary, copy depth buffer */ - if (!rv3d->depths) rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); - if (rv3d->depths) { - ViewDepths *d = rv3d->depths; - if (d->w != ar->winx || - d->h != ar->winy || - !d->depths) - { - d->w = ar->winx; - d->h = ar->winy; - if (d->depths) - MEM_freeN(d->depths); - d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); - d->damaged = true; - } - - if (d->damaged) { - view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); - glGetDoublev(GL_DEPTH_RANGE, d->depth_range); - - d->damaged = false; - } - } -} + immBegin(GWN_PRIM_LINE_LOOP, segments); -/* utility function to find the closest Z value, use for autodepth */ -float view3d_depth_near(ViewDepths *d) -{ - /* convert to float for comparisons */ - const float near = (float)d->depth_range[0]; - const float far_real = (float)d->depth_range[1]; - float far = far_real; - - const float *depths = d->depths; - float depth = FLT_MAX; - int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */ - - /* far is both the starting 'far' value - * and the closest value found. */ - while (i--) { - depth = *depths++; - if ((depth < far) && (depth > near)) { - far = depth; + for (int i = 0; i < segments; ++i) { + float angle = 2 * M_PI * ((float)i / (float)segments); + float x = co[0] + f10 * cosf(angle); + float y = co[1] + f10 * sinf(angle); + + if (i % 2 == 0) + immAttrib3ub(color, 255, 0, 0); + else + immAttrib3ub(color, 255, 255, 255); + + immVertex2f(pos, x, y); } - } + immEnd(); - return far == far_real ? FLT_MAX : far; -} + immUnbindProgram(); -void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d) -{ - short zbuf = v3d->zbuf; - RegionView3D *rv3d = ar->regiondata; + GWN_vertformat_clear(format); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - /* Setup view matrix. */ - ED_view3d_draw_setup_view(NULL, scene, ar, v3d, rv3d->viewmat, rv3d->winmat, NULL); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - glClear(GL_DEPTH_BUFFER_BIT); + unsigned char crosshair_color[3]; + UI_GetThemeColor3ubv(TH_VIEW_OVERLAY, crosshair_color); + immUniformColor3ubv(crosshair_color); - v3d->zbuf = true; - glEnable(GL_DEPTH_TEST); + immBegin(GWN_PRIM_LINES, 8); + immVertex2f(pos, co[0] - f20, co[1]); + immVertex2f(pos, co[0] - f5, co[1]); + immVertex2f(pos, co[0] + f5, co[1]); + immVertex2f(pos, co[0] + f20, co[1]); + immVertex2f(pos, co[0], co[1] - f20); + immVertex2f(pos, co[0], co[1] - f5); + immVertex2f(pos, co[0], co[1] + f5); + immVertex2f(pos, co[0], co[1] + f20); + immEnd(); - if (v3d->flag2 & V3D_SHOW_GPENCIL) { - ED_gpencil_draw_view3d(NULL, scene, v3d, ar, true); + immUnbindProgram(); } - - v3d->zbuf = zbuf; } -static void view3d_draw_depth_loop(Scene *scene, ARegion *ar, View3D *v3d) +static void draw_view_axis(RegionView3D *rv3d, rcti *rect) { - Base *base; - - /* no need for color when drawing depth buffer */ - const short dflag_depth = DRAW_CONSTCOLOR; - - /* draw set first */ - if (scene->set) { - Scene *sce_iter; - for (SETLOOPER(scene->set, sce_iter, base)) { - if (v3d->lay & base->lay) { - draw_object(scene, ar, v3d, base, 0); - if (base->object->transflag & OB_DUPLI) { - draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED); - } - } - } - } - - for (base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { - /* dupli drawing */ - if (base->object->transflag & OB_DUPLI) { - draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED); - } - draw_object(scene, ar, v3d, base, dflag_depth); - } + const float k = U.rvisize * U.pixelsize; /* axis size */ + const int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */ + + const float startx = rect->xmin + k + 1.0f; /* axis center in screen coordinates, x=y */ + const float starty = rect->ymin + k + 1.0f; + + float axis_pos[3][2]; + unsigned char axis_col[3][4]; + + int axis_order[3] = {0, 1, 2}; + axis_sort_v3(rv3d->viewinv[2], axis_order); + + for (int axis_i = 0; axis_i < 3; axis_i++) { + int i = axis_order[axis_i]; + + /* get position of each axis tip on screen */ + float vec[3] = { 0.0f }; + vec[i] = 1.0f; + mul_qt_v3(rv3d->viewquat, vec); + axis_pos[i][0] = startx + vec[0] * k; + axis_pos[i][1] = starty + vec[1] * k; + + /* get color of each axis */ + UI_GetThemeColorShade3ubv(TH_AXIS_X + i, bright, axis_col[i]); /* rgb */ + axis_col[i][3] = 255 * hypotf(vec[0], vec[1]); /* alpha */ } - - /* this isn't that nice, draw xray objects as if they are normal */ - if (v3d->afterdraw_transp.first || - v3d->afterdraw_xray.first || - v3d->afterdraw_xraytransp.first) - { - View3DAfter *v3da; - int mask_orig; - v3d->xray = true; - - /* transp materials can change the depth mask, see #21388 */ - glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig); + /* draw axis lines */ + glLineWidth(2.0f); + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); - if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) { - glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */ - for (v3da = v3d->afterdraw_xray.first; v3da; v3da = v3da->next) { - draw_object(scene, ar, v3d, v3da->base, dflag_depth); - } - glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */ - } + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBegin(GWN_PRIM_LINES, 6); - /* draw 3 passes, transp/xray/xraytransp */ - v3d->xray = false; - v3d->transp = true; - while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) { - draw_object(scene, ar, v3d, v3da->base, dflag_depth); - MEM_freeN(v3da); - } + for (int axis_i = 0; axis_i < 3; axis_i++) { + int i = axis_order[axis_i]; - v3d->xray = true; - v3d->transp = false; - while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { - draw_object(scene, ar, v3d, v3da->base, dflag_depth); - MEM_freeN(v3da); - } + immAttrib4ubv(col, axis_col[i]); + immVertex2f(pos, startx, starty); + immVertex2fv(pos, axis_pos[i]); + } - v3d->xray = true; - v3d->transp = true; - while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) { - draw_object(scene, ar, v3d, v3da->base, dflag_depth); - MEM_freeN(v3da); - } + immEnd(); + immUnbindProgram(); + glDisable(GL_LINE_SMOOTH); - - v3d->xray = false; - v3d->transp = false; + /* draw axis names */ + for (int axis_i = 0; axis_i < 3; axis_i++) { + int i = axis_order[axis_i]; - glDepthMask(mask_orig); + const char axis_text[2] = {'x' + i, '\0'}; + BLF_color4ubv(BLF_default(), axis_col[i]); + BLF_draw_default_ascii(axis_pos[i][0] + 2, axis_pos[i][1] + 2, 0.0f, axis_text, 1); } } -void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride) +#ifdef WITH_INPUT_NDOF +/* draw center and axis of rotation for ongoing 3D mouse navigation */ +static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d) { - struct bThemeState theme_state; - RegionView3D *rv3d = ar->regiondata; - short zbuf = v3d->zbuf; - short flag = v3d->flag; - float glalphaclip = U.glalphaclip; - int obcenter_dia = U.obcenter_dia; - /* temp set drawtype to solid */ - - /* Setting these temporarily is not nice */ - v3d->flag &= ~V3D_SELECT_OUTLINE; - U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */ - U.obcenter_dia = 0; - - /* Tools may request depth outside of regular drawing code. */ - UI_Theme_Store(&theme_state); - UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); + float o[3]; /* center of rotation */ + float end[3]; /* endpoints for drawing */ - /* Setup view matrix. */ - ED_view3d_draw_setup_view(NULL, scene, ar, v3d, rv3d->viewmat, rv3d->winmat, NULL); - - glClear(GL_DEPTH_BUFFER_BIT); - - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_set(rv3d); - } - /* get surface depth without bias */ - rv3d->rflag |= RV3D_ZOFFSET_DISABLED; + GLubyte color[4] = {0, 108, 255, 255}; /* bright blue so it matches device LEDs */ - v3d->zbuf = true; - glEnable(GL_DEPTH_TEST); + negate_v3_v3(o, rv3d->ofs); - view3d_draw_depth_loop(scene, ar, v3d); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(GL_FALSE); /* don't overwrite zbuf */ - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_disable(); - } - rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED; - - v3d->zbuf = zbuf; - if (!v3d->zbuf) glDisable(GL_DEPTH_TEST); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); - U.glalphaclip = glalphaclip; - v3d->flag = flag; - U.obcenter_dia = obcenter_dia; + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); - UI_Theme_Restore(&theme_state); -} + if (rv3d->rot_angle != 0.0f) { + /* -- draw rotation axis -- */ + float scaled_axis[3]; + const float scale = rv3d->dist; + mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale); -void ED_view3d_draw_select_loop( - ViewContext *vc, Scene *scene, View3D *v3d, ARegion *ar, - bool use_obedit_skip, bool use_nearest) -{ - short code = 1; - const short dflag = DRAW_PICKING | DRAW_CONSTCOLOR; - if (vc->obedit && vc->obedit->type == OB_MBALL) { - draw_object(scene, ar, v3d, BASACT, dflag); - } - else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) { - /* if not drawing sketch, draw bones */ - if (!BDR_drawSketchNames(vc)) { - draw_object(scene, ar, v3d, BASACT, dflag); - } - } - else { - Base *base; + immBegin(GWN_PRIM_LINE_STRIP, 3); + color[3] = 0; /* more transparent toward the ends */ + immAttrib4ubv(col, color); + add_v3_v3v3(end, o, scaled_axis); + immVertex3fv(pos, end); - for (base = scene->base.first; base; base = base->next) { - if (base->lay & v3d->lay) { +#if 0 + color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */ + /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */ +#endif - if ((base->object->restrictflag & OB_RESTRICT_SELECT) || - (use_obedit_skip && (scene->obedit->data == base->object->data))) - { - base->selcol = 0; - } - else { - base->selcol = code; + color[3] = 127; /* more opaque toward the center */ + immAttrib4ubv(col, color); + immVertex3fv(pos, o); - if (use_nearest && (base->object->dtx & OB_DRAWXRAY)) { - ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag); - } - else { - if (GPU_select_load_id(code)) { - draw_object_select(scene, ar, v3d, base, dflag); - } - } - code++; - } + color[3] = 0; + immAttrib4ubv(col, color); + sub_v3_v3v3(end, o, scaled_axis); + immVertex3fv(pos, end); + immEnd(); + + /* -- draw ring around rotation center -- */ + { +#define ROT_AXIS_DETAIL 13 + + const float s = 0.05f * scale; + const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL); + + float q[4]; /* rotate ring so it's perpendicular to axis */ + const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f; + if (!upright) { + const float up[3] = {0.0f, 0.0f, 1.0f}; + float vis_angle, vis_axis[3]; + + cross_v3_v3v3(vis_axis, up, rv3d->rot_axis); + vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis)); + axis_angle_to_quat(q, vis_axis, vis_angle); } - } - if (use_nearest) { - bool xrayclear = true; - if (v3d->afterdraw_xray.first) { - view3d_draw_xray_select(scene, ar, v3d, &xrayclear); + immBegin(GWN_PRIM_LINE_LOOP, ROT_AXIS_DETAIL); + color[3] = 63; /* somewhat faint */ + immAttrib4ubv(col, color); + float angle = 0.0f; + for (int i = 0; i < ROT_AXIS_DETAIL; ++i, angle += step) { + float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f}; + + if (!upright) { + mul_qt_v3(q, p); + } + + add_v3_v3(p, o); + immVertex3fv(pos, p); } + immEnd(); + +#undef ROT_AXIS_DETAIL } + + color[3] = 255; /* solid dot */ } + else + color[3] = 127; /* see-through dot */ + + immUnbindProgram(); + + /* -- draw rotation center -- */ + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); + glPointSize(5.0f); + immBegin(GWN_PRIM_POINTS, 1); + immAttrib4ubv(col, color); + immVertex3fv(pos, o); + immEnd(); + immUnbindProgram(); + +#if 0 + /* find screen coordinates for rotation center, then draw pretty icon */ + mul_m4_v3(rv3d->persinv, rot_center); + UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN); + /* ^^ just playing around, does not work */ +#endif + + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); } +#endif /* WITH_INPUT_NDOF */ -typedef struct View3DShadow { - struct View3DShadow *next, *prev; - GPULamp *lamp; -} View3DShadow; +/* ******************** info ***************** */ -static void gpu_render_lamp_update(Scene *scene, View3D *v3d, - Object *ob, Object *par, - float obmat[4][4], unsigned int lay, - ListBase *shadows, SceneRenderLayer *srl) +/** +* Render and camera border +*/ +static void view3d_draw_border(const bContext *C, ARegion *ar) { - GPULamp *lamp; - Lamp *la = (Lamp *)ob->data; - View3DShadow *shadow; - unsigned int layers; - - lamp = GPU_lamp_from_blender(scene, ob, par); - - if (lamp) { - GPU_lamp_update(lamp, lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat); - GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy); - - layers = lay & v3d->lay; - if (srl) - layers &= srl->lay; - - if (layers && - GPU_lamp_has_shadow_buffer(lamp) && - /* keep last, may do string lookup */ - GPU_lamp_visible(lamp, srl, NULL)) - { - shadow = MEM_callocN(sizeof(View3DShadow), "View3DShadow"); - shadow->lamp = lamp; - BLI_addtail(shadows, shadow); - } + Scene *scene = CTX_data_scene(C); + RegionView3D *rv3d = ar->regiondata; + View3D *v3d = CTX_wm_view3d(C); + + if (rv3d->persp == RV3D_CAMOB) { + drawviewborder(scene, ar, v3d); + } + else if (v3d->flag2 & V3D_RENDER_BORDER) { + drawrenderborder(ar, v3d); } } -static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d) +/** +* Grease Pencil +*/ +static void view3d_draw_grease_pencil(const bContext *UNUSED(C)) { - ListBase shadows; - View3DShadow *shadow; - Scene *sce_iter; - Base *base; - Object *ob; - World *world = scene->world; - SceneRenderLayer *srl = v3d->scenelock ? BLI_findlink(&scene->r.layers, scene->r.actlay) : NULL; - - BLI_listbase_clear(&shadows); - - /* update lamp transform and gather shadow lamps */ - for (SETLOOPER(scene, sce_iter, base)) { - ob = base->object; - - if (ob->type == OB_LAMP) - gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, ob->lay, &shadows, srl); - - if (ob->transflag & OB_DUPLI) { - DupliObject *dob; - ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob); - - for (dob = lb->first; dob; dob = dob->next) - if (dob->ob->type == OB_LAMP) - gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, ob->lay, &shadows, srl); - - free_object_duplilist(lb); - } - } - - /* render shadows after updating all lamps, nested object_duplilist - * don't work correct since it's replacing object matrices */ - for (shadow = shadows.first; shadow; shadow = shadow->next) { - /* this needs to be done better .. */ - float viewmat[4][4], winmat[4][4]; - int drawtype, lay, winsize, flag2 = v3d->flag2; - ARegion ar = {NULL}; - RegionView3D rv3d = {{{0}}}; - - drawtype = v3d->drawtype; - lay = v3d->lay; - - v3d->drawtype = OB_SOLID; - v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp); - v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP); - v3d->flag2 |= V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW; - - GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat); - - ar.regiondata = &rv3d; - ar.regiontype = RGN_TYPE_WINDOW; - rv3d.persp = RV3D_CAMOB; - copy_m4_m4(rv3d.winmat, winmat); - copy_m4_m4(rv3d.viewmat, viewmat); - invert_m4_m4(rv3d.viewinv, rv3d.viewmat); - mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat); - invert_m4_m4(rv3d.persinv, rv3d.viewinv); - - /* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */ - ED_view3d_draw_offscreen( - scene, v3d, &ar, winsize, winsize, viewmat, winmat, - false, false, true, - NULL, NULL, NULL, NULL); - GPU_lamp_shadow_buffer_unbind(shadow->lamp); - - v3d->drawtype = drawtype; - v3d->lay = lay; - v3d->flag2 = flag2; - } - - BLI_freelistN(&shadows); - - /* update world values */ - if (world) { - GPU_mist_update_enable(world->mode & WO_MIST); - GPU_mist_update_values(world->mistype, world->miststa, world->mistdist, world->misi, &world->horr); - GPU_horizon_update_color(&world->horr); - GPU_ambient_update_color(&world->ambr); - GPU_zenith_update_color(&world->zenr); - } + /* TODO viewport */ } -/* *********************** customdata **************** */ -CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d) +/** +* Viewport Name +*/ +static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d) { - CustomDataMask mask = 0; - const int drawtype = view3d_effective_drawtype(v3d); + const char *name = NULL; - if (ELEM(drawtype, OB_TEXTURE, OB_MATERIAL) || - ((drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX))) - { - mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; + switch (rv3d->view) { + case RV3D_VIEW_FRONT: + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho"); + else name = IFACE_("Front Persp"); + break; + case RV3D_VIEW_BACK: + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho"); + else name = IFACE_("Back Persp"); + break; + case RV3D_VIEW_TOP: + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho"); + else name = IFACE_("Top Persp"); + break; + case RV3D_VIEW_BOTTOM: + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho"); + else name = IFACE_("Bottom Persp"); + break; + case RV3D_VIEW_RIGHT: + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho"); + else name = IFACE_("Right Persp"); + break; + case RV3D_VIEW_LEFT: + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho"); + else name = IFACE_("Left Persp"); + break; - if (BKE_scene_use_new_shading_nodes(scene)) { - if (drawtype == OB_MATERIAL) - mask |= CD_MASK_ORCO; - } - else { - if ((scene->gm.matmode == GAME_MAT_GLSL && drawtype == OB_TEXTURE) || - (drawtype == OB_MATERIAL)) - { - mask |= CD_MASK_ORCO; + default: + if (rv3d->persp == RV3D_CAMOB) { + if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) { + Camera *cam; + cam = v3d->camera->data; + if (cam->type == CAM_PERSP) { + name = IFACE_("Camera Persp"); + } + else if (cam->type == CAM_ORTHO) { + name = IFACE_("Camera Ortho"); + } + else { + BLI_assert(cam->type == CAM_PANO); + name = IFACE_("Camera Pano"); + } + } + else { + name = IFACE_("Object as Camera"); + } + } + else { + name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp"); } - } } - return mask; + return name; } -/* goes over all modes and view3d settings */ -CustomDataMask ED_view3d_screen_datamask(const bScreen *screen) +static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect) { - const Scene *scene = screen->scene; - CustomDataMask mask = CD_MASK_BAREMESH; - const ScrArea *sa; - - /* check if we need tfaces & mcols due to view mode */ - for (sa = screen->areabase.first; sa; sa = sa->next) { - if (sa->spacetype == SPACE_VIEW3D) { - mask |= ED_view3d_datamask(scene, sa->spacedata.first); - } + RegionView3D *rv3d = ar->regiondata; + const char *name = view3d_get_name(v3d, rv3d); + /* increase size for unicode languages (Chinese in utf-8...) */ +#ifdef WITH_INTERNATIONAL + char tmpstr[96]; +#else + char tmpstr[32]; +#endif + + if (v3d->localvd) { + BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name); + name = tmpstr; } - return mask; + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); +#ifdef WITH_INTERNATIONAL + BLF_draw_default(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr)); +#else + BLF_draw_default_ascii(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr)); +#endif } /** - * \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore + * draw info beside axes in bottom left-corner: + * framenum, object name, bone name (if available), marker name (if available) */ -void ED_view3d_update_viewmat( - Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect) -{ - RegionView3D *rv3d = ar->regiondata; - /* setup window matrices */ - if (winmat) - copy_m4_m4(rv3d->winmat, winmat); - else - view3d_winmatrix_set(ar, v3d, rect); +static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) +{ + const int cfra = CFRA; + const char *msg_pin = " (Pinned)"; + const char *msg_sep = " : "; - /* setup view matrix */ - if (viewmat) - copy_m4_m4(rv3d->viewmat, viewmat); - else - view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */ + const int font_id = BLF_default(); - /* update utility matrices */ - mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); - invert_m4_m4(rv3d->persinv, rv3d->persmat); - invert_m4_m4(rv3d->viewinv, rv3d->viewmat); - - /* calculate GLSL view dependent values */ + char info[300]; + char *s = info; + short offset = 1.5f * UI_UNIT_X + rect->xmin; - /* store window coordinates scaling/offset */ - if (rv3d->persp == RV3D_CAMOB && v3d->camera) { - rctf cameraborder; - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false); - rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder); - rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder); - - rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx; - rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy; - } - else { - rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f; - rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f; - } + s += sprintf(s, "(%d)", cfra); - /** - * Calculate pixel-size factor once, is used for lamps and object centers. - * Used by #ED_view3d_pixel_size and typically not accessed directly. - * - * \note #BKE_camera_params_compute_viewplane' also calculates a pixel-size value, - * passed to #RE_SetPixelSize, in ortho mode this is compatible with this value, - * but in perspective mode its offset by the near-clip. - * - * 'RegionView3D.pixsize' is used for viewport drawing, not rendering. + /* + * info can contain: + * - a frame (7 + 2) + * - 3 object names (MAX_NAME) + * - 2 BREAD_CRUMB_SEPARATORs (6) + * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room! + * - a marker name (MAX_NAME + 3) */ - { - /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' - * because of float point precision problems at large values [#23908] */ - float v1[3], v2[3]; - float len_px, len_sc; - - v1[0] = rv3d->persmat[0][0]; - v1[1] = rv3d->persmat[1][0]; - v1[2] = rv3d->persmat[2][0]; - v2[0] = rv3d->persmat[0][1]; - v2[1] = rv3d->persmat[1][1]; - v2[2] = rv3d->persmat[2][1]; - - len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2))); - len_sc = (float)MAX2(ar->winx, ar->winy); - - rv3d->pixsize = len_px / len_sc; - } -} + /* get name of marker on current frame (if available) */ + const char *markern = BKE_scene_find_marker_name(scene, cfra); -/** - * Shared by #ED_view3d_draw_offscreen and #view3d_main_region_draw_objects - * - * \note \a C and \a grid_unit will be NULL when \a draw_offscreen is set. - * \note Drawing lamps and opengl render uses this, so dont do grease pencil or view widgets here. - */ -static void view3d_draw_objects( - const bContext *C, - Scene *scene, View3D *v3d, ARegion *ar, - const char **grid_unit, - const bool do_bgpic, const bool draw_offscreen, GPUFX *fx) -{ - RegionView3D *rv3d = ar->regiondata; - Base *base; - const bool do_camera_frame = !draw_offscreen; - const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0; - const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO); - /* only draw grids after in solid modes, else it hovers over mesh wires */ - const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx; - bool do_composite_xray = false; - bool xrayclear = true; - - if (!draw_offscreen) { - ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); - } + /* check if there is an object */ + if (ob) { + *s++ = ' '; + s += BLI_strcpy_rlen(s, ob->id.name + 2); - if (rv3d->rflag & RV3D_CLIPPING) - view3d_draw_clipping(rv3d); + /* name(s) to display depends on type of object */ + if (ob->type == OB_ARMATURE) { + bArmature *arm = ob->data; - /* set zbuffer after we draw clipping region */ - if (v3d->drawtype > OB_WIRE) { - v3d->zbuf = true; - } - else { - v3d->zbuf = false; - } + /* show name of active bone too (if possible) */ + if (arm->edbo) { + if (arm->act_edbone) { + s += BLI_strcpy_rlen(s, msg_sep); + s += BLI_strcpy_rlen(s, arm->act_edbone->name); + } + } + else if (ob->mode & OB_MODE_POSE) { + if (arm->act_bone) { - /* special case (depth for wire color) */ - if (v3d->drawtype <= OB_WIRE) { - if (scene->obedit && scene->obedit->type == OB_MESH) { - Mesh *me = scene->obedit->data; - if (me->drawflag & ME_DRAWEIGHT) { - v3d->zbuf = true; + if (arm->act_bone->layer & arm->layer) { + s += BLI_strcpy_rlen(s, msg_sep); + s += BLI_strcpy_rlen(s, arm->act_bone->name); + } + } } } - } - - if (v3d->zbuf) { - glEnable(GL_DEPTH_TEST); - } + else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) { + /* try to display active bone and active shapekey too (if they exist) */ - /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override - * objects if done last */ - if (draw_grids) { - /* needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views. */ - rv3d->gridview = ED_view3d_grid_scale(scene, v3d, grid_unit); + if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) { + Object *armobj = BKE_object_pose_armature_get(ob); + if (armobj && armobj->mode & OB_MODE_POSE) { + bArmature *arm = armobj->data; + if (arm->act_bone) { + if (arm->act_bone->layer & arm->layer) { + s += BLI_strcpy_rlen(s, msg_sep); + s += BLI_strcpy_rlen(s, arm->act_bone->name); + } + } + } + } - if (!draw_floor) { - ED_region_pixelspace(ar); - *grid_unit = NULL; /* drawgrid need this to detect/affect smallest valid unit... */ - drawgrid(&scene->unit, ar, v3d, grid_unit); - /* XXX make function? replaces persp(1) */ - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(rv3d->winmat); - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(rv3d->viewmat); - } - else if (!draw_grids_after) { - drawfloor(scene, v3d, grid_unit, true); + Key *key = BKE_key_from_object(ob); + if (key) { + KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1); + if (kb) { + s += BLI_strcpy_rlen(s, msg_sep); + s += BLI_strcpy_rlen(s, kb->name); + if (ob->shapeflag & OB_SHAPE_LOCK) { + s += BLI_strcpy_rlen(s, IFACE_(msg_pin)); + } + } + } } - } - /* important to do before clipping */ - if (do_bgpic) { - view3d_draw_bgpic_test(scene, ar, v3d, false, do_camera_frame); + /* color depends on whether there is a keyframe */ + if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) + UI_FontThemeColor(font_id, TH_TIME_KEYFRAME); + else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) + UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME); + else + UI_FontThemeColor(font_id, TH_TEXT_HI); } - - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_set(rv3d); + else { + /* no object */ + if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra)) + UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME); + else + UI_FontThemeColor(font_id, TH_TEXT_HI); } - /* draw set first */ - if (scene->set) { - const short dflag = DRAW_CONSTCOLOR | DRAW_SCENESET; - Scene *sce_iter; - for (SETLOOPER(scene->set, sce_iter, base)) { - if (v3d->lay & base->lay) { - UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f); - draw_object(scene, ar, v3d, base, dflag); - - if (base->object->transflag & OB_DUPLI) { - draw_dupli_objects_color(scene, ar, v3d, base, dflag, TH_UNDEFINED); - } - } - } - - /* Transp and X-ray afterdraw stuff for sets is done later */ + if (markern) { + s += sprintf(s, " <%s>", markern); } + if (U.uiflag & USER_SHOW_ROTVIEWICON) + offset = U.widget_unit + (U.rvisize * 2) + rect->xmin; - if (draw_offscreen) { - for (base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { - /* dupli drawing */ - if (base->object->transflag & OB_DUPLI) - draw_dupli_objects(scene, ar, v3d, base); + BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info)); +} - draw_object(scene, ar, v3d, base, 0); - } - } - } - else { - unsigned int lay_used = 0; +/* ******************** view loop ***************** */ - /* then draw not selected and the duplis, but skip editmode object */ - for (base = scene->base.first; base; base = base->next) { - lay_used |= base->lay; +/** +* Information drawn on top of the solid plates and composed data +*/ +void view3d_draw_region_info(const bContext *C, ARegion *ar, const int offset) +{ + RegionView3D *rv3d = ar->regiondata; + View3D *v3d = CTX_wm_view3d(C); + Scene *scene = CTX_data_scene(C); + wmWindowManager *wm = CTX_wm_manager(C); - if (v3d->lay & base->lay) { + /* correct projection matrix */ + ED_region_pixelspace(ar); - /* dupli drawing */ - if (base->object->transflag & OB_DUPLI) { - draw_dupli_objects(scene, ar, v3d, base); - } - if ((base->flag & SELECT) == 0) { - if (base->object != scene->obedit) - draw_object(scene, ar, v3d, base, 0); - } - } - } + /* local coordinate visible rect inside region, to accomodate overlapping ui */ + rcti rect; + ED_region_visible_rect(ar, &rect); - /* mask out localview */ - v3d->lay_used = lay_used & ((1 << 20) - 1); + /* Leave room for previously drawn info. */ + rect.ymax -= offset; - /* draw selected and editmode */ - for (base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { - if (base->object == scene->obedit || (base->flag & SELECT)) { - draw_object(scene, ar, v3d, base, 0); - } - } - } + view3d_draw_border(C, ar); + view3d_draw_grease_pencil(C); + + if (U.uiflag & USER_SHOW_ROTVIEWICON) { + draw_view_axis(rv3d, &rect); } - /* perspective floor goes last to use scene depth and avoid writing to depth buffer */ - if (draw_grids_after) { - drawfloor(scene, v3d, grid_unit, false); + if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) { + ED_scene_draw_fps(scene, &rect); + } + else if (U.uiflag & USER_SHOW_VIEWPORTNAME) { + draw_viewport_name(ar, v3d, &rect); } - /* must be before xray draw which clears the depth buffer */ - if (v3d->flag2 & V3D_SHOW_GPENCIL) { - wmWindowManager *wm = (C != NULL) ? CTX_wm_manager(C) : NULL; - - /* must be before xray draw which clears the depth buffer */ - if (v3d->zbuf) glDisable(GL_DEPTH_TEST); - ED_gpencil_draw_view3d(wm, scene, v3d, ar, true); - if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + if (U.uiflag & USER_DRAWVIEWINFO) { + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = OBACT(sl); + draw_selected_name(scene, ob, &rect); } +#if 0 /* TODO */ + if (grid_unit) { /* draw below the viewport name */ + char numstr[32] = ""; - /* transp and X-ray afterdraw stuff */ - if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d); + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); + if (v3d->grid != 1.0f) { + BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); + } - /* always do that here to cleanup depth buffers if none needed */ - if (fx) { - do_composite_xray = v3d->zbuf && (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first); - GPU_fx_compositor_setup_XRay_pass(fx, do_composite_xray); + BLF_draw_default_ascii(rect.xmin + U.widget_unit, + rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f, + numstr[0] ? numstr : grid_unit, sizeof(numstr)); } +#endif +} - if (v3d->afterdraw_xray.first) view3d_draw_xray(scene, ar, v3d, &xrayclear); - if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, xrayclear); +static void view3d_draw_view(const bContext *C, ARegion *ar) +{ + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); - if (fx && do_composite_xray) { - GPU_fx_compositor_XRay_resolve(fx); - } + ED_view3d_draw_setup_view(CTX_wm_window(C), &eval_ctx, CTX_data_scene(C), ar, CTX_wm_view3d(C), NULL, NULL, NULL); - if (!draw_offscreen) { - ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); - } + /* Only 100% compliant on new spec goes bellow */ + DRW_draw_view(C); +} - if (rv3d->rflag & RV3D_CLIPPING) - ED_view3d_clipping_disable(); +void view3d_main_region_draw(const bContext *C, ARegion *ar) +{ + Scene *scene = CTX_data_scene(C); + WorkSpace *workspace = CTX_wm_workspace(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = ar->regiondata; + ViewRender *view_render = BKE_viewrender_get(scene, workspace); + RenderEngineType *type = RE_engines_find(view_render->engine_id); - /* important to do after clipping */ - if (do_bgpic) { - view3d_draw_bgpic_test(scene, ar, v3d, true, do_camera_frame); + /* Provisory Blender Internal drawing */ + if (type->flag & RE_USE_LEGACY_PIPELINE) { + view3d_main_region_draw_legacy(C, ar); + return; } - if (!draw_offscreen) { - BIF_draw_manipulator(C); + if (!rv3d->viewport) { + rv3d->viewport = GPU_viewport_create(); } - /* cleanup */ - if (v3d->zbuf) { - v3d->zbuf = false; - glDisable(GL_DEPTH_TEST); - } + GPU_viewport_bind(rv3d->viewport, &ar->winrct); + view3d_draw_view(C, ar); + GPU_viewport_unbind(rv3d->viewport); - if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) { - GPU_free_images_old(); - } + v3d->flag |= V3D_INVALID_BACKBUF; } -static void view3d_main_region_setup_view( - Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect) -{ - RegionView3D *rv3d = ar->regiondata; - ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat, rect); +/* -------------------------------------------------------------------- */ - /* set for opengl */ - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(rv3d->winmat); - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(rv3d->viewmat); -} +/** \name Offscreen Drawing + * \{ */ -/** - * Store values from #RegionView3D, set when drawing. - * This is needed when we draw with to a viewport using a different matrix (offscreen drawing for example). - * - * Values set by #ED_view3d_update_viewmat should be handled here. - */ -struct RV3DMatrixStore { - float winmat[4][4]; - float viewmat[4][4]; - float viewinv[4][4]; - float persmat[4][4]; - float persinv[4][4]; - float viewcamtexcofac[4]; - float pixsize; -}; - -struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d) +static void view3d_stereo3d_setup_offscreen( + const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar, + float winmat[4][4], const char *viewname) { - struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__); - copy_m4_m4(rv3dmat->winmat, rv3d->winmat); - copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat); - copy_m4_m4(rv3dmat->persmat, rv3d->persmat); - copy_m4_m4(rv3dmat->persinv, rv3d->persinv); - copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv); - copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac); - rv3dmat->pixsize = rv3d->pixsize; - return (void *)rv3dmat; -} + /* update the viewport matrices with the new camera */ + if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { + float viewmat[4][4]; + const bool is_left = STREQ(viewname, STEREO_LEFT_NAME); -void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat) -{ - copy_m4_m4(rv3d->winmat, rv3dmat->winmat); - copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat); - copy_m4_m4(rv3d->persmat, rv3dmat->persmat); - copy_m4_m4(rv3d->persinv, rv3dmat->persinv); - copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv); - copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac); - rv3d->pixsize = rv3dmat->pixsize; + BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL); + } + else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ + float viewmat[4][4]; + Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); + + BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL); + } } -void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d) +void ED_view3d_draw_offscreen_init(const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d) { - /* shadow buffers, before we setup matrices */ - if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) - gpu_update_lamps_shadows_world(scene, v3d); + RenderEngineType *type = eval_ctx->engine; + if (type->flag & RE_USE_LEGACY_PIPELINE) { + /* shadow buffers, before we setup matrices */ + if (draw_glsl_material(scene, sl, NULL, v3d, v3d->drawtype)) { + VP_deprecated_gpu_update_lamps_shadows_world(eval_ctx, scene, v3d); + } + } } /* @@ -3077,79 +1946,13 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d) */ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar) { - if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) { - RegionView3D *rv3d = ar->regiondata; - GPUMaterial *gpumat = GPU_material_world(scene, scene->world); - - /* calculate full shader for background */ - GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0)); - - bool material_not_bound = !GPU_material_bound(gpumat); - - if (material_not_bound) { - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glColor4f(0.0f, 0.0f, 0.0f, 1.0f); - } - - /* Draw world */ - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); - glBegin(GL_TRIANGLE_STRIP); - glVertex3f(-1.0, -1.0, 1.0); - glVertex3f(1.0, -1.0, 1.0); - glVertex3f(-1.0, 1.0, 1.0); - glVertex3f(1.0, 1.0, 1.0); - glEnd(); - - if (material_not_bound) { - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - } + glClear(GL_DEPTH_BUFFER_BIT); - GPU_material_unbind(gpumat); - - glDepthFunc(GL_LEQUAL); - glDisable(GL_DEPTH_TEST); + if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) { + VP_view3d_draw_background_world(scene, ar->regiondata); } else { - if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) { - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); - glBegin(GL_QUADS); - UI_ThemeColor(TH_LOW_GRAD); - glVertex3f(-1.0, -1.0, 1.0); - glVertex3f(1.0, -1.0, 1.0); - UI_ThemeColor(TH_HIGH_GRAD); - glVertex3f(1.0, 1.0, 1.0); - glVertex3f(-1.0, 1.0, 1.0); - glEnd(); - glDepthFunc(GL_LEQUAL); - glDisable(GL_DEPTH_TEST); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - } - else { - UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } + VP_view3d_draw_background_none(); } } @@ -3157,24 +1960,20 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar) * stuff like shadow buffers */ void ED_view3d_draw_offscreen( - Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy, + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *scene_layer, + View3D *v3d, ARegion *ar, int winx, int winy, float viewmat[4][4], float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, const char *viewname, GPUFX *fx, GPUFXSettings *fx_settings, GPUOffScreen *ofs) { - struct bThemeState theme_state; - int bwinx, bwiny; - rcti brect; bool do_compositing = false; RegionView3D *rv3d = ar->regiondata; - glPushMatrix(); - /* set temporary new size */ - bwinx = ar->winx; - bwiny = ar->winy; - brect = ar->winrct; + int bwinx = ar->winx; + int bwiny = ar->winy; + rcti brect = ar->winrct; ar->winx = winx; ar->winy = winy; @@ -3183,6 +1982,7 @@ void ED_view3d_draw_offscreen( ar->winrct.xmax = winx; ar->winrct.ymax = winy; + struct bThemeState theme_state; UI_Theme_Store(&theme_state); UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); @@ -3195,26 +1995,10 @@ void ED_view3d_draw_offscreen( GPU_free_images_anim(); } - /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */ - if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera) - view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname); - else - view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL); - - /* framebuffer fx needed, we need to draw offscreen first */ - if (v3d->fx_settings.fx_flag && fx) { - GPUSSAOSettings *ssao = NULL; - - if (v3d->drawtype < OB_SOLID) { - ssao = v3d->fx_settings.ssao; - v3d->fx_settings.ssao = NULL; - } - - do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings); - - if (ssao) - v3d->fx_settings.ssao = ssao; - } + gpuPushProjectionMatrix(); + gpuLoadIdentity(); + gpuPushMatrix(); + gpuLoadIdentity(); /* clear opengl buffers */ if (do_sky) { @@ -3225,28 +2009,57 @@ void ED_view3d_draw_offscreen( glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } + if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera) + view3d_stereo3d_setup_offscreen(eval_ctx, scene, v3d, ar, winmat, viewname); + else + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL); + /* main drawing call */ - view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL); + RenderEngineType *type = eval_ctx->engine; + if (type->flag & RE_USE_LEGACY_PIPELINE) { - /* post process */ - if (do_compositing) { - if (!winmat) - is_persp = rv3d->is_persp; - GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs); - } + /* framebuffer fx needed, we need to draw offscreen first */ + if (v3d->fx_settings.fx_flag && fx) { + GPUSSAOSettings *ssao = NULL; - if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) { - /* draw grease-pencil stuff */ - ED_region_pixelspace(ar); + if (v3d->drawtype < OB_SOLID) { + ssao = v3d->fx_settings.ssao; + v3d->fx_settings.ssao = NULL; + } + do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings); - if (v3d->flag2 & V3D_SHOW_GPENCIL) { - /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */ - ED_gpencil_draw_view3d(NULL, scene, v3d, ar, false); + if (ssao) + v3d->fx_settings.ssao = ssao; } - /* freeing the images again here could be done after the operator runs, leaving for now */ - GPU_free_images_anim(); + VP_deprecated_view3d_draw_objects(NULL, eval_ctx, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL); + + /* post process */ + if (do_compositing) { + if (!winmat) + is_persp = rv3d->is_persp; + GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs); + } + + if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + /* draw grease-pencil stuff */ + ED_region_pixelspace(ar); + + if (v3d->flag2 & V3D_SHOW_GPENCIL) { + /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */ + ED_gpencil_draw_view3d(NULL, scene, scene_layer, v3d, ar, false); + } + + /* freeing the images again here could be done after the operator runs, leaving for now */ + GPU_free_images_anim(); + } + } + else { + /* XXX, should take depsgraph as arg */ + Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, scene_layer, false); + BLI_assert(depsgraph != NULL); + DRW_draw_render_loop_offscreen(depsgraph, eval_ctx->engine, ar, v3d, ofs); } /* restore size */ @@ -3254,7 +2067,8 @@ void ED_view3d_draw_offscreen( ar->winy = bwiny; ar->winrct = brect; - glPopMatrix(); + gpuPopProjectionMatrix(); + gpuPopMatrix(); UI_Theme_Restore(&theme_state); @@ -3262,37 +2076,20 @@ void ED_view3d_draw_offscreen( } /** - * Set the correct matrices - */ -void ED_view3d_draw_setup_view( - wmWindow *win, Scene *scene, ARegion *ar, View3D *v3d, float viewmat[4][4], float winmat[4][4], const rcti *rect) -{ - RegionView3D *rv3d = ar->regiondata; - - /* Setup the view matrix. */ - if (view3d_stereo3d_active(win, scene, v3d, rv3d)) { - view3d_stereo3d_setup(scene, v3d, ar, rect); - } - else { - view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, rect); - } -} - -/** * Utility func for ED_view3d_draw_offscreen * * \param ofs: Optional off-screen buffer, can be NULL. * (avoids re-creating when doing multiple GL renders). */ ImBuf *ED_view3d_draw_offscreen_imbuf( - Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey, + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *scene_layer, + View3D *v3d, ARegion *ar, int sizex, int sizey, unsigned int flag, bool draw_background, int alpha_mode, int samples, bool full_samples, const char *viewname, /* output vars */ GPUFX *fx, GPUOffScreen *ofs, char err_out[256]) { RegionView3D *rv3d = ar->regiondata; - ImBuf *ibuf; const bool draw_sky = (alpha_mode == R_ADDSKY); /* view state */ @@ -3315,12 +2112,12 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( } } - ED_view3d_draw_offscreen_init(scene, v3d); + ED_view3d_draw_offscreen_init(eval_ctx, scene, scene_layer, v3d); GPU_offscreen_bind(ofs, true); /* read in pixels & stamp */ - ibuf = IMB_allocImBuf(sizex, sizey, 32, flag); + ImBuf *ibuf = IMB_allocImBuf(sizex, sizey, 32, flag); /* render 3d view */ if (rv3d->persp == RV3D_CAMOB && v3d->camera) { @@ -3357,7 +2154,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( if ((samples && full_samples) == 0) { /* Single-pass render, common case */ ED_view3d_draw_offscreen( - scene, v3d, ar, sizex, sizey, NULL, winmat, + eval_ctx, scene, scene_layer, v3d, ar, sizex, sizey, NULL, winmat, draw_background, draw_sky, !is_ortho, viewname, fx, &fx_settings, ofs); @@ -3376,25 +2173,23 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( /* use imbuf as temp storage, before writing into it from accumulation buffer */ unsigned char *rect_temp = ibuf->rect ? (void *)ibuf->rect : (void *)ibuf->rect_float; unsigned int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int[4]), "accum1"); - unsigned int i; - int j; BLI_jitter_init(jit_ofs, samples); /* first sample buffer, also initializes 'rv3d->persmat' */ ED_view3d_draw_offscreen( - scene, v3d, ar, sizex, sizey, NULL, winmat, + eval_ctx, scene, scene_layer, v3d, ar, sizex, sizey, NULL, winmat, draw_background, draw_sky, !is_ortho, viewname, fx, &fx_settings, ofs); GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp); - i = sizex * sizey * 4; + unsigned i = sizex * sizey * 4; while (i--) { accum_buffer[i] = rect_temp[i]; } /* skip the first sample */ - for (j = 1; j < samples; j++) { + for (int j = 1; j < samples; j++) { copy_m4_m4(winmat_jitter, winmat); window_translate_m4( winmat_jitter, rv3d->persmat, @@ -3402,7 +2197,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( (jit_ofs[j][1] * 2.0f) / sizey); ED_view3d_draw_offscreen( - scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, + eval_ctx, scene, scene_layer, v3d, ar, sizex, sizey, NULL, winmat_jitter, draw_background, draw_sky, !is_ortho, viewname, fx, &fx_settings, ofs); GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp); @@ -3453,7 +2248,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( * \note used by the sequencer */ ImBuf *ED_view3d_draw_offscreen_imbuf_simple( - Scene *scene, Object *camera, int width, int height, + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *scene_layer, + Object *camera, int width, int height, unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, int samples, bool full_samples, const char *viewname, GPUFX *fx, GPUOffScreen *ofs, char err_out[256]) @@ -3471,13 +2267,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple( v3d.lay = scene->lay; v3d.drawtype = drawtype; v3d.flag2 = V3D_RENDER_OVERRIDE; - + if (use_gpencil) v3d.flag2 |= V3D_SHOW_GPENCIL; if (use_solid_tex) v3d.flag2 |= V3D_SOLID_TEX; - + if (draw_background) v3d.flag3 |= V3D_SHOW_WORLD; @@ -3507,665 +2303,105 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple( invert_m4_m4(rv3d.persinv, rv3d.viewinv); return ED_view3d_draw_offscreen_imbuf( - scene, &v3d, &ar, width, height, flag, + eval_ctx, scene, scene_layer, &v3d, &ar, width, height, flag, draw_background, alpha_mode, samples, full_samples, viewname, fx, ofs, err_out); } +/** \} */ -/** - * \note The info that this uses is updated in #ED_refresh_viewport_fps, - * which currently gets called during #SCREEN_OT_animation_step. - */ -void ED_scene_draw_fps(Scene *scene, const rcti *rect) -{ - ScreenFrameRateInfo *fpsi = scene->fps_info; - float fps; - char printable[16]; - int i, tot; - - if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) - return; - - printable[0] = '\0'; - -#if 0 - /* this is too simple, better do an average */ - fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime)) -#else - fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime)); - - for (i = 0, tot = 0, fps = 0.0f; i < REDRAW_FRAME_AVERAGE; i++) { - if (fpsi->redrawtimes_fps[i]) { - fps += fpsi->redrawtimes_fps[i]; - tot++; - } - } - if (tot) { - fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE; - - //fpsi->redrawtime_index++; - //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE) - // fpsi->redrawtime = 0; - - fps = fps / tot; - } -#endif - - /* is this more than half a frame behind? */ - if (fps + 0.5f < (float)(FPS)) { - UI_ThemeColor(TH_REDALERT); - BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps); - } - else { - UI_ThemeColor(TH_TEXT_HI); - BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f)); - } - -#ifdef WITH_INTERNATIONAL - BLF_draw_default(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable)); -#else - BLF_draw_default_ascii(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable)); -#endif -} -static bool view3d_main_region_do_render_draw(Scene *scene) -{ - RenderEngineType *type = RE_engines_find(scene->r.engine); +/* -------------------------------------------------------------------- */ - return (type && type->view_update && type->view_draw); -} +/** \name Legacy Interface + * + * This will be removed once the viewport gets replaced + * meanwhile it should keep the old viewport working. + * + * \{ */ -bool ED_view3d_calc_render_border(Scene *scene, View3D *v3d, ARegion *ar, rcti *rect) +void VP_legacy_drawcursor(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d) { - RegionView3D *rv3d = ar->regiondata; - rctf viewborder; - bool use_border; - - /* test if there is a 3d view rendering */ - if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene)) - return false; - - /* test if there is a border render */ - if (rv3d->persp == RV3D_CAMOB) - use_border = (scene->r.mode & R_BORDER) != 0; - else - use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0; - - if (!use_border) - return false; - - /* compute border */ - if (rv3d->persp == RV3D_CAMOB) { - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false); - - rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); - rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); - rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); - rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); + if (is_cursor_visible(scene, sl)) { + drawcursor(scene, ar, v3d); } - else { - rect->xmin = v3d->render_border.xmin * ar->winx; - rect->xmax = v3d->render_border.xmax * ar->winx; - rect->ymin = v3d->render_border.ymin * ar->winy; - rect->ymax = v3d->render_border.ymax * ar->winy; - } - - BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin); - BLI_rcti_isect(&ar->winrct, rect, rect); - - return true; } -static bool view3d_main_region_draw_engine(const bContext *C, Scene *scene, - ARegion *ar, View3D *v3d, - bool clip_border, const rcti *border_rect) +void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect) { - RegionView3D *rv3d = ar->regiondata; - RenderEngineType *type; - GLint scissor[4]; - - /* create render engine */ - if (!rv3d->render_engine) { - RenderEngine *engine; - - type = RE_engines_find(scene->r.engine); - - if (!(type->view_update && type->view_draw)) - return false; - - engine = RE_engine_create_ex(type, true); - - engine->tile_x = scene->r.tilex; - engine->tile_y = scene->r.tiley; - - type->view_update(engine, C); - - rv3d->render_engine = engine; - } - - /* setup view matrices */ - view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL, NULL); - - /* background draw */ - ED_region_pixelspace(ar); - - if (clip_border) { - /* for border draw, we only need to clear a subset of the 3d view */ - if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) { - glGetIntegerv(GL_SCISSOR_BOX, scissor); - glScissor(border_rect->xmin, border_rect->ymin, - BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect)); - } - else { - return false; - } - } - - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - if (v3d->flag & V3D_DISPBGPICS) - view3d_draw_bgpic_test(scene, ar, v3d, false, true); - else - fdrawcheckerboard(0, 0, ar->winx, ar->winy); - - /* render result draw */ - type = rv3d->render_engine->type; - type->view_draw(rv3d->render_engine, C); - - if (v3d->flag & V3D_DISPBGPICS) - view3d_draw_bgpic_test(scene, ar, v3d, true, true); - - if (clip_border) { - /* restore scissor as it was before */ - glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); - } - - return true; + draw_view_axis(rv3d, rect); } -static void view3d_main_region_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ARegion *ar, bool render_border) +void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect) { - float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f}; - - if (!rv3d->render_engine || !rv3d->render_engine->text[0]) - return; - - if (render_border) { - /* draw darkened background color. no alpha because border render does - * partial redraw and will not redraw the region behind this info bar */ - float alpha = 1.0f - fill_color[3]; - Camera *camera = ED_view3d_camera_data_get(v3d, rv3d); - - if (camera) { - if (camera->flag & CAM_SHOWPASSEPARTOUT) { - alpha *= (1.0f - camera->passepartalpha); - } - } - - UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color); - mul_v3_fl(fill_color, alpha); - fill_color[3] = 1.0f; - } - - ED_region_info_draw(ar, rv3d->render_engine->text, fill_color, true); + draw_viewport_name(ar, v3d, rect); } -static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d) +void VP_legacy_draw_selected_name(Scene *scene, Object *ob, rcti *rect) { - if ((scene->r.scemode & R_MULTIVIEW) == 0) { - return false; - } - - if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) { - return false; - } - - switch (v3d->stereo3d_camera) { - case STEREO_MONO_ID: - return false; - break; - case STEREO_3D_ID: - /* win will be NULL when calling this from the selection or draw loop. */ - if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) { - return false; - } - if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) && - !BKE_scene_multiview_is_stereo3d(&scene->r)) - { - return false; - } - break; - /* We always need the stereo calculation for left and right cameras. */ - case STEREO_LEFT_ID: - case STEREO_RIGHT_ID: - default: - break; - } - return true; + draw_selected_name(scene, ob, rect); } -/* setup the view and win matrices for the multiview cameras - * - * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called - * we have no winmatrix (i.e., projection matrix) defined at that time. - * Since the camera and the camera shift are needed for the winmat calculation - * we do a small hack to replace it temporarily so we don't need to change the - * view3d)main_region_setup_view() code to account for that. - */ -static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect) +void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit) { - bool is_left; - const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; - const char *viewname; - - /* show only left or right camera */ - if (v3d->stereo3d_camera != STEREO_3D_ID) - v3d->multiview_eye = v3d->stereo3d_camera; - - is_left = v3d->multiview_eye == STEREO_LEFT_ID; - viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID]; - - /* update the viewport matrices with the new camera */ - if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { - Camera *data; - float viewmat[4][4]; - float shiftx; - - data = (Camera *)v3d->camera->data; - shiftx = data->shiftx; - - BLI_lock_thread(LOCK_VIEW3D); - data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname); - - BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); - view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL, rect); - - data->shiftx = shiftx; - BLI_unlock_thread(LOCK_VIEW3D); - } - else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ - float viewmat[4][4]; - Object *view_ob = v3d->camera; - Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); - - BLI_lock_thread(LOCK_VIEW3D); - v3d->camera = camera; - - BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); - view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL, rect); - - v3d->camera = view_ob; - BLI_unlock_thread(LOCK_VIEW3D); - } + drawgrid(unit, ar, v3d, grid_unit); } -static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar, - float winmat[4][4], const char *viewname) +void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth) { - /* update the viewport matrices with the new camera */ - if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { - float viewmat[4][4]; - const bool is_left = STREQ(viewname, STEREO_LEFT_NAME); - - BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); - view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL); - } - else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ - float viewmat[4][4]; - Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); - - BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); - view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL); - } + drawfloor(scene, v3d, grid_unit, write_depth); } -#ifdef WITH_GAMEENGINE -static void update_lods(Scene *scene, float camera_pos[3]) +void VP_legacy_view3d_main_region_setup_view( + const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, + ARegion *ar, float viewmat[4][4], float winmat[4][4]) { - Scene *sce_iter; - Base *base; - Object *ob; - - for (SETLOOPER(scene, sce_iter, base)) { - ob = base->object; - BKE_object_lod_update(ob, camera_pos); - } + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL); } -#endif -static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, View3D *v3d, - ARegion *ar, const char **grid_unit) +bool VP_legacy_view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d) { - wmWindow *win = CTX_wm_window(C); - RegionView3D *rv3d = ar->regiondata; - unsigned int lay_used = v3d->lay_used; - - /* post processing */ - bool do_compositing = false; - - /* shadow buffers, before we setup matrices */ - if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) - gpu_update_lamps_shadows_world(scene, v3d); - - /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */ - if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) { - rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE; - GPU_default_lights(); - } - - /* Setup the view matrix. */ - ED_view3d_draw_setup_view(CTX_wm_window(C), scene, ar, v3d, NULL, NULL, NULL); - - rv3d->rflag &= ~RV3D_IS_GAME_ENGINE; -#ifdef WITH_GAMEENGINE - if (STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME)) { - rv3d->rflag |= RV3D_IS_GAME_ENGINE; - - /* Make sure LoDs are up to date */ - update_lods(scene, rv3d->viewinv[3]); - } -#endif - - /* framebuffer fx needed, we need to draw offscreen first */ - if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) { - GPUFXSettings fx_settings; - BKE_screen_gpu_fx_validate(&v3d->fx_settings); - fx_settings = v3d->fx_settings; - if (!rv3d->compositor) - rv3d->compositor = GPU_fx_compositor_create(); - - if (rv3d->persp == RV3D_CAMOB && v3d->camera) - BKE_camera_to_gpu_dof(v3d->camera, &fx_settings); - else { - fx_settings.dof = NULL; - } - - do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings); - } - - /* clear the background */ - view3d_main_region_clear(scene, v3d, ar); - - /* enables anti-aliasing for 3D view drawing */ - if (win->multisamples != USER_MULTISAMPLE_NONE) { - glEnable(GL_MULTISAMPLE); - } - - /* main drawing call */ - view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL); - - /* post process */ - if (do_compositing) { - GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL); - } - - /* Disable back anti-aliasing */ - if (win->multisamples != USER_MULTISAMPLE_NONE) { - glDisable(GL_MULTISAMPLE); - } - - if (v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */ - /* find header and force tag redraw */ - ScrArea *sa = CTX_wm_area(C); - ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER); - ED_region_tag_redraw(ar_header); /* can be NULL */ - } - - if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { - BDR_drawSketch(C); - } - -#ifdef WITH_INPUT_NDOF - if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((rv3d->viewlock & RV3D_LOCKED) == 0) && (rv3d->persp != RV3D_CAMOB)) - /* TODO: draw something else (but not this) during fly mode */ - draw_rotation_guide(rv3d); -#endif + return view3d_stereo3d_active(win, scene, v3d, rv3d); } -static bool is_cursor_visible(Scene *scene) +void VP_legacy_view3d_stereo3d_setup(const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar) { - Object *ob = OBACT; - - /* don't draw cursor in paint modes, but with a few exceptions */ - if (ob && ob->mode & OB_MODE_ALL_PAINT) { - /* exception: object is in weight paint and has deforming armature in pose mode */ - if (ob->mode & OB_MODE_WEIGHT_PAINT) { - if (BKE_object_pose_armature_get(ob) != NULL) { - return true; - } - } - /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */ - else if (ob->mode & OB_MODE_TEXTURE_PAINT) { - const Paint *p = BKE_paint_get_active(scene); - - if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) { - if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) { - return true; - } - } - } - - /* no exception met? then don't draw cursor! */ - return false; - } - - return true; + view3d_stereo3d_setup(eval_ctx, scene, v3d, ar, NULL); } -static void view3d_main_region_draw_info(const bContext *C, Scene *scene, - ARegion *ar, View3D *v3d, - const char *grid_unit, bool render_border) +bool VP_legacy_use_depth(Scene *scene, View3D *v3d) { - wmWindowManager *wm = CTX_wm_manager(C); - RegionView3D *rv3d = ar->regiondata; - rcti rect; - - /* local coordinate visible rect inside region, to accomodate overlapping ui */ - ED_region_visible_rect(ar, &rect); - - if (rv3d->persp == RV3D_CAMOB) { - drawviewborder(scene, ar, v3d); - } - else if (v3d->flag2 & V3D_RENDER_BORDER) { - glLineWidth(1.0f); - setlinestyle(3); - cpack(0x4040FF); - - sdrawbox(v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy, - v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy); - - setlinestyle(0); - } - - if (v3d->flag2 & V3D_SHOW_GPENCIL) { - /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */ - ED_gpencil_draw_view3d(wm, scene, v3d, ar, false); - } - - if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { - Object *ob; - - /* 3d cursor */ - if (is_cursor_visible(scene)) { - drawcursor(scene, ar, v3d); - } - - if (U.uiflag & USER_SHOW_ROTVIEWICON) - draw_view_axis(rv3d, &rect); - else - draw_view_icon(rv3d, &rect); - - ob = OBACT; - if (U.uiflag & USER_DRAWVIEWINFO) - draw_selected_name(scene, ob, &rect); - } - - if (rv3d->render_engine) { - view3d_main_region_draw_engine_info(v3d, rv3d, ar, render_border); - return; - } - - if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { - if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) { - ED_scene_draw_fps(scene, &rect); - } - else if (U.uiflag & USER_SHOW_VIEWPORTNAME) { - draw_viewport_name(ar, v3d, &rect); - } - - if (grid_unit) { /* draw below the viewport name */ - char numstr[32] = ""; - - UI_ThemeColor(TH_TEXT_HI); - if (v3d->grid != 1.0f) { - BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); - } - - BLF_draw_default_ascii(rect.xmin + U.widget_unit, - rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f, - numstr[0] ? numstr : grid_unit, sizeof(numstr)); - } - } + return use_depth_doit(scene, v3d); } -void view3d_main_region_draw(const bContext *C, ARegion *ar) +void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) { - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - const char *grid_unit = NULL; - rcti border_rect; - bool render_border, clip_border; - - /* if we only redraw render border area, skip opengl draw and also - * don't do scissor because it's already set */ - render_border = ED_view3d_calc_render_border(scene, v3d, ar, &border_rect); - clip_border = (render_border && !BLI_rcti_compare(&ar->drawrct, &border_rect)); - - /* draw viewport using opengl */ - if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene) || clip_border) { - view3d_main_region_draw_objects(C, scene, v3d, ar, &grid_unit); - -#ifdef DEBUG_DRAW - bl_debug_draw(); -#endif - if (G.debug & G_DEBUG_SIMDATA) - draw_sim_debug_data(scene, v3d, ar); - - ED_region_pixelspace(ar); - } - - /* draw viewport using external renderer */ - if (v3d->drawtype == OB_RENDER) - view3d_main_region_draw_engine(C, scene, ar, v3d, clip_border, &border_rect); - - view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border); - - v3d->flag |= V3D_INVALID_BACKBUF; - - BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_transp)); - BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xray)); - BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xraytransp)); + drawviewborder(scene, ar, v3d); } -#ifdef DEBUG_DRAW -/* debug drawing */ -#define _DEBUG_DRAW_QUAD_TOT 1024 -#define _DEBUG_DRAW_EDGE_TOT 1024 -static float _bl_debug_draw_quads[_DEBUG_DRAW_QUAD_TOT][4][3]; -static int _bl_debug_draw_quads_tot = 0; -static float _bl_debug_draw_edges[_DEBUG_DRAW_QUAD_TOT][2][3]; -static int _bl_debug_draw_edges_tot = 0; -static unsigned int _bl_debug_draw_quads_color[_DEBUG_DRAW_QUAD_TOT]; -static unsigned int _bl_debug_draw_edges_color[_DEBUG_DRAW_EDGE_TOT]; -static unsigned int _bl_debug_draw_color; - -void bl_debug_draw_quad_clear(void) -{ - _bl_debug_draw_quads_tot = 0; - _bl_debug_draw_edges_tot = 0; - _bl_debug_draw_color = 0x00FF0000; -} -void bl_debug_color_set(const unsigned int color) +void VP_drawrenderborder(ARegion *ar, View3D *v3d) { - _bl_debug_draw_color = color; + drawrenderborder(ar, v3d); } -void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]) + +void VP_view3d_draw_background_none(void) { - if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_QUAD_TOT) { - printf("%s: max quad count hit %d!", __func__, _bl_debug_draw_quads_tot); + if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) { + view3d_draw_background_gradient(); } else { - float *pt = &_bl_debug_draw_quads[_bl_debug_draw_quads_tot][0][0]; - copy_v3_v3(pt, v0); pt += 3; - copy_v3_v3(pt, v1); pt += 3; - copy_v3_v3(pt, v2); pt += 3; - copy_v3_v3(pt, v3); pt += 3; - _bl_debug_draw_quads_color[_bl_debug_draw_quads_tot] = _bl_debug_draw_color; - _bl_debug_draw_quads_tot++; + view3d_draw_background_none(); } } -void bl_debug_draw_edge_add(const float v0[3], const float v1[3]) + +void VP_view3d_draw_background_world(Scene *scene, RegionView3D *rv3d) { - if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_EDGE_TOT) { - printf("%s: max edge count hit %d!", __func__, _bl_debug_draw_edges_tot); - } - else { - float *pt = &_bl_debug_draw_edges[_bl_debug_draw_edges_tot][0][0]; - copy_v3_v3(pt, v0); pt += 3; - copy_v3_v3(pt, v1); pt += 3; - _bl_debug_draw_edges_color[_bl_debug_draw_edges_tot] = _bl_debug_draw_color; - _bl_debug_draw_edges_tot++; - } + view3d_draw_background_world(scene, rv3d); } -static void bl_debug_draw(void) + +void VP_view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar) { - unsigned int color; - if (_bl_debug_draw_quads_tot) { - int i; - color = _bl_debug_draw_quads_color[0]; - cpack(color); - for (i = 0; i < _bl_debug_draw_quads_tot; i ++) { - if (_bl_debug_draw_quads_color[i] != color) { - color = _bl_debug_draw_quads_color[i]; - cpack(color); - } - glBegin(GL_LINE_LOOP); - glVertex3fv(_bl_debug_draw_quads[i][0]); - glVertex3fv(_bl_debug_draw_quads[i][1]); - glVertex3fv(_bl_debug_draw_quads[i][2]); - glVertex3fv(_bl_debug_draw_quads[i][3]); - glEnd(); - } - } - if (_bl_debug_draw_edges_tot) { - int i; - color = _bl_debug_draw_edges_color[0]; - cpack(color); - glBegin(GL_LINES); - for (i = 0; i < _bl_debug_draw_edges_tot; i ++) { - if (_bl_debug_draw_edges_color[i] != color) { - color = _bl_debug_draw_edges_color[i]; - cpack(color); - } - glVertex3fv(_bl_debug_draw_edges[i][0]); - glVertex3fv(_bl_debug_draw_edges[i][1]); - } - glEnd(); - color = _bl_debug_draw_edges_color[0]; - cpack(color); - glPointSize(4.0); - glBegin(GL_POINTS); - for (i = 0; i < _bl_debug_draw_edges_tot; i ++) { - if (_bl_debug_draw_edges_color[i] != color) { - color = _bl_debug_draw_edges_color[i]; - cpack(color); - } - glVertex3fv(_bl_debug_draw_edges[i][0]); - glVertex3fv(_bl_debug_draw_edges[i][1]); - } - glEnd(); - } + view3d_main_region_clear(scene, v3d, ar); } -#endif + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c new file mode 100644 index 00000000000..9f1c27a09e7 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -0,0 +1,2186 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_draw_legacy.c + * \ingroup spview3d + */ + +#include <string.h> +#include <stdio.h> +#include <math.h> + +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_customdata_types.h" +#include "DNA_object_types.h" +#include "DNA_group_types.h" +#include "DNA_mesh_types.h" +#include "DNA_key_types.h" +#include "DNA_lamp_types.h" +#include "DNA_scene_types.h" +#include "DNA_world_types.h" +#include "DNA_brush_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_jitter.h" +#include "BLI_utildefines.h" +#include "BLI_endian_switch.h" +#include "BLI_threads.h" + +#include "BKE_anim.h" +#include "BKE_camera.h" +#include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_DerivedMesh.h" +#include "BKE_image.h" +#include "BKE_key.h" +#include "BKE_layer.h" +#include "BKE_main.h" +#include "BKE_object.h" +#include "BKE_global.h" +#include "BKE_paint.h" +#include "BKE_scene.h" +#include "BKE_screen.h" +#include "BKE_unit.h" +#include "BKE_movieclip.h" + +#include "DEG_depsgraph.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "IMB_colormanagement.h" + +#include "BIF_glutil.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "BLF_api.h" +#include "BLT_translation.h" + +#include "ED_armature.h" +#include "ED_keyframing.h" +#include "ED_gpencil.h" +#include "ED_screen.h" +#include "ED_space_api.h" +#include "ED_screen_types.h" +#include "ED_transform.h" + +#include "UI_interface.h" +#include "UI_interface_icons.h" +#include "UI_resources.h" + +#include "GPU_draw.h" +#include "GPU_framebuffer.h" +#include "GPU_lamp.h" +#include "GPU_material.h" +#include "GPU_compositing.h" +#include "GPU_extensions.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_select.h" +#include "GPU_matrix.h" + +#include "RE_engine.h" + +#include "DRW_engine.h" + +#include "view3d_intern.h" /* own include */ + +/* ********* custom clipping *********** */ + +static void view3d_draw_clipping(RegionView3D *rv3d) +{ + BoundBox *bb = rv3d->clipbb; + + if (bb) { + const unsigned int clipping_index[6][4] = { + {0, 1, 2, 3}, + {0, 4, 5, 1}, + {4, 7, 6, 5}, + {7, 3, 2, 6}, + {1, 5, 6, 2}, + {7, 4, 0, 3} + }; + + /* fill in zero alpha for rendering & re-projection [#31530] */ + unsigned char col[4]; + UI_GetThemeColor4ubv(TH_V3D_CLIPPING_BORDER, col); + glColor4ubv(col); + + glEnable(GL_BLEND); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, bb->vec); + glDrawElements(GL_QUADS, sizeof(clipping_index) / sizeof(unsigned int), GL_UNSIGNED_INT, clipping_index); + glDisableClientState(GL_VERTEX_ARRAY); + glDisable(GL_BLEND); + } +} + +void ED_view3d_clipping_set(RegionView3D *rv3d) +{ + double plane[4]; + const unsigned int tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6; + + for (unsigned a = 0; a < tot; a++) { + copy_v4db_v4fl(plane, rv3d->clip[a]); + glClipPlane(GL_CLIP_PLANE0 + a, plane); + glEnable(GL_CLIP_PLANE0 + a); + } +} + +/* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */ +void ED_view3d_clipping_disable(void) +{ + for (unsigned a = 0; a < 6; a++) { + glDisable(GL_CLIP_PLANE0 + a); + } +} +void ED_view3d_clipping_enable(void) +{ + for (unsigned a = 0; a < 6; a++) { + glEnable(GL_CLIP_PLANE0 + a); + } +} + +static bool view3d_clipping_test(const float co[3], const float clip[6][4]) +{ + if (plane_point_side_v3(clip[0], co) > 0.0f) + if (plane_point_side_v3(clip[1], co) > 0.0f) + if (plane_point_side_v3(clip[2], co) > 0.0f) + if (plane_point_side_v3(clip[3], co) > 0.0f) + return false; + + return true; +} + +/* for 'local' ED_view3d_clipping_local must run first + * then all comparisons can be done in localspace */ +bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local) +{ + return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip); +} + +/* ********* end custom clipping *********** */ + +static void draw_view_icon(RegionView3D *rv3d, rcti *rect) +{ + BIFIconID icon; + + if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) + icon = ICON_AXIS_TOP; + else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) + icon = ICON_AXIS_FRONT; + else if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) + icon = ICON_AXIS_SIDE; + else return; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + UI_icon_draw(5.0 + rect->xmin, 5.0 + rect->ymin, icon); + + glDisable(GL_BLEND); +} + +/* *********************** backdraw for selection *************** */ + +static void backdrawview3d(const struct EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, wmWindow *win, ARegion *ar, View3D *v3d) +{ + RegionView3D *rv3d = ar->regiondata; + struct Base *base = sl->basact; + int multisample_enabled; + + BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); + + if (base && (base->object->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) || + BKE_paint_select_face_test(base->object))) + { + /* do nothing */ + } + /* texture paint mode sampling */ + else if (base && (base->object->mode & OB_MODE_TEXTURE_PAINT) && + (v3d->drawtype > OB_WIRE)) + { + /* do nothing */ + } + else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) && + V3D_IS_ZBUF(v3d)) + { + /* do nothing */ + } + else if (scene->obedit && + V3D_IS_ZBUF(v3d)) + { + /* do nothing */ + } + else { + v3d->flag &= ~V3D_INVALID_BACKBUF; + return; + } + + if (!(v3d->flag & V3D_INVALID_BACKBUF)) + return; + +#if 0 + if (test) { + if (qtest()) { + addafterqueue(ar->win, BACKBUFDRAW, 1); + return; + } + } +#endif + + if (v3d->drawtype > OB_WIRE) v3d->zbuf = true; + + /* dithering and AA break color coding, so disable */ + glDisable(GL_DITHER); + + multisample_enabled = glIsEnabled(GL_MULTISAMPLE); + if (multisample_enabled) + glDisable(GL_MULTISAMPLE); + + if (win->multisamples != USER_MULTISAMPLE_NONE) { + /* for multisample we use an offscreen FBO. multisample drawing can fail + * with color coded selection drawing, and reading back depths from such + * a buffer can also cause a few seconds freeze on OS X / NVidia. */ + int w = BLI_rcti_size_x(&ar->winrct); + int h = BLI_rcti_size_y(&ar->winrct); + char error[256]; + + if (rv3d->gpuoffscreen) { + if (GPU_offscreen_width(rv3d->gpuoffscreen) != w || + GPU_offscreen_height(rv3d->gpuoffscreen) != h) + { + GPU_offscreen_free(rv3d->gpuoffscreen); + rv3d->gpuoffscreen = NULL; + } + } + + if (!rv3d->gpuoffscreen) { + rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error); + + if (!rv3d->gpuoffscreen) + fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error); + } + } + + if (rv3d->gpuoffscreen) + GPU_offscreen_bind(rv3d->gpuoffscreen, true); + else + glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct)); + + glClearColor(0.0, 0.0, 0.0, 0.0); + if (v3d->zbuf) { + glEnable(GL_DEPTH_TEST); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + else { + glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_DEPTH_TEST); + } + + if (rv3d->rflag & RV3D_CLIPPING) + ED_view3d_clipping_set(rv3d); + + G.f |= G_BACKBUFSEL; + + if (base && ((base->flag & BASE_VISIBLED) != 0)) + draw_object_backbufsel(eval_ctx, scene, v3d, rv3d, base->object); + + if (rv3d->gpuoffscreen) + GPU_offscreen_unbind(rv3d->gpuoffscreen, true); + else + ar->swap = 0; /* mark invalid backbuf for wm draw */ + + v3d->flag &= ~V3D_INVALID_BACKBUF; + + G.f &= ~G_BACKBUFSEL; + v3d->zbuf = false; + glDisable(GL_DEPTH_TEST); + glEnable(GL_DITHER); + if (multisample_enabled) + glEnable(GL_MULTISAMPLE); + + if (rv3d->rflag & RV3D_CLIPPING) + ED_view3d_clipping_disable(); +} + +void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data) +{ + RegionView3D *rv3d = ar->regiondata; + + if (rv3d->gpuoffscreen) { + GPU_offscreen_bind(rv3d->gpuoffscreen, true); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glReadPixels(x, y, w, h, format, type, data); + GPU_offscreen_unbind(rv3d->gpuoffscreen, true); + } + else { + glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); + } +} + +/* XXX depth reading exception, for code not using gpu offscreen */ +static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data) +{ + glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); +} + +void ED_view3d_backbuf_validate(const struct EvaluationContext *eval_ctx, ViewContext *vc) +{ + if (vc->v3d->flag & V3D_INVALID_BACKBUF) { + backdrawview3d(eval_ctx, vc->scene, vc->scene_layer, vc->win, vc->ar, vc->v3d); + } +} + +/** + * allow for small values [0.5 - 2.5], + * and large values, FLT_MAX by clamping by the area size + */ +int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) +{ + return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); +} + +/* samples a single pixel (copied from vpaint) */ +unsigned int ED_view3d_backbuf_sample( + const EvaluationContext *eval_ctx, ViewContext *vc, int x, int y) +{ + if (x >= vc->ar->winx || y >= vc->ar->winy) { + return 0; + } + + ED_view3d_backbuf_validate(eval_ctx, vc); + + unsigned int col; + view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); + glReadBuffer(GL_BACK); + + if (ENDIAN_ORDER == B_ENDIAN) { + BLI_endian_switch_uint32(&col); + } + + return GPU_select_to_index(col); +} + +/* reads full rect, converts indices */ +ImBuf *ED_view3d_backbuf_read( + const EvaluationContext *eval_ctx, ViewContext *vc, int xmin, int ymin, int xmax, int ymax) +{ + /* clip */ + const rcti clip = { + max_ii(xmin, 0), min_ii(xmax, vc->ar->winx - 1), + max_ii(ymin, 0), min_ii(ymax, vc->ar->winy - 1)}; + const int size_clip[2] = { + BLI_rcti_size_x(&clip) + 1, + BLI_rcti_size_y(&clip) + 1}; + + if (UNLIKELY((clip.xmin > clip.xmax) || + (clip.ymin > clip.ymax))) + { + return NULL; + } + + ImBuf *ibuf_clip = IMB_allocImBuf(size_clip[0], size_clip[1], 32, IB_rect); + + ED_view3d_backbuf_validate(eval_ctx, vc); + + view3d_opengl_read_pixels(vc->ar, clip.xmin, clip.ymin, size_clip[0], size_clip[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf_clip->rect); + + glReadBuffer(GL_BACK); + + if (ENDIAN_ORDER == B_ENDIAN) { + IMB_convert_rgba_to_abgr(ibuf_clip); + } + + GPU_select_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]); + + if ((clip.xmin == xmin) && + (clip.xmax == xmax) && + (clip.ymin == ymin) && + (clip.ymax == ymax)) + { + return ibuf_clip; + } + else { + /* put clipped result into a non-clipped buffer */ + const int size[2] = { + (xmax - xmin + 1), + (ymax - ymin + 1)}; + + ImBuf *ibuf_full = IMB_allocImBuf(size[0], size[1], 32, IB_rect); + + IMB_rectcpy( + ibuf_full, ibuf_clip, + clip.xmin - xmin, clip.ymin - ymin, + 0, 0, + size_clip[0], size_clip[1]); + IMB_freeImBuf(ibuf_clip); + return ibuf_full; + } +} + +/* smart function to sample a rect spiralling outside, nice for backbuf selection */ +unsigned int ED_view3d_backbuf_sample_rect( + const EvaluationContext *eval_ctx, ViewContext *vc, const int mval[2], int size, + unsigned int min, unsigned int max, float *r_dist) +{ + int dirvec[4][2]; + + const int amount = (size - 1) / 2; + + const int minx = mval[0] - (amount + 1); + const int miny = mval[1] - (amount + 1); + ImBuf *buf = ED_view3d_backbuf_read(eval_ctx, vc, minx, miny, minx + size - 1, miny + size - 1); + if (!buf) return 0; + + unsigned index = 0; + int rc = 0; + + dirvec[0][0] = 1; dirvec[0][1] = 0; + dirvec[1][0] = 0; dirvec[1][1] = -size; + dirvec[2][0] = -1; dirvec[2][1] = 0; + dirvec[3][0] = 0; dirvec[3][1] = size; + + const unsigned *bufmin = buf->rect; + const unsigned *tbuf = buf->rect; + const unsigned *bufmax = buf->rect + size * size; + tbuf += amount * size + amount; + + for (int nr = 1; nr <= size; nr++) { + for (int a = 0; a < 2; a++) { + for (int b = 0; b < nr; b++) { + if (*tbuf && *tbuf >= min && *tbuf < max) { + /* we got a hit */ + + /* get x,y pixel coords from the offset + * (manhatten distance in keeping with other screen-based selection) */ + *r_dist = (float)( + abs(((int)(tbuf - buf->rect) % size) - (size / 2)) + + abs(((int)(tbuf - buf->rect) / size) - (size / 2))); + + /* indices start at 1 here */ + index = (*tbuf - min) + 1; + goto exit; + } + + tbuf += (dirvec[rc][0] + dirvec[rc][1]); + + if (tbuf < bufmin || tbuf >= bufmax) { + goto exit; + } + } + rc++; + rc &= 3; + } + } + +exit: + IMB_freeImBuf(buf); + return index; +} + + +/* ************************************************************* */ + +static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser) +{ + if (BKE_image_is_stereo(ima)) { + iuser->flag |= IMA_SHOW_STEREO; + + if ((scene->r.scemode & R_MULTIVIEW) == 0) { + iuser->multiview_eye = STEREO_LEFT_ID; + } + else if (v3d->stereo3d_camera != STEREO_3D_ID) { + /* show only left or right camera */ + iuser->multiview_eye = v3d->stereo3d_camera; + } + + BKE_image_multiview_index(ima, iuser); + } + else { + iuser->flag &= ~IMA_SHOW_STEREO; + } +} + +static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, + const bool do_foreground, const bool do_camera_frame) +{ + RegionView3D *rv3d = ar->regiondata; + int fg_flag = do_foreground ? CAM_BGIMG_FLAG_FOREGROUND : 0; + if (v3d->camera == NULL || v3d->camera->type != OB_CAMERA) { + return; + } + Camera *cam = v3d->camera->data; + + for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) { + bgpic->iuser.scene = scene; /* Needed for render results. */ + + if ((bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != fg_flag) + continue; + + { + float image_aspect[2]; + float x1, y1, x2, y2, centx, centy; + + void *lock; + + Image *ima = NULL; + + /* disable individual images */ + if ((bgpic->flag & CAM_BGIMG_FLAG_DISABLED)) + continue; + + ImBuf *ibuf = NULL; + ImBuf *freeibuf = NULL; + ImBuf *releaseibuf = NULL; + if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) { + ima = bgpic->ima; + if (ima == NULL) + continue; + BKE_image_user_frame_calc(&bgpic->iuser, CFRA, 0); + if (ima->source == IMA_SRC_SEQUENCE && !(bgpic->iuser.flag & IMA_USER_FRAME_IN_RANGE)) { + ibuf = NULL; /* frame is out of range, dont show */ + } + else { + view3d_stereo_bgpic_setup(scene, v3d, ima, &bgpic->iuser); + ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, &lock); + releaseibuf = ibuf; + } + + image_aspect[0] = ima->aspx; + image_aspect[1] = ima->aspy; + } + else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) { + /* TODO: skip drawing when out of frame range (as image sequences do above) */ + MovieClip *clip = NULL; + + if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) { + if (scene->camera) + clip = BKE_object_movieclip_get(scene, scene->camera, true); + } + else { + clip = bgpic->clip; + } + + if (clip == NULL) + continue; + + BKE_movieclip_user_set_frame(&bgpic->cuser, CFRA); + ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser); + + image_aspect[0] = clip->aspx; + image_aspect[1] = clip->aspy; + + /* working with ibuf from image and clip has got different workflow now. + * ibuf acquired from clip is referenced by cache system and should + * be dereferenced after usage. */ + freeibuf = ibuf; + } + else { + /* perhaps when loading future files... */ + BLI_assert(0); + copy_v2_fl(image_aspect, 1.0f); + } + + if (ibuf == NULL) + continue; + + if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */ + if (freeibuf) + IMB_freeImBuf(freeibuf); + if (releaseibuf) + BKE_image_release_ibuf(ima, releaseibuf, lock); + + continue; + } + + if (ibuf->rect == NULL) + IMB_rect_from_float(ibuf); + + BLI_assert(rv3d->persp == RV3D_CAMOB); + { + if (do_camera_frame) { + rctf vb; + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false); + x1 = vb.xmin; + y1 = vb.ymin; + x2 = vb.xmax; + y2 = vb.ymax; + } + else { + x1 = ar->winrct.xmin; + y1 = ar->winrct.ymin; + x2 = ar->winrct.xmax; + y2 = ar->winrct.ymax; + } + + /* apply offset last - camera offset is different to offset in blender units */ + /* so this has some sane way of working - this matches camera's shift _exactly_ */ + { + const float max_dim = max_ff(x2 - x1, y2 - y1); + const float xof_scale = bgpic->offset[0] * max_dim; + const float yof_scale = bgpic->offset[1] * max_dim; + + x1 += xof_scale; + y1 += yof_scale; + x2 += xof_scale; + y2 += yof_scale; + } + + centx = (x1 + x2) * 0.5f; + centy = (y1 + y2) * 0.5f; + + /* aspect correction */ + if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_ASPECT) { + /* apply aspect from clip */ + const float w_src = ibuf->x * image_aspect[0]; + const float h_src = ibuf->y * image_aspect[1]; + + /* destination aspect is already applied from the camera frame */ + const float w_dst = x1 - x2; + const float h_dst = y1 - y2; + + const float asp_src = w_src / h_src; + const float asp_dst = w_dst / h_dst; + + if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) { + if ((asp_src > asp_dst) == ((bgpic->flag & CAM_BGIMG_FLAG_CAMERA_CROP) != 0)) { + /* fit X */ + const float div = asp_src / asp_dst; + x1 = ((x1 - centx) * div) + centx; + x2 = ((x2 - centx) * div) + centx; + } + else { + /* fit Y */ + const float div = asp_dst / asp_src; + y1 = ((y1 - centy) * div) + centy; + y2 = ((y2 - centy) * div) + centy; + } + } + } + } + + /* complete clip? */ + rctf clip_rect; + BLI_rctf_init(&clip_rect, x1, x2, y1, y2); + if (bgpic->rotation) { + BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation); + } + + if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) { + if (freeibuf) + IMB_freeImBuf(freeibuf); + if (releaseibuf) + BKE_image_release_ibuf(ima, releaseibuf, lock); + + continue; + } + + float zoomx = (x2 - x1) / ibuf->x; + float zoomy = (y2 - y1) / ibuf->y; + + /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */ + if (zoomx < 1.0f || zoomy < 1.0f) { + float tzoom = min_ff(zoomx, zoomy); + int mip = 0; + + if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) { + IMB_remakemipmap(ibuf, 0); + ibuf->userflags &= ~IB_MIPMAP_INVALID; + } + else if (ibuf->mipmap[0] == NULL) + IMB_makemipmap(ibuf, 0); + + while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) { + tzoom *= 2.0f; + zoomx *= 2.0f; + zoomy *= 2.0f; + mip++; + } + if (mip > 0) + ibuf = ibuf->mipmap[mip - 1]; + } + + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + gpuPushProjectionMatrix(); + gpuPushMatrix(); + ED_region_pixelspace(ar); + + gpuTranslate2f(centx, centy); + gpuScaleUniform(bgpic->scale); + gpuRotate2D(RAD2DEGF(-bgpic->rotation)); + + if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) { + zoomx *= -1.0f; + x1 = x2; + } + if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) { + zoomy *= -1.0f; + y1 = y2; + } + + float col[4] = {1.0f, 1.0f, 1.0f, bgpic->alpha}; + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect, + zoomx, zoomy, col); + + gpuPopProjectionMatrix(); + gpuPopMatrix(); + + glDisable(GL_BLEND); + + glDepthMask(GL_TRUE); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + + if (freeibuf) + IMB_freeImBuf(freeibuf); + if (releaseibuf) + BKE_image_release_ibuf(ima, releaseibuf, lock); + } + } +} + +void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d, + const bool do_foreground, const bool do_camera_frame) +{ + RegionView3D *rv3d = ar->regiondata; + + if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) { + Camera *cam = v3d->camera->data; + if ((cam->flag & CAM_SHOW_BG_IMAGE) == 0) { + return; + } + } + else { + return; + } + + /* disabled - mango request, since footage /w only render is quite useful + * and this option is easy to disable all background images at once */ +#if 0 + if (v3d->flag2 & V3D_RENDER_OVERRIDE) + return; +#endif + + if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) { + if (rv3d->persp == RV3D_CAMOB) { + view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame); + } + } + else { + view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame); + } +} + +/* ****************** View3d afterdraw *************** */ + +typedef struct View3DAfter { + struct View3DAfter *next, *prev; + struct Base *base; + short dflag; +} View3DAfter; + +/* temp storage of Objects that need to be drawn as last */ +void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag) +{ + View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after"); + BLI_assert((base->flag_legacy & OB_FROMDUPLI) == 0); + BLI_addtail(lb, v3da); + v3da->base = base; + v3da->dflag = dflag; +} + +/* disables write in zbuffer and draws it over */ +static void view3d_draw_transp( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d) +{ + View3DAfter *v3da; + + glDepthMask(GL_FALSE); + v3d->transp = true; + + while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, v3da->dflag); + MEM_freeN(v3da); + } + v3d->transp = false; + + glDepthMask(GL_TRUE); + +} + +/* clears zbuffer and draws it over */ +static void view3d_draw_xray( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, bool *clear) +{ + if (*clear && v3d->zbuf) { + glClear(GL_DEPTH_BUFFER_BIT); + *clear = false; + } + + v3d->xray = true; + View3DAfter *v3da; + while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, v3da->dflag); + MEM_freeN(v3da); + } + v3d->xray = false; +} + + +/* clears zbuffer and draws it over */ +static void view3d_draw_xraytransp( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, const bool clear) +{ + if (clear && v3d->zbuf) + glClear(GL_DEPTH_BUFFER_BIT); + + v3d->xray = true; + v3d->transp = true; + + glDepthMask(GL_FALSE); + + View3DAfter *v3da; + while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, v3da->dflag); + MEM_freeN(v3da); + } + + v3d->transp = false; + v3d->xray = false; + + glDepthMask(GL_TRUE); +} + +/* clears zbuffer and draws it over, + * note that in the select version we don't care about transparent flag as with regular drawing */ +static void view3d_draw_xray_select( + const struct EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, bool *clear) +{ + /* Not ideal, but we need to read from the previous depths before clearing + * otherwise we could have a function to load the depths after drawing. + * + * Clearing the depth buffer isn't all that common between drawing objects so accept this for now. + */ + if (U.gpu_select_pick_deph) { + GPU_select_load_id(-1); + } + + View3DAfter *v3da; + if (*clear && v3d->zbuf) { + glClear(GL_DEPTH_BUFFER_BIT); + *clear = false; + } + + v3d->xray = true; + while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { + if (GPU_select_load_id(v3da->base->object->select_color)) { + draw_object_select(eval_ctx, scene, sl, ar, v3d, v3da->base, v3da->dflag); + } + MEM_freeN(v3da); + } + v3d->xray = false; +} + +/* *********************** */ + +/* + * In most cases call draw_dupli_objects, + * draw_dupli_objects_color was added because when drawing set dupli's + * we need to force the color + */ + +#if 0 +int dupli_ob_sort(void *arg1, void *arg2) +{ + void *p1 = ((DupliObject *)arg1)->ob; + void *p2 = ((DupliObject *)arg2)->ob; + int val = 0; + if (p1 < p2) val = -1; + else if (p1 > p2) val = 1; + return val; +} +#endif + + +static DupliObject *dupli_step(DupliObject *dob) +{ + while (dob && dob->no_draw) + dob = dob->next; + return dob; +} + +static void draw_dupli_objects_color( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *base, + const short dflag, const int color) +{ + RegionView3D *rv3d = ar->regiondata; + ListBase *lb; + LodLevel *savedlod; + Base tbase = {NULL}; + BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */ + unsigned char color_rgb[3]; + const short dflag_dupli = dflag | DRAW_CONSTCOLOR; + short transflag; + char dt; + short dtx; + DupliApplyData *apply_data; + + if ((base->flag & BASE_VISIBLED) == 0) return; + if ((base->object->restrictflag & OB_RESTRICT_RENDER) && (v3d->flag2 & V3D_RENDER_OVERRIDE)) return; + + if (dflag & DRAW_CONSTCOLOR) { + BLI_assert(color == TH_UNDEFINED); + } + else { + UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb); + } + + tbase.flag_legacy = OB_FROMDUPLI | base->flag_legacy; + tbase.flag = base->flag; + lb = object_duplilist(eval_ctx, scene, base->object); + // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */ + + apply_data = duplilist_apply(eval_ctx, base->object, scene, lb); + + DupliObject *dob_next = NULL; + DupliObject *dob = dupli_step(lb->first); + if (dob) dob_next = dupli_step(dob->next); + + for (; dob; dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) { + bool testbb = false; + + tbase.object = dob->ob; + + /* Make sure lod is updated from dupli's position */ + savedlod = dob->ob->currentlod; + +#ifdef WITH_GAMEENGINE + if (rv3d->rflag & RV3D_IS_GAME_ENGINE) { + BKE_object_lod_update(dob->ob, rv3d->viewinv[3]); + } +#endif + + /* extra service: draw the duplicator in drawtype of parent, minimum taken + * to allow e.g. boundbox box objects in groups for LOD */ + dt = tbase.object->dt; + tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); + + /* inherit draw extra, but not if a boundbox under the assumption that this + * is intended to speed up drawing, and drawing extra (especially wire) can + * slow it down too much */ + dtx = tbase.object->dtx; + if (tbase.object->dt != OB_BOUNDBOX) + tbase.object->dtx = base->object->dtx; + + /* negative scale flag has to propagate */ + transflag = tbase.object->transflag; + + if (is_negative_m4(dob->mat)) + tbase.object->transflag |= OB_NEG_SCALE; + else + tbase.object->transflag &= ~OB_NEG_SCALE; + + /* should move outside the loop but possible color is set in draw_object still */ + if ((dflag & DRAW_CONSTCOLOR) == 0) { + glColor3ubv(color_rgb); + } + + if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) { + bb = *bb_tmp; /* must make a copy */ + testbb = true; + } + + if (!testbb || ED_view3d_boundbox_clip_ex(rv3d, &bb, dob->mat)) { + copy_m4_m4(dob->ob->obmat, dob->mat); + GPU_begin_dupli_object(dob); + draw_object(eval_ctx, scene, sl, ar, v3d, &tbase, dflag_dupli); + GPU_end_dupli_object(); + } + + tbase.object->dt = dt; + tbase.object->dtx = dtx; + tbase.object->transflag = transflag; + tbase.object->currentlod = savedlod; + } + + if (apply_data) { + duplilist_restore(lb, apply_data); + duplilist_free_apply_data(apply_data); + } + + free_object_duplilist(lb); +} + +void draw_dupli_objects(const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *base) +{ + /* define the color here so draw_dupli_objects_color can be called + * from the set loop */ + + int color = (base->flag & BASE_SELECTED) ? TH_SELECT : TH_WIRE; + /* debug */ + if (base->object->dup_group && base->object->dup_group->id.us < 1) + color = TH_REDALERT; + + draw_dupli_objects_color(eval_ctx, scene, sl, ar, v3d, base, 0, color); +} + +/* XXX warning, not using gpu offscreen here */ +void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) +{ + /* clamp rect by region */ + rcti r = { + .xmin = 0, + .xmax = ar->winx - 1, + .ymin = 0, + .ymax = ar->winy - 1 + }; + + /* Constrain rect to depth bounds */ + BLI_rcti_isect(&r, rect, rect); + + /* assign values to compare with the ViewDepths */ + int x = rect->xmin; + int y = rect->ymin; + + int w = BLI_rcti_size_x(rect); + int h = BLI_rcti_size_y(rect); + + if (w <= 0 || h <= 0) { + if (d->depths) + MEM_freeN(d->depths); + d->depths = NULL; + + d->damaged = false; + } + else if (d->w != w || + d->h != h || + d->x != x || + d->y != y || + d->depths == NULL + ) + { + d->x = x; + d->y = y; + d->w = w; + d->h = h; + + if (d->depths) + MEM_freeN(d->depths); + + d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset"); + + d->damaged = true; + } + + if (d->damaged) { + /* XXX using special function here, it doesn't use the gpu offscreen system */ + view3d_opengl_read_Z_pixels(ar, d->x, d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); + glGetDoublev(GL_DEPTH_RANGE, d->depth_range); + d->damaged = false; + } +} + +/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */ +void ED_view3d_depth_update(ARegion *ar) +{ + RegionView3D *rv3d = ar->regiondata; + + /* Create storage for, and, if necessary, copy depth buffer */ + if (!rv3d->depths) rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); + if (rv3d->depths) { + ViewDepths *d = rv3d->depths; + if (d->w != ar->winx || + d->h != ar->winy || + !d->depths) + { + d->w = ar->winx; + d->h = ar->winy; + if (d->depths) + MEM_freeN(d->depths); + d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); + d->damaged = true; + } + + if (d->damaged) { + view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); + glGetDoublev(GL_DEPTH_RANGE, d->depth_range); + + d->damaged = false; + } + } +} + +/* utility function to find the closest Z value, use for autodepth */ +float view3d_depth_near(ViewDepths *d) +{ + /* convert to float for comparisons */ + const float near = (float)d->depth_range[0]; + const float far_real = (float)d->depth_range[1]; + float far = far_real; + + const float *depths = d->depths; + float depth = FLT_MAX; + int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */ + + /* far is both the starting 'far' value + * and the closest value found. */ + while (i--) { + depth = *depths++; + if ((depth < far) && (depth > near)) { + far = depth; + } + } + + return far == far_real ? FLT_MAX : far; +} + +void ED_view3d_draw_depth_gpencil( + const EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d) +{ + bool zbuf = v3d->zbuf; + + /* Setup view matrix. */ + ED_view3d_draw_setup_view(NULL, eval_ctx, scene, ar, v3d, NULL, NULL, NULL); + + glClear(GL_DEPTH_BUFFER_BIT); + + v3d->zbuf = true; + glEnable(GL_DEPTH_TEST); + + if (v3d->flag2 & V3D_SHOW_GPENCIL) { + ED_gpencil_draw_view3d(NULL, scene, eval_ctx->scene_layer, v3d, ar, true); + } + + v3d->zbuf = zbuf; + if (!zbuf) glDisable(GL_DEPTH_TEST); +} + +void ED_view3d_draw_depth_loop(const EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d) +{ + Base *base; + SceneLayer *sl = eval_ctx->scene_layer; + /* no need for color when drawing depth buffer */ + const short dflag_depth = DRAW_CONSTCOLOR; + + /* draw set first */ + if (scene->set) { + Scene *sce_iter; + for (SETLOOPER(scene->set, sce_iter, base)) { + if ((base->flag & BASE_VISIBLED) != 0) { + draw_object(eval_ctx, scene, sl, ar, v3d, base, 0); + if (base->object->transflag & OB_DUPLI) { + draw_dupli_objects_color(eval_ctx, scene, sl, ar, v3d, base, dflag_depth, TH_UNDEFINED); + } + } + } + } + + for (base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { + /* dupli drawing */ + if (base->object->transflag & OB_DUPLI) { + draw_dupli_objects_color(eval_ctx, scene, sl, ar, v3d, base, dflag_depth, TH_UNDEFINED); + } + draw_object(eval_ctx, scene, sl, ar, v3d, base, dflag_depth); + } + } + + /* this isn't that nice, draw xray objects as if they are normal */ + if (v3d->afterdraw_transp.first || + v3d->afterdraw_xray.first || + v3d->afterdraw_xraytransp.first) + { + View3DAfter *v3da; + int mask_orig; + + v3d->xray = true; + + /* transp materials can change the depth mask, see #21388 */ + glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig); + + + if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) { + glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */ + for (v3da = v3d->afterdraw_xray.first; v3da; v3da = v3da->next) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, dflag_depth); + } + glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */ + } + + /* draw 3 passes, transp/xray/xraytransp */ + v3d->xray = false; + v3d->transp = true; + while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, dflag_depth); + MEM_freeN(v3da); + } + + v3d->xray = true; + v3d->transp = false; + while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, dflag_depth); + MEM_freeN(v3da); + } + + v3d->xray = true; + v3d->transp = true; + while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, dflag_depth); + MEM_freeN(v3da); + } + + + v3d->xray = false; + v3d->transp = false; + + glDepthMask(mask_orig); + } +} + +void ED_view3d_draw_select_loop( + const struct EvaluationContext *eval_ctx, ViewContext *vc, Scene *scene, SceneLayer *sl, + View3D *v3d, ARegion *ar, bool use_obedit_skip, bool use_nearest) +{ + struct bThemeState theme_state; + + short code = 1; + const short dflag = DRAW_PICKING | DRAW_CONSTCOLOR; + + /* Tools may request depth outside of regular drawing code. */ + UI_Theme_Store(&theme_state); + UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); + + if (vc->obedit && vc->obedit->type == OB_MBALL) { + draw_object(eval_ctx, scene, sl, ar, v3d, BASACT(sl), dflag); + } + else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) { + /* if not drawing sketch, draw bones */ + if (!BDR_drawSketchNames(vc)) { + draw_object(eval_ctx, scene, sl, ar, v3d, BASACT(sl), dflag); + } + } + else { + Base *base; + + for (base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { + if (((base->flag & BASE_SELECTABLED) == 0) || + (use_obedit_skip && (scene->obedit->data == base->object->data))) + { + base->object->select_color = 0; + } + else { + base->object->select_color = code; + + if (use_nearest && (base->object->dtx & OB_DRAWXRAY)) { + ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag); + } + else { + if (GPU_select_load_id(code)) { + draw_object(eval_ctx, scene, sl, ar, v3d, base, dflag); + } + } + code++; + } + } + } + + if (use_nearest) { + bool xrayclear = true; + if (v3d->afterdraw_xray.first) { + view3d_draw_xray_select(eval_ctx, scene, sl, ar, v3d, &xrayclear); + } + } + } + + UI_Theme_Restore(&theme_state); +} + +typedef struct View3DShadow { + struct View3DShadow *next, *prev; + GPULamp *lamp; +} View3DShadow; + +static void gpu_render_lamp_update(Scene *scene, View3D *v3d, + Object *ob, Object *par, + float obmat[4][4], unsigned int lay, + ListBase *shadows) +{ + GPULamp *lamp = GPU_lamp_from_blender(scene, ob, par); + + if (lamp) { + Lamp *la = (Lamp *)ob->data; + + GPU_lamp_update(lamp, lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat); + GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy); + + unsigned int layers = lay & v3d->lay; + + if (layers && + GPU_lamp_has_shadow_buffer(lamp) && + /* keep last, may do string lookup */ + GPU_lamp_visible(lamp, NULL)) + { + View3DShadow *shadow = MEM_callocN(sizeof(View3DShadow), "View3DShadow"); + shadow->lamp = lamp; + BLI_addtail(shadows, shadow); + } + } +} + +static void gpu_update_lamps_shadows_world(const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d) +{ + ListBase shadows; + Scene *sce_iter; + Base *base; + World *world = scene->world; + + BLI_listbase_clear(&shadows); + + /* update lamp transform and gather shadow lamps */ + for (SETLOOPER(scene, sce_iter, base)) { + Object *ob = base->object; + + if (ob->type == OB_LAMP) + gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, ob->lay, &shadows); + + if (ob->transflag & OB_DUPLI) { + DupliObject *dob; + ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob); + + for (dob = lb->first; dob; dob = dob->next) + if (dob->ob->type == OB_LAMP) + gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, ob->lay, &shadows); + + free_object_duplilist(lb); + } + } + + /* render shadows after updating all lamps, nested object_duplilist + * don't work correct since it's replacing object matrices */ + for (View3DShadow *shadow = shadows.first; shadow; shadow = shadow->next) { + /* this needs to be done better .. */ + float viewmat[4][4], winmat[4][4]; + ARegion ar = {NULL}; + RegionView3D rv3d = {{{0}}}; + + int drawtype = v3d->drawtype; + int lay = v3d->lay; + int flag2 = v3d->flag2; + + v3d->drawtype = OB_SOLID; + v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp); + v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP); + v3d->flag2 |= V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW; + + int winsize; + GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat); + + ar.regiondata = &rv3d; + ar.regiontype = RGN_TYPE_WINDOW; + rv3d.persp = RV3D_CAMOB; + copy_m4_m4(rv3d.winmat, winmat); + copy_m4_m4(rv3d.viewmat, viewmat); + invert_m4_m4(rv3d.viewinv, rv3d.viewmat); + mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat); + invert_m4_m4(rv3d.persinv, rv3d.viewinv); + + /* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */ + ED_view3d_draw_offscreen( + eval_ctx, scene, eval_ctx->scene_layer, v3d, &ar, winsize, winsize, viewmat, winmat, + false, false, true, + NULL, NULL, NULL, NULL); + GPU_lamp_shadow_buffer_unbind(shadow->lamp); + + v3d->drawtype = drawtype; + v3d->lay = lay; + v3d->flag2 = flag2; + } + + BLI_freelistN(&shadows); + + /* update world values */ + if (world) { + GPU_mist_update_enable(world->mode & WO_MIST); + GPU_mist_update_values(world->mistype, world->miststa, world->mistdist, world->misi, &world->horr); + GPU_horizon_update_color(&world->horr); + GPU_ambient_update_color(&world->ambr); + GPU_zenith_update_color(&world->zenr); + } +} + +/* *********************** customdata **************** */ + +CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d) +{ + CustomDataMask mask = 0; + const int drawtype = view3d_effective_drawtype(v3d); + + if (ELEM(drawtype, OB_TEXTURE, OB_MATERIAL) || + ((drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX))) + { + mask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; + + if (BKE_scene_use_new_shading_nodes(scene)) { + if (drawtype == OB_MATERIAL) + mask |= CD_MASK_ORCO; + } + else { + if ((scene->gm.matmode == GAME_MAT_GLSL && drawtype == OB_TEXTURE) || + (drawtype == OB_MATERIAL)) + { + mask |= CD_MASK_ORCO; + } + } + } + + return mask; +} + +/* goes over all modes and view3d settings */ +CustomDataMask ED_view3d_screen_datamask(const Scene *scene, const bScreen *screen) +{ + CustomDataMask mask = CD_MASK_BAREMESH; + + /* check if we need tfaces & mcols due to view mode */ + for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_VIEW3D) { + mask |= ED_view3d_datamask(scene, sa->spacedata.first); + } + } + + return mask; +} + +/** + * Shared by #ED_view3d_draw_offscreen and #view3d_main_region_draw_objects + * + * \note \a C and \a grid_unit will be NULL when \a draw_offscreen is set. + * \note Drawing lamps and opengl render uses this, so dont do grease pencil or view widgets here. + */ +static void view3d_draw_objects( + const bContext *C, + const EvaluationContext *eval_ctx, + Scene *scene, View3D *v3d, ARegion *ar, + const char **grid_unit, + const bool do_bgpic, const bool draw_offscreen, GPUFX *fx) +{ + SceneLayer *scene_layer = C ? CTX_data_scene_layer(C) : BKE_scene_layer_from_scene_get(scene); + RegionView3D *rv3d = ar->regiondata; + Base *base; + const bool do_camera_frame = !draw_offscreen; + const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0; + const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO); + /* only draw grids after in solid modes, else it hovers over mesh wires */ + const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx; + bool do_composite_xray = false; + bool xrayclear = true; + + if (!draw_offscreen) { + ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); + } + + if (rv3d->rflag & RV3D_CLIPPING) + view3d_draw_clipping(rv3d); + + /* set zbuffer after we draw clipping region */ + v3d->zbuf = VP_legacy_use_depth(scene, v3d); + + if (v3d->zbuf) { + glEnable(GL_DEPTH_TEST); + } + + /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override + * objects if done last */ + if (draw_grids) { + /* needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views. */ + rv3d->gridview = ED_view3d_grid_scale(scene, v3d, grid_unit); + + if (!draw_floor) { + ED_region_pixelspace(ar); + *grid_unit = NULL; /* drawgrid need this to detect/affect smallest valid unit... */ + VP_legacy_drawgrid(&scene->unit, ar, v3d, grid_unit); + gpuLoadProjectionMatrix(rv3d->winmat); + gpuLoadMatrix(rv3d->viewmat); + } + else if (!draw_grids_after) { + VP_legacy_drawfloor(scene, v3d, grid_unit, true); + } + } + + /* important to do before clipping */ + if (do_bgpic) { + view3d_draw_bgpic_test(scene, ar, v3d, false, do_camera_frame); + } + + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_set(rv3d); + } + + /* draw set first */ + if (scene->set) { + const short dflag = DRAW_CONSTCOLOR | DRAW_SCENESET; + Scene *sce_iter; + for (SETLOOPER(scene->set, sce_iter, base)) { + if ((base->flag & BASE_VISIBLED) != 0) { + UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f); + draw_object(eval_ctx, scene, scene_layer, ar, v3d, base, dflag); + + if (base->object->transflag & OB_DUPLI) { + draw_dupli_objects_color(eval_ctx, scene, scene_layer, ar, v3d, base, dflag, TH_UNDEFINED); + } + } + } + + /* Transp and X-ray afterdraw stuff for sets is done later */ + } + + if (draw_offscreen) { + for (base = scene_layer->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { + /* dupli drawing */ + if (base->object->transflag & OB_DUPLI) { + draw_dupli_objects(eval_ctx, scene, scene_layer, ar, v3d, base); + } + + draw_object(eval_ctx, scene, scene_layer, ar, v3d, base, 0); + } + } + } + else { + unsigned int lay_used = 0; + + /* then draw not selected and the duplis, but skip editmode object */ + for (base = scene_layer->object_bases.first; base; base = base->next) { + lay_used |= base->lay; + + if ((base->flag & BASE_VISIBLED) != 0) { + + /* dupli drawing */ + if (base->object->transflag & OB_DUPLI) { + draw_dupli_objects(eval_ctx, scene, scene_layer, ar, v3d, base); + } + if ((base->flag & BASE_SELECTED) == 0) { + if (base->object != scene->obedit) + draw_object(eval_ctx, scene, scene_layer, ar, v3d, base, 0); + } + } + } + + /* mask out localview */ + v3d->lay_used = lay_used & ((1 << 20) - 1); + + /* draw selected and editmode */ + for (base = scene_layer->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { + if (base->object == scene->obedit || (base->flag & BASE_SELECTED)) { + draw_object(eval_ctx, scene, scene_layer, ar, v3d, base, 0); + } + } + } + } + + /* perspective floor goes last to use scene depth and avoid writing to depth buffer */ + if (draw_grids_after) { + VP_legacy_drawfloor(scene, v3d, grid_unit, false); + } + + /* must be before xray draw which clears the depth buffer */ + if (v3d->flag2 & V3D_SHOW_GPENCIL) { + wmWindowManager *wm = (C != NULL) ? CTX_wm_manager(C) : NULL; + + /* must be before xray draw which clears the depth buffer */ + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); + ED_gpencil_draw_view3d(wm, scene, scene_layer, v3d, ar, true); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + } + + /* transp and X-ray afterdraw stuff */ + if (v3d->afterdraw_transp.first) view3d_draw_transp(eval_ctx, scene, scene_layer, ar, v3d); + + /* always do that here to cleanup depth buffers if none needed */ + if (fx) { + do_composite_xray = v3d->zbuf && (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first); + GPU_fx_compositor_setup_XRay_pass(fx, do_composite_xray); + } + + if (v3d->afterdraw_xray.first) view3d_draw_xray(eval_ctx, scene, scene_layer, ar, v3d, &xrayclear); + if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(eval_ctx, scene, scene_layer, ar, v3d, xrayclear); + + if (fx && do_composite_xray) { + GPU_fx_compositor_XRay_resolve(fx); + } + + if (!draw_offscreen) { + ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); + } + + if (rv3d->rflag & RV3D_CLIPPING) + ED_view3d_clipping_disable(); + + /* important to do after clipping */ + if (do_bgpic) { + view3d_draw_bgpic_test(scene, ar, v3d, true, do_camera_frame); + } + + /* cleanup */ + if (v3d->zbuf) { + v3d->zbuf = false; + glDisable(GL_DEPTH_TEST); + } + + if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + GPU_free_images_old(); + } +} + +/** + * Store values from #RegionView3D, set when drawing. + * This is needed when we draw with to a viewport using a different matrix (offscreen drawing for example). + * + * Values set by #ED_view3d_update_viewmat should be handled here. + */ +struct RV3DMatrixStore { + float winmat[4][4]; + float viewmat[4][4]; + float viewinv[4][4]; + float persmat[4][4]; + float persinv[4][4]; + float viewcamtexcofac[4]; + float pixsize; +}; + +struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d) +{ + struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__); + copy_m4_m4(rv3dmat->winmat, rv3d->winmat); + copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat); + copy_m4_m4(rv3dmat->persmat, rv3d->persmat); + copy_m4_m4(rv3dmat->persinv, rv3d->persinv); + copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv); + copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac); + rv3dmat->pixsize = rv3d->pixsize; + return (void *)rv3dmat; +} + +void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat_pt) +{ + struct RV3DMatrixStore *rv3dmat = rv3dmat_pt; + copy_m4_m4(rv3d->winmat, rv3dmat->winmat); + copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat); + copy_m4_m4(rv3d->persmat, rv3dmat->persmat); + copy_m4_m4(rv3d->persinv, rv3dmat->persinv); + copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv); + copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac); + rv3d->pixsize = rv3dmat->pixsize; +} + +/** + * \note The info that this uses is updated in #ED_refresh_viewport_fps, + * which currently gets called during #SCREEN_OT_animation_step. + */ +void ED_scene_draw_fps(Scene *scene, const rcti *rect) +{ + ScreenFrameRateInfo *fpsi = scene->fps_info; + char printable[16]; + + if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) + return; + + printable[0] = '\0'; + +#if 0 + /* this is too simple, better do an average */ + fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime)) +#else + fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime)); + + float fps = 0.0f; + int tot = 0; + for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) { + if (fpsi->redrawtimes_fps[i]) { + fps += fpsi->redrawtimes_fps[i]; + tot++; + } + } + if (tot) { + fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE; + + //fpsi->redrawtime_index++; + //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE) + // fpsi->redrawtime = 0; + + fps = fps / tot; + } +#endif + + const int font_id = BLF_default(); + + /* is this more than half a frame behind? */ + if (fps + 0.5f < (float)(FPS)) { + UI_FontThemeColor(font_id, TH_REDALERT); + BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps); + } + else { + UI_FontThemeColor(font_id, TH_TEXT_HI); + BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f)); + } + +#ifdef WITH_INTERNATIONAL + BLF_draw_default(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable)); +#else + BLF_draw_default_ascii(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable)); +#endif +} + +static bool view3d_main_region_do_render_draw(const Scene *scene) +{ + RenderEngineType *type = RE_engines_find(scene->view_render.engine_id); + return (type && type->view_update && type->render_to_view); +} + +bool ED_view3d_calc_render_border(const Scene *scene, View3D *v3d, ARegion *ar, rcti *rect) +{ + RegionView3D *rv3d = ar->regiondata; + bool use_border; + + /* test if there is a 3d view rendering */ + if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene)) + return false; + + /* test if there is a border render */ + if (rv3d->persp == RV3D_CAMOB) + use_border = (scene->r.mode & R_BORDER) != 0; + else + use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0; + + if (!use_border) + return false; + + /* compute border */ + if (rv3d->persp == RV3D_CAMOB) { + rctf viewborder; + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false); + + rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); + rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); + rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); + rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); + } + else { + rect->xmin = v3d->render_border.xmin * ar->winx; + rect->xmax = v3d->render_border.xmax * ar->winx; + rect->ymin = v3d->render_border.ymin * ar->winy; + rect->ymax = v3d->render_border.ymax * ar->winy; + } + + BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin); + BLI_rcti_isect(&ar->winrct, rect, rect); + + return true; +} + +/** + * IMPORTANT: this is deprecated, any changes made in this function should + * be mirrored in view3d_draw_render_draw() in view3d_draw.c + */ +static bool view3d_main_region_draw_engine( + const bContext *C, const EvaluationContext *eval_ctx, Scene *scene, + ARegion *ar, View3D *v3d, + bool clip_border, const rcti *border_rect) +{ + RegionView3D *rv3d = ar->regiondata; + RenderEngineType *type; + GLint scissor[4]; + + + /* create render engine */ + if (!rv3d->render_engine) { + RenderEngine *engine; + type = RE_engines_find(scene->view_render.engine_id); + + if (!(type->view_update && type->render_to_view)) + return false; + + engine = RE_engine_create_ex(type, true); + + engine->tile_x = scene->r.tilex; + engine->tile_y = scene->r.tiley; + + type->view_update(engine, C); + + rv3d->render_engine = engine; + } + + /* setup view matrices */ + VP_legacy_view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, NULL, NULL); + + /* background draw */ + ED_region_pixelspace(ar); + + if (clip_border) { + /* for border draw, we only need to clear a subset of the 3d view */ + if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) { + glGetIntegerv(GL_SCISSOR_BOX, scissor); + glScissor(border_rect->xmin, border_rect->ymin, + BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect)); + } + else { + return false; + } + } + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + bool show_image = false; + { + Camera *cam = ED_view3d_camera_data_get(v3d, rv3d); + if (cam->flag & CAM_SHOW_BG_IMAGE) { + show_image = true; + view3d_draw_bgpic_test(scene, ar, v3d, false, true); + } + else { + imm_draw_box_checker_2d(0, 0, ar->winx, ar->winy); + } + } + + if (show_image) { + view3d_draw_bgpic_test(scene, ar, v3d, false, true); + } + else { + imm_draw_box_checker_2d(0, 0, ar->winx, ar->winy); + } + + /* render result draw */ + type = rv3d->render_engine->type; + type->render_to_view(rv3d->render_engine, C); + + if (show_image) { + view3d_draw_bgpic_test(scene, ar, v3d, true, true); + } + + if (clip_border) { + /* restore scissor as it was before */ + glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); + } + + return true; +} + +static void view3d_main_region_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ARegion *ar, bool render_border) +{ + float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f}; + + if (!rv3d->render_engine || !rv3d->render_engine->text[0]) + return; + + if (render_border) { + /* draw darkened background color. no alpha because border render does + * partial redraw and will not redraw the region behind this info bar */ + float alpha = 1.0f - fill_color[3]; + Camera *camera = ED_view3d_camera_data_get(v3d, rv3d); + + if (camera) { + if (camera->flag & CAM_SHOWPASSEPARTOUT) { + alpha *= (1.0f - camera->passepartalpha); + } + } + + UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color); + mul_v3_fl(fill_color, alpha); + fill_color[3] = 1.0f; + } + + ED_region_info_draw(ar, rv3d->render_engine->text, fill_color, true); +} + +#ifdef WITH_GAMEENGINE +static void update_lods(Scene *scene, float camera_pos[3]) +{ + Scene *sce_iter; + Base *base; + + for (SETLOOPER(scene, sce_iter, base)) { + Object *ob = base->object; + BKE_object_lod_update(ob, camera_pos); + } +} +#endif + +static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, SceneLayer *sl, View3D *v3d, + ARegion *ar, const char **grid_unit) +{ + wmWindow *win = CTX_wm_window(C); + EvaluationContext eval_ctx; + RegionView3D *rv3d = ar->regiondata; + unsigned int lay_used = v3d->lay_used; + + CTX_data_eval_ctx(C, &eval_ctx); + + /* post processing */ + bool do_compositing = false; + + /* shadow buffers, before we setup matrices */ + if (draw_glsl_material(scene, sl, NULL, v3d, v3d->drawtype)) + gpu_update_lamps_shadows_world(&eval_ctx, scene, v3d); + + /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */ + if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) { + rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE; + GPU_default_lights(); + } + + /* setup the view matrix */ + if (VP_legacy_view3d_stereo3d_active(win, scene, v3d, rv3d)) { + VP_legacy_view3d_stereo3d_setup(&eval_ctx, scene, v3d, ar); + } + else { + VP_legacy_view3d_main_region_setup_view(&eval_ctx, scene, v3d, ar, NULL, NULL); + } + + rv3d->rflag &= ~RV3D_IS_GAME_ENGINE; +#ifdef WITH_GAMEENGINE + if (STREQ(scene->view_render.engine_id, RE_engine_id_BLENDER_GAME)) { + rv3d->rflag |= RV3D_IS_GAME_ENGINE; + + /* Make sure LoDs are up to date */ + update_lods(scene, rv3d->viewinv[3]); + } +#endif + + /* framebuffer fx needed, we need to draw offscreen first */ + if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) { + BKE_screen_gpu_fx_validate(&v3d->fx_settings); + GPUFXSettings fx_settings = v3d->fx_settings; + if (!rv3d->compositor) + rv3d->compositor = GPU_fx_compositor_create(); + + if (rv3d->persp == RV3D_CAMOB && v3d->camera) + BKE_camera_to_gpu_dof(v3d->camera, &fx_settings); + else { + fx_settings.dof = NULL; + } + + do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings); + } + + /* enables anti-aliasing for 3D view drawing */ + if (win->multisamples != USER_MULTISAMPLE_NONE) { + glEnable(GL_MULTISAMPLE); + } + + /* main drawing call */ + view3d_draw_objects(C, &eval_ctx, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL); + + /* draw depth culled manipulators - manipulators need to be updated *after* view matrix was set up */ + /* TODO depth culling manipulators is not yet supported, just drawing _3D here, should + * later become _IN_SCENE (and draw _3D separate) */ + WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_3D); + + /* post process */ + if (do_compositing) { + GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL); + } + + /* Disable back anti-aliasing */ + if (win->multisamples != USER_MULTISAMPLE_NONE) { + glDisable(GL_MULTISAMPLE); + } + + if (v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */ + /* find header and force tag redraw */ + ScrArea *sa = CTX_wm_area(C); + ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER); + ED_region_tag_redraw(ar_header); /* can be NULL */ + } + + if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + BDR_drawSketch(C); + } +} + +static void view3d_main_region_draw_info(const bContext *C, Scene *scene, + ARegion *ar, View3D *v3d, + const char *grid_unit, bool render_border) +{ + SceneLayer *scene_layer = CTX_data_scene_layer(C); + wmWindowManager *wm = CTX_wm_manager(C); + RegionView3D *rv3d = ar->regiondata; + rcti rect; + + /* local coordinate visible rect inside region, to accomodate overlapping ui */ + ED_region_visible_rect(ar, &rect); + + if (rv3d->persp == RV3D_CAMOB) { + VP_drawviewborder(scene, ar, v3d); + } + else if (v3d->flag2 & V3D_RENDER_BORDER) { + VP_drawrenderborder(ar, v3d); + } + + if (v3d->flag2 & V3D_SHOW_GPENCIL) { + /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */ + ED_gpencil_draw_view3d(wm, scene, scene_layer, v3d, ar, false); + } + + if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + VP_legacy_drawcursor(scene, scene_layer, ar, v3d); /* 3D cursor */ + + if (U.uiflag & USER_SHOW_ROTVIEWICON) + VP_legacy_draw_view_axis(rv3d, &rect); + else + draw_view_icon(rv3d, &rect); + + if (U.uiflag & USER_DRAWVIEWINFO) { + Object *ob = OBACT(scene_layer); + VP_legacy_draw_selected_name(scene, ob, &rect); + } + } + + if (rv3d->render_engine) { + view3d_main_region_draw_engine_info(v3d, rv3d, ar, render_border); + return; + } + + if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) { + ED_scene_draw_fps(scene, &rect); + } + else if (U.uiflag & USER_SHOW_VIEWPORTNAME) { + VP_legacy_draw_viewport_name(ar, v3d, &rect); + } + + if (grid_unit) { /* draw below the viewport name */ + char numstr[32] = ""; + + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); + if (v3d->grid != 1.0f) { + BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); + } + + BLF_draw_default_ascii(rect.xmin + U.widget_unit, + rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f, + numstr[0] ? numstr : grid_unit, sizeof(numstr)); + } + } +} + +void view3d_main_region_draw_legacy(const bContext *C, ARegion *ar) +{ + EvaluationContext eval_ctx; + Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + View3D *v3d = CTX_wm_view3d(C); + const char *grid_unit = NULL; + rcti border_rect; + + /* if we only redraw render border area, skip opengl draw and also + * don't do scissor because it's already set */ + bool render_border = ED_view3d_calc_render_border(scene, v3d, ar, &border_rect); + bool clip_border = (render_border && !BLI_rcti_compare(&ar->drawrct, &border_rect)); + + gpuPushProjectionMatrix(); + gpuLoadIdentityProjectionMatrix(); + gpuPushMatrix(); + gpuLoadIdentity(); + + CTX_data_eval_ctx(C, &eval_ctx); + + /* draw viewport using opengl */ + if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene) || clip_border) { + VP_view3d_main_region_clear(scene, v3d, ar); /* background */ + view3d_main_region_draw_objects(C, scene, sl, v3d, ar, &grid_unit); + + if (G.debug & G_DEBUG_SIMDATA) + draw_sim_debug_data(scene, v3d, ar); + + glDisable(GL_DEPTH_TEST); + ED_region_pixelspace(ar); + } + + /* draw viewport using external renderer */ + if (v3d->drawtype == OB_RENDER) { + view3d_main_region_draw_engine(C, &eval_ctx, scene, ar, v3d, clip_border, &border_rect); + } + + VP_legacy_view3d_main_region_setup_view(&eval_ctx, scene, v3d, ar, NULL, NULL); + glClear(GL_DEPTH_BUFFER_BIT); + + ED_region_pixelspace(ar); + + WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_2D); + + view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border); + + gpuPopProjectionMatrix(); + gpuPopMatrix(); + + v3d->flag |= V3D_INVALID_BACKBUF; + + BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_transp)); + BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xray)); + BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xraytransp)); +} + + +/* -------------------------------------------------------------------- */ + +/** \name Deprecated Interface + * + * New viewport sometimes has a check for new/old viewport code. + * Use these functions so new viewport can *optionally* call. + * + * \{ */ + + +void VP_deprecated_view3d_draw_objects( + const bContext *C, + const EvaluationContext *eval_ctx, + Scene *scene, View3D *v3d, ARegion *ar, + const char **grid_unit, + const bool do_bgpic, const bool draw_offscreen, GPUFX *fx) +{ + view3d_draw_objects(C, eval_ctx, scene, v3d, ar, grid_unit, do_bgpic, draw_offscreen, fx); +} + +void VP_deprecated_gpu_update_lamps_shadows_world(const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d) +{ + gpu_update_lamps_shadows_world(eval_ctx, scene, v3d); +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 5203e0617ee..dc6d6382d37 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -34,6 +34,7 @@ #include <float.h> #include "DNA_armature_types.h" +#include "DNA_camera_types.h" #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -51,6 +52,7 @@ #include "BKE_camera.h" #include "BKE_context.h" #include "BKE_font.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_object.h" #include "BKE_paint.h" @@ -58,11 +60,10 @@ #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_action.h" -#include "BKE_depsgraph.h" /* for ED_view3d_camera_lock_sync */ +#include "DEG_depsgraph.h" #include "BIF_gl.h" -#include "BIF_glutil.h" #include "WM_api.h" #include "WM_types.h" @@ -79,6 +80,8 @@ #include "ED_gpencil.h" #include "ED_view3d.h" +#include "DEG_depsgraph_query.h" + #include "UI_resources.h" #include "PIL_time.h" /* smoothview */ @@ -163,7 +166,7 @@ bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d) ob_update = v3d->camera; while (ob_update) { - DAG_id_tag_update(&ob_update->id, OB_RECALC_OB); + DEG_id_tag_update(&ob_update->id, OB_RECALC_OB); WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, ob_update); ob_update = ob_update->parent; } @@ -175,7 +178,7 @@ bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d) ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist); BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag | protect_scale_all); - DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); + DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->camera); } @@ -621,7 +624,8 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) bool is_set = false; Scene *scene = CTX_data_scene(C); - Object *ob_act = OBACT; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob_act = OBACT(sl); if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) && /* with weight-paint + pose-mode, fall through to using calculateTransformCenter */ @@ -658,14 +662,13 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) } else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) { /* object mode use boundbox centers */ - View3D *v3d = CTX_wm_view3d(C); Base *base; unsigned int tot = 0; float select_center[3]; zero_v3(select_center); - for (base = FIRSTBASE; base; base = base->next) { - if (TESTBASE(v3d, base)) { + for (base = FIRSTBASE(sl); base; base = base->next) { + if (TESTBASE(base)) { /* use the boundbox if we can */ Object *ob = base->object; @@ -741,14 +744,18 @@ static void viewops_data_create_ex( /* we need the depth info before changing any viewport options */ if (orbit_mode & VIEWOPS_ORBIT_DEPTH) { + EvaluationContext eval_ctx; + struct Depsgraph *graph = CTX_data_depsgraph(C); float fallback_depth_pt[3]; + CTX_data_eval_ctx(C, &eval_ctx); + view3d_operator_needs_opengl(C); /* needed for zbuf drawing */ negate_v3_v3(fallback_depth_pt, rv3d->ofs); vod->use_dyn_ofs = ED_view3d_autodist( - vod->scene, vod->ar, vod->v3d, + &eval_ctx, graph, vod->ar, vod->v3d, event->mval, vod->dyn_ofs, true, fallback_depth_pt); } else { @@ -866,8 +873,9 @@ static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *even static void viewops_data_free(bContext *C, wmOperator *op) { ARegion *ar; +#if 0 Paint *p = BKE_paint_get_active_from_context(C); - +#endif if (op->customdata) { ViewOpsData *vod = op->customdata; ar = vod->ar; @@ -883,7 +891,9 @@ static void viewops_data_free(bContext *C, wmOperator *op) ar = CTX_wm_region(C); } +#if 0 if (p && (p->flags & PAINT_FAST_NAVIGATE)) +#endif ED_region_tag_redraw(ar); } /** \} */ @@ -2980,6 +2990,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Base *base; float *curs; const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions"); @@ -3003,8 +3014,8 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in INIT_MINMAX(min, max); } - for (base = scene->base.first; base; base = base->next) { - if (BASE_VISIBLE(v3d, base)) { + for (base = sl->object_bases.first; base; base = base->next) { + if (BASE_VISIBLE(base)) { changed = true; if (skip_camera && base->object == v3d->camera) { @@ -3064,9 +3075,12 @@ static int viewselected_exec(bContext *C, wmOperator *op) ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); bGPdata *gpd = CTX_data_gpencil_data(C); const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)); - Object *ob = OBACT; + const bool is_face_map = ((is_gp_edit == false) && ar->manipulator_map && + WM_manipulatormap_is_any_selected(ar->manipulator_map)); + Object *ob = OBACT(sl); Object *obedit = CTX_data_edit_object(C); float min[3], max[3]; bool ok = false, ok_dist = true; @@ -3077,8 +3091,7 @@ static int viewselected_exec(bContext *C, wmOperator *op) const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); INIT_MINMAX(min, max); - - if (is_gp_edit) { + if (is_gp_edit || is_face_map) { ob = NULL; } @@ -3086,8 +3099,8 @@ static int viewselected_exec(bContext *C, wmOperator *op) /* hard-coded exception, we look for the one selected armature */ /* this is weak code this way, we should make a generic active/selection callback interface once... */ Base *base; - for (base = scene->base.first; base; base = base->next) { - if (TESTBASELIB(v3d, base)) { + for (base = sl->object_bases.first; base; base = base->next) { + if (TESTBASELIB(base)) { if (base->object->type == OB_ARMATURE) if (base->object->mode & OB_MODE_POSE) break; @@ -3110,6 +3123,9 @@ static int viewselected_exec(bContext *C, wmOperator *op) } CTX_DATA_END; } + else if (is_face_map) { + ok = WM_manipulatormap_minmax(ar->manipulator_map, true, true, min, max); + } else if (obedit) { ok = ED_view3d_minmax_verts(obedit, min, max); /* only selected */ } @@ -3120,7 +3136,7 @@ static int viewselected_exec(bContext *C, wmOperator *op) ok = paintface_minmax(ob, min, max); } else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { - ok = PE_minmax(scene, min, max); + ok = PE_minmax(scene, sl, min, max); } else if (ob && (ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) @@ -3132,8 +3148,8 @@ static int viewselected_exec(bContext *C, wmOperator *op) } else { Base *base; - for (base = FIRSTBASE; base; base = base->next) { - if (TESTBASE(v3d, base)) { + for (base = FIRSTBASE(sl); base; base = base->next) { + if (TESTBASE(base)) { if (skip_camera && base->object == v3d->camera) { continue; @@ -3310,18 +3326,21 @@ static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *ev { View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); - Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); if (rv3d) { + EvaluationContext eval_ctx; + struct Depsgraph *graph = CTX_data_depsgraph(C); float new_ofs[3]; const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + CTX_data_eval_ctx(C, &eval_ctx); + ED_view3d_smooth_view_force_finish(C, v3d, ar); view3d_operator_needs_opengl(C); - if (ED_view3d_autodist(scene, ar, v3d, event->mval, new_ofs, false, NULL)) { + if (ED_view3d_autodist(&eval_ctx, graph, ar, v3d, event->mval, new_ofs, false, NULL)) { /* pass */ } else { @@ -3576,10 +3595,10 @@ void VIEW3D_OT_clear_render_border(wmOperatorType *ot) static int view3d_zoom_border_exec(bContext *C, wmOperator *op) { + EvaluationContext eval_ctx; ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); - Scene *scene = CTX_data_scene(C); const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); /* Zooms in on a border drawn by the user */ @@ -3592,13 +3611,14 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) float new_ofs[3]; /* ZBuffer depth vars */ - bglMats mats; float depth_close = FLT_MAX; - double cent[2], p[3]; + float p[3]; /* note; otherwise opengl won't work */ view3d_operator_needs_opengl(C); + CTX_data_eval_ctx(C, &eval_ctx); + /* get border select values using rna */ WM_operator_properties_border_to_rcti(op, &rect); @@ -3608,8 +3628,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) ED_view3d_dist_range_get(v3d, dist_range); /* Get Z Depths, needed for perspective, nice for ortho */ - bgl_get_mats(&mats); - ED_view3d_draw_depth(scene, ar, v3d, true); + ED_view3d_draw_depth(&eval_ctx, CTX_data_depsgraph(C), ar, v3d, true); { /* avoid allocating the whole depth buffer */ @@ -3624,11 +3643,11 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) MEM_SAFE_FREE(depth_temp.depths); } - cent[0] = (((double)rect.xmin) + ((double)rect.xmax)) / 2; - cent[1] = (((double)rect.ymin) + ((double)rect.ymax)) / 2; + float centx = (((float)rect.xmin) + ((float)rect.xmax)) / 2; + float centy = (((float)rect.ymin) + ((float)rect.ymax)) / 2; if (rv3d->is_persp) { - double p_corner[3]; + float p_corner[3]; /* no depths to use, we cant do anything! */ if (depth_close == FLT_MAX) { @@ -3636,23 +3655,14 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } /* convert border to 3d coordinates */ - if ((!gluUnProject(cent[0], cent[1], depth_close, - mats.modelview, mats.projection, (GLint *)mats.viewport, - &p[0], &p[1], &p[2])) || - (!gluUnProject((double)rect.xmin, (double)rect.ymin, depth_close, - mats.modelview, mats.projection, (GLint *)mats.viewport, - &p_corner[0], &p_corner[1], &p_corner[2]))) + if ((!ED_view3d_unproject(ar, centx, centy, depth_close, p)) || + (!ED_view3d_unproject(ar, rect.xmin, rect.ymin, depth_close, p_corner))) { return OPERATOR_CANCELLED; } - dvec[0] = p[0] - p_corner[0]; - dvec[1] = p[1] - p_corner[1]; - dvec[2] = p[2] - p_corner[2]; - - new_ofs[0] = -p[0]; - new_ofs[1] = -p[1]; - new_ofs[2] = -p[2]; + sub_v3_v3v3(dvec, p, p_corner); + negate_v3_v3(new_ofs, p); new_dist = len_v3(dvec); @@ -3667,13 +3677,8 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) new_dist = rv3d->dist; /* convert the drawn rectangle into 3d space */ - if (depth_close != FLT_MAX && gluUnProject(cent[0], cent[1], depth_close, - mats.modelview, mats.projection, (GLint *)mats.viewport, - &p[0], &p[1], &p[2])) - { - new_ofs[0] = -p[0]; - new_ofs[1] = -p[1]; - new_ofs[2] = -p[2]; + if (depth_close != FLT_MAX && ED_view3d_unproject(ar, centx, centy, depth_close, p)) { + negate_v3_v3(new_ofs, p); } else { float mval_f[2]; @@ -3910,6 +3915,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op) ARegion *ar; RegionView3D *rv3d; Scene *scene = CTX_data_scene(C); + SceneLayer *scene_layer = CTX_data_scene_layer(C); static int perspo = RV3D_PERSP; int viewnum, nextperspo; bool align_active; @@ -3944,7 +3950,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op) /* lastview - */ if (rv3d->persp != RV3D_CAMOB) { - Object *ob = OBACT; + Object *ob = OBACT(scene_layer); if (!rv3d->smooth_timer) { /* store settings of current view before allowing overwriting with camera view @@ -3979,7 +3985,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op) v3d->camera = ob; if (v3d->camera == NULL) - v3d->camera = BKE_scene_camera_find(scene); + v3d->camera = BKE_scene_layer_camera_find(scene_layer); /* couldnt find any useful camera, bail out */ if (v3d->camera == NULL) @@ -4511,11 +4517,11 @@ void VIEW3D_OT_navigate(wmOperatorType *ot) /* ******************** add background image operator **************** */ -static BGpic *background_image_add(bContext *C) +static CameraBGImage *background_image_add(bContext *C) { - View3D *v3d = CTX_wm_view3d(C); + Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; - return ED_view3D_background_image_new(v3d); + return BKE_camera_background_image_new(cam); } static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op)) @@ -4527,9 +4533,9 @@ static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op)) static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - View3D *v3d = CTX_wm_view3d(C); + Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; Image *ima; - BGpic *bgpic; + CameraBGImage *bgpic; ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM); /* may be NULL, continue anyway */ @@ -4537,10 +4543,10 @@ static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEven bgpic = background_image_add(C); bgpic->ima = ima; - v3d->flag |= V3D_DISPBGPICS; - - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); - + cam->flag |= CAM_SHOW_BG_IMAGE; + + WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam); + return OPERATOR_FINISHED; } @@ -4556,7 +4562,7 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot) /* api callbacks */ ot->invoke = background_image_add_invoke; ot->exec = background_image_add_exec; - ot->poll = ED_operator_view3d_active; + ot->poll = ED_operator_camera; /* flags */ ot->flag = OPTYPE_UNDO; @@ -4572,21 +4578,22 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot) /* ***** remove image operator ******* */ static int background_image_remove_exec(bContext *C, wmOperator *op) { - View3D *v3d = CTX_wm_view3d(C); + Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; const int index = RNA_int_get(op->ptr, "index"); - BGpic *bgpic_rem = BLI_findlink(&v3d->bgpicbase, index); + CameraBGImage *bgpic_rem = BLI_findlink(&cam->bg_images, index); if (bgpic_rem) { - if (bgpic_rem->source == V3D_BGPIC_IMAGE) { + if (bgpic_rem->source == CAM_BGIMG_SOURCE_IMAGE) { id_us_min((ID *)bgpic_rem->ima); } - else if (bgpic_rem->source == V3D_BGPIC_MOVIE) { + else if (bgpic_rem->source == CAM_BGIMG_SOURCE_MOVIE) { id_us_min((ID *)bgpic_rem->clip); } - ED_view3D_background_image_remove(v3d, bgpic_rem); + BKE_camera_background_image_remove(cam, bgpic_rem); + + WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); return OPERATOR_FINISHED; } else { @@ -4604,7 +4611,7 @@ void VIEW3D_OT_background_image_remove(wmOperatorType *ot) /* api callbacks */ ot->exec = background_image_remove_exec; - ot->poll = ED_operator_view3d_active; + ot->poll = ED_operator_camera; /* flags */ ot->flag = 0; @@ -4638,9 +4645,8 @@ void ED_view3d_clipping_local(RegionView3D *rv3d, float mat[4][4]) static int view3d_clipping_exec(bContext *C, wmOperator *op) { + ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); - ViewContext vc; - bglMats mats; rcti rect; WM_operator_properties_border_to_rcti(op, &rect); @@ -4648,12 +4654,8 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op) rv3d->rflag |= RV3D_CLIPPING; rv3d->clipbb = MEM_callocN(sizeof(BoundBox), "clipbb"); - /* note; otherwise opengl won't work */ - view3d_operator_needs_opengl(C); - - view3d_set_viewcontext(C, &vc); - view3d_get_transformation(vc.ar, vc.rv3d, NULL, &mats); /* NULL because we don't want it in object space */ - ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, &mats, &rect); + /* NULL object because we don't want it in object space */ + ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, ar, NULL, &rect); return OPERATOR_FINISHED; } @@ -4705,7 +4707,6 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot) /* note: cannot use event->mval here (called by object_add() */ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2]) { - Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = ar->regiondata; @@ -4727,9 +4728,15 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2]) } if (U.uiflag & USER_ZBUF_CURSOR) { /* maybe this should be accessed some other way */ + EvaluationContext eval_ctx; + struct Depsgraph *graph = CTX_data_depsgraph(C); + + CTX_data_eval_ctx(C, &eval_ctx); + view3d_operator_needs_opengl(C); - if (ED_view3d_autodist(scene, ar, v3d, mval, fp, true, NULL)) + if (ED_view3d_autodist(&eval_ctx, graph, ar, v3d, mval, fp, true, NULL)) { depth_used = true; + } } if (depth_used == false) { @@ -4808,45 +4815,6 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot) /* ***************** manipulator op ******************* */ - -static int manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - View3D *v3d = CTX_wm_view3d(C); - - if (!(v3d->twflag & V3D_USE_MANIPULATOR)) return OPERATOR_PASS_THROUGH; - if (!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return OPERATOR_PASS_THROUGH; - - /* note; otherwise opengl won't work */ - view3d_operator_needs_opengl(C); - - if (BIF_do_manipulator(C, event, op) == 0) - return OPERATOR_PASS_THROUGH; - - return OPERATOR_FINISHED; -} - -void VIEW3D_OT_manipulator(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name = "3D Manipulator"; - ot->description = "Manipulate selected item by axis"; - ot->idname = "VIEW3D_OT_manipulator"; - - /* api callbacks */ - ot->invoke = manipulator_invoke; - - ot->poll = ED_operator_view3d_active; - - /* properties to pass to transform */ - Transform_Properties(ot, P_CONSTRAINT); - - prop = RNA_def_boolean(ot->srna, "use_planar_constraint", false, "Planar Constraint", "Limit the transformation to the " - "two axes that have not been clicked (translate/scale only)"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); -} - static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { View3D *v3d = CTX_wm_view3d(C); @@ -4950,22 +4918,17 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg * \param fallback_depth_pt: Use this points depth when no depth can be found. */ bool ED_view3d_autodist( - Scene *scene, ARegion *ar, View3D *v3d, + const EvaluationContext *eval_ctx, struct Depsgraph *graph, ARegion *ar, View3D *v3d, const int mval[2], float mouse_worldloc[3], const bool alphaoverride, const float fallback_depth_pt[3]) { - bglMats mats; /* ZBuffer depth vars */ float depth_close; - double cent[2], p[3]; int margin_arr[] = {0, 2, 4}; int i; bool depth_ok = false; /* Get Z Depths, needed for perspective, nice for ortho */ - ED_view3d_draw_depth(scene, ar, v3d, alphaoverride); - - /* call after in case settings have been modified since last drawing, see: T47089 */ - bgl_get_mats(&mats); + ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, alphaoverride); /* Attempt with low margin's first */ i = 0; @@ -4975,15 +4938,10 @@ bool ED_view3d_autodist( } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr))); if (depth_ok) { - cent[0] = (double)mval[0] + 0.5; - cent[1] = (double)mval[1] + 0.5; + float centx = (float)mval[0] + 0.5f; + float centy = (float)mval[1] + 0.5f; - if (gluUnProject(cent[0], cent[1], depth_close, - mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) - { - mouse_worldloc[0] = (float)p[0]; - mouse_worldloc[1] = (float)p[1]; - mouse_worldloc[2] = (float)p[2]; + if (ED_view3d_unproject(ar, centx, centy, depth_close, mouse_worldloc)) { return true; } } @@ -4997,16 +4955,21 @@ bool ED_view3d_autodist( } } -void ED_view3d_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) +void ED_view3d_autodist_init( + const EvaluationContext *eval_ctx, struct Depsgraph *graph, + ARegion *ar, View3D *v3d, int mode) { /* Get Z Depths, needed for perspective, nice for ortho */ switch (mode) { case 0: - ED_view3d_draw_depth(scene, ar, v3d, true); + ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, true); break; case 1: - ED_view3d_draw_depth_gpencil(scene, ar, v3d); + { + Scene *scene = DEG_get_evaluated_scene(graph); + ED_view3d_draw_depth_gpencil(eval_ctx, scene, ar, v3d); break; + } } } @@ -5014,9 +4977,7 @@ void ED_view3d_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth) { - bglMats mats; /* ZBuffer depth vars, could cache? */ float depth; - double cent[2], p[3]; /* Get Z Depths, needed for perspective, nice for ortho */ if (force_depth) @@ -5027,21 +4988,9 @@ bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_world if (depth == FLT_MAX) return false; - cent[0] = (double)mval[0] + 0.5; - cent[1] = (double)mval[1] + 0.5; - - bgl_get_mats(&mats); - - if (!gluUnProject(cent[0], cent[1], depth, - mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) - { - return false; - } - - mouse_worldloc[0] = (float)p[0]; - mouse_worldloc[1] = (float)p[1]; - mouse_worldloc[2] = (float)p[2]; - return true; + float centx = (float)mval[0] + 0.5f; + float centy = (float)mval[1] + 0.5f; + return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc); } bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth) @@ -5223,6 +5172,7 @@ void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], const float dist) { float mat[4][4]; + ED_view3d_to_m4(mat, ofs, quat, dist); BKE_object_apply_mat4(ob, mat, true, true); } @@ -5239,43 +5189,6 @@ void ED_view3d_lastview_store(RegionView3D *rv3d) } } -BGpic *ED_view3D_background_image_new(View3D *v3d) -{ - BGpic *bgpic = MEM_callocN(sizeof(BGpic), "Background Image"); - - bgpic->rotation = 0.0f; - bgpic->size = 5.0f; - bgpic->blend = 0.5f; - bgpic->iuser.fie_ima = 2; - bgpic->iuser.ok = 1; - bgpic->view = 0; /* 0 for all */ - bgpic->flag |= V3D_BGPIC_EXPANDED; - - BLI_addtail(&v3d->bgpicbase, bgpic); - - return bgpic; -} - -void ED_view3D_background_image_remove(View3D *v3d, BGpic *bgpic) -{ - BLI_remlink(&v3d->bgpicbase, bgpic); - - MEM_freeN(bgpic); -} - -void ED_view3D_background_image_clear(View3D *v3d) -{ - BGpic *bgpic = v3d->bgpicbase.first; - - while (bgpic) { - BGpic *next_bgpic = bgpic->next; - - ED_view3D_background_image_remove(v3d, bgpic); - - bgpic = next_bgpic; - } -} - void ED_view3D_lock_clear(View3D *v3d) { v3d->ob_centre = NULL; diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index eda780d01a7..5e7eddb1c22 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -56,6 +56,8 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "GPU_immediate.h" + #include "view3d_intern.h" /* own include */ /* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ @@ -257,36 +259,45 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), x2 = xoff + 0.55f * fly->width; y2 = yoff + 0.55f * fly->height; - UI_ThemeColor(TH_VIEW_OVERLAY); - glBegin(GL_LINES); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColor(TH_VIEW_OVERLAY); + + immBegin(GWN_PRIM_LINES, 16); + /* bottom left */ - glVertex2f(x1, y1); - glVertex2f(x1, y1 + 5); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x1, y1 + 5); - glVertex2f(x1, y1); - glVertex2f(x1 + 5, y1); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x1 + 5, y1); /* top right */ - glVertex2f(x2, y2); - glVertex2f(x2, y2 - 5); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x2, y2 - 5); - glVertex2f(x2, y2); - glVertex2f(x2 - 5, y2); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x2 - 5, y2); /* top left */ - glVertex2f(x1, y2); - glVertex2f(x1, y2 - 5); + immVertex2f(pos, x1, y2); + immVertex2f(pos, x1, y2 - 5); - glVertex2f(x1, y2); - glVertex2f(x1 + 5, y2); + immVertex2f(pos, x1, y2); + immVertex2f(pos, x1 + 5, y2); /* bottom right */ - glVertex2f(x2, y1); - glVertex2f(x2, y1 + 5); + immVertex2f(pos, x2, y1); + immVertex2f(pos, x2, y1 + 5); + + immVertex2f(pos, x2, y1); + immVertex2f(pos, x2 - 5, y1); - glVertex2f(x2, y1); - glVertex2f(x2 - 5, y1); - glEnd(); + immEnd(); + immUnbindProgram(); } static void fly_update_header(bContext *C, wmOperator *op, FlyInfo *fly) @@ -406,7 +417,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent } fly->v3d_camera_control = ED_view3d_cameracontrol_acquire( - fly->scene, fly->v3d, fly->rv3d, + C, fly->scene, fly->v3d, fly->rv3d, (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); /* calculate center */ diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 11dc4d10f2a..4f322b8519d 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -41,11 +41,12 @@ #include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_screen.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -71,11 +72,10 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event); /* XXX quickly ported across */ static void handle_view3d_lock(bContext *C) { - Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ScrArea *sa = CTX_wm_area(C); View3D *v3d = CTX_wm_view3d(C); - + if (v3d != NULL && sa != NULL) { if (v3d->localvd == NULL && v3d->scenelock && sa->spacetype == SPACE_VIEW3D) { /* copy to scene */ @@ -83,10 +83,6 @@ static void handle_view3d_lock(bContext *C) scene->layact = v3d->layact; scene->camera = v3d->camera; - /* not through notifier, listener don't have context - * and non-open screens or spaces need to be updated too */ - BKE_screen_view3d_main_sync(&bmain->screen, scene); - /* notifiers for scene update */ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); } @@ -172,7 +168,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op) if (v3d->scenelock) handle_view3d_lock(C); - DAG_on_visible_update(CTX_data_main(C), false); + DEG_on_visible_update(CTX_data_main(C), false); ED_area_tag_redraw(sa); @@ -284,15 +280,16 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); ToolSettings *ts = CTX_data_tool_settings(C); PointerRNA v3dptr, toolsptr, sceneptr; - Object *ob = OBACT; + Object *ob = OBACT(sl); Object *obedit = CTX_data_edit_object(C); bGPdata *gpd = CTX_data_gpencil_data(C); uiBlock *block; uiLayout *row; - bool is_paint = false; - int modeselect; + bool is_paint = ob && !(gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) && + ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT); RNA_pointer_create(&screen->id, &RNA_SpaceView3D, v3d, &v3dptr); RNA_pointer_create(&scene->id, &RNA_ToolSettings, ts, &toolsptr); @@ -303,39 +300,6 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) /* other buttons: */ UI_block_emboss_set(block, UI_EMBOSS); - - /* mode */ - if ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)) { - modeselect = OB_MODE_GPENCIL; - } - else if (ob) { - modeselect = ob->mode; - is_paint = ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT); - } - else { - modeselect = OB_MODE_OBJECT; - } - - row = uiLayoutRow(layout, false); - { - const EnumPropertyItem *item = rna_enum_object_mode_items; - const char *name = ""; - int icon = ICON_OBJECT_DATAMODE; - - while (item->identifier) { - if (item->value == modeselect && item->identifier[0]) { - name = IFACE_(item->name); - icon = item->icon; - break; - } - item++; - } - - uiItemMenuEnumO(row, C, "OBJECT_OT_mode_set", "mode", name, icon); - } - - /* Draw type */ - uiItemR(layout, &v3dptr, "viewport_shade", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); row = uiLayoutRow(layout, true); uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); @@ -364,18 +328,13 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) /* Transform widget / manipulators */ row = uiLayoutRow(layout, true); uiItemR(row, &v3dptr, "show_manipulator", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); - if (v3d->twflag & V3D_USE_MANIPULATOR) { + if (v3d->twflag & V3D_MANIPULATOR_DRAW) { uiItemR(row, &v3dptr, "transform_manipulators", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); } uiItemR(row, &v3dptr, "transform_orientation", 0, "", ICON_NONE); } if (obedit == NULL && v3d->localvd == NULL) { - unsigned int ob_lay = ob ? ob->lay : 0; - - /* Layers */ - uiTemplateLayers(layout, v3d->scenelock ? &sceneptr : &v3dptr, "layers", &v3dptr, "layers_used", ob_lay); - /* Scene lock */ uiItemR(layout, &v3dptr, "lock_camera_and_layers", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 7a106a27833..189e22a04d7 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -37,7 +37,9 @@ struct ARegion; struct ARegionType; +struct Base; struct BoundBox; +struct Gwn_Batch; struct DerivedMesh; struct Object; struct SmokeDomainSettings; @@ -46,9 +48,12 @@ struct bContext; struct bMotionPath; struct bPoseChannel; struct Mesh; +struct SceneLayer; struct wmOperatorType; -struct wmWindowManager; struct wmKeyConfig; +struct wmManipulatorGroupType; +struct wmManipulatorType; +struct wmWindowManager; /* drawing flags: */ enum { @@ -99,7 +104,6 @@ void VIEW3D_OT_view_orbit(struct wmOperatorType *ot); void VIEW3D_OT_view_roll(struct wmOperatorType *ot); void VIEW3D_OT_clip_border(struct wmOperatorType *ot); void VIEW3D_OT_cursor3d(struct wmOperatorType *ot); -void VIEW3D_OT_manipulator(struct wmOperatorType *ot); void VIEW3D_OT_enable_manipulator(struct wmOperatorType *ot); void VIEW3D_OT_render_border(struct wmOperatorType *ot); void VIEW3D_OT_clear_render_border(struct wmOperatorType *ot); @@ -142,13 +146,29 @@ void draw_motion_paths_cleanup(View3D *v3d); /* drawobject.c */ -void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, const short dflag); -void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag); - -bool draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const char dt); -void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline); -void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob); -void drawaxes(const float viewmat_local[4][4], float size, char drawtype); +void draw_object( + const struct EvaluationContext *eval_ctx, Scene *scene, struct SceneLayer *sl, struct ARegion *ar, View3D *v3d, + struct Base *base, const short dflag); +void draw_object_select( + const struct EvaluationContext *eval_ctx, Scene *scene, struct SceneLayer *sl, struct ARegion *ar, View3D *v3d, + Base *base, const short dflag); + +void draw_mesh_object_outline(View3D *v3d, Object *ob, struct DerivedMesh *dm, const unsigned char ob_wire_col[4]); + +bool draw_glsl_material(Scene *scene, struct SceneLayer *sl, struct Object *ob, View3D *v3d, const char dt); +void draw_object_instance(const struct EvaluationContext *eval_ctx, Scene *scene, struct SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline, const float wire_col[4]); +void draw_object_backbufsel(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob); + +void draw_object_wire_color(Scene *scene, struct SceneLayer *, Base *base, unsigned char r_ob_wire_col[4]); +void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const unsigned char color[4]); +void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const short dflag, const unsigned char ob_wire_col[4], + const bool is_obact); +void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, + const short dflag, const unsigned char ob_wire_col[4]); +void drawspeaker(const unsigned char ob_wire_col[3]); +void draw_bounding_volume(struct Object *ob, char type, const unsigned char ob_wire_col[4]); +void draw_rigidbody_shape(struct Object *ob, const unsigned char ob_wire_col[4]); void view3d_cached_text_draw_begin(void); void view3d_cached_text_draw_add(const float co[3], @@ -169,12 +189,13 @@ enum { int view3d_effective_drawtype(const struct View3D *v3d); /* drawarmature.c */ -bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4], - const bool is_outline); +bool draw_armature( + const struct EvaluationContext *eval_ctx, Scene *scene, struct SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, + const short dt, const short dflag, const unsigned char ob_wire_col[4], + const bool is_outline); /* drawmesh.c */ -void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, +void draw_mesh_textured(Scene *scene, struct SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, struct Object *ob, struct DerivedMesh *dm, const int draw_flags); void draw_mesh_face_select( struct RegionView3D *rv3d, struct Mesh *me, struct DerivedMesh *dm, @@ -195,16 +216,28 @@ void draw_sim_debug_data(Scene *scene, View3D *v3d, ARegion *ar); /* view3d_draw.c */ void view3d_main_region_draw(const struct bContext *C, struct ARegion *ar); -void ED_view3d_draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, bool alphaoverride); -void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d); +void view3d_draw_region_info(const struct bContext *C, struct ARegion *ar, const int offset); + +void ED_view3d_draw_depth( + const struct EvaluationContext *eval_ctx, struct Depsgraph *graph, + struct ARegion *ar, View3D *v3d, bool alphaoverride); + +/* view3d_draw_legacy.c */ +void view3d_main_region_draw_legacy(const struct bContext *C, struct ARegion *ar); +void ED_view3d_draw_depth_gpencil(const struct EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d); + void ED_view3d_draw_select_loop( - ViewContext *vc, Scene *scene, View3D *v3d, ARegion *ar, + const struct EvaluationContext *eval_ctx, ViewContext *vc, Scene *scene, struct SceneLayer *sl, View3D *v3d, ARegion *ar, bool use_obedit_skip, bool use_nearest); -void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag);\ +void ED_view3d_draw_depth_loop( + const struct EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d); + +void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d, + const bool do_foreground, const bool do_camera_frame); + +void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag); -void circf(float x, float y, float rad); -void circ(float x, float y, float rad); void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect); float view3d_depth_near(struct ViewDepths *d); @@ -219,7 +252,6 @@ void VIEW3D_OT_smoothview(struct wmOperatorType *ot); void VIEW3D_OT_camera_to_view(struct wmOperatorType *ot); void VIEW3D_OT_camera_to_view_selected(struct wmOperatorType *ot); void VIEW3D_OT_object_as_camera(struct wmOperatorType *ot); -void VIEW3D_OT_localview(struct wmOperatorType *ot); void VIEW3D_OT_game_start(struct wmOperatorType *ot); @@ -248,7 +280,7 @@ void ED_view3d_smooth_view_force_finish( struct View3D *v3d, struct ARegion *ar); void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect); -void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d); +void view3d_viewmatrix_set(const struct EvaluationContext *eval_ctx, Scene *scene, const View3D *v3d, RegionView3D *rv3d); void fly_modal_keymap(struct wmKeyConfig *keyconf); void walk_modal_keymap(struct wmKeyConfig *keyconf); @@ -263,7 +295,7 @@ void view3d_buttons_register(struct ARegionType *art); /* view3d_camera_control.c */ struct View3DCameraControl *ED_view3d_cameracontrol_acquire( - Scene *scene, View3D *v3d, RegionView3D *rv3d, + const struct bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d, const bool use_parent_root); void ED_view3d_cameracontrol_update( struct View3DCameraControl *vctrl, @@ -297,6 +329,20 @@ ARegion *view3d_has_tools_region(ScrArea *sa); extern const char *view3d_context_dir[]; /* doc access */ +/* view3d_widgets.c */ +void VIEW3D_WGT_lamp_spot(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_lamp_area(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_lamp_target(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_camera(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_camera_view(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_force_field(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_empty_image(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_armature_spline(struct wmManipulatorGroupType *wgt); + +void VIEW3D_WGT_ruler(struct wmManipulatorGroupType *wgt); +void VIEW3D_WT_ruler_item(struct wmManipulatorType *wt); +void VIEW3D_OT_ruler_add(struct wmOperatorType *ot); + /* draw_volume.c */ void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob, const float min[3], const float max[3], @@ -315,5 +361,31 @@ extern unsigned char view3d_camera_border_hack_col[3]; extern bool view3d_camera_border_hack_test; #endif -#endif /* __VIEW3D_INTERN_H__ */ +/* temporary for legacy viewport to work */ +void VP_legacy_drawcursor(Scene *scene, struct SceneLayer *sl, ARegion *ar, View3D *v3d); +void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect); +void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect); +void VP_legacy_draw_selected_name(Scene *scene, Object *ob, rcti *rect); +void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit); +void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth); +void VP_legacy_view3d_main_region_setup_view(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4]); +bool VP_legacy_view3d_stereo3d_active(struct wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d); +void VP_legacy_view3d_stereo3d_setup(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar); +void draw_dupli_objects(const struct EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *base); +bool VP_legacy_use_depth(Scene *scene, View3D *v3d); +void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d); +void VP_drawrenderborder(ARegion *ar, View3D *v3d); +void VP_view3d_draw_background_none(void); +void VP_view3d_draw_background_world(Scene *scene, RegionView3D *rv3d); +void VP_view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar); + +/* temporary legacy calls, only when there is a switch between new/old draw calls */ +void VP_deprecated_gpu_update_lamps_shadows_world(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d); +void VP_deprecated_view3d_draw_objects( + const struct bContext *C, + const struct EvaluationContext *eval_ctx, + Scene *scene, View3D *v3d, ARegion *ar, + const char **grid_unit, + const bool do_bgpic, const bool draw_offscreen, struct GPUFX *fx); +#endif /* __VIEW3D_INTERN_H__ */ diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index ef7b01f7a21..4f80270e1e7 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -40,6 +40,9 @@ #include "BKE_DerivedMesh.h" #include "BKE_displist.h" #include "BKE_editmesh.h" +#include "BKE_context.h" + +#include "DEG_depsgraph.h" #include "bmesh.h" @@ -104,12 +107,14 @@ static void meshobject_foreachScreenVert__mapFunc(void *userData, int index, con } void meshobject_foreachScreenVert( - ViewContext *vc, + const EvaluationContext *eval_ctx, ViewContext *vc, void (*func)(void *userData, MVert *eve, const float screen_co[2], int index), void *userData, eV3DProjTest clip_flag) { foreachScreenObjectVert_userData data; - DerivedMesh *dm = mesh_get_derived_deform(vc->scene, vc->obact, CD_MASK_BAREMESH); + DerivedMesh *dm; + + dm = mesh_get_derived_deform(eval_ctx, vc->scene, vc->obact, CD_MASK_BAREMESH); ED_view3d_check_mats_rv3d(vc->rv3d); @@ -145,12 +150,14 @@ static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const flo } void mesh_foreachScreenVert( - ViewContext *vc, + const EvaluationContext *eval_ctx, ViewContext *vc, void (*func)(void *userData, BMVert *eve, const float screen_co[2], int index), void *userData, eV3DProjTest clip_flag) { foreachScreenVert_userData data; - DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); + DerivedMesh *dm; + + dm = editbmesh_get_derived_cage(eval_ctx, vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); ED_view3d_check_mats_rv3d(vc->rv3d); @@ -199,12 +206,14 @@ static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, const flo } void mesh_foreachScreenEdge( - ViewContext *vc, + const EvaluationContext *eval_ctx, ViewContext *vc, void (*func)(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index), void *userData, eV3DProjTest clip_flag) { foreachScreenEdge_userData data; - DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); + DerivedMesh *dm; + + dm = editbmesh_get_derived_cage(eval_ctx, vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); ED_view3d_check_mats_rv3d(vc->rv3d); @@ -245,12 +254,14 @@ static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const flo } void mesh_foreachScreenFace( - ViewContext *vc, + const EvaluationContext *eval_ctx, ViewContext *vc, void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index), void *userData, const eV3DProjTest clip_flag) { foreachScreenFace_userData data; - DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); + DerivedMesh *dm; + + dm = editbmesh_get_derived_cage(eval_ctx, vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); ED_view3d_check_mats_rv3d(vc->rv3d); diff --git a/source/blender/editors/space_view3d/view3d_manipulator_armature.c b/source/blender/editors/space_view3d/view3d_manipulator_armature.c new file mode 100644 index 00000000000..5d3d88ff2a2 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_armature.c @@ -0,0 +1,220 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_manipulator_armature.c + * \ingroup spview3d + */ + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_armature.h" +#include "BKE_action.h" +#include "BKE_context.h" +#include "BKE_object.h" + +#include "DNA_object_types.h" +#include "DNA_armature_types.h" + +#include "ED_armature.h" +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +#include "UI_resources.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "view3d_intern.h" /* own include */ + + +/* -------------------------------------------------------------------- */ + +/** \name Armature Spline Manipulator + * + * \{ */ + +/* + * TODO(campbell): Current conversion is a approximation (usable not correct), + * we'll need to take the next/previous bones into account to get the tangent directions. + * First last matrices from 'b_bone_spline_setup' are close but also not quite accurate + * since they're not at either end-points on the curve. + * + * Likely we'll need a function especially to get the first/last orientations. + */ + +#define BBONE_SCALE_Y 3.0f + +struct BoneSplineHandle { + wmManipulator *manipulator; + bPoseChannel *pchan; + /* We could remove, keep since at the moment for checking the conversion. */ + float co[3]; + int index; +}; + +struct BoneSplineWidgetGroup { + struct BoneSplineHandle handles[2]; +}; + +static void manipulator_bbone_offset_get( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + void *value_p) +{ + struct BoneSplineHandle *bh = mpr_prop->custom_func.user_data; + bPoseChannel *pchan = bh->pchan; + + float *value = value_p; + BLI_assert(mpr_prop->type->array_length == 3); + + if (bh->index == 0) { + bh->co[1] = pchan->bone->ease1 / BBONE_SCALE_Y; + bh->co[0] = pchan->curveInX; + bh->co[2] = pchan->curveInY; + } + else { + bh->co[1] = -pchan->bone->ease2 / BBONE_SCALE_Y; + bh->co[0] = pchan->curveOutX; + bh->co[2] = pchan->curveOutY; + } + copy_v3_v3(value, bh->co); +} + +static void manipulator_bbone_offset_set( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + struct BoneSplineHandle *bh = mpr_prop->custom_func.user_data; + bPoseChannel *pchan = bh->pchan; + + const float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 3); + copy_v3_v3(bh->co, value); + + if (bh->index == 0) { + pchan->bone->ease1 = max_ff(0.0f, bh->co[1] * BBONE_SCALE_Y); + pchan->curveInX = bh->co[0]; + pchan->curveInY = bh->co[2]; + } + else { + pchan->bone->ease2 = max_ff(0.0f, -bh->co[1] * BBONE_SCALE_Y); + pchan->curveOutX = bh->co[0]; + pchan->curveOutY = bh->co[2]; + } + +} + +static bool WIDGETGROUP_armature_spline_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); + if (ob != NULL) { + const bArmature *arm = ob->data; + if (arm->drawtype == ARM_B_BONE) { + if (arm->act_bone && arm->act_bone->segments > 1) { + return true; + } + } + } + return false; +} + + +static void WIDGETGROUP_armature_spline_setup(const bContext *C, wmManipulatorGroup *mgroup) +{ + Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); + bPoseChannel *pchan = BKE_pose_channel_active(ob); + + const wmManipulatorType *wt_grab = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", true); + + struct BoneSplineWidgetGroup *bspline_group = MEM_callocN(sizeof(struct BoneSplineWidgetGroup), __func__); + mgroup->customdata = bspline_group; + + /* Handles */ + for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) { + wmManipulator *mpr; + mpr = bspline_group->handles[i].manipulator = WM_manipulator_new_ptr(wt_grab, mgroup, NULL); + RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_RING_2D); + RNA_enum_set(mpr->ptr, "draw_options", + ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL | ED_MANIPULATOR_GRAB_DRAW_FLAG_ALIGN_VIEW); + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_VALUE, true); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); + + mpr->scale_basis = 0.06f; + + if (i == 0) { + copy_v3_v3(mpr->matrix_basis[3], pchan->loc); + } + } +} + +static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); + + if (!mgroup->customdata) + return; + + struct BoneSplineWidgetGroup *bspline_group = mgroup->customdata; + bPoseChannel *pchan = BKE_pose_channel_active(ob); + + /* Handles */ + for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) { + wmManipulator *mpr = bspline_group->handles[i].manipulator; + bspline_group->handles[i].pchan = pchan; + bspline_group->handles[i].index = i; + + float mat[4][4]; + mul_m4_m4m4(mat, ob->obmat, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat); + copy_m4_m4(mpr->matrix_space, mat); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + WM_manipulator_target_property_def_func( + mpr, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_bbone_offset_get, + .value_set_fn = manipulator_bbone_offset_set, + .range_get_fn = NULL, + .user_data = &bspline_group->handles[i], + }); + } +} + +void VIEW3D_WGT_armature_spline(wmManipulatorGroupType *wgt) +{ + wgt->name = "Armature Spline Widgets"; + wgt->idname = "VIEW3D_WGT_armature_spline"; + + wgt->flag = (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D); + + wgt->poll = WIDGETGROUP_armature_spline_poll; + wgt->setup = WIDGETGROUP_armature_spline_setup; + wgt->refresh = WIDGETGROUP_armature_spline_refresh; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_manipulator_camera.c b/source/blender/editors/space_view3d/view3d_manipulator_camera.c new file mode 100644 index 00000000000..e8a1b5cea89 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c @@ -0,0 +1,401 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_manipulator_camera.c + * \ingroup spview3d + */ + + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_camera.h" +#include "BKE_context.h" + +#include "DNA_object_types.h" +#include "DNA_camera_types.h" + +#include "ED_armature.h" +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +#include "UI_resources.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "view3d_intern.h" /* own include */ + + +/* -------------------------------------------------------------------- */ + +/** \name Camera Manipulators + * \{ */ + +struct CameraWidgetGroup { + wmManipulator *dop_dist; + wmManipulator *focal_len; + wmManipulator *ortho_scale; +}; + +static bool WIDGETGROUP_camera_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = CTX_data_active_object(C); + + return (ob && ob->type == OB_CAMERA); +} + +static void cameragroup_property_setup(wmManipulator *widget, Object *ob, Camera *ca, const bool is_ortho) +{ + const float scale[3] = {1.0f / len_v3(ob->obmat[0]), 1.0f / len_v3(ob->obmat[1]), 1.0f / len_v3(ob->obmat[2])}; + const float scale_fac = ca->drawsize; + const float drawsize = is_ortho ? + (0.5f * ca->ortho_scale) : + (scale_fac / ((scale[0] + scale[1] + scale[2]) / 3.0f)); + const float half_sensor = 0.5f * ((ca->sensor_fit == CAMERA_SENSOR_FIT_VERT) ? ca->sensor_y : ca->sensor_x); + const char *propname = is_ortho ? "ortho_scale" : "lens"; + + PointerRNA camera_ptr; + float min, max, range; + float step, precision; + + RNA_pointer_create(&ca->id, &RNA_Camera, ca, &camera_ptr); + + /* get property range */ + PropertyRNA *prop = RNA_struct_find_property(&camera_ptr, propname); + RNA_property_float_ui_range(&camera_ptr, prop, &min, &max, &step, &precision); + range = max - min; + + ED_manipulator_arrow3d_set_range_fac(widget, is_ortho ? (scale_fac * range) : (drawsize * range / half_sensor)); +} + +static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgroup) +{ + Object *ob = CTX_data_active_object(C); + Camera *ca = ob->data; + float dir[3]; + + const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true); + + struct CameraWidgetGroup *camgroup = MEM_callocN(sizeof(struct CameraWidgetGroup), __func__); + mgroup->customdata = camgroup; + + negate_v3_v3(dir, ob->obmat[2]); + + /* dof distance */ + { + wmManipulator *mpr; + mpr = camgroup->dop_dist = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); + RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CROSS); + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_HOVER, true); + + UI_GetThemeColor3fv(TH_MANIPULATOR_A, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); + } + + /* focal length + * - logic/calculations are similar to BKE_camera_view_frame_ex, better keep in sync */ + { + wmManipulator *mpr; + mpr = camgroup->focal_len = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); + mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE; + RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE); + RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); + cameragroup_property_setup(mpr, ob, ca, false); + + mpr = camgroup->ortho_scale = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); + mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE; + RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE); + RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); + cameragroup_property_setup(mpr, ob, ca, true); + } +} + +static void WIDGETGROUP_camera_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + if (!mgroup->customdata) + return; + + struct CameraWidgetGroup *camgroup = mgroup->customdata; + Object *ob = CTX_data_active_object(C); + Camera *ca = ob->data; + PointerRNA camera_ptr; + float dir[3]; + + RNA_pointer_create(&ca->id, &RNA_Camera, ca, &camera_ptr); + + negate_v3_v3(dir, ob->obmat[2]); + + if (ca->flag & CAM_SHOWLIMITS) { + WM_manipulator_set_matrix_location(camgroup->dop_dist, ob->obmat[3]); + WM_manipulator_set_matrix_rotation_from_yz_axis(camgroup->dop_dist, ob->obmat[1], dir); + WM_manipulator_set_scale(camgroup->dop_dist, ca->drawsize); + WM_manipulator_set_flag(camgroup->dop_dist, WM_MANIPULATOR_HIDDEN, false); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + WM_manipulator_target_property_def_rna(camgroup->dop_dist, "offset", &camera_ptr, "dof_distance", -1); + } + else { + WM_manipulator_set_flag(camgroup->dop_dist, WM_MANIPULATOR_HIDDEN, true); + } + + /* TODO - make focal length/ortho scale widget optional */ + if (true) { + const bool is_ortho = (ca->type == CAM_ORTHO); + float offset[3]; + float aspect[2]; + + wmManipulator *widget = is_ortho ? camgroup->ortho_scale : camgroup->focal_len; + WM_manipulator_set_flag(widget, WM_MANIPULATOR_HIDDEN, false); + WM_manipulator_set_flag(is_ortho ? camgroup->focal_len : camgroup->ortho_scale, WM_MANIPULATOR_HIDDEN, true); + + + /* account for lens shifting */ + offset[0] = ((ob->size[0] > 0.0f) ? -2.0f : 2.0f) * ca->shiftx; + offset[1] = 2.0f * ca->shifty; + offset[2] = 0.0f; + + /* get aspect */ + const Scene *scene = CTX_data_scene(C); + const float aspx = (float)scene->r.xsch * scene->r.xasp; + const float aspy = (float)scene->r.ysch * scene->r.yasp; + const int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, aspx, aspy); + aspect[0] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? 1.0f : aspx / aspy; + aspect[1] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? aspy / aspx : 1.0f; + + unit_m4(widget->matrix_basis); + WM_manipulator_set_matrix_location(widget, ob->obmat[3]); + WM_manipulator_set_matrix_rotation_from_yz_axis(widget, ob->obmat[1], dir); + + { + float scale_matrix; + if (is_ortho) { + scale_matrix = ca->ortho_scale * 0.5f; + } + else { + const float scale[3] = { + 1.0f / len_v3(ob->obmat[0]), + 1.0f / len_v3(ob->obmat[1]), + 1.0f / len_v3(ob->obmat[2]), + }; + scale_matrix = ca->drawsize / ((scale[0] + scale[1] + scale[2]) / 3.0f); + } + mul_v3_fl(widget->matrix_basis[0], scale_matrix); + mul_v3_fl(widget->matrix_basis[1], scale_matrix); + } + + RNA_float_set_array(widget->ptr, "aspect", aspect); + + WM_manipulator_set_matrix_offset_location(widget, offset); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + WM_manipulator_target_property_def_rna(camgroup->focal_len, "offset", &camera_ptr, "lens", -1); + WM_manipulator_target_property_def_rna(camgroup->ortho_scale, "offset", &camera_ptr, "ortho_scale", -1); + } +} + +void VIEW3D_WGT_camera(wmManipulatorGroupType *wgt) +{ + wgt->name = "Camera Widgets"; + wgt->idname = "VIEW3D_WGT_camera"; + + wgt->flag = (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D | + WM_MANIPULATORGROUPTYPE_DEPTH_3D); + + wgt->poll = WIDGETGROUP_camera_poll; + wgt->setup = WIDGETGROUP_camera_setup; + wgt->refresh = WIDGETGROUP_camera_refresh; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name CameraView Manipulators + * \{ */ + +struct CameraViewWidgetGroup { + wmManipulator *border; + + struct { + rctf *edit_border; + rctf view_border; + } state; +}; + +/* scale callbacks */ +static void manipulator_render_border_prop_matrix_get( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + void *value_p) +{ + float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + struct CameraViewWidgetGroup *viewgroup = mpr_prop->custom_func.user_data; + const rctf *border = viewgroup->state.edit_border; + + unit_m4(matrix); + matrix[0][0] = BLI_rctf_size_x(border); + matrix[1][1] = BLI_rctf_size_y(border); + matrix[3][0] = BLI_rctf_cent_x(border); + matrix[3][1] = BLI_rctf_cent_y(border); +} + +static void manipulator_render_border_prop_matrix_set( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + const float (*matrix)[4] = value_p; + struct CameraViewWidgetGroup *viewgroup = mpr_prop->custom_func.user_data; + rctf *border = viewgroup->state.edit_border; + BLI_assert(mpr_prop->type->array_length == 16); + + BLI_rctf_resize(border, len_v3(matrix[0]), len_v3(matrix[1])); + BLI_rctf_recenter(border, matrix[3][0], matrix[3][1]); + BLI_rctf_isect(&(rctf){.xmin = 0, .ymin = 0, .xmax = 1, .ymax = 1}, border, border); +} + +static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + + /* This is just so the border isn't always in the way, + * stealing mouse clicks from regular usage. + * We could change the rules for when to show. */ + { + SceneLayer *sl = CTX_data_scene_layer(C); + if (scene->camera != OBACT(sl)) { + return false; + } + } + + if (rv3d->persp == RV3D_CAMOB) { + if (scene->r.mode & R_BORDER) { + return true; + } + } + else if (v3d->flag2 & V3D_RENDER_BORDER) { + return true; + } + return false; +} + +static void WIDGETGROUP_camera_view_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + struct CameraViewWidgetGroup *viewgroup = MEM_mallocN(sizeof(struct CameraViewWidgetGroup), __func__); + + viewgroup->border = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL); + + RNA_enum_set(viewgroup->border->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE); + /* Box style is more subtle in this case. */ + RNA_enum_set(viewgroup->border->ptr, "draw_style", ED_MANIPULATOR_CAGE2D_STYLE_BOX); + + + mgroup->customdata = viewgroup; +} + +static void WIDGETGROUP_camera_view_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct CameraViewWidgetGroup *viewgroup = mgroup->customdata; + + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + if (rv3d->persp == RV3D_CAMOB) { + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewgroup->state.view_border, false); + } + else { + viewgroup->state.view_border = (rctf){.xmin = 0, .ymin = 0, .xmax = ar->winx, .ymax = ar->winy}; + } + + wmManipulator *mpr = viewgroup->border; + unit_m4(mpr->matrix_space); + mul_v3_fl(mpr->matrix_space[0], BLI_rctf_size_x(&viewgroup->state.view_border)); + mul_v3_fl(mpr->matrix_space[1], BLI_rctf_size_y(&viewgroup->state.view_border)); + mpr->matrix_space[3][0] = viewgroup->state.view_border.xmin; + mpr->matrix_space[3][1] = viewgroup->state.view_border.ymin; +} + +static void WIDGETGROUP_camera_view_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct CameraViewWidgetGroup *viewgroup = mgroup->customdata; + + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + Scene *scene = CTX_data_scene(C); + + { + wmManipulator *mpr = viewgroup->border; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + + RNA_enum_set(viewgroup->border->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE); + + if (rv3d->persp == RV3D_CAMOB) { + viewgroup->state.edit_border = &scene->r.border; + } + else { + viewgroup->state.edit_border = &v3d->render_border; + } + + WM_manipulator_target_property_def_func( + mpr, "matrix", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_render_border_prop_matrix_get, + .value_set_fn = manipulator_render_border_prop_matrix_set, + .range_get_fn = NULL, + .user_data = viewgroup, + }); + } + +} + +void VIEW3D_WGT_camera_view(wmManipulatorGroupType *wgt) +{ + wgt->name = "Camera View Widgets"; + wgt->idname = "VIEW3D_WGT_camera_view"; + + wgt->flag = (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_SCALE); + + wgt->poll = WIDGETGROUP_camera_view_poll; + wgt->setup = WIDGETGROUP_camera_view_setup; + wgt->draw_prepare = WIDGETGROUP_camera_view_draw_prepare; + wgt->refresh = WIDGETGROUP_camera_view_refresh; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_manipulator_empty.c b/source/blender/editors/space_view3d/view3d_manipulator_empty.c new file mode 100644 index 00000000000..1d56c5ee7f4 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_empty.c @@ -0,0 +1,196 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_manipulator_empty.c + * \ingroup spview3d + */ + + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_object.h" +#include "BKE_image.h" + +#include "DNA_object_types.h" +#include "DNA_lamp_types.h" + +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +#include "UI_resources.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "view3d_intern.h" /* own include */ + +/* -------------------------------------------------------------------- */ + +/** \name Empty Image Manipulators + * \{ */ + +struct EmptyImageWidgetGroup { + wmManipulator *manipulator; + struct { + Object *ob; + float dims[2]; + } state; +}; + +/* translate callbacks */ +static void manipulator_empty_image_prop_matrix_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + struct EmptyImageWidgetGroup *imgroup = mpr_prop->custom_func.user_data; + const Object *ob = imgroup->state.ob; + + unit_m4(matrix); + matrix[0][0] = ob->empty_drawsize; + matrix[1][1] = ob->empty_drawsize; + + float dims[2] = {0.0f, 0.0f}; + RNA_float_get_array(mpr->ptr, "dimensions", dims); + dims[0] *= ob->empty_drawsize; + dims[1] *= ob->empty_drawsize; + + matrix[3][0] = (ob->ima_ofs[0] * dims[0]) + (0.5f * dims[0]); + matrix[3][1] = (ob->ima_ofs[1] * dims[1]) + (0.5f * dims[1]); +} + +static void manipulator_empty_image_prop_matrix_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + const float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + struct EmptyImageWidgetGroup *imgroup = mpr_prop->custom_func.user_data; + Object *ob = imgroup->state.ob; + + ob->empty_drawsize = matrix[0][0]; + + float dims[2]; + RNA_float_get_array(mpr->ptr, "dimensions", dims); + dims[0] *= ob->empty_drawsize; + dims[1] *= ob->empty_drawsize; + + ob->ima_ofs[0] = (matrix[3][0] - (0.5f * dims[0])) / dims[0]; + ob->ima_ofs[1] = (matrix[3][1] - (0.5f * dims[1])) / dims[1]; +} + +static bool WIDGETGROUP_empty_image_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = CTX_data_active_object(C); + + if (ob && ob->type == OB_EMPTY) { + return (ob->empty_drawtype == OB_EMPTY_IMAGE); + } + return false; +} + +static void WIDGETGROUP_empty_image_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + struct EmptyImageWidgetGroup *imgroup = MEM_mallocN(sizeof(struct EmptyImageWidgetGroup), __func__); + imgroup->manipulator = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL); + wmManipulator *mpr = imgroup->manipulator; + RNA_enum_set(mpr->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE); + + mgroup->customdata = imgroup; + + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_HOVER, true); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); +} + +static void WIDGETGROUP_empty_image_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct EmptyImageWidgetGroup *imgroup = mgroup->customdata; + Object *ob = CTX_data_active_object(C); + wmManipulator *mpr = imgroup->manipulator; + + copy_m4_m4(mpr->matrix_basis, ob->obmat); + + RNA_enum_set(mpr->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE | + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM); + + imgroup->state.ob = ob; + + /* Use dimensions for aspect. */ + if (ob->data != NULL) { + const Image *image = ob->data; + ImageUser iuser = *ob->iuser; + float size[2]; + BKE_image_get_size_fl(ob->data, &iuser, size); + + /* Get the image aspect even if the buffer is invalid */ + if (image->aspx > image->aspy) { + size[1] *= image->aspy / image->aspx; + } + else if (image->aspx < image->aspy) { + size[0] *= image->aspx / image->aspy; + } + + const float dims_max = max_ff(size[0], size[1]); + imgroup->state.dims[0] = size[0] / dims_max; + imgroup->state.dims[1] = size[1] / dims_max; + } + else { + copy_v2_fl(imgroup->state.dims, 1.0f); + } + RNA_float_set_array(mpr->ptr, "dimensions", imgroup->state.dims); + + WM_manipulator_target_property_def_func( + mpr, "matrix", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_empty_image_prop_matrix_get, + .value_set_fn = manipulator_empty_image_prop_matrix_set, + .range_get_fn = NULL, + .user_data = imgroup, + }); +} + +void VIEW3D_WGT_empty_image(wmManipulatorGroupType *wgt) +{ + wgt->name = "Area Lamp Widgets"; + wgt->idname = "VIEW3D_WGT_empty_image"; + + wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D | + WM_MANIPULATORGROUPTYPE_DEPTH_3D); + + wgt->poll = WIDGETGROUP_empty_image_poll; + wgt->setup = WIDGETGROUP_empty_image_setup; + wgt->refresh = WIDGETGROUP_empty_image_refresh; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c new file mode 100644 index 00000000000..6a34f493caf --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c @@ -0,0 +1,118 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_manipulator_forcefield.c + * \ingroup spview3d + */ + + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_object.h" + +#include "DNA_object_types.h" +#include "DNA_object_force.h" + +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +#include "UI_resources.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "view3d_intern.h" /* own include */ + +/* -------------------------------------------------------------------- */ + +/** \name Force Field Manipulators + * \{ */ + +static bool WIDGETGROUP_forcefield_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = CTX_data_active_object(C); + + return (ob && ob->pd && ob->pd->forcefield); +} + +static void WIDGETGROUP_forcefield_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + /* only wind effector for now */ + wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__); + mgroup->customdata = wwrapper; + + wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL); + wmManipulator *mpr = wwrapper->manipulator; + RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED); + ED_manipulator_arrow3d_set_ui_range(mpr, -200.0f, 200.0f); + ED_manipulator_arrow3d_set_range_fac(mpr, 6.0f); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); +} + +static void WIDGETGROUP_forcefield_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = mgroup->customdata; + wmManipulator *mpr = wwrapper->manipulator; + Object *ob = CTX_data_active_object(C); + PartDeflect *pd = ob->pd; + + if (pd->forcefield == PFIELD_WIND) { + const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f; + const float ofs[3] = {0.0f, -size, 0.0f}; + PointerRNA field_ptr; + + RNA_pointer_create(&ob->id, &RNA_FieldSettings, pd, &field_ptr); + WM_manipulator_set_matrix_location(mpr, ob->obmat[3]); + WM_manipulator_set_matrix_rotation_from_z_axis(mpr, ob->obmat[2]); + WM_manipulator_set_matrix_offset_location(mpr, ofs); + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + WM_manipulator_target_property_def_rna(mpr, "offset", &field_ptr, "strength", -1); + } + else { + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); + } +} + +void VIEW3D_WGT_force_field(wmManipulatorGroupType *wgt) +{ + wgt->name = "Force Field Widgets"; + wgt->idname = "VIEW3D_WGT_force_field"; + + wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D | + WM_MANIPULATORGROUPTYPE_SCALE | + WM_MANIPULATORGROUPTYPE_DEPTH_3D); + + wgt->poll = WIDGETGROUP_forcefield_poll; + wgt->setup = WIDGETGROUP_forcefield_setup; + wgt->refresh = WIDGETGROUP_forcefield_refresh; +} + +/** \} */ + diff --git a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c new file mode 100644 index 00000000000..93b6b69a105 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c @@ -0,0 +1,289 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_manipulator_lamp.c + * \ingroup spview3d + */ + + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_object.h" + +#include "DNA_object_types.h" +#include "DNA_lamp_types.h" + +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +#include "UI_resources.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "view3d_intern.h" /* own include */ + +/* -------------------------------------------------------------------- */ + +/** \name Spot Lamp Manipulators + * \{ */ + +static bool WIDGETGROUP_lamp_spot_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = CTX_data_active_object(C); + + if (ob && ob->type == OB_LAMP) { + Lamp *la = ob->data; + return (la->type == LA_SPOT); + } + return false; +} + +static void WIDGETGROUP_lamp_spot_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__); + + wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL); + wmManipulator *mpr = wwrapper->manipulator; + RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_INVERTED); + + mgroup->customdata = wwrapper; + + ED_manipulator_arrow3d_set_range_fac(mpr, 4.0f); + + UI_GetThemeColor3fv(TH_MANIPULATOR_SECONDARY, mpr->color); +} + +static void WIDGETGROUP_lamp_spot_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = mgroup->customdata; + wmManipulator *mpr = wwrapper->manipulator; + Object *ob = CTX_data_active_object(C); + Lamp *la = ob->data; + float dir[3]; + + negate_v3_v3(dir, ob->obmat[2]); + + WM_manipulator_set_matrix_rotation_from_z_axis(mpr, dir); + WM_manipulator_set_matrix_location(mpr, ob->obmat[3]); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + PointerRNA lamp_ptr; + const char *propname = "spot_size"; + RNA_pointer_create(&la->id, &RNA_Lamp, la, &lamp_ptr); + WM_manipulator_target_property_def_rna(mpr, "offset", &lamp_ptr, propname, -1); +} + +void VIEW3D_WGT_lamp_spot(wmManipulatorGroupType *wgt) +{ + wgt->name = "Spot Lamp Widgets"; + wgt->idname = "VIEW3D_WGT_lamp_spot"; + + wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D | + WM_MANIPULATORGROUPTYPE_DEPTH_3D); + + wgt->poll = WIDGETGROUP_lamp_spot_poll; + wgt->setup = WIDGETGROUP_lamp_spot_setup; + wgt->refresh = WIDGETGROUP_lamp_spot_refresh; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Area Lamp Manipulators + * \{ */ + +/* scale callbacks */ +static void manipulator_area_lamp_prop_matrix_get( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + void *value_p) +{ + BLI_assert(mpr_prop->type->array_length == 16); + float (*matrix)[4] = value_p; + const Lamp *la = mpr_prop->custom_func.user_data; + + matrix[0][0] = la->area_size; + matrix[1][1] = (la->area_shape == LA_AREA_RECT) ? la->area_sizey : la->area_size; +} + +static void manipulator_area_lamp_prop_matrix_set( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + const float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + Lamp *la = mpr_prop->custom_func.user_data; + + if (la->area_shape == LA_AREA_RECT) { + la->area_size = len_v3(matrix[0]); + la->area_sizey = len_v3(matrix[1]); + } + else { + la->area_size = len_v3(matrix[0]); + } +} + +static bool WIDGETGROUP_lamp_area_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = CTX_data_active_object(C); + + if (ob && ob->type == OB_LAMP) { + Lamp *la = ob->data; + return (la->type == LA_AREA); + } + return false; +} + +static void WIDGETGROUP_lamp_area_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__); + wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL); + wmManipulator *mpr = wwrapper->manipulator; + RNA_enum_set(mpr->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE); + + mgroup->customdata = wwrapper; + + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_HOVER, true); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); +} + +static void WIDGETGROUP_lamp_area_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = mgroup->customdata; + Object *ob = CTX_data_active_object(C); + Lamp *la = ob->data; + wmManipulator *mpr = wwrapper->manipulator; + + copy_m4_m4(mpr->matrix_basis, ob->obmat); + + RNA_enum_set(mpr->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE | + ((la->area_shape == LA_AREA_SQUARE) ? ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM : 0)); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + WM_manipulator_target_property_def_func( + mpr, "matrix", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_area_lamp_prop_matrix_get, + .value_set_fn = manipulator_area_lamp_prop_matrix_set, + .range_get_fn = NULL, + .user_data = la, + }); +} + +void VIEW3D_WGT_lamp_area(wmManipulatorGroupType *wgt) +{ + wgt->name = "Area Lamp Widgets"; + wgt->idname = "VIEW3D_WGT_lamp_area"; + + wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D | + WM_MANIPULATORGROUPTYPE_DEPTH_3D); + + wgt->poll = WIDGETGROUP_lamp_area_poll; + wgt->setup = WIDGETGROUP_lamp_area_setup; + wgt->refresh = WIDGETGROUP_lamp_area_refresh; +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Lamp Target Manipulator + * \{ */ + +static bool WIDGETGROUP_lamp_target_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = CTX_data_active_object(C); + + if (ob != NULL) { + if (ob->type == OB_LAMP) { + Lamp *la = ob->data; + return (ELEM(la->type, LA_SUN, LA_SPOT, LA_HEMI, LA_AREA)); + } +#if 0 + else if (ob->type == OB_CAMERA) { + return true; + } +#endif + } + return false; +} + +static void WIDGETGROUP_lamp_target_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__); + wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_grab_3d", mgroup, NULL); + wmManipulator *mpr = wwrapper->manipulator; + + mgroup->customdata = wwrapper; + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); + + mpr->scale_basis = 0.06f; + + wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_transform_axis_target", true); + + RNA_enum_set(mpr->ptr, "draw_options", + ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL | ED_MANIPULATOR_GRAB_DRAW_FLAG_ALIGN_VIEW); + + WM_manipulator_operator_set(mpr, 0, ot, NULL); +} + +static void WIDGETGROUP_lamp_target_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = mgroup->customdata; + Object *ob = CTX_data_active_object(C); + wmManipulator *mpr = wwrapper->manipulator; + + copy_m4_m4(mpr->matrix_basis, ob->obmat); + unit_m4(mpr->matrix_offset); + mpr->matrix_offset[3][2] = -2.4f / mpr->scale_basis; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true); +} + +void VIEW3D_WGT_lamp_target(wmManipulatorGroupType *wgt) +{ + wgt->name = "Target Lamp Widgets"; + wgt->idname = "VIEW3D_WGT_lamp_target"; + + wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D); + + wgt->poll = WIDGETGROUP_lamp_target_poll; + wgt->setup = WIDGETGROUP_lamp_target_setup; + wgt->draw_prepare = WIDGETGROUP_lamp_target_draw_prepare; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c new file mode 100644 index 00000000000..01cf67259a4 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c @@ -0,0 +1,1079 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_manipulator_ruler.c + * \ingroup spview3d + */ + +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_rect.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "BKE_context.h" +#include "BKE_object.h" +#include "BKE_gpencil.h" +#include "BKE_unit.h" + +#include "DNA_object_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_view3d_types.h" + +#include "BIF_gl.h" + +#include "ED_screen.h" +#include "ED_transform_snap_object_context.h" +#include "ED_view3d.h" + +#include "UI_resources.h" +#include "UI_interface.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "view3d_intern.h" /* own include */ + +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_select.h" + +#include "BLF_api.h" + + +static const char *view3d_wgt_ruler_id = "VIEW3D_WGT_ruler"; + + +#define MVAL_MAX_PX_DIST 12.0f + +/* -------------------------------------------------------------------- */ +/* Ruler Item (we can have many) */ +enum { + RULERITEM_USE_ANGLE = (1 << 0), /* use protractor */ + RULERITEM_USE_RAYCAST = (1 << 1) +}; + +enum { + RULERITEM_DIRECTION_IN = 0, + RULERITEM_DIRECTION_OUT +}; + +/* keep smaller then selection, since we may want click elsewhere without selecting a ruler */ +#define RULER_PICK_DIST 12.0f +#define RULER_PICK_DIST_SQ (RULER_PICK_DIST * RULER_PICK_DIST) + +/* not clicking on a point */ +#define PART_LINE 0xff + +/* -------------------------------------------------------------------- */ +/* Ruler Info (wmManipulatorGroup customdata) */ + +enum { + RULER_STATE_NORMAL = 0, + RULER_STATE_DRAG +}; + +enum { + RULER_SNAP_OK = (1 << 0), +}; + +typedef struct RulerInfo { + // ListBase items; + int item_active; + int flag; + int snap_flag; + int state; + + struct SnapObjectContext *snap_context; + + /* wm state */ + wmWindow *win; + ScrArea *sa; + ARegion *ar; /* re-assigned every modal update */ +} RulerInfo; + +/* -------------------------------------------------------------------- */ +/* Ruler Item (two or three points) */ + +typedef struct RulerItem { + wmManipulator mpr; + + /* worldspace coords, middle being optional */ + float co[3][3]; + + int flag; + int raycast_dir; /* RULER_DIRECTION_* */ +} RulerItem; + +typedef struct RulerInteraction { + /* selected coord */ + char co_index; /* 0 -> 2 */ + float drag_start_co[3]; + uint inside_region : 1; +} RulerInteraction; + +/* -------------------------------------------------------------------- */ +/** \name Internal Ruler Utilities + * \{ */ + +static RulerItem *ruler_item_add(wmManipulatorGroup *mgroup) +{ + /* could pass this as an arg */ + const wmManipulatorType *wt_ruler = WM_manipulatortype_find("VIEW3D_WT_ruler_item", true); + RulerItem *ruler_item = (RulerItem *)WM_manipulator_new_ptr(wt_ruler, mgroup, NULL); + WM_manipulator_set_flag(&ruler_item->mpr, WM_MANIPULATOR_DRAW_MODAL, true); + return ruler_item; +} + +static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit, + char *numstr, size_t numstr_size, int prec) +{ + const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0; + + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + const float ruler_angle = angle_v3v3v3(ruler_item->co[0], + ruler_item->co[1], + ruler_item->co[2]); + + if (unit->system == USER_UNIT_NONE) { + BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle)); + } + else { + bUnit_AsString(numstr, numstr_size, + (double)ruler_angle, + prec, unit->system, B_UNIT_ROTATION, do_split, false); + } + } + else { + const float ruler_len = len_v3v3(ruler_item->co[0], + ruler_item->co[2]); + + if (unit->system == USER_UNIT_NONE) { + BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len); + } + else { + bUnit_AsString(numstr, numstr_size, + (double)(ruler_len * unit->scale_length), + prec, unit->system, B_UNIT_LENGTH, do_split, false); + } + } +} + +static bool view3d_ruler_pick( + wmManipulatorGroup *mgroup, RulerItem *ruler_item, const float mval[2], + int *r_co_index) +{ + RulerInfo *ruler_info = mgroup->customdata; + ARegion *ar = ruler_info->ar; + bool found = false; + + float dist_best = RULER_PICK_DIST_SQ; + int co_index_best = -1; + + { + float co_ss[3][2]; + float dist; + int j; + + /* should these be checked? - ok for now not to */ + for (j = 0; j < 3; j++) { + ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP); + } + + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + dist = min_ff(dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[1]), + dist_squared_to_line_segment_v2(mval, co_ss[1], co_ss[2])); + if (dist < dist_best) { + dist_best = dist; + found = true; + + { + const float dist_points[3] = { + len_squared_v2v2(co_ss[0], mval), + len_squared_v2v2(co_ss[1], mval), + len_squared_v2v2(co_ss[2], mval), + }; + if (min_fff(UNPACK3(dist_points)) < RULER_PICK_DIST_SQ) { + co_index_best = min_axis_v3(dist_points); + } + else { + co_index_best = -1; + } + } + } + } + else { + dist = dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[2]); + if (dist < dist_best) { + dist_best = dist; + found = true; + + { + const float dist_points[2] = { + len_squared_v2v2(co_ss[0], mval), + len_squared_v2v2(co_ss[2], mval), + }; + if (min_ff(UNPACK2(dist_points)) < RULER_PICK_DIST_SQ) { + co_index_best = (dist_points[0] < dist_points[1]) ? 0 : 2; + } + else { + co_index_best = -1; + } + } + } + } + } + + *r_co_index = co_index_best; + return found; +} + +/** + * Ensure the 'snap_context' is only cached while dragging, + * needed since the user may toggle modes between tool use. + */ +static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) +{ + if (state == ruler_info->state) { + return; + } + + /* always remove */ + if (ruler_info->snap_context) { + ED_transform_snap_object_context_destroy(ruler_info->snap_context); + ruler_info->snap_context = NULL; + } + + if (state == RULER_STATE_NORMAL) { + /* pass */ + } + else if (state == RULER_STATE_DRAG) { + ruler_info->snap_context = ED_transform_snap_object_context_create_view3d( + CTX_data_main(C), CTX_data_scene(C), CTX_data_scene_layer(C), CTX_data_engine(C), 0, + ruler_info->ar, CTX_wm_view3d(C)); + } + else { + BLI_assert(0); + } + + ruler_info->state = state; +} + +static void view3d_ruler_item_project( + RulerInfo *ruler_info, float r_co[3], + const int xy[2]) +{ + ED_view3d_win_to_3d_int(ruler_info->sa->spacedata.first, ruler_info->ar, r_co, xy, r_co); +} + +/* use for mousemove events */ +static bool view3d_ruler_item_mousemove( + RulerInfo *ruler_info, RulerItem *ruler_item, const int mval[2], + const bool do_thickness, const bool do_snap) +{ + RulerInteraction *inter = ruler_item->mpr.interaction_data; + const float eps_bias = 0.0002f; + float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */ + + ruler_info->snap_flag &= ~RULER_SNAP_OK; + + if (ruler_item) { + float *co = ruler_item->co[inter->co_index]; + /* restore the initial depth */ + copy_v3_v3(co, inter->drag_start_co); + view3d_ruler_item_project(ruler_info, co, mval); + if (do_thickness && inter->co_index != 1) { + // Scene *scene = CTX_data_scene(C); + // View3D *v3d = ruler_info->sa->spacedata.first; + const float mval_fl[2] = {UNPACK2(mval)}; + float ray_normal[3]; + float ray_start[3]; + float *co_other; + + co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0]; + + if (ED_transform_snap_object_project_view3d_mixed( + ruler_info->snap_context, + SCE_SELECT_FACE, + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + .use_object_edit_cage = true, + }, + mval_fl, &dist_px, true, + co, ray_normal)) + { + negate_v3(ray_normal); + /* add some bias */ + madd_v3_v3v3fl(ray_start, co, ray_normal, eps_bias); + ED_transform_snap_object_project_ray( + ruler_info->snap_context, + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + .use_object_edit_cage = true, + }, + ray_start, ray_normal, NULL, + co_other, NULL); + } + } + else if (do_snap) { + // Scene *scene = CTX_data_scene(C); + View3D *v3d = ruler_info->sa->spacedata.first; + const float mval_fl[2] = {UNPACK2(mval)}; + bool use_depth = (v3d->drawtype >= OB_SOLID); + + if (ED_transform_snap_object_project_view3d_mixed( + ruler_info->snap_context, + (SCE_SELECT_VERTEX | SCE_SELECT_EDGE) | (use_depth ? SCE_SELECT_FACE : 0), + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + .use_object_edit_cage = true, + }, + mval_fl, &dist_px, use_depth, + co, NULL)) + { + ruler_info->snap_flag |= RULER_SNAP_OK; + } + } + return true; + } + else { + return false; + } +} + + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Ruler/Grease Pencil Conversion + * \{ */ + +#define RULER_ID "RulerData3D" +static bool view3d_ruler_to_gpencil(bContext *C, wmManipulatorGroup *mgroup) +{ + // RulerInfo *ruler_info = mgroup->customdata; + Scene *scene = CTX_data_scene(C); + bGPDlayer *gpl; + bGPDframe *gpf; + bGPDstroke *gps; + bGPDpalette *palette; + bGPDpalettecolor *palcolor; + RulerItem *ruler_item; + const char *ruler_name = RULER_ID; + bool changed = false; + + if (scene->gpd == NULL) { + scene->gpd = BKE_gpencil_data_addnew("GPencil"); + } + + gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); + if (gpl == NULL) { + gpl = BKE_gpencil_layer_addnew(scene->gpd, ruler_name, false); + gpl->thickness = 1; + gpl->flag |= GP_LAYER_HIDE; + } + + /* try to get active palette or create a new one */ + palette = BKE_gpencil_palette_getactive(scene->gpd); + if (palette == NULL) { + palette = BKE_gpencil_palette_addnew(scene->gpd, DATA_("GP_Palette"), true); + } + /* try to get color with the ruler name or create a new one */ + palcolor = BKE_gpencil_palettecolor_getbyname(palette, (char *)ruler_name); + if (palcolor == NULL) { + palcolor = BKE_gpencil_palettecolor_addnew(palette, (char *)ruler_name, true); + } + + gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true); + BKE_gpencil_free_strokes(gpf); + + for (ruler_item = mgroup->manipulators.first; ruler_item; ruler_item = (RulerItem *)ruler_item->mpr.next) { + bGPDspoint *pt; + int j; + + /* allocate memory for a new stroke */ + gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + gps->totpoints = 3; + pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + for (j = 0; j < 3; j++) { + copy_v3_v3(&pt->x, ruler_item->co[j]); + pt->pressure = 1.0f; + pt->strength = 1.0f; + pt++; + } + } + else { + gps->totpoints = 2; + pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + for (j = 0; j < 3; j += 2) { + copy_v3_v3(&pt->x, ruler_item->co[j]); + pt->pressure = 1.0f; + pt->strength = 1.0f; + pt++; + } + } + gps->flag = GP_STROKE_3DSPACE; + gps->thickness = 3; + /* assign color to stroke */ + BLI_strncpy(gps->colorname, palcolor->info, sizeof(gps->colorname)); + gps->palcolor = palcolor; + BLI_addtail(&gpf->strokes, gps); + changed = true; + } + + return changed; +} + +static bool view3d_ruler_from_gpencil(const bContext *C, wmManipulatorGroup *mgroup) +{ + Scene *scene = CTX_data_scene(C); + bool changed = false; + + if (scene->gpd) { + bGPDlayer *gpl; + const char *ruler_name = RULER_ID; + gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); + if (gpl) { + bGPDframe *gpf; + gpf = BKE_gpencil_layer_getframe(gpl, CFRA, false); + if (gpf) { + bGPDstroke *gps; + for (gps = gpf->strokes.first; gps; gps = gps->next) { + bGPDspoint *pt = gps->points; + int j; + RulerItem *ruler_item = NULL; + if (gps->totpoints == 3) { + ruler_item = ruler_item_add(mgroup); + for (j = 0; j < 3; j++) { + copy_v3_v3(ruler_item->co[j], &pt->x); + pt++; + } + ruler_item->flag |= RULERITEM_USE_ANGLE; + changed = true; + } + else if (gps->totpoints == 2) { + ruler_item = ruler_item_add(mgroup); + for (j = 0; j < 3; j += 2) { + copy_v3_v3(ruler_item->co[j], &pt->x); + pt++; + } + changed = true; + } + } + } + } + } + + return changed; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Ruler Item Manipulator Type + * \{ */ + +static void manipulator_ruler_draw(const bContext *C, wmManipulator *mpr) +{ + Scene *scene = CTX_data_scene(C); + UnitSettings *unit = &scene->unit; + RulerInfo *ruler_info = mpr->parent_mgroup->customdata; + RulerItem *ruler_item = (RulerItem *)mpr; + ARegion *ar = ruler_info->ar; + RegionView3D *rv3d = ar->regiondata; + const float cap_size = 4.0f; + const float bg_margin = 4.0f * U.pixelsize; + const float bg_radius = 4.0f * U.pixelsize; + const float arc_size = 64.0f * U.pixelsize; +#define ARC_STEPS 24 + const int arc_steps = ARC_STEPS; + const float color_act[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const float color_base[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + unsigned char color_text[3]; + unsigned char color_wire[3]; + float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f}; + + /* anti-aliased lines for more consistent appearance */ + glEnable(GL_LINE_SMOOTH); + + BLF_enable(blf_mono_font, BLF_ROTATION); + BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi); + BLF_rotation(blf_mono_font, 0.0f); + + UI_GetThemeColor3ubv(TH_TEXT, color_text); + UI_GetThemeColor3ubv(TH_WIRE, color_wire); + + const bool is_act = (mpr->flag & WM_MANIPULATOR_DRAW_HOVER); + float dir_ruler[2]; + float co_ss[3][2]; + int j; + + /* should these be checked? - ok for now not to */ + for (j = 0; j < 3; j++) { + ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP); + } + + glEnable(GL_BLEND); + + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 2); /* "advanced" mode */ + const float *col = is_act ? color_act : color_base; + immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2); + immUniform1f("dash_width", 6.0f); + + immBegin(GWN_PRIM_LINE_STRIP, 3); + + immVertex2fv(shdr_pos, co_ss[0]); + immVertex2fv(shdr_pos, co_ss[1]); + immVertex2fv(shdr_pos, co_ss[2]); + + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* arc */ + { + float dir_tmp[3]; + float co_tmp[3]; + float arc_ss_coord[2]; + + float dir_a[3]; + float dir_b[3]; + float quat[4]; + float axis[3]; + float angle; + const float px_scale = (ED_view3d_pixel_size(rv3d, ruler_item->co[1]) * + min_fff(arc_size, + len_v2v2(co_ss[0], co_ss[1]) / 2.0f, + len_v2v2(co_ss[2], co_ss[1]) / 2.0f)); + + sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]); + sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]); + normalize_v3(dir_a); + normalize_v3(dir_b); + + cross_v3_v3v3(axis, dir_a, dir_b); + angle = angle_normalized_v3v3(dir_a, dir_b); + + axis_angle_to_quat(quat, axis, angle / arc_steps); + + copy_v3_v3(dir_tmp, dir_a); + + immUniformColor3ubv(color_wire); + + immBegin(GWN_PRIM_LINE_STRIP, arc_steps + 1); + + for (j = 0; j <= arc_steps; j++) { + madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale); + ED_view3d_project_float_global(ar, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP); + mul_qt_v3(quat, dir_tmp); + + immVertex2fv(shdr_pos, arc_ss_coord); + } + + immEnd(); + } + + /* capping */ + { + float rot_90_vec_a[2]; + float rot_90_vec_b[2]; + float cap[2]; + + sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]); + rot_90_vec_a[0] = -dir_ruler[1]; + rot_90_vec_a[1] = dir_ruler[0]; + normalize_v2(rot_90_vec_a); + + sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]); + rot_90_vec_b[0] = -dir_ruler[1]; + rot_90_vec_b[1] = dir_ruler[0]; + normalize_v2(rot_90_vec_b); + + glEnable(GL_BLEND); + + immUniformColor3ubv(color_wire); + + immBegin(GWN_PRIM_LINES, 8); + + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size); + immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size); + immVertex2fv(shdr_pos, cap); + + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size); + immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size); + immVertex2fv(shdr_pos, cap); + + /* angle vertex */ + immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); + immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); + immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); + immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); + + immEnd(); + + glDisable(GL_BLEND); + } + + immUnbindProgram(); + + /* text */ + { + char numstr[256]; + float numstr_size[2]; + float posit[2]; + const int prec = 2; /* XXX, todo, make optional */ + + ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); + + BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); + + posit[0] = co_ss[1][0] + (cap_size * 2.0f); + posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f); + + /* draw text (bg) */ + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_aa( + true, + posit[0] - bg_margin, posit[1] - bg_margin, + posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1], + bg_radius, color_back); + /* draw text */ + BLF_color3ubv(blf_mono_font, color_text); + BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); + BLF_rotation(blf_mono_font, 0.0f); + BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + } + } + else { + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 2); /* "advanced" mode */ + const float *col = is_act ? color_act : color_base; + immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2); + immUniform1f("dash_width", 6.0f); + + immBegin(GWN_PRIM_LINES, 2); + + immVertex2fv(shdr_pos, co_ss[0]); + immVertex2fv(shdr_pos, co_ss[2]); + + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); + + /* capping */ + { + float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]}; + float cap[2]; + + normalize_v2(rot_90_vec); + + glEnable(GL_BLEND); + + immUniformColor3ubv(color_wire); + + immBegin(GWN_PRIM_LINES, 4); + + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size); + immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size); + immVertex2fv(shdr_pos, cap); + + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size); + immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size); + immVertex2fv(shdr_pos, cap); + + immEnd(); + + glDisable(GL_BLEND); + } + + immUnbindProgram(); + + /* text */ + { + char numstr[256]; + float numstr_size[2]; + const int prec = 6; /* XXX, todo, make optional */ + float posit[2]; + + ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); + + BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); + + mid_v2_v2v2(posit, co_ss[0], co_ss[2]); + + /* center text */ + posit[0] -= numstr_size[0] / 2.0f; + posit[1] -= numstr_size[1] / 2.0f; + + /* draw text (bg) */ + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_aa( + true, + posit[0] - bg_margin, posit[1] - bg_margin, + posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1], + bg_radius, color_back); + /* draw text */ + BLF_color3ubv(blf_mono_font, color_text); + BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); + BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + } + } + + glDisable(GL_LINE_SMOOTH); + + BLF_disable(blf_mono_font, BLF_ROTATION); + +#undef ARC_STEPS + + /* draw snap */ + if ((ruler_info->snap_flag & RULER_SNAP_OK) && + (ruler_info->state == RULER_STATE_DRAG) && + (ruler_item->mpr.interaction_data != NULL)) + { + RulerInteraction *inter = ruler_item->mpr.interaction_data; + /* size from drawSnapping */ + const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); + float co_ss_snap[3]; + ED_view3d_project_float_global(ar, ruler_item->co[inter->co_index], co_ss_snap, V3D_PROJ_TEST_NOP); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv(color_act); + + imm_draw_circle_wire_2d(pos, co_ss_snap[0], co_ss_snap[1], size * U.pixelsize, 32); + + immUnbindProgram(); + } +} + +static int manipulator_ruler_test_select( + bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event) +{ + RulerItem *ruler_item_pick = (RulerItem *)mpr; + float mval_fl[2] = {UNPACK2(event->mval)}; + int co_index; + + /* select and drag */ + if (view3d_ruler_pick(mpr->parent_mgroup, ruler_item_pick, mval_fl, &co_index)) { + if (co_index == -1) { + if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) { + return PART_LINE; + } + } + else { + return co_index; + } + } + return -1; +} + +static int manipulator_ruler_modal( + bContext *C, wmManipulator *mpr, const wmEvent *event, + eWM_ManipulatorTweak UNUSED(tweak_flag)) +{ + bool do_draw = false; + int exit_code = OPERATOR_RUNNING_MODAL; + RulerInfo *ruler_info = mpr->parent_mgroup->customdata; + RulerItem *ruler_item = (RulerItem *)mpr; + RulerInteraction *inter = ruler_item->mpr.interaction_data; + ARegion *ar = CTX_wm_region(C); + + ruler_info->ar = ar; + + switch (event->type) { + case MOUSEMOVE: + { + if (ruler_info->state == RULER_STATE_DRAG) { + if (view3d_ruler_item_mousemove( + ruler_info, ruler_item, event->mval, + event->shift != 0, event->ctrl != 0)) + { + do_draw = true; + } + inter->inside_region = BLI_rcti_isect_pt_v(&ar->winrct, &event->x); + } + break; + } + } + if (do_draw) { + ED_region_tag_redraw(ar); + } + return exit_code; +} + +static int manipulator_ruler_invoke( + bContext *C, wmManipulator *mpr, const wmEvent *event) +{ + wmManipulatorGroup *mgroup = mpr->parent_mgroup; + RulerInfo *ruler_info = mgroup->customdata; + RulerItem *ruler_item_pick = (RulerItem *)mpr; + RulerInteraction *inter = MEM_callocN(sizeof(RulerInteraction), __func__); + mpr->interaction_data = inter; + + ARegion *ar = ruler_info->ar; + + const float mval_fl[2] = {UNPACK2(event->mval)}; + + /* select and drag */ + if (mpr->highlight_part == PART_LINE) { + if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) { + /* Add Center Point */ + ruler_item_pick->flag |= RULERITEM_USE_ANGLE; + inter->co_index = 1; + ruler_state_set(C, ruler_info, RULER_STATE_DRAG); + + /* find the factor */ + { + float co_ss[2][2]; + float fac; + + ED_view3d_project_float_global(ar, ruler_item_pick->co[0], co_ss[0], V3D_PROJ_TEST_NOP); + ED_view3d_project_float_global(ar, ruler_item_pick->co[2], co_ss[1], V3D_PROJ_TEST_NOP); + + fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]); + CLAMP(fac, 0.0f, 1.0f); + + interp_v3_v3v3(ruler_item_pick->co[1], + ruler_item_pick->co[0], + ruler_item_pick->co[2], fac); + } + + /* update the new location */ + view3d_ruler_item_mousemove( + ruler_info, ruler_item_pick, event->mval, + event->shift != 0, event->ctrl != 0); + } + } + else { + inter->co_index = mpr->highlight_part; + ruler_state_set(C, ruler_info, RULER_STATE_DRAG); + + /* store the initial depth */ + copy_v3_v3(inter->drag_start_co, ruler_item_pick->co[inter->co_index]); + } + + return OPERATOR_RUNNING_MODAL; +} + +static void manipulator_ruler_exit(bContext *C, wmManipulator *mpr, const bool cancel) +{ + wmManipulatorGroup *mgroup = mpr->parent_mgroup; + RulerInfo *ruler_info = mgroup->customdata; + RulerItem *ruler_item = (RulerItem *)mpr; + RulerInteraction *inter = mpr->interaction_data; + + if (!cancel) { + if (ruler_info->state == RULER_STATE_DRAG) { + /* rubber-band angle removal */ + if (ruler_item && (inter->co_index == 1) && (ruler_item->flag & RULERITEM_USE_ANGLE)) { + if (!inter->inside_region) { + ruler_item->flag &= ~RULERITEM_USE_ANGLE; + } + } + if (ruler_info->snap_flag & RULER_SNAP_OK) { + ruler_info->snap_flag &= ~RULER_SNAP_OK; + } + ruler_state_set(C, ruler_info, RULER_STATE_NORMAL); + } + /* We could convert only the current manipulator, for now just re-generate. */ + view3d_ruler_to_gpencil(C, mgroup); + } + + MEM_SAFE_FREE(mpr->interaction_data); + + ruler_state_set(C, ruler_info, RULER_STATE_NORMAL); +} + +static int manipulator_ruler_cursor_get(wmManipulator *mpr) +{ + if (mpr->highlight_part == PART_LINE) { + return BC_CROSSCURSOR; + } + return BC_NSEW_SCROLLCURSOR; +} + +void VIEW3D_WT_ruler_item(wmManipulatorType *wt) +{ + /* identifiers */ + wt->idname = "VIEW3D_WT_ruler_item"; + + /* api callbacks */ + wt->draw = manipulator_ruler_draw; + wt->test_select = manipulator_ruler_test_select; + wt->modal = manipulator_ruler_modal; + wt->invoke = manipulator_ruler_invoke; + wt->exit = manipulator_ruler_exit; + wt->cursor_get = manipulator_ruler_cursor_get; + + wt->struct_size = sizeof(RulerItem); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Ruler Manipulator Group + * \{ */ + +static bool WIDGETGROUP_ruler_poll(const bContext *C, wmManipulatorGroupType *wgt) +{ + WorkSpace *workspace = CTX_wm_workspace(C); + if (!STREQ(wgt->idname, workspace->tool.manipulator_group)) { + WM_manipulator_group_type_unlink_delayed_ptr(wgt); + return false; + } + return true; +} + +static void WIDGETGROUP_ruler_setup(const bContext *C, wmManipulatorGroup *mgroup) +{ + RulerInfo *ruler_info = MEM_callocN(sizeof(RulerInfo), __func__); + + if (view3d_ruler_from_gpencil(C, mgroup)) { + /* nop */ + } + + wmWindow *win = CTX_wm_window(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + ruler_info->win = win; + ruler_info->sa = sa; + ruler_info->ar = ar; + + mgroup->customdata = ruler_info; +} + +void VIEW3D_WGT_ruler(wmManipulatorGroupType *wgt) +{ + wgt->name = "Ruler Widgets"; + wgt->idname = view3d_wgt_ruler_id; + + wgt->flag |= WM_MANIPULATORGROUPTYPE_SCALE; + + wgt->mmap_params.spaceid = SPACE_VIEW3D; + wgt->mmap_params.regionid = RGN_TYPE_WINDOW; + + wgt->poll = WIDGETGROUP_ruler_poll; + wgt->setup = WIDGETGROUP_ruler_setup; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Add Ruler Operator + * \{ */ + +static int view3d_ruler_poll(bContext *C) +{ + WorkSpace *workspace = CTX_wm_workspace(C); + if (!STREQ(view3d_wgt_ruler_id, workspace->tool.manipulator_group) || + CTX_wm_region_view3d(C) == NULL) + { + return false; + } + return true; +} + +static int view3d_ruler_add_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = ar->regiondata; + + wmManipulatorMap *mmap = ar->manipulator_map; + wmManipulatorGroup *mgroup = WM_manipulatormap_group_find(mmap, view3d_wgt_ruler_id); + const bool use_depth = (v3d->drawtype >= OB_SOLID); + + /* Create new line */ + RulerItem *ruler_item; + ruler_item = ruler_item_add(mgroup); + + /* This is a little weak, but there is no real good way to tweak directly. */ + WM_manipulator_highlight_set(mmap, &ruler_item->mpr); + if (WM_operator_name_call( + C, "MANIPULATORGROUP_OT_manipulator_tweak", + WM_OP_INVOKE_REGION_WIN, NULL) == OPERATOR_RUNNING_MODAL) + { + RulerInfo *ruler_info = mgroup->customdata; + RulerInteraction *inter = ruler_item->mpr.interaction_data; + if (use_depth) { + /* snap the first point added, not essential but handy */ + inter->co_index = 0; + view3d_ruler_item_mousemove(ruler_info, ruler_item, event->mval, false, true); + copy_v3_v3(inter->drag_start_co, ruler_item->co[inter->co_index]); + } + else { + negate_v3_v3(inter->drag_start_co, rv3d->ofs); + copy_v3_v3(ruler_item->co[0], inter->drag_start_co); + view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval); + } + + copy_v3_v3(ruler_item->co[2], ruler_item->co[0]); + ruler_item->mpr.highlight_part = inter->co_index = 2; + } + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_ruler_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Ruler Add"; + ot->idname = "VIEW3D_OT_ruler_add"; + ot->description = ""; + + ot->invoke = view3d_ruler_add_invoke; + ot->poll = view3d_ruler_poll; + + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index d71639c35d2..568343f8ec8 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -119,8 +119,8 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op) if (RNA_boolean_get(op->ptr, "autoselect")) flag |= FILE_AUTOSELECT; - if (RNA_boolean_get(op->ptr, "active_layer")) - flag |= FILE_ACTIVELAY; + if (RNA_boolean_get(op->ptr, "active_collection")) + flag |= FILE_ACTIVE_COLLECTION; BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend"); if (BKE_copybuffer_paste(C, str, flag, op->reports)) { @@ -152,7 +152,7 @@ static void VIEW3D_OT_pastebuffer(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select pasted objects"); - RNA_def_boolean(ot->srna, "active_layer", true, "Active Layer", "Put pasted objects on the active layer"); + RNA_def_boolean(ot->srna, "active_collection", true, "Active Collection", "Put pasted objects on the active collection"); } /* ************************** registration **********************************/ @@ -193,7 +193,6 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_render_border); WM_operatortype_append(VIEW3D_OT_clear_render_border); WM_operatortype_append(VIEW3D_OT_zoom_border); - WM_operatortype_append(VIEW3D_OT_manipulator); WM_operatortype_append(VIEW3D_OT_enable_manipulator); WM_operatortype_append(VIEW3D_OT_cursor3d); WM_operatortype_append(VIEW3D_OT_select_lasso); @@ -201,7 +200,6 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_camera_to_view); WM_operatortype_append(VIEW3D_OT_camera_to_view_selected); WM_operatortype_append(VIEW3D_OT_object_as_camera); - WM_operatortype_append(VIEW3D_OT_localview); WM_operatortype_append(VIEW3D_OT_game_start); WM_operatortype_append(VIEW3D_OT_fly); WM_operatortype_append(VIEW3D_OT_walk); @@ -224,6 +222,8 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_toggle_render); + WM_operatortype_append(VIEW3D_OT_ruler_add); + transform_operatortypes(); } @@ -240,24 +240,7 @@ void view3d_keymap(wmKeyConfig *keyconf) /* only for region 3D window */ keymap = WM_keymap_find(keyconf, "3D View", SPACE_VIEW3D, 0); - /* Shift+LMB behavior first, so it has priority over KM_ANY item below. */ - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", true); - RNA_boolean_set(kmi->ptr, "use_accurate", false); - - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", false); - RNA_boolean_set(kmi->ptr, "use_accurate", true); - - /* Using KM_ANY here to allow holding modifiers before starting to transform. */ - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_ANY, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", false); - RNA_boolean_set(kmi->ptr, "use_accurate", false); - - WM_keymap_verify_item(keymap, "VIEW3D_OT_cursor3d", ACTIONMOUSE, KM_PRESS, 0, 0); + WM_keymap_verify_item(keymap, "VIEW3D_OT_cursor3d", ACTIONMOUSE, KM_CLICK, 0, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_rotate", MIDDLEMOUSE, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_move", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0); @@ -372,8 +355,6 @@ void view3d_keymap(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD7, KM_PRESS, KM_SHIFT | KM_CTRL, 0); RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_BOTTOM); RNA_boolean_set(kmi->ptr, "align_active", true); - - WM_keymap_add_item(keymap, "VIEW3D_OT_localview", PADSLASHKEY, KM_PRESS, 0, 0); #ifdef WITH_INPUT_NDOF /* note: positioned here so keymaps show keyboard keys if assigned */ diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 65a6dee2f6c..f8b02f0b405 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -36,14 +36,13 @@ #include "BLI_sys_types.h" /* int64_t */ -#include "BIF_gl.h" /* bglMats */ -#include "BIF_glutil.h" /* bglMats */ - #include "BLI_math_vector.h" #include "BKE_camera.h" #include "BKE_screen.h" +#include "GPU_matrix.h" + #include "ED_view3d.h" /* own include */ #define BL_NEAR_CLIP 0.001 @@ -656,16 +655,22 @@ void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, float obm } /** - * Uses window coordinates (x,y) and depth component z to find a point in - * modelspace */ -void ED_view3d_unproject(bglMats *mats, float out[3], const float x, const float y, const float z) + * Convert between region relative coordinates (x,y) and depth component z and + * a point in world space. */ +void ED_view3d_project(const struct ARegion *ar, const float world[3], float region[3]) { - double ux, uy, uz; + // viewport is set up to make coordinates relative to the region, not window + RegionView3D *rv3d = ar->regiondata; + int viewport[4] = {0, 0, ar->winx, ar->winy}; - gluUnProject(x, y, z, mats->modelview, mats->projection, - (GLint *)mats->viewport, &ux, &uy, &uz); + gpuProject(world, rv3d->viewmat, rv3d->winmat, viewport, region); +} + +bool ED_view3d_unproject(const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3]) +{ + RegionView3D *rv3d = ar->regiondata; + int viewport[4] = {0, 0, ar->winx, ar->winy}; + float region[3] = {regionx, regiony, regionz}; - out[0] = ux; - out[1] = uy; - out[2] = uz; + return gpuUnProject(region, rv3d->viewmat, rv3d->winmat, viewport, world); } diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index f2c87953302..03f4f506c13 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -43,6 +43,9 @@ #include "BIF_gl.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" + #include "WM_api.h" #include "WM_types.h" @@ -279,7 +282,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) } else if (state == RULER_STATE_DRAG) { ruler_info->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), 0, + CTX_data_main(C), CTX_data_scene(C), CTX_data_scene_layer(C), CTX_data_engine(C), 0, ruler_info->ar, CTX_wm_view3d(C)); } else { @@ -425,12 +428,11 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a #define ARC_STEPS 24 const int arc_steps = ARC_STEPS; int i; - //unsigned int color_act = 0x666600; - unsigned int color_act = 0xffffff; - unsigned int color_base = 0x0; - unsigned char color_back[4] = {0xff, 0xff, 0xff, 0x80}; + const float color_act[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const float color_base[4] = {0.0f, 0.0f, 0.0f, 1.0f}; unsigned char color_text[3]; unsigned char color_wire[3]; + float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f}; /* anti-aliased lines for more consistent appearance */ glEnable(GL_LINE_SMOOTH); @@ -455,28 +457,37 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a glEnable(GL_BLEND); - cpack(is_act ? color_act : color_base); + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); if (ruler_item->flag & RULERITEM_USE_ANGLE) { - glBegin(GL_LINE_STRIP); - for (j = 0; j < 3; j++) { - glVertex2fv(co_ss[j]); - } - glEnd(); - cpack(0xaaaaaa); - setlinestyle(3); - glBegin(GL_LINE_STRIP); - for (j = 0; j < 3; j++) { - glVertex2fv(co_ss[j]); - } - glEnd(); - setlinestyle(0); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 2); /* "advanced" mode */ + const float *col = is_act ? color_act : color_base; + immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2); + immUniform1f("dash_width", 6.0f); + + immBegin(GWN_PRIM_LINE_STRIP, 3); + + immVertex2fv(shdr_pos, co_ss[0]); + immVertex2fv(shdr_pos, co_ss[1]); + immVertex2fv(shdr_pos, co_ss[2]); + + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* arc */ { float dir_tmp[3]; float co_tmp[3]; - float arc_ss_coords[ARC_STEPS + 1][2]; + float arc_ss_coord[2]; float dir_a[3]; float dir_b[3]; @@ -500,46 +511,19 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a copy_v3_v3(dir_tmp, dir_a); - glColor3ubv(color_wire); + immUniformColor3ubv(color_wire); + + immBegin(GWN_PRIM_LINE_STRIP, arc_steps + 1); for (j = 0; j <= arc_steps; j++) { madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale); - ED_view3d_project_float_global(ar, co_tmp, arc_ss_coords[j], V3D_PROJ_TEST_NOP); + ED_view3d_project_float_global(ar, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP); mul_qt_v3(quat, dir_tmp); - } - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, arc_ss_coords); - glDrawArrays(GL_LINE_STRIP, 0, arc_steps + 1); - glDisableClientState(GL_VERTEX_ARRAY); - } - /* text */ - { - char numstr[256]; - float numstr_size[2]; - float pos[2]; - const int prec = 2; /* XXX, todo, make optional */ - - ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); - - BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); - - pos[0] = co_ss[1][0] + (cap_size * 2.0f); - pos[1] = co_ss[1][1] - (numstr_size[1] / 2.0f); + immVertex2fv(shdr_pos, arc_ss_coord); + } - /* draw text (bg) */ - glColor4ubv(color_back); - UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox( - pos[0] - bg_margin, pos[1] - bg_margin, - pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1], - bg_radius); - /* draw text */ - glColor3ubv(color_text); - BLF_position(blf_mono_font, pos[0], pos[1], 0.0f); - BLF_rotation(blf_mono_font, 0.0f); - BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + immEnd(); } /* capping */ @@ -560,75 +544,84 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a glEnable(GL_BLEND); - glColor3ubv(color_wire); + immUniformColor3ubv(color_wire); - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, 8); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); /* angle vertex */ - glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); - glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); - glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); - glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); - glEnd(); + immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); + immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); + immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); + immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); + + immEnd(); glDisable(GL_BLEND); } - } - else { - glBegin(GL_LINE_STRIP); - for (j = 0; j < 3; j += 2) { - glVertex2fv(co_ss[j]); - } - glEnd(); - cpack(0xaaaaaa); - setlinestyle(3); - glBegin(GL_LINE_STRIP); - for (j = 0; j < 3; j += 2) { - glVertex2fv(co_ss[j]); - } - glEnd(); - setlinestyle(0); - sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); + immUnbindProgram(); /* text */ { char numstr[256]; float numstr_size[2]; - const int prec = 6; /* XXX, todo, make optional */ - float pos[2]; + float posit[2]; + const int prec = 2; /* XXX, todo, make optional */ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); - mid_v2_v2v2(pos, co_ss[0], co_ss[2]); - - /* center text */ - pos[0] -= numstr_size[0] / 2.0f; - pos[1] -= numstr_size[1] / 2.0f; + posit[0] = co_ss[1][0] + (cap_size * 2.0f); + posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f); /* draw text (bg) */ - glColor4ubv(color_back); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox(pos[0] - bg_margin, pos[1] - bg_margin, - pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1], - bg_radius); + UI_draw_roundbox_aa(true, + posit[0] - bg_margin, posit[1] - bg_margin, + posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1], + bg_radius, color_back); /* draw text */ - glColor3ubv(color_text); - BLF_position(blf_mono_font, pos[0], pos[1], 0.0f); + BLF_color3ubv(blf_mono_font, color_text); + BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); + BLF_rotation(blf_mono_font, 0.0f); BLF_draw(blf_mono_font, numstr, sizeof(numstr)); } + } + else { + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 2); /* "advanced" mode */ + const float *col = is_act ? color_act : color_base; + immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2); + immUniform1f("dash_width", 6.0f); + + immBegin(GWN_PRIM_LINES, 2); + + immVertex2fv(shdr_pos, co_ss[0]); + immVertex2fv(shdr_pos, co_ss[2]); + + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); /* capping */ { @@ -638,22 +631,56 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a normalize_v2(rot_90_vec); glEnable(GL_BLEND); - glColor3ubv(color_wire); - glBegin(GL_LINES); + immUniformColor3ubv(color_wire); + + immBegin(GWN_PRIM_LINES, 4); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size); - glVertex2fv(cap); - glEnd(); + immVertex2fv(shdr_pos, cap); + + immEnd(); glDisable(GL_BLEND); } + + immUnbindProgram(); + + /* text */ + { + char numstr[256]; + float numstr_size[2]; + const int prec = 6; /* XXX, todo, make optional */ + float posit[2]; + + ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); + + BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); + + mid_v2_v2v2(posit, co_ss[0], co_ss[2]); + + /* center text */ + posit[0] -= numstr_size[0] / 2.0f; + posit[1] -= numstr_size[1] / 2.0f; + + /* draw text (bg) */ + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_aa(true, + posit[0] - bg_margin, posit[1] - bg_margin, + posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1], + bg_radius, color_back); + /* draw text */ + BLF_color3ubv(blf_mono_font, color_text); + BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); + BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + } } } @@ -672,8 +699,14 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a float co_ss[3]; ED_view3d_project_float_global(ar, ruler_item->co[ruler_item->co_index], co_ss, V3D_PROJ_TEST_NOP); - cpack(color_act); - circ(co_ss[0], co_ss[1], size * U.pixelsize); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv(color_act); + + imm_draw_circle_wire_2d(pos, co_ss[0], co_ss[1], size * U.pixelsize, 32); + + immUnbindProgram(); } } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 05cf552e5cc..297bd5c4aa1 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -63,16 +63,16 @@ #include "BKE_armature.h" #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" +#include "BKE_layer.h" #include "BKE_mball.h" #include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_editmesh.h" +#include "BKE_scene.h" #include "BKE_tracking.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" +#include "DEG_depsgraph.h" #include "WM_api.h" #include "WM_types.h" @@ -93,6 +93,8 @@ #include "UI_interface.h" #include "GPU_draw.h" +#include "GPU_glew.h" +#include "GPU_matrix.h" #include "view3d_intern.h" /* own include */ @@ -108,7 +110,10 @@ void view3d_set_viewcontext(bContext *C, ViewContext *vc) { memset(vc, 0, sizeof(ViewContext)); vc->ar = CTX_wm_region(C); + vc->depsgraph = CTX_data_depsgraph(C); vc->scene = CTX_data_scene(C); + vc->scene_layer = CTX_data_scene_layer(C); + vc->engine = CTX_data_engine(C); vc->v3d = CTX_wm_view3d(C); vc->win = CTX_wm_window(C); vc->rv3d = CTX_wm_region_view3d(C); @@ -116,34 +121,6 @@ void view3d_set_viewcontext(bContext *C, ViewContext *vc) vc->obedit = CTX_data_edit_object(C); } -/* - * ob == NULL if you want global matrices - * */ -void view3d_get_transformation(const ARegion *ar, RegionView3D *rv3d, Object *ob, bglMats *mats) -{ - float cpy[4][4]; - int i, j; - - if (ob) { - mul_m4_m4m4(cpy, rv3d->viewmat, ob->obmat); - } - else { - copy_m4_m4(cpy, rv3d->viewmat); - } - - for (i = 0; i < 4; ++i) { - for (j = 0; j < 4; ++j) { - mats->projection[i * 4 + j] = rv3d->winmat[i][j]; - mats->modelview[i * 4 + j] = cpy[i][j]; - } - } - - mats->viewport[0] = ar->winrct.xmin; - mats->viewport[1] = ar->winrct.ymin; - mats->viewport[2] = ar->winx; - mats->viewport[3] = ar->winy; -} - /* ********************** view3d_select: selection manipulations ********************* */ /* local prototypes */ @@ -394,18 +371,18 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[] bArmature *arm = ob->data; if (arm->flag & ARM_HAS_VIZ_DEPS) { /* mask modifier ('armature' mode), etc. */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } } -static void object_deselect_all_visible(Scene *scene, View3D *v3d) +static void object_deselect_all_visible(SceneLayer *sl) { Base *base; - for (base = scene->base.first; base; base = base->next) { - if (BASE_SELECTABLE(v3d, base)) { - ED_base_object_select(base, BA_DESELECT); + for (base = sl->object_bases.first; base; base = base->next) { + if (BASE_SELECTABLE(base)) { + ED_object_base_select(base, BA_DESELECT); } } } @@ -416,15 +393,14 @@ static void do_lasso_select_objects(ViewContext *vc, const int mcords[][2], cons Base *base; if (extend == false && select) - object_deselect_all_visible(vc->scene, vc->v3d); + object_deselect_all_visible(vc->scene_layer); - for (base = vc->scene->base.first; base; base = base->next) { - if (BASE_SELECTABLE(vc->v3d, base)) { /* use this to avoid un-needed lasso lookups */ + for (base = vc->scene_layer->object_bases.first; base; base = base->next) { + if (BASE_SELECTABLE(base)) { /* use this to avoid un-needed lasso lookups */ if (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) { if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) { - ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT); - base->object->flag = base->flag; + ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); } } if (vc->obact == base->object && (base->object->mode & OB_MODE_POSE)) { @@ -481,7 +457,9 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, cons } } -static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) +static void do_lasso_select_mesh( + const struct EvaluationContext *eval_ctx, ViewContext *vc, + const int mcords[][2], short moves, bool extend, bool select) { LassoSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; @@ -501,25 +479,25 @@ static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short m /* for non zbuf projections, don't change the GL state */ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - glLoadMatrixf(vc->rv3d->viewmat); - bbsel = EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + gpuLoadMatrix(vc->rv3d->viewmat); + bbsel = EDBM_backbuf_border_mask_init(eval_ctx, vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); if (ts->selectmode & SCE_SELECT_VERTEX) { if (bbsel) { edbm_backbuf_check_and_select_verts(vc->em, select); } else { - mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenVert(eval_ctx, vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } if (ts->selectmode & SCE_SELECT_EDGE) { /* Does both bbsel and non-bbsel versions (need screen cos for both) */ data.pass = 0; - mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); + mesh_foreachScreenEdge(eval_ctx, vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); if (data.is_done == false) { data.pass = 1; - mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); + mesh_foreachScreenEdge(eval_ctx, vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); } } @@ -528,7 +506,7 @@ static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short m edbm_backbuf_check_and_select_faces(vc->em, select); } else { - mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenFace(eval_ctx, vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -727,7 +705,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); } } -static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) +static void do_lasso_select_paintvert(const struct EvaluationContext *eval_ctx, ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) { const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Object *ob = vc->obact; @@ -745,7 +723,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh if (use_zbuf) { bm_vertoffs = me->totvert + 1; /* max index array */ - EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + EDBM_backbuf_border_mask_init(eval_ctx, vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); edbm_backbuf_check_and_select_verts_obmode(me, select); @@ -758,7 +736,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); - meshobject_foreachScreenVert(vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + meshobject_foreachScreenVert(eval_ctx, vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } @@ -767,7 +745,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh } paintvert_flush_flags(ob); } -static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) +static void do_lasso_select_paintface(const struct EvaluationContext *eval_ctx, ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) { Object *ob = vc->obact; Mesh *me = ob->data; @@ -782,7 +760,7 @@ static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], sh bm_vertoffs = me->totpoly + 1; /* max index array */ BLI_lasso_boundbox(&rect, mcords, moves); - EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + EDBM_backbuf_border_mask_init(eval_ctx, vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); edbm_backbuf_check_and_select_tfaces(me, select); @@ -828,16 +806,22 @@ static void view3d_lasso_select(bContext *C, ViewContext *vc, { Object *ob = CTX_data_active_object(C); + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + if (vc->obedit == NULL) { /* Object Mode */ - if (BKE_paint_select_face_test(ob)) - do_lasso_select_paintface(vc, mcords, moves, extend, select); - else if (BKE_paint_select_vert_test(ob)) - do_lasso_select_paintvert(vc, mcords, moves, extend, select); + if (BKE_paint_select_face_test(ob)) { + do_lasso_select_paintface(&eval_ctx, vc, mcords, moves, extend, select); + } + else if (BKE_paint_select_vert_test(ob)) { + do_lasso_select_paintvert(&eval_ctx, vc, mcords, moves, extend, select); + } else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { /* pass */ } - else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) + else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { PE_lasso_select(C, mcords, moves, extend, select); + } else { do_lasso_select_objects(vc, mcords, moves, extend, select); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); @@ -846,7 +830,7 @@ static void view3d_lasso_select(bContext *C, ViewContext *vc, else { /* Edit Mode */ switch (vc->obedit->type) { case OB_MESH: - do_lasso_select_mesh(vc, mcords, moves, extend, select); + do_lasso_select_mesh(&eval_ctx, vc, mcords, moves, extend, select); break; case OB_CURVE: case OB_SURF: @@ -930,7 +914,7 @@ static unsigned int samplerect(unsigned int *buf, int size, unsigned int dontdo) base = LASTBASE; if (base == 0) return 0; - maxob = base->selcol; + maxob = base->object->select_color; len = (size - 1) / 2; rc = 0; @@ -1016,8 +1000,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) if (!toggle) { CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if (base->flag & SELECT) { - ED_base_object_select(base, BA_DESELECT); + if ((base->flag & BASE_SELECTED) != 0) { + ED_object_base_select(base, BA_DESELECT); changed = true; } } @@ -1028,8 +1012,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) { /* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */ if (STREQ(name, base->object->id.name + 2)) { - ED_base_object_activate(C, base); - ED_base_object_select(base, BA_SELECT); + ED_object_base_activate(C, base); + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -1073,14 +1057,12 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot) RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first"); } -static void deselectall_except(Scene *scene, Base *b) /* deselect all except b */ +static void deselectall_except(SceneLayer *sl, Base *b) /* deselect all except b */ { - Base *base; - - for (base = FIRSTBASE; base; base = base->next) { - if (base->flag & SELECT) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if (base->flag & BASE_SELECTED) { if (b != base) { - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); } } } @@ -1093,7 +1075,8 @@ static Base *object_mouse_select_menu( short baseCount = 0; bool ok; LinkNode *linklist = NULL; - + + /* handle base->object->select_color */ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { ok = false; @@ -1102,7 +1085,7 @@ static Base *object_mouse_select_menu( if (buffer) { for (int a = 0; a < hits; a++) { /* index was converted */ - if (base->selcol == (buffer[(4 * a) + 3] & ~0xFFFF0000)) { + if (base->object->select_color == (buffer[(4 * a) + 3] & ~0xFFFF0000)) { ok = true; break; } @@ -1201,7 +1184,7 @@ static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits15, const /* we want a select buffer with bones, if there are... */ /* so check three selection levels and compare */ static int mixed_bones_object_selectbuffer( - ViewContext *vc, unsigned int *buffer, const int mval[2], + const EvaluationContext *eval_ctx, ViewContext *vc, unsigned int *buffer, const int mval[2], bool use_cycle, bool enumerate, bool *r_do_nearest) { @@ -1241,7 +1224,7 @@ static int mixed_bones_object_selectbuffer( view3d_opengl_select_cache_begin(); BLI_rcti_init_pt_radius(&rect, mval, 14); - hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode); + hits15 = view3d_opengl_select(eval_ctx, vc, buffer, MAXPICKBUF, &rect, select_mode); if (hits15 == 1) { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; @@ -1252,7 +1235,7 @@ static int mixed_bones_object_selectbuffer( offs = 4 * hits15; BLI_rcti_init_pt_radius(&rect, mval, 9); - hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); + hits9 = view3d_opengl_select(eval_ctx, vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); if (hits9 == 1) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; @@ -1262,7 +1245,7 @@ static int mixed_bones_object_selectbuffer( offs += 4 * hits9; BLI_rcti_init_pt_radius(&rect, mval, 5); - hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); + hits5 = view3d_opengl_select(eval_ctx, vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); if (hits5 == 1) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; @@ -1291,8 +1274,7 @@ finally: static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits, Base *startbase, bool has_bones, bool do_nearest) { - Scene *scene = vc->scene; - View3D *v3d = vc->v3d; + SceneLayer *sl = vc->scene_layer; Base *base, *basact = NULL; int a; @@ -1312,7 +1294,9 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int } else { /* only exclude active object when it is selected... */ - if (BASACT && (BASACT->flag & SELECT) && hits > 1) notcol = BASACT->selcol; + if (BASACT(sl) && (BASACT(sl)->flag & BASE_SELECTED) && hits > 1) { + notcol = BASACT(sl)->object->select_color; + } for (a = 0; a < hits; a++) { if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) { @@ -1322,10 +1306,10 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int } } - base = FIRSTBASE; + base = FIRSTBASE(sl); while (base) { - if (BASE_SELECTABLE(v3d, base)) { - if (base->selcol == selcol) break; + if (BASE_SELECTABLE(base)) { + if (base->object->select_color == selcol) break; } base = base->next; } @@ -1337,23 +1321,23 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int while (base) { /* skip objects with select restriction, to prevent prematurely ending this loop * with an un-selectable choice */ - if (base->object->restrictflag & OB_RESTRICT_SELECT) { + if ((base->flag & BASE_SELECTABLED) == 0) { base = base->next; - if (base == NULL) base = FIRSTBASE; + if (base == NULL) base = FIRSTBASE(sl); if (base == startbase) break; } - if (BASE_SELECTABLE(v3d, base)) { + if (BASE_SELECTABLE(base)) { for (a = 0; a < hits; a++) { if (has_bones) { /* skip non-bone objects */ if ((buffer[4 * a + 3] & 0xFFFF0000)) { - if (base->selcol == (buffer[(4 * a) + 3] & 0xFFFF)) + if (base->object->select_color == (buffer[(4 * a) + 3] & 0xFFFF)) basact = base; } } else { - if (base->selcol == (buffer[(4 * a) + 3] & 0xFFFF)) + if (base->object->select_color == (buffer[(4 * a) + 3] & 0xFFFF)) basact = base; } } @@ -1362,7 +1346,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int if (basact) break; base = base->next; - if (base == NULL) base = FIRSTBASE; + if (base == NULL) base = FIRSTBASE(sl); if (base == startbase) break; } } @@ -1373,6 +1357,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int /* mval comes from event->mval, only use within region handlers */ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) { + EvaluationContext eval_ctx; ViewContext vc; Base *basact = NULL; unsigned int buffer[MAXPICKBUF]; @@ -1381,13 +1366,15 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) /* setup view context for argument to callbacks */ view3d_operator_needs_opengl(C); + + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); - hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, false, false, &do_nearest); + hits = mixed_bones_object_selectbuffer(&eval_ctx, &vc, buffer, mval, false, false, &do_nearest); if (hits > 0) { const bool has_bones = selectbuffer_has_bones(buffer, hits); - basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.scene->base.first, has_bones, do_nearest); + basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.scene_layer->object_bases.first, has_bones, do_nearest); } return basact; @@ -1417,10 +1404,11 @@ static bool ed_object_select_pick( bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool obcenter, bool enumerate, bool object) { + EvaluationContext eval_ctx; ViewContext vc; ARegion *ar = CTX_wm_region(C); - View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL; bool is_obedit; float dist = ED_view3d_select_dist_px() * 1.3333f; @@ -1430,6 +1418,7 @@ static bool ed_object_select_pick( /* setup view context for argument to callbacks */ + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); is_obedit = (vc.obedit != NULL); @@ -1439,8 +1428,8 @@ static bool ed_object_select_pick( } /* always start list from basact in wire mode */ - startbase = FIRSTBASE; - if (BASACT && BASACT->next) startbase = BASACT->next; + startbase = FIRSTBASE(sl); + if (BASACT(sl) && BASACT(sl)->next) startbase = BASACT(sl)->next; /* This block uses the control key to make the object selected by its center point rather than its contents */ /* in editmode do not activate */ @@ -1453,13 +1442,13 @@ static bool ed_object_select_pick( else { base = startbase; while (base) { - if (BASE_SELECTABLE(v3d, base)) { + if (BASE_SELECTABLE(base)) { float screen_co[2]; if (ED_view3d_project_float_global(ar, base->object->obmat[3], screen_co, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { float dist_temp = len_manhattan_v2v2(mval_fl, screen_co); - if (base == BASACT) dist_temp += 10.0f; + if (base == BASACT(sl)) dist_temp += 10.0f; if (dist_temp < dist) { dist = dist_temp; basact = base; @@ -1468,7 +1457,7 @@ static bool ed_object_select_pick( } base = base->next; - if (base == NULL) base = FIRSTBASE; + if (base == NULL) base = FIRSTBASE(sl); if (base == startbase) break; } } @@ -1480,7 +1469,7 @@ static bool ed_object_select_pick( // TIMEIT_START(select_time); /* if objects have posemode set, the bones are in the same selection buffer */ - hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, true, enumerate, &do_nearest); + hits = mixed_bones_object_selectbuffer(&eval_ctx, &vc, buffer, mval, true, enumerate, &do_nearest); // TIMEIT_END(select_time); @@ -1498,7 +1487,7 @@ static bool ed_object_select_pick( if (has_bones && basact) { if (basact->object->type == OB_CAMERA) { - if (BASACT == basact) { + if (BASACT(sl) == basact) { int i, hitresult; bool changed = false; @@ -1507,7 +1496,7 @@ static bool ed_object_select_pick( /* if there's bundles in buffer select bundles first, * so non-camera elements should be ignored in buffer */ - if (basact->selcol != (hitresult & 0xFFFF)) { + if (basact->object->select_color != (hitresult & 0xFFFF)) { continue; } @@ -1536,8 +1525,8 @@ static bool ed_object_select_pick( changed = true; } - basact->flag |= SELECT; - basact->object->flag = basact->flag; + basact->flag |= BASE_SELECTED; + BKE_scene_object_base_flag_sync_from_base(basact); retval = true; @@ -1555,27 +1544,27 @@ static bool ed_object_select_pick( } } } - else if (ED_do_pose_selectbuffer(scene, basact, buffer, hits, extend, deselect, toggle, do_nearest)) { + else if (ED_do_pose_selectbuffer(scene, sl, basact, buffer, hits, extend, deselect, toggle, do_nearest)) { /* then bone is found */ /* we make the armature selected: * not-selected active object in posemode won't work well for tools */ - basact->flag |= SELECT; - basact->object->flag = basact->flag; + basact->flag |= BASE_SELECTED; + BKE_scene_object_base_flag_sync_from_base(basact); retval = true; WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object); WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object); /* in weightpaint, we use selected bone to select vertexgroup, so no switch to new active object */ - if (BASACT && (BASACT->object->mode & OB_MODE_WEIGHT_PAINT)) { + if (BASACT(sl) && (BASACT(sl)->object->mode & OB_MODE_WEIGHT_PAINT)) { /* prevent activating */ basact = NULL; } } /* prevent bone selecting to pass on to object selecting */ - if (basact == BASACT) + if (basact == BASACT(sl)) basact = NULL; } } @@ -1587,37 +1576,37 @@ static bool ed_object_select_pick( if (vc.obedit) { /* only do select */ - deselectall_except(scene, basact); - ED_base_object_select(basact, BA_SELECT); + deselectall_except(sl, basact); + ED_object_base_select(basact, BA_SELECT); } /* also prevent making it active on mouse selection */ - else if (BASE_SELECTABLE(v3d, basact)) { + else if (BASE_SELECTABLE(basact)) { - oldbasact = BASACT; + oldbasact = BASACT(sl); if (extend) { - ED_base_object_select(basact, BA_SELECT); + ED_object_base_select(basact, BA_SELECT); } else if (deselect) { - ED_base_object_select(basact, BA_DESELECT); + ED_object_base_select(basact, BA_DESELECT); } else if (toggle) { - if (basact->flag & SELECT) { + if (basact->flag & BASE_SELECTED) { if (basact == oldbasact) { - ED_base_object_select(basact, BA_DESELECT); + ED_object_base_select(basact, BA_DESELECT); } } else { - ED_base_object_select(basact, BA_SELECT); + ED_object_base_select(basact, BA_SELECT); } } else { - deselectall_except(scene, basact); - ED_base_object_select(basact, BA_SELECT); + deselectall_except(sl, basact); + ED_object_base_select(basact, BA_SELECT); } if ((oldbasact != basact) && (is_obedit == false)) { - ED_base_object_activate(C, basact); /* adds notifier */ + ED_object_base_activate(C, basact); /* adds notifier */ } } @@ -1673,7 +1662,8 @@ static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, con SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); } } -static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) +static int do_paintvert_box_select( + const EvaluationContext *eval_ctx, ViewContext *vc, rcti *rect, bool select, bool extend) { const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Mesh *me; @@ -1697,7 +1687,7 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo if (use_zbuf) { selar = MEM_callocN(me->totvert + 1, "selar"); - ED_view3d_backbuf_validate(vc); + ED_view3d_backbuf_validate(eval_ctx, vc); ibuf = IMB_allocImBuf(size[0], size[1], 32, IB_rect); rt = ibuf->rect; @@ -1745,7 +1735,7 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); - meshobject_foreachScreenVert(vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + meshobject_foreachScreenVert(eval_ctx, vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } if (select == false) { @@ -1860,7 +1850,8 @@ static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, const BM_face_select_set(data->vc->em->bm, efa, data->select); } } -static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) +static int do_mesh_box_select( + const struct EvaluationContext *eval_ctx, ViewContext *vc, rcti *rect, bool select, bool extend) { BoxSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; @@ -1874,26 +1865,26 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool ext /* for non zbuf projections, don't change the GL state */ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - glLoadMatrixf(vc->rv3d->viewmat); - bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + gpuLoadMatrix(vc->rv3d->viewmat); + bbsel = EDBM_backbuf_border_init(eval_ctx, vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax); if (ts->selectmode & SCE_SELECT_VERTEX) { if (bbsel) { edbm_backbuf_check_and_select_verts(vc->em, select); } else { - mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenVert(eval_ctx, vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } if (ts->selectmode & SCE_SELECT_EDGE) { /* Does both bbsel and non-bbsel versions (need screen cos for both) */ data.pass = 0; - mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); + mesh_foreachScreenEdge(eval_ctx, vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); if (data.is_done == 0) { data.pass = 1; - mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); + mesh_foreachScreenEdge(eval_ctx, vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); } } @@ -1902,7 +1893,7 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool ext edbm_backbuf_check_and_select_faces(vc->em, select); } else { - mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenFace(eval_ctx, vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -1913,7 +1904,9 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool ext return OPERATOR_FINISHED; } -static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) +static int do_meta_box_select( + const struct EvaluationContext *eval_ctx, ViewContext *vc, + const rcti *rect, bool select, bool extend) { MetaBall *mb = (MetaBall *)vc->obedit->data; MetaElem *ml; @@ -1922,7 +1915,7 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool ext unsigned int buffer[MAXPICKBUF]; int hits; - hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); + hits = view3d_opengl_select(eval_ctx, vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); if (extend == false && select) BKE_mball_deselect_all(mb); @@ -1947,7 +1940,9 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool ext return OPERATOR_FINISHED; } -static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) +static int do_armature_box_select( + const struct EvaluationContext *eval_ctx, ViewContext *vc, + const rcti *rect, bool select, bool extend) { bArmature *arm = vc->obedit->data; EditBone *ebone; @@ -1956,7 +1951,7 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool unsigned int buffer[MAXPICKBUF]; int hits; - hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); + hits = view3d_opengl_select(eval_ctx, vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); /* clear flag we use to detect point was affected */ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) @@ -2020,8 +2015,30 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool return hits > 0 ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } +/** + * Compare result of 'GPU_select': 'uint[4]', + * needed for when we need to align with object draw-order. + */ +static int opengl_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p) +{ + /* 4th element is select id */ + const uint sel_a = ((uint *)sel_a_p)[3]; + const uint sel_b = ((uint *)sel_b_p)[3]; + + if (sel_a < sel_b) { + return -1; + } + else if (sel_a > sel_b) { + return 1; + } + else { + return 0; + } +} + static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, bool select, bool extend) { + EvaluationContext eval_ctx; Bone *bone; Object *ob = vc->obact; unsigned int *vbuffer = NULL; /* selection buffer */ @@ -2031,6 +2048,8 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b int totobj = MAXPICKBUF; /* XXX solve later */ int hits; + CTX_data_eval_ctx(C, &eval_ctx); + if ((ob) && (ob->mode & OB_MODE_POSE)) bone_only = 1; else @@ -2047,13 +2066,13 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b CTX_DATA_END; } else { - object_deselect_all_visible(vc->scene, vc->v3d); + object_deselect_all_visible(vc->scene_layer); } } /* selection buffer now has bones potentially too, so we add MAXPICKBUF */ vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(unsigned int), "selection buffer"); - hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL); + hits = view3d_opengl_select(&eval_ctx, vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL); /* * LOGIC NOTES (theeth): * The buffer and ListBase have the same relative order, which makes the selection @@ -2061,18 +2080,22 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b * is the same as the object, we have a hit and can move to the next color * and object pair, if not, just move to the next object, * keeping the same color until we have a hit. - * - * The buffer order is defined by OGL standard, hopefully no stupid GFX card - * does it incorrectly. */ if (hits > 0) { /* no need to loop if there's no hit */ Base *base; col = vbuffer + 3; - - for (base = vc->scene->base.first; base && hits; base = base->next) { - if (BASE_SELECTABLE(vc->v3d, base)) { - while (base->selcol == (*col & 0xFFFF)) { /* we got an object */ + + /* The draw order doesn't always match the order we populate the engine, see: T51695. */ + qsort(vbuffer, hits, sizeof(uint[4]), opengl_select_buffer_cmp); + + /* + * Even though 'DRW_draw_select_loop' uses 'DEG_OBJECT_ITER', + * we can be sure the order remains the same between both. + */ + for (base = vc->scene_layer->object_bases.first; base && hits; base = base->next) { + if (BASE_SELECTABLE(base)) { + while (base->object->select_color == (*col & 0xFFFF)) { /* we got an object */ if (*col & 0xFFFF0000) { /* we got a bone */ bone = get_indexed_bone(base->object, *col & ~(BONESEL_ANY)); if (bone) { @@ -2091,7 +2114,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b } } else if (!bone_only) { - ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT); + ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); } col += 4; /* next color */ @@ -2108,7 +2131,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b if (arm && (arm->flag & ARM_HAS_VIZ_DEPS)) { /* mask modifier ('armature' mode), etc. */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } } @@ -2123,6 +2146,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b static int view3d_borderselect_exec(bContext *C, wmOperator *op) { + EvaluationContext eval_ctx; ViewContext vc; rcti rect; bool extend; @@ -2133,6 +2157,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) view3d_operator_needs_opengl(C); /* setup view context for argument to callbacks */ + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); select = !RNA_boolean_get(op->ptr, "deselect"); @@ -2143,7 +2168,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) switch (vc.obedit->type) { case OB_MESH: vc.em = BKE_editmesh_from_object(vc.obedit); - ret = do_mesh_box_select(&vc, &rect, select, extend); + ret = do_mesh_box_select(&eval_ctx, &vc, &rect, select, extend); // if (EM_texFaceCheck()) if (ret & OPERATOR_FINISHED) { WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); @@ -2157,13 +2182,13 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) } break; case OB_MBALL: - ret = do_meta_box_select(&vc, &rect, select, extend); + ret = do_meta_box_select(&eval_ctx, &vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; case OB_ARMATURE: - ret = do_armature_box_select(&vc, &rect, select, extend); + ret = do_armature_box_select(&eval_ctx, &vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit); } @@ -2184,10 +2209,10 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) ret = ED_sculpt_mask_box_select(C, &vc, &rect, select, extend); } else if (vc.obact && BKE_paint_select_face_test(vc.obact)) { - ret = do_paintface_box_select(&vc, &rect, select, extend); + ret = do_paintface_box_select(&eval_ctx, &vc, &rect, select, extend); } else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) { - ret = do_paintvert_box_select(&vc, &rect, select, extend); + ret = do_paintvert_box_select(&eval_ctx, &vc, &rect, select, extend); } else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) { ret = PE_border_select(C, &rect, select, extend); @@ -2431,13 +2456,13 @@ static void mesh_circle_doSelectFace(void *userData, BMFace *efa, const float sc } } -static void mesh_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) +static void mesh_circle_select(const struct EvaluationContext *eval_ctx, ViewContext *vc, const bool select, const int mval[2], float rad) { ToolSettings *ts = vc->scene->toolsettings; int bbsel; CircleSelectUserData data; - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + bbsel = EDBM_backbuf_circle_init(eval_ctx, vc, mval[0], mval[1], (short)(rad + 1.0f)); ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ vc->em = BKE_editmesh_from_object(vc->obedit); @@ -2449,7 +2474,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva edbm_backbuf_check_and_select_verts(vc->em, select); } else { - mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenVert(eval_ctx, vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -2458,7 +2483,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva edbm_backbuf_check_and_select_edges(vc->em, select); } else { - mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); + mesh_foreachScreenEdge(eval_ctx, vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); } } @@ -2467,7 +2492,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva edbm_backbuf_check_and_select_faces(vc->em, select); } else { - mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenFace(eval_ctx, vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -2475,7 +2500,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva EDBM_selectmode_flush(vc->em); } -static void paint_facesel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) +static void paint_facesel_circle_select(const struct EvaluationContext *eval_ctx, ViewContext *vc, const bool select, const int mval[2], float rad) { Object *ob = vc->obact; Mesh *me = ob->data; @@ -2483,7 +2508,7 @@ static void paint_facesel_circle_select(ViewContext *vc, const bool select, cons bm_vertoffs = me->totpoly + 1; /* max index array */ - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + bbsel = EDBM_backbuf_circle_init(eval_ctx, vc, mval[0], mval[1], (short)(rad + 1.0f)); if (bbsel) { edbm_backbuf_check_and_select_tfaces(me, select); EDBM_backbuf_free(); @@ -2499,7 +2524,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); } } -static void paint_vertsel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) +static void paint_vertsel_circle_select(const struct EvaluationContext *eval_ctx, ViewContext *vc, const bool select, const int mval[2], float rad) { const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Object *ob = vc->obact; @@ -2510,7 +2535,7 @@ static void paint_vertsel_circle_select(ViewContext *vc, const bool select, cons if (use_zbuf) { bm_vertoffs = me->totvert + 1; /* max index array */ - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + bbsel = EDBM_backbuf_circle_init(eval_ctx, vc, mval[0], mval[1], (short)(rad + 1.0f)); if (bbsel) { edbm_backbuf_check_and_select_verts_obmode(me, select); EDBM_backbuf_free(); @@ -2522,7 +2547,7 @@ static void paint_vertsel_circle_select(ViewContext *vc, const bool select, cons ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ view3d_userdata_circleselect_init(&data, vc, select, mval, rad); - meshobject_foreachScreenVert(vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + meshobject_foreachScreenVert(eval_ctx, vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } if (select != LEFTMOUSE) { @@ -2666,7 +2691,7 @@ static void pose_circle_select(ViewContext *vc, const bool select, const int mva if (arm->flag & ARM_HAS_VIZ_DEPS) { /* mask modifier ('armature' mode), etc. */ - DAG_id_tag_update(&vc->obact->id, OB_RECALC_DATA); + DEG_id_tag_update(&vc->obact->id, OB_RECALC_DATA); } } } @@ -2776,11 +2801,12 @@ static void mball_circle_select(ViewContext *vc, const bool select, const int mv /** Callbacks for circle selection in Editmode */ -static void obedit_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) +static void obedit_circle_select( + const struct EvaluationContext *eval_ctx, ViewContext *vc, const bool select, const int mval[2], float rad) { switch (vc->obedit->type) { case OB_MESH: - mesh_circle_select(vc, select, mval, rad); + mesh_circle_select(eval_ctx, vc, select, mval, rad); break; case OB_CURVE: case OB_SURF: @@ -2802,22 +2828,22 @@ static void obedit_circle_select(ViewContext *vc, const bool select, const int m static bool object_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) { - Scene *scene = vc->scene; + SceneLayer *sl = vc->scene_layer; const float radius_squared = rad * rad; const float mval_fl[2] = {mval[0], mval[1]}; bool changed = false; - const int select_flag = select ? SELECT : 0; + const int select_flag = select ? BASE_SELECTED : 0; Base *base; - for (base = FIRSTBASE; base; base = base->next) { - if (BASE_SELECTABLE(vc->v3d, base) && ((base->flag & SELECT) != select_flag)) { + for (base = FIRSTBASE(sl); base; base = base->next) { + if (BASE_SELECTABLE(base) && ((base->flag & BASE_SELECTED) != select_flag)) { float screen_co[2]; if (ED_view3d_project_float_global(vc->ar, base->object->obmat[3], screen_co, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) { - ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT); + ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); changed = true; } } @@ -2840,22 +2866,24 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) if (CTX_data_edit_object(C) || BKE_paint_select_elem_test(obact) || (obact && (obact->mode & (OB_MODE_PARTICLE_EDIT | OB_MODE_POSE))) ) { + EvaluationContext eval_ctx; ViewContext vc; view3d_operator_needs_opengl(C); + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); if (CTX_data_edit_object(C)) { - obedit_circle_select(&vc, select, mval, (float)radius); + obedit_circle_select(&eval_ctx, &vc, select, mval, (float)radius); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); } else if (BKE_paint_select_face_test(obact)) { - paint_facesel_circle_select(&vc, select, mval, (float)radius); + paint_facesel_circle_select(&eval_ctx, &vc, select, mval, (float)radius); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); } else if (BKE_paint_select_vert_test(obact)) { - paint_vertsel_circle_select(&vc, select, mval, (float)radius); + paint_vertsel_circle_select(&eval_ctx, &vc, select, mval, (float)radius); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); } else if (obact->mode & OB_MODE_POSE) diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 5dd69cc66eb..1df29201bf6 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -40,13 +40,14 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_mball.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_tracking.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -73,9 +74,12 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) RegionView3D *rv3d = CTX_wm_region_data(C); TransVertStore tvs = {NULL}; TransVert *tv; + EvaluationContext eval_ctx; float gridf, imat[3][3], bmat[3][3], vec[3]; int a; + CTX_data_eval_ctx(C, &eval_ctx); + gridf = rv3d->gridview; if (obedit) { @@ -153,7 +157,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) } ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } else { vec[0] = -ob->obmat[3][0] + gridf * floorf(0.5f + ob->obmat[3][0] / gridf); @@ -162,7 +166,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) if (ob->parent) { float originmat[3][3]; - BKE_object_where_is_calc_ex(scene, NULL, ob, originmat); + BKE_object_where_is_calc_ex(&eval_ctx, scene, NULL, ob, originmat); invert_m3_m3(imat, originmat); mul_m3_v3(imat, vec); @@ -177,7 +181,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) /* auto-keyframing */ ED_autokeyframe_object(C, scene, ob, ks); - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } } CTX_DATA_END; @@ -213,11 +217,14 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global View3D *v3d = CTX_wm_view3d(C); TransVertStore tvs = {NULL}; TransVert *tv; + EvaluationContext eval_ctx; float imat[3][3], bmat[3][3]; float center_global[3]; float offset_global[3]; int a; + CTX_data_eval_ctx(C, &eval_ctx); + if (use_offset) { if ((v3d && v3d->around == V3D_AROUND_ACTIVE) && snap_calc_active_center(C, true, center_global)) @@ -329,7 +336,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global obact->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); - DAG_id_tag_update(&obact->id, OB_RECALC_DATA); + DEG_id_tag_update(&obact->id, OB_RECALC_DATA); } else { struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); @@ -370,7 +377,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global if (ob->parent) { float originmat[3][3]; - BKE_object_where_is_calc_ex(scene, NULL, ob, originmat); + BKE_object_where_is_calc_ex(&eval_ctx, scene, NULL, ob, originmat); invert_m3_m3(imat, originmat); mul_m3_v3(imat, cursor_parent); @@ -385,7 +392,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global /* auto-keyframing */ ED_autokeyframe_object(C, scene, ob, ks); - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } } diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 0bccab626e6..4e98386be97 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -43,7 +43,6 @@ #include "BKE_action.h" #include "BKE_camera.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_object.h" #include "BKE_global.h" #include "BKE_main.h" @@ -51,12 +50,15 @@ #include "BKE_scene.h" #include "BKE_screen.h" -#include "BIF_gl.h" +#include "DEG_depsgraph.h" + #include "BIF_glutil.h" #include "UI_resources.h" +#include "GPU_glew.h" #include "GPU_select.h" +#include "GPU_matrix.h" #include "WM_api.h" #include "WM_types.h" @@ -64,6 +66,8 @@ #include "ED_screen.h" #include "ED_armature.h" +#include "DRW_engine.h" + #ifdef WITH_GAMEENGINE # include "BLI_listbase.h" @@ -98,10 +102,8 @@ void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar) RegionView3D *rv3d = ar->regiondata; wmSubWindowSet(win, ar->swinid); - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(rv3d->winmat); - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(rv3d->viewmat); + gpuLoadProjectionMatrix(rv3d->winmat); + gpuLoadMatrix(rv3d->viewmat); } } @@ -443,6 +445,9 @@ void ED_view3d_smooth_view_force_finish( View3D *v3d, ARegion *ar) { RegionView3D *rv3d = ar->regiondata; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); if (rv3d && rv3d->sms) { rv3d->sms->time_allowed = 0.0; /* force finishing */ @@ -451,7 +456,7 @@ void ED_view3d_smooth_view_force_finish( /* force update of view matrix so tools that run immediately after * can use them without redrawing first */ Scene *scene = CTX_data_scene(C); - ED_view3d_update_viewmat(scene, v3d, ar, NULL, NULL, NULL); + ED_view3d_update_viewmat(&eval_ctx, scene, v3d, ar, NULL, NULL, NULL); } } @@ -493,7 +498,7 @@ static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op)) BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag); - DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); + DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); rv3d->persp = RV3D_CAMOB; WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, v3d->camera); @@ -541,6 +546,7 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot) static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); View3D *v3d = CTX_wm_view3d(C); /* can be NULL */ Object *camera_ob = v3d ? v3d->camera : scene->camera; @@ -553,7 +559,7 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op) } /* this function does all the important stuff */ - if (BKE_camera_view_frame_fit_to_scene(scene, v3d, camera_ob, r_co, &r_scale)) { + if (BKE_camera_view_frame_fit_to_scene(scene, sl, camera_ob, r_co, &r_scale)) { ObjectTfmProtectedChannels obtfm; float obmat_new[4][4]; @@ -570,7 +576,7 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op) BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D); /* notifiers */ - DAG_id_tag_update(&camera_ob->id, OB_RECALC_OB); + DEG_id_tag_update(&camera_ob->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, camera_ob); return OPERATOR_FINISHED; } @@ -727,40 +733,35 @@ void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, } } -void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], bglMats *mats, const rcti *rect) +void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect) { - float modelview[4][4]; - double xs, ys, p[3]; - int val, flip_sign, a; - - /* near zero floating point values can give issues with gluUnProject - * in side view on some implementations */ - if (fabs(mats->modelview[0]) < 1e-6) mats->modelview[0] = 0.0; - if (fabs(mats->modelview[5]) < 1e-6) mats->modelview[5] = 0.0; - - /* Set up viewport so that gluUnProject will give correct values */ - mats->viewport[0] = 0; - mats->viewport[1] = 0; + /* init in case unproject fails */ + memset(bb->vec, 0, sizeof(bb->vec)); /* four clipping planes and bounding volume */ /* first do the bounding volume */ - for (val = 0; val < 4; val++) { - xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax; - ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax; + for (int val = 0; val < 4; val++) { + float xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax; + float ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax; - gluUnProject(xs, ys, 0.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]); - copy_v3fl_v3db(bb->vec[val], p); + ED_view3d_unproject(ar, xs, ys, 0.0, bb->vec[val]); + ED_view3d_unproject(ar, xs, ys, 1.0, bb->vec[4 + val]); + } - gluUnProject(xs, ys, 1.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]); - copy_v3fl_v3db(bb->vec[4 + val], p); + /* optionally transform to object space */ + if (ob) { + float imat[4][4]; + invert_m4_m4(imat, ob->obmat); + + for (int val = 0; val < 8; val++) { + mul_m4_v3(imat, bb->vec[val]); + } } /* verify if we have negative scale. doing the transform before cross * product flips the sign of the vector compared to doing cross product * before transform then, so we correct for that. */ - for (a = 0; a < 16; a++) - ((float *)modelview)[a] = mats->modelview[a]; - flip_sign = is_negative_m4(modelview); + int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false; ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign); } @@ -836,7 +837,7 @@ float ED_view3d_depth_read_cached(const ViewContext *vc, const int mval[2]) } bool ED_view3d_depth_read_cached_normal( - const ViewContext *vc, const bglMats *mats, const int mval[2], + const ViewContext *vc, const int mval[2], float r_normal[3]) { /* Note: we could support passing in a radius. @@ -855,7 +856,7 @@ bool ED_view3d_depth_read_cached_normal( const double depth = (double)ED_view3d_depth_read_cached(vc, mval_ofs); if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) { - if (ED_view3d_depth_unproject(ar, mats, mval_ofs, depth, coords[i])) { + if (ED_view3d_depth_unproject(ar, mval_ofs, depth, coords[i])) { depths_valid[i] = true; } } @@ -897,21 +898,13 @@ bool ED_view3d_depth_read_cached_normal( } bool ED_view3d_depth_unproject( - const ARegion *ar, const bglMats *mats, + const ARegion *ar, const int mval[2], const double depth, float r_location_world[3]) { - double p[3]; - if (gluUnProject( - (double)ar->winrct.xmin + mval[0] + 0.5, - (double)ar->winrct.ymin + mval[1] + 0.5, - depth, mats->modelview, mats->projection, (const GLint *)mats->viewport, - &p[0], &p[1], &p[2])) - { - copy_v3fl_v3db(r_location_world, p); - return true; - } - return false; + float centx = (float)mval[0] + 0.5f; + float centy = (float)mval[1] + 0.5f; + return ED_view3d_unproject(ar, centx, centy, depth, r_location_world); } /** \} */ @@ -1025,14 +1018,14 @@ void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect) } if (is_ortho) { - wmOrtho(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); + gpuOrtho(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); } else { - wmFrustum(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); + gpuFrustum(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); } /* update matrix in 3d view region */ - glGetFloatv(GL_PROJECTION_MATRIX, (float *)rv3d->winmat); + gpuGetProjectionMatrix(rv3d->winmat); } static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob) @@ -1116,11 +1109,11 @@ bool ED_view3d_lock(RegionView3D *rv3d) } /* don't set windows active in here, is used by renderwin too */ -void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d) +void view3d_viewmatrix_set(const EvaluationContext *eval_ctx, Scene *scene, const View3D *v3d, RegionView3D *rv3d) { if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */ if (v3d->camera) { - BKE_object_where_is_calc(scene, v3d->camera); + BKE_object_where_is_calc(eval_ctx, scene, v3d->camera); obmat_to_viewmat(rv3d, v3d->camera); } else { @@ -1205,10 +1198,11 @@ void view3d_opengl_select_cache_end(void) * \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection. */ int view3d_opengl_select( - ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input, + const EvaluationContext *eval_ctx, ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input, eV3DSelectMode select_mode) { struct bThemeState theme_state; + Depsgraph *graph = vc->depsgraph; Scene *scene = vc->scene; View3D *v3d = vc->v3d; ARegion *ar = vc->ar; @@ -1270,7 +1264,7 @@ int view3d_opengl_select( /* Important we use the 'viewmat' and don't re-calculate since * the object & bone view locking takes 'rect' into account, see: T51629. */ - ED_view3d_draw_setup_view(vc->win, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect); + ED_view3d_draw_setup_view(vc->win, eval_ctx, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect); if (v3d->drawtype > OB_WIRE) { v3d->zbuf = true; @@ -1282,7 +1276,16 @@ int view3d_opengl_select( GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0); - ED_view3d_draw_select_loop(vc, scene, v3d, ar, use_obedit_skip, use_nearest); +#ifdef WITH_OPENGL_LEGACY + if (IS_VIEWPORT_LEGACY(vc->v3d)) { + ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest); + } + else +#else + { + DRW_draw_select_loop(graph, ar, v3d, use_obedit_skip, use_nearest, &rect); + } +#endif /* WITH_OPENGL_LEGACY */ hits = GPU_select_end(); @@ -1290,13 +1293,22 @@ int view3d_opengl_select( if (do_passes && (hits > 0)) { GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits); - ED_view3d_draw_select_loop(vc, scene, v3d, ar, use_obedit_skip, use_nearest); +#ifdef WITH_OPENGL_LEGACY + if (IS_VIEWPORT_LEGACY(vc->v3d)) { + ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest); + } + else +#else + { + DRW_draw_select_loop(graph, ar, v3d, use_obedit_skip, use_nearest, &rect); + } +#endif /* WITH_OPENGL_LEGACY */ GPU_select_end(); } G.f &= ~G_PICKSEL; - ED_view3d_draw_setup_view(vc->win, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL); + ED_view3d_draw_setup_view(vc->win, eval_ctx, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL); if (v3d->drawtype > OB_WIRE) { v3d->zbuf = 0; @@ -1314,42 +1326,6 @@ finally: return hits; } -/* ********************** local view operator ******************** */ - -static unsigned int free_localbit(Main *bmain) -{ - unsigned int lay; - ScrArea *sa; - bScreen *sc; - - lay = 0; - - /* sometimes we loose a localview: when an area is closed */ - /* check all areas: which localviews are in use? */ - for (sc = bmain->screen.first; sc; sc = sc->id.next) { - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl = sa->spacedata.first; - for (; sl; sl = sl->next) { - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *) sl; - lay |= v3d->lay; - } - } - } - } - - if ((lay & 0x01000000) == 0) return 0x01000000; - if ((lay & 0x02000000) == 0) return 0x02000000; - if ((lay & 0x04000000) == 0) return 0x04000000; - if ((lay & 0x08000000) == 0) return 0x08000000; - if ((lay & 0x10000000) == 0) return 0x10000000; - if ((lay & 0x20000000) == 0) return 0x20000000; - if ((lay & 0x40000000) == 0) return 0x40000000; - if ((lay & 0x80000000) == 0) return 0x80000000; - - return 0; -} - int ED_view3d_scene_layer_set(int lay, const int *values, int *active) { int i, tot = 0; @@ -1388,267 +1364,6 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active) return lay; } -static bool view3d_localview_init( - wmWindowManager *wm, wmWindow *win, - Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx, - ReportList *reports) -{ - View3D *v3d = sa->spacedata.first; - Base *base; - float min[3], max[3], box[3], mid[3]; - float size = 0.0f; - unsigned int locallay; - bool ok = false; - - if (v3d->localvd) { - return ok; - } - - INIT_MINMAX(min, max); - - locallay = free_localbit(bmain); - - if (locallay == 0) { - BKE_report(reports, RPT_ERROR, "No more than 8 local views"); - ok = false; - } - else { - if (scene->obedit) { - BKE_object_minmax(scene->obedit, min, max, false); - - ok = true; - - BASACT->lay |= locallay; - scene->obedit->lay = BASACT->lay; - } - else { - for (base = FIRSTBASE; base; base = base->next) { - if (TESTBASE(v3d, base)) { - BKE_object_minmax(base->object, min, max, false); - base->lay |= locallay; - base->object->lay = base->lay; - ok = true; - } - } - } - - sub_v3_v3v3(box, max, min); - size = max_fff(box[0], box[1], box[2]); - } - - if (ok == true) { - ARegion *ar; - - v3d->localvd = MEM_mallocN(sizeof(View3D), "localview"); - - memcpy(v3d->localvd, v3d, sizeof(View3D)); - - mid_v3_v3v3(mid, min, max); - - copy_v3_v3(v3d->cursor, mid); - - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = ar->regiondata; - bool ok_dist = true; - - /* new view values */ - Object *camera_old = NULL; - float dist_new, ofs_new[3]; - - rv3d->localvd = MEM_mallocN(sizeof(RegionView3D), "localview region"); - memcpy(rv3d->localvd, rv3d, sizeof(RegionView3D)); - - negate_v3_v3(ofs_new, mid); - - if (rv3d->persp == RV3D_CAMOB) { - rv3d->persp = RV3D_PERSP; - camera_old = v3d->camera; - } - - if (rv3d->persp == RV3D_ORTHO) { - if (size < 0.0001f) { - ok_dist = false; - } - } - - if (ok_dist) { - dist_new = ED_view3d_radius_to_dist(v3d, ar, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN); - if (rv3d->persp == RV3D_PERSP) { - /* don't zoom closer than the near clipping plane */ - dist_new = max_ff(dist_new, v3d->near * 1.5f); - } - } - - ED_view3d_smooth_view_ex( - wm, win, sa, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { - .camera_old = camera_old, - .ofs = ofs_new, .quat = rv3d->viewquat, - .dist = ok_dist ? &dist_new : NULL, .lens = &v3d->lens}); - } - } - - v3d->lay = locallay; - } - else { - /* clear flags */ - for (base = FIRSTBASE; base; base = base->next) { - if (base->lay & locallay) { - base->lay -= locallay; - if (base->lay == 0) base->lay = v3d->layact; - if (base->object != scene->obedit) base->flag |= SELECT; - base->object->lay = base->lay; - } - } - } - - DAG_on_visible_update(bmain, false); - - return ok; -} - -static void restore_localviewdata(wmWindowManager *wm, wmWindow *win, Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx) -{ - const bool free = true; - ARegion *ar; - View3D *v3d = sa->spacedata.first; - Object *camera_old, *camera_new; - - if (v3d->localvd == NULL) return; - - camera_old = v3d->camera; - camera_new = v3d->localvd->camera; - - v3d->lay = v3d->localvd->lay; - v3d->layact = v3d->localvd->layact; - v3d->drawtype = v3d->localvd->drawtype; - v3d->camera = v3d->localvd->camera; - - if (free) { - MEM_freeN(v3d->localvd); - v3d->localvd = NULL; - } - - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = ar->regiondata; - - if (rv3d->localvd) { - Object *camera_old_rv3d, *camera_new_rv3d; - - camera_old_rv3d = (rv3d->persp == RV3D_CAMOB) ? camera_old : NULL; - camera_new_rv3d = (rv3d->localvd->persp == RV3D_CAMOB) ? camera_new : NULL; - - rv3d->view = rv3d->localvd->view; - rv3d->persp = rv3d->localvd->persp; - rv3d->camzoom = rv3d->localvd->camzoom; - - ED_view3d_smooth_view_ex( - wm, win, sa, - v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { - .camera_old = camera_old_rv3d, .camera = camera_new_rv3d, - .ofs = rv3d->localvd->ofs, .quat = rv3d->localvd->viewquat, - .dist = &rv3d->localvd->dist}); - - if (free) { - MEM_freeN(rv3d->localvd); - rv3d->localvd = NULL; - } - } - - ED_view3d_shade_update(bmain, scene, v3d, sa); - } - } -} - -static bool view3d_localview_exit( - wmWindowManager *wm, wmWindow *win, - Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx) -{ - View3D *v3d = sa->spacedata.first; - struct Base *base; - unsigned int locallay; - - if (v3d->localvd) { - - locallay = v3d->lay & 0xFF000000; - - restore_localviewdata(wm, win, bmain, scene, sa, smooth_viewtx); - - /* for when in other window the layers have changed */ - if (v3d->scenelock) v3d->lay = scene->lay; - - for (base = FIRSTBASE; base; base = base->next) { - if (base->lay & locallay) { - base->lay -= locallay; - if (base->lay == 0) base->lay = v3d->layact; - if (base->object != scene->obedit) { - base->flag |= SELECT; - base->object->flag |= SELECT; - } - base->object->lay = base->lay; - } - } - - DAG_on_visible_update(bmain, false); - - return true; - } - else { - return false; - } -} - -static int localview_exec(bContext *C, wmOperator *op) -{ - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ScrArea *sa = CTX_wm_area(C); - View3D *v3d = CTX_wm_view3d(C); - bool changed; - - if (v3d->localvd) { - changed = view3d_localview_exit(wm, win, bmain, scene, sa, smooth_viewtx); - } - else { - changed = view3d_localview_init(wm, win, bmain, scene, sa, smooth_viewtx, op->reports); - } - - if (changed) { - DAG_id_type_tag(bmain, ID_OB); - ED_area_tag_redraw(sa); - - /* unselected objects become selected when exiting */ - if (v3d->localvd == NULL) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - } - - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } -} - -void VIEW3D_OT_localview(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Local View"; - ot->description = "Toggle display of selected object(s) separately and centered in view"; - ot->idname = "VIEW3D_OT_localview"; - - /* api callbacks */ - ot->exec = localview_exec; - ot->flag = OPTYPE_UNDO; /* localview changes object layer bitflags */ - - ot->poll = ED_operator_view3d_active; -} - #ifdef WITH_GAMEENGINE static ListBase queue_back; @@ -1687,7 +1402,6 @@ static void RestoreState(bContext *C, wmWindow *win) win->queue = queue_back; GPU_state_init(); - GPU_set_tpage(NULL, 0, 0); glPopAttrib(); } @@ -1730,10 +1444,6 @@ static void game_set_commmandline_options(GameData *gm) SYS_WriteCommandLineInt(syshandle, "blender_material", test); test = (gm->matmode == GAME_MAT_GLSL); SYS_WriteCommandLineInt(syshandle, "blender_glsl_material", test); - test = (gm->flag & GAME_DISPLAY_LISTS); - SYS_WriteCommandLineInt(syshandle, "displaylists", test); - - } } @@ -1741,19 +1451,21 @@ static void game_set_commmandline_options(GameData *gm) static int game_engine_poll(bContext *C) { - bScreen *screen; + const wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); + /* we need a context and area to launch BGE * it's a temporary solution to avoid crash at load time * if we try to auto run the BGE. Ideally we want the * context to be set as soon as we load the file. */ - if (CTX_wm_window(C) == NULL) return 0; - if ((screen = CTX_wm_screen(C)) == NULL) return 0; + if (win == NULL) return 0; + if (CTX_wm_screen(C) == NULL) return 0; if (CTX_data_mode_enum(C) != CTX_MODE_OBJECT) return 0; - if (!BKE_scene_uses_blender_game(screen->scene)) + if (!BKE_scene_uses_blender_game(scene)) return 0; return 1; @@ -1862,7 +1574,7 @@ static int game_engine_exec(bContext *C, wmOperator *op) //XXX restore_all_scene_cfra(scene_cfra_store); BKE_scene_set_background(CTX_data_main(C), startscene); - //XXX BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay); + //XXX BKE_scene_graph_update_for_newframe(bmain->eval_ctx, bmain, scene, depsgraph); BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_POST); diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 9464f332d39..95390fe9065 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -56,6 +56,10 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "GPU_immediate.h" + +#include "RE_engine.h" + #include "view3d_intern.h" /* own include */ #ifdef WITH_INPUT_NDOF @@ -246,6 +250,8 @@ typedef struct WalkInfo { View3D *v3d; ARegion *ar; Scene *scene; + SceneLayer *scene_layer; + RenderEngineType *engine; wmTimer *timer; /* needed for redraws */ @@ -337,24 +343,33 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *a yoff = walk->ar->winy / 2; } - UI_ThemeColor(TH_VIEW_OVERLAY); - glBegin(GL_LINES); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColor(TH_VIEW_OVERLAY); + + immBegin(GWN_PRIM_LINES, 8); + /* North */ - glVertex2i(xoff, yoff + inner_length); - glVertex2i(xoff, yoff + outter_length); + immVertex2i(pos, xoff, yoff + inner_length); + immVertex2i(pos, xoff, yoff + outter_length); /* East */ - glVertex2i(xoff + inner_length, yoff); - glVertex2i(xoff + outter_length, yoff); + immVertex2i(pos, xoff + inner_length, yoff); + immVertex2i(pos, xoff + outter_length, yoff); /* South */ - glVertex2i(xoff, yoff - inner_length); - glVertex2i(xoff, yoff - outter_length); + immVertex2i(pos, xoff, yoff - inner_length); + immVertex2i(pos, xoff, yoff - outter_length); /* West */ - glVertex2i(xoff - inner_length, yoff); - glVertex2i(xoff - outter_length, yoff); - glEnd(); + immVertex2i(pos, xoff - inner_length, yoff); + immVertex2i(pos, xoff - outter_length, yoff); + + immEnd(); + immUnbindProgram(); } static void walk_update_header(bContext *C, wmOperator *op, WalkInfo *walk) @@ -499,6 +514,8 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->v3d = CTX_wm_view3d(C); walk->ar = CTX_wm_region(C); walk->scene = CTX_data_scene(C); + walk->scene_layer = CTX_data_scene_layer(C); + walk->engine = CTX_data_engine(C); #ifdef NDOF_WALK_DEBUG puts("\n-- walk begin --"); @@ -587,11 +604,11 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->rv3d->rflag |= RV3D_NAVIGATING; walk->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), walk->scene, 0, + CTX_data_main(C), walk->scene, walk->scene_layer, walk->engine, 0, walk->ar, walk->v3d); walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( - walk->scene, walk->v3d, walk->rv3d, + C, walk->scene, walk->v3d, walk->rv3d, (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); /* center the mouse */ diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index b7de49d8158..f38f6c064b8 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -29,6 +29,7 @@ set(INC ../../ikplugin ../../makesdna ../../makesrna + ../../render/extern/include ../../windowmanager ../../depsgraph ../../../../intern/guardedalloc @@ -46,6 +47,7 @@ set(SRC transform_generics.c transform_input.c transform_manipulator.c + transform_manipulator2d.c transform_ops.c transform_orientations.c transform_snap.c @@ -58,10 +60,6 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -if(WITH_LEGACY_DEPSGRAPH) - add_definitions(-DWITH_LEGACY_DEPSGRAPH) -endif() - add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_transform "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index b25ab1c6a89..e036ffd526c 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -43,6 +43,7 @@ #include "DNA_mask_types.h" #include "DNA_movieclip_types.h" #include "DNA_scene_types.h" /* PET modes */ +#include "DNA_workspace_types.h" #include "BLI_alloca.h" #include "BLI_utildefines.h" @@ -63,10 +64,16 @@ #include "BKE_unit.h" #include "BKE_mask.h" #include "BKE_report.h" +#include "BKE_workspace.h" + +#include "DEG_depsgraph.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" + #include "ED_image.h" #include "ED_keyframing.h" #include "ED_screen.h" @@ -1598,8 +1605,16 @@ typedef enum { LEFT, RIGHT } ArrowDirection; + +#define POS_INDEX 0 +/* NOTE: this --^ is a bit hackish, but simplifies Gwn_VertFormat usage among functions + * private to this file - merwin + */ + static void drawArrow(ArrowDirection d, short offset, short length, short size) { + immBegin(GWN_PRIM_LINES, 6); + switch (d) { case LEFT: offset = -offset; @@ -1607,14 +1622,12 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size) size = -size; ATTR_FALLTHROUGH; case RIGHT: - glBegin(GL_LINES); - glVertex2s(offset, 0); - glVertex2s(offset + length, 0); - glVertex2s(offset + length, 0); - glVertex2s(offset + length - size, -size); - glVertex2s(offset + length, 0); - glVertex2s(offset + length - size, size); - glEnd(); + immVertex2f(POS_INDEX, offset, 0); + immVertex2f(POS_INDEX, offset + length, 0); + immVertex2f(POS_INDEX, offset + length, 0); + immVertex2f(POS_INDEX, offset + length - size, -size); + immVertex2f(POS_INDEX, offset + length, 0); + immVertex2f(POS_INDEX, offset + length - size, size); break; case DOWN: @@ -1623,45 +1636,45 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size) size = -size; ATTR_FALLTHROUGH; case UP: - glBegin(GL_LINES); - glVertex2s(0, offset); - glVertex2s(0, offset + length); - glVertex2s(0, offset + length); - glVertex2s(-size, offset + length - size); - glVertex2s(0, offset + length); - glVertex2s(size, offset + length - size); - glEnd(); + immVertex2f(POS_INDEX, 0, offset); + immVertex2f(POS_INDEX, 0, offset + length); + immVertex2f(POS_INDEX, 0, offset + length); + immVertex2f(POS_INDEX, -size, offset + length - size); + immVertex2f(POS_INDEX, 0, offset + length); + immVertex2f(POS_INDEX, size, offset + length - size); break; } + + immEnd(); } static void drawArrowHead(ArrowDirection d, short size) { + immBegin(GWN_PRIM_LINES, 4); + switch (d) { case LEFT: size = -size; ATTR_FALLTHROUGH; case RIGHT: - glBegin(GL_LINES); - glVertex2s(0, 0); - glVertex2s(-size, -size); - glVertex2s(0, 0); - glVertex2s(-size, size); - glEnd(); + immVertex2f(POS_INDEX, 0, 0); + immVertex2f(POS_INDEX, -size, -size); + immVertex2f(POS_INDEX, 0, 0); + immVertex2f(POS_INDEX, -size, size); break; case DOWN: size = -size; ATTR_FALLTHROUGH; case UP: - glBegin(GL_LINES); - glVertex2s(0, 0); - glVertex2s(-size, -size); - glVertex2s(0, 0); - glVertex2s(size, -size); - glEnd(); + immVertex2f(POS_INDEX, 0, 0); + immVertex2f(POS_INDEX, -size, -size); + immVertex2f(POS_INDEX, 0, 0); + immVertex2f(POS_INDEX, size, -size); break; } + + immEnd(); } static void drawArc(float size, float angle_start, float angle_end, int segments) @@ -1670,14 +1683,14 @@ static void drawArc(float size, float angle_start, float angle_end, int segments float angle; int a; - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, segments + 1); for (angle = angle_start, a = 0; a < segments; angle += delta, a++) { - glVertex2f(cosf(angle) * size, sinf(angle) * size); + immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size); } - glVertex2f(cosf(angle_end) * size, sinf(angle_end) * size); + immVertex2f(POS_INDEX, cosf(angle_end) * size, sinf(angle_end) * size); - glEnd(); + immEnd(); } static int helpline_poll(bContext *C) @@ -1693,12 +1706,9 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) { TransInfo *t = (TransInfo *)customdata; - if (t->helpline != HLP_NONE && !(t->flag & T_USES_MANIPULATOR)) { + if (t->helpline != HLP_NONE) { float vecrot[3], cent[2]; - int mval[2]; - - mval[0] = x; - mval[1] = y; + float mval[3] = { x, y, 0.0f }; copy_v3_v3(vecrot, t->center); if (t->flag & T_EDIT) { @@ -1712,42 +1722,67 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) projectFloatViewEx(t, vecrot, cent, V3D_PROJ_TEST_CLIP_ZERO); - glPushMatrix(); + gpuPushMatrix(); + + /* Dashed lines first. */ + if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) { + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */ + BLI_assert(shdr_pos == POS_INDEX); + + glLineWidth(1.0f); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniformThemeColor(TH_VIEW_OVERLAY); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(POS_INDEX, cent); + immVertex2f(POS_INDEX, (float)t->mval[0], (float)t->mval[1]); + immEnd(); + + immUnbindProgram(); + } + + /* And now, solid lines. */ + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + UNUSED_VARS_NDEBUG(pos); /* silence warning */ + BLI_assert(pos == POS_INDEX); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); switch (t->helpline) { case HLP_SPRING: - UI_ThemeColor(TH_VIEW_OVERLAY); - - setlinestyle(3); - glLineWidth(1); - glBegin(GL_LINES); - glVertex2iv(t->mval); - glVertex2fv(cent); - glEnd(); + immUniformThemeColor(TH_VIEW_OVERLAY); - glTranslate2iv(mval); - glRotatef(-RAD2DEGF(atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1])), 0, 0, 1); + gpuTranslate3fv(mval); + gpuRotateAxis(-RAD2DEGF(atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1])), 'Z'); - setlinestyle(0); - glLineWidth(3.0); + glLineWidth(3.0f); drawArrow(UP, 5, 10, 5); drawArrow(DOWN, 5, 10, 5); break; case HLP_HARROW: - UI_ThemeColor(TH_VIEW_OVERLAY); + immUniformThemeColor(TH_VIEW_OVERLAY); + gpuTranslate3fv(mval); - glTranslate2iv(mval); - - glLineWidth(3.0); + glLineWidth(3.0f); drawArrow(RIGHT, 5, 10, 5); drawArrow(LEFT, 5, 10, 5); break; case HLP_VARROW: - UI_ThemeColor(TH_VIEW_OVERLAY); + immUniformThemeColor(TH_VIEW_OVERLAY); - glTranslate2iv(mval); + gpuTranslate3fv(mval); - glLineWidth(3.0); + glLineWidth(3.0f); drawArrow(UP, 5, 10, 5); drawArrow(DOWN, 5, 10, 5); break; @@ -1758,33 +1793,26 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) float dist = hypotf(dx, dy); float delta_angle = min_ff(15.0f / dist, (float)M_PI / 4.0f); float spacing_angle = min_ff(5.0f / dist, (float)M_PI / 12.0f); - UI_ThemeColor(TH_VIEW_OVERLAY); - setlinestyle(3); - glLineWidth(1); - glBegin(GL_LINES); - glVertex2iv(t->mval); - glVertex2fv(cent); - glEnd(); + immUniformThemeColor(TH_VIEW_OVERLAY); - glTranslatef(cent[0] - t->mval[0] + mval[0], cent[1] - t->mval[1] + mval[1], 0); + gpuTranslate3f(cent[0] - t->mval[0] + mval[0], cent[1] - t->mval[1] + mval[1], 0); - setlinestyle(0); - glLineWidth(3.0); + glLineWidth(3.0f); drawArc(dist, angle - delta_angle, angle - spacing_angle, 10); drawArc(dist, angle + spacing_angle, angle + delta_angle, 10); - glPushMatrix(); + gpuPushMatrix(); - glTranslatef(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0); - glRotatef(RAD2DEGF(angle - delta_angle), 0, 0, 1); + gpuTranslate3f(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0); + gpuRotateAxis(RAD2DEGF(angle - delta_angle), 'Z'); drawArrowHead(DOWN, 5); - glPopMatrix(); + gpuPopMatrix(); - glTranslatef(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0); - glRotatef(RAD2DEGF(angle + delta_angle), 0, 0, 1); + gpuTranslate3f(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0); + gpuRotateAxis(RAD2DEGF(angle + delta_angle), 'Z'); drawArrowHead(UP, 5); break; @@ -1794,18 +1822,18 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) unsigned char col[3], col2[3]; UI_GetThemeColor3ubv(TH_GRID, col); - glTranslate2iv(mval); + gpuTranslate3fv(mval); - glLineWidth(3.0); + glLineWidth(3.0f); UI_make_axis_color(col, col2, 'X'); - glColor3ubv((GLubyte *)col2); + immUniformColor3ubv((GLubyte *)col2); drawArrow(RIGHT, 5, 10, 5); drawArrow(LEFT, 5, 10, 5); UI_make_axis_color(col, col2, 'Y'); - glColor3ubv((GLubyte *)col2); + immUniformColor3ubv((GLubyte *)col2); drawArrow(UP, 5, 10, 5); drawArrow(DOWN, 5, 10, 5); @@ -1813,7 +1841,8 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) } } - glPopMatrix(); + immUnbindProgram(); + gpuPopMatrix(); } } @@ -1821,7 +1850,7 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi { TransInfo *t = arg; - glLineWidth(1.0); + glLineWidth(1.0f); drawConstraint(t); drawPropCircle(C, t); @@ -1841,8 +1870,9 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) int xco, yco; ED_region_visible_rect(ar, &rect); - - BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); + + const int font_id = BLF_default(); + BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); xco = (rect.xmax - U.widget_unit) - (int)printable_size[0]; yco = (rect.ymax - U.widget_unit); @@ -1850,7 +1880,9 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) /* warning text (to clarify meaning of overlays) * - original color was red to match the icon, but that clashes badly with a less nasty border */ - UI_ThemeColorShade(TH_TEXT_HI, -50); + unsigned char color[3]; + UI_GetThemeColorShade3ubv(TH_TEXT_HI, -50, color); + BLF_color3ubv(font_id, color); #ifdef WITH_INTERNATIONAL BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); #else @@ -1873,7 +1905,8 @@ static void drawTransformPixel(const struct bContext *UNUSED(C), ARegion *ar, vo { TransInfo *t = arg; Scene *scene = t->scene; - Object *ob = OBACT; + SceneLayer *sl = t->scene_layer; + Object *ob = OBACT(sl); /* draw autokeyframing hint in the corner * - only draw if enabled (advanced users may be distracted/annoyed), @@ -1984,6 +2017,10 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) View3D *v3d = t->view; v3d->twmode = t->current_orientation; + + BLI_assert(((v3d->custom_orientation_index == -1) && (t->custom_orientation == NULL)) || + (BKE_workspace_transform_orientation_get_index( + CTX_wm_workspace(C), t->custom_orientation) == v3d->custom_orientation_index)); } } } @@ -2003,15 +2040,20 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) { - /* constraint orientation can be global, event if user selects something else - * so use the orientation in the constraint if set - * */ - if (t->con.mode & CON_APPLY) { - RNA_enum_set(op->ptr, "constraint_orientation", t->con.orientation); - } - else { - RNA_enum_set(op->ptr, "constraint_orientation", t->current_orientation); + /* constraint orientation can be global, even if user selects something else + * so use the orientation in the constraint if set */ + short orientation = (t->con.mode & CON_APPLY) ? t->con.orientation : t->current_orientation; + + if (orientation == V3D_MANIP_CUSTOM) { + WorkSpace *workspace = CTX_wm_workspace(C); + const int custom_orientation_index = BKE_workspace_transform_orientation_get_index( + workspace, t->custom_orientation); + + /* Maybe we need a t->con.custom_orientation? Seems like it would always match t->custom_orientation. */ + orientation = V3D_MANIP_CUSTOM + custom_orientation_index; + BLI_assert(orientation >= V3D_MANIP_CUSTOM); } + RNA_enum_set(op->ptr, "constraint_orientation", orientation); if (t->con.mode & CON_APPLY) { if (t->con.mode & CON_AXIS0) { @@ -2583,6 +2625,9 @@ static void constraintTransLim(TransInfo *t, TransData *td) if (td->con) { const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_LOCLIMIT); const bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_DISTLIMIT); + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(t->context, &eval_ctx); bConstraintOb cob = {NULL}; bConstraint *con; @@ -2632,7 +2677,7 @@ static void constraintTransLim(TransInfo *t, TransData *td) } /* get constraint targets if needed */ - BKE_constraint_targets_for_solving_get(con, &cob, &targets, ctime); + BKE_constraint_targets_for_solving_get(&eval_ctx, con, &cob, &targets, ctime); /* do constraint */ cti->evaluate_constraint(con, &cob, &targets); @@ -3402,7 +3447,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) constraintTransLim(t, td); } -static void applyResize(TransInfo *t, const int mval[2]) +static void applyResize(TransInfo *t, const int UNUSED(mval[2])) { TransData *td; float mat[3][3]; @@ -3413,15 +3458,7 @@ static void applyResize(TransInfo *t, const int mval[2]) copy_v3_v3(t->values, t->auto_values); } else { - float ratio; - - /* for manipulator, center handle, the scaling can't be done relative to center */ - if ((t->flag & T_USES_MANIPULATOR) && t->con.mode == 0) { - ratio = 1.0f - ((t->mouse.imval[0] - mval[0]) + (t->mouse.imval[1] - mval[1])) / 100.0f; - } - else { - ratio = t->values[0]; - } + float ratio = t->values[0]; copy_v3_fl(t->values, ratio); @@ -5248,23 +5285,14 @@ static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3]) td->loc[1] = oldy; } -static void applyBoneSize(TransInfo *t, const int mval[2]) +static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2])) { TransData *td = t->data; float size[3], mat[3][3]; - float ratio; + float ratio = t->values[0]; int i; char str[UI_MAX_DRAW_STR]; - - // TRANSFORM_FIX_ME MOVE TO MOUSE INPUT - /* for manipulator, center handle, the scaling can't be done relative to center */ - if ((t->flag & T_USES_MANIPULATOR) && t->con.mode == 0) { - ratio = 1.0f - ((t->mouse.imval[0] - mval[0]) + (t->mouse.imval[1] - mval[1])) / 100.0f; - } - else { - ratio = t->values[0]; - } - + copy_v3_fl(size, ratio); snapGridIncrement(t, size); @@ -6856,10 +6884,12 @@ static void drawEdgeSlide(TransInfo *t) glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT); - glPushMatrix(); + gpuPushMatrix(); + gpuMultMatrix(t->obedit->obmat); - glMultMatrixf(t->obedit->obmat); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); if (sld->use_even == true) { float co_a[3], co_b[3], co_mark[3]; @@ -6873,39 +6903,35 @@ static void drawEdgeSlide(TransInfo *t) add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]); glLineWidth(line_size); - UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - glBegin(GL_LINES); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + immBeginAtMost(GWN_PRIM_LINES, 4); if (curr_sv->v_side[0]) { - glVertex3fv(curr_sv->v_side[0]->co); - glVertex3fv(curr_sv->v_co_orig); + immVertex3fv(pos, curr_sv->v_side[0]->co); + immVertex3fv(pos, curr_sv->v_co_orig); } if (curr_sv->v_side[1]) { - glVertex3fv(curr_sv->v_side[1]->co); - glVertex3fv(curr_sv->v_co_orig); + immVertex3fv(pos, curr_sv->v_side[1]->co); + immVertex3fv(pos, curr_sv->v_co_orig); } - glEnd(); + immEnd(); - UI_ThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); + immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); glPointSize(ctrl_size); - glBegin(GL_POINTS); + immBegin(GWN_PRIM_POINTS, 1); if (sld->flipped) { - if (curr_sv->v_side[1]) glVertex3fv(curr_sv->v_side[1]->co); + if (curr_sv->v_side[1]) immVertex3fv(pos, curr_sv->v_side[1]->co); } else { - if (curr_sv->v_side[0]) glVertex3fv(curr_sv->v_side[0]->co); + if (curr_sv->v_side[0]) immVertex3fv(pos, curr_sv->v_side[0]->co); } - glEnd(); + immEnd(); - UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); + immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); glPointSize(guide_size); - glBegin(GL_POINTS); -#if 0 - interp_v3_v3v3(co_mark, co_b, co_a, fac); - glVertex3fv(co_mark); -#endif + immBegin(GWN_PRIM_POINTS, 1); interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac); - glVertex3fv(co_mark); - glEnd(); + immVertex3fv(pos, co_mark); + immEnd(); } else { if (is_clamp == false) { @@ -6915,8 +6941,8 @@ static void drawEdgeSlide(TransInfo *t) const int alpha_shade = -160; glLineWidth(line_size); - UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - glBegin(GL_LINES); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + immBegin(GWN_PRIM_LINES, sld->totsv * 2); sv = sld->sv; for (i = 0; i < sld->totsv; i++, sv++) { @@ -6934,18 +6960,19 @@ static void drawEdgeSlide(TransInfo *t) add_v3_v3(a, sv->v_co_orig); add_v3_v3(b, sv->v_co_orig); - glVertex3fv(a); - glVertex3fv(b); + immVertex3fv(pos, a); + immVertex3fv(pos, b); } - glEnd(); + immEnd(); } else { BLI_assert(0); } } - glPopMatrix(); - glPopAttrib(); + immUnbindProgram(); + + gpuPopMatrix(); glDisable(GL_BLEND); @@ -7469,19 +7496,22 @@ static void drawVertSlide(TransInfo *t) glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT); - glPushMatrix(); - - glMultMatrixf(t->obedit->obmat); + gpuPushMatrix(); + gpuMultMatrix(t->obedit->obmat); glLineWidth(line_size); - UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - glBegin(GL_LINES); + + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + + immBegin(GWN_PRIM_LINES, sld->totsv * 2); if (is_clamp) { sv = sld->sv; for (i = 0; i < sld->totsv; i++, sv++) { - glVertex3fv(sv->co_orig_3d); - glVertex3fv(sv->co_link_orig_3d[sv->co_link_curr]); + immVertex3fv(shdr_pos, sv->co_orig_3d); + immVertex3fv(shdr_pos, sv->co_link_orig_3d[sv->co_link_curr]); } } else { @@ -7494,21 +7524,21 @@ static void drawVertSlide(TransInfo *t) add_v3_v3(a, sv->co_orig_3d); add_v3_v3(b, sv->co_orig_3d); - glVertex3fv(a); - glVertex3fv(b); + immVertex3fv(shdr_pos, a); + immVertex3fv(shdr_pos, b); } } - glEnd(); + immEnd(); glPointSize(ctrl_size); - glBegin(GL_POINTS); - glVertex3fv((sld->flipped && sld->use_even) ? + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(shdr_pos, (sld->flipped && sld->use_even) ? curr_sv->co_link_orig_3d[curr_sv->co_link_curr] : curr_sv->co_orig_3d); - glEnd(); + immEnd(); - glDisable(GL_BLEND); + immUnbindProgram(); /* direction from active vertex! */ if ((t->mval[0] != t->mouse.imval[0]) || @@ -7532,19 +7562,28 @@ static void drawVertSlide(TransInfo *t) add_v3_v3(co_dest_3d, curr_sv->co_orig_3d); - glLineWidth(1); - setlinestyle(1); + glLineWidth(1.0f); + + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); - cpack(0xffffff); - glBegin(GL_LINES); - glVertex3fv(curr_sv->co_orig_3d); - glVertex3fv(co_dest_3d); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(shdr_pos, curr_sv->co_orig_3d); + immVertex3fv(shdr_pos, co_dest_3d); + immEnd(); - glEnd(); + immUnbindProgram(); } - glPopMatrix(); - glPopAttrib(); + gpuPopMatrix(); if (v3d && v3d->zbuf) glEnable(GL_DEPTH_TEST); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 06a60456cdb..60ad61e3475 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -37,6 +37,8 @@ #include "ED_numinput.h" #include "ED_view3d.h" +#include "RE_engine.h" + #include "DNA_listBase.h" /* ************************** Types ***************************** */ @@ -50,6 +52,7 @@ struct Object; struct View3D; struct ScrArea; struct Scene; +struct SceneLayer; struct bConstraint; struct wmKeyMap; struct wmKeyConfig; @@ -59,6 +62,7 @@ struct wmTimer; struct ARegion; struct ReportList; struct EditBone; +struct RenderEngineType; struct SnapObjectContext; /* transinfo->redraw */ @@ -446,6 +450,7 @@ typedef struct TransInfo { short launch_event; /* event type used to launch transform */ short current_orientation; + TransformOrientation *custom_orientation; /* this gets used when current_orientation is V3D_MANIP_CUSTOM */ short twtype; /* backup from view3d, to restore on end */ short prop_mode; @@ -464,6 +469,8 @@ typedef struct TransInfo { struct ScrArea *sa; struct ARegion *ar; struct Scene *scene; + struct SceneLayer *scene_layer; + struct RenderEngineType *engine; struct ToolSettings *settings; struct wmTimer *animtimer; struct wmKeyMap *keymap; /* so we can do lookups for header text */ @@ -496,8 +503,7 @@ typedef struct TransInfo { #define T_CAMERA (1 << 4) // trans on points, having no rotation/scale #define T_POINTS (1 << 6) - // for manipulator exceptions, like scaling using center point, drawing help lines -#define T_USES_MANIPULATOR (1 << 7) +/* empty slot - (1 << 7) */ /* restrictions flags */ #define T_ALL_RESTRICTIONS ((1 << 8)|(1 << 9)|(1 << 10)) @@ -637,7 +643,10 @@ void flushTransMasking(TransInfo *t); void flushTransPaintCurve(TransInfo *t); void restoreBones(TransInfo *t); -/*********************** exported from transform_manipulator.c ********** */ +/*********************** transform_manipulator.c ********** */ + +#define MANIPULATOR_AXIS_LINE_WIDTH 2.0f + bool gimbal_axis(struct Object *ob, float gmat[3][3]); /* return 0 when no gimbal for selection */ /*********************** TransData Creation and General Handling *********** */ @@ -652,7 +661,7 @@ bool transdata_check_local_islands(TransInfo *t, short around); int count_set_pose_transflags(int *out_mode, short around, struct Object *ob); /* auto-keying stuff used by special_aftertrans_update */ -void autokeyframe_ob_cb_func(struct bContext *C, struct Scene *scene, struct View3D *v3d, struct Object *ob, int tmode); +void autokeyframe_ob_cb_func(struct bContext *C, struct Scene *scene, struct SceneLayer *sl, struct View3D *v3d, struct Object *ob, int tmode); void autokeyframe_pose_cb_func(struct bContext *C, struct Scene *scene, struct View3D *v3d, struct Object *ob, int tmode, short targetless_ik); /*********************** Constraints *****************************/ @@ -787,7 +796,7 @@ bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const floa struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3], const char *name, const bool overwrite); -bool applyTransformOrientation(const struct bContext *C, float mat[3][3], char r_name[64], int index); +bool applyTransformOrientation(const struct TransformOrientation *ts, float r_mat[3][3], char r_name[64]); #define ORIENTATION_NONE 0 #define ORIENTATION_NORMAL 1 diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 5621eede543..4e409e7f77f 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -40,9 +40,11 @@ #include "DNA_space_types.h" #include "DNA_view3d_types.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" + #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_string.h" @@ -651,7 +653,7 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[]) */ void setUserConstraint(TransInfo *t, short orientation, int mode, const char ftext[]) { - char text[40]; + char text[256]; switch (orientation) { case V3D_MANIP_GLOBAL: @@ -683,10 +685,15 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char fte BLI_snprintf(text, sizeof(text), ftext, IFACE_("gimbal")); setConstraint(t, t->spacemtx, mode, text); break; - default: /* V3D_MANIP_CUSTOM */ - BLI_snprintf(text, sizeof(text), ftext, t->spacename); + case V3D_MANIP_CUSTOM: + { + char orientation_str[128]; + BLI_snprintf(orientation_str, sizeof(orientation_str), "%s \"%s\"", + IFACE_("custom orientation"), t->custom_orientation->name); + BLI_snprintf(text, sizeof(text), ftext, orientation_str); setConstraint(t, t->spacemtx, mode, text); break; + } } t->con.orientation = orientation; @@ -704,8 +711,6 @@ void drawConstraint(TransInfo *t) return; if (!(tc->mode & CON_APPLY)) return; - if (t->flag & T_USES_MANIPULATOR) - return; if (t->flag & T_NO_CONSTRAINT) return; @@ -715,7 +720,6 @@ void drawConstraint(TransInfo *t) else { if (tc->mode & CON_SELECT) { float vec[3]; - char col2[3] = {255, 255, 255}; int depth_test_enabled; convertViewVec(t, vec, (t->mval[0] - t->con.imval[0]), (t->mval[1] - t->con.imval[1])); @@ -725,18 +729,29 @@ void drawConstraint(TransInfo *t) drawLine(t, t->center_global, tc->mtx[1], 'Y', 0); drawLine(t, t->center_global, tc->mtx[2], 'Z', 0); - glColor3ubv((GLubyte *)col2); - depth_test_enabled = glIsEnabled(GL_DEPTH_TEST); if (depth_test_enabled) glDisable(GL_DEPTH_TEST); - setlinestyle(1); - glBegin(GL_LINES); - glVertex3fv(t->center_global); - glVertex3fv(vec); - glEnd(); - setlinestyle(0); + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f); + immUniform1f("dash_width", 2.0f); + immUniform1f("dash_factor", 0.5f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(shdr_pos, t->center_global); + immVertex3fv(shdr_pos, vec); + immEnd(); + + immUnbindProgram(); if (depth_test_enabled) glEnable(GL_DEPTH_TEST); @@ -762,8 +777,6 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) float tmat[4][4], imat[4][4]; int depth_test_enabled; - UI_ThemeColor(TH_GRID); - if (t->spacetype == SPACE_VIEW3D && rv3d != NULL) { copy_m4_m4(tmat, rv3d->viewmat); invert_m4_m4(imat, tmat); @@ -773,13 +786,13 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) unit_m4(imat); } - glPushMatrix(); + gpuPushMatrix(); if (t->spacetype == SPACE_VIEW3D) { /* pass */ } else if (t->spacetype == SPACE_IMAGE) { - glScalef(1.0f / t->aspect[0], 1.0f / t->aspect[1], 1.0f); + gpuScale2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]); } else if (ELEM(t->spacetype, SPACE_IPO, SPACE_ACTION)) { /* only scale y */ @@ -789,21 +802,28 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) float ysize = BLI_rctf_size_y(datamask); float xmask = BLI_rcti_size_x(mask); float ymask = BLI_rcti_size_y(mask); - glScalef(1.0f, (ysize / xsize) * (xmask / ymask), 1.0f); + gpuScale2f(1.0f, (ysize / xsize) * (xmask / ymask)); } depth_test_enabled = glIsEnabled(GL_DEPTH_TEST); if (depth_test_enabled) glDisable(GL_DEPTH_TEST); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_GRID); + set_inverted_drawing(1); - drawcircball(GL_LINE_LOOP, t->center_global, t->prop_size, imat); + imm_drawcircball(t->center_global, t->prop_size, imat, pos); set_inverted_drawing(0); + immUnbindProgram(); + if (depth_test_enabled) glEnable(GL_DEPTH_TEST); - glPopMatrix(); + gpuPopMatrix(); } } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index af83b666bba..0905e3785da 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -68,10 +68,10 @@ #include "BKE_context.h" #include "BKE_crazyspace.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_gpencil.h" +#include "BKE_layer.h" #include "BKE_key.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -118,6 +118,7 @@ #include "RNA_access.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" #include "transform.h" #include "bmesh.h" @@ -285,13 +286,13 @@ static void set_prop_dist(TransInfo *t, const bool with_dist) static void createTransTexspace(TransInfo *t) { - Scene *scene = t->scene; + SceneLayer *sl = t->scene_layer; TransData *td; Object *ob; ID *id; short *texflag; - ob = OBACT; + ob = OBACT(sl); if (ob == NULL) { // Shouldn't logically happen, but still... t->total = 0; @@ -836,14 +837,9 @@ void transform_autoik_update(TransInfo *t, short mode) changed |= pchan_autoik_adjust(pchan, *chainlen); } -#ifdef WITH_LEGACY_DEPSGRAPH - if (!DEG_depsgraph_use_legacy()) -#endif - { - if (changed) { - /* TODO(sergey): Consider doing partial update only. */ - DAG_relations_tag_update(G.main); - } + if (changed) { + /* TODO(sergey): Consider doing partial update only. */ + DEG_relations_tag_update(G.main); } } @@ -853,9 +849,7 @@ static void pose_grab_with_ik_clear(Object *ob) bKinematicConstraint *data; bPoseChannel *pchan; bConstraint *con, *next; -#ifdef WITH_LEGACY_DEPSGRAPH - bool need_dependency_update = false; -#endif + bool relations_changed = false; for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { /* clear all temporary lock flags */ @@ -869,10 +863,9 @@ static void pose_grab_with_ik_clear(Object *ob) if (con->type == CONSTRAINT_TYPE_KINEMATIC) { data = con->data; if (data->flag & CONSTRAINT_IK_TEMP) { + relations_changed = true; + /* iTaSC needs clear for removed constraints */ -#ifdef WITH_LEGACY_DEPSGRAPH - need_dependency_update = true; -#endif BIK_clear_data(ob->pose); BLI_remlink(&pchan->constraints, con); @@ -887,12 +880,9 @@ static void pose_grab_with_ik_clear(Object *ob) } } -#ifdef WITH_LEGACY_DEPSGRAPH - if (!DEG_depsgraph_use_legacy() && need_dependency_update) -#endif - { + if (relations_changed) { /* TODO(sergey): Consider doing partial update only. */ - DAG_relations_tag_update(G.main); + DEG_relations_tag_update(G.main); } } @@ -1046,13 +1036,8 @@ static short pose_grab_with_ik(Object *ob) /* iTaSC needs clear for new IK constraints */ if (tot_ik) { BIK_clear_data(ob->pose); -#ifdef WITH_LEGACY_DEPSGRAPH - if (!DEG_depsgraph_use_legacy()) -#endif - { - /* TODO(sergey): Consuder doing partial update only. */ - DAG_relations_tag_update(G.main); - } + /* TODO(sergey): Consuder doing partial update only. */ + DEG_relations_tag_update(G.main); } return (tot_ik) ? 1 : 0; @@ -1908,7 +1893,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) Base *base = CTX_data_active_base(C); Object *ob = CTX_data_active_object(C); ParticleEditSettings *pset = PE_settings(t->scene); - PTCacheEdit *edit = PE_get_current(t->scene, ob); + PTCacheEdit *edit = PE_get_current(t->scene, t->scene_layer, ob); ParticleSystem *psys = NULL; ParticleSystemModifierData *psmd = NULL; PTCacheEditPoint *point; @@ -2025,8 +2010,9 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) void flushTransParticles(TransInfo *t) { Scene *scene = t->scene; - Object *ob = OBACT; - PTCacheEdit *edit = PE_get_current(scene, ob); + SceneLayer *sl = t->scene_layer; + Object *ob = OBACT(sl); + PTCacheEdit *edit = PE_get_current(scene, sl, ob); ParticleSystem *psys = edit->psys; ParticleSystemModifierData *psmd = NULL; PTCacheEditPoint *point; @@ -2065,7 +2051,9 @@ void flushTransParticles(TransInfo *t) point->flag |= PEP_EDIT_RECALC; } - PE_update_object(scene, OBACT, 1); + EvaluationContext eval_ctx; + CTX_data_eval_ctx(t->context, &eval_ctx); + PE_update_object(&eval_ctx, scene, sl, OBACT(sl), 1); } /* ********************* mesh ****************** */ @@ -2477,6 +2465,7 @@ static void createTransEditVerts(TransInfo *t) { TransData *tob = NULL; TransDataExtension *tx = NULL; + EvaluationContext eval_ctx; BMEditMesh *em = BKE_editmesh_from_object(t->obedit); Mesh *me = t->obedit->data; BMesh *bm = em->bm; @@ -2495,6 +2484,10 @@ static void createTransEditVerts(TransInfo *t) int island_info_tot; int *island_vert_map = NULL; + DEG_evaluation_context_init_from_scene(&eval_ctx, + t->scene, t->scene_layer, t->engine, + DAG_EVAL_VIEWPORT); + /* Even for translation this is needed because of island-orientation, see: T51651. */ const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS); /* Original index of our connected vertex when connected distances are calculated. @@ -2578,7 +2571,7 @@ static void createTransEditVerts(TransInfo *t) if (modifiers_isCorrectableDeformed(t->scene, t->obedit)) { /* check if we can use deform matrices for modifier from the * start up to stack, they are more accurate than quats */ - totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(t->scene, t->obedit, em, &defmats, &defcos); + totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(&eval_ctx, t->scene, t->obedit, em, &defmats, &defcos); } /* if we still have more modifiers, also do crazyspace @@ -2591,7 +2584,7 @@ static void createTransEditVerts(TransInfo *t) if (totleft > 0) #endif { - mappedcos = BKE_crazyspace_get_mapped_editverts(t->scene, t->obedit); + mappedcos = BKE_crazyspace_get_mapped_editverts(&eval_ctx, t->scene, t->obedit); quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats"); BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode); if (mappedcos) @@ -2960,7 +2953,6 @@ static void createTransUVs(bContext *C, TransInfo *t) const bool is_prop_connected = (t->flag & T_PROP_CONNECTED) != 0; const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS); const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); if (!ED_space_image_show_uvedit(sima, t->obedit)) return; @@ -2984,10 +2976,9 @@ static void createTransUVs(bContext *C, TransInfo *t) } BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); BMLoop *l; - if (!uvedit_face_visible_test(scene, ima, efa, tf)) { + if (!uvedit_face_visible_test(scene, ima, efa)) { BM_elem_flag_disable(efa, BM_ELEM_TAG); continue; } @@ -5419,6 +5410,9 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) Scene *scene = t->scene; bool constinv; bool skip_invert = false; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(t->context, &eval_ctx); if (t->mode != TFM_DUMMY && ob->rigidbody_object) { float rot[3][3], scale[3]; @@ -5466,11 +5460,11 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) if (skip_invert == false && constinv == false) { ob->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc_time checks this */ - BKE_object_where_is_calc(t->scene, ob); + BKE_object_where_is_calc(&eval_ctx, t->scene, ob); ob->transflag &= ~OB_NO_CONSTRAINTS; } else - BKE_object_where_is_calc(t->scene, ob); + BKE_object_where_is_calc(&eval_ctx, t->scene, ob); td->ob = ob; @@ -5542,12 +5536,15 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) /* it deselects Bases, so we have to call the clear function always after */ static void set_trans_object_base_flags(TransInfo *t) { + /* TODO(sergey): Get rid of global, use explicit main. */ + Main *bmain = G.main; + SceneLayer *sl = t->scene_layer; Scene *scene = t->scene; - View3D *v3d = t->view; + Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, sl, true); /* * if Base selected and has parent selected: - * base->flag = BA_WAS_SEL + * base->flag_legacy = BA_WAS_SEL */ Base *base; @@ -5556,32 +5553,36 @@ static void set_trans_object_base_flags(TransInfo *t) return; /* makes sure base flags and object flags are identical */ - BKE_scene_base_flag_to_objects(t->scene); + BKE_scene_base_flag_to_objects(t->scene_layer); /* Make sure depsgraph is here. */ - DAG_scene_relations_update(G.main, t->scene); + DEG_graph_relations_update(depsgraph, bmain, scene, sl); /* handle pending update events, otherwise they got copied below */ - for (base = scene->base.first; base; base = base->next) { + EvaluationContext eval_ctx; + DEG_evaluation_context_init_from_scene(&eval_ctx, + t->scene, t->scene_layer, t->engine, + DAG_EVAL_VIEWPORT); + for (base = sl->object_bases.first; base; base = base->next) { if (base->object->recalc & OB_RECALC_ALL) { /* TODO(sergey): Ideally, it's not needed. */ - BKE_object_handle_update(G.main->eval_ctx, t->scene, base->object); + BKE_object_handle_update(&eval_ctx, t->scene, base->object); } } - for (base = scene->base.first; base; base = base->next) { - base->flag &= ~BA_WAS_SEL; + for (base = sl->object_bases.first; base; base = base->next) { + base->flag_legacy &= ~BA_WAS_SEL; - if (TESTBASELIB_BGMODE(v3d, scene, base)) { + if (TESTBASELIB_BGMODE(base)) { Object *ob = base->object; Object *parsel = ob->parent; /* if parent selected, deselect */ while (parsel) { - if (parsel->flag & SELECT) { - Base *parbase = BKE_scene_base_find(scene, parsel); + if (parsel->base_flag & BASE_SELECTED) { + Base *parbase = BKE_scene_layer_base_find(sl, parsel); if (parbase) { /* in rare cases this can fail */ - if (TESTBASELIB_BGMODE(v3d, scene, parbase)) { + if (TESTBASELIB_BGMODE(parbase)) { break; } } @@ -5594,27 +5595,27 @@ static void set_trans_object_base_flags(TransInfo *t) if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)) { - base->flag |= BA_TRANSFORM_CHILD; + base->flag_legacy |= BA_TRANSFORM_CHILD; } else { - base->flag &= ~SELECT; - base->flag |= BA_WAS_SEL; + base->flag &= ~BASE_SELECTED; + base->flag_legacy |= BA_WAS_SEL; } } - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } } /* all recalc flags get flushed to all layers, so a layer flip later on works fine */ - DAG_scene_flush_update(G.main, t->scene, -1, 0); + DEG_graph_flush_update(bmain, depsgraph); /* and we store them temporal in base (only used for transform code) */ /* this because after doing updates, the object->recalc is cleared */ - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { if (base->object->recalc & OB_RECALC_OB) - base->flag |= BA_HAS_RECALC_OB; + base->flag_legacy |= BA_HAS_RECALC_OB; if (base->object->recalc & OB_RECALC_DATA) - base->flag |= BA_HAS_RECALC_DATA; + base->flag_legacy |= BA_HAS_RECALC_DATA; } } @@ -5636,8 +5637,11 @@ static bool mark_children(Object *ob) static int count_proportional_objects(TransInfo *t) { int total = 0; + /* TODO(sergey): Get rid of global, use explicit main. */ + Main *bmain = G.main; + SceneLayer *sl = t->scene_layer; Scene *scene = t->scene; - View3D *v3d = t->view; + Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, sl, true); Base *base; /* rotations around local centers are allowed to propagate, so we take all objects */ @@ -5645,8 +5649,8 @@ static int count_proportional_objects(TransInfo *t) (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))) { /* mark all parents */ - for (base = scene->base.first; base; base = base->next) { - if (TESTBASELIB_BGMODE(v3d, scene, base)) { + for (base = sl->object_bases.first; base; base = base->next) { + if (TESTBASELIB_BGMODE(base)) { Object *parent = base->object->parent; /* flag all parents */ @@ -5658,25 +5662,27 @@ static int count_proportional_objects(TransInfo *t) } /* mark all children */ - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { /* all base not already selected or marked that is editable */ - if ((base->object->flag & (SELECT | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && - (BASE_EDITABLE_BGMODE(v3d, scene, base))) + if ((base->object->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && + (base->flag & BASE_SELECTED) == 0 && + (BASE_EDITABLE_BGMODE(base))) { mark_children(base->object); } } } - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { Object *ob = base->object; /* if base is not selected, not a parent of selection or not a child of selection and it is editable */ - if ((ob->flag & (SELECT | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && - (BASE_EDITABLE_BGMODE(v3d, scene, base))) + if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && + (base->flag & BASE_SELECTED) == 0 && + (BASE_EDITABLE_BGMODE(base))) { - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); total += 1; } @@ -5684,16 +5690,16 @@ static int count_proportional_objects(TransInfo *t) /* all recalc flags get flushed to all layers, so a layer flip later on works fine */ - DAG_scene_relations_update(G.main, t->scene); - DAG_scene_flush_update(G.main, t->scene, -1, 0); + DEG_graph_relations_update(depsgraph, bmain, scene, sl); + DEG_graph_flush_update(bmain, depsgraph); /* and we store them temporal in base (only used for transform code) */ /* this because after doing updates, the object->recalc is cleared */ - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { if (base->object->recalc & OB_RECALC_OB) - base->flag |= BA_HAS_RECALC_OB; + base->flag_legacy |= BA_HAS_RECALC_OB; if (base->object->recalc & OB_RECALC_DATA) - base->flag |= BA_HAS_RECALC_DATA; + base->flag_legacy |= BA_HAS_RECALC_DATA; } return total; @@ -5701,14 +5707,15 @@ static int count_proportional_objects(TransInfo *t) static void clear_trans_object_base_flags(TransInfo *t) { - Scene *sce = t->scene; + SceneLayer *sl = t->scene_layer; Base *base; - for (base = sce->base.first; base; base = base->next) { - if (base->flag & BA_WAS_SEL) - base->flag |= SELECT; + for (base = sl->object_bases.first; base; base = base->next) { + if (base->flag_legacy & BA_WAS_SEL) { + base->flag |= BASE_SELECTED; + } - base->flag &= ~(BA_WAS_SEL | BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT); + base->flag_legacy &= ~(BA_WAS_SEL | BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT); } } @@ -5716,7 +5723,7 @@ static void clear_trans_object_base_flags(TransInfo *t) * tmode: should be a transform mode */ // NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases -void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, int tmode) +void autokeyframe_ob_cb_func(bContext *C, Scene *scene, SceneLayer *sl, View3D *v3d, Object *ob, int tmode) { ID *id = &ob->id; FCurve *fcu; @@ -5765,7 +5772,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, } else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) { if (v3d->around == V3D_AROUND_ACTIVE) { - if (ob != OBACT) + if (ob != OBACT(sl)) do_loc = true; } else if (v3d->around == V3D_AROUND_CURSOR) @@ -5776,7 +5783,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, } else if (tmode == TFM_RESIZE) { if (v3d->around == V3D_AROUND_ACTIVE) { - if (ob != OBACT) + if (ob != OBACT(sl)) do_loc = true; } else if (v3d->around == V3D_AROUND_CURSOR) @@ -5954,7 +5961,7 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o */ if (C && (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { //ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear - ED_pose_recalculate_paths(scene, ob); + ED_pose_recalculate_paths(C, scene, ob); } } else { @@ -6109,10 +6116,13 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t) * */ void special_aftertrans_update(bContext *C, TransInfo *t) { + EvaluationContext eval_ctx; Object *ob; // short redrawipo=0, resetslowpar=1; const bool canceled = (t->state == TRANS_CANCEL); const bool duplicate = (t->mode == TFM_TIME_DUPLICATE); + + CTX_data_eval_ctx(C, &eval_ctx); /* early out when nothing happened */ if (t->total == 0 || t->mode == TFM_DUMMY) @@ -6264,9 +6274,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t) // fixme... some of this stuff is not good if (ob) { if (ob->pose || BKE_key_from_object(ob)) - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); else - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } /* 3 cases here for curve cleanups: @@ -6452,7 +6462,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) * we need to update the pose otherwise no updates get called during * transform and the auto-ik is not applied. see [#26164] */ struct Object *pose_ob = t->poseobj; - BKE_pose_where_is(t->scene, pose_ob); + BKE_pose_where_is(&eval_ctx, t->scene, pose_ob); } /* set BONE_TRANSFORM flags for autokey, manipulator draw might have changed them */ @@ -6476,24 +6486,24 @@ void special_aftertrans_update(bContext *C, TransInfo *t) /* automatic inserting of keys and unkeyed tagging - only if transform wasn't canceled (or TFM_DUMMY) */ if (!canceled && (t->mode != TFM_DUMMY)) { autokeyframe_pose_cb_func(C, t->scene, (View3D *)t->view, ob, t->mode, targetless_ik); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } else if (arm->flag & ARM_DELAYDEFORM) { /* old optimize trick... this enforces to bypass the depgraph */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); ob->recalc = 0; // is set on OK position already by recalcData() } else - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } else if (t->options & CTX_PAINT_CURVE) { /* pass */ } - else if ((t->scene->basact) && - (ob = t->scene->basact->object) && + else if ((t->scene_layer->basact) && + (ob = t->scene_layer->basact->object) && (ob->mode & OB_MODE_PARTICLE_EDIT) && - PE_get_current(t->scene, ob)) + PE_get_current(t->scene, t->scene_layer, ob)) { /* do nothing */ } @@ -6524,17 +6534,17 @@ void special_aftertrans_update(bContext *C, TransInfo *t) /* pointcache refresh */ if (BKE_ptcache_object_reset(t->scene, ob, PTCACHE_RESET_OUTDATED)) - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* Needed for proper updating of "quick cached" dynamics. */ /* Creates troubles for moving animated objects without */ /* autokey though, probably needed is an anim sys override? */ /* Please remove if some other solution is found. -jahka */ - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); /* Set autokey if necessary */ if (!canceled) { - autokeyframe_ob_cb_func(C, t->scene, (View3D *)t->view, ob, t->mode); + autokeyframe_ob_cb_func(C, t->scene, t->scene_layer, (View3D *)t->view, ob, t->mode); } /* restore rigid body transform */ @@ -6569,8 +6579,6 @@ int special_transform_moving(TransInfo *t) static void createTransObject(bContext *C, TransInfo *t) { - Scene *scene = t->scene; - TransData *td = NULL; TransDataExtension *tx; const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; @@ -6620,15 +6628,16 @@ static void createTransObject(bContext *C, TransInfo *t) CTX_DATA_END; if (is_prop_edit) { - View3D *v3d = t->view; + SceneLayer *sl = t->scene_layer; Base *base; - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { Object *ob = base->object; /* if base is not selected, not a parent of selection or not a child of selection and it is editable */ - if ((ob->flag & (SELECT | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && - BASE_EDITABLE_BGMODE(v3d, scene, base)) + if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && + (base->flag & BASE_SELECTED) == 0 && + BASE_EDITABLE_BGMODE(base)) { td->protectflag = ob->protectflag; td->ext = tx; @@ -8075,7 +8084,8 @@ static void createTransGPencil(bContext *C, TransInfo *t) void createTransData(bContext *C, TransInfo *t) { Scene *scene = t->scene; - Object *ob = OBACT; + SceneLayer *sl = t->scene_layer; + Object *ob = OBACT(sl); /* if tests must match recalcData for correct updates */ if (t->options & CTX_TEXTURE) { @@ -8240,17 +8250,16 @@ void createTransData(bContext *C, TransInfo *t) * lines below just check is also visible */ Object *ob_armature = modifiers_isDeformedByArmature(ob); if (ob_armature && ob_armature->mode & OB_MODE_POSE) { - Base *base_arm = BKE_scene_base_find(t->scene, ob_armature); + Base *base_arm = BKE_scene_layer_base_find(t->scene_layer, ob_armature); if (base_arm) { - View3D *v3d = t->view; - if (BASE_VISIBLE(v3d, base_arm)) { + if (BASE_VISIBLE(base_arm)) { createTransPose(t, ob_armature); } } } } - else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, ob))) { + else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, sl, ob))) { createTransParticleVerts(C, t); t->flag |= T_POINTS; diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 277e01d1e2b..8d2fb595e24 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -62,8 +62,8 @@ #include "RNA_access.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" #include "BIK_api.h" @@ -71,7 +71,6 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_lattice.h" #include "BKE_library.h" @@ -82,6 +81,9 @@ #include "BKE_editmesh.h" #include "BKE_tracking.h" #include "BKE_mask.h" +#include "BKE_workspace.h" + +#include "DEG_depsgraph.h" #include "ED_anim_api.h" #include "ED_armature.h" @@ -102,6 +104,8 @@ #include "WM_types.h" #include "WM_api.h" +#include "RE_engine.h" + #include "UI_resources.h" #include "UI_view2d.h" @@ -314,7 +318,7 @@ static bool fcu_test_selected(FCurve *fcu) /* helper for recalcData() - for Action Editor transforms */ static void recalcData_actedit(TransInfo *t) { - Scene *scene = t->scene; + SceneLayer *sl = t->scene_layer; SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first; bAnimContext ac = {NULL}; @@ -325,7 +329,8 @@ static void recalcData_actedit(TransInfo *t) /* initialize relevant anim-context 'context' data from TransInfo data */ /* NOTE: sync this with the code in ANIM_animdata_get_context() */ ac.scene = t->scene; - ac.obact = OBACT; + ac.scene_layer = t->scene_layer; + ac.obact = OBACT(sl); ac.sa = t->sa; ac.ar = t->ar; ac.sl = (t->sa) ? t->sa->spacedata.first : NULL; @@ -362,7 +367,7 @@ static void recalcData_actedit(TransInfo *t) static void recalcData_graphedit(TransInfo *t) { SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first; - Scene *scene; + SceneLayer *sl = t->scene_layer; ListBase anim_data = {NULL, NULL}; bAnimContext ac = {NULL}; @@ -373,8 +378,9 @@ static void recalcData_graphedit(TransInfo *t) /* initialize relevant anim-context 'context' data from TransInfo data */ /* NOTE: sync this with the code in ANIM_animdata_get_context() */ - scene = ac.scene = t->scene; - ac.obact = OBACT; + ac.scene = t->scene; + ac.scene_layer = t->scene_layer; + ac.obact = OBACT(sl); ac.sa = t->sa; ac.ar = t->ar; ac.sl = (t->sa) ? t->sa->spacedata.first : NULL; @@ -636,7 +642,7 @@ static void recalcData_mask_common(TransInfo *t) flushTransMasking(t); - DAG_id_tag_update(&mask->id, 0); + DEG_id_tag_update(&mask->id, 0); } /* helper for recalcData() - for Image Editor transforms */ @@ -655,7 +661,7 @@ static void recalcData_image(TransInfo *t) if (sima->flag & SI_LIVE_UNWRAP) ED_uvedit_live_unwrap_re_solve(); - DAG_id_tag_update(t->obedit->data, 0); + DEG_id_tag_update(t->obedit->data, 0); } } @@ -698,7 +704,7 @@ static void recalcData_spaceclip(TransInfo *t) track = track->next; } - DAG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&clip->id, 0); } else if (t->options & CTX_MASK) { recalcData_mask_common(t); @@ -708,7 +714,10 @@ static void recalcData_spaceclip(TransInfo *t) /* helper for recalcData() - for object transforms, typically in the 3D view */ static void recalcData_objects(TransInfo *t) { - Base *base = t->scene->basact; + Base *base = t->scene_layer->basact; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(t->context, &eval_ctx); if (t->obedit) { if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) { @@ -721,7 +730,7 @@ static void recalcData_objects(TransInfo *t) applyProject(t); } - DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */ + DEG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */ if (t->state == TRANS_CANCEL) { while (nu) { @@ -745,7 +754,7 @@ static void recalcData_objects(TransInfo *t) applyProject(t); } - DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */ + DEG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */ if (la->editlatt->latt->flag & LT_OUTSIDE) outside_lattice(la->editlatt->latt); } @@ -767,7 +776,7 @@ static void recalcData_objects(TransInfo *t) projectVertSlideData(t, false); } - DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */ + DEG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */ EDBM_mesh_normals_update(em); BKE_editmesh_tessface_calc(em); @@ -865,7 +874,7 @@ static void recalcData_objects(TransInfo *t) if (t->state != TRANS_CANCEL) { applyProject(t); } - DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */ + DEG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */ } } else if ((t->flag & T_POSE) && t->poseobj) { @@ -888,14 +897,14 @@ static void recalcData_objects(TransInfo *t) /* old optimize trick... this enforces to bypass the depgraph */ if (!(arm->flag & ARM_DELAYDEFORM)) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */ + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */ /* transformation of pose may affect IK tree, make sure it is rebuilt */ BIK_clear_data(ob->pose); } else - BKE_pose_where_is(t->scene, ob); + BKE_pose_where_is(&eval_ctx, t->scene, ob); } - else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, base->object)) { + else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, t->scene_layer, base->object)) { if (t->state != TRANS_CANCEL) { applyProject(t); } @@ -925,16 +934,16 @@ static void recalcData_objects(TransInfo *t) // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes? if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) { animrecord_check_state(t->scene, &ob->id, t->animtimer); - autokeyframe_ob_cb_func(t->context, t->scene, (View3D *)t->view, ob, t->mode); + autokeyframe_ob_cb_func(t->context, t->scene, t->scene_layer, (View3D *)t->view, ob, t->mode); } /* sets recalc flags fully, instead of flushing existing ones * otherwise proxies don't function correctly */ - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); if (t->flag & T_TEXTURE) - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } } @@ -1031,11 +1040,10 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis if (t->spacetype == SPACE_VIEW3D) { View3D *v3d = t->view; - glPushMatrix(); - - //if (t->obedit) glLoadMatrixf(t->obedit->obmat); // sets opengl viewing - - + gpuPushMatrix(); + + // if (t->obedit) gpuLoadMatrix(t->obedit->obmat); // sets opengl viewing + copy_v3_v3(v3, dir); mul_v3_fl(v3, v3d->far); @@ -1049,15 +1057,20 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis UI_GetThemeColor3ubv(TH_GRID, col); } UI_make_axis_color(col, col2, axis); - glColor3ubv(col2); - - setlinestyle(0); - glBegin(GL_LINES); - glVertex3fv(v1); - glVertex3fv(v2); - glEnd(); - - glPopMatrix(); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(col2); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + immEnd(); + + immUnbindProgram(); + + gpuPopMatrix(); } } @@ -1103,15 +1116,19 @@ static int initTransInfo_edit_pet_to_flag(const int proportional) void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event) { Scene *sce = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); ToolSettings *ts = CTX_data_tool_settings(C); ARegion *ar = CTX_wm_region(C); ScrArea *sa = CTX_wm_area(C); Object *obedit = CTX_data_edit_object(C); Object *ob = CTX_data_active_object(C); bGPdata *gpd = CTX_data_gpencil_data(C); + RenderEngineType *engine = CTX_data_engine(C); PropertyRNA *prop; t->scene = sce; + t->scene_layer = sl; + t->engine = engine; t->sa = sa; t->ar = ar; t->obedit = obedit; @@ -1219,7 +1236,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->animtimer = (animscreen) ? animscreen->animtimer : NULL; /* turn manipulator off during transform */ - // FIXME: but don't do this when USING the manipulator... if (t->flag & T_MODAL) { t->twtype = v3d->twtype; v3d->twtype = 0; @@ -1234,6 +1250,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } t->current_orientation = v3d->twmode; + t->custom_orientation = BKE_workspace_transform_orientation_find( + CTX_wm_workspace(C), v3d->custom_orientation_index); /* exceptional case */ if (t->around == V3D_AROUND_LOCAL_ORIGINS) { @@ -1324,11 +1342,22 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) && RNA_property_is_set(op->ptr, prop))) { - t->current_orientation = RNA_property_enum_get(op->ptr, prop); + short orientation = RNA_property_enum_get(op->ptr, prop); + TransformOrientation *custom_orientation = NULL; - if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C)) { - t->current_orientation = V3D_MANIP_GLOBAL; + if (orientation >= V3D_MANIP_CUSTOM) { + if (orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C)) { + orientation = V3D_MANIP_GLOBAL; + } + else { + custom_orientation = BKE_workspace_transform_orientation_find( + CTX_wm_workspace(C), orientation - V3D_MANIP_CUSTOM); + orientation = V3D_MANIP_CUSTOM; + } } + + t->current_orientation = orientation; + t->custom_orientation = custom_orientation; } if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) && @@ -1773,8 +1802,8 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) } } else if (t->flag & T_POSE) { - Scene *scene = t->scene; - Object *ob = OBACT; + SceneLayer *sl = t->scene_layer; + Object *ob = OBACT(sl); if (ob) { bPoseChannel *pchan = BKE_pose_channel_active(ob); if (pchan && (!select_only || (pchan->bone->flag & BONE_SELECTED))) { @@ -1784,7 +1813,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) } } else if (t->options & CTX_PAINT_CURVE) { - Paint *p = BKE_paint_get_active(t->scene); + Paint *p = BKE_paint_get_active(t->scene, t->scene_layer); Brush *br = p->brush; PaintCurve *pc = br->paint_curve; copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]); @@ -1793,9 +1822,10 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) } else { /* object mode */ - Scene *scene = t->scene; - Object *ob = OBACT; - if (ob && (!select_only || (ob->flag & SELECT))) { + SceneLayer *sl = t->scene_layer; + Object *ob = OBACT(sl); + Base *base = BASACT(sl); + if (ob && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) { copy_v3_v3(r_center, ob->obmat[3]); ok = true; } diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 9a362ee609f..be33cb85f0e 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -59,6 +59,7 @@ #include "BKE_editmesh.h" #include "BKE_lattice.h" #include "BKE_gpencil.h" +#include "BKE_workspace.h" #include "BIF_gl.h" @@ -67,16 +68,25 @@ #include "ED_armature.h" #include "ED_curve.h" +#include "ED_object.h" #include "ED_particle.h" #include "ED_view3d.h" #include "ED_gpencil.h" +#include "ED_screen.h" +#include "ED_manipulator_library.h" #include "UI_resources.h" /* local module include */ #include "transform.h" +#include "MEM_guardedalloc.h" + #include "GPU_select.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" + +#define USE_AXIS_BOUNDS /* return codes for select, and drawing flags */ @@ -88,35 +98,348 @@ #define MAN_ROT_X (1 << 3) #define MAN_ROT_Y (1 << 4) #define MAN_ROT_Z (1 << 5) -#define MAN_ROT_V (1 << 6) -#define MAN_ROT_T (1 << 7) -#define MAN_ROT_C (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z | MAN_ROT_V | MAN_ROT_T) +#define MAN_ROT_C (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z) #define MAN_SCALE_X (1 << 8) #define MAN_SCALE_Y (1 << 9) #define MAN_SCALE_Z (1 << 10) #define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z) -/* color codes */ - -#define MAN_RGB 0 -#define MAN_GHOST 1 -#define MAN_MOVECOL 2 - /* threshold for testing view aligned manipulator axis */ #define TW_AXIS_DOT_MIN 0.02f #define TW_AXIS_DOT_MAX 0.1f +/* axes as index */ +enum { + MAN_AXIS_TRANS_X = 0, + MAN_AXIS_TRANS_Y, + MAN_AXIS_TRANS_Z, + MAN_AXIS_TRANS_C, + + MAN_AXIS_TRANS_XY, + MAN_AXIS_TRANS_YZ, + MAN_AXIS_TRANS_ZX, +#define MAN_AXIS_RANGE_TRANS_START MAN_AXIS_TRANS_X +#define MAN_AXIS_RANGE_TRANS_END (MAN_AXIS_TRANS_ZX + 1) + + MAN_AXIS_ROT_X, + MAN_AXIS_ROT_Y, + MAN_AXIS_ROT_Z, + MAN_AXIS_ROT_C, + MAN_AXIS_ROT_T, /* trackball rotation */ +#define MAN_AXIS_RANGE_ROT_START MAN_AXIS_ROT_X +#define MAN_AXIS_RANGE_ROT_END (MAN_AXIS_ROT_T + 1) + + MAN_AXIS_SCALE_X, + MAN_AXIS_SCALE_Y, + MAN_AXIS_SCALE_Z, + MAN_AXIS_SCALE_C, + MAN_AXIS_SCALE_XY, + MAN_AXIS_SCALE_YZ, + MAN_AXIS_SCALE_ZX, +#define MAN_AXIS_RANGE_SCALE_START MAN_AXIS_SCALE_X +#define MAN_AXIS_RANGE_SCALE_END (MAN_AXIS_SCALE_ZX + 1) + + MAN_AXIS_LAST = MAN_AXIS_RANGE_SCALE_END, +}; + +/* axis types */ +enum { + MAN_AXES_ALL = 0, + MAN_AXES_TRANSLATE, + MAN_AXES_ROTATE, + MAN_AXES_SCALE, +}; + +typedef struct ManipulatorGroup { + bool all_hidden; + + struct wmManipulator *manipulators[MAN_AXIS_LAST]; +} ManipulatorGroup; + struct TransformBounds { float center[3]; /* Center for transform widget. */ float min[3], max[3]; /* Boundbox of selection for transform widget. */ + +#ifdef USE_AXIS_BOUNDS + /* Normalized axis */ + float axis[3][3]; + float axis_min[3], axis_max[3]; +#endif }; +/* -------------------------------------------------------------------- */ +/** \name Utilities + * \{ */ + +/* loop over axes */ +#define MAN_ITER_AXES_BEGIN(axis, axis_idx) \ + { \ + wmManipulator *axis; \ + int axis_idx; \ + for (axis_idx = 0; axis_idx < MAN_AXIS_LAST; axis_idx++) { \ + axis = manipulator_get_axis_from_index(man, axis_idx); + +#define MAN_ITER_AXES_END \ + } \ + } ((void)0) + +static wmManipulator *manipulator_get_axis_from_index(const ManipulatorGroup *man, const short axis_idx) +{ + BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN_AXIS_TRANS_X, (float)MAN_AXIS_LAST)); + return man->manipulators[axis_idx]; +} + +static short manipulator_get_axis_type(const int axis_idx) +{ + if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) { + return MAN_AXES_TRANSLATE; + } + if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) { + return MAN_AXES_ROTATE; + } + if (axis_idx >= MAN_AXIS_RANGE_SCALE_START && axis_idx < MAN_AXIS_RANGE_SCALE_END) { + return MAN_AXES_SCALE; + } + BLI_assert(0); + return -1; +} + +static uint manipulator_orientation_axis(const int axis_idx, bool *r_is_plane) +{ + switch (axis_idx) { + case MAN_AXIS_TRANS_YZ: + case MAN_AXIS_SCALE_YZ: + if (r_is_plane) { + *r_is_plane = true; + } + ATTR_FALLTHROUGH; + case MAN_AXIS_TRANS_X: + case MAN_AXIS_ROT_X: + case MAN_AXIS_SCALE_X: + return 0; + + case MAN_AXIS_TRANS_ZX: + case MAN_AXIS_SCALE_ZX: + if (r_is_plane) { + *r_is_plane = true; + } + ATTR_FALLTHROUGH; + case MAN_AXIS_TRANS_Y: + case MAN_AXIS_ROT_Y: + case MAN_AXIS_SCALE_Y: + return 1; + + case MAN_AXIS_TRANS_XY: + case MAN_AXIS_SCALE_XY: + if (r_is_plane) { + *r_is_plane = true; + } + ATTR_FALLTHROUGH; + case MAN_AXIS_TRANS_Z: + case MAN_AXIS_ROT_Z: + case MAN_AXIS_SCALE_Z: + return 2; + } + return 3; +} + +static bool manipulator_is_axis_visible( + const View3D *v3d, const RegionView3D *rv3d, + const float idot[3], const int axis_type, const int axis_idx) +{ + bool is_plane = false; + const uint aidx_norm = manipulator_orientation_axis(axis_idx, &is_plane); + /* don't draw axis perpendicular to the view */ + if (aidx_norm < 3) { + float idot_axis = idot[aidx_norm]; + if (is_plane) { + idot_axis = 1.0f - idot_axis; + } + if (idot_axis < TW_AXIS_DOT_MIN) { + return false; + } + } + + if ((axis_type == MAN_AXES_TRANSLATE && !(v3d->twtype & V3D_MANIP_TRANSLATE)) || + (axis_type == MAN_AXES_ROTATE && !(v3d->twtype & V3D_MANIP_ROTATE)) || + (axis_type == MAN_AXES_SCALE && !(v3d->twtype & V3D_MANIP_SCALE))) + { + return false; + } + + switch (axis_idx) { + case MAN_AXIS_TRANS_X: + return (rv3d->twdrawflag & MAN_TRANS_X); + case MAN_AXIS_TRANS_Y: + return (rv3d->twdrawflag & MAN_TRANS_Y); + case MAN_AXIS_TRANS_Z: + return (rv3d->twdrawflag & MAN_TRANS_Z); + case MAN_AXIS_TRANS_C: + return (rv3d->twdrawflag & MAN_TRANS_C); + case MAN_AXIS_ROT_X: + return (rv3d->twdrawflag & MAN_ROT_X); + case MAN_AXIS_ROT_Y: + return (rv3d->twdrawflag & MAN_ROT_Y); + case MAN_AXIS_ROT_Z: + return (rv3d->twdrawflag & MAN_ROT_Z); + case MAN_AXIS_ROT_C: + case MAN_AXIS_ROT_T: + return (rv3d->twdrawflag & MAN_ROT_C); + case MAN_AXIS_SCALE_X: + return (rv3d->twdrawflag & MAN_SCALE_X); + case MAN_AXIS_SCALE_Y: + return (rv3d->twdrawflag & MAN_SCALE_Y); + case MAN_AXIS_SCALE_Z: + return (rv3d->twdrawflag & MAN_SCALE_Z); + case MAN_AXIS_SCALE_C: + return (rv3d->twdrawflag & MAN_SCALE_C && (v3d->twtype & V3D_MANIP_TRANSLATE) == 0); + case MAN_AXIS_TRANS_XY: + return (rv3d->twdrawflag & MAN_TRANS_X && + rv3d->twdrawflag & MAN_TRANS_Y && + (v3d->twtype & V3D_MANIP_ROTATE) == 0); + case MAN_AXIS_TRANS_YZ: + return (rv3d->twdrawflag & MAN_TRANS_Y && + rv3d->twdrawflag & MAN_TRANS_Z && + (v3d->twtype & V3D_MANIP_ROTATE) == 0); + case MAN_AXIS_TRANS_ZX: + return (rv3d->twdrawflag & MAN_TRANS_Z && + rv3d->twdrawflag & MAN_TRANS_X && + (v3d->twtype & V3D_MANIP_ROTATE) == 0); + case MAN_AXIS_SCALE_XY: + return (rv3d->twdrawflag & MAN_SCALE_X && + rv3d->twdrawflag & MAN_SCALE_Y && + (v3d->twtype & V3D_MANIP_TRANSLATE) == 0 && + (v3d->twtype & V3D_MANIP_ROTATE) == 0); + case MAN_AXIS_SCALE_YZ: + return (rv3d->twdrawflag & MAN_SCALE_Y && + rv3d->twdrawflag & MAN_SCALE_Z && + (v3d->twtype & V3D_MANIP_TRANSLATE) == 0 && + (v3d->twtype & V3D_MANIP_ROTATE) == 0); + case MAN_AXIS_SCALE_ZX: + return (rv3d->twdrawflag & MAN_SCALE_Z && + rv3d->twdrawflag & MAN_SCALE_X && + (v3d->twtype & V3D_MANIP_TRANSLATE) == 0 && + (v3d->twtype & V3D_MANIP_ROTATE) == 0); + } + return false; +} + +static void manipulator_get_axis_color( + const int axis_idx, const float idot[3], + float r_col[4], float r_col_hi[4]) +{ + /* alpha values for normal/highlighted states */ + const float alpha = 0.6f; + const float alpha_hi = 1.0f; + float alpha_fac; + + bool is_plane = false; + const int axis_idx_norm = manipulator_orientation_axis(axis_idx, &is_plane); + /* get alpha fac based on axis angle, to fade axis out when hiding it because it points towards view */ + if (axis_idx_norm < 3) { + float idot_axis = idot[axis_idx_norm]; + if (is_plane) { + idot_axis = 1.0f - idot_axis; + } + alpha_fac = (idot_axis > TW_AXIS_DOT_MAX) ? + 1.0f : (idot_axis < TW_AXIS_DOT_MIN) ? + 0.0f : ((idot_axis - TW_AXIS_DOT_MIN) / (TW_AXIS_DOT_MAX - TW_AXIS_DOT_MIN)); + } + else { + /* trackball rotation axis is a special case, we only draw a slight overlay */ + alpha_fac = (axis_idx == MAN_AXIS_ROT_T) ? 0.1f : 1.0f; + } + + switch (axis_idx) { + case MAN_AXIS_TRANS_X: + case MAN_AXIS_ROT_X: + case MAN_AXIS_SCALE_X: + case MAN_AXIS_TRANS_YZ: + case MAN_AXIS_SCALE_YZ: + UI_GetThemeColor4fv(TH_AXIS_X, r_col); + break; + case MAN_AXIS_TRANS_Y: + case MAN_AXIS_ROT_Y: + case MAN_AXIS_SCALE_Y: + case MAN_AXIS_TRANS_ZX: + case MAN_AXIS_SCALE_ZX: + UI_GetThemeColor4fv(TH_AXIS_Y, r_col); + break; + case MAN_AXIS_TRANS_Z: + case MAN_AXIS_ROT_Z: + case MAN_AXIS_SCALE_Z: + case MAN_AXIS_TRANS_XY: + case MAN_AXIS_SCALE_XY: + UI_GetThemeColor4fv(TH_AXIS_Z, r_col); + break; + case MAN_AXIS_TRANS_C: + case MAN_AXIS_ROT_C: + case MAN_AXIS_SCALE_C: + case MAN_AXIS_ROT_T: + copy_v4_fl(r_col, 1.0f); + break; + } + + copy_v4_v4(r_col_hi, r_col); + + r_col[3] = alpha * alpha_fac; + r_col_hi[3] = alpha_hi * alpha_fac; +} + +static void manipulator_get_axis_constraint(const int axis_idx, int r_axis[3]) +{ + zero_v3_int(r_axis); + + switch (axis_idx) { + case MAN_AXIS_TRANS_X: + case MAN_AXIS_ROT_X: + case MAN_AXIS_SCALE_X: + r_axis[0] = 1; + break; + case MAN_AXIS_TRANS_Y: + case MAN_AXIS_ROT_Y: + case MAN_AXIS_SCALE_Y: + r_axis[1] = 1; + break; + case MAN_AXIS_TRANS_Z: + case MAN_AXIS_ROT_Z: + case MAN_AXIS_SCALE_Z: + r_axis[2] = 1; + break; + case MAN_AXIS_TRANS_XY: + case MAN_AXIS_SCALE_XY: + r_axis[0] = r_axis[1] = 1; + break; + case MAN_AXIS_TRANS_YZ: + case MAN_AXIS_SCALE_YZ: + r_axis[1] = r_axis[2] = 1; + break; + case MAN_AXIS_TRANS_ZX: + case MAN_AXIS_SCALE_ZX: + r_axis[2] = r_axis[0] = 1; + break; + default: + break; + } +} + + +/* **************** Preparation Stuff **************** */ + /* transform widget center calc helper for below */ static void calc_tw_center(struct TransformBounds *tbounds, const float co[3]) { minmax_v3v3_v3(tbounds->min, tbounds->max, co); add_v3_v3(tbounds->center, co); + +#ifdef USE_AXIS_BOUNDS + for (int i = 0; i < 3; i++) { + const float d = dot_v3v3(tbounds->axis[i], co); + tbounds->axis_min[i] = min_ff(d, tbounds->axis_min[i]); + tbounds->axis_max[i] = max_ff(d, tbounds->axis_max[i]); + } +#endif } static void protectflag_to_drawflags(short protectflag, short *drawflags) @@ -261,16 +584,19 @@ bool gimbal_axis(Object *ob, float gmat[3][3]) /* centroid, boundbox, of selection */ /* returns total items selected */ -static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbounds) +static int calc_manipulator_stats( + const bContext *C, bool use_only_center, + struct TransformBounds *tbounds) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; Base *base; - Object *ob = OBACT; + Object *ob = OBACT(sl); bGPdata *gpd = CTX_data_gpencil_data(C); const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)); int a, totsel = 0; @@ -278,12 +604,104 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo /* transform widget matrix */ unit_m4(rv3d->twmat); +#ifdef USE_AXIS_BOUNDS + unit_m3(rv3d->tw_axis_matrix); + zero_v3(rv3d->tw_axis_min); + zero_v3(rv3d->tw_axis_max); +#endif + rv3d->twdrawflag = 0xFFFF; + /* global, local or normal orientation? + * if we could check 'totsel' now, this should be skipped with no selection. */ + if (ob && !is_gp_edit) { + + switch (v3d->twmode) { + + case V3D_MANIP_GLOBAL: + { + break; /* nothing to do */ + } + case V3D_MANIP_GIMBAL: + { + float mat[3][3]; + if (gimbal_axis(ob, mat)) { + copy_m4_m3(rv3d->twmat, mat); + break; + } + /* if not gimbal, fall through to normal */ + ATTR_FALLTHROUGH; + } + case V3D_MANIP_NORMAL: + { + if (obedit || ob->mode & OB_MODE_POSE) { + float mat[3][3]; + ED_getTransformOrientationMatrix(C, mat, v3d->around); + copy_m4_m3(rv3d->twmat, mat); + break; + } + /* no break we define 'normal' as 'local' in Object mode */ + ATTR_FALLTHROUGH; + } + case V3D_MANIP_LOCAL: + { + if (ob->mode & OB_MODE_POSE) { + /* each bone moves on its own local axis, but to avoid confusion, + * use the active pones axis for display [#33575], this works as expected on a single bone + * and users who select many bones will understand whats going on and what local means + * when they start transforming */ + float mat[3][3]; + ED_getTransformOrientationMatrix(C, mat, v3d->around); + copy_m4_m3(rv3d->twmat, mat); + break; + } + copy_m4_m4(rv3d->twmat, ob->obmat); + normalize_m4(rv3d->twmat); + break; + } + case V3D_MANIP_VIEW: + { + float mat[3][3]; + copy_m3_m4(mat, rv3d->viewinv); + normalize_m3(mat); + copy_m4_m3(rv3d->twmat, mat); + break; + } + case V3D_MANIP_CUSTOM: + { + TransformOrientation *custom_orientation = BKE_workspace_transform_orientation_find( + CTX_wm_workspace(C), v3d->custom_orientation_index); + float mat[3][3]; + + if (applyTransformOrientation(custom_orientation, mat, NULL)) { + copy_m4_m3(rv3d->twmat, mat); + } + break; + } + } + } + /* transform widget centroid/center */ INIT_MINMAX(tbounds->min, tbounds->max); zero_v3(tbounds->center); +#ifdef USE_AXIS_BOUNDS + copy_m3_m4(tbounds->axis, rv3d->twmat); + if (ob && ob->mode & OB_MODE_EDIT) { + float diff_mat[3][3]; + copy_m3_m4(diff_mat, ob->obmat); + normalize_m3(diff_mat); + invert_m3(diff_mat); + mul_m3_m3m3(tbounds->axis, tbounds->axis, diff_mat); + normalize_m3(tbounds->axis); + } + + for (int i = 0; i < 3; i++) { + tbounds->axis_min[i] = +FLT_MAX; + tbounds->axis_max[i] = -FLT_MAX; + } +#endif + if (is_gp_edit) { float diff_mat[4][4]; float fpt[3]; @@ -330,13 +748,11 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo /* selection center */ if (totsel) { - mul_v3_fl(tbounds->center, 1.0f / (float)totsel); + mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */ } } else if (obedit) { ob = obedit; - if ((ob->lay & v3d->lay) == 0) return 0; - if (obedit->type == OB_MESH) { BMEditMesh *em = BKE_editmesh_from_object(obedit); BMEditSelection ese; @@ -442,15 +858,11 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo } else { if (bezt->f1 & SELECT) { - calc_tw_center( - tbounds, - bezt->vec[(v3d->around == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 0]); + calc_tw_center(tbounds, bezt->vec[(v3d->around == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 0]); totsel++; } if (bezt->f3 & SELECT) { - calc_tw_center( - tbounds, - bezt->vec[(v3d->around == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 2]); + calc_tw_center(tbounds, bezt->vec[(v3d->around == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 2]); totsel++; } } @@ -512,7 +924,7 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo /* selection center */ if (totsel) { - mul_v3_fl(tbounds->center, 1.0f / (float)totsel); + mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid! mul_m4_v3(obedit->obmat, tbounds->center); mul_m4_v3(obedit->obmat, tbounds->min); mul_m4_v3(obedit->obmat, tbounds->max); @@ -523,8 +935,6 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo int mode = TFM_ROTATION; // mislead counting bones... bah. We don't know the manipulator mode, could be mixed bool ok = false; - if ((ob->lay & v3d->lay) == 0) return 0; - if ((v3d->around == V3D_AROUND_ACTIVE) && (pchan = BKE_pose_channel_active(ob))) { /* doesn't check selection or visibility intentionally */ Bone *bone = pchan->bone; @@ -552,7 +962,7 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo } if (ok) { - mul_v3_fl(tbounds->center, 1.0f / (float)totsel); + mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid! mul_m4_v3(ob->obmat, tbounds->center); mul_m4_v3(ob->obmat, tbounds->min); mul_m4_v3(ob->obmat, tbounds->max); @@ -562,7 +972,7 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo /* pass */ } else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) { - PTCacheEdit *edit = PE_get_current(scene, ob); + PTCacheEdit *edit = PE_get_current(scene, sl, ob); PTCacheEditPoint *point; PTCacheEditKey *ek; int k; @@ -582,20 +992,30 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo /* selection center */ if (totsel) - mul_v3_fl(tbounds->center, 1.0f / (float)totsel); + mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid! } } else { /* we need the one selected object, if its not active */ - ob = OBACT; - if (ob && !(ob->flag & SELECT)) ob = NULL; + base = BASACT(sl); + ob = OBACT(sl); + if (base && ((base->flag & BASE_SELECTED) == 0)) ob = NULL; - for (base = scene->base.first; base; base = base->next) { - if (TESTBASELIB(v3d, base)) { + for (base = sl->object_bases.first; base; base = base->next) { + if (TESTBASELIB(base)) { if (ob == NULL) ob = base->object; - calc_tw_center(tbounds, base->object->obmat[3]); + if (use_only_center || base->object->bb == NULL) { + calc_tw_center(tbounds, base->object->obmat[3]); + } + else { + for (uint j = 0; j < 8; j++) { + float co[3]; + mul_v3_m4v3(co, base->object->obmat, base->object->bb->vec[j]); + calc_tw_center(tbounds, co); + } + } protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag); totsel++; } @@ -603,1378 +1023,598 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo /* selection center */ if (totsel) { - mul_v3_fl(tbounds->center, 1.0f / (float)totsel); + mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid! } } - /* global, local or normal orientation? */ - if (ob && totsel && !is_gp_edit) { - - switch (v3d->twmode) { - - case V3D_MANIP_GLOBAL: - { - break; /* nothing to do */ - } - case V3D_MANIP_GIMBAL: - { - float mat[3][3]; - if (gimbal_axis(ob, mat)) { - copy_m4_m3(rv3d->twmat, mat); - break; - } - /* if not gimbal, fall through to normal */ - ATTR_FALLTHROUGH; - } - case V3D_MANIP_NORMAL: - { - if (obedit || ob->mode & OB_MODE_POSE) { - float mat[3][3]; - ED_getTransformOrientationMatrix(C, mat, v3d->around); - copy_m4_m3(rv3d->twmat, mat); - break; - } - /* no break we define 'normal' as 'local' in Object mode */ - ATTR_FALLTHROUGH; - } - case V3D_MANIP_LOCAL: - { - if (ob->mode & OB_MODE_POSE) { - /* each bone moves on its own local axis, but to avoid confusion, - * use the active pones axis for display [#33575], this works as expected on a single bone - * and users who select many bones will understand whats going on and what local means - * when they start transforming */ - float mat[3][3]; - ED_getTransformOrientationMatrix(C, mat, v3d->around); - copy_m4_m3(rv3d->twmat, mat); - break; - } - copy_m4_m4(rv3d->twmat, ob->obmat); - normalize_m4(rv3d->twmat); - break; - } - case V3D_MANIP_VIEW: - { - float mat[3][3]; - copy_m3_m4(mat, rv3d->viewinv); - normalize_m3(mat); - copy_m4_m3(rv3d->twmat, mat); - break; - } - default: /* V3D_MANIP_CUSTOM */ - { - float mat[3][3]; - if (applyTransformOrientation(C, mat, NULL, v3d->twmode - V3D_MANIP_CUSTOM)) { - copy_m4_m3(rv3d->twmat, mat); - } - break; - } - } - + if (totsel == 0) { + unit_m4(rv3d->twmat); + } + else { +#ifdef USE_AXIS_BOUNDS + copy_v3_v3(rv3d->tw_axis_min, tbounds->axis_min); + copy_v3_v3(rv3d->tw_axis_max, tbounds->axis_max); + copy_m3_m3(rv3d->tw_axis_matrix, tbounds->axis); +#endif } return totsel; } -/* don't draw axis perpendicular to the view */ -static void test_manipulator_axis(const bContext *C) +static void manipulator_get_idot(RegionView3D *rv3d, float r_idot[3]) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); float view_vec[3], axis_vec[3]; - float idot; - int i; - - const int twdrawflag_axis[3] = { - (MAN_TRANS_X | MAN_SCALE_X), - (MAN_TRANS_Y | MAN_SCALE_Y), - (MAN_TRANS_Z | MAN_SCALE_Z)}; - ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], view_vec); - - for (i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { normalize_v3_v3(axis_vec, rv3d->twmat[i]); - rv3d->tw_idot[i] = idot = 1.0f - fabsf(dot_v3v3(view_vec, axis_vec)); - if (idot < TW_AXIS_DOT_MIN) { - rv3d->twdrawflag &= ~twdrawflag_axis[i]; - } + r_idot[i] = 1.0f - fabsf(dot_v3v3(view_vec, axis_vec)); } } - -/* ******************** DRAWING STUFFIES *********** */ - -static float screen_aligned(RegionView3D *rv3d, float mat[4][4]) -{ - glTranslate3fv(mat[3]); - - /* sets view screen aligned */ - glRotatef(-360.0f * saacos(rv3d->viewquat[0]) / (float)M_PI, rv3d->viewquat[1], rv3d->viewquat[2], rv3d->viewquat[3]); - - return len_v3(mat[0]); /* draw scale */ -} - - -/* radring = radius of doughnut rings - * radhole = radius hole - * start = starting segment (based on nrings) - * end = end segment - * nsides = amount of points in ring - * nrigns = amount of rings - */ -static void partial_doughnut(float radring, float radhole, int start, int end, int nsides, int nrings) +static void manipulator_prepare_mat( + const bContext *C, View3D *v3d, RegionView3D *rv3d, const struct TransformBounds *tbounds) { - float theta, phi, theta1; - float cos_theta, sin_theta; - float cos_theta1, sin_theta1; - float ring_delta, side_delta; - int i, j, do_caps = true; - - if (start == 0 && end == nrings) do_caps = false; - - ring_delta = 2.0f * (float)M_PI / (float)nrings; - side_delta = 2.0f * (float)M_PI / (float)nsides; - - theta = (float)M_PI + 0.5f * ring_delta; - cos_theta = cosf(theta); - sin_theta = sinf(theta); - - for (i = nrings - 1; i >= 0; i--) { - theta1 = theta + ring_delta; - cos_theta1 = cosf(theta1); - sin_theta1 = sinf(theta1); - - if (do_caps && i == start) { // cap - glBegin(GL_POLYGON); - phi = 0.0; - for (j = nsides; j >= 0; j--) { - float cos_phi, sin_phi, dist; - - phi += side_delta; - cos_phi = cosf(phi); - sin_phi = sinf(phi); - dist = radhole + radring * cos_phi; - - glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi); - } - glEnd(); - } - if (i >= start && i <= end) { - glBegin(GL_QUAD_STRIP); - phi = 0.0; - for (j = nsides; j >= 0; j--) { - float cos_phi, sin_phi, dist; - - phi += side_delta; - cos_phi = cosf(phi); - sin_phi = sinf(phi); - dist = radhole + radring * cos_phi; - - glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi); - glVertex3f(cos_theta * dist, -sin_theta * dist, radring * sin_phi); + Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + + switch (v3d->around) { + case V3D_AROUND_CENTER_BOUNDS: + case V3D_AROUND_ACTIVE: + { + bGPdata *gpd = CTX_data_gpencil_data(C); + Object *ob = OBACT(sl); + + if (((v3d->around == V3D_AROUND_ACTIVE) && (scene->obedit == NULL)) && + ((gpd == NULL) || !(gpd->flag & GP_DATA_STROKE_EDITMODE)) && + (!(ob->mode & OB_MODE_POSE))) + { + copy_v3_v3(rv3d->twmat[3], ob->obmat[3]); } - glEnd(); - } - - if (do_caps && i == end) { // cap - glBegin(GL_POLYGON); - phi = 0.0; - for (j = nsides; j >= 0; j--) { - float cos_phi, sin_phi, dist; - - phi -= side_delta; - cos_phi = cosf(phi); - sin_phi = sinf(phi); - dist = radhole + radring * cos_phi; - - glVertex3f(cos_theta * dist, -sin_theta * dist, radring * sin_phi); + else { + mid_v3_v3v3(rv3d->twmat[3], tbounds->min, tbounds->max); } - glEnd(); + break; } - - - theta = theta1; - cos_theta = cos_theta1; - sin_theta = sin_theta1; - } -} - -static char axisBlendAngle(float idot) -{ - if (idot > TW_AXIS_DOT_MAX) { - return 255; - } - else if (idot < TW_AXIS_DOT_MIN) { - return 0; - } - else { - return (char)(255.0f * (idot - TW_AXIS_DOT_MIN) / (TW_AXIS_DOT_MAX - TW_AXIS_DOT_MIN)); + case V3D_AROUND_LOCAL_ORIGINS: + case V3D_AROUND_CENTER_MEAN: + copy_v3_v3(rv3d->twmat[3], tbounds->center); + break; + case V3D_AROUND_CURSOR: + copy_v3_v3(rv3d->twmat[3], ED_view3d_cursor3d_get(scene, v3d)); + break; } } -/* three colors can be set: - * gray for ghosting - * moving: in transform theme color - * else the red/green/blue +/** + * Sets up \a r_start and \a r_len to define arrow line range. + * Needed to adjust line drawing for combined manipulator axis types. */ -static void manipulator_setcolor(View3D *v3d, char axis, int colcode, unsigned char alpha) -{ - unsigned char col[4] = {0}; - col[3] = alpha; - - if (colcode == MAN_GHOST) { - col[3] = 70; - } - else if (colcode == MAN_MOVECOL) { - UI_GetThemeColor3ubv(TH_TRANSFORM, col); - } - else { - switch (axis) { - case 'C': - UI_GetThemeColor3ubv(TH_TRANSFORM, col); - if (v3d->twmode == V3D_MANIP_LOCAL) { - col[0] = col[0] > 200 ? 255 : col[0] + 55; - col[1] = col[1] > 200 ? 255 : col[1] + 55; - col[2] = col[2] > 200 ? 255 : col[2] + 55; - } - else if (v3d->twmode == V3D_MANIP_NORMAL) { - col[0] = col[0] < 55 ? 0 : col[0] - 55; - col[1] = col[1] < 55 ? 0 : col[1] - 55; - col[2] = col[2] < 55 ? 0 : col[2] - 55; - } - break; - case 'X': - UI_GetThemeColor3ubv(TH_AXIS_X, col); - break; - case 'Y': - UI_GetThemeColor3ubv(TH_AXIS_Y, col); - break; - case 'Z': - UI_GetThemeColor3ubv(TH_AXIS_Z, col); - break; - default: - BLI_assert(0); - break; - } - } - - glColor4ubv(col); -} - -static void manipulator_axis_order(RegionView3D *rv3d, int r_axis_order[3]) +static void manipulator_line_range(const View3D *v3d, const short axis_type, float *r_start, float *r_len) { - float axis_values[3]; - float vec[3]; - - ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], vec); + const float ofs = 0.2f; - axis_values[0] = -dot_v3v3(rv3d->twmat[0], vec); - axis_values[1] = -dot_v3v3(rv3d->twmat[1], vec); - axis_values[2] = -dot_v3v3(rv3d->twmat[2], vec); + *r_start = 0.2f; + *r_len = 1.0f; - axis_sort_v3(axis_values, r_axis_order); -} - -/* viewmatrix should have been set OK, also no shademode! */ -static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int colcode, - int flagx, int flagy, int flagz, int axis, - const bool is_picksel) -{ - switch (axis) { - case 0: - /* axes */ - if (flagx) { - if (is_picksel) { - if (flagx & MAN_SCALE_X) GPU_select_load_id(MAN_SCALE_X); - else if (flagx & MAN_TRANS_X) GPU_select_load_id(MAN_TRANS_X); - } - else { - manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0])); - } - glBegin(GL_LINES); - glVertex3f(0.2f, 0.0f, 0.0f); - glVertex3f(1.0f, 0.0f, 0.0f); - glEnd(); + switch (axis_type) { + case MAN_AXES_TRANSLATE: + if (v3d->twtype & V3D_MANIP_SCALE) { + *r_start = *r_len - ofs + 0.075f; } - break; - case 1: - if (flagy) { - if (is_picksel) { - if (flagy & MAN_SCALE_Y) GPU_select_load_id(MAN_SCALE_Y); - else if (flagy & MAN_TRANS_Y) GPU_select_load_id(MAN_TRANS_Y); - } - else { - manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1])); - } - glBegin(GL_LINES); - glVertex3f(0.0f, 0.2f, 0.0f); - glVertex3f(0.0f, 1.0f, 0.0f); - glEnd(); + if (v3d->twtype & V3D_MANIP_ROTATE) { + *r_len += ofs; } break; - case 2: - if (flagz) { - if (is_picksel) { - if (flagz & MAN_SCALE_Z) GPU_select_load_id(MAN_SCALE_Z); - else if (flagz & MAN_TRANS_Z) GPU_select_load_id(MAN_TRANS_Z); - } - else { - manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2])); - } - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.2f); - glVertex3f(0.0f, 0.0f, 1.0f); - glEnd(); + case MAN_AXES_SCALE: + if (v3d->twtype & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE)) { + *r_len -= ofs + 0.025f; } break; } -} -static void draw_manipulator_axes(View3D *v3d, RegionView3D *rv3d, int colcode, - int flagx, int flagy, int flagz, - const int axis_order[3], const bool is_picksel) -{ - int i; - for (i = 0; i < 3; i++) { - draw_manipulator_axes_single(v3d, rv3d, colcode, flagx, flagy, flagz, axis_order[i], is_picksel); - } -} - -static void preOrthoFront(const bool ortho, float twmat[4][4], int axis) -{ - if (ortho == false) { - float omat[4][4]; - copy_m4_m4(omat, twmat); - orthogonalize_m4(omat, axis); - glPushMatrix(); - glMultMatrixf(omat); - glFrontFace(is_negative_m4(omat) ? GL_CW : GL_CCW); - } -} - -static void postOrtho(const bool ortho) -{ - if (ortho == false) { - glPopMatrix(); - } -} -BLI_INLINE bool manipulator_rotate_is_visible(const int drawflags) -{ - return (drawflags & (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z)); + *r_len -= *r_start; } -static void draw_manipulator_rotate( - View3D *v3d, RegionView3D *rv3d, const int drawflags, const int combo, - const bool is_moving, const bool is_picksel) -{ - double plane[4]; - float matt[4][4]; - float size, unitmat[4][4]; - float cywid = 0.33f * 0.01f * (float)U.tw_handlesize; - float cusize = cywid * 0.65f; - int arcs = (G.debug_value != 2); - const int colcode = (is_moving) ? MAN_MOVECOL : MAN_RGB; - bool ortho; - - /* skip drawing if all axes are locked */ - if (manipulator_rotate_is_visible(drawflags) == false) return; - - /* Init stuff */ - glDisable(GL_DEPTH_TEST); - unit_m4(unitmat); - - /* prepare for screen aligned draw */ - size = len_v3(rv3d->twmat[0]); - glPushMatrix(); - glTranslate3fv(rv3d->twmat[3]); - - if (arcs) { - /* clipplane makes nice handles, calc here because of multmatrix but with translate! */ - copy_v3db_v3fl(plane, rv3d->viewinv[2]); - plane[3] = -0.02f * size; // clip just a bit more - glClipPlane(GL_CLIP_PLANE0, plane); - } - /* sets view screen aligned */ - glRotatef(-360.0f * saacos(rv3d->viewquat[0]) / (float)M_PI, rv3d->viewquat[1], rv3d->viewquat[2], rv3d->viewquat[3]); - - /* Screen aligned help circle */ - if (arcs) { - if (is_picksel == false) { - UI_ThemeColorShade(TH_BACK, -30); - drawcircball(GL_LINE_LOOP, unitmat[3], size, unitmat); - } - } - - /* Screen aligned trackball rot circle */ - if (drawflags & MAN_ROT_T) { - if (is_picksel) GPU_select_load_id(MAN_ROT_T); - else UI_ThemeColor(TH_TRANSFORM); +/** \} */ - drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f * size, unitmat); - } - /* Screen aligned view rot circle */ - if (drawflags & MAN_ROT_V) { - if (is_picksel) GPU_select_load_id(MAN_ROT_V); - else UI_ThemeColor(TH_TRANSFORM); - drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f * size, unitmat); - - if (is_moving) { - float vec[3]; - vec[0] = 0; // XXX (float)(t->mouse.imval[0] - t->center2d[0]); - vec[1] = 0; // XXX (float)(t->mouse.imval[1] - t->center2d[1]); - vec[2] = 0.0f; - normalize_v3_length(vec, 1.2f * size); - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3fv(vec); - glEnd(); - } - } - glPopMatrix(); - - - ortho = is_orthogonal_m4(rv3d->twmat); - - /* apply the transform delta */ - if (is_moving) { - copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3] - // XXX mul_m4_m3m4(matt, t->mat, rv3d->twmat); - if (ortho) { - glMultMatrixf(matt); - glFrontFace(is_negative_m4(matt) ? GL_CW : GL_CCW); - } - } - else { - if (ortho) { - glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW : GL_CCW); - glMultMatrixf(rv3d->twmat); - } - } +/* -------------------------------------------------------------------- */ +/** \name Transform Manipulator + * \{ */ - /* axes */ - if (arcs == 0) { - if (!is_picksel) { - if ((combo & V3D_MANIP_SCALE) == 0) { - /* axis */ - if ((drawflags & MAN_ROT_X) || (is_moving && (drawflags & MAN_ROT_Z))) { - preOrthoFront(ortho, rv3d->twmat, 2); - manipulator_setcolor(v3d, 'X', colcode, 255); - glBegin(GL_LINES); - glVertex3f(0.2f, 0.0f, 0.0f); - glVertex3f(1.0f, 0.0f, 0.0f); - glEnd(); - postOrtho(ortho); - } - if ((drawflags & MAN_ROT_Y) || (is_moving && (drawflags & MAN_ROT_X))) { - preOrthoFront(ortho, rv3d->twmat, 0); - manipulator_setcolor(v3d, 'Y', colcode, 255); - glBegin(GL_LINES); - glVertex3f(0.0f, 0.2f, 0.0f); - glVertex3f(0.0f, 1.0f, 0.0f); - glEnd(); - postOrtho(ortho); - } - if ((drawflags & MAN_ROT_Z) || (is_moving && (drawflags & MAN_ROT_Y))) { - preOrthoFront(ortho, rv3d->twmat, 1); - manipulator_setcolor(v3d, 'Z', colcode, 255); - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.2f); - glVertex3f(0.0f, 0.0f, 1.0f); - glEnd(); - postOrtho(ortho); - } - } - } - } - - if (arcs == 0 && is_moving) { - - /* Z circle */ - if (drawflags & MAN_ROT_Z) { - preOrthoFront(ortho, matt, 2); - if (is_picksel) GPU_select_load_id(MAN_ROT_Z); - else manipulator_setcolor(v3d, 'Z', colcode, 255); - drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat); - postOrtho(ortho); - } - /* X circle */ - if (drawflags & MAN_ROT_X) { - preOrthoFront(ortho, matt, 0); - if (is_picksel) GPU_select_load_id(MAN_ROT_X); - else manipulator_setcolor(v3d, 'X', colcode, 255); - glRotatef(90.0, 0.0, 1.0, 0.0); - drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat); - glRotatef(-90.0, 0.0, 1.0, 0.0); - postOrtho(ortho); - } - /* Y circle */ - if (drawflags & MAN_ROT_Y) { - preOrthoFront(ortho, matt, 1); - if (is_picksel) GPU_select_load_id(MAN_ROT_Y); - else manipulator_setcolor(v3d, 'Y', colcode, 255); - glRotatef(-90.0, 1.0, 0.0, 0.0); - drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat); - glRotatef(90.0, 1.0, 0.0, 0.0); - postOrtho(ortho); - } - } - // donut arcs - if (arcs) { - glEnable(GL_CLIP_PLANE0); - - /* Z circle */ - if (drawflags & MAN_ROT_Z) { - preOrthoFront(ortho, rv3d->twmat, 2); - if (is_picksel) GPU_select_load_id(MAN_ROT_Z); - else manipulator_setcolor(v3d, 'Z', colcode, 255); - partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48); - postOrtho(ortho); - } - /* X circle */ - if (drawflags & MAN_ROT_X) { - preOrthoFront(ortho, rv3d->twmat, 0); - if (is_picksel) GPU_select_load_id(MAN_ROT_X); - else manipulator_setcolor(v3d, 'X', colcode, 255); - glRotatef(90.0, 0.0, 1.0, 0.0); - partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48); - glRotatef(-90.0, 0.0, 1.0, 0.0); - postOrtho(ortho); - } - /* Y circle */ - if (drawflags & MAN_ROT_Y) { - preOrthoFront(ortho, rv3d->twmat, 1); - if (is_picksel) GPU_select_load_id(MAN_ROT_Y); - else manipulator_setcolor(v3d, 'Y', colcode, 255); - glRotatef(-90.0, 1.0, 0.0, 0.0); - partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48); - glRotatef(90.0, 1.0, 0.0, 0.0); - postOrtho(ortho); - } - - glDisable(GL_CLIP_PLANE0); - } +static ManipulatorGroup *manipulatorgroup_init(wmManipulatorGroup *mgroup) +{ + ManipulatorGroup *man; - if (arcs == 0) { + man = MEM_callocN(sizeof(ManipulatorGroup), "manipulator_data"); - /* Z handle on X axis */ - if (drawflags & MAN_ROT_Z) { - preOrthoFront(ortho, rv3d->twmat, 2); - glPushMatrix(); - if (is_picksel) GPU_select_load_id(MAN_ROT_Z); - else manipulator_setcolor(v3d, 'Z', colcode, 255); + const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true); + const wmManipulatorType *wt_dial = WM_manipulatortype_find("MANIPULATOR_WT_dial_3d", true); + const wmManipulatorType *wt_prim = WM_manipulatortype_find("MANIPULATOR_WT_primitive_3d", true); - partial_doughnut(0.7f * cusize, 1.0f, 31, 33, 8, 64); +#define MANIPULATOR_NEW_ARROW(v, draw_style) { \ + man->manipulators[v] = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); \ + RNA_enum_set(man->manipulators[v]->ptr, "draw_style", draw_style); \ +} ((void)0) +#define MANIPULATOR_NEW_DIAL(v, draw_options) { \ + man->manipulators[v] = WM_manipulator_new_ptr(wt_dial, mgroup, NULL); \ + RNA_enum_set(man->manipulators[v]->ptr, "draw_options", draw_options); \ +} ((void)0) +#define MANIPULATOR_NEW_PRIM(v, draw_style) { \ + man->manipulators[v] = WM_manipulator_new_ptr(wt_prim, mgroup, NULL); \ + RNA_enum_set(man->manipulators[v]->ptr, "draw_style", draw_style); \ +} ((void)0) - glPopMatrix(); - postOrtho(ortho); - } + /* add/init widgets - order matters! */ + MANIPULATOR_NEW_DIAL(MAN_AXIS_ROT_T, ED_MANIPULATOR_DIAL_DRAW_FLAG_FILL); - /* Y handle on X axis */ - if (drawflags & MAN_ROT_Y) { - preOrthoFront(ortho, rv3d->twmat, 1); - glPushMatrix(); - if (is_picksel) GPU_select_load_id(MAN_ROT_Y); - else manipulator_setcolor(v3d, 'Y', colcode, 255); + MANIPULATOR_NEW_DIAL(MAN_AXIS_SCALE_C, ED_MANIPULATOR_DIAL_DRAW_FLAG_NOP); - glRotatef(90.0, 1.0, 0.0, 0.0); - glRotatef(90.0, 0.0, 0.0, 1.0); - partial_doughnut(0.7f * cusize, 1.0f, 31, 33, 8, 64); + MANIPULATOR_NEW_ARROW(MAN_AXIS_SCALE_X, ED_MANIPULATOR_ARROW_STYLE_BOX); + MANIPULATOR_NEW_ARROW(MAN_AXIS_SCALE_Y, ED_MANIPULATOR_ARROW_STYLE_BOX); + MANIPULATOR_NEW_ARROW(MAN_AXIS_SCALE_Z, ED_MANIPULATOR_ARROW_STYLE_BOX); - glPopMatrix(); - postOrtho(ortho); - } + MANIPULATOR_NEW_PRIM(MAN_AXIS_SCALE_XY, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE); + MANIPULATOR_NEW_PRIM(MAN_AXIS_SCALE_YZ, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE); + MANIPULATOR_NEW_PRIM(MAN_AXIS_SCALE_ZX, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE); - /* X handle on Z axis */ - if (drawflags & MAN_ROT_X) { - preOrthoFront(ortho, rv3d->twmat, 0); - glPushMatrix(); - if (is_picksel) GPU_select_load_id(MAN_ROT_X); - else manipulator_setcolor(v3d, 'X', colcode, 255); + MANIPULATOR_NEW_DIAL(MAN_AXIS_ROT_X, ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP); + MANIPULATOR_NEW_DIAL(MAN_AXIS_ROT_Y, ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP); + MANIPULATOR_NEW_DIAL(MAN_AXIS_ROT_Z, ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP); - glRotatef(-90.0, 0.0, 1.0, 0.0); - glRotatef(90.0, 0.0, 0.0, 1.0); - partial_doughnut(0.7f * cusize, 1.0f, 31, 33, 8, 64); + /* init screen aligned widget last here, looks better, behaves better */ + MANIPULATOR_NEW_DIAL(MAN_AXIS_ROT_C, ED_MANIPULATOR_DIAL_DRAW_FLAG_NOP); - glPopMatrix(); - postOrtho(ortho); - } + MANIPULATOR_NEW_DIAL(MAN_AXIS_TRANS_C, ED_MANIPULATOR_DIAL_DRAW_FLAG_NOP); - } + MANIPULATOR_NEW_ARROW(MAN_AXIS_TRANS_X, ED_MANIPULATOR_ARROW_STYLE_NORMAL); + MANIPULATOR_NEW_ARROW(MAN_AXIS_TRANS_Y, ED_MANIPULATOR_ARROW_STYLE_NORMAL); + MANIPULATOR_NEW_ARROW(MAN_AXIS_TRANS_Z, ED_MANIPULATOR_ARROW_STYLE_NORMAL); - /* restore */ - glLoadMatrixf(rv3d->viewmat); - if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + MANIPULATOR_NEW_PRIM(MAN_AXIS_TRANS_XY, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE); + MANIPULATOR_NEW_PRIM(MAN_AXIS_TRANS_YZ, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE); + MANIPULATOR_NEW_PRIM(MAN_AXIS_TRANS_ZX, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE); + return man; } -static void drawsolidcube(float size) -{ - const float cube[8][3] = { - {-1.0, -1.0, -1.0}, - {-1.0, -1.0, 1.0}, - {-1.0, 1.0, 1.0}, - {-1.0, 1.0, -1.0}, - { 1.0, -1.0, -1.0}, - { 1.0, -1.0, 1.0}, - { 1.0, 1.0, 1.0}, - { 1.0, 1.0, -1.0}, - }; - float n[3] = {0.0f}; - - glPushMatrix(); - glScalef(size, size, size); - - glBegin(GL_QUADS); - n[0] = -1.0; - glNormal3fv(n); - glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]); - n[0] = 0; - glEnd(); - - glBegin(GL_QUADS); - n[1] = -1.0; - glNormal3fv(n); - glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]); - n[1] = 0; - glEnd(); - - glBegin(GL_QUADS); - n[0] = 1.0; - glNormal3fv(n); - glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]); - n[0] = 0; - glEnd(); - - glBegin(GL_QUADS); - n[1] = 1.0; - glNormal3fv(n); - glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]); - n[1] = 0; - glEnd(); - - glBegin(GL_QUADS); - n[2] = 1.0; - glNormal3fv(n); - glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]); - n[2] = 0; - glEnd(); - - glBegin(GL_QUADS); - n[2] = -1.0; - glNormal3fv(n); - glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]); - glEnd(); - - glPopMatrix(); -} - - -static void draw_manipulator_scale( - View3D *v3d, RegionView3D *rv3d, const int drawflags, const int combo, const int colcode, - const bool is_moving, const bool is_picksel) +/** + * Custom handler for manipulator widgets + */ +static int manipulator_modal( + bContext *C, wmManipulator *widget, const wmEvent *UNUSED(event), + eWM_ManipulatorTweak UNUSED(tweak_flag)) { - float cywid = 0.25f * 0.01f * (float)U.tw_handlesize; - float cusize = cywid * 0.75f, dz; - int axis_order[3] = {2, 0, 1}; - int i; - - /* when called while moving in mixed mode, do not draw when... */ - if ((drawflags & MAN_SCALE_C) == 0) return; - - manipulator_axis_order(rv3d, axis_order); - - glDisable(GL_DEPTH_TEST); - - /* not in combo mode */ - if ((combo & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE)) == 0) { - float size, unitmat[4][4]; - int shift = 0; // XXX - - /* center circle, do not add to selection when shift is pressed (planar constraint) */ - if (is_picksel && shift == 0) GPU_select_load_id(MAN_SCALE_C); - else manipulator_setcolor(v3d, 'C', colcode, 255); + const ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + View3D *v3d = sa->spacedata.first; + RegionView3D *rv3d = ar->regiondata; + struct TransformBounds tbounds; - glPushMatrix(); - size = screen_aligned(rv3d, rv3d->twmat); - unit_m4(unitmat); - drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f * size, unitmat); - glPopMatrix(); - dz = 1.0; - } - else { - dz = 1.0f - 4.0f * cusize; + if (calc_manipulator_stats(C, true, &tbounds)) { + manipulator_prepare_mat(C, v3d, rv3d, &tbounds); + WM_manipulator_set_matrix_location(widget, rv3d->twmat[3]); } - if (is_moving) { - float matt[4][4]; + ED_region_tag_redraw(ar); - copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3] - // XXX mul_m4_m3m4(matt, t->mat, rv3d->twmat); - glMultMatrixf(matt); - glFrontFace(is_negative_m4(matt) ? GL_CW : GL_CCW); - } - else { - glMultMatrixf(rv3d->twmat); - glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW : GL_CCW); - } + return OPERATOR_RUNNING_MODAL; +} - /* axis */ +static void WIDGETGROUP_manipulator_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + ManipulatorGroup *man = manipulatorgroup_init(mgroup); + struct { + wmOperatorType *translate, *rotate, *trackball, *resize; + } ot_store = {NULL}; - /* in combo mode, this is always drawn as first type */ - draw_manipulator_axes(v3d, rv3d, colcode, - drawflags & MAN_SCALE_X, drawflags & MAN_SCALE_Y, drawflags & MAN_SCALE_Z, - axis_order, is_picksel); + mgroup->customdata = man; + /* *** set properties for axes *** */ - for (i = 0; i < 3; i++) { - switch (axis_order[i]) { - case 0: /* X cube */ - if (drawflags & MAN_SCALE_X) { - glTranslatef(dz, 0.0, 0.0); - if (is_picksel) GPU_select_load_id(MAN_SCALE_X); - else manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0])); - drawsolidcube(cusize); - glTranslatef(-dz, 0.0, 0.0); - } + MAN_ITER_AXES_BEGIN(axis, axis_idx) + { + const short axis_type = manipulator_get_axis_type(axis_idx); + int constraint_axis[3] = {1, 0, 0}; + PointerRNA *ptr; + + manipulator_get_axis_constraint(axis_idx, constraint_axis); + + /* custom handler! */ + WM_manipulator_set_fn_custom_modal(axis, manipulator_modal); + + switch (axis_idx) { + case MAN_AXIS_TRANS_X: + case MAN_AXIS_TRANS_Y: + case MAN_AXIS_TRANS_Z: + case MAN_AXIS_SCALE_X: + case MAN_AXIS_SCALE_Y: + case MAN_AXIS_SCALE_Z: + WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH); break; - case 1: /* Y cube */ - if (drawflags & MAN_SCALE_Y) { - glTranslatef(0.0, dz, 0.0); - if (is_picksel) GPU_select_load_id(MAN_SCALE_Y); - else manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1])); - drawsolidcube(cusize); - glTranslatef(0.0, -dz, 0.0); - } + case MAN_AXIS_ROT_X: + case MAN_AXIS_ROT_Y: + case MAN_AXIS_ROT_Z: + /* increased line width for better display */ + WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH + 1.0f); + WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_VALUE, true); break; - case 2: /* Z cube */ - if (drawflags & MAN_SCALE_Z) { - glTranslatef(0.0, 0.0, dz); - if (is_picksel) GPU_select_load_id(MAN_SCALE_Z); - else manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2])); - drawsolidcube(cusize); - glTranslatef(0.0, 0.0, -dz); - } + case MAN_AXIS_TRANS_XY: + case MAN_AXIS_TRANS_YZ: + case MAN_AXIS_TRANS_ZX: + case MAN_AXIS_SCALE_XY: + case MAN_AXIS_SCALE_YZ: + case MAN_AXIS_SCALE_ZX: + { + const float ofs_ax = 11.0f; + const float ofs[3] = {ofs_ax, ofs_ax, 0.0f}; + WM_manipulator_set_scale(axis, 0.07f); + WM_manipulator_set_matrix_offset_location(axis, ofs); + WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true); break; - } - } - -#if 0 // XXX - /* if shiftkey, center point as last, for selectbuffer order */ - if (is_picksel) { - int shift = 0; // XXX - - if (shift) { - glTranslatef(0.0, -dz, 0.0); - GPU_select_load_id(MAN_SCALE_C); - /* TODO: set glPointSize before drawing center point */ - glBegin(GL_POINTS); - glVertex3f(0.0, 0.0, 0.0); - glEnd(); - } - } -#endif - - /* restore */ - glLoadMatrixf(rv3d->viewmat); - - if (v3d->zbuf) glEnable(GL_DEPTH_TEST); - glFrontFace(GL_CCW); -} - - -static void draw_cone(GLUquadricObj *qobj, float len, float width) -{ - glTranslatef(0.0, 0.0, -0.5f * len); - gluCylinder(qobj, width, 0.0, len, 8, 1); - gluQuadricOrientation(qobj, GLU_INSIDE); - gluDisk(qobj, 0.0, width, 8, 1); - gluQuadricOrientation(qobj, GLU_OUTSIDE); - glTranslatef(0.0, 0.0, 0.5f * len); -} - -static void draw_cylinder(GLUquadricObj *qobj, float len, float width) -{ - - width *= 0.8f; // just for beauty - - glTranslatef(0.0, 0.0, -0.5f * len); - gluCylinder(qobj, width, width, len, 8, 1); - gluQuadricOrientation(qobj, GLU_INSIDE); - gluDisk(qobj, 0.0, width, 8, 1); - gluQuadricOrientation(qobj, GLU_OUTSIDE); - glTranslatef(0.0, 0.0, len); - gluDisk(qobj, 0.0, width, 8, 1); - glTranslatef(0.0, 0.0, -0.5f * len); -} - - -static void draw_manipulator_translate( - View3D *v3d, RegionView3D *rv3d, int drawflags, int combo, int colcode, - const bool UNUSED(is_moving), const bool is_picksel) -{ - GLUquadricObj *qobj; - float cylen = 0.01f * (float)U.tw_handlesize; - float cywid = 0.25f * cylen, dz, size; - float unitmat[4][4]; - int shift = 0; // XXX - int axis_order[3] = {0, 1, 2}; - int i; - - /* when called while moving in mixed mode, do not draw when... */ - if ((drawflags & MAN_TRANS_C) == 0) return; - - manipulator_axis_order(rv3d, axis_order); - - // XXX if (moving) glTranslate3fv(t->vec); - glDisable(GL_DEPTH_TEST); - - /* center circle, do not add to selection when shift is pressed (planar constraint) */ - if (is_picksel && shift == 0) GPU_select_load_id(MAN_TRANS_C); - else manipulator_setcolor(v3d, 'C', colcode, 255); - - glPushMatrix(); - size = screen_aligned(rv3d, rv3d->twmat); - unit_m4(unitmat); - drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f * size, unitmat); - glPopMatrix(); - - /* and now apply matrix, we move to local matrix drawing */ - glMultMatrixf(rv3d->twmat); - - /* axis */ - GPU_select_load_id(-1); - - // translate drawn as last, only axis when no combo with scale, or for ghosting - if ((combo & V3D_MANIP_SCALE) == 0 || colcode == MAN_GHOST) { - draw_manipulator_axes(v3d, rv3d, colcode, - drawflags & MAN_TRANS_X, drawflags & MAN_TRANS_Y, drawflags & MAN_TRANS_Z, - axis_order, is_picksel); - } - - - /* offset in combo mode, for rotate a bit more */ - if (combo & (V3D_MANIP_ROTATE)) dz = 1.0f + 2.0f * cylen; - else if (combo & (V3D_MANIP_SCALE)) dz = 1.0f + 0.5f * cylen; - else dz = 1.0f; - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_FILL); - - for (i = 0; i < 3; i++) { - switch (axis_order[i]) { - case 0: /* Z Cone */ - if (drawflags & MAN_TRANS_Z) { - glTranslatef(0.0, 0.0, dz); - if (is_picksel) GPU_select_load_id(MAN_TRANS_Z); - else manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2])); - draw_cone(qobj, cylen, cywid); - glTranslatef(0.0, 0.0, -dz); + } + case MAN_AXIS_TRANS_C: + case MAN_AXIS_ROT_C: + case MAN_AXIS_SCALE_C: + case MAN_AXIS_ROT_T: + WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH); + if (axis_idx == MAN_AXIS_ROT_T) { + WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_HOVER, true); } - break; - case 1: /* X Cone */ - if (drawflags & MAN_TRANS_X) { - glTranslatef(dz, 0.0, 0.0); - if (is_picksel) GPU_select_load_id(MAN_TRANS_X); - else manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0])); - glRotatef(90.0, 0.0, 1.0, 0.0); - draw_cone(qobj, cylen, cywid); - glRotatef(-90.0, 0.0, 1.0, 0.0); - glTranslatef(-dz, 0.0, 0.0); + else if (axis_idx == MAN_AXIS_ROT_C) { + WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_VALUE, true); } - break; - case 2: /* Y Cone */ - if (drawflags & MAN_TRANS_Y) { - glTranslatef(0.0, dz, 0.0); - if (is_picksel) GPU_select_load_id(MAN_TRANS_Y); - else manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1])); - glRotatef(-90.0, 1.0, 0.0, 0.0); - draw_cone(qobj, cylen, cywid); - glRotatef(90.0, 1.0, 0.0, 0.0); - glTranslatef(0.0, -dz, 0.0); + else { + WM_manipulator_set_scale(axis, 0.2f); } break; } - } - - gluDeleteQuadric(qobj); - glLoadMatrixf(rv3d->viewmat); - - if (v3d->zbuf) glEnable(GL_DEPTH_TEST); - -} - -static void draw_manipulator_rotate_cyl( - View3D *v3d, RegionView3D *rv3d, int drawflags, const int combo, const int colcode, - const bool is_moving, const bool is_picksel) -{ - GLUquadricObj *qobj; - float size; - float cylen = 0.01f * (float)U.tw_handlesize; - float cywid = 0.25f * cylen; - int axis_order[3] = {2, 0, 1}; - int i; - - /* skip drawing if all axes are locked */ - if (manipulator_rotate_is_visible(drawflags) == false) return; - - manipulator_axis_order(rv3d, axis_order); - - /* prepare for screen aligned draw */ - glPushMatrix(); - size = screen_aligned(rv3d, rv3d->twmat); - - glDisable(GL_DEPTH_TEST); - - qobj = gluNewQuadric(); - - /* Screen aligned view rot circle */ - if (drawflags & MAN_ROT_V) { - float unitmat[4][4]; - - unit_m4(unitmat); - - if (is_picksel) GPU_select_load_id(MAN_ROT_V); - UI_ThemeColor(TH_TRANSFORM); - drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f * size, unitmat); - - if (is_moving) { - float vec[3]; - vec[0] = 0; // XXX (float)(t->mouse.imval[0] - t->center2d[0]); - vec[1] = 0; // XXX (float)(t->mouse.imval[1] - t->center2d[1]); - vec[2] = 0.0f; - normalize_v3_length(vec, 1.2f * size); - glBegin(GL_LINES); - glVertex3f(0.0, 0.0, 0.0); - glVertex3fv(vec); - glEnd(); - } - } - glPopMatrix(); - - /* apply the transform delta */ - if (is_moving) { - float matt[4][4]; - copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3] - // XXX if (t->flag & T_USES_MANIPULATOR) { - // XXX mul_m4_m3m4(matt, t->mat, rv3d->twmat); - // XXX } - glMultMatrixf(matt); - } - else { - glMultMatrixf(rv3d->twmat); - } - - glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW : GL_CCW); - - /* axis */ - if (is_picksel == false) { - - // only draw axis when combo didn't draw scale axes - if ((combo & V3D_MANIP_SCALE) == 0) { - draw_manipulator_axes(v3d, rv3d, colcode, - drawflags & MAN_ROT_X, drawflags & MAN_ROT_Y, drawflags & MAN_ROT_Z, - axis_order, is_picksel); - } - - /* only has to be set when not in picking */ - gluQuadricDrawStyle(qobj, GLU_FILL); - } - for (i = 0; i < 3; i++) { - switch (axis_order[i]) { - case 0: /* X cylinder */ - if (drawflags & MAN_ROT_X) { - glTranslatef(1.0, 0.0, 0.0); - if (is_picksel) GPU_select_load_id(MAN_ROT_X); - glRotatef(90.0, 0.0, 1.0, 0.0); - manipulator_setcolor(v3d, 'X', colcode, 255); - draw_cylinder(qobj, cylen, cywid); - glRotatef(-90.0, 0.0, 1.0, 0.0); - glTranslatef(-1.0, 0.0, 0.0); + switch (axis_type) { + case MAN_AXES_TRANSLATE: + if (ot_store.translate == NULL) { + ot_store.translate = WM_operatortype_find("TRANSFORM_OT_translate", true); } + ptr = WM_manipulator_operator_set(axis, 0, ot_store.translate, NULL); break; - case 1: /* Y cylinder */ - if (drawflags & MAN_ROT_Y) { - glTranslatef(0.0, 1.0, 0.0); - if (is_picksel) GPU_select_load_id(MAN_ROT_Y); - glRotatef(-90.0, 1.0, 0.0, 0.0); - manipulator_setcolor(v3d, 'Y', colcode, 255); - draw_cylinder(qobj, cylen, cywid); - glRotatef(90.0, 1.0, 0.0, 0.0); - glTranslatef(0.0, -1.0, 0.0); + case MAN_AXES_ROTATE: + { + wmOperatorType *ot_rotate; + if (axis_idx == MAN_AXIS_ROT_T) { + if (ot_store.trackball == NULL) { + ot_store.trackball = WM_operatortype_find("TRANSFORM_OT_trackball", true); + } + ot_rotate = ot_store.trackball; + } + else { + if (ot_store.rotate == NULL) { + ot_store.rotate = WM_operatortype_find("TRANSFORM_OT_rotate", true); + } + ot_rotate = ot_store.rotate; } + ptr = WM_manipulator_operator_set(axis, 0, ot_rotate, NULL); break; - case 2: /* Z cylinder */ - if (drawflags & MAN_ROT_Z) { - glTranslatef(0.0, 0.0, 1.0); - if (is_picksel) GPU_select_load_id(MAN_ROT_Z); - manipulator_setcolor(v3d, 'Z', colcode, 255); - draw_cylinder(qobj, cylen, cywid); - glTranslatef(0.0, 0.0, -1.0); + } + case MAN_AXES_SCALE: + { + if (ot_store.resize == NULL) { + ot_store.resize = WM_operatortype_find("TRANSFORM_OT_resize", true); } + ptr = WM_manipulator_operator_set(axis, 0, ot_store.resize, NULL); break; + } } - } - /* restore */ - - gluDeleteQuadric(qobj); - glLoadMatrixf(rv3d->viewmat); - - if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + { + PropertyRNA *prop; + if ((prop = RNA_struct_find_property(ptr, "constraint_axis"))) { + RNA_property_boolean_set_array(ptr, prop, constraint_axis); + } + } + RNA_boolean_set(ptr, "release_confirm", 1); + } + MAN_ITER_AXES_END; } - -/* ********************************************* */ - -/* main call, does calc centers & orientation too */ -static int drawflags = 0xFFFF; // only for the calls below, belongs in scene...? - -void BIF_draw_manipulator(const bContext *C) +static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGroup *mgroup) { + ManipulatorGroup *man = mgroup->customdata; ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); - Scene *scene = CTX_data_scene(C); View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; - int totsel; + struct TransformBounds tbounds; - const bool is_picksel = false; + /* skip, we don't draw anything anyway */ + if ((man->all_hidden = (calc_manipulator_stats(C, true, &tbounds) == 0))) + return; - if (!(v3d->twflag & V3D_USE_MANIPULATOR)) return; + manipulator_prepare_mat(C, v3d, rv3d, &tbounds); - if ((v3d->twtype & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE | V3D_MANIP_SCALE)) == 0) return; + /* *** set properties for axes *** */ + MAN_ITER_AXES_BEGIN(axis, axis_idx) { - struct TransformBounds tbounds; - v3d->twflag &= ~V3D_DRAW_MANIPULATOR; - - totsel = calc_manipulator_stats(C, &tbounds); - if (totsel == 0) return; - - v3d->twflag |= V3D_DRAW_MANIPULATOR; - - /* now we can define center */ - switch (v3d->around) { - case V3D_AROUND_CENTER_BOUNDS: - case V3D_AROUND_ACTIVE: + const short axis_type = manipulator_get_axis_type(axis_idx); + const int aidx_norm = manipulator_orientation_axis(axis_idx, NULL); + + WM_manipulator_set_matrix_location(axis, rv3d->twmat[3]); + + switch (axis_idx) { + case MAN_AXIS_TRANS_X: + case MAN_AXIS_TRANS_Y: + case MAN_AXIS_TRANS_Z: + case MAN_AXIS_SCALE_X: + case MAN_AXIS_SCALE_Y: + case MAN_AXIS_SCALE_Z: { - bGPdata *gpd = CTX_data_gpencil_data(C); - Object *ob = OBACT; + float start_co[3] = {0.0f, 0.0f, 0.0f}; + float len; - if (((v3d->around == V3D_AROUND_ACTIVE) && (scene->obedit == NULL)) && - ((gpd == NULL) || !(gpd->flag & GP_DATA_STROKE_EDITMODE)) && - (ob && !(ob->mode & OB_MODE_POSE))) - { - copy_v3_v3(rv3d->twmat[3], ob->obmat[3]); - } - else { - mid_v3_v3v3(rv3d->twmat[3], tbounds.min, tbounds.max); - } + manipulator_line_range(v3d, axis_type, &start_co[2], &len); + + WM_manipulator_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]); + RNA_float_set(axis->ptr, "length", len); + WM_manipulator_set_matrix_offset_location(axis, start_co); + WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true); break; } - case V3D_AROUND_LOCAL_ORIGINS: - case V3D_AROUND_CENTER_MEAN: - copy_v3_v3(rv3d->twmat[3], tbounds.center); + case MAN_AXIS_ROT_X: + case MAN_AXIS_ROT_Y: + case MAN_AXIS_ROT_Z: + WM_manipulator_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]); break; - case V3D_AROUND_CURSOR: - copy_v3_v3(rv3d->twmat[3], ED_view3d_cursor3d_get(scene, v3d)); + case MAN_AXIS_TRANS_XY: + case MAN_AXIS_TRANS_YZ: + case MAN_AXIS_TRANS_ZX: + case MAN_AXIS_SCALE_XY: + case MAN_AXIS_SCALE_YZ: + case MAN_AXIS_SCALE_ZX: + { + const float *y_axis = rv3d->twmat[aidx_norm - 1 < 0 ? 2 : aidx_norm - 1]; + const float *z_axis = rv3d->twmat[aidx_norm]; + WM_manipulator_set_matrix_rotation_from_yz_axis(axis, y_axis, z_axis); break; + } } - - mul_mat3_m4_fl(rv3d->twmat, ED_view3d_pixel_size(rv3d, rv3d->twmat[3]) * U.tw_size); } + MAN_ITER_AXES_END; +} + +static void WIDGETGROUP_manipulator_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + ManipulatorGroup *man = mgroup->customdata; + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + View3D *v3d = sa->spacedata.first; + RegionView3D *rv3d = ar->regiondata; + float idot[3]; /* when looking through a selected camera, the manipulator can be at the * exact same position as the view, skip so we don't break selection */ - if (fabsf(mat4_to_scale(rv3d->twmat)) < 1e-7f) + if (man->all_hidden || fabsf(ED_view3d_pixel_size(rv3d, rv3d->twmat[3])) < 1e-6f) { + MAN_ITER_AXES_BEGIN(axis, axis_idx) + { + WM_manipulator_set_flag(axis, WM_MANIPULATOR_HIDDEN, true); + } + MAN_ITER_AXES_END; return; + } + manipulator_get_idot(rv3d, idot); - test_manipulator_axis(C); - drawflags = rv3d->twdrawflag; /* set in calc_manipulator_stats */ - - if (v3d->twflag & V3D_DRAW_MANIPULATOR) { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glLineWidth(1.0f); + /* *** set properties for axes *** */ - if (v3d->twtype & V3D_MANIP_ROTATE) { - if (G.debug_value == 3) { - if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) - draw_manipulator_rotate_cyl(v3d, rv3d, drawflags, v3d->twtype, MAN_MOVECOL, true, is_picksel); - else - draw_manipulator_rotate_cyl(v3d, rv3d, drawflags, v3d->twtype, MAN_RGB, false, is_picksel); - } - else { - draw_manipulator_rotate(v3d, rv3d, drawflags, v3d->twtype, false, is_picksel); - } - } - if (v3d->twtype & V3D_MANIP_SCALE) { - draw_manipulator_scale(v3d, rv3d, drawflags, v3d->twtype, MAN_RGB, false, is_picksel); + MAN_ITER_AXES_BEGIN(axis, axis_idx) + { + const short axis_type = manipulator_get_axis_type(axis_idx); + /* XXX maybe unset _HIDDEN flag on redraw? */ + if (manipulator_is_axis_visible(v3d, rv3d, idot, axis_type, axis_idx)) { + WM_manipulator_set_flag(axis, WM_MANIPULATOR_HIDDEN, false); } - if (v3d->twtype & V3D_MANIP_TRANSLATE) { - draw_manipulator_translate(v3d, rv3d, drawflags, v3d->twtype, MAN_RGB, false, is_picksel); + else { + WM_manipulator_set_flag(axis, WM_MANIPULATOR_HIDDEN, true); + continue; } - glDisable(GL_BLEND); + float color[4], color_hi[4]; + manipulator_get_axis_color(axis_idx, idot, color, color_hi); + WM_manipulator_set_color(axis, color); + WM_manipulator_set_color_highlight(axis, color_hi); + + switch (axis_idx) { + case MAN_AXIS_TRANS_C: + case MAN_AXIS_ROT_C: + case MAN_AXIS_SCALE_C: + case MAN_AXIS_ROT_T: + WM_manipulator_set_matrix_rotation_from_z_axis(axis, rv3d->viewinv[2]); + break; + } } + MAN_ITER_AXES_END; } -static int manipulator_selectbuf(Scene *scene, ScrArea *sa, ARegion *ar, const int mval[2], float hotspot) +static bool WIDGETGROUP_manipulator_poll(const struct bContext *C, struct wmManipulatorGroupType *UNUSED(wgt)) { - View3D *v3d = sa->spacedata.first; - RegionView3D *rv3d = ar->regiondata; - rcti rect; - GLuint buffer[64]; // max 4 items per select, so large enuf - short hits; - const bool is_picksel = true; - const bool do_passes = GPU_select_query_check_active(); + /* it's a given we only use this in 3D view */ + const ScrArea *sa = CTX_wm_area(C); + const View3D *v3d = sa->spacedata.first; - /* when looking through a selected camera, the manipulator can be at the - * exact same position as the view, skip so we don't break selection */ - if (fabsf(mat4_to_scale(rv3d->twmat)) < 1e-7f) - return 0; + if (((v3d->twflag & V3D_MANIPULATOR_DRAW) != 0) && + ((v3d->twtype & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE | V3D_MANIP_SCALE)) != 0)) + { + /* Don't show when tools have a manipulator. */ + WorkSpace *workspace = CTX_wm_workspace(C); + if (workspace->tool.manipulator_group[0] == '\0') { + return true; + } + } + return false; +} - rect.xmin = mval[0] - hotspot; - rect.xmax = mval[0] + hotspot; - rect.ymin = mval[1] - hotspot; - rect.ymax = mval[1] + hotspot; +void TRANSFORM_WGT_manipulator(wmManipulatorGroupType *wgt) +{ + wgt->name = "Transform Manipulator"; + wgt->idname = "TRANSFORM_WGT_manipulator"; - ED_view3d_draw_setup_view(NULL, scene, ar, v3d, NULL, NULL, &rect); + wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D); - if (do_passes) - GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0); - else - GPU_select_begin(buffer, 64, &rect, GPU_SELECT_ALL, 0); + wgt->poll = WIDGETGROUP_manipulator_poll; + wgt->setup = WIDGETGROUP_manipulator_setup; + wgt->refresh = WIDGETGROUP_manipulator_refresh; + wgt->draw_prepare = WIDGETGROUP_manipulator_draw_prepare; +} - /* do the drawing */ - if (v3d->twtype & V3D_MANIP_ROTATE) { - if (G.debug_value == 3) draw_manipulator_rotate_cyl(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); - else draw_manipulator_rotate(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, false, is_picksel); - } - if (v3d->twtype & V3D_MANIP_SCALE) - draw_manipulator_scale(v3d, rv3d, MAN_SCALE_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); - if (v3d->twtype & V3D_MANIP_TRANSLATE) - draw_manipulator_translate(v3d, rv3d, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); +/** \} */ - hits = GPU_select_end(); - if (do_passes && (hits > 0)) { - GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits); +/* -------------------------------------------------------------------- */ +/** \name Scale Cage Manipulator + * \{ */ - /* do the drawing */ - if (v3d->twtype & V3D_MANIP_ROTATE) { - if (G.debug_value == 3) draw_manipulator_rotate_cyl(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); - else draw_manipulator_rotate(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, false, is_picksel); - } - if (v3d->twtype & V3D_MANIP_SCALE) - draw_manipulator_scale(v3d, rv3d, MAN_SCALE_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); - if (v3d->twtype & V3D_MANIP_TRANSLATE) - draw_manipulator_translate(v3d, rv3d, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); +struct XFormCageWidgetGroup { + wmManipulator *manipulator; +}; - GPU_select_end(); +static bool WIDGETGROUP_xform_cage_poll(const bContext *C, wmManipulatorGroupType *wgt) +{ + WorkSpace *workspace = CTX_wm_workspace(C); + if (!STREQ(wgt->idname, workspace->tool.manipulator_group)) { + WM_manipulator_group_type_unlink_delayed_ptr(wgt); + return false; } + return true; +} - ED_view3d_draw_setup_view(NULL, scene, ar, v3d, NULL, NULL, NULL); +static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + struct XFormCageWidgetGroup *xmgroup = MEM_mallocN(sizeof(struct XFormCageWidgetGroup), __func__); + const wmManipulatorType *wt_cage = WM_manipulatortype_find("MANIPULATOR_WT_cage_3d", true); + xmgroup->manipulator = WM_manipulator_new_ptr(wt_cage, mgroup, NULL); + wmManipulator *mpr = xmgroup->manipulator; - if (hits == 1) return buffer[3]; - else if (hits > 1) { - GLuint val, dep, mindep = 0, mindeprot = 0, minval = 0, minvalrot = 0; - int a; + RNA_enum_set(mpr->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE | + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE); - /* we compare the hits in buffer, but value centers highest */ - /* we also store the rotation hits separate (because of arcs) and return hits on other widgets if there are */ + mpr->color[0] = 1; + mpr->color_hi[0]=1; - for (a = 0; a < hits; a++) { - dep = buffer[4 * a + 1]; - val = buffer[4 * a + 3]; + mgroup->customdata = xmgroup; - if (val == MAN_TRANS_C) { - return MAN_TRANS_C; - } - else if (val == MAN_SCALE_C) { - return MAN_SCALE_C; - } - else { - if (val & MAN_ROT_C) { - if (minvalrot == 0 || dep < mindeprot) { - mindeprot = dep; - minvalrot = val; - } - } - else { - if (minval == 0 || dep < mindep) { - mindep = dep; - minval = val; + { + wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true); + PointerRNA *ptr; + + /* assign operator */ + PropertyRNA *prop_release_confirm = NULL; + PropertyRNA *prop_constraint_axis = NULL; + + int i = ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z; + for (int x = 0; x < 3; x++) { + for (int y = 0; y < 3; y++) { + for (int z = 0; z < 3; z++) { + int constraint[3] = {x != 1, y != 1, z != 1}; + ptr = WM_manipulator_operator_set(mpr, i, ot_resize, NULL); + if (prop_release_confirm == NULL) { + prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm"); + prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis"); } + RNA_property_boolean_set(ptr, prop_release_confirm, true); + RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint); + i++; } } } - - if (minval) - return minval; - else - return minvalrot; } - return 0; } -static const char *manipulator_get_operator_name(int man_val) +static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmManipulatorGroup *mgroup) { - if (man_val & MAN_TRANS_C) { - return "TRANSFORM_OT_translate"; - } - else if (man_val == MAN_ROT_T) { - return "TRANSFORM_OT_trackball"; - } - else if (man_val & MAN_ROT_C) { - return "TRANSFORM_OT_rotate"; - } - else if (man_val & MAN_SCALE_C) { - return "TRANSFORM_OT_resize"; - } - - return NULL; -} - -/* return 0; nothing happened */ -int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; ARegion *ar = CTX_wm_region(C); - int constraint_axis[3] = {0, 0, 0}; - int val; - const bool use_planar = RNA_boolean_get(op->ptr, "use_planar_constraint"); - - if (!(v3d->twflag & V3D_USE_MANIPULATOR)) return 0; - if (!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return 0; - - /* Force orientation */ - RNA_enum_set(op->ptr, "constraint_orientation", v3d->twmode); - - // find the hotspots first test narrow hotspot - val = manipulator_selectbuf(scene, sa, ar, event->mval, 0.5f * (float)U.tw_hotspot); - if (val) { - wmOperatorType *ot; - PointerRNA props_ptr; - PropertyRNA *prop; - const char *opname; - - // drawflags still global, for drawing call above - drawflags = manipulator_selectbuf(scene, sa, ar, event->mval, 0.2f * (float)U.tw_hotspot); - if (drawflags == 0) drawflags = val; - - /* Planar constraint doesn't make sense for rotation, give other keymaps a chance */ - if ((drawflags & MAN_ROT_C) && use_planar) { - return 0; - } + RegionView3D *rv3d = ar->regiondata; - opname = manipulator_get_operator_name(drawflags); - ot = WM_operatortype_find(opname, true); - WM_operator_properties_create_ptr(&props_ptr, ot); + struct XFormCageWidgetGroup *xmgroup = mgroup->customdata; + wmManipulator *mpr = xmgroup->manipulator; - if (drawflags & MAN_TRANS_C) { - switch (drawflags) { - case MAN_TRANS_C: - break; - case MAN_TRANS_X: - if (use_planar) { - constraint_axis[1] = 1; - constraint_axis[2] = 1; - } - else - constraint_axis[0] = 1; - break; - case MAN_TRANS_Y: - if (use_planar) { - constraint_axis[0] = 1; - constraint_axis[2] = 1; - } - else - constraint_axis[1] = 1; - break; - case MAN_TRANS_Z: - if (use_planar) { - constraint_axis[0] = 1; - constraint_axis[1] = 1; - } - else - constraint_axis[2] = 1; - break; - } - RNA_boolean_set_array(&props_ptr, "constraint_axis", constraint_axis); - } - else if (drawflags & MAN_SCALE_C) { - switch (drawflags) { - case MAN_SCALE_X: - if (use_planar) { - constraint_axis[1] = 1; - constraint_axis[2] = 1; - } - else - constraint_axis[0] = 1; - break; - case MAN_SCALE_Y: - if (use_planar) { - constraint_axis[0] = 1; - constraint_axis[2] = 1; - } - else - constraint_axis[1] = 1; - break; - case MAN_SCALE_Z: - if (use_planar) { - constraint_axis[0] = 1; - constraint_axis[1] = 1; + struct TransformBounds tbounds; + + if ((calc_manipulator_stats(C, false, &tbounds) == 0) || + equals_v3v3(rv3d->tw_axis_min, rv3d->tw_axis_max)) + { + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); + } + else { + manipulator_prepare_mat(C, v3d, rv3d, &tbounds); + + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + + float dims[3]; + sub_v3_v3v3(dims, rv3d->tw_axis_max, rv3d->tw_axis_min); + RNA_float_set_array(mpr->ptr, "dimensions", dims); + mul_v3_fl(dims, 0.5f); + + copy_m4_m3(mpr->matrix_offset, rv3d->tw_axis_matrix); + mid_v3_v3v3(mpr->matrix_offset[3], rv3d->tw_axis_max, rv3d->tw_axis_min); + mul_m3_v3(rv3d->tw_axis_matrix, mpr->matrix_offset[3]); + + PropertyRNA *prop_center_override = NULL; + float center[3]; + float center_global[3]; + int i = ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z; + for (int x = 0; x < 3; x++) { + center[0] = (float)(1 - x) * dims[0]; + for (int y = 0; y < 3; y++) { + center[1] = (float)(1 - y) * dims[1]; + for (int z = 0; z < 3; z++) { + center[2] = (float)(1 - z) * dims[2]; + struct wmManipulatorOpElem *mpop = WM_manipulator_operator_get(mpr, i); + if (prop_center_override == NULL) { + prop_center_override = RNA_struct_find_property(&mpop->ptr, "center_override"); } - else - constraint_axis[2] = 1; - break; - } - RNA_boolean_set_array(&props_ptr, "constraint_axis", constraint_axis); - } - else if (drawflags == MAN_ROT_T) { - /* pass */ - } - else if (drawflags & MAN_ROT_C) { - switch (drawflags) { - case MAN_ROT_X: - constraint_axis[0] = 1; - break; - case MAN_ROT_Y: - constraint_axis[1] = 1; - break; - case MAN_ROT_Z: - constraint_axis[2] = 1; - break; + mul_v3_m4v3(center_global, mpr->matrix_offset, center); + RNA_property_float_set_array(&mpop->ptr, prop_center_override, center_global); + i++; + } } - RNA_boolean_set_array(&props_ptr, "constraint_axis", constraint_axis); } + } +} - /* pass operator properties on to transform operators */ - prop = RNA_struct_find_property(op->ptr, "use_accurate"); - if (RNA_property_is_set(op->ptr, prop)) { - RNA_property_boolean_set(&props_ptr, prop, RNA_property_boolean_get(op->ptr, prop)); - } - prop = RNA_struct_find_property(op->ptr, "release_confirm"); - if (RNA_property_is_set(op->ptr, prop)) { - RNA_property_boolean_set(&props_ptr, prop, RNA_property_boolean_get(op->ptr, prop)); - } - prop = RNA_struct_find_property(op->ptr, "constraint_orientation"); - if (RNA_property_is_set(op->ptr, prop)) { - RNA_property_enum_set(&props_ptr, prop, RNA_property_enum_get(op->ptr, prop)); - } +static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct XFormCageWidgetGroup *xmgroup = mgroup->customdata; + wmManipulator *mpr = xmgroup->manipulator; - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); - WM_operator_properties_free(&props_ptr); + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = OBACT(sl); + if (ob && ob->mode & OB_MODE_EDIT) { + copy_m4_m4(mpr->matrix_space, ob->obmat); + } + else { + unit_m4(mpr->matrix_space); } - /* after transform, restore drawflags */ - drawflags = 0xFFFF; +} + +void VIEW3D_WGT_xform_cage(wmManipulatorGroupType *wgt) +{ + wgt->name = "Transform Cage"; + wgt->idname = "VIEW3D_WGT_xform_cage"; + + wgt->flag |= (WM_MANIPULATORGROUPTYPE_3D | + WM_MANIPULATORGROUPTYPE_DEPTH_3D); + + wgt->mmap_params.spaceid = SPACE_VIEW3D; + wgt->mmap_params.regionid = RGN_TYPE_WINDOW; - return val; + wgt->poll = WIDGETGROUP_xform_cage_poll; + wgt->setup = WIDGETGROUP_xform_cage_setup; + wgt->refresh = WIDGETGROUP_xform_cage_refresh; + wgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare; } +/** \} */ diff --git a/source/blender/editors/transform/transform_manipulator2d.c b/source/blender/editors/transform/transform_manipulator2d.c new file mode 100644 index 00000000000..6e2d0d8c5c0 --- /dev/null +++ b/source/blender/editors/transform/transform_manipulator2d.c @@ -0,0 +1,383 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 Blender Foundation. + * All rights reserved. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/transform/transform_manipulator2d.c + * \ingroup edtransform + * + * \name 2D Transform Manipulator + * + * Used for UV/Image Editor + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_view3d_types.h" + +#include "BKE_context.h" +#include "BKE_editmesh.h" + +#include "RNA_access.h" + +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "WM_api.h" +#include "WM_types.h" +#include "wm.h" /* XXX */ + +#include "ED_image.h" +#include "ED_screen.h" +#include "ED_uvedit.h" +#include "ED_manipulator_library.h" + +#include "transform.h" /* own include */ + +/* axes as index */ +enum { + MAN2D_AXIS_TRANS_X = 0, + MAN2D_AXIS_TRANS_Y, + + MAN2D_AXIS_LAST, +}; + +typedef struct ManipulatorGroup2D { + wmManipulator *translate_x, + *translate_y; + + wmManipulator *cage; + + /* Current origin in view space, used to update widget origin for possible view changes */ + float origin[2]; + float min[2]; + float max[2]; + +} ManipulatorGroup2D; + + +/* **************** Utilities **************** */ + +/* loop over axes */ +#define MAN2D_ITER_AXES_BEGIN(axis, axis_idx) \ + { \ + wmManipulator *axis; \ + int axis_idx; \ + for (axis_idx = 0; axis_idx < MAN2D_AXIS_LAST; axis_idx++) { \ + axis = manipulator2d_get_axis_from_index(man, axis_idx); + +#define MAN2D_ITER_AXES_END \ + } \ + } ((void)0) + +static wmManipulator *manipulator2d_get_axis_from_index(const ManipulatorGroup2D *man, const short axis_idx) +{ + BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN2D_AXIS_TRANS_X, (float)MAN2D_AXIS_TRANS_Y)); + + switch (axis_idx) { + case MAN2D_AXIS_TRANS_X: + return man->translate_x; + case MAN2D_AXIS_TRANS_Y: + return man->translate_y; + } + + return NULL; +} + +static void manipulator2d_get_axis_color(const int axis_idx, float *r_col, float *r_col_hi) +{ + const float alpha = 0.6f; + const float alpha_hi = 1.0f; + int col_id; + + switch (axis_idx) { + case MAN2D_AXIS_TRANS_X: + col_id = TH_AXIS_X; + break; + case MAN2D_AXIS_TRANS_Y: + col_id = TH_AXIS_Y; + break; + } + + UI_GetThemeColor4fv(col_id, r_col); + + copy_v4_v4(r_col_hi, r_col); + r_col[3] *= alpha; + r_col_hi[3] *= alpha_hi; +} + +static ManipulatorGroup2D *manipulatorgroup2d_init(wmManipulatorGroup *mgroup) +{ + const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_2d", true); + const wmManipulatorType *wt_cage = WM_manipulatortype_find("MANIPULATOR_WT_cage_2d", true); + + ManipulatorGroup2D *man = MEM_callocN(sizeof(ManipulatorGroup2D), __func__); + + man->translate_x = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); + man->translate_y = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); + man->cage = WM_manipulator_new_ptr(wt_cage, mgroup, NULL); + + RNA_enum_set(man->cage->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE | + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE); + + return man; +} + +/** + * Calculates origin in view space, use with #manipulator2d_origin_to_region. + */ +static void manipulator2d_calc_bounds(const bContext *C, float *r_center, float *r_min, float *r_max) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = ED_space_image(sima); + + float min_buf[2], max_buf[2]; + if (r_min == NULL) { + r_min = min_buf; + } + if (r_max == NULL) { + r_max = max_buf; + } + + if (!ED_uvedit_minmax(CTX_data_scene(C), ima, CTX_data_edit_object(C), r_min, r_max)) { + zero_v2(r_min); + zero_v2(r_max); + } + mid_v2_v2v2(r_center, r_min, r_max); +} + +/** + * Convert origin (or any other point) from view to region space. + */ +BLI_INLINE void manipulator2d_origin_to_region(ARegion *ar, float *r_origin) +{ + UI_view2d_view_to_region_fl(&ar->v2d, r_origin[0], r_origin[1], &r_origin[0], &r_origin[1]); +} + +/** + * Custom handler for manipulator widgets + */ +static int manipulator2d_modal( + bContext *C, wmManipulator *widget, const wmEvent *UNUSED(event), + eWM_ManipulatorTweak UNUSED(tweak_flag)) +{ + ARegion *ar = CTX_wm_region(C); + float origin[3]; + + manipulator2d_calc_bounds(C, origin, NULL, NULL); + manipulator2d_origin_to_region(ar, origin); + WM_manipulator_set_matrix_location(widget, origin); + + ED_region_tag_redraw(ar); + + return OPERATOR_RUNNING_MODAL; +} + +void ED_widgetgroup_manipulator2d_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + wmOperatorType *ot_translate = WM_operatortype_find("TRANSFORM_OT_translate", true); + ManipulatorGroup2D *man = manipulatorgroup2d_init(mgroup); + mgroup->customdata = man; + + MAN2D_ITER_AXES_BEGIN(axis, axis_idx) + { + const float offset[3] = {0.0f, 0.2f}; + + float color[4], color_hi[4]; + manipulator2d_get_axis_color(axis_idx, color, color_hi); + + /* custom handler! */ + WM_manipulator_set_fn_custom_modal(axis, manipulator2d_modal); + /* set up widget data */ + RNA_float_set(axis->ptr, "angle", -M_PI_2 * axis_idx); + RNA_float_set(axis->ptr, "length", 0.8f); + WM_manipulator_set_matrix_offset_location(axis, offset); + WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH); + WM_manipulator_set_scale(axis, U.manipulator_size); + WM_manipulator_set_color(axis, color); + WM_manipulator_set_color_highlight(axis, color_hi); + + /* assign operator */ + PointerRNA *ptr = WM_manipulator_operator_set(axis, 0, ot_translate, NULL); + int constraint[3] = {0}; + constraint[(axis_idx + 1) % 2] = 1; + if (RNA_struct_find_property(ptr, "constraint_axis")) + RNA_boolean_set_array(ptr, "constraint_axis", constraint); + RNA_boolean_set(ptr, "release_confirm", 1); + } + MAN2D_ITER_AXES_END; + + { + wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true); + wmOperatorType *ot_rotate = WM_operatortype_find("TRANSFORM_OT_rotate", true); + PointerRNA *ptr; + + /* assign operator */ + ptr = WM_manipulator_operator_set(man->cage, 0, ot_translate, NULL); + RNA_boolean_set(ptr, "release_confirm", 1); + + int constraint_x[3] = {1, 0, 0}; + int constraint_y[3] = {0, 1, 0}; + + ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X, ot_resize, NULL); + PropertyRNA *prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm"); + PropertyRNA *prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis"); + RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x); + RNA_property_boolean_set(ptr, prop_release_confirm, true); + ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X, ot_resize, NULL); + RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x); + RNA_property_boolean_set(ptr, prop_release_confirm, true); + ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y, ot_resize, NULL); + RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y); + RNA_property_boolean_set(ptr, prop_release_confirm, true); + ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y, ot_resize, NULL); + RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y); + RNA_property_boolean_set(ptr, prop_release_confirm, true); + + ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y, ot_resize, NULL); + RNA_property_boolean_set(ptr, prop_release_confirm, true); + ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y, ot_resize, NULL); + RNA_property_boolean_set(ptr, prop_release_confirm, true); + ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y, ot_resize, NULL); + RNA_property_boolean_set(ptr, prop_release_confirm, true); + ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y, ot_resize, NULL); + RNA_property_boolean_set(ptr, prop_release_confirm, true); + ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_ROTATE, ot_rotate, NULL); + RNA_property_boolean_set(ptr, prop_release_confirm, true); + } +} + +void ED_widgetgroup_manipulator2d_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + ManipulatorGroup2D *man = mgroup->customdata; + float origin[3]; + manipulator2d_calc_bounds(C, origin, man->min, man->max); + copy_v2_v2(man->origin, origin); + bool show_cage = !equals_v2v2(man->min, man->max); + + if (show_cage) { + man->cage->flag &= ~WM_MANIPULATOR_HIDDEN; + man->translate_x->flag |= WM_MANIPULATOR_HIDDEN; + man->translate_y->flag |= WM_MANIPULATOR_HIDDEN; + } + else { + man->cage->flag |= WM_MANIPULATOR_HIDDEN; + man->translate_x->flag &= ~WM_MANIPULATOR_HIDDEN; + man->translate_y->flag &= ~WM_MANIPULATOR_HIDDEN; + } + + if (show_cage) { + wmManipulatorOpElem *mpop; + float mid[2]; + const float *min = man->min; + const float *max = man->max; + mid_v2_v2v2(mid, min, max); + + mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X); + PropertyRNA *prop_center_override = RNA_struct_find_property(&mpop->ptr, "center_override"); + RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){max[0], mid[1], 0.0f}); + mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X); + RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){min[0], mid[1], 0.0f}); + mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y); + RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){mid[0], max[1], 0.0f}); + mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y); + RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){mid[0], min[1], 0.0f}); + + mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y); + RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){max[0], max[1], 0.0f}); + mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y); + RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){max[0], min[1], 0.0f}); + mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y); + RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){min[0], max[1], 0.0f}); + mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y); + RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){min[0], min[1], 0.0f}); + + mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_ROTATE); + RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){mid[0], mid[1], 0.0f}); + } +} + +void ED_widgetgroup_manipulator2d_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + ARegion *ar = CTX_wm_region(C); + ManipulatorGroup2D *man = mgroup->customdata; + float origin[3] = {UNPACK2(man->origin), 0.0f}; + float origin_aa[3] = {UNPACK2(man->origin), 0.0f}; + + manipulator2d_origin_to_region(ar, origin); + + MAN2D_ITER_AXES_BEGIN(axis, axis_idx) + { + WM_manipulator_set_matrix_location(axis, origin); + } + MAN2D_ITER_AXES_END; + + UI_view2d_view_to_region_m4(&ar->v2d, man->cage->matrix_space); + WM_manipulator_set_matrix_offset_location(man->cage, origin_aa); + man->cage->matrix_offset[0][0] = (man->max[0] - man->min[0]); + man->cage->matrix_offset[1][1] = (man->max[1] - man->min[1]); +} + +/* TODO (Julian) + * - Called on every redraw, better to do a more simple poll and check for selection in _refresh + * - UV editing only, could be expanded for other things. + */ +bool ED_widgetgroup_manipulator2d_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Object *obedit = CTX_data_edit_object(C); + + if (ED_space_image_show_uvedit(sima, obedit)) { + Image *ima = ED_space_image(sima); + Scene *scene = CTX_data_scene(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* check if there's a selected poly */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, ima, efa)) + continue; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + return true; + } + } + } + } + + return false; +} diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 46bd83b5d35..ad855427ff1 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -160,11 +160,12 @@ const EnumPropertyItem rna_enum_transform_mode_types[] = static int select_orientation_exec(bContext *C, wmOperator *op) { + View3D *v3d = CTX_wm_view3d(C); int orientation = RNA_enum_get(op->ptr, "orientation"); - BIF_selectTransformOrientationValue(C, orientation); + BIF_selectTransformOrientationValue(v3d, orientation); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); return OPERATOR_FINISHED; } @@ -206,10 +207,9 @@ static void TRANSFORM_OT_select_orientation(struct wmOperatorType *ot) static int delete_orientation_exec(bContext *C, wmOperator *UNUSED(op)) { View3D *v3d = CTX_wm_view3d(C); - int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM); - BIF_removeTransformOrientationIndex(C, selected_index); - + BIF_removeTransformOrientationIndex(C, v3d->custom_orientation_index); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); WM_event_add_notifier(C, NC_SCENE | NA_EDITED, CTX_data_scene(C)); @@ -223,18 +223,12 @@ static int delete_orientation_invoke(bContext *C, wmOperator *op, const wmEvent static int delete_orientation_poll(bContext *C) { - int selected_index = -1; View3D *v3d = CTX_wm_view3d(C); - + if (ED_operator_areaactive(C) == 0) return 0; - - - if (v3d) { - selected_index = (v3d->twmode - V3D_MANIP_CUSTOM); - } - - return selected_index >= 0; + + return (v3d->twmode >= V3D_MANIP_CUSTOM) && (v3d->custom_orientation_index != -1); } static void TRANSFORM_OT_delete_orientation(struct wmOperatorType *ot) @@ -1066,6 +1060,8 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_element"); + /* Will fall-through to texture-space transform. */ + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_transform_axis_target", TKEY, KM_PRESS, KM_SHIFT, 0); kmi = WM_keymap_add_item(keymap, OP_TRANSLATION, TKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "texture_space", true); diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 54959304d72..86f99c4fed2 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -38,6 +38,7 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" +#include "DNA_workspace_types.h" #include "BLI_math.h" #include "BLI_listbase.h" @@ -52,6 +53,7 @@ #include "BKE_report.h" #include "BKE_main.h" #include "BKE_screen.h" +#include "BKE_workspace.h" #include "BLT_translation.h" @@ -63,14 +65,16 @@ void BIF_clearTransformOrientation(bContext *C) { + WorkSpace *workspace = CTX_wm_workspace(C); + ListBase *transform_orientations = BKE_workspace_transform_orientations_get(workspace); View3D *v3d = CTX_wm_view3d(C); - ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; - BLI_freelistN(transform_spaces); + BLI_freelistN(transform_orientations); // Need to loop over all view3d - if (v3d && v3d->twmode >= V3D_MANIP_CUSTOM) { - v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */ + if (v3d && v3d->twmode == V3D_MANIP_CUSTOM) { + v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */ + v3d->custom_orientation_index = -1; } } @@ -318,23 +322,24 @@ void BIF_createTransformOrientation(bContext *C, ReportList *reports, TransformOrientation *addMatrixSpace(bContext *C, float mat[3][3], const char *name, const bool overwrite) { - ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; TransformOrientation *ts = NULL; + WorkSpace *workspace = CTX_wm_workspace(C); + ListBase *transform_orientations = BKE_workspace_transform_orientations_get(workspace); char name_unique[sizeof(ts->name)]; if (overwrite) { - ts = findOrientationName(transform_spaces, name); + ts = findOrientationName(transform_orientations, name); } else { BLI_strncpy(name_unique, name, sizeof(name_unique)); - uniqueOrientationName(transform_spaces, name_unique); + uniqueOrientationName(transform_orientations, name_unique); name = name_unique; } /* if not, create a new one */ if (ts == NULL) { ts = MEM_callocN(sizeof(TransformOrientation), "UserTransSpace from matrix"); - BLI_addtail(transform_spaces, ts); + BLI_addtail(transform_orientations, ts); BLI_strncpy(ts->name, name, sizeof(ts->name)); } @@ -346,70 +351,55 @@ TransformOrientation *addMatrixSpace(bContext *C, float mat[3][3], void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target) { - Scene *scene = CTX_data_scene(C); - ListBase *transform_spaces = &scene->transform_spaces; - const int i = BLI_findindex(transform_spaces, target); - - if (i != -1) { - Main *bmain = CTX_data_main(C); - BKE_screen_view3d_main_twmode_remove(&bmain->screen, scene, i); - BLI_freelinkN(transform_spaces, target); - } + BKE_workspace_transform_orientation_remove(CTX_wm_workspace(C), target); } void BIF_removeTransformOrientationIndex(bContext *C, int index) { - ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; - TransformOrientation *ts = BLI_findlink(transform_spaces, index); - - if (ts) { - BIF_removeTransformOrientation(C, ts); - } + TransformOrientation *target = BKE_workspace_transform_orientation_find(CTX_wm_workspace(C), index); + BIF_removeTransformOrientation(C, target); } void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target) { - ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; - const int i = BLI_findindex(transform_spaces, target); + int index = BKE_workspace_transform_orientation_get_index(CTX_wm_workspace(C), target); + View3D *v3d = CTX_wm_view3d(C); - if (i != -1) { - View3D *v3d = CTX_wm_view3d(C); - v3d->twmode = V3D_MANIP_CUSTOM + i; - } + BLI_assert(index != -1); + + v3d->twmode = V3D_MANIP_CUSTOM; + v3d->custom_orientation_index = index; } -void BIF_selectTransformOrientationValue(bContext *C, int orientation) +/** + * Activate a transform orientation in a 3D view based on an enum value. + * + * \param orientation: If this is #V3D_MANIP_CUSTOM or greater, the custom transform orientation + * with index \a orientation - #V3D_MANIP_CUSTOM gets activated. + */ +void BIF_selectTransformOrientationValue(View3D *v3d, int orientation) { - View3D *v3d = CTX_wm_view3d(C); - if (v3d) /* currently using generic poll */ - v3d->twmode = orientation; + const bool is_custom = orientation >= V3D_MANIP_CUSTOM; + + v3d->twmode = is_custom ? V3D_MANIP_CUSTOM : orientation; + v3d->custom_orientation_index = is_custom ? (orientation - V3D_MANIP_CUSTOM) : -1; } int BIF_countTransformOrientation(const bContext *C) { - ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; - return BLI_listbase_count(transform_spaces); + WorkSpace *workspace = CTX_wm_workspace(C); + ListBase *transform_orientations = BKE_workspace_transform_orientations_get(workspace); + return BLI_listbase_count(transform_orientations); } -bool applyTransformOrientation(const bContext *C, float mat[3][3], char *r_name, int index) +bool applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name) { - ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; - TransformOrientation *ts = BLI_findlink(transform_spaces, index); - - BLI_assert(index >= 0); - - if (ts) { - if (r_name) { - BLI_strncpy(r_name, ts->name, MAX_NAME); - } - - copy_m3_m3(mat, ts->mat); - return true; - } - else { - /* invalid index, can happen sometimes */ - return false; + if (r_name) { + BLI_strncpy(r_name, ts->name, MAX_NAME); } + copy_m3_m3(r_mat, ts->mat); + + return true; } static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it) @@ -492,8 +482,10 @@ void initTransformOrientation(bContext *C, TransInfo *t) unit_m3(t->spacemtx); } break; - default: /* V3D_MANIP_CUSTOM */ - if (applyTransformOrientation(C, t->spacemtx, t->spacename, t->current_orientation - V3D_MANIP_CUSTOM)) { + case V3D_MANIP_CUSTOM: + BLI_strncpy(t->spacename, t->custom_orientation->name, sizeof(t->spacename)); + + if (applyTransformOrientation(t->custom_orientation, t->spacemtx, t->spacename)) { /* pass */ } else { @@ -586,10 +578,10 @@ static unsigned int bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3], const short around) { - Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); Base *base; - Object *ob = OBACT; + Object *ob = OBACT(sl); int result = ORIENTATION_NONE; const bool activeOnly = (around == V3D_AROUND_ACTIVE); @@ -1052,16 +1044,16 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3 } else { /* we need the one selected object, if its not active */ - View3D *v3d = CTX_wm_view3d(C); - ob = OBACT; - if (ob && (ob->flag & SELECT)) { + base = BASACT(sl); + ob = OBACT(sl); + if (base && ((base->flag & BASE_SELECTED) != 0)) { /* pass */ } else { /* first selected */ ob = NULL; - for (base = scene->base.first; base; base = base->next) { - if (TESTBASELIB(v3d, base)) { + for (base = sl->object_bases.first; base; base = base->next) { + if (TESTBASELIB(base)) { ob = base->object; break; } diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 45b8ca3749f..3a71800e9cd 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -49,7 +49,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BIF_gl.h" +#include "GPU_immediate.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" @@ -163,36 +163,42 @@ void drawSnapping(const struct bContext *C, TransInfo *t) size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); invert_m4_m4(imat, rv3d->viewmat); - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + for (p = t->tsnap.points.first; p; p = p->next) { if (p == t->tsnap.selectedPoint) { - glColor4ubv(selectedCol); + immUniformColor4ubv(selectedCol); } else { - glColor4ubv(col); + immUniformColor4ubv(col); } - drawcircball(GL_LINE_LOOP, p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat); + imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat, pos); } if (t->tsnap.status & POINT_INIT) { - glColor4ubv(activeCol); + immUniformColor4ubv(activeCol); - drawcircball(GL_LINE_LOOP, t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat); + imm_drawcircball(t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat, pos); } /* draw normal if needed */ if (usingSnappingNormal(t) && validSnappingNormal(t)) { - glColor4ubv(activeCol); + immUniformColor4ubv(activeCol); - glBegin(GL_LINES); - glVertex3f(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]); - glVertex3f(t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0], - t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1], - t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3f(pos, t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]); + immVertex3f(pos, t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0], + t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1], + t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]); + immEnd(); } - + + immUnbindProgram(); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } @@ -200,35 +206,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t) else if (t->spacetype == SPACE_IMAGE) { if (validSnap(t)) { /* This will not draw, and Im nor sure why - campbell */ -#if 0 - float xuser_asp, yuser_asp; - int wi, hi; - float w, h; - - calc_image_view(G.sima, 'f'); // float - myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax); - glLoadIdentity(); - - ED_space_image_get_aspect(t->sa->spacedata.first, &xuser_aspx, &yuser_asp); - ED_space_image_width(t->sa->spacedata.first, &wi, &hi); - w = (((float)wi) / IMG_SIZE_FALLBACK) * G.sima->zoom * xuser_asp; - h = (((float)hi) / IMG_SIZE_FALLBACK) * G.sima->zoom * yuser_asp; - - cpack(0xFFFFFF); - glTranslate2fv(t->tsnap.snapPoint); - - //glRectf(0, 0, 1, 1); - - setlinestyle(0); - cpack(0x0); - fdrawline(-0.020 / w, 0, -0.1 / w, 0); - fdrawline(0.1 / w, 0, 0.020 / w, 0); - fdrawline(0, -0.020 / h, 0, -0.1 / h); - fdrawline(0, 0.1 / h, 0, 0.020 / h); - - glTranslatef(-t->tsnap.snapPoint[0], -t->tsnap.snapPoint[1], 0.0f); - setlinestyle(0); -#endif + /* TODO: see 2.7x for non-working code */ } } else if (t->spacetype == SPACE_NODE) { @@ -241,23 +219,29 @@ void drawSnapping(const struct bContext *C, TransInfo *t) glEnable(GL_BLEND); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + for (p = t->tsnap.points.first; p; p = p->next) { if (p == t->tsnap.selectedPoint) { - glColor4ubv(selectedCol); + immUniformColor4ubv(selectedCol); } else { - glColor4ubv(col); + immUniformColor4ubv(col); } - ED_node_draw_snap(&ar->v2d, p->co, size, 0); + ED_node_draw_snap(&ar->v2d, p->co, size, 0, pos); } if (t->tsnap.status & POINT_INIT) { - glColor4ubv(activeCol); + immUniformColor4ubv(activeCol); - ED_node_draw_snap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder); + ED_node_draw_snap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder, pos); } - + + immUnbindProgram(); + glDisable(GL_BLEND); } } @@ -519,8 +503,8 @@ static void initSnappingMode(TransInfo *t) { ToolSettings *ts = t->settings; Object *obedit = t->obedit; - Scene *scene = t->scene; - Base *base_act = scene->basact; + SceneLayer *sl = t->scene_layer; + Base *base_act = sl->basact; if (t->spacetype == SPACE_NODE) { /* force project off when not supported */ @@ -601,7 +585,7 @@ static void initSnappingMode(TransInfo *t) if (t->spacetype == SPACE_VIEW3D) { if (t->tsnap.object_context == NULL) { t->tsnap.object_context = ED_transform_snap_object_context_create_view3d( - G.main, t->scene, 0, + G.main, t->scene, t->scene_layer, t->engine, 0, t->ar, t->view); ED_transform_snap_object_context_set_editmesh_callbacks( diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 737005ccf8b..135ea406d60 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -51,6 +51,9 @@ #include "BKE_editmesh.h" #include "BKE_main.h" #include "BKE_tracking.h" +#include "BKE_context.h" + +#include "DEG_depsgraph.h" #include "ED_transform.h" #include "ED_transform_snap_object_context.h" @@ -101,6 +104,8 @@ typedef struct SnapObjectData_EditMesh { struct SnapObjectContext { Main *bmain; Scene *scene; + EvaluationContext eval_ctx; + int flag; /* Optional: when performing screen-space projection. @@ -155,7 +160,7 @@ static void iter_snap_objects( IterSnapObjsCallback sob_callback, void *data) { - Base *base_act = sctx->scene->basact; + Base *base_act = sctx->eval_ctx.scene_layer->basact; /* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA * which makes the loop skip it, even the derived mesh will never change * @@ -165,17 +170,16 @@ static void iter_snap_objects( sob_callback(sctx, false, base_act->object, base_act->object->obmat, data); } - for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) { - if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) && - (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 && - !((snap_select == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL))) || + for (Base *base = sctx->eval_ctx.scene_layer->object_bases.first; base != NULL; base = base->next) { + if ((BASE_VISIBLE(base)) && (base->flag_legacy & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 && + !((snap_select == SNAP_NOT_SELECTED && ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) || (snap_select == SNAP_NOT_ACTIVE && base == base_act))) { bool use_obedit; Object *obj = base->object; if (obj->transflag & OB_DUPLI) { DupliObject *dupli_ob; - ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, obj); + ListBase *lb = object_duplilist(&sctx->eval_ctx, sctx->scene, obj); for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { use_obedit = obedit && dupli_ob->ob->data == obedit->data; sob_callback(sctx, use_obedit, use_obedit ? obedit : dupli_ob->ob, dupli_ob->mat, data); @@ -734,10 +738,10 @@ static bool raycastObj( DerivedMesh *dm; em = BKE_editmesh_from_object(ob); if (em) { - editbmesh_get_derived_cage_and_final(sctx->scene, ob, em, CD_MASK_BAREMESH, &dm); + editbmesh_get_derived_cage_and_final(&sctx->eval_ctx, sctx->scene, ob, em, CD_MASK_BAREMESH, &dm); } else { - dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH); + dm = mesh_get_derived_final(&sctx->eval_ctx, sctx->scene, ob, CD_MASK_BAREMESH); } retval = raycastDerivedMesh( sctx, @@ -1947,10 +1951,10 @@ static bool snapObject( DerivedMesh *dm; em = BKE_editmesh_from_object(ob); if (em) { - editbmesh_get_derived_cage_and_final(sctx->scene, ob, em, CD_MASK_BAREMESH, &dm); + editbmesh_get_derived_cage_and_final(&sctx->eval_ctx, sctx->scene, ob, em, CD_MASK_BAREMESH, &dm); } else { - dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH); + dm = mesh_get_derived_final(&sctx->eval_ctx, sctx->scene, ob, CD_MASK_BAREMESH); } retval = snapDerivedMesh( sctx, snapdata, ob, dm, obmat, @@ -2092,7 +2096,7 @@ static bool snapObjectsRay( * \{ */ SnapObjectContext *ED_transform_snap_object_context_create( - Main *bmain, Scene *scene, int flag) + Main *bmain, Scene *scene, SceneLayer *sl, RenderEngineType *engine, int flag) { SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__); @@ -2101,6 +2105,8 @@ SnapObjectContext *ED_transform_snap_object_context_create( sctx->bmain = bmain; sctx->scene = scene; + DEG_evaluation_context_init_from_scene(&sctx->eval_ctx, scene, sl, engine, DAG_EVAL_VIEWPORT); + sctx->cache.object_map = BLI_ghash_ptr_new(__func__); sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); @@ -2108,11 +2114,11 @@ SnapObjectContext *ED_transform_snap_object_context_create( } SnapObjectContext *ED_transform_snap_object_context_create_view3d( - Main *bmain, Scene *scene, int flag, + Main *bmain, Scene *scene, SceneLayer *sl, RenderEngineType *engine, int flag, /* extra args for view3d */ const ARegion *ar, const View3D *v3d) { - SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, flag); + SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, sl, engine, flag); sctx->use_v3d = true; sctx->v3d_data.ar = ar; diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index c0b30f93939..71a3322cb50 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blenlib ../../blentranslation ../../bmesh + ../../depsgraph ../../imbuf ../../gpu ../../makesdna @@ -64,6 +65,7 @@ set(SRC ../include/ED_lattice.h ../include/ED_logic.h ../include/ED_markers.h + ../include/ED_manipulator_library.h ../include/ED_mask.h ../include/ED_mball.h ../include/ED_mesh.h @@ -75,6 +77,7 @@ set(SRC ../include/ED_particle.h ../include/ED_physics.h ../include/ED_render.h + ../include/ED_scene.h ../include/ED_screen.h ../include/ED_screen_types.h ../include/ED_sculpt.h diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c index b0970cdfd48..872810c5cf2 100644 --- a/source/blender/editors/util/ed_transverts.c +++ b/source/blender/editors/util/ed_transverts.c @@ -39,12 +39,13 @@ #include "BLI_math.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_lattice.h" #include "BKE_editmesh.h" #include "BKE_DerivedMesh.h" #include "BKE_context.h" +#include "DEG_depsgraph.h" + #include "ED_armature.h" #include "ED_transverts.h" /* own include */ @@ -56,7 +57,7 @@ void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit) const int mode = tvs->mode; BLI_assert(ED_transverts_check_obedit(obedit) == true); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); if (obedit->type == OB_MESH) { BMEditMesh *em = BKE_editmesh_from_object(obedit); diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 278b8e34311..d0f29abc62f 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -70,6 +70,8 @@ #include "ED_space_api.h" #include "ED_util.h" +#include "GPU_immediate.h" + #include "UI_interface.h" #include "UI_resources.h" @@ -86,7 +88,8 @@ void ED_editors_init(bContext *C) wmWindowManager *wm = CTX_wm_manager(C); Main *bmain = CTX_data_main(C); Scene *sce = CTX_data_scene(C); - Object *ob, *obact = (sce && sce->basact) ? sce->basact->object : NULL; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob, *obact = (sl && sl->basact) ? sl->basact->object : NULL; ID *data; /* This is called during initialization, so we don't want to store any reports */ @@ -101,12 +104,15 @@ void ED_editors_init(bContext *C) for (ob = bmain->object.first; ob; ob = ob->id.next) { int mode = ob->mode; - if (!ELEM(mode, OB_MODE_OBJECT, OB_MODE_POSE)) { - ob->mode = OB_MODE_OBJECT; + if (mode == OB_MODE_OBJECT) { + /* pass */ + } + else { data = ob->data; - - if (ob == obact && !ID_IS_LINKED(ob) && !(data && ID_IS_LINKED(data))) + ob->mode = OB_MODE_OBJECT; + if ((ob == obact) && !ID_IS_LINKED(ob) && !(data && ID_IS_LINKED(data))) { ED_object_toggle_modes(C, mode); + } } } @@ -313,16 +319,28 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info { wmWindow *win = CTX_wm_window(C); const float *mval_src = (float *)arg_info; - const int mval_dst[2] = {win->eventstate->x - ar->winrct.xmin, - win->eventstate->y - ar->winrct.ymin}; - - UI_ThemeColor(TH_VIEW_OVERLAY); - setlinestyle(3); - glBegin(GL_LINES); - glVertex2iv(mval_dst); - glVertex2fv(mval_src); - glEnd(); - setlinestyle(0); + const float mval_dst[2] = {win->eventstate->x - ar->winrct.xmin, + win->eventstate->y - ar->winrct.ymin}; + + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniformThemeColor(TH_VIEW_OVERLAY); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(shdr_pos, mval_src); + immVertex2fv(shdr_pos, mval_dst); + immEnd(); + + immUnbindProgram(); } /** diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c index 441fd446cd6..d9f777771a8 100644 --- a/source/blender/editors/util/editmode_undo.c +++ b/source/blender/editors/util/editmode_undo.c @@ -42,9 +42,10 @@ #include "BKE_blender_undo.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" +#include "DEG_depsgraph.h" + #include "ED_util.h" #include "ED_mesh.h" @@ -269,7 +270,7 @@ void undo_editmode_step(bContext *C, int step) EDBM_selectmode_to_scene(C); } - DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + DEG_id_tag_update(&obedit->id, OB_RECALC_DATA); /* XXX notifiers */ } diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index 95b5c2c1e48..5b91ee4fc29 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -101,7 +101,7 @@ void ED_undo_push(bContext *C, const char *str) else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) { if (U.undosteps == 0) return; - PE_undo_push(CTX_data_scene(C), str); + PE_undo_push(CTX_data_scene(C), CTX_data_scene_layer(C), str); } else if (obact && obact->mode & OB_MODE_SCULPT) { /* do nothing for now */ @@ -120,6 +120,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname) wmWindow *win = CTX_wm_window(C); Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); Object *obact = CTX_data_active_object(C); ScrArea *sa = CTX_wm_area(C); @@ -180,9 +181,9 @@ static int ed_undo_step(bContext *C, int step, const char *undoname) } else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) { if (step == 1) - PE_undo(scene); + PE_undo(scene, sl); else - PE_redo(scene); + PE_redo(scene, sl); } else if (U.uiflag & USER_GLOBALUNDO) { // note python defines not valid here anymore. @@ -297,7 +298,7 @@ bool ED_undo_is_valid(const bContext *C, const char *undoname) return 1; } else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) { - return PE_undo_is_valid(CTX_data_scene(C)); + return PE_undo_is_valid(CTX_data_scene(C), CTX_data_scene_layer(C)); } if (U.uiflag & USER_GLOBALUNDO) { @@ -542,7 +543,7 @@ static const EnumPropertyItem *rna_undo_itemf(bContext *C, int undosys, int *tot const char *name = NULL; if (undosys == UNDOSYSTEM_PARTICLE) { - name = PE_undo_get_name(CTX_data_scene(C), i, &active); + name = PE_undo_get_name(CTX_data_scene(C), CTX_data_scene_layer(C), i, &active); } else if (undosys == UNDOSYSTEM_EDITMODE) { name = undo_editmode_get_name(C, i, &active); @@ -625,7 +626,7 @@ static int undo_history_exec(bContext *C, wmOperator *op) int item = RNA_int_get(op->ptr, "item"); if (undosys == UNDOSYSTEM_PARTICLE) { - PE_undo_number(CTX_data_scene(C), item); + PE_undo_number(CTX_data_scene(C), CTX_data_scene_layer(C), item); } else if (undosys == UNDOSYSTEM_EDITMODE) { undo_editmode_number(C, item + 1); diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt index 543ef0e0663..a933717fe98 100644 --- a/source/blender/editors/uvedit/CMakeLists.txt +++ b/source/blender/editors/uvedit/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blenlib ../../blentranslation ../../bmesh + ../../depsgraph ../../gpu ../../makesdna ../../makesrna diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c index ab415c0cb83..6b4dd0f0210 100644 --- a/source/blender/editors/uvedit/uvedit_buttons.c +++ b/source/blender/editors/uvedit/uvedit_buttons.c @@ -66,17 +66,14 @@ static int uvedit_center(Scene *scene, BMEditMesh *em, Image *ima, float center[ BMFace *f; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; int tot = 0; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); zero_v2(center); BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(f, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, f, tf)) + if (!uvedit_face_visible_test(scene, ima, f)) continue; BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { @@ -102,14 +99,11 @@ static void uvedit_translate(Scene *scene, BMEditMesh *em, Image *ima, float del BMLoop *l; BMIter iter, liter; MLoopUV *luv; - MTexPoly *tf; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(f, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, f, tf)) + if (!uvedit_face_visible_test(scene, ima, f)) continue; BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index fecacd07997..100c30459e9 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -33,6 +33,8 @@ #include <stdlib.h> #include <string.h> +#include "MEM_guardedalloc.h" + #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -52,9 +54,15 @@ #include "BKE_scene.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" + #include "ED_image.h" #include "ED_mesh.h" #include "ED_uvedit.h" @@ -65,12 +73,7 @@ #include "uvedit_intern.h" -#include "GPU_basic_shader.h" - -/* use editmesh tessface */ -#define USE_EDBM_LOOPTRIS - -static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset); +static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset, const uint shdr_pos); void ED_image_draw_cursor(ARegion *ar, const float cursor[2]) { @@ -81,38 +84,59 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2]) mul_v2_fl(zoom, 256.0f * UI_DPI_FAC); x_fac = zoom[0]; y_fac = zoom[1]; - - cpack(0xFFFFFF); - glTranslate2fv(cursor); - fdrawline(-0.05f * x_fac, 0, 0, 0.05f * y_fac); - fdrawline(0, 0.05f * y_fac, 0.05f * x_fac, 0.0f); - fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac); - fdrawline(0.0f, -0.05f * y_fac, -0.05f * x_fac, 0.0f); - - setlinestyle(4); - cpack(0xFF); - fdrawline(-0.05f * x_fac, 0.0f, 0.0f, 0.05f * y_fac); - fdrawline(0.0f, 0.05f * y_fac, 0.05f * x_fac, 0.0f); - fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac); - fdrawline(0.0f, -0.05f * y_fac, -0.05f * x_fac, 0.0f); - - - setlinestyle(0.0f); - cpack(0x0); - fdrawline(-0.020f * x_fac, 0.0f, -0.1f * x_fac, 0.0f); - fdrawline(0.1f * x_fac, 0.0f, 0.020f * x_fac, 0.0f); - fdrawline(0.0f, -0.020f * y_fac, 0.0f, -0.1f * y_fac); - fdrawline(0.0f, 0.1f * y_fac, 0.0f, 0.020f * y_fac); - - setlinestyle(1); - cpack(0xFFFFFF); - fdrawline(-0.020f * x_fac, 0.0f, -0.1f * x_fac, 0.0f); - fdrawline(0.1f * x_fac, 0.0f, 0.020f * x_fac, 0.0f); - fdrawline(0.0f, -0.020f * y_fac, 0.0f, -0.1f * y_fac); - fdrawline(0.0f, 0.1f * y_fac, 0.0f, 0.020f * y_fac); - - glTranslatef(-cursor[0], -cursor[1], 0.0); - setlinestyle(0); + + gpuTranslate2fv(cursor); + + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 2); /* "advanced" mode */ + immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2); + immUniform1f("dash_width", 8.0f); + + immBegin(GWN_PRIM_LINES, 8); + + immVertex2f(shdr_pos, -0.05f * x_fac, 0.0f); + immVertex2f(shdr_pos, 0.0f, 0.05f * y_fac); + + immVertex2f(shdr_pos, 0.0f, 0.05f * y_fac); + immVertex2f(shdr_pos, 0.05f * x_fac, 0.0f); + + immVertex2f(shdr_pos, 0.05f * x_fac, 0.0f); + immVertex2f(shdr_pos, 0.0f, -0.05f * y_fac); + + immVertex2f(shdr_pos, 0.0f, -0.05f * y_fac); + immVertex2f(shdr_pos, -0.05f * x_fac, 0.0f); + + immEnd(); + + immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2); + immUniform1f("dash_width", 2.0f); + + immBegin(GWN_PRIM_LINES, 8); + + immVertex2f(shdr_pos, -0.020f * x_fac, 0.0f); + immVertex2f(shdr_pos, -0.1f * x_fac, 0.0f); + + immVertex2f(shdr_pos, 0.1f * x_fac, 0.0f); + immVertex2f(shdr_pos, 0.020f * x_fac, 0.0f); + + immVertex2f(shdr_pos, 0.0f, -0.020f * y_fac); + immVertex2f(shdr_pos, 0.0f, -0.1f * y_fac); + + immVertex2f(shdr_pos, 0.0f, 0.1f * y_fac); + immVertex2f(shdr_pos, 0.0f, 0.020f * y_fac); + + immEnd(); + + immUnbindProgram(); + + gpuTranslate2f(-cursor[0], -cursor[1]); } static int draw_uvs_face_check(Scene *scene) @@ -141,41 +165,32 @@ static void draw_uvs_shadow(Object *obedit) const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - /* draws the mesh when painting */ - UI_ThemeColor(TH_UV_SHADOW); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset); - } -} + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); -static int draw_uvs_dm_shadow(DerivedMesh *dm) -{ - /* draw shadow mesh - this is the mesh with the modifier applied */ + /* draws the mesh when painting */ + immUniformThemeColor(TH_UV_SHADOW); - if (dm && dm->drawUVEdges && CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) { - UI_ThemeColor(TH_UV_SHADOW); - dm->drawUVEdges(dm); - return 1; + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos); } - return 0; + immUnbindProgram(); } -static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTexPoly *activetf) +static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, const BMFace *efa_act) { BMesh *bm = em->bm; BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; Image *ima = sima->image; float aspx, aspy, col[4]; int i; const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); BLI_buffer_declare_static(vec2f, tf_uvorig_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); @@ -191,7 +206,6 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe const int efa_len = efa->len; float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa_len); float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uvorig_buf, vec2f, efa_len); - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); @@ -203,28 +217,37 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe totarea += BM_face_calc_area(efa); totuvarea += area_poly_v2(tf_uv, efa->len); - if (uvedit_face_visible_test(scene, ima, efa, tf)) { + if (uvedit_face_visible_test(scene, ima, efa)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); } else { - if (tf == activetf) - activetf = NULL; + if (efa == efa_act) { + efa_act = NULL; + } BM_elem_flag_disable(efa, BM_ELEM_TAG); } } - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + if (totarea < FLT_EPSILON || totuvarea < FLT_EPSILON) { col[0] = 1.0; col[1] = col[2] = 0.0; - glColor3fv(col); + + immUniformColor3fv(col); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - glBegin(GL_POLYGON); + immBegin(GWN_PRIM_TRI_FAN, efa->len); + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } - glEnd(); + + immEnd(); } } } @@ -254,18 +277,23 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe areadiff = 1.0f - (area / uvarea); weight_to_rgb(col, areadiff); - glColor3fv(col); + immUniformColor3fv(col); - /* TODO: USE_EDBM_LOOPTRIS */ - glBegin(GL_POLYGON); + /* TODO: use editmesh tessface */ + immBegin(GWN_PRIM_TRI_FAN, efa->len); + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } - glEnd(); + + immEnd(); } } } + + immUnbindProgram(); + break; } case SI_UVDT_STRETCH_ANGLE: @@ -278,11 +306,15 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe BLI_buffer_declare_static(vec2f, auv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); col[3] = 0.5f; /* hard coded alpha, not that nice */ - + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - if (uvedit_face_visible_test(scene, ima, efa, tf)) { + if (uvedit_face_visible_test(scene, ima, efa)) { const int efa_len = efa->len; float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa_len); float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uvorig_buf, vec2f, efa_len); @@ -319,24 +351,26 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe ang[i] = angle_normalized_v3v3(av[i], av[(i + 1) % efa_len]); } - /* TODO: USE_EDBM_LOOPTRIS */ - glBegin(GL_POLYGON); + /* TODO: use editmesh tessface */ + immBegin(GWN_PRIM_TRI_FAN, efa->len); BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); a = fabsf(uvang[i] - ang[i]) / (float)M_PI; weight_to_rgb(col, 1.0f - pow2f(1.0f - a)); - glColor3fv(col); - glVertex2fv(luv->uv); + immAttrib3fv(color, col); + immVertex2fv(pos, luv->uv); } - glEnd(); + immEnd(); } else { - if (tf == activetf) - activetf = NULL; + if (efa == efa_act) + efa_act = NULL; BM_elem_flag_disable(efa, BM_ELEM_TAG); } } + immUnbindProgram(); + BLI_buffer_free(&uvang_buf); BLI_buffer_free(&ang_buf); BLI_buffer_free(&av_buf); @@ -350,58 +384,74 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe BLI_buffer_free(&tf_uvorig_buf); } -static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset) +static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset, const uint shdr_pos) { BMIter liter; BMLoop *l; MLoopUV *luv; - glBegin(GL_LINE_LOOP); + immBegin(GWN_PRIM_LINE_LOOP, efa->len); + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(shdr_pos, luv->uv); } - glEnd(); + + immEnd(); } -static void draw_uvs_lineloop_mpoly(Mesh *me, MPoly *mpoly) +static void draw_uvs_lineloop_mpoly(Mesh *me, MPoly *mpoly, unsigned int pos) { MLoopUV *mloopuv; int i; - glBegin(GL_LINE_LOOP); + immBegin(GWN_PRIM_LINE_LOOP, mpoly->totloop); + mloopuv = &me->mloopuv[mpoly->loopstart]; for (i = mpoly->totloop; i != 0; i--, mloopuv++) { - glVertex2fv(mloopuv->uv); + immVertex2fv(pos, mloopuv->uv); } - glEnd(); + + immEnd(); } -static void draw_uvs_other_mesh_texface(Object *ob, const Image *curimage, const int other_uv_filter) +static void draw_uvs_other_mesh_texface(Object *ob, const Image *curimage, const int other_uv_filter, unsigned int pos) { Mesh *me = ob->data; MPoly *mpoly = me->mpoly; - MTexPoly *mtpoly = me->mtpoly; int a; if (me->mloopuv == NULL) { return; } - for (a = me->totpoly; a != 0; a--, mpoly++, mtpoly++) { + Image **image_array = NULL; + + if (other_uv_filter == SI_FILTER_SAME_IMAGE) { + image_array = BKE_object_material_edit_image_get_array(ob); + } + + for (a = me->totpoly; a != 0; a--, mpoly++) { if (other_uv_filter == SI_FILTER_ALL) { /* Nothing to compare, all UV faces are visible. */ } else if (other_uv_filter == SI_FILTER_SAME_IMAGE) { - if (mtpoly->tpage != curimage) { + if (mpoly[a].mat_nr >= ob->totcol) { + continue; + } + if (image_array[mpoly[a].mat_nr] != curimage) { continue; } } - draw_uvs_lineloop_mpoly(me, mpoly); + draw_uvs_lineloop_mpoly(me, mpoly, pos); + } + + if (image_array) { + MEM_freeN(image_array); } } -static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage, const int other_uv_filter) +static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage, const int other_uv_filter, unsigned int pos) { Mesh *me = ob->data; MPoly *mpoly = me->mpoly; @@ -453,41 +503,43 @@ static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage, c } } - draw_uvs_lineloop_mpoly(me, mpoly); + draw_uvs_lineloop_mpoly(me, mpoly, pos); } } static void draw_uvs_other_mesh(Object *ob, const Image *curimage, const bool new_shading_nodes, - const int other_uv_filter) + const int other_uv_filter, unsigned int pos) { if (new_shading_nodes) { - draw_uvs_other_mesh_new_shading(ob, curimage, other_uv_filter); + draw_uvs_other_mesh_new_shading(ob, curimage, other_uv_filter, pos); } else { - draw_uvs_other_mesh_texface(ob, curimage, other_uv_filter); + draw_uvs_other_mesh_texface(ob, curimage, other_uv_filter, pos); } } -static void draw_uvs_other(Scene *scene, Object *obedit, const Image *curimage, const bool new_shading_nodes, +static void draw_uvs_other(SceneLayer *sl, Object *obedit, const Image *curimage, const bool new_shading_nodes, const int other_uv_filter) { - Base *base; - - UI_ThemeColor(TH_UV_OTHERS); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - for (base = scene->base.first; base; base = base->next) { - Object *ob = base->object; + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - if (!(base->flag & SELECT)) continue; - if (!(base->lay & scene->lay)) continue; - if (ob->restrictflag & OB_RESTRICT_VIEW) continue; + immUniformThemeColor(TH_UV_OTHERS); - if ((ob->type == OB_MESH) && (ob != obedit) && ((Mesh *)ob->data)->mloopuv) { - draw_uvs_other_mesh(ob, curimage, new_shading_nodes, other_uv_filter); + for (Base *base = sl->object_bases.first; base; base = base->next) { + if (((base->flag & BASE_SELECTED) != 0) && + ((base->flag & BASE_VISIBLED) != 0)) + { + Object *ob = base->object; + if ((ob->type == OB_MESH) && (ob != obedit) && ((Mesh *)ob->data)->mloopuv) { + draw_uvs_other_mesh(ob, curimage, new_shading_nodes, other_uv_filter, pos); + } } } + immUnbindProgram(); } -static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob) +static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, SceneLayer *sl, Object *ob) { const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); Image *curimage = ED_space_image(sima); @@ -495,11 +547,9 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob) Material *ma; if (sima->flag & SI_DRAW_OTHER) { - draw_uvs_other(scene, ob, curimage, new_shading_nodes, sima->other_uv_filter); + draw_uvs_other(sl, ob, curimage, new_shading_nodes, sima->other_uv_filter); } - UI_ThemeColor(TH_UV_SHADOW); - ma = give_current_material(ob, ob->actcol); if (me->mloopuv) { @@ -512,24 +562,33 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob) mloopuv = me->mloopuv; } + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColor(TH_UV_SHADOW); + mloopuv_base = mloopuv; for (a = me->totpoly; a > 0; a--, mpoly++) { if ((scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE) && mpoly->mat_nr != ob->actcol - 1) continue; - glBegin(GL_LINE_LOOP); + + immBegin(GWN_PRIM_LINE_LOOP, mpoly->totloop); mloopuv = mloopuv_base + mpoly->loopstart; for (b = 0; b < mpoly->totloop; b++, mloopuv++) { - glVertex2fv(mloopuv->uv); + immVertex2fv(pos, mloopuv->uv); } - glEnd(); + + immEnd(); } + + immUnbindProgram(); } } -#ifdef USE_EDBM_LOOPTRIS -static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const int cd_loop_uv_offset) +static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const int cd_loop_uv_offset, unsigned int pos) { unsigned int i = *r_loop_index; BMFace *f = em->looptris[i][0]->f; @@ -537,16 +596,15 @@ static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const i unsigned int j; for (j = 0; j < 3; j++) { MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(em->looptris[i][j], cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } i++; } while (i != em->tottri && (f == em->looptris[i][0]->f)); *r_loop_index = i - 1; } -#endif /* draws uv's in the image space */ -static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) +static void draw_uvs(SpaceImage *sima, Scene *scene, SceneLayer *sl, Object *obedit, Depsgraph *depsgraph) { const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); ToolSettings *ts; @@ -554,26 +612,19 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) BMEditMesh *em = me->edit_btmesh; BMesh *bm = em->bm; BMFace *efa, *efa_act; -#ifndef USE_EDBM_LOOPTRIS - BMFace *activef; -#endif BMLoop *l; BMIter iter, liter; - MTexPoly *tf, *activetf = NULL; MLoopUV *luv; - DerivedMesh *finaldm, *cagedm; unsigned char col1[4], col2[4]; float pointsize; int drawfaces, interpedges; Image *ima = sima->image; const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); - activetf = EDBM_mtexpoly_active_get(em, &efa_act, false, false); /* will be set to NULL if hidden */ -#ifndef USE_EDBM_LOOPTRIS - activef = BM_mesh_active_face_get(bm, false, false); -#endif + unsigned int pos; + + efa_act = EDBM_uv_active_face_get(em, false, false); /* will be set to NULL if hidden */ ts = scene->toolsettings; drawfaces = draw_uvs_face_check(scene); @@ -595,38 +646,30 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) } } else { - curimage = (activetf) ? activetf->tpage : ima; + curimage = (efa_act) ? BKE_object_material_edit_image_get(obedit, efa_act->mat_nr) : ima; } - draw_uvs_other(scene, obedit, curimage, new_shading_nodes, sima->other_uv_filter); + draw_uvs_other(sl, obedit, curimage, new_shading_nodes, sima->other_uv_filter); } /* 1. draw shadow mesh */ if (sima->flag & SI_DRAWSHADOW) { - DM_update_materials(em->derivedFinal, obedit); - /* first try existing derivedmesh */ - if (!draw_uvs_dm_shadow(em->derivedFinal)) { - /* create one if it does not exist */ - cagedm = editbmesh_get_derived_cage_and_final( - scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH | CD_MASK_MTFACE, - &finaldm); - - /* when sync selection is enabled, all faces are drawn (except for hidden) - * so if cage is the same as the final, theres no point in drawing this */ - if (!((ts->uv_flag & UV_SYNC_SELECTION) && (cagedm == finaldm))) - draw_uvs_dm_shadow(finaldm); - - /* release derivedmesh again */ - if (cagedm != finaldm) cagedm->release(cagedm); - finaldm->release(finaldm); + Object *ob_cage = DEG_get_evaluated_object(depsgraph, obedit); + /* XXX TODO: Need to check if shadow mesh is different than original mesh. */ + bool is_cage_like_final_meshes = (ob_cage == obedit); + + /* When sync selection is enabled, all faces are drawn (except for hidden) + * so if cage is the same as the final, there is no point in drawing this. */ + if (((ts->uv_flag & UV_SYNC_SELECTION) == 0) || is_cage_like_final_meshes) { + draw_uvs_shadow(ob_cage); } } - + /* 2. draw colored faces */ if (sima->flag & SI_DRAW_STRETCH) { - draw_uvs_stretch(sima, scene, em, activetf); + draw_uvs_stretch(sima, scene, em, efa_act); } else if (!(sima->flag & SI_NO_DRAWFACES)) { /* draw transparent faces */ @@ -635,79 +678,47 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); -#ifdef USE_EDBM_LOOPTRIS - { - unsigned int i; - for (i = 0; i < em->tottri; i++) { - efa = em->looptris[i][0]->f; - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (uvedit_face_visible_test(scene, ima, efa, tf)) { - const bool is_select = uvedit_face_select_test(scene, efa, cd_loop_uv_offset); - BM_elem_flag_enable(efa, BM_ELEM_TAG); + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - if (tf == activetf) { - /* only once */ - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE); - UI_ThemeColor4(TH_EDITMESH_ACTIVE); - } - else { - glColor4ubv((GLubyte *)(is_select ? col2 : col1)); - } + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - glBegin(GL_TRIANGLES); - draw_uvs_looptri(em, &i, cd_loop_uv_offset); - glEnd(); + for (unsigned int i = 0; i < em->tottri; i++) { + efa = em->looptris[i][0]->f; + if (uvedit_face_visible_test(scene, ima, efa)) { + const bool is_select = uvedit_face_select_test(scene, efa, cd_loop_uv_offset); + BM_elem_flag_enable(efa, BM_ELEM_TAG); - if (tf == activetf) { - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } + if (efa == efa_act) { + /* only once */ + immUniformThemeColor(TH_EDITMESH_ACTIVE); } else { - BM_elem_flag_disable(efa, BM_ELEM_TAG); + immUniformColor4ubv(is_select ? col2 : col1); } - } - } -#else - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (uvedit_face_visible_test(scene, ima, efa, tf)) { - BM_elem_flag_enable(efa, BM_ELEM_TAG); - if (tf == activetf) continue; /* important the temp boolean is set above */ - if (uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) - glColor4ubv((GLubyte *)col2); - else - glColor4ubv((GLubyte *)col1); - - glBegin(GL_POLYGON); - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - glVertex2fv(luv->uv); - } - glEnd(); + immBegin(GWN_PRIM_TRIS, (em->looptris[i][0]->f->len - 2) * 3); + draw_uvs_looptri(em, &i, cd_loop_uv_offset, pos); + immEnd(); } else { - if (tf == activetf) - activetf = NULL; BM_elem_flag_disable(efa, BM_ELEM_TAG); } } -#endif + + immUnbindProgram(); + glDisable(GL_BLEND); } else { /* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - if (uvedit_face_visible_test(scene, ima, efa, tf)) { + if (uvedit_face_visible_test(scene, ima, efa)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); } else { - if (tf == activetf) - activetf = NULL; + if (efa == efa_act) + efa_act = NULL; BM_elem_flag_disable(efa, BM_ELEM_TAG); } } @@ -715,30 +726,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) } /* 3. draw active face stippled */ -#ifndef USE_EDBM_LOOPTRIS - if (activef) { - tf = BM_ELEM_CD_GET_VOID_P(activef, cd_poly_tex_offset); - if (uvedit_face_visible_test(scene, ima, activef, tf)) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - UI_ThemeColor4(TH_EDITMESH_ACTIVE); - - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE); - - glBegin(GL_POLYGON); - BM_ITER_ELEM (l, &liter, activef, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - glVertex2fv(luv->uv); - } - glEnd(); + /* (removed during OpenGL upgrade, reimplement if needed) */ - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - glDisable(GL_BLEND); - } - } -#endif - /* 4. draw edges */ if (sima->flag & SI_SMOOTH_UV) { @@ -751,104 +740,150 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) switch (sima->dt_uv) { case SI_UVDT_DASH: + { + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 2); /* "advanced" mode */ + immUniformArray4fv("colors", (float *)(float[][4]){{0.56f, 0.56f, 0.56f, 1.0f}, {0.07f, 0.07f, 0.07f, 1.0f}}, 2); + immUniform1f("dash_width", 4.0f); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (tf) { - cpack(0x111111); + draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, shdr_pos); + } - draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset); + immUnbindProgram(); - setlinestyle(2); - cpack(0x909090); + break; + } + case SI_UVDT_BLACK: /* black/white */ + case SI_UVDT_WHITE: + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - setlinestyle(0); - } + if (sima->dt_uv == SI_UVDT_WHITE) { + immUniformColor3f(1.0f, 1.0f, 1.0f); + } + else { + immUniformColor3f(0.0f, 0.0f, 0.0f); } - break; - case SI_UVDT_BLACK: /* black/white */ - case SI_UVDT_WHITE: - if (sima->dt_uv == SI_UVDT_WHITE) glColor3f(1.0f, 1.0f, 1.0f); - else glColor3f(0.0f, 0.0f, 0.0f); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; - draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset); + draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos); } + + immUnbindProgram(); + break; case SI_UVDT_OUTLINE: + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + glLineWidth(3); - cpack(0x0); - + imm_cpack(0x0); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; - draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset); + draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos); } - + + immUnbindProgram(); + glLineWidth(1); UI_GetThemeColor4ubv(TH_WIRE_EDIT, col2); - glColor4ubv((unsigned char *)col2); if (me->drawflag & ME_DRAWEDGES) { - int sel, lastsel = -1; + int sel; UI_GetThemeColor4ubv(TH_EDGE_SELECT, col1); + Gwn_VertFormat *format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + if (interpedges) { - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; - glBegin(GL_LINE_LOOP); + immBegin(GWN_PRIM_LINE_LOOP, efa->len); + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { sel = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); - glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); + immAttrib4ubv(color, sel ? (GLubyte *)col1 : (GLubyte *)col2); luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } - glEnd(); + + immEnd(); } + + immUnbindProgram(); } else { + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + int lastsel = -1; + if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, efa->len * 2); + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { sel = uvedit_edge_select_test(scene, l, cd_loop_uv_offset); if (sel != lastsel) { - glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); + immAttrib4ubv(color, sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); luv = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } - glEnd(); + + immEnd(); } + + immUnbindProgram(); } } else { + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv(col2); + /* no nice edges */ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; - draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset); + draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos); } + + immUnbindProgram(); } - + break; } @@ -861,50 +896,80 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) if (drawfaces) { float cent[2]; - + bool col_set = false; + + Gwn_VertFormat *format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + pointsize = UI_GetThemeValuef(TH_FACEDOT_SIZE); glPointSize(pointsize); - glBegin(GL_POINTS); + immBeginAtMost(GWN_PRIM_POINTS, bm->totface); /* unselected faces */ - UI_ThemeColor(TH_WIRE); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; if (!uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + /* Only set color for the first face */ + if (!col_set) { + UI_GetThemeColor3ubv(TH_WIRE, col1); + immAttrib3ubv(color, col1); + + col_set = true; + } + uv_poly_center(efa, cent, cd_loop_uv_offset); - glVertex2fv(cent); + immVertex2fv(pos, cent); } } + col_set = false; + /* selected faces */ - UI_ThemeColor(TH_FACE_DOT); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; if (uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + /* Only set color for the first face */ + if (!col_set) { + UI_GetThemeColor3ubv(TH_FACE_DOT, col1); + immAttrib3ubv(color, col1); + + col_set = true; + } + uv_poly_center(efa, cent, cd_loop_uv_offset); - glVertex2fv(cent); + immVertex2fv(pos, cent); } } - glEnd(); + immEnd(); + + immUnbindProgram(); } /* 6. draw uv vertices */ if (drawfaces != 2) { /* 2 means Mesh Face Mode */ + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* unselected uvs */ - UI_ThemeColor(TH_VERTEX); + immUniformThemeColor(TH_VERTEX); pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE); glPointSize(pointsize); - - glBegin(GL_POINTS); + + immBeginAtMost(GWN_PRIM_POINTS, bm->totloop); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; @@ -912,17 +977,19 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (!uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } } - glEnd(); + + immEnd(); /* pinned uvs */ /* give odd pointsizes odd pin pointsizes */ glPointSize(pointsize * 2 + (((int)pointsize % 2) ? (-1) : 0)); - cpack(0xFF); + imm_cpack(0xFF); - glBegin(GL_POINTS); + immBeginAtMost(GWN_PRIM_POINTS, bm->totloop); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; @@ -931,16 +998,18 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_PINNED) - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } } - glEnd(); + + immEnd(); /* selected uvs */ - UI_ThemeColor(TH_VERTEX_SELECT); + immUniformThemeColor(TH_VERTEX_SELECT); glPointSize(pointsize); - glBegin(GL_POINTS); + immBeginAtMost(GWN_PRIM_POINTS, bm->totloop); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; @@ -949,10 +1018,13 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } } - glEnd(); + + immEnd(); + + immUnbindProgram(); } } @@ -967,13 +1039,13 @@ static void draw_uv_shadows_get(SpaceImage *sima, Object *ob, Object *obedit, bo if ((sima->mode == SI_MODE_PAINT) && obedit && obedit->type == OB_MESH) { struct BMEditMesh *em = BKE_editmesh_from_object(obedit); - *show_shadow = EDBM_mtexpoly_check(em); + *show_shadow = EDBM_uv_check(em); } *show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT); } -void ED_uvedit_draw_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit, Object *obact) +void ED_uvedit_draw_main(SpaceImage *sima, ARegion *ar, Scene *scene, SceneLayer *sl, Object *obedit, Object *obact, Depsgraph *depsgraph) { ToolSettings *toolsettings = scene->toolsettings; bool show_uvedit, show_uvshadow, show_texpaint_uvshadow; @@ -985,9 +1057,9 @@ void ED_uvedit_draw_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *ob if (show_uvshadow) draw_uvs_shadow(obedit); else if (show_uvedit) - draw_uvs(sima, scene, obedit); + draw_uvs(sima, scene, sl, obedit, depsgraph); else - draw_uvs_texpaint(sima, scene, obact); + draw_uvs_texpaint(sima, scene, sl, obact); if (show_uvedit && !(toolsettings->use_uv_sculpt)) ED_image_draw_cursor(ar, sima->cursor); diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index e028c08091c..6ca46941404 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -32,7 +32,6 @@ #ifndef __UVEDIT_INTERN_H__ #define __UVEDIT_INTERN_H__ -struct MTexPoly; struct Image; struct Object; struct Scene; @@ -53,7 +52,6 @@ void uv_poly_center(struct BMFace *f, float r_cent[2], const int cd_loop_uv_off typedef struct NearestHit { struct BMFace *efa; - struct MTexPoly *tf; struct BMLoop *l; struct MLoopUV *luv, *luv_next; int lindex; /* index of loop within face */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index d69588e91c6..03a5f4dddc8 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -57,7 +57,6 @@ #include "BKE_context.h" #include "BKE_customdata.h" -#include "BKE_depsgraph.h" #include "BKE_image.h" #include "BKE_library.h" #include "BKE_main.h" @@ -68,6 +67,8 @@ #include "BKE_scene.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" + #include "ED_image.h" #include "ED_mesh.h" #include "ED_node.h" @@ -106,7 +107,7 @@ bool ED_uvedit_test(Object *obedit) return 0; em = BKE_editmesh_from_object(obedit); - ret = EDBM_mtexpoly_check(em); + ret = EDBM_uv_check(em); return ret; } @@ -182,7 +183,6 @@ void ED_uvedit_assign_image(Main *UNUSED(bmain), Scene *scene, Object *obedit, I { BMEditMesh *em; BMIter iter; - MTexPoly *tf; bool update = false; const bool selected = !(scene->toolsettings->uv_flag & UV_SYNC_SELECTION); @@ -206,8 +206,6 @@ void ED_uvedit_assign_image(Main *UNUSED(bmain), Scene *scene, Object *obedit, I BMFace *efa; int cd_loop_uv_offset; - int cd_poly_tex_offset; - /* old shading system, assign image to selected faces */ #ifdef USE_SWITCH_ASPECT float prev_aspect[2], fprev_aspect; @@ -221,31 +219,22 @@ void ED_uvedit_assign_image(Main *UNUSED(bmain), Scene *scene, Object *obedit, I #endif /* ensure we have a uv map */ - if (!CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) { - BM_data_layer_add(em->bm, &em->bm->pdata, CD_MTEXPOLY); + if (!CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) { BM_data_layer_add(em->bm, &em->bm->ldata, CD_MLOOPUV); /* make UVs all nice 0-1 */ - ED_mesh_uv_loop_reset_ex(obedit->data, CustomData_get_active_layer(&em->bm->pdata, CD_MTEXPOLY)); + ED_mesh_uv_loop_reset_ex(obedit->data, CustomData_get_active_layer(&em->bm->ldata, CD_MLOOPUV)); update = true; } cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); /* now assign to all visible faces */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - if (uvedit_face_visible_test(scene, previma, efa, tf) && + if (uvedit_face_visible_test(scene, previma, efa) && (selected == true || uvedit_face_select_test(scene, efa, cd_loop_uv_offset))) { - if (ima) { - tf->tpage = ima; - - if (ima->id.us == 0) id_us_plus(&ima->id); - else id_lib_extern(&ima->id); - #ifdef USE_SWITCH_ASPECT + if (ima) { /* we also need to correct the aspect of uvs */ if (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) { /* do nothing */ @@ -261,11 +250,9 @@ void ED_uvedit_assign_image(Main *UNUSED(bmain), Scene *scene, Object *obedit, I luv->uv[0] /= faspect; } } -#endif - } - else { - tf->tpage = NULL; } +#endif + BKE_object_material_edit_image_set(obedit, efa->mat_nr, ima); update = true; } @@ -273,49 +260,12 @@ void ED_uvedit_assign_image(Main *UNUSED(bmain), Scene *scene, Object *obedit, I /* and update depdency graph */ if (update) { - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); } } } -/* dotile - 1, set the tile flag (from the space image) - * 2, set the tile index for the faces. */ -static bool uvedit_set_tile(Object *obedit, Image *ima, int curtile) -{ - BMEditMesh *em; - BMFace *efa; - BMIter iter; - MTexPoly *tf; - int cd_poly_tex_offset; - - /* verify if we have something to do */ - if (!ima || !ED_uvedit_test(obedit)) - return false; - - if ((ima->tpageflag & IMA_TILES) == 0) - return false; - - /* skip assigning these procedural images... */ - if (ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE) - return false; - - em = BKE_editmesh_from_object(obedit); - - cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) - tf->tile = curtile; /* set tile index */ - } - - DAG_id_tag_update(obedit->data, 0); - - return true; -} - /*********************** space conversion *********************/ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist) @@ -346,14 +296,17 @@ bool uvedit_face_visible_nolocal(Scene *scene, BMFace *efa) return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0 && BM_elem_flag_test(efa, BM_ELEM_SELECT)); } -bool uvedit_face_visible_test(Scene *scene, Image *ima, BMFace *efa, MTexPoly *tf) +bool uvedit_face_visible_test(Scene *scene, Image *ima, BMFace *efa) { ToolSettings *ts = scene->toolsettings; - if (ts->uv_flag & UV_SHOW_SAME_IMAGE) - return (tf->tpage == ima) ? uvedit_face_visible_nolocal(scene, efa) : false; - else + if (ts->uv_flag & UV_SHOW_SAME_IMAGE) { + const Image *face_image = BKE_object_material_edit_image_get(scene->obedit, efa->mat_nr); + return (face_image == ima) ? uvedit_face_visible_nolocal(scene, efa) : false; + } + else { return uvedit_face_visible_nolocal(scene, efa); + } } bool uvedit_face_select_test(Scene *scene, BMFace *efa, @@ -646,18 +599,15 @@ bool ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2], BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; bool changed = false; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); INIT_MINMAX2(r_min, r_max); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -696,17 +646,14 @@ static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[ BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; unsigned int sel = 0; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); zero_v2(co); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -723,7 +670,7 @@ static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[ return (sel != 0); } -static bool uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], char mode) +bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], char mode) { bool changed = false; @@ -747,7 +694,6 @@ static bool uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2 void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float co[2], NearestHit *hit) { - MTexPoly *tf; BMFace *efa; BMLoop *l; BMIter iter, liter; @@ -756,7 +702,6 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float int i; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); mindist_squared = 1e10f; memset(hit, 0, sizeof(*hit)); @@ -764,8 +709,7 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float BM_mesh_elem_index_ensure(em->bm, BM_VERT); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { @@ -775,7 +719,6 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float dist_squared = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv); if (dist_squared < mindist_squared) { - hit->tf = tf; hit->efa = efa; hit->l = l; @@ -791,13 +734,11 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float static void uv_find_nearest_face(Scene *scene, Image *ima, BMEditMesh *em, const float co[2], NearestHit *hit) { - MTexPoly *tf; BMFace *efa; BMIter iter; float mindist, dist, cent[2]; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); mindist = 1e10f; memset(hit, 0, sizeof(*hit)); @@ -808,8 +749,7 @@ static void uv_find_nearest_face(Scene *scene, Image *ima, BMEditMesh *em, const hit->luv = hit->luv_next = NULL; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; uv_poly_center(efa, cent, cd_loop_uv_offset); @@ -817,7 +757,6 @@ static void uv_find_nearest_face(Scene *scene, Image *ima, BMEditMesh *em, const dist = len_manhattan_v2v2(co, cent); if (dist < mindist) { - hit->tf = tf; hit->efa = efa; mindist = dist; } @@ -841,13 +780,11 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em, BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; float mindist, dist; int i; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); /*this will fill in hit.vert1 and hit.vert2*/ uv_find_nearest_edge(scene, ima, em, co, hit); @@ -860,8 +797,7 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em, BM_mesh_elem_index_ensure(em->bm, BM_VERT); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { @@ -883,7 +819,6 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em, hit->l = l; hit->luv = luv; hit->luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - hit->tf = tf; hit->efa = efa; hit->lindex = i; } @@ -897,20 +832,17 @@ bool ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; float mindist, dist; bool found = false; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); mindist = 1e10f; copy_v2_v2(r_uv, co); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -1020,7 +952,6 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH BMFace *efa; BMIter iter, liter; BMLoop *l; - MTexPoly *tf; UvVertMap *vmap; UvMapVert *iterv_curr; UvMapVert *iterv_next; @@ -1028,7 +959,6 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH bool looking, select; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); /* setup */ BM_mesh_elem_table_ensure(em->bm, BM_FACE); @@ -1061,9 +991,7 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH /* find correct valence edges which are not tagged yet, but connect to tagged one */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && uvedit_face_visible_test(scene, ima, efa, tf)) { + if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && uvedit_face_visible_test(scene, ima, efa)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { /* check face not hidden and not tagged */ if (!(iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l))) @@ -1123,7 +1051,6 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; UvVertMap *vmap; UvMapVert *vlist, *iterv, *startv; @@ -1132,7 +1059,6 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo char *flag; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */ @@ -1152,9 +1078,7 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo if (!hit) { BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - if (uvedit_face_visible_test(scene, ima, efa, tf)) { + if (uvedit_face_visible_test(scene, ima, efa)) { if (select_faces) { if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { stack[stacksize] = a; @@ -1318,12 +1242,9 @@ static float *uv_sel_co_from_eve(Scene *scene, Image *ima, BMEditMesh *em, BMVer BMLoop *l; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) { - MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset); - - if (!uvedit_face_visible_test(scene, ima, l->f, tf)) + if (!uvedit_face_visible_test(scene, ima, l->f)) continue; if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { @@ -1349,7 +1270,6 @@ static int uv_select_more_less(bContext *C, const bool select) ToolSettings *ts = scene->toolsettings; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); if (ts->uv_flag & UV_SYNC_SELECTION) { if (select) { @@ -1372,9 +1292,7 @@ static int uv_select_more_less(bContext *C, const bool select) /* mark loops to be selected */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - if (uvedit_face_visible_test(scene, ima, efa, tf)) { + if (uvedit_face_visible_test(scene, ima, efa)) { #define IS_SEL 1 #define IS_UNSEL 2 @@ -1417,9 +1335,7 @@ static int uv_select_more_less(bContext *C, const bool select) /* mark loops to be selected */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - if (uvedit_face_visible_test(scene, ima, efa, tf)) { + if (uvedit_face_visible_test(scene, ima, efa)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); @@ -1486,11 +1402,9 @@ static void uv_weld_align(bContext *C, int tool) SpaceImage *sima; Scene *scene; Image *ima; - MTexPoly *tf; float cent[2], min[2], max[2]; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); scene = CTX_data_scene(C); ima = CTX_data_edit_image(C); @@ -1504,9 +1418,7 @@ static void uv_weld_align(bContext *C, int tool) BMLoop *l; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -1520,7 +1432,7 @@ static void uv_weld_align(bContext *C, int tool) tool = (max[0] - min[0] >= max[1] - min[1]) ? 'y' : 'x'; } - uvedit_center(scene, ima, obedit, cent, 0); + ED_uvedit_center(scene, ima, obedit, cent, 0); if (tool == 'x' || tool == 'w') { BMIter iter, liter; @@ -1528,8 +1440,7 @@ static void uv_weld_align(bContext *C, int tool) BMLoop *l; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -1548,8 +1459,7 @@ static void uv_weld_align(bContext *C, int tool) BMLoop *l; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -1577,9 +1487,7 @@ static void uv_weld_align(bContext *C, int tool) /* tag verts with a selected UV */ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) { - tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset); - - if (!uvedit_face_visible_test(scene, ima, l->f, tf)) + if (!uvedit_face_visible_test(scene, ima, l->f)) continue; if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { @@ -1667,9 +1575,7 @@ static void uv_weld_align(bContext *C, int tool) /* go over all verts except for endpoints */ for (i = 0; i < BLI_array_count(eve_line); i++) { BM_ITER_ELEM (l, &liter, eve_line[i], BM_LOOPS_OF_VERT) { - tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset); - - if (!uvedit_face_visible_test(scene, ima, l->f, tf)) + if (!uvedit_face_visible_test(scene, ima, l->f)) continue; if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { @@ -1703,7 +1609,7 @@ static void uv_weld_align(bContext *C, int tool) uvedit_live_unwrap_update(sima, scene, obedit); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); } @@ -1755,7 +1661,6 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); Image *ima; - MTexPoly *tf; int uv_a_index; int uv_b_index; float *uv_a; @@ -1766,7 +1671,6 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op) BMLoop *l; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); sima = CTX_wm_space_image(C); scene = CTX_data_scene(C); @@ -1780,8 +1684,7 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op) /* TODO, use qsort as with MESH_OT_remove_doubles, this isn't optimal */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -1843,8 +1746,7 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op) BLI_array_declare(loop_arr_unselected); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -1881,7 +1783,7 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op) } uvedit_live_unwrap_update(sima, scene, obedit); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -1934,11 +1836,9 @@ static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); if (ts->uv_flag & UV_SYNC_SELECTION) { @@ -1962,9 +1862,7 @@ static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int if (action == SEL_TOGGLE) { action = SEL_SELECT; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -1980,9 +1878,7 @@ static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -2071,7 +1967,6 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; NearestHit hit; int i, selectmode, sticky, sync, *hitv = NULL; @@ -2081,7 +1976,6 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo float penalty[2]; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); /* notice 'limit' is the same no matter the zoom level, since this is like * remove doubles and could annoying if it joined points when zoomed out. @@ -2233,8 +2127,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo BM_mesh_elem_index_ensure(em->bm, BM_VERT); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -2269,8 +2162,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo /* select sticky uvs */ if (sticky != SI_STICKY_DISABLE) { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -2313,7 +2205,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo #endif } - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; @@ -2452,7 +2344,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent uv_select_linked(scene, ima, em, limit, hit_p, extend, select_faces); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -2526,12 +2418,10 @@ static int uv_select_split_exec(bContext *C, wmOperator *op) BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; bool changed = false; const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); if (ts->uv_flag & UV_SYNC_SELECTION) { BKE_report(op->reports, RPT_ERROR, "Cannot split selection when sync selection is enabled"); @@ -2543,9 +2433,8 @@ static int uv_select_split_exec(bContext *C, wmOperator *op) BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { bool is_sel = false; bool is_unsel = false; - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; /* are we all selected? */ @@ -2686,7 +2575,6 @@ static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object BMFace *efa; BMLoop *l; BMIter iter, liter; - /* MTexPoly *tf; */ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) { @@ -2775,7 +2663,6 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object BMFace *efa; BMLoop *l; BMIter iter, liter; - /* MTexPoly *tf; */ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); @@ -2859,7 +2746,6 @@ static int uv_border_select_exec(bContext *C, wmOperator *op) BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; rctf rectf; bool changed, pinned, select, extend; @@ -2868,7 +2754,6 @@ static int uv_border_select_exec(bContext *C, wmOperator *op) (ts->uv_selectmode == UV_SELECT_FACE); const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); /* get rectangle from operator */ WM_operator_properties_border_to_rctf(op, &rectf); @@ -2893,8 +2778,7 @@ static int uv_border_select_exec(bContext *C, wmOperator *op) /* assume not touched */ BM_elem_flag_disable(efa, BM_ELEM_TAG); - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (uvedit_face_visible_test(scene, ima, efa, tf)) { + if (uvedit_face_visible_test(scene, ima, efa)) { uv_poly_center(efa, cent, cd_loop_uv_offset); if (BLI_rctf_isect_pt_v(&rectf, cent)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); @@ -2913,8 +2797,7 @@ static int uv_border_select_exec(bContext *C, wmOperator *op) changed = true; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); @@ -3111,13 +2994,11 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo (ts->uv_selectmode == UV_SELECT_FACE)); const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); BMIter iter, liter; BMFace *efa; BMLoop *l; - MTexPoly *tf; int screen_uv[2]; bool changed = false; rcti rect; @@ -3153,8 +3034,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo } else { /* Vert Sel */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (uvedit_face_visible_test(scene, ima, efa, tf)) { + if (uvedit_face_visible_test(scene, ima, efa)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); @@ -3244,7 +3124,7 @@ static void uv_snap_cursor_to_pixels(SpaceImage *sima) static bool uv_snap_cursor_to_selection(Scene *scene, Image *ima, Object *obedit, SpaceImage *sima) { - return uvedit_center(scene, ima, obedit, sima->cursor, sima->around); + return ED_uvedit_center(scene, ima, obedit, sima->cursor, sima->around); } static int uv_snap_cursor_exec(bContext *C, wmOperator *op) @@ -3302,16 +3182,13 @@ static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, cons BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tface; MLoopUV *luv; bool changed = false; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tface)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -3332,16 +3209,13 @@ static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const f BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *mtexpoly; MLoopUV *luv; bool changed = false; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - mtexpoly = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, mtexpoly)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -3363,17 +3237,14 @@ static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object BMFace *f; BMLoop *l, *lsub; BMIter iter, liter, lsubiter; - MTexPoly *tface; MLoopUV *luv; bool changed = false; const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); /* index every vert that has a selected UV using it, but only once so as to * get unique indices and to count how much to malloc */ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - tface = BM_ELEM_CD_GET_VOID_P(f, cd_poly_tex_offset); - if (uvedit_face_visible_test(scene, ima, f, tface)) { + if (uvedit_face_visible_test(scene, ima, f)) { BM_elem_flag_enable(f, BM_ELEM_TAG); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BM_elem_flag_set(l, BM_ELEM_TAG, uvedit_uv_select_test(scene, l, cd_loop_uv_offset)); @@ -3421,22 +3292,19 @@ static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tface; MLoopUV *luv; int width = 0, height = 0; float w, h; bool changed = false; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); ED_space_image_get_size(sima, &width, &height); w = (float)width; h = (float)height; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tface)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -3470,7 +3338,7 @@ static int uv_snap_selection_exec(bContext *C, wmOperator *op) case 2: { float center[2]; - if (uvedit_center(scene, ima, obedit, center, sima->around)) { + if (ED_uvedit_center(scene, ima, obedit, center, sima->around)) { float offset[2]; sub_v2_v2v2(offset, sima->cursor, center); changed = uv_snap_uvs_offset(scene, ima, obedit, offset); @@ -3486,7 +3354,7 @@ static int uv_snap_selection_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; uvedit_live_unwrap_update(sima, scene, obedit); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -3526,16 +3394,13 @@ static int uv_pin_exec(bContext *C, wmOperator *op) BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tface; MLoopUV *luv; const bool clear = RNA_boolean_get(op->ptr, "clear"); const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tface)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -3584,15 +3449,12 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tface; MLoopUV *luv; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tface)) + if (!uvedit_face_visible_test(scene, ima, efa)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -3656,13 +3518,11 @@ static int uv_hide_exec(bContext *C, wmOperator *op) BMLoop *l; BMIter iter, liter; MLoopUV *luv; - MTexPoly *tf; const bool swap = RNA_boolean_get(op->ptr, "unselected"); Image *ima = sima ? sima->image : NULL; const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); if (ts->uv_flag & UV_SYNC_SELECTION) { EDBM_mesh_hide(em, swap); @@ -3674,9 +3534,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op) BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { int hide = 0; - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - if (!uvedit_face_visible_test(scene, ima, efa, tf)) { + if (!uvedit_face_visible_test(scene, ima, efa)) { continue; } @@ -3957,73 +3815,6 @@ static void UV_OT_cursor_set(wmOperatorType *ot) "Cursor location in normalized (0.0-1.0) coordinates", -10.0f, 10.0f); } -/********************** set tile operator **********************/ - -static int set_tile_exec(bContext *C, wmOperator *op) -{ - Image *ima = CTX_data_edit_image(C); - int tile[2]; - Object *obedit = CTX_data_edit_object(C); - - RNA_int_get_array(op->ptr, "tile", tile); - - if (uvedit_set_tile(obedit, ima, tile[0] + ima->xrep * tile[1])) { - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL); - - return OPERATOR_FINISHED; - } - - return OPERATOR_CANCELLED; -} - -static int set_tile_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - SpaceImage *sima = CTX_wm_space_image(C); - Image *ima = CTX_data_edit_image(C); - ARegion *ar = CTX_wm_region(C); - float fx, fy; - int tile[2]; - - if (!ima || !(ima->tpageflag & IMA_TILES)) - return OPERATOR_CANCELLED; - - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx, &fy); - - if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) { - fx = fx * ima->xrep; - fy = fy * ima->yrep; - - tile[0] = fx; - tile[1] = fy; - - sima->curtile = tile[1] * ima->xrep + tile[0]; - RNA_int_set_array(op->ptr, "tile", tile); - } - - return set_tile_exec(C, op); -} - -static void UV_OT_tile_set(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Set Tile"; - ot->description = "Set UV image tile coordinates"; - ot->idname = "UV_OT_tile_set"; - - /* api callbacks */ - ot->exec = set_tile_exec; - ot->invoke = set_tile_invoke; - ot->poll = ED_operator_image_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_int_vector(ot->srna, "tile", 2, NULL, 0, INT_MAX, "Tile", "Tile coordinate", 0, 10); -} - - static int uv_seams_from_islands_exec(bContext *C, wmOperator *op) { UvVertMap *vmap; @@ -4041,7 +3832,7 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op) em = me->edit_btmesh; bm = em->bm; - if (!EDBM_mtexpoly_check(em)) { + if (!EDBM_uv_check(em)) { return OPERATOR_CANCELLED; } @@ -4133,7 +3924,7 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op) BM_uv_vert_map_free(vmap); - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); return OPERATOR_FINISHED; @@ -4188,7 +3979,7 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *op) if (scene->toolsettings->edge_mode_live_unwrap) ED_unwrap_lscm(scene, ob, false); - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); return OPERATOR_FINISHED; @@ -4278,7 +4069,6 @@ void ED_operatortypes_uvedit(void) WM_operatortype_append(UV_OT_hide); WM_operatortype_append(UV_OT_cursor_set); - WM_operatortype_append(UV_OT_tile_set); } void ED_keymap_uvedit(wmKeyConfig *keyconf) @@ -4358,7 +4148,6 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf) /* cursor */ WM_keymap_add_item(keymap, "UV_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "UV_OT_tile_set", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0); /* menus */ WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_snap", SKEY, KM_PRESS, KM_SHIFT, 0); diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index c2a38a90621..fa936e998fa 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -52,10 +52,11 @@ #include "BKE_context.h" #include "BKE_customdata.h" -#include "BKE_depsgraph.h" #include "BKE_mesh_mapping.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" + #include "UI_interface.h" #include "ED_mesh.h" @@ -63,6 +64,8 @@ #include "ED_screen.h" #include "ED_space_api.h" +#include "GPU_batch.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -1538,63 +1541,126 @@ static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *no normalize_v2(normal); } +/** + */ +static void stitch_draw_vbo(Gwn_VertBuf *vbo, Gwn_PrimType prim_type, const float col[4]) +{ + Gwn_Batch *batch = GWN_batch_create_ex(prim_type, vbo, NULL, GWN_BATCH_OWNS_VBO); + GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR); + GWN_batch_uniform_4fv(batch, "color", col); + GWN_batch_draw(batch); + GWN_batch_discard(batch); +} + +/* TODO make things pretier : store batches inside StitchPreviewer instead of the bare verts pos */ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg) { - int i, index = 0; + int j, index = 0; + unsigned int num_line = 0, num_tri, tri_idx = 0, line_idx = 0; StitchState *state = (StitchState *)arg; StitchPreviewer *stitch_preview = state->stitch_preview; + Gwn_VertBuf *vbo, *vbo_line; + float col[4]; - glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); - glEnableClientState(GL_VERTEX_ARRAY); + static Gwn_VertFormat format = { 0 }; + static unsigned int pos_id; + if (format.attrib_ct == 0) { + pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } glEnable(GL_BLEND); - UI_ThemeColor4(TH_STITCH_PREVIEW_ACTIVE); - glVertexPointer(2, GL_FLOAT, 0, stitch_preview->static_tris); - glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_static_tris * 3); - - glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_polys); - for (i = 0; i < stitch_preview->num_polys; i++) { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - UI_ThemeColor4(TH_STITCH_PREVIEW_FACE); - glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - UI_ThemeColor4(TH_STITCH_PREVIEW_EDGE); - glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]); -#if 0 - glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); - UI_ThemeColor4(TH_STITCH_PREVIEW_VERT); - glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]); -#endif - - index += stitch_preview->uvs_per_polygon[i]; + /* Static Tris */ + UI_GetThemeColor4fv(TH_STITCH_PREVIEW_ACTIVE, col); + vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, stitch_preview->num_static_tris * 3); + for (int i = 0; i < stitch_preview->num_static_tris * 3; i++) { + GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->static_tris[i * 2]); + } + stitch_draw_vbo(vbo, GWN_PRIM_TRIS, col); + + + /* Preview Polys */ + for (int i = 0; i < stitch_preview->num_polys; i++) + num_line += stitch_preview->uvs_per_polygon[i]; + + num_tri = num_line - 2 * stitch_preview->num_polys; + + /* we need to convert the polys into triangles / lines */ + vbo = GWN_vertbuf_create_with_format(&format); + vbo_line = GWN_vertbuf_create_with_format(&format); + + GWN_vertbuf_data_alloc(vbo, num_tri * 3); + GWN_vertbuf_data_alloc(vbo_line, num_line * 2); + + for (int i = 0; i < stitch_preview->num_polys; i++) { + BLI_assert(stitch_preview->uvs_per_polygon[i] >= 3); + + /* Start line */ + GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]); + GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + 2]); + + for (j = 1; j < stitch_preview->uvs_per_polygon[i] - 1; ++j) { + GWN_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index]); + GWN_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]); + GWN_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]); + + GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]); + GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]); + } + + /* Closing line */ + GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]); + /* j = uvs_per_polygon[i] - 1*/ + GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + j * 2]); + + index += stitch_preview->uvs_per_polygon[i] * 2; } + UI_GetThemeColor4fv(TH_STITCH_PREVIEW_FACE, col); + stitch_draw_vbo(vbo, GWN_PRIM_TRIS, col); + UI_GetThemeColor4fv(TH_STITCH_PREVIEW_EDGE, col); + stitch_draw_vbo(vbo_line, GWN_PRIM_LINES, col); + glDisable(GL_BLEND); - /* draw vert preview */ + + /* draw stitch vert/lines preview */ if (state->mode == STITCH_VERT) { glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) * 2.0f); - UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE); - glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable); - glDrawArrays(GL_POINTS, 0, stitch_preview->num_stitchable); + UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col); + vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, stitch_preview->num_stitchable); + for (int i = 0; i < stitch_preview->num_stitchable; i++) { + GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_stitchable[i * 2]); + } + stitch_draw_vbo(vbo, GWN_PRIM_POINTS, col); - UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE); - glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable); - glDrawArrays(GL_POINTS, 0, stitch_preview->num_unstitchable); + UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col); + vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, stitch_preview->num_unstitchable); + for (int i = 0; i < stitch_preview->num_unstitchable; i++) { + GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i * 2]); + } + stitch_draw_vbo(vbo, GWN_PRIM_POINTS, col); } else { - UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE); - glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable); - glDrawArrays(GL_LINES, 0, 2 * stitch_preview->num_stitchable); + UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col); + vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, stitch_preview->num_stitchable * 2); + for (int i = 0; i < stitch_preview->num_stitchable * 2; i++) { + GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_stitchable[i * 2]); + } + stitch_draw_vbo(vbo, GWN_PRIM_LINES, col); - UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE); - glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable); - glDrawArrays(GL_LINES, 0, 2 * stitch_preview->num_unstitchable); + UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col); + vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, stitch_preview->num_unstitchable * 2); + for (int i = 0; i < stitch_preview->num_unstitchable * 2; i++) { + GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i * 2]); + } + stitch_draw_vbo(vbo, GWN_PRIM_LINES, col); } - - glPopClientAttrib(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } static UvEdge *uv_edge_get(BMLoop *l, StitchState *state) @@ -2024,7 +2090,7 @@ static void stitch_exit(bContext *C, wmOperator *op, int finished) ED_region_draw_cb_exit(CTX_wm_region(C)->type, state->draw_handle); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); state_delete(state); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index bc38a1cd3bb..4f28d1f9eea 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -55,13 +55,15 @@ #include "BKE_subsurf.h" #include "BKE_context.h" #include "BKE_customdata.h" -#include "BKE_depsgraph.h" #include "BKE_image.h" #include "BKE_main.h" +#include "BKE_material.h" #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" + #include "PIL_time.h" #include "UI_interface.h" @@ -116,7 +118,7 @@ static bool ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit) if (ED_uvedit_test(obedit)) return 1; - if (em && em->bm->totface && !CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) + if (em && em->bm->totface && !CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) ED_mesh_uv_texture_add(obedit->data, NULL, true); if (!ED_uvedit_test(obedit)) @@ -214,8 +216,7 @@ void ED_uvedit_get_aspect(Scene *scene, Object *ob, BMesh *bm, float *aspx, floa ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL, NULL); } else { - MTexPoly *tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); - ima = tf->tpage; + ima = BKE_object_material_edit_image_get(ob, efa->mat_nr); } ED_image_get_uv_aspect(ima, NULL, aspx, aspy); @@ -570,7 +571,7 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, bool interac ms->lasttime = PIL_check_seconds_timer(); - DAG_id_tag_update(ms->obedit->data, 0); + DEG_id_tag_update(ms->obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ms->obedit->data); } } @@ -593,7 +594,7 @@ static void minimize_stretch_exit(bContext *C, wmOperator *op, bool cancel) param_stretch_end(ms->handle); param_delete(ms->handle); - DAG_id_tag_update(ms->obedit->data, 0); + DEG_id_tag_update(ms->obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ms->obedit->data); MEM_freeN(ms); @@ -741,7 +742,7 @@ static int pack_islands_exec(bContext *C, wmOperator *op) ED_uvedit_pack_islands(scene, obedit, em->bm, true, true, do_rotate); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -784,7 +785,7 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op)) param_flush(handle); param_delete(handle); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -1265,7 +1266,7 @@ static int unwrap_exec(bContext *C, wmOperator *op) /* execute unwrap */ ED_unwrap_lscm(scene, obedit, true); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -1392,7 +1393,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) uv_map_clip_correct(scene, obedit, em, op); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -1445,7 +1446,7 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op)) ED_mesh_uv_loop_reset(C, me); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -1481,7 +1482,7 @@ static void uv_sphere_project(float target[2], float source[3], float center[3], target[0] -= 1.0f; } -static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *UNUSED(tf)) +static void uv_map_mirror(BMEditMesh *em, BMFace *efa) { BMLoop *l; BMIter liter; @@ -1519,7 +1520,6 @@ static int sphere_project_exec(bContext *C, wmOperator *op) BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; float center[3], rotmat[4][4]; @@ -1545,13 +1545,12 @@ static int sphere_project_exec(bContext *C, wmOperator *op) uv_sphere_project(luv->uv, l->v->co, center, rotmat); } - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - uv_map_mirror(em, efa, tf); + uv_map_mirror(em, efa); } uv_map_clip_correct(scene, obedit, em, op); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -1600,7 +1599,6 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; float center[3], rotmat[4][4]; @@ -1626,13 +1624,12 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) uv_cylinder_project(luv->uv, l->v->co, center, rotmat); } - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - uv_map_mirror(em, efa, tf); + uv_map_mirror(em, efa); } uv_map_clip_correct(scene, obedit, em, op); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -1663,7 +1660,6 @@ void ED_uvedit_unwrap_cube_project(BMesh *bm, float cube_size, bool use_select, BMFace *efa; BMLoop *l; BMIter iter, liter; - /* MTexPoly *tf; */ /* UNUSED */ MLoopUV *luv; float loc[3]; int cox, coy; @@ -1733,7 +1729,7 @@ static int cube_project_exec(bContext *C, wmOperator *op) uv_map_clip_correct(scene, obedit, em, op); - DAG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; |