diff options
Diffstat (limited to 'source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c')
-rw-r--r-- | source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c new file mode 100644 index 00000000000..7e57b48c77c --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c @@ -0,0 +1,262 @@ +/* + * ***** 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 button2d_manipulator.c + * \ingroup wm + * + * \name Button Manipulator + * + * 2D Manipulator, also works in 3D views. + * + * \brief Single click button action for use in manipulator groups. + * + * \note Currently only basic icon & vector-shape buttons are supported. + * + */ + +#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 "GPU_batch.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_view3d.h" +#include "ED_manipulator_library.h" + +#include "UI_interface_icons.h" +#include "UI_resources.h" + +/* own includes */ +#include "../manipulator_geometry.h" +#include "../manipulator_library_intern.h" + +typedef struct ButtonManipulator2D { + wmManipulator manipulator; + bool is_init; + /* Use an icon or shape */ + int icon; + Gwn_Batch *shape_batch[2]; +} ButtonManipulator2D; + +#define CIRCLE_RESOLUTION 32 + +/* -------------------------------------------------------------------- */ + +static void button2d_geom_draw_backdrop( + const wmManipulator *mpr, const float color[4], const bool select) +{ + 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); + + /* TODO, other draw styles */ + imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION); + + immUnbindProgram(); + + UNUSED_VARS(select); +} + +static void button2d_draw_intern( + const bContext *UNUSED(C), wmManipulator *mpr, + const bool select, const bool highlight) +{ + ButtonManipulator2D *button = (ButtonManipulator2D *)mpr; + + if (button->is_init == false) { + button->is_init = true; + PropertyRNA *prop = RNA_struct_find_property(mpr->ptr, "icon"); + if (RNA_property_is_set(mpr->ptr, prop)) { + button->icon = RNA_property_enum_get(mpr->ptr, prop); + } + else { + prop = RNA_struct_find_property(mpr->ptr, "shape"); + const uint polys_len = RNA_property_string_length(mpr->ptr, prop); + /* We shouldn't need the +1, but a NULL char is set. */ + char *polys = MEM_mallocN(polys_len + 1, __func__); + RNA_property_string_get(mpr->ptr, prop, polys); + button->shape_batch[0] = GPU_batch_wire_from_poly_2d_encoded((uchar *)polys, polys_len, NULL); + button->shape_batch[1] = GPU_batch_tris_from_poly_2d_encoded((uchar *)polys, polys_len, NULL); + MEM_freeN(polys); + } + } + + 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); + + if (select == false) { + if (button->shape_batch[0] != NULL) { + glEnable(GL_LINE_SMOOTH); + glLineWidth(1.0f); + for (uint i = 0; i < ARRAY_SIZE(button->shape_batch) && button->shape_batch[i]; i++) { + /* Invert line color for wire. */ + color[0] = 1.0f - color[0]; + color[1] = 1.0f - color[1]; + color[2] = 1.0f - color[2]; + + GWN_batch_program_set_builtin(button->shape_batch[i], GPU_SHADER_2D_UNIFORM_COLOR); + GWN_batch_uniform_4f(button->shape_batch[i], "color", UNPACK4(color)); + GWN_batch_draw(button->shape_batch[i]); + } + glDisable(GL_LINE_SMOOTH); + gpuPopMatrix(); + } + else if (button->icon != ICON_NONE) { + button2d_geom_draw_backdrop(mpr, color, select); + gpuPopMatrix(); + UI_icon_draw( + mpr->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * U.ui_scale, + mpr->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * U.ui_scale, + button->icon); + } + else { + gpuPopMatrix(); + } + } + glDisable(GL_BLEND); +} + +static void manipulator_button2d_draw_select(const bContext *C, wmManipulator *mpr, int select_id) +{ + GPU_select_load_id(select_id); + button2d_draw_intern(C, mpr, true, false); +} + +static void manipulator_button2d_draw(const bContext *C, wmManipulator *mpr) +{ + const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0; + + glEnable(GL_BLEND); + button2d_draw_intern(C, mpr, false, is_highlight); + glDisable(GL_BLEND); +} + +static int manipulator_button2d_test_select( + bContext *C, wmManipulator *mpr, const wmEvent *event) +{ + float point_local[2]; + + if (0) { + /* correct, but unnecessarily slow. */ + if (manipulator_window_project_2d( + C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, true, point_local) == false) + { + return -1; + } + } + else { + copy_v2_v2(point_local, (float [2]){UNPACK2(event->mval)}); + sub_v2_v2(point_local, mpr->matrix_basis[3]); + mul_v2_fl(point_local, 1.0f / (mpr->scale_basis * U.ui_scale)); + } + /* The 'mpr->scale_final' is already applied when projecting. */ + if (len_squared_v2(point_local) < 1.0f) { + return 0; + } + + return -1; +} + +static int manipulator_button2d_cursor_get(wmManipulator *mpr) +{ + if (RNA_boolean_get(mpr->ptr, "show_drag")) { + return BC_NSEW_SCROLLCURSOR; + } + return CURSOR_STD; +} + +static void manipulator_button2d_free(wmManipulator *mpr) +{ + ButtonManipulator2D *shape = (ButtonManipulator2D *)mpr; + + for (uint i = 0; i < ARRAY_SIZE(shape->shape_batch); i++) { + GWN_BATCH_DISCARD_SAFE(shape->shape_batch[i]); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Button Manipulator API + * + * \{ */ + +static void MANIPULATOR_WT_button_2d(wmManipulatorType *wt) +{ + /* identifiers */ + wt->idname = "MANIPULATOR_WT_button_2d"; + + /* api callbacks */ + wt->draw = manipulator_button2d_draw; + wt->draw_select = manipulator_button2d_draw_select; + wt->test_select = manipulator_button2d_test_select; + wt->cursor_get = manipulator_button2d_cursor_get; + wt->free = manipulator_button2d_free; + + wt->struct_size = sizeof(ButtonManipulator2D); + + /* rna */ + PropertyRNA *prop; + prop = RNA_def_property(wt->srna, "icon", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_icon_items); + + /* Passed to 'GPU_batch_from_poly_2d_encoded' */ + RNA_def_property(wt->srna, "shape", PROP_STRING, PROP_BYTESTRING); + + /* Currently only used for cursor display. */ + RNA_def_boolean(wt->srna, "show_drag", true, "Show Drag", ""); +} + +void ED_manipulatortypes_button_2d(void) +{ + WM_manipulatortype_append(MANIPULATOR_WT_button_2d); +} + +/** \} */ // Button Manipulator API |