Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <eiseljulian@gmail.com>2015-10-22 20:25:02 +0300
committerJulian Eisel <eiseljulian@gmail.com>2015-10-22 20:25:02 +0300
commit0fd7310b5133aa57a4307c4cb19e44531d723ec1 (patch)
treee7f53b574f38102916bbb09cb403b472bc4373a9
parent83a2d3dcf5a73f907c741038d5c55cb9f7aff1f9 (diff)
parent6ec01dcbf29104a6f323b54f8afb2adfd2163ada (diff)
Merge branch 'wiggly-widgets' into UI-experimentsUI-experiments
Conflicts: source/blender/blenkernel/intern/customdata.c source/blender/blenloader/intern/versioning_270.c source/blender/editors/interface/resources.c source/blender/editors/transform/transform_manipulator.c
-rw-r--r--source/blender/blenkernel/intern/camera.c1
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c60
-rw-r--r--source/blender/blenkernel/intern/customdata.c2
-rw-r--r--source/blender/editors/object/object_edit.c5
-rw-r--r--source/blender/editors/object/object_lamp.c17
-rw-r--r--source/blender/editors/space_graph/graph_edit.c30
-rw-r--r--source/blender/editors/space_node/space_node.c10
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c42
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c175
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c16
-rw-r--r--source/blender/editors/transform/transform.h2
-rw-r--r--source/blender/editors/transform/transform_generics.c11
-rw-r--r--source/blender/editors/transform/transform_manipulator.c79
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c8
-rw-r--r--source/blender/makesdna/DNA_widget_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_wm.c2
-rw-r--r--source/blender/windowmanager/WM_api.h60
-rw-r--r--source/blender/windowmanager/WM_types.h23
-rw-r--r--source/blender/windowmanager/intern/wm.c1
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c92
-rw-r--r--source/blender/windowmanager/intern/wm_generic_widgets.c550
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c6
-rw-r--r--source/blender/windowmanager/intern/wm_widgets.c566
-rw-r--r--source/blender/windowmanager/wm.h44
-rw-r--r--source/blender/windowmanager/wm_event_system.h17
25 files changed, 1310 insertions, 511 deletions
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 46b74c58965..2d1f8ef664d 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -399,6 +399,7 @@ void BKE_camera_params_compute_matrix(CameraParams *params)
/***************************** Camera View Frame *****************************/
+/* keep logic in sync with WIDGETGROUP_camera_create */
void BKE_camera_view_frame_ex(
const Scene *scene, const Camera *camera,
const float drawsize, const bool do_clip, const float scale[3],
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 3b86c42d8c9..54ee5c373c6 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -1572,6 +1572,63 @@ static void cdDM_buffer_copy_uvedge(
}
}
+static void cdDM_buffer_copy_facemap(DerivedMesh *dm, unsigned int *varray)
+{
+ GPUDrawObject *gdo = dm->drawObject;
+ int *facemap_iter, *facemap = DM_get_poly_data_layer(dm, CD_FACEMAP);
+ int i, totpoly, offset = 0;
+ MPoly *mp_iter, *mp = dm->getPolyArray(dm);
+ const MLoopTri *ltri = dm->getLoopTriArray(dm);
+ MLoop *mloop = dm->getLoopArray(dm);
+ int *facemap_offset;
+
+ totpoly = dm->getNumPolys(dm);
+
+ gdo->totfacemaps = 0;
+
+ facemap_iter = facemap;
+
+ /* pretty crappy to iterate so many times but it's only being done on creation */
+ for (i = 0; i < totpoly; i++, facemap_iter++) {
+ gdo->totfacemaps = max_ii(*facemap_iter, gdo->totfacemaps);
+ }
+ /* account for 0 - n -1 range */
+ gdo->totfacemaps++;
+
+ gdo->facemap_start = MEM_callocN(gdo->totfacemaps * sizeof(*gdo->facemap_start), "GDO_facemap_start");
+ gdo->facemap_count = MEM_callocN(gdo->totfacemaps * sizeof(*gdo->facemap_count), "GDO_facemap_count");
+ facemap_offset = MEM_callocN(gdo->totfacemaps * sizeof(*facemap_offset), "facemap_offset");
+
+ facemap_iter = facemap;
+ mp_iter = mp;
+ for (i = 0; i < totpoly; i++, facemap_iter++, mp_iter++) {
+ gdo->facemap_count[*facemap_iter] += ME_POLY_TRI_TOT(mp_iter);
+ }
+
+ for (i = 0; i < gdo->totfacemaps; i++) {
+ gdo->facemap_start[i] = offset;
+ offset += gdo->facemap_count[i];
+ }
+
+ facemap_iter = facemap;
+ mp_iter = mp;
+ for (i = 0; i < totpoly; i++, facemap_iter++, mp_iter++) {
+ int numtri = ME_POLY_TRI_TOT(mp_iter);
+ int fmap_offset = (gdo->facemap_start[*facemap_iter] + facemap_offset[*facemap_iter]) * 3;
+ const MLoopTri *ltri_iter = ltri + poly_to_tri_count(i, mp_iter->loopstart);
+
+ facemap_offset[*facemap_iter] += numtri;
+
+ for (; numtri > 0; numtri--) {
+ varray[fmap_offset++] = gdo->vert_points[mloop[ltri_iter->tri[0]].v].point_index;
+ varray[fmap_offset++] = gdo->vert_points[mloop[ltri_iter->tri[1]].v].point_index;
+ varray[fmap_offset++] = gdo->vert_points[mloop[ltri_iter->tri[2]].v].point_index;
+ }
+ }
+
+ MEM_freeN(facemap_offset);
+}
+
static void cdDM_copy_gpu_data(
DerivedMesh *dm, int type, void *varray_p,
const int *mat_orig_to_new, const void *user_data)
@@ -1602,6 +1659,9 @@ static void cdDM_copy_gpu_data(
case GPU_BUFFER_TRIANGLES:
cdDM_buffer_copy_triangles(dm, (unsigned int *)varray_p, mat_orig_to_new);
break;
+ case GPU_BUFFER_FACEMAP:
+ cdDM_buffer_copy_facemap(dm, (unsigned int *)varray_p);
+ break;
default:
break;
}
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index c9b059e259e..1525087e9af 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -1378,7 +1378,7 @@ const CustomDataMask CD_MASK_BMESH =
CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_MDISPS |
CD_MASK_CREASE | CD_MASK_BWEIGHT | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
- CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP;
+ CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP;
/**
* cover values copied by #BKE_mesh_loops_to_tessdata
*/
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 05a55a8996b..6913710b9f9 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -2101,8 +2101,9 @@ static int object_widget_add_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = ED_object_active_context((bContext *)C);
wmWidgetGroupType *wgrouptype = WM_widgetgrouptype_new(WIDGETGROUP_object_manipulator_poll,
WIDGETGROUP_object_manipulator_create,
- CTX_data_main(C), "View3D", SPACE_VIEW3D,
- RGN_TYPE_WINDOW, true);
+ WM_widgetgroup_keymap_common,
+ CTX_data_main(C), "View3D", "Object Widgets",
+ SPACE_VIEW3D, RGN_TYPE_WINDOW, true);
/* assign the objects id name to the widget */
strcpy(wgrouptype->idname, ob->id.name);
diff --git a/source/blender/editors/object/object_lamp.c b/source/blender/editors/object/object_lamp.c
index 922762695be..cb0e5784cc5 100644
--- a/source/blender/editors/object/object_lamp.c
+++ b/source/blender/editors/object/object_lamp.c
@@ -216,8 +216,6 @@ int WIDGETGROUP_lamp_poll(const struct bContext *C, struct wmWidgetGroupType *UN
void WIDGETGROUP_lamp_create(const struct bContext *C, struct wmWidgetGroup *wgroup)
{
- float color_lamp[4] = {0.5f, 0.5f, 1.0f, 1.0f};
- float color_hi_lamp[4] = {0.8f, 0.8f, 0.45f, 1.0f};
Object *ob = CTX_data_active_object(C);
Lamp *la = ob->data;
wmWidget *widget;
@@ -225,13 +223,18 @@ void WIDGETGROUP_lamp_create(const struct bContext *C, struct wmWidgetGroup *wgr
float dir[3];
const char *propname = "spot_size";
+ const float color[4] = {0.5f, 0.5f, 1.0f, 1.0f};
+ const float color_hi[4] = {0.8f, 0.8f, 0.45f, 1.0f};
+
+
+ negate_v3_v3(dir, ob->obmat[2]);
+
widget = WIDGET_arrow_new(wgroup, propname, WIDGET_ARROW_STYLE_INVERTED);
- WM_widget_set_colors(widget, color_lamp, color_hi_lamp);
-
RNA_pointer_create(&la->id, &RNA_Lamp, la, &ptr);
- WM_widget_set_origin(widget, ob->obmat[3]);
- WM_widget_property(widget, ARROW_SLOT_OFFSET_WORLD_SPACE, &ptr, propname);
- negate_v3_v3(dir, ob->obmat[2]);
+ WIDGET_arrow_set_range_fac(widget, 4.0f);
WIDGET_arrow_set_direction(widget, dir);
+ WM_widget_set_origin(widget, ob->obmat[3]);
+ WM_widget_set_colors(widget, color, color_hi);
+ WM_widget_set_property(widget, ARROW_SLOT_OFFSET_WORLD_SPACE, &ptr, propname);
}
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index faf32161323..ca962d2147a 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -2507,7 +2507,8 @@ static int graph_widget_backdrop_transform_poll(bContext *C)
SpaceIpo *sipo = CTX_wm_space_graph(C);
ARegion *ar = CTX_wm_region(C);
- return ((ar->type->regionid == RGN_TYPE_WINDOW) &&
+ return ((sipo != NULL) &&
+ (ar->type->regionid == RGN_TYPE_WINDOW) &&
(sipo->flag & SIPO_DRAW_BACKDROP) &&
(sipo->backdrop_camera));
}
@@ -2525,8 +2526,8 @@ static void widgetgroup_backdrop_create(const struct bContext *C, struct wmWidge
wgroup, "backdrop_cage",
WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM | WIDGET_RECT_TRANSFORM_STYLE_TRANSLATE,
width, height);
- WM_widget_property(cage, RECT_TRANSFORM_SLOT_OFFSET, op->ptr, "offset");
- WM_widget_property(cage, RECT_TRANSFORM_SLOT_SCALE, op->ptr, "scale");
+ WM_widget_set_property(cage, RECT_TRANSFORM_SLOT_OFFSET, op->ptr, "offset");
+ WM_widget_set_property(cage, RECT_TRANSFORM_SLOT_SCALE, op->ptr, "scale");
origin[0] = BLI_rcti_size_x(&ar->winrct) / 2.0f;
origin[1] = BLI_rcti_size_y(&ar->winrct) / 2.0f;
@@ -2539,7 +2540,10 @@ static int graph_widget_backdrop_transform_invoke(bContext *C, wmOperator *op, c
ScrArea *sa = CTX_wm_area(C);
SpaceIpo *sipo = CTX_wm_space_graph(C);
/* no poll, lives always for the duration of the operator */
- wmWidgetGroupType *cagetype = WM_widgetgrouptype_new(NULL, widgetgroup_backdrop_create, CTX_data_main(C), "Graph_Canvas", SPACE_IPO, RGN_TYPE_WINDOW, false);
+ wmWidgetGroupType *cagetype = WM_widgetgrouptype_new(NULL, widgetgroup_backdrop_create,
+ WM_widgetgroup_keymap_common, CTX_data_main(C),
+ "Graph_Canvas", "Backdrop Transform Widgets",
+ SPACE_IPO, RGN_TYPE_WINDOW, false);
struct wmEventHandler *handler = WM_event_add_modal_handler(C, op);
BackDropTransformData *data = MEM_mallocN(sizeof(BackDropTransformData), "overdrop transform data");
WM_modal_handler_attach_widgetgroup(C, handler, cagetype, op);
@@ -2583,7 +2587,9 @@ static int graph_widget_backdrop_transform_modal(bContext *C, wmOperator *op, co
}
switch (event->type) {
- case EVT_WIDGET_UPDATE: {
+ case EVT_WIDGET_UPDATE:
+ case EVT_WIDGET_RELEASED:
+ {
SpaceIpo *sipo = CTX_wm_space_graph(C);
RNA_float_get_array(op->ptr, "offset", sipo->backdrop_offset);
sipo->backdrop_zoom = RNA_float_get(op->ptr, "scale");
@@ -2613,12 +2619,18 @@ static int graph_widget_backdrop_transform_modal(bContext *C, wmOperator *op, co
case ESCKEY:
case RIGHTMOUSE:
{
+ ARegion *ar = CTX_wm_region(C);
+ wmWidgetMap *wmap = ar->widgetmaps.first;
SpaceIpo *sipo = CTX_wm_space_graph(C);
- copy_v2_v2(sipo->backdrop_offset, data->init_offset);
- sipo->backdrop_zoom = data->init_zoom;
- graph_widget_backdrop_transform_finish(C, data);
- return OPERATOR_CANCELLED;
+ /* only end modal if we're not dragging a widget */
+ if (!wmap->active_widget && event->val == KM_PRESS) {
+ copy_v2_v2(sipo->backdrop_offset, data->init_offset);
+ sipo->backdrop_zoom = data->init_zoom;
+
+ graph_widget_backdrop_transform_finish(C, data);
+ return OPERATOR_CANCELLED;
+ }
}
}
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 2c26b784776..08231da5993 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -877,8 +877,8 @@ static void WIDGETGROUP_node_transform_create(const struct bContext *C, struct w
RNA_pointer_create(snode->id, &RNA_SpaceNodeEditor, snode, &nodeptr);
WM_widget_set_origin(cage, origin);
- WM_widget_property(cage, RECT_TRANSFORM_SLOT_OFFSET, &nodeptr, "backdrop_offset");
- WM_widget_property(cage, RECT_TRANSFORM_SLOT_SCALE, &nodeptr, "backdrop_zoom");
+ WM_widget_set_property(cage, RECT_TRANSFORM_SLOT_OFFSET, &nodeptr, "backdrop_offset");
+ WM_widget_set_property(cage, RECT_TRANSFORM_SLOT_SCALE, &nodeptr, "backdrop_zoom");
}
BKE_image_release_ibuf(ima, ibuf, lock);
}
@@ -888,7 +888,11 @@ static void node_widgets(void)
/* create the widgetmap for the area here */
WM_widgetmaptype_find("Node_Canvas", SPACE_NODE, RGN_TYPE_WINDOW, false, true);
- WM_widgetgrouptype_new(WIDGETGROUP_node_transform_poll, WIDGETGROUP_node_transform_create, NULL, "Node_Canvas", SPACE_NODE, RGN_TYPE_WINDOW, false);
+ WM_widgetgrouptype_new(WIDGETGROUP_node_transform_poll,
+ WIDGETGROUP_node_transform_create,
+ WM_widgetgroup_keymap_common,
+ NULL, "Node_Canvas", "Backdrop Transform Widgets",
+ SPACE_NODE, RGN_TYPE_WINDOW, false);
}
/* only called once, from space/spacetypes.c */
diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c
index d3292db7160..3208a115b18 100644
--- a/source/blender/editors/space_sequencer/sequencer_view.c
+++ b/source/blender/editors/space_sequencer/sequencer_view.c
@@ -279,8 +279,8 @@ static void widgetgroup_overdrop_create(const struct bContext *C, struct wmWidge
wgroup, "overdrop_cage",
WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM | WIDGET_RECT_TRANSFORM_STYLE_TRANSLATE,
sizex, sizey);
- WM_widget_property(cage, RECT_TRANSFORM_SLOT_OFFSET, op->ptr, "offset");
- WM_widget_property(cage, RECT_TRANSFORM_SLOT_SCALE, op->ptr, "scale");
+ WM_widget_set_property(cage, RECT_TRANSFORM_SLOT_OFFSET, op->ptr, "offset");
+ WM_widget_set_property(cage, RECT_TRANSFORM_SLOT_SCALE, op->ptr, "scale");
origin[0] = BLI_rcti_size_x(&ar->winrct)/2.0f;
origin[1] = BLI_rcti_size_y(&ar->winrct)/2.0f;
@@ -293,7 +293,10 @@ static int sequencer_overdrop_transform_invoke(bContext *C, wmOperator *op, cons
ScrArea *sa = CTX_wm_area(C);
SpaceSeq *sseq = CTX_wm_space_seq(C);
/* no poll, lives always for the duration of the operator */
- wmWidgetGroupType *cagetype = WM_widgetgrouptype_new(NULL, widgetgroup_overdrop_create, CTX_data_main(C), "Seq_Canvas", SPACE_SEQ, RGN_TYPE_WINDOW, false);
+ wmWidgetGroupType *cagetype = WM_widgetgrouptype_new(NULL, widgetgroup_overdrop_create,
+ WM_widgetgroup_keymap_common, CTX_data_main(C),
+ "Seq_Canvas", "Backdrop Transform Widgets",
+ SPACE_SEQ, RGN_TYPE_WINDOW, false);
struct wmEventHandler *handler = WM_event_add_modal_handler(C, op);
OverDropTransformData *data = MEM_mallocN(sizeof(OverDropTransformData), "overdrop transform data");
WM_modal_handler_attach_widgetgroup(C, handler, cagetype, op);
@@ -337,14 +340,15 @@ static int sequencer_overdrop_transform_modal(bContext *C, wmOperator *op, const
}
switch (event->type) {
- case EVT_WIDGET_UPDATE: {
+ case EVT_WIDGET_UPDATE:
+ case EVT_WIDGET_RELEASED:
+ {
SpaceSeq *sseq = CTX_wm_space_seq(C);
RNA_float_get_array(op->ptr, "offset", sseq->overdrop_offset);
sseq->overdrop_zoom = RNA_float_get(op->ptr, "scale");
break;
}
-
- case RKEY:
+ case RKEY:
{
SpaceSeq *sseq = CTX_wm_space_seq(C);
ARegion *ar = CTX_wm_region(C);
@@ -369,12 +373,18 @@ static int sequencer_overdrop_transform_modal(bContext *C, wmOperator *op, const
case ESCKEY:
case RIGHTMOUSE:
{
+ ARegion *ar = CTX_wm_region(C);
+ wmWidgetMap *wmap = ar->widgetmaps.first;
SpaceSeq *sseq = CTX_wm_space_seq(C);
- copy_v2_v2(sseq->overdrop_offset, data->init_offset);
- sseq->overdrop_zoom = data->init_zoom;
-
- sequencer_overdrop_finish(C, data);
- return OPERATOR_CANCELLED;
+
+ /* only end modal if we're not dragging a widget */
+ if (!wmap->active_widget && event->val == KM_PRESS) {
+ copy_v2_v2(sseq->overdrop_offset, data->init_offset);
+ sseq->overdrop_zoom = data->init_zoom;
+
+ sequencer_overdrop_finish(C, data);
+ return OPERATOR_CANCELLED;
+ }
}
}
@@ -437,7 +447,7 @@ static void widgetgroup_image_transform_create(const struct bContext *C, struct
wgroup, "image_cage",
WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM | WIDGET_RECT_TRANSFORM_STYLE_TRANSLATE,
viewrect[0] * scale[0], viewrect[1] * scale[1]);
- WM_widget_property(cage, RECT_TRANSFORM_SLOT_SCALE, op->ptr, "scale");
+ WM_widget_set_property(cage, RECT_TRANSFORM_SLOT_SCALE, op->ptr, "scale");
origin[0] = -(v2d->cur.xmin * scale[0]);
origin[1] = -(v2d->cur.ymin * scale[1]);
@@ -450,8 +460,10 @@ static int sequencer_image_transform_widget_invoke(bContext *C, wmOperator *op,
SpaceSeq *sseq = CTX_wm_space_seq(C);
Scene *scene = CTX_data_scene(C);
/* no poll, lives always for the duration of the operator */
- wmWidgetGroupType *cagetype = WM_widgetgrouptype_new(NULL, widgetgroup_image_transform_create, CTX_data_main(C),
- "Seq_Canvas", SPACE_SEQ, RGN_TYPE_PREVIEW, false);
+ wmWidgetGroupType *cagetype = WM_widgetgrouptype_new(NULL, widgetgroup_image_transform_create,
+ WM_widgetgroup_keymap_common, CTX_data_main(C),
+ "Seq_Canvas", "Image Transform Widgets",
+ SPACE_SEQ, RGN_TYPE_PREVIEW, false);
struct wmEventHandler *handler = WM_event_add_modal_handler(C, op);
ImageTransformData *data = MEM_mallocN(sizeof(ImageTransformData), "overdrop transform data");
ImBuf *ibuf = sequencer_ibuf_get(CTX_data_main(C), scene, sseq, CFRA, 0, NULL);
@@ -519,7 +531,7 @@ static int sequencer_image_transform_widget_modal(bContext *C, wmOperator *op, c
/* no offset needed in this case */
offset[0] = offset[1] = 0;
- WIDGET_rect_transform_set_offset(wmap->active_widget, offset);
+ WM_widget_set_offset(wmap->active_widget, offset);
break;
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 7f038a13fd0..1b46040adc1 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -36,6 +36,7 @@
#include "DNA_material_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
+#include "DNA_object_force.h"
#include "DNA_scene_types.h"
#include "DNA_camera_types.h"
#include "DNA_key_types.h"
@@ -47,6 +48,7 @@
#include "BLI_utildefines.h"
#include "BKE_action.h"
+#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_icons.h"
@@ -732,36 +734,131 @@ static int WIDGETGROUP_camera_poll(const struct bContext *C, struct wmWidgetGrou
{
Object *ob = CTX_data_active_object(C);
- if (ob && ob->type == OB_CAMERA) {
- Camera *ca = ob->data;
- return (ca->flag & CAM_SHOWLIMITS) != 0;
- }
- return false;
+ return (ob && ob->type == OB_CAMERA);
}
static void WIDGETGROUP_camera_create(const struct bContext *C, struct wmWidgetGroup *wgroup)
{
- float color_camera[4] = {1.0f, 0.3f, 0.0f, 1.0f};
- float color_hi_camera[4] = {1.0f, 0.3f, 0.0f, 1.0f};
Object *ob = CTX_data_active_object(C);
Camera *ca = ob->data;
wmWidget *widget;
PointerRNA cameraptr;
float dir[3];
- const char *propname = "dof_distance";
-
- widget = WIDGET_arrow_new(wgroup, propname, WIDGET_ARROW_STYLE_CROSS);
- WM_widget_set_draw_on_hover_only(widget, true);
- WM_widget_set_3d_scale(widget, false);
- WM_widget_set_colors(widget, color_camera, color_hi_camera);
+ const bool focallen_widget = true; /* TODO make optional */
RNA_pointer_create(&ca->id, &RNA_Camera, ca, &cameraptr);
- WM_widget_set_origin(widget, ob->obmat[3]);
- WM_widget_property(widget, ARROW_SLOT_OFFSET_WORLD_SPACE, &cameraptr, propname);
negate_v3_v3(dir, ob->obmat[2]);
- WIDGET_arrow_set_direction(widget, dir);
- WIDGET_arrow_set_up_vector(widget, ob->obmat[1]);
- WM_widget_set_scale(widget, ca->drawsize);
+
+ /* dof distance */
+ if (ca->flag & CAM_SHOWLIMITS) {
+ const float color[4] = {1.0f, 0.3f, 0.0f, 1.0f};
+ const float color_hi[4] = {1.0f, 0.3f, 0.0f, 1.0f};
+ const char *propname = "dof_distance";
+
+ widget = WIDGET_arrow_new(wgroup, propname, WIDGET_ARROW_STYLE_CROSS);
+ WIDGET_arrow_set_direction(widget, dir);
+ WIDGET_arrow_set_up_vector(widget, ob->obmat[1]);
+ WM_widget_set_flag(widget, WM_WIDGET_DRAW_HOVER, true);
+ WM_widget_set_flag(widget, WM_WIDGET_SCALE_3D, false);
+ WM_widget_set_colors(widget, color, color_hi);
+ WM_widget_set_origin(widget, ob->obmat[3]);
+ WM_widget_set_property(widget, ARROW_SLOT_OFFSET_WORLD_SPACE, &cameraptr, propname);
+ WM_widget_set_scale(widget, ca->drawsize);
+ }
+
+ /* focal length
+ * - logic/calculations are similar to BKE_camera_view_frame_ex, better keep in sync */
+ if (focallen_widget) {
+ const Scene *scene = CTX_data_scene(C);
+ const bool is_ortho = (ca->type == CAM_ORTHO);
+ const float scale_fac = ca->drawsize;
+ const float half_sensor = 0.5f * ((ca->sensor_fit == CAMERA_SENSOR_FIT_VERT) ? ca->sensor_y : ca->sensor_x);
+ 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 drawsize = is_ortho ? (0.5f * ca->ortho_scale) :
+ (scale_fac / ((scale[0] + scale[1] + scale[2]) / 3.0f));
+ 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);
+ const char *propname = is_ortho ? "ortho_scale" : "lens";
+ const bool fit_hor = (sensor_fit == CAMERA_SENSOR_FIT_HOR);
+
+ const float color[4] = {1.0f, 1.0, 0.27f, 0.5f};
+ const float color_hi[4] = {1.0f, 1.0, 0.27f, 1.0f};
+
+ PropertyRNA *prop;
+ float offset[3], asp[2];
+ float min, max, range;
+ float step, precision; /* dummys, unused */
+
+
+ /* get aspect */
+ asp[0] = fit_hor ? 1.0 : aspx / aspy;
+ asp[1] = fit_hor ? aspy / aspx : 1.0f;
+
+ /* 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 property range */
+ prop = RNA_struct_find_property(&cameraptr, propname);
+ RNA_property_float_ui_range(&cameraptr, prop, &min, &max, &step, &precision);
+ range = max - min;
+
+
+ /* *** actual widget stuff *** */
+
+ widget = WIDGET_arrow_new(wgroup, propname, (WIDGET_ARROW_STYLE_CONE | WIDGET_ARROW_STYLE_CONSTRAINED));
+
+ WIDGET_arrow_set_range_fac(widget, is_ortho ? (scale_fac * range) : (drawsize * range / half_sensor));
+ WIDGET_arrow_set_direction(widget, dir);
+ WIDGET_arrow_set_up_vector(widget, ob->obmat[1]);
+ WIDGET_arrow_cone_set_aspect(widget, asp);
+ WM_widget_set_property(widget, ARROW_SLOT_OFFSET_WORLD_SPACE, &cameraptr, propname);
+ WM_widget_set_origin(widget, ob->obmat[3]);
+ WM_widget_set_offset(widget, offset);
+ WM_widget_set_scale(widget, drawsize);
+ WM_widget_set_flag(widget, WM_WIDGET_SCALE_3D, false);
+ WM_widget_set_colors(widget, color, color_hi);
+
+ }
+}
+
+static int WIDGETGROUP_forcefield_poll(const struct bContext *C, struct wmWidgetGroupType *UNUSED(wgrouptype))
+{
+ Object *ob = CTX_data_active_object(C);
+
+ return ob && ob->pd && ob->pd->forcefield;
+}
+
+static void WIDGETGROUP_forcefield_create(const struct bContext *C, struct wmWidgetGroup *wgroup)
+{
+ Object *ob = CTX_data_active_object(C);
+ PartDeflect *pd = ob->pd;
+ PointerRNA ptr;
+ wmWidget *widget;
+
+ const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f;
+ const float ofs[3] = {0.0f, -size, 0.0f};
+
+ const float col[4] = {0.8f, 0.8f, 0.45f, 0.5f};
+ const float col_hi[4] = {0.8f, 0.8f, 0.45f, 1.0f};
+
+
+ /* only wind effector for now */
+ if (pd->forcefield == PFIELD_WIND) {
+ widget = WIDGET_arrow_new(wgroup, "field_strength", WIDGET_ARROW_STYLE_CONSTRAINED);
+
+ RNA_pointer_create(&ob->id, &RNA_FieldSettings, pd, &ptr);
+ WIDGET_arrow_set_direction(widget, ob->obmat[2]);
+ WIDGET_arrow_set_ui_range(widget, -200.0f, 200.0f);
+ WIDGET_arrow_set_range_fac(widget, 6.0f);
+ WM_widget_set_colors(widget, col, col_hi);
+ WM_widget_set_origin(widget, ob->obmat[3]);
+ WM_widget_set_offset(widget, ofs);
+ WM_widget_set_flag(widget, WM_WIDGET_SCALE_3D, false);
+ WM_widget_set_property(widget, ARROW_SLOT_OFFSET_WORLD_SPACE, &ptr, "strength");
+ }
}
#if 0
@@ -799,7 +896,7 @@ static void WIDGETGROUP_shapekey_draw(const struct bContext *C, struct wmWidgetG
WIDGET_arrow_set_color(widget, color_shape);
RNA_pointer_create(&key->id, &RNA_ShapeKey, kb, &shapeptr);
WM_widget_set_origin(widget, ob->obmat[3]);
- WM_widget_property(widget, ARROW_SLOT_OFFSET_WORLD_SPACE, &shapeptr, "value");
+ WM_widget_set_property(widget, ARROW_SLOT_OFFSET_WORLD_SPACE, &shapeptr, "value");
negate_v3_v3(dir, ob->obmat[2]);
WIDGET_arrow_set_direction(widget, dir);
}
@@ -829,7 +926,6 @@ static int WIDGETGROUP_armature_facemap_poll(const struct bContext *C, struct wm
static void WIDGETGROUP_armature_facemap_create(const struct bContext *C, struct wmWidgetGroup *wgroup)
{
- float color_shape[4] = {1.0f, 0.3f, 0.0f, 1.0f};
Object *ob = CTX_data_active_object(C);
wmWidget *widget;
Object *armature;
@@ -839,7 +935,10 @@ static void WIDGETGROUP_armature_facemap_create(const struct bContext *C, struct
VirtualModifierData virtualModifierData;
int index = 0;
bFaceMap *fmap = ob->fmaps.first;
-
+
+ const float color_shape[4] = {1.0f, 0.3f, 0.0f, 1.0f};
+
+
md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
/* exception for shape keys because we can edit those */
@@ -857,15 +956,17 @@ static void WIDGETGROUP_armature_facemap_create(const struct bContext *C, struct
for (; fmap; fmap = fmap->next, index++) {
if (BKE_pose_channel_find_name(armature->pose, fmap->name)) {
PointerRNA *opptr;
+
widget = WIDGET_facemap_new(wgroup, fmap->name, 0, ob, index);
+
RNA_pointer_create(&ob->id, &RNA_FaceMap, fmap, &famapptr);
- WM_widget_property(widget, FACEMAP_SLOT_FACEMAP, &famapptr, "name");
- opptr = WM_widget_operator(widget, "TRANSFORM_OT_translate");
+ WM_widget_set_property(widget, FACEMAP_SLOT_FACEMAP, &famapptr, "name");
+ WM_widget_set_colors(widget, color_shape, color_shape);
+ WM_widget_set_flag(widget, WM_WIDGET_DRAW_HOVER, true);
+ opptr = WM_widget_set_operator(widget, "TRANSFORM_OT_translate");
if ((prop = RNA_struct_find_property(opptr, "release_confirm"))) {
RNA_property_boolean_set(opptr, prop, true);
}
- WM_widget_set_colors(widget, color_shape, color_shape);
- WM_widget_set_draw_on_hover_only(widget, true);
}
}
}
@@ -875,10 +976,26 @@ static void view3d_widgets(void)
{
WM_widgetmaptype_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW, true, true);
- WM_widgetgrouptype_new(WIDGETGROUP_manipulator_poll, WIDGETGROUP_manipulator_create, NULL, "View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW, true);
- WM_widgetgrouptype_new(WIDGETGROUP_lamp_poll, WIDGETGROUP_lamp_create, NULL, "View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW, true);
- WM_widgetgrouptype_new(WIDGETGROUP_camera_poll, WIDGETGROUP_camera_create, NULL, "View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW, true);
- WM_widgetgrouptype_new(WIDGETGROUP_armature_facemap_poll, WIDGETGROUP_armature_facemap_create, NULL, "View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW, true);
+ WM_widgetgrouptype_new(WIDGETGROUP_armature_facemap_poll,
+ WIDGETGROUP_armature_facemap_create,
+ WM_widgetgroup_keymap_common,
+ NULL, "View3D", "Face Map Widgets", SPACE_VIEW3D, RGN_TYPE_WINDOW, true);
+ WM_widgetgrouptype_new(WIDGETGROUP_lamp_poll,
+ WIDGETGROUP_lamp_create,
+ WM_widgetgroup_keymap_common,
+ NULL, "View3D", "Lamp Widgets", SPACE_VIEW3D, RGN_TYPE_WINDOW, true);
+ WM_widgetgrouptype_new(WIDGETGROUP_forcefield_poll,
+ WIDGETGROUP_forcefield_create,
+ WM_widgetgroup_keymap_common,
+ NULL, "View3D", "Force Field Widgets", SPACE_VIEW3D, RGN_TYPE_WINDOW, true);
+ WM_widgetgrouptype_new(WIDGETGROUP_camera_poll,
+ WIDGETGROUP_camera_create,
+ WM_widgetgroup_keymap_common,
+ NULL, "View3D", "Camera Widgets", SPACE_VIEW3D, RGN_TYPE_WINDOW, true);
+ WM_widgetgrouptype_new(WIDGETGROUP_manipulator_poll,
+ WIDGETGROUP_manipulator_create,
+ WM_widgetgroup_keymap_common,
+ NULL, "View3D", "Manipulator Widgets", SPACE_VIEW3D, RGN_TYPE_WINDOW, true);
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 25fa3085596..125246fd05c 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -3774,6 +3774,11 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
/* main drawing call */
view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL);
+ /* widgets need to be updated *after* view matrix was set up
+ * XXX since we do 2 draw calls (with and without depth culling),
+ * it might be better to have 2 update calls, too */
+ WM_widgets_update(C, ar->widgetmaps.first);
+ /* draw depth culled widgets */
WM_widgets_draw(C, ar->widgetmaps.first, true);
/* post process */
@@ -3918,18 +3923,18 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
const char *grid_unit = NULL;
rcti border_rect;
bool render_border, clip_border;
+ bool update_widgets = true;
/* 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));
- WM_widgets_update(C, ar->widgetmaps.first);
-
/* draw viewport using opengl */
if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(scene) || clip_border) {
view3d_main_area_draw_objects(C, scene, v3d, ar, &grid_unit);
-
+ update_widgets = false; /* widgets were updated in view3d_main_area_draw_objects */
+
#ifdef DEBUG_DRAW
bl_debug_draw();
#endif
@@ -3945,7 +3950,12 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
glClear(GL_DEPTH_BUFFER_BIT);
+
+ if (update_widgets) {
+ WM_widgets_update(C, ar->widgetmaps.first);
+ }
WM_widgets_draw(C, ar->widgetmaps.first, false);
+
ED_region_pixelspace(ar);
view3d_main_area_draw_info(C, scene, ar, v3d, grid_unit, render_border);
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index a735801ff47..e77ebfc4532 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -484,8 +484,6 @@ typedef struct TransInfo {
/* alternative transformation. used to add offset to tracking markers */
#define T_ALT_TRANSFORM (1 << 24)
-#define T_USE_WIDGET (1 << 24)
-
/* TransInfo->modifiers */
#define MOD_CONSTRAINT_SELECT 0x01
#define MOD_PRECISION 0x02
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index f3009ba0068..f5fc34ff5fd 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1192,15 +1192,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->view = v3d;
t->animtimer = (animscreen) ? animscreen->animtimer : NULL;
- if (op && ((prop = RNA_struct_find_property(op->ptr, "use_widget_input")) &&
- RNA_property_is_set(op->ptr, prop)))
- {
- if (RNA_property_boolean_get(op->ptr, prop))
- t->flag |= T_USE_WIDGET;
- }
-
/* turn manipulator off during transform */
- if ((t->flag & T_MODAL) && !(t->flag & T_USE_WIDGET)) {
+ if (t->flag & T_MODAL) {
t->twtype = v3d->twtype;
v3d->twtype = 0;
}
@@ -1480,7 +1473,7 @@ void postTrans(bContext *C, TransInfo *t)
else if (t->spacetype == SPACE_VIEW3D) {
View3D *v3d = t->sa->spacedata.first;
/* restore manipulator */
- if ((t->flag & T_MODAL) && !(t->flag & T_USE_WIDGET)) {
+ if (t->flag & T_MODAL) {
v3d->twtype = t->twtype;
}
}
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 522cf15eb10..436e44b4f9c 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -462,7 +462,7 @@ static void axis_angle_to_gimbal_axis(float gmat[3][3], const float axis[3], con
mul_qt_v3(quat, gmat[0]);
/* Y-axis */
- axis_angle_to_quat(quat, axis, M_PI / 2.0);
+ axis_angle_to_quat(quat, axis, M_PI_2);
copy_v3_v3(gmat[1], gmat[0]);
mul_qt_v3(quat, gmat[1]);
@@ -847,8 +847,6 @@ static int calc_manipulator_stats(const bContext *C)
}
}
else {
- float loc[3];
-
/* we need the one selected object, if its not active */
ob = OBACT;
if (ob && !(ob->flag & SELECT))
@@ -859,9 +857,7 @@ static int calc_manipulator_stats(const bContext *C)
if (ob == NULL)
ob = base->object;
- /* updated object matrix after transform */
- add_v3_v3v3(loc, base->object->loc, base->object->dloc);
- calc_tw_center(scene, loc);
+ calc_tw_center(scene, base->object->loc);
protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag);
totsel++;
}
@@ -889,8 +885,7 @@ static int calc_manipulator_stats(const bContext *C)
/* fall-through */
case V3D_MANIP_NORMAL:
if (obedit || ob->mode & OB_MODE_POSE) {
- float mat[3][3];
- ED_getTransformOrientationMatrix(C, mat, (v3d->around == V3D_ACTIVE));
+ ED_getTransformOrientationMatrix(C, mat, v3d->around);
copy_m4_m3(rv3d->twmat, mat);
break;
}
@@ -902,8 +897,7 @@ static int calc_manipulator_stats(const bContext *C)
* 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 == V3D_ACTIVE));
+ ED_getTransformOrientationMatrix(C, mat, v3d->around);
copy_m4_m3(rv3d->twmat, mat);
break;
}
@@ -916,13 +910,10 @@ static int calc_manipulator_stats(const bContext *C)
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;
- }
}
}
@@ -961,11 +952,7 @@ static void manipulator_prepare_mat(Scene *scene, View3D *v3d, RegionView3D *rv3
{
Object *ob = OBACT;
if ((v3d->around == V3D_ACTIVE) && !scene->obedit && !(ob->mode & OB_MODE_POSE)) {
- float loc[3];
-
- /* updated object matrix after transform */
- add_v3_v3v3(loc, ob->loc, ob->dloc);
- copy_v3_v3(rv3d->twmat[3], loc);
+ copy_v3_v3(rv3d->twmat[3], ob->obmat[3]);
}
else {
mid_v3_v3v3(rv3d->twmat[3], scene->twmin, scene->twmax);
@@ -985,32 +972,33 @@ static void manipulator_prepare_mat(Scene *scene, View3D *v3d, RegionView3D *rv3
}
/**
- * Sets up \a r_vec for custom arrow widget line drawing. Needed to
- * adjust line drawing for combined manipulator axis types.
+ * 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_line_vec(const View3D *v3d, float r_vec[2][3], const short axis_type)
+static void manipulator_line_range(const View3D *v3d, const short axis_type, float *r_start, float *r_len)
{
const float ofs = 0.2f;
- float start[3] = {0.0f, 0.0f, 0.2f};
- float end[3] = {0.0f, 0.0f, 1.0f};
+
+ *r_start = 0.2f;
+ *r_len = 1.0f;
switch (axis_type) {
case MAN_AXES_TRANSLATE:
if (v3d->twtype & V3D_MANIP_SCALE) {
- start[2] = end[2] - ofs + 0.025f;
+ *r_start = *r_len - ofs + 0.075f;
}
if (v3d->twtype & V3D_MANIP_ROTATE) {
- end[2] += ofs;
+ *r_len += ofs;
}
break;
case MAN_AXES_SCALE:
if (v3d->twtype & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE)) {
- end[2] -= ofs + 0.025f;
+ *r_len -= ofs + 0.025f;
}
break;
}
- copy_v3_v3(r_vec[0], start);
- copy_v3_v3(r_vec[1], end);
+
+ *r_len -= *r_start;
}
@@ -1087,7 +1075,7 @@ void WIDGETGROUP_manipulator_create(const struct bContext *C, struct wmWidgetGro
const bool trans_visble = (any_visible && (v3d->twtype & V3D_MANIP_TRANSLATE));
const bool rot_visble = (any_visible && (v3d->twtype & V3D_MANIP_ROTATE));
const bool scale_visible = (any_visible && (v3d->twtype & V3D_MANIP_SCALE));
- const ManipulatorGroup *man = manipulatorgroup_init(wgroup, trans_visble, rot_visble, scale_visible);
+ ManipulatorGroup *man = manipulatorgroup_init(wgroup, trans_visble, rot_visble, scale_visible);
if (!man)
return;
@@ -1101,7 +1089,7 @@ void WIDGETGROUP_manipulator_create(const struct bContext *C, struct wmWidgetGro
if (fabsf(mat4_to_scale(rv3d->twmat)) < 1e-7f) {
MAN_ITER_AXES_BEGIN
{
- WM_widget_flag_set(axis, WM_WIDGET_HIDDEN, true);
+ WM_widget_set_flag(axis, WM_WIDGET_HIDDEN, true);
}
MAN_ITER_AXES_END;
@@ -1118,11 +1106,10 @@ void WIDGETGROUP_manipulator_create(const struct bContext *C, struct wmWidgetGro
int constraint_axis[3] = {1, 0, 0};
PointerRNA *ptr;
- float line_vec[2][3];
float col[4], col_hi[4];
if (manipulator_is_axis_visible(v3d, rv3d, axis_idx) == false) {
- WM_widget_flag_set(axis, WM_WIDGET_HIDDEN, true);
+ WM_widget_set_flag(axis, WM_WIDGET_HIDDEN, true);
continue;
}
@@ -1141,17 +1128,23 @@ void WIDGETGROUP_manipulator_create(const struct bContext *C, struct wmWidgetGro
case MAN_AXIS_SCALE_X:
case MAN_AXIS_SCALE_Y:
case MAN_AXIS_SCALE_Z:
- manipulator_line_vec(v3d, line_vec, axis_type);
+ {
+ float start_co[3] = {0.0f, 0.0f, 0.0f};
+ float len;
+
+ manipulator_line_range(v3d, axis_type, &start_co[2], &len);
WIDGET_arrow_set_direction(axis, rv3d->twmat[aidx_norm]);
- WIDGET_arrow_set_line_vec(axis, (const float (*)[3])line_vec, ARRAY_SIZE(line_vec));
+ WIDGET_arrow_set_line_len(axis, len);
+ WM_widget_set_offset(axis, start_co);
WM_widget_set_line_width(axis, MAN_AXIS_LINE_WIDTH);
break;
+ }
case MAN_AXIS_ROT_X:
case MAN_AXIS_ROT_Y:
case MAN_AXIS_ROT_Z:
+ WIDGET_dial_set_up_vector(axis, rv3d->twmat[aidx_norm]);
WM_widget_set_line_width(axis, MAN_AXIS_LINE_WIDTH);
- WIDGET_dial_set_direction(axis, rv3d->twmat[aidx_norm]);
break;
case MAN_AXIS_TRANS_XY:
case MAN_AXIS_TRANS_YZ:
@@ -1167,38 +1160,40 @@ void WIDGETGROUP_manipulator_create(const struct bContext *C, struct wmWidgetGro
ofs[1] = ofs_ax;
ofs[2] = 0.0f;
- WM_widget_set_scale(axis, 0.07f);
- WM_widget_set_origin(axis, rv3d->twmat[3]);
- WIDGET_plane_set_offset(axis, ofs);
WIDGET_plane_set_direction(axis, rv3d->twmat[aidx_norm - 1 < 0 ? 2 : aidx_norm - 1]);
WIDGET_plane_set_up_vector(axis, rv3d->twmat[aidx_norm + 1 > 2 ? 0 : aidx_norm + 1]);
+ WM_widget_set_scale(axis, 0.07f);
+ WM_widget_set_origin(axis, rv3d->twmat[3]);
+ WM_widget_set_offset(axis, ofs);
break;
}
case MAN_AXIS_TRANS_C:
case MAN_AXIS_ROT_C:
case MAN_AXIS_SCALE_C:
+ WIDGET_dial_set_up_vector(axis, rv3d->viewinv[2]);
if (axis_idx != MAN_AXIS_ROT_C) {
WM_widget_set_scale(axis, 0.2f);
}
- WIDGET_dial_set_direction(axis, rv3d->viewinv[2]);
break;
}
switch (axis_type) {
case MAN_AXES_TRANSLATE:
- ptr = WM_widget_operator(axis, "TRANSFORM_OT_translate");
+ ptr = WM_widget_set_operator(axis, "TRANSFORM_OT_translate");
break;
case MAN_AXES_ROTATE:
- ptr = WM_widget_operator(axis, "TRANSFORM_OT_rotate");
+ ptr = WM_widget_set_operator(axis, "TRANSFORM_OT_rotate");
break;
case MAN_AXES_SCALE:
- ptr = WM_widget_operator(axis, "TRANSFORM_OT_resize");
+ ptr = WM_widget_set_operator(axis, "TRANSFORM_OT_resize");
break;
}
RNA_boolean_set_array(ptr, "constraint_axis", constraint_axis);
RNA_boolean_set(ptr, "release_confirm", 1);
}
MAN_ITER_AXES_END;
+
+ MEM_freeN(man);
}
void WIDGETGROUP_object_manipulator_create(const struct bContext *C, struct wmWidgetGroup *wgroup)
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 2c434fb405e..d354cc30f3c 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -95,6 +95,8 @@ const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
{GL_ELEMENT_ARRAY_BUFFER_ARB, 4},
/* triangles, 1 point since we are allocating from tottriangle points, which account for all points */
{GL_ELEMENT_ARRAY_BUFFER_ARB, 1},
+ /* facemap */
+ {GL_ELEMENT_ARRAY_BUFFER_ARB, 3},
};
#define MAX_GPU_ATTRIB_DATA 32
@@ -489,6 +491,10 @@ void GPU_drawobject_free(DerivedMesh *dm)
#ifdef USE_GPU_POINT_LINK
MEM_freeN(gdo->vert_points_mem);
#endif
+ if (gdo->facemap_start)
+ MEM_freeN(gdo->facemap_start);
+ if (gdo->facemap_count)
+ MEM_freeN(gdo->facemap_count);
GPU_buffer_free(gdo->points);
GPU_buffer_free(gdo->normals);
GPU_buffer_free(gdo->uv);
@@ -657,7 +663,7 @@ static size_t gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
case GPU_BUFFER_TRIANGLES:
return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_triangle_point;
case GPU_BUFFER_FACEMAP:
- return sizeof(int) * 3 * dm->drawObject->tot_triangle_point;
+ return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_triangle_point;
default:
return -1;
}
diff --git a/source/blender/makesdna/DNA_widget_types.h b/source/blender/makesdna/DNA_widget_types.h
index 6d9c5c02c01..5fa2cd813f8 100644
--- a/source/blender/makesdna/DNA_widget_types.h
+++ b/source/blender/makesdna/DNA_widget_types.h
@@ -55,8 +55,6 @@ struct wmWidgetGroup {
int flag;
int pad;
-
- void *customdata;
};
#endif
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 37550b1eaed..a77e41c15af 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -1568,7 +1568,7 @@ static StructRNA *rna_WidgetGroup_register(Main *bmain, ReportList *reports, voi
dummywgt.poll = (have_function[0]) ? widgetgroup_poll : NULL;
dummywgt.create = (have_function[1]) ? widgetgroup_draw : NULL;
- wgrouptype = WM_widgetgrouptype_new(dummywgt.poll, dummywgt.create, bmain, dummywgt.mapidname, dummywgt.spaceid, dummywgt.regionid, dummywgt.is_3d);
+ wgrouptype = WM_widgetgrouptype_new(dummywgt.poll, dummywgt.create, NULL, bmain, dummywgt.mapidname, NULL, dummywgt.spaceid, dummywgt.regionid, dummywgt.is_3d);
memcpy(wgrouptype, &dummywgt, sizeof(dummywgt));
/* update while blender is running */
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index f0dbc4d4108..15a3a35b00b 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -506,31 +506,48 @@ struct wmWidget *WM_widget_new(void (*draw)(const struct bContext *, struct wmWi
int (*intersect)(struct bContext *, const struct wmEvent *, struct wmWidget *),
int (*handler)(struct bContext *, const struct wmEvent *, struct wmWidget *));
-void WM_widget_property(struct wmWidget *, int slot, struct PointerRNA *ptr, const char *propname);
-struct PointerRNA *WM_widget_operator(struct wmWidget *, const char *opname);
-void WM_widgets_update(const struct bContext *C, struct wmWidgetMap *wmap);
-void WM_widgets_draw(const struct bContext *C, const struct wmWidgetMap *wmap, const bool in_scene);
-void WM_event_add_area_widgetmap_handlers(struct ARegion *ar);
-void WM_modal_handler_attach_widgetgroup(struct bContext *C, struct wmEventHandler *handler,
- struct wmWidgetGroupType *wgrouptype, struct wmOperator *op);
-void WM_widgetgroup_customdata_set(struct wmWidgetGroup *wgroup, void *data);
+void WM_widgets_update(const struct bContext *C, struct wmWidgetMap *wmap);
+void WM_widgets_draw(const struct bContext *C, const struct wmWidgetMap *wmap, const bool in_scene);
+void WM_event_add_area_widgetmap_handlers(struct ARegion *ar);
+void WM_modal_handler_attach_widgetgroup(struct bContext *C, struct wmEventHandler *handler,
+ struct wmWidgetGroupType *wgrouptype, struct wmOperator *op);
+void WM_widgetgroup_customdata_set(struct wmWidgetGroup *wgroup, void *data);
void *WM_widgetgroup_customdata(const struct wmWidgetGroup *wgroup);
+/* wmWidget->flag */
+enum widgetflags {
+ /* states */
+ WM_WIDGET_HIGHLIGHT = (1 << 0),
+ WM_WIDGET_ACTIVE = (1 << 1),
+ WM_WIDGET_SELECTED = (1 << 2),
+ /* settings */
+ WM_WIDGET_DRAW_HOVER = (1 << 3),
+ WM_WIDGET_DRAW_ACTIVE = (1 << 4), /* draw while dragging */
+ WM_WIDGET_SCALE_3D = (1 << 5),
+ WM_WIDGET_SCENE_DEPTH = (1 << 6), /* widget is depth culled with scene objects*/
+ WM_WIDGET_HIDDEN = (1 << 7),
+ WM_WIDGET_SELECTABLE = (1 << 8),
+};
+
+void WM_widget_set_property(struct wmWidget *, int slot, struct PointerRNA *ptr, const char *propname);
+struct PointerRNA *WM_widget_set_operator(struct wmWidget *, const char *opname);
void WM_widget_set_origin(struct wmWidget *widget, const float origin[3]);
-void WM_widget_set_3d_scale(struct wmWidget *widget, const bool scale);
-void WM_widget_flag_set(struct wmWidget *widget, const int flag, const bool enable);
-void WM_widget_set_draw_on_hover_only(struct wmWidget *widget, const bool draw);
-void WM_widget_set_scene_depth(struct wmWidget *widget, const bool scene);
+void WM_widget_set_offset(struct wmWidget *widget, const float offset[3]);
+void WM_widget_set_flag(struct wmWidget *widget, const int flag, const bool enable);
void WM_widget_set_scale(struct wmWidget *widget, float scale);
void WM_widget_set_line_width(struct wmWidget *widget, const float line_width);
void WM_widget_set_colors(struct wmWidget *widget, const float col[4], const float col_hi[4]);
+wmKeyMap *WM_widgetgroup_keymap_common(wmKeyConfig *config, const char *wgroupname);
+
struct wmWidgetMapType *WM_widgetmaptype_find(const char *idname, const int spaceid, const int regionid,
const bool is_3d, const bool create);
-struct wmWidgetGroupType *WM_widgetgrouptype_new(int (*poll)(const struct bContext *, struct wmWidgetGroupType *),
- void (*create)(const struct bContext *, struct wmWidgetGroup *),
- const struct Main *bmain, const char *mapidname,
- const short spaceid, const short regionid, const bool is_3d);
+struct wmWidgetGroupType *WM_widgetgrouptype_new(
+ int (*poll)(const struct bContext *, struct wmWidgetGroupType *),
+ void (*create)(const struct bContext *, struct wmWidgetGroup *),
+ wmKeyMap *(*keymap_init)(wmKeyConfig *, const char *),
+ const struct Main *bmain, const char *mapidname, const char *name,
+ const short spaceid, const short regionid, const bool is_3d);
void WM_widgetgrouptype_unregister(struct bContext *C, struct Main *bmain, struct wmWidgetGroupType *wgroup);
/* creates a widgetmap with all registered widgets for that type */
@@ -549,6 +566,7 @@ enum {
WIDGET_ARROW_STYLE_INVERTED = (1 << 3), /* inverted offset during interaction - if set it also sets constrained below */
WIDGET_ARROW_STYLE_CONSTRAINED = (1 << 4), /* clamp arrow interaction to property width */
WIDGET_ARROW_STYLE_BOX = (1 << 5), /* use a box for the arrowhead */
+ WIDGET_ARROW_STYLE_CONE = (1 << 6),
};
enum {
@@ -580,21 +598,21 @@ enum {
struct wmWidget *WIDGET_arrow_new(struct wmWidgetGroup *wgroup, const char *name, const int style);
void WIDGET_arrow_set_direction(struct wmWidget *widget, const float direction[3]);
void WIDGET_arrow_set_up_vector(struct wmWidget *widget, const float direction[3]);
-void WIDGET_arrow_set_line_vec(struct wmWidget *widget, const float (*vec)[3], const int tot_points);
-void WIDGET_arrow_set_scale(struct wmWidget *widget, const float scale);
+void WIDGET_arrow_set_line_len(struct wmWidget *widget, const float len);
+void WIDGET_arrow_set_ui_range(struct wmWidget *widget, const float min, const float max);
+void WIDGET_arrow_set_range_fac(struct wmWidget *widget, const float range_fac);
+void WIDGET_arrow_cone_set_aspect(struct wmWidget *widget, const float aspect[2]);
struct wmWidget *WIDGET_dial_new(struct wmWidgetGroup *wgroup, const char *name, const int style);
-void WIDGET_dial_set_direction(struct wmWidget *widget, const float direction[3]);
+void WIDGET_dial_set_up_vector(struct wmWidget *widget, const float direction[3]);
struct wmWidget *WIDGET_plane_new(struct wmWidgetGroup *wgroup, const char *name, const int style);
void WIDGET_plane_set_direction(struct wmWidget *widget, const float direction[3]);
-void WIDGET_plane_set_offset(struct wmWidget *widget, const float offset[3]);
void WIDGET_plane_set_up_vector(struct wmWidget *widget, const float direction[3]);
struct wmWidget *WIDGET_rect_transform_new(
struct wmWidgetGroup *wgroup, const char *name, const int style,
const float width, const float height);
-void WIDGET_rect_transform_set_offset(struct wmWidget *widget, const float offset[2]);
struct wmWidget *WIDGET_facemap_new(
struct wmWidgetGroup *wgroup, const char *name, const int style,
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 248f5760720..3e43047c96c 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -108,6 +108,8 @@ extern "C" {
struct bContext;
struct wmEvent;
+struct wmKeyMap;
+struct wmKeyConfig;
struct wmWindowManager;
struct wmOperator;
struct ImBuf;
@@ -672,18 +674,17 @@ typedef struct wmDropBox {
/* WidgetGroups store and manage groups of widgets.
- * They are responsible for drawing necessary widgets and updating their state and position.
- * Also they */
+ * They are responsible for drawing necessary widgets and updating their state and position. */
typedef struct wmWidget wmWidget;
typedef struct wmWidgetGroup wmWidgetGroup;
typedef struct wmWidgetMapType wmWidgetMapType;
-typedef struct wmWidgetGroupType wmWidgetGroupType;
/* factory class for a widgetgroup type, gets called every time a new area is spawned */
typedef struct wmWidgetGroupType {
struct wmWidgetGroupType *next, *prev;
char idname[64]; /* MAX_NAME */
+ char name[64]; /* widget group name - displayed in UI (keymap editor) */
/* poll if widgetmap should be active */
int (*poll)(const struct bContext *C, struct wmWidgetGroupType *wgrouptype) ATTR_WARN_UNUSED_RESULT;
@@ -691,6 +692,12 @@ typedef struct wmWidgetGroupType {
/* update widgets, called right before drawing */
void (*create)(const struct bContext *C, struct wmWidgetGroup *wgroup);
+ /* keymap init callback for this widgetgroup */
+ struct wmKeyMap *(*keymap_init)(struct wmKeyConfig *, const char *);
+
+ /* keymap created with callback from above */
+ struct wmKeyMap *keymap;
+
/* rna for properties */
struct StructRNA *srna;
@@ -711,16 +718,18 @@ typedef struct wmWidgetGroupType {
typedef struct wmWidgetMap {
struct wmWidgetMap *next, *prev;
-
+
struct wmWidgetMapType *type;
ListBase widgetgroups;
-
+
/* highlighted widget for this map. We redraw the widgetmap when this changes */
struct wmWidget *highlighted_widget;
/* active widget for this map. User has clicked currently this widget and it gets all input */
struct wmWidget *active_widget;
-
- /* active group is overriding all other widgets while active */
+ /* selected widget for this map. */
+ struct wmWidget *selected_widget;
+
+ /* active group - set while widget is highlighted/active */
struct wmWidgetGroup *activegroup;
} wmWidgetMap;
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index fd46d9bd1d0..4b3d66b9e71 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -342,6 +342,7 @@ void WM_keymap_init(bContext *C)
* it's persistent across sessions */
if (!(wm->defaultconf->flag & KEYCONF_INIT_DEFAULT)) {
wm_window_keymap(wm->defaultconf);
+ wm_widgets_keymap(wm->defaultconf);
ED_spacetypes_keymap(wm->defaultconf);
wm->defaultconf->flag |= KEYCONF_INIT_DEFAULT;
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 2a9de6f5029..98f88c9a081 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1697,6 +1697,9 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
CTX_wm_region_set(C, NULL);
}
+ /* update widgets during modal handlers */
+ wm_widget_handler_modal_update(C, event, handler);
+
/* remove modal handler, operator itself should have been canceled and freed */
if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) {
WM_cursor_grab_disable(CTX_wm_window(C), NULL);
@@ -1933,6 +1936,9 @@ static int wm_action_not_handled(int action)
return action == WM_HANDLER_CONTINUE || action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL);
}
+/* use old, hardcoded widget map handling - kept in case new one doesn't work out */
+//#define USE_OLD_WIDGETMAP_HANDLING
+
static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers)
{
#ifndef NDEBUG
@@ -2063,16 +2069,59 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
}
}
else if (handler->widgetmap) {
- wmWidgetMap *wmap = handler->widgetmap;
- unsigned char part;
- short event_processed = 0;
- wmWidget *widget = wm_widgetmap_get_active_widget(wmap);
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
+ wmWidgetMap *wmap = handler->widgetmap;
+ wmWidget *widget = wm_widgetmap_get_highlighted_widget(wmap);
+ short event_processed = 0;
+ unsigned char part;
wm_widgetmap_handler_context(C, handler);
wm_region_mouse_co(C, event);
+#ifndef USE_OLD_WIDGETMAP_HANDLING
+ /* handle widget highlighting */
+ if (event->type == MOUSEMOVE && !wm_widgetmap_get_active_widget(wmap)) {
+ if (wm_widgetmap_is_3d(wmap)) {
+ widget = wm_widget_find_highlighted_3D(wmap, C, event, &part);
+ wm_widgetmap_set_highlighted_widget(wmap, C, widget, part);
+ }
+ else {
+ widget = wm_widget_find_highlighted(wmap, C, event, &part);
+ wm_widgetmap_set_highlighted_widget(wmap, C, widget, part);
+ }
+ }
+ /* handle user configurable widgetmap keymap */
+ else if (widget && wmap->activegroup) {
+ /* get user customized keymap from default one */
+ const wmKeyMap *keymap = WM_keymap_active(wm, wmap->activegroup->type->keymap);
+ wmKeyMapItem *kmi;
+
+ if (!keymap->poll || keymap->poll(C)) {
+ for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ if (wm_eventmatch(event, kmi)) {
+ wmOperator *op = handler->op;
+
+ /* weak, but allows interactive callback to not use rawkey */
+ event->keymap_idname = kmi->idname;
+
+ /* handler->op is called later, we want keymap op to be triggered here */
+ handler->op = NULL;
+ action |= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr);
+ handler->op = op;
+
+ if (action & WM_HANDLER_BREAK) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ UNUSED_VARS(event_processed);
+#else
+ widget = wm_widgetmap_get_active_widget(wmap);
+
/* handle the widget first, before passing the event down */
switch (event->type) {
case MOUSEMOVE:
@@ -2090,12 +2139,11 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
wm_widgetmap_set_highlighted_widget(wmap, C, widget, part);
}
break;
-
case LEFTMOUSE:
- {
if (widget) {
if (event->val == KM_RELEASE) {
wm_widgetmap_set_active_widget(wmap, C, event, NULL, false);
+ wm_widgetmap_set_selected_widget(C, wmap, NULL);
event_processed = EVT_WIDGET_RELEASED;
action |= WM_HANDLER_BREAK;
}
@@ -2112,27 +2160,51 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
}
}
break;
+ case RIGHTMOUSE:
+ case ESCKEY:
+ {
+ wmWidget *highlight = wm_widgetmap_get_highlighted_widget(wmap);
+ if (event->type == RIGHTMOUSE && highlight) {
+ if (highlight->flag & WM_WIDGET_SELECTABLE) {
+ if (event->val == KM_RELEASE) {
+ wm_widgetmap_set_selected_widget(C, wmap, highlight);
+ action |= WM_HANDLER_BREAK;
+ }
+ }
+ }
+ else if (widget) {
+ if (widget->cancel) {
+ widget->cancel(C, widget);
+ }
+ wm_widgetmap_set_active_widget(wmap, C, event, NULL, false);
+ event_processed = EVT_WIDGET_RELEASED;
+ action |= WM_HANDLER_BREAK;
+ }
+ else {
+ wm_widgetmap_set_selected_widget(C, wmap, NULL);
+ }
+ break;
}
}
-
+#endif
+
/* restore the area */
CTX_wm_area_set(C, area);
CTX_wm_region_set(C, region);
if (handler->op) {
+#ifdef USE_OLD_WIDGETMAP_HANDLING
/* if event was processed by an active widget pass the modified event to the operator */
if (event_processed) {
event->type = event_processed;
}
+#endif
action |= wm_handler_operator_call(C, handlers, handler, event, NULL);
}
}
else {
/* modal, swallows all */
action |= wm_handler_operator_call(C, handlers, handler, event, NULL);
-
- /* update widgets during modal handlers */
- wm_widget_handler_modal_update(C, event, handler);
}
if (action & WM_HANDLER_BREAK) {
diff --git a/source/blender/windowmanager/intern/wm_generic_widgets.c b/source/blender/windowmanager/intern/wm_generic_widgets.c
index e56d415e700..7e26c086ba0 100644
--- a/source/blender/windowmanager/intern/wm_generic_widgets.c
+++ b/source/blender/windowmanager/intern/wm_generic_widgets.c
@@ -15,7 +15,7 @@
* 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) 2009 Blender Foundation.
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
* All rights reserved.
*
* Contributor(s): Blender Foundation
@@ -23,8 +23,12 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/editors/interface/interface_generic_widgets.c
- * \ingroup edinterface
+/** \file blender/windowmanager/intern/wm_generic_widgets.c
+ * \ingroup wm
+ *
+ * *****************************************************
+ * GENERIC WIDGET LIBRARY
+ * *****************************************************
*/
#include "RNA_types.h"
@@ -69,17 +73,15 @@
#include "WM_types.h"
-/******************************************************
- * GENERIC WIDGET LIBRARY *
- ******************************************************/
-
-
/* to use custom arrows exported to arrow_widget.c */
//#define WIDGET_USE_CUSTOM_ARROWS
-/* to use custom dials exported to arrow_widget.c */
+/* to use custom dials exported to dial_widget.c */
//#define WIDGET_USE_CUSTOM_DIAS
+/* -------------------------------------------------------------------- */
+/* Widget drawing */
+
typedef struct WidgetDrawInfo {
int nverts;
int ntris;
@@ -151,24 +153,43 @@ static void widget_draw_intern(WidgetDrawInfo *info, const bool select)
}
}
-/********* Arrow widget ************/
-#define ARROW_UP_VECTOR_SET 1
+/* -------------------------------------------------------------------- */
+/* Widget defines */
+
+/** \name Arrow Widget
+ *
+ * 3D Widget
+ *
+ * \brief Simple arrow widget which is dragged into a certain direction.
+ * The arrow head can have have varying shapes, e.g. cone, box, etc.
+ *
+ * \{ */
+
+/* ArrowWidget->flag */
+enum {
+ ARROW_UP_VECTOR_SET = (1 << 0),
+ ARROW_CUSTOM_RANGE_SET = (1 << 1),
+};
typedef struct ArrowWidget {
wmWidget widget;
int style;
int flag;
+
+ float len; /* arrow line length */
float direction[3];
float up[3];
- float (*line)[3]; /* custom coords for arrow line drawing */
- int tot_line_points; /* amount of points for arrow line drawing */
+ float aspect[2]; /* cone style only */
+
+ float range_fac; /* factor for arrow min/max distance */
float offset;
/* property range and minimum for constrained arrows */
float range, min;
} ArrowWidget;
typedef struct ArrowInteraction {
+ float orig_value; /* initial property value */
float orig_origin[3];
float orig_mouse[2];
float orig_offset;
@@ -203,41 +224,80 @@ static void arrow_draw_geom(const ArrowWidget *arrow, const bool select)
glPopAttrib();
}
+ else if (arrow->style & WIDGET_ARROW_STYLE_CONE) {
+ const float unitx = arrow->aspect[0];
+ const float unity = arrow->aspect[1];
+ const float vec[4][3] = {
+ {-unitx, -unity, 0},
+ { unitx, -unity, 0},
+ { unitx, unity, 0},
+ {-unitx, unity, 0},
+ };
+
+ glLineWidth(arrow->widget.line_width);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, vec);
+ glDrawArrays(GL_LINE_LOOP, 0, ARRAY_SIZE(vec));
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glLineWidth(1.0);
+ }
else {
#ifdef WIDGET_USE_CUSTOM_ARROWS
widget_draw_intern(&arrow_head_draw_info, select);
#else
+ const float vec[2][3] = {
+ {0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, arrow->len},
+ };
+
glLineWidth(arrow->widget.line_width);
glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, arrow->line);
- glDrawArrays(GL_LINES, 0, arrow->tot_line_points);
+ glVertexPointer(3, GL_FLOAT, 0, vec);
+ glDrawArrays(GL_LINE_STRIP, 0, ARRAY_SIZE(vec));
glDisableClientState(GL_VERTEX_ARRAY);
glLineWidth(1.0);
- /* draw arrow head */
- glTranslatef(UNPACK3(arrow->line[arrow->tot_line_points - 1]));
+ /* *** draw arrow head *** */
+
+ glPushMatrix();
if (arrow->style & WIDGET_ARROW_STYLE_BOX) {
const float size = 0.05f;
- /* draw cube */
+ /* translate to line end with some extra offset so box starts exactly where line ends */
+ glTranslatef(0.0f, 0.0f, arrow->len + size);
+ /* scale down to box size */
glScalef(size, size, size);
+
+ /* draw cube */
widget_draw_intern(&cube_draw_info, select);
}
else {
GLUquadricObj *qobj = gluNewQuadric();
const float len = 0.25f;
const float width = 0.06f;
+ const bool use_lighting = select == false && ((U.tw_flag & V3D_SHADED_WIDGETS) != 0);
+
+ /* translate to line end */
+ glTranslatef(0.0f, 0.0f, arrow->len);
+
+ if (use_lighting) {
+ glShadeModel(GL_SMOOTH);
+ }
gluQuadricDrawStyle(qobj, GLU_FILL);
- gluCylinder(qobj, width, 0.0, len, 8, 1);
gluQuadricOrientation(qobj, GLU_INSIDE);
gluDisk(qobj, 0.0, width, 8, 1);
gluQuadricOrientation(qobj, GLU_OUTSIDE);
+ gluCylinder(qobj, width, 0.0, len, 8, 1);
+
+ if (use_lighting) {
+ glShadeModel(GL_FLAT);
+ }
}
- (void)select;
+ glPopMatrix();
#endif
}
@@ -276,6 +336,7 @@ static void arrow_draw_intern(ArrowWidget *arrow, const bool select, const bool
}
glEnable(GL_BLEND);
+ glTranslate3fv(arrow->widget.offset);
arrow_draw_geom(arrow, select);
glDisable(GL_BLEND);
@@ -293,8 +354,8 @@ static void arrow_draw_intern(ArrowWidget *arrow, const bool select, const bool
glEnable(GL_BLEND);
glColor4f(0.5f, 0.5f, 0.5f, 0.5f);
+ glTranslate3fv(arrow->widget.offset);
arrow_draw_geom(arrow, select);
-
glDisable(GL_BLEND);
glPopMatrix();
@@ -312,7 +373,11 @@ static void widget_arrow_draw(const bContext *UNUSED(C), wmWidget *widget)
arrow_draw_intern((ArrowWidget *)widget, false, (widget->flag & WM_WIDGET_HIGHLIGHT) != 0);
}
-#define ARROW_RANGE 1.5f
+/**
+ * Calculate arrow offset independent from prop min value,
+ * meaning the range will not be offset by min value first.
+ */
+#define USE_ABS_HANDLE_RANGE
static int widget_arrow_handler(bContext *C, const wmEvent *event, wmWidget *widget)
{
@@ -330,6 +395,7 @@ static int widget_arrow_handler(bContext *C, const wmEvent *event, wmWidget *wid
float facdir = 1.0f;
bool use_vertical = false;
+
copy_v3_v3(orig_origin, data->orig_origin);
orig_origin[3] = 1.0f;
add_v3_v3v3(offset, orig_origin, arrow->direction);
@@ -403,14 +469,24 @@ static int widget_arrow_handler(bContext *C, const wmEvent *event, wmWidget *wid
if (widget->props[ARROW_SLOT_OFFSET_WORLD_SPACE]) {
PointerRNA ptr = widget->ptr[ARROW_SLOT_OFFSET_WORLD_SPACE];
PropertyRNA *prop = widget->props[ARROW_SLOT_OFFSET_WORLD_SPACE];
+ float max = arrow->min + arrow->range;
float value;
value = data->orig_offset + facdir * len_v3(offset);
if (arrow->style & WIDGET_ARROW_STYLE_CONSTRAINED) {
if (arrow->style & WIDGET_ARROW_STYLE_INVERTED)
- value = arrow->min + arrow->range - (value * arrow->range / ARROW_RANGE);
+ value = max - (value * arrow->range / arrow->range_fac);
else
- value = arrow->min + (value * arrow->range / ARROW_RANGE);
+#ifdef USE_ABS_HANDLE_RANGE
+ value = value * arrow->range / arrow->range_fac;
+#else
+ value = arrow->min + (value * arrow->range / arrow->range_fac);
+#endif
+ }
+
+ /* clamp to custom range */
+ if (arrow->flag & ARROW_CUSTOM_RANGE_SET) {
+ CLAMP(value, arrow->min, max);
}
RNA_property_float_set(&ptr, prop, value);
@@ -421,9 +497,13 @@ static int widget_arrow_handler(bContext *C, const wmEvent *event, wmWidget *wid
/* accounts for clamping properly */
if (arrow->style & WIDGET_ARROW_STYLE_CONSTRAINED) {
if (arrow->style & WIDGET_ARROW_STYLE_INVERTED)
- arrow->offset = ARROW_RANGE * (arrow->min + arrow->range - value) / arrow->range;
+ arrow->offset = arrow->range_fac * (max - value) / arrow->range;
else
- arrow->offset = ARROW_RANGE * ((value - arrow->min) / arrow->range);
+#ifdef USE_ABS_HANDLE_RANGE
+ arrow->offset = arrow->range_fac * (value / arrow->range);
+#else
+ arrow->offset = arrow->range_fac * ((value - arrow->min) / arrow->range);
+#endif
}
else
arrow->offset = value;
@@ -443,6 +523,12 @@ static int widget_arrow_invoke(bContext *UNUSED(C), const wmEvent *event, wmWidg
{
ArrowWidget *arrow = (ArrowWidget *) widget;
ArrowInteraction *data = MEM_callocN(sizeof(ArrowInteraction), "arrow_interaction");
+ PointerRNA ptr = widget->ptr[ARROW_SLOT_OFFSET_WORLD_SPACE];
+ PropertyRNA *prop = widget->props[ARROW_SLOT_OFFSET_WORLD_SPACE];
+
+ if (prop) {
+ data->orig_value = RNA_property_float_get(&ptr, prop);
+ }
data->orig_offset = arrow->offset;
@@ -465,20 +551,29 @@ static void widget_arrow_bind_to_prop(wmWidget *widget, const int UNUSED(slot))
PropertyRNA *prop = widget->props[ARROW_SLOT_OFFSET_WORLD_SPACE];
if (prop) {
- const float float_prop = RNA_property_float_get(&ptr, prop);
+ float float_prop = RNA_property_float_get(&ptr, prop);
if (arrow->style & WIDGET_ARROW_STYLE_CONSTRAINED) {
float min, max, step, precision;
- RNA_property_float_ui_range(&ptr, prop, &min, &max, &step, &precision);
- arrow->range = max - min;
- arrow->min = min;
+ if (arrow->flag & ARROW_CUSTOM_RANGE_SET) {
+ max = arrow->min + arrow->range;
+ }
+ else {
+ RNA_property_float_ui_range(&ptr, prop, &min, &max, &step, &precision);
+ arrow->range = max - min;
+ arrow->min = min;
+ }
if (arrow->style & WIDGET_ARROW_STYLE_INVERTED) {
- arrow->offset = ARROW_RANGE * (max - float_prop) / arrow->range;
+ arrow->offset = arrow->range_fac * (max - float_prop) / arrow->range;
}
else {
- arrow->offset = ARROW_RANGE * ((float_prop - arrow->min) / arrow->range);
+#ifdef USE_ABS_HANDLE_RANGE
+ arrow->offset = arrow->range_fac * (float_prop / arrow->range);
+#else
+ arrow->offset = arrow->range_fac * ((float_prop - arrow->min) / arrow->range);
+#endif
}
}
else {
@@ -490,14 +585,25 @@ static void widget_arrow_bind_to_prop(wmWidget *widget, const int UNUSED(slot))
arrow->offset = 0.0f;
}
+static void widget_arrow_cancel(bContext *C, wmWidget *widget)
+{
+ PointerRNA ptr = widget->ptr[ARROW_SLOT_OFFSET_WORLD_SPACE];
+ PropertyRNA *prop = widget->props[ARROW_SLOT_OFFSET_WORLD_SPACE];
+ ArrowInteraction *data = widget->interaction_data;
+
+ /* reset property */
+ RNA_property_float_set(&ptr, prop, data->orig_value);
+ RNA_property_update(C, &ptr, prop);
+}
+
+/** \name Arrow Widget API
+ *
+ * \{ */
+
wmWidget *WIDGET_arrow_new(wmWidgetGroup *wgroup, const char *name, const int style)
{
ArrowWidget *arrow = MEM_callocN(sizeof(ArrowWidget), name);
const float dir_default[3] = {0.0f, 0.0f, 1.0f};
- const float line_default[2][3] = {
- {0.0f, 0.0f, 0.0f},
- {0.0f, 0.0f, 1.0f}
- };
int real_style = style;
#ifdef WIDGET_USE_CUSTOM_ARROWS
@@ -532,29 +638,33 @@ wmWidget *WIDGET_arrow_new(wmWidgetGroup *wgroup, const char *name, const int st
arrow->widget.invoke = widget_arrow_invoke;
arrow->widget.render_3d_intersection = widget_arrow_render_3d_intersect;
arrow->widget.bind_to_prop = widget_arrow_bind_to_prop;
- arrow->widget.flag |= WM_WIDGET_SCALE_3D;
+ arrow->widget.cancel = widget_arrow_cancel;
+ arrow->widget.flag |= (WM_WIDGET_SCALE_3D | WM_WIDGET_DRAW_ACTIVE);
arrow->style = real_style;
-
- /* defaults */
+ arrow->len = 1.0f;
+ arrow->range_fac = 1.0f;
copy_v3_v3(arrow->direction, dir_default);
- arrow->tot_line_points = ARRAY_SIZE(line_default);
- arrow->line = MEM_mallocN(sizeof(line_default), __func__);
- memcpy(arrow->line, line_default, sizeof(line_default));
wm_widget_register(wgroup, &arrow->widget, name);
return (wmWidget *)arrow;
}
+/**
+ * Define direction the arrow will point towards
+ */
void WIDGET_arrow_set_direction(wmWidget *widget, const float direction[3])
{
ArrowWidget *arrow = (ArrowWidget *)widget;
-
+
copy_v3_v3(arrow->direction, direction);
normalize_v3(arrow->direction);
}
+/**
+ * Define up-direction of the arrow widget
+ */
void WIDGET_arrow_set_up_vector(wmWidget *widget, const float direction[3])
{
ArrowWidget *arrow = (ArrowWidget *)widget;
@@ -570,20 +680,67 @@ void WIDGET_arrow_set_up_vector(wmWidget *widget, const float direction[3])
}
/**
- * Define a custom coord vec for arrow line drawing
+ * Define a custom arrow line length
+ */
+void WIDGET_arrow_set_line_len(wmWidget *widget, const float len)
+{
+ ArrowWidget *arrow = (ArrowWidget *)widget;
+ arrow->len = len;
+}
+
+/**
+ * Define a custom property UI range
+ *
+ * \note Needs to be called before WM_widget_set_property!
+ */
+void WIDGET_arrow_set_ui_range(wmWidget *widget, const float min, const float max)
+{
+ ArrowWidget *arrow = (ArrowWidget *)widget;
+
+ BLI_assert(min < max);
+ BLI_assert(!(arrow->widget.props[0] && "Make sure this function is called before WM_widget_set_property"));
+
+ arrow->range = max - min;
+ arrow->min = min;
+ arrow->flag |= ARROW_CUSTOM_RANGE_SET;
+}
+
+/**
+ * Define a custom factor for arrow min/max distance
+ *
+ * \note Needs to be called before WM_widget_set_property!
+ */
+void WIDGET_arrow_set_range_fac(wmWidget *widget, const float range_fac)
+{
+ ArrowWidget *arrow = (ArrowWidget *)widget;
+
+ BLI_assert(!(arrow->widget.props[0] && "Make sure this function is called before WM_widget_set_property"));
+
+ arrow->range_fac = range_fac;
+}
+
+/**
+ * Define xy-aspect for arrow cone
*/
-void WIDGET_arrow_set_line_vec(wmWidget *widget, const float (*vec)[3], const int tot_points)
+void WIDGET_arrow_cone_set_aspect(wmWidget *widget, const float aspect[2])
{
ArrowWidget *arrow = (ArrowWidget *)widget;
- const size_t vec_size = 3 * tot_points * sizeof(float);
- arrow->tot_line_points = tot_points;
- arrow->line = MEM_reallocN(arrow->line, vec_size);
- memcpy(arrow->line, vec, vec_size);
+ copy_v2_v2(arrow->aspect, aspect);
}
+/** \} */ // Arrow Widget API
+/** \} */ // Arrow Widget
+
-/********* Dial widget ************/
+/** \name Dial Widget
+ *
+ * 3D Widget
+ *
+ * \brief Circle shaped widget for circular interaction.
+ * Currently no own handling, use with operator only.
+ *
+ * \{ */
typedef struct DialWidget {
wmWidget widget;
@@ -593,24 +750,23 @@ typedef struct DialWidget {
static void dial_draw_geom(const DialWidget *dial, const bool select)
{
+#ifdef WIDGET_USE_CUSTOM_DIAS
+ glEnable(GL_MULTISAMPLE_ARB);
+
+ widget_draw_intern(&dial_draw_info, select);
+#else
GLUquadricObj *qobj = gluNewQuadric();
const float width = 1.0f;
const int resol = 32;
glEnable(GL_MULTISAMPLE_ARB);
-#ifdef WIDGET_USE_CUSTOM_DIAS
- widget_draw_intern(&dial_draw_info, select);
-
- (void)qobj; (void)width; (void)resol;
-#else
-
glLineWidth(dial->widget.line_width);
gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
gluDisk(qobj, 0.0, width, resol, 1);
glLineWidth(1.0);
- (void)select;
+ UNUSED_VARS(select);
#endif
glDisable(GL_MULTISAMPLE_ARB);
@@ -635,6 +791,7 @@ static void dial_draw_intern(DialWidget *dial, const bool select, const bool hig
else
glColor4fv(dial->widget.col);
+ glTranslate3fv(dial->widget.offset);
dial_draw_geom(dial, select);
glPopMatrix();
@@ -688,6 +845,10 @@ static void widget_dial_draw(const bContext *C, wmWidget *widget)
}
}
+/** \name Dial Widget API
+ *
+ * \{ */
+
wmWidget *WIDGET_dial_new(wmWidgetGroup *wgroup, const char *name, const int style)
{
DialWidget *dial = MEM_callocN(sizeof(DialWidget), name);
@@ -719,7 +880,10 @@ wmWidget *WIDGET_dial_new(wmWidgetGroup *wgroup, const char *name, const int sty
return (wmWidget *)dial;
}
-void WIDGET_dial_set_direction(wmWidget *widget, const float direction[3])
+/**
+ * Define up-direction of the dial widget
+ */
+void WIDGET_dial_set_up_vector(wmWidget *widget, const float direction[3])
{
DialWidget *dial = (DialWidget *)widget;
@@ -727,21 +891,32 @@ void WIDGET_dial_set_direction(wmWidget *widget, const float direction[3])
normalize_v3(dial->direction);
}
-/********* Plane widget ************/
+/** \} */ // Dial Widget API
+/** \} */ // Dial Widget
+
+/** \name Plane Widget
+ *
+ * 3D Widget
+ *
+ * \brief Flat and rectangular shaped widget for planar interaction.
+ * Currently no own handling, use with operator only.
+ *
+ * \{ */
+
+/* PlaneWidget->flag */
#define PLANE_UP_VECTOR_SET 1
typedef struct PlaneWidget {
wmWidget widget;
float direction[3];
- float offset[3];
float up[3];
int flag;
} PlaneWidget;
-static void widget_plane_draw_geom(const float ofs[3], const float col_inner[4], const float col_outer[4])
+static void widget_plane_draw_geom(const float col_inner[4], const float col_outer[4])
{
static float vec[4][3] = {
{-1, -1, 0},
@@ -750,8 +925,6 @@ static void widget_plane_draw_geom(const float ofs[3], const float col_inner[4],
{-1, 1, 0},
};
- glTranslatef(UNPACK3(ofs));
-
glEnable(GL_MULTISAMPLE_ARB);
glEnableClientState(GL_VERTEX_ARRAY);
@@ -799,7 +972,8 @@ static void widget_plane_draw_intern(PlaneWidget *plane, const bool UNUSED(selec
col_inner[3] *= 0.5f;
glEnable(GL_BLEND);
- widget_plane_draw_geom(plane->offset, col_inner, col_outer);
+ glTranslate3fv(plane->widget.offset);
+ widget_plane_draw_geom(col_inner, col_outer);
glDisable(GL_BLEND);
glPopMatrix();
@@ -816,6 +990,10 @@ static void widget_plane_draw(const bContext *UNUSED(C), wmWidget *widget)
widget_plane_draw_intern((PlaneWidget *)widget, false, (widget->flag & WM_WIDGET_HIGHLIGHT));
}
+/** \name Plane Widget API
+ *
+ * \{ */
+
wmWidget *WIDGET_plane_new(wmWidgetGroup *wgroup, const char *name, const int UNUSED(style))
{
PlaneWidget *plane = MEM_callocN(sizeof(PlaneWidget), name);
@@ -828,13 +1006,15 @@ wmWidget *WIDGET_plane_new(wmWidgetGroup *wgroup, const char *name, const int UN
/* defaults */
copy_v3_v3(plane->direction, dir_default);
- zero_v3(plane->offset);
wm_widget_register(wgroup, &plane->widget, name);
return (wmWidget *)plane;
}
+/**
+ * Define direction the plane will point towards
+ */
void WIDGET_plane_set_direction(wmWidget *widget, const float direction[3])
{
PlaneWidget *plane = (PlaneWidget *)widget;
@@ -843,13 +1023,9 @@ void WIDGET_plane_set_direction(wmWidget *widget, const float direction[3])
normalize_v3(plane->direction);
}
-void WIDGET_plane_set_offset(wmWidget *widget, const float offset[3])
-{
- PlaneWidget *plane = (PlaneWidget *)widget;
-
- copy_v3_v3(plane->offset, offset);
-}
-
+/**
+ * Define up-direction of the plane widget
+ */
void WIDGET_plane_set_up_vector(wmWidget *widget, const float direction[3])
{
PlaneWidget *plane = (PlaneWidget *)widget;
@@ -864,8 +1040,20 @@ void WIDGET_plane_set_up_vector(wmWidget *widget, const float direction[3])
}
}
-/********* Cage widget ************/
+/** \} */ // Plane Widget API
+/** \} */ // Plane Widget
+
+
+/** \name Cage Widget
+ *
+ * 2D Widget
+ *
+ * \brief Rectangular widget acting as a 'cage' around its content.
+ * Interacting scales or translates the widget.
+ *
+ * \{ */
+/* wmWidget->highlighted_part */
enum {
WIDGET_RECT_TRANSFORM_INTERSECT_TRANSLATE = 1,
WIDGET_RECT_TRANSFORM_INTERSECT_SCALEX_LEFT = 2,
@@ -879,7 +1067,6 @@ enum {
typedef struct RectTransformWidget {
wmWidget widget;
- float offset[2]; /* position of widget */
float w, h; /* dimensions of widget */
float rotation; /* rotation of the rectangle */
float scale[2]; /* scaling for the widget for non-destructive editing. */
@@ -918,7 +1105,7 @@ static void rect_transform_draw_interaction(
{
float verts[4][2];
unsigned short elems[4] = {0, 1, 3, 2};
-
+
switch (highlighted) {
case WIDGET_RECT_TRANSFORM_INTERSECT_SCALEX_LEFT:
verts[0][0] = -half_w + w;
@@ -930,7 +1117,7 @@ static void rect_transform_draw_interaction(
verts[3][0] = -half_w + w;
verts[3][1] = half_h;
break;
-
+
case WIDGET_RECT_TRANSFORM_INTERSECT_SCALEX_RIGHT:
verts[0][0] = half_w - w;
verts[0][1] = -half_h;
@@ -941,7 +1128,7 @@ static void rect_transform_draw_interaction(
verts[3][0] = half_w - w;
verts[3][1] = half_h;
break;
-
+
case WIDGET_RECT_TRANSFORM_INTERSECT_SCALEY_DOWN:
verts[0][0] = -half_w;
verts[0][1] = -half_h + h;
@@ -952,7 +1139,7 @@ static void rect_transform_draw_interaction(
verts[3][0] = half_w;
verts[3][1] = -half_h + h;
break;
-
+
case WIDGET_RECT_TRANSFORM_INTERSECT_SCALEY_UP:
verts[0][0] = -half_w;
verts[0][1] = half_h - h;
@@ -963,11 +1150,11 @@ static void rect_transform_draw_interaction(
verts[3][0] = half_w;
verts[3][1] = half_h - h;
break;
-
+
default:
return;
}
-
+
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, verts);
glLineWidth(line_width + 3.0);
@@ -978,7 +1165,7 @@ static void rect_transform_draw_interaction(
glDrawArrays(GL_LINE_STRIP, 0, 3);
glLineWidth(1.0);
- (void)elems;
+ UNUSED_VARS(elems);
}
static void widget_rect_transform_draw(const bContext *UNUSED(C), wmWidget *widget)
@@ -990,14 +1177,14 @@ static void widget_rect_transform_draw(const bContext *UNUSED(C), wmWidget *widg
float half_w = w / 2.0f;
float half_h = h / 2.0f;
float aspx = 1.0f, aspy = 1.0f;
-
+
r.xmin = -half_w;
r.ymin = -half_h;
r.xmax = half_w;
r.ymax = half_h;
-
+
glPushMatrix();
- glTranslatef(widget->origin[0] + cage->offset[0], widget->origin[1] + cage->offset[1], 0.0f);
+ glTranslatef(widget->origin[0] + widget->offset[0], widget->origin[1] + widget->offset[1], 0.0f);
if (cage->style & WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM)
glScalef(cage->scale[0], cage->scale[0], 1.0);
else
@@ -1029,7 +1216,7 @@ static void widget_rect_transform_draw(const bContext *UNUSED(C), wmWidget *widg
glPopMatrix();
}
-static int widget_rect_tranfrorm_get_cursor(wmWidget *widget)
+static int widget_rect_transform_get_cursor(wmWidget *widget)
{
switch (widget->highlighted_part) {
case WIDGET_RECT_TRANSFORM_INTERSECT_TRANSLATE:
@@ -1045,7 +1232,7 @@ static int widget_rect_tranfrorm_get_cursor(wmWidget *widget)
}
}
-static int widget_rect_tranfrorm_intersect(bContext *UNUSED(C), const wmEvent *event, wmWidget *widget)
+static int widget_rect_transform_intersect(bContext *UNUSED(C), const wmEvent *event, wmWidget *widget)
{
RectTransformWidget *cage = (RectTransformWidget *)widget;
const float mouse[2] = {event->mval[0], event->mval[1]};
@@ -1058,11 +1245,11 @@ static int widget_rect_tranfrorm_intersect(bContext *UNUSED(C), const wmEvent *e
bool isect;
rctf r;
float aspx = 1.0f, aspy = 1.0f;
-
+
/* rotate mouse in relation to the center and relocate it */
sub_v2_v2v2(point_local, mouse, widget->origin);
- point_local[0] -= cage->offset[0];
- point_local[1] -= cage->offset[1];
+ point_local[0] -= widget->offset[0];
+ point_local[1] -= widget->offset[1];
//rotate_m2(matrot, -cage->transform.rotation);
if (cage->style & WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM)
@@ -1071,7 +1258,7 @@ static int widget_rect_tranfrorm_intersect(bContext *UNUSED(C), const wmEvent *e
point_local[0] /= cage->scale[0];
point_local[1] /= cage->scale[0];
}
-
+
if (cage->w > cage->h)
aspx = h / w;
else
@@ -1084,9 +1271,9 @@ static int widget_rect_tranfrorm_intersect(bContext *UNUSED(C), const wmEvent *e
r.ymin = -half_h + h;
r.xmax = half_w - w;
r.ymax = half_h - h;
-
+
isect = BLI_rctf_isect_pt_v(&r, point_local);
-
+
if (isect)
return WIDGET_RECT_TRANSFORM_INTERSECT_TRANSLATE;
@@ -1096,43 +1283,43 @@ static int widget_rect_tranfrorm_intersect(bContext *UNUSED(C), const wmEvent *e
r.ymin = -half_h;
r.xmax = -half_w + w;
r.ymax = half_h;
-
+
isect = BLI_rctf_isect_pt_v(&r, point_local);
-
+
if (isect)
return WIDGET_RECT_TRANSFORM_INTERSECT_SCALEX_LEFT;
-
+
r.xmin = half_w - w;
r.ymin = -half_h;
r.xmax = half_w;
r.ymax = half_h;
-
+
isect = BLI_rctf_isect_pt_v(&r, point_local);
-
+
if (isect)
return WIDGET_RECT_TRANSFORM_INTERSECT_SCALEX_RIGHT;
-
+
r.xmin = -half_w;
r.ymin = -half_h;
r.xmax = half_w;
r.ymax = -half_h + h;
-
+
isect = BLI_rctf_isect_pt_v(&r, point_local);
-
+
if (isect)
return WIDGET_RECT_TRANSFORM_INTERSECT_SCALEY_DOWN;
-
+
r.xmin = -half_w;
r.ymin = half_h - h;
r.xmax = half_w;
r.ymax = half_h;
-
+
isect = BLI_rctf_isect_pt_v(&r, point_local);
-
+
if (isect)
return WIDGET_RECT_TRANSFORM_INTERSECT_SCALEY_UP;
}
-
+
return 0;
}
@@ -1156,13 +1343,13 @@ static bool widget_rect_transform_get_property(wmWidget *widget, const int slot,
fprintf(stderr, "Rect Transform widget offset not only be bound to array float property");
return false;
}
-
RNA_property_float_get_array(&widget->ptr[slot], widget->props[slot], value);
}
else if (slot == RECT_TRANSFORM_SLOT_SCALE) {
RectTransformWidget *cage = (RectTransformWidget *)widget;
- if (cage->style & WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM)
+ if (cage->style & WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) {
*value = RNA_property_float_get(&widget->ptr[slot], widget->props[slot]);
+ }
else {
if (RNA_property_array_length(&widget->ptr[slot], widget->props[slot]) != 2) {
fprintf(stderr, "Rect Transform widget scale not only be bound to array float property");
@@ -1172,7 +1359,7 @@ static bool widget_rect_transform_get_property(wmWidget *widget, const int slot,
}
}
}
-
+
return true;
}
@@ -1180,45 +1367,45 @@ static int widget_rect_transform_invoke(bContext *UNUSED(C), const wmEvent *even
{
RectTransformWidget *cage = (RectTransformWidget *) widget;
RectTransformInteraction *data = MEM_callocN(sizeof (RectTransformInteraction), "cage_interaction");
-
- copy_v2_v2(data->orig_offset, cage->offset);
+
+ copy_v2_v2(data->orig_offset, widget->offset);
copy_v2_v2(data->orig_scale, cage->scale);
-
+
data->orig_mouse[0] = event->mval[0];
data->orig_mouse[1] = event->mval[1];
-
+
widget->interaction_data = data;
-
+
return OPERATOR_RUNNING_MODAL;
}
static int widget_rect_transform_handler(bContext *C, const wmEvent *event, wmWidget *widget)
{
- RectTransformWidget *cage = (RectTransformWidget *) widget;
+ RectTransformWidget *cage = (RectTransformWidget *)widget;
RectTransformInteraction *data = widget->interaction_data;
ARegion *ar = CTX_wm_region(C);
float valuex, valuey;
/* needed here as well in case clamping occurs */
- const float orig_ofx = cage->offset[0], orig_ofy = cage->offset[1];
-
+ const float orig_ofx = widget->offset[0], orig_ofy = widget->offset[1];
+
valuex = (event->mval[0] - data->orig_mouse[0]);
valuey = (event->mval[1] - data->orig_mouse[1]);
-
+
if (widget->highlighted_part == WIDGET_RECT_TRANSFORM_INTERSECT_TRANSLATE) {
- cage->offset[0] = data->orig_offset[0] + valuex;
- cage->offset[1] = data->orig_offset[1] + valuey;
+ widget->offset[0] = data->orig_offset[0] + valuex;
+ widget->offset[1] = data->orig_offset[1] + valuey;
}
else if (widget->highlighted_part == WIDGET_RECT_TRANSFORM_INTERSECT_SCALEX_LEFT) {
- cage->offset[0] = data->orig_offset[0] + valuex / 2.0;
+ widget->offset[0] = data->orig_offset[0] + valuex / 2.0;
cage->scale[0] = (cage->w * data->orig_scale[0] - valuex) / cage->w;
}
else if (widget->highlighted_part == WIDGET_RECT_TRANSFORM_INTERSECT_SCALEX_RIGHT) {
- cage->offset[0] = data->orig_offset[0] + valuex / 2.0;
+ widget->offset[0] = data->orig_offset[0] + valuex / 2.0;
cage->scale[0] = (cage->w * data->orig_scale[0] + valuex) / cage->w;
}
else if (widget->highlighted_part == WIDGET_RECT_TRANSFORM_INTERSECT_SCALEY_DOWN) {
- cage->offset[1] = data->orig_offset[1] + valuey / 2.0;
-
+ widget->offset[1] = data->orig_offset[1] + valuey / 2.0;
+
if (cage->style & WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) {
cage->scale[0] = (cage->h * data->orig_scale[0] - valuey) / cage->h;
}
@@ -1227,8 +1414,8 @@ static int widget_rect_transform_handler(bContext *C, const wmEvent *event, wmWi
}
}
else if (widget->highlighted_part == WIDGET_RECT_TRANSFORM_INTERSECT_SCALEY_UP) {
- cage->offset[1] = data->orig_offset[1] + valuey / 2.0;
-
+ widget->offset[1] = data->orig_offset[1] + valuey / 2.0;
+
if (cage->style & WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) {
cage->scale[0] = (cage->h * data->orig_scale[0] + valuey) / cage->h;
}
@@ -1236,33 +1423,33 @@ static int widget_rect_transform_handler(bContext *C, const wmEvent *event, wmWi
cage->scale[1] = (cage->h * data->orig_scale[1] + valuey) / cage->h;
}
}
-
+
/* clamping - make sure widget is at least 5 pixels wide */
if (cage->style & WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) {
if (cage->scale[0] < WIDGET_RECT_MIN_WIDTH / cage->h ||
cage->scale[0] < WIDGET_RECT_MIN_WIDTH / cage->w)
{
cage->scale[0] = max_ff(WIDGET_RECT_MIN_WIDTH / cage->h, WIDGET_RECT_MIN_WIDTH / cage->w);
- cage->offset[0] = orig_ofx;
- cage->offset[1] = orig_ofy;
+ widget->offset[0] = orig_ofx;
+ widget->offset[1] = orig_ofy;
}
}
else {
if (cage->scale[0] < WIDGET_RECT_MIN_WIDTH / cage->w) {
cage->scale[0] = WIDGET_RECT_MIN_WIDTH / cage->w;
- cage->offset[0] = orig_ofx;
+ widget->offset[0] = orig_ofx;
}
if (cage->scale[1] < WIDGET_RECT_MIN_WIDTH / cage->h) {
cage->scale[1] = WIDGET_RECT_MIN_WIDTH / cage->h;
- cage->offset[1] = orig_ofy;
+ widget->offset[1] = orig_ofy;
}
}
-
+
if (widget->props[RECT_TRANSFORM_SLOT_OFFSET]) {
PointerRNA ptr = widget->ptr[RECT_TRANSFORM_SLOT_OFFSET];
PropertyRNA *prop = widget->props[RECT_TRANSFORM_SLOT_OFFSET];
- RNA_property_float_set_array(&ptr, prop, cage->offset);
+ RNA_property_float_set_array(&ptr, prop, widget->offset);
RNA_property_update(C, &ptr, prop);
}
@@ -1278,23 +1465,54 @@ static int widget_rect_transform_handler(bContext *C, const wmEvent *event, wmWi
}
RNA_property_update(C, &ptr, prop);
}
-
+
/* tag the region for redraw */
ED_region_tag_redraw(ar);
-
+
return OPERATOR_PASS_THROUGH;
}
static void widget_rect_transform_bind_to_prop(wmWidget *widget, const int slot)
{
RectTransformWidget *cage = (RectTransformWidget *) widget;
-
+
if (slot == RECT_TRANSFORM_SLOT_OFFSET)
- widget_rect_transform_get_property(widget, RECT_TRANSFORM_SLOT_OFFSET, cage->offset);
+ widget_rect_transform_get_property(widget, RECT_TRANSFORM_SLOT_OFFSET, widget->offset);
if (slot == RECT_TRANSFORM_SLOT_SCALE)
widget_rect_transform_get_property(widget, RECT_TRANSFORM_SLOT_SCALE, cage->scale);
}
+static void widget_rect_transform_cancel(bContext *C, wmWidget *widget)
+{
+ RectTransformWidget *cage = (RectTransformWidget *) widget;
+ RectTransformInteraction *data = widget->interaction_data;
+
+ /* reset properties */
+ if (widget->props[RECT_TRANSFORM_SLOT_OFFSET]) {
+ PointerRNA ptr = widget->ptr[RECT_TRANSFORM_SLOT_OFFSET];
+ PropertyRNA *prop = widget->props[RECT_TRANSFORM_SLOT_OFFSET];
+
+ RNA_property_float_set_array(&ptr, prop, data->orig_offset);
+ RNA_property_update(C, &ptr, prop);
+ }
+ if (widget->props[RECT_TRANSFORM_SLOT_SCALE]) {
+ PointerRNA ptr = widget->ptr[RECT_TRANSFORM_SLOT_SCALE];
+ PropertyRNA *prop = widget->props[RECT_TRANSFORM_SLOT_SCALE];
+
+ if (cage->style & WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM){
+ RNA_property_float_set(&ptr, prop, data->orig_scale[0]);
+ }
+ else {
+ RNA_property_float_set_array(&ptr, prop, data->orig_scale);
+ }
+ RNA_property_update(C, &ptr, prop);
+ }
+}
+
+/** \name Cage Widget API
+ *
+ * \{ */
+
wmWidget *WIDGET_rect_transform_new(
wmWidgetGroup *wgroup, const char *name, const int style,
const float width, const float height)
@@ -1305,27 +1523,33 @@ wmWidget *WIDGET_rect_transform_new(
cage->widget.invoke = widget_rect_transform_invoke;
cage->widget.bind_to_prop = widget_rect_transform_bind_to_prop;
cage->widget.handler = widget_rect_transform_handler;
- cage->widget.intersect = widget_rect_tranfrorm_intersect;
- cage->widget.get_cursor = widget_rect_tranfrorm_get_cursor;
+ cage->widget.intersect = widget_rect_transform_intersect;
+ cage->widget.cancel = widget_rect_transform_cancel;
+ cage->widget.get_cursor = widget_rect_transform_get_cursor;
cage->widget.max_prop = 2;
+ cage->widget.flag |= WM_WIDGET_DRAW_ACTIVE;
cage->scale[0] = cage->scale[1] = 1.0f;
cage->style = style;
cage->w = width;
cage->h = height;
-
+
wm_widget_register(wgroup, &cage->widget, name);
-
+
return (wmWidget *)cage;
}
-void WIDGET_rect_transform_set_offset(wmWidget *widget, const float offset[2])
-{
- RectTransformWidget *cage = (RectTransformWidget *)widget;
+/** \} */ // Cage Widget API
+/** \} */ // Cage Widget
- copy_v2_v2(cage->offset, offset);
-}
-/********* Facemap widget ************/
+/** \name Facemap Widget
+ *
+ * 3D Widget
+ *
+ * \brief Widget representing shape of a face map.
+ * Currently no own handling, use with operator only.
+ *
+ * \{ */
typedef struct FacemapWidget {
wmWidget widget;
@@ -1340,7 +1564,10 @@ static void widget_facemap_draw(const bContext *C, wmWidget *widget)
FacemapWidget *fmap_widget = (FacemapWidget *)widget;
glPushMatrix();
glMultMatrixf(fmap_widget->ob->obmat);
+ glTranslate3fv(widget->offset);
+ glEnable(GL_MULTISAMPLE_ARB);
ED_draw_object_facemap(CTX_data_scene(C), fmap_widget->ob, fmap_widget->facemap);
+ glDisable(GL_MULTISAMPLE_ARB);
glPopMatrix();
}
@@ -1350,29 +1577,50 @@ static void widget_facemap_render_3d_intersect(const bContext *C, wmWidget *widg
widget_facemap_draw(C, widget);
}
+#if 0
+static int widget_facemap_invoke(bContext *UNUSED(C), const wmEvent *event, wmWidget *widget)
+{
+ return OPERATOR_PASS_THROUGH;
+}
+
+static int widget_facemap_handler(bContext *C, const wmEvent *event, wmWidget *widget)
+{
+ return OPERATOR_PASS_THROUGH;
+}
+#endif
-struct wmWidget *WIDGET_facemap_new(
+/** \name Facemap Widget API
+ *
+ * \{ */
+
+wmWidget *WIDGET_facemap_new(
wmWidgetGroup *wgroup, const char *name, const int style,
Object *ob, const int facemap)
{
FacemapWidget *fmap_widget = MEM_callocN(sizeof(FacemapWidget), "CageWidget");
fmap_widget->widget.draw = widget_facemap_draw;
-// fmap_widget->widget.invoke = NULL;
+// fmap_widget->widget.invoke = widget_facemap_invoke;
// fmap_widget->widget.bind_to_prop = NULL;
-// fmap_widget->widget.handler = NULL;
+// fmap_widget->widget.handler = widget_facemap_handler;
fmap_widget->widget.render_3d_intersection = widget_facemap_render_3d_intersect;
+ fmap_widget->widget.flag |= WM_WIDGET_SELECTABLE ;
fmap_widget->ob = ob;
fmap_widget->facemap = facemap;
fmap_widget->style = style;
-
+
wm_widget_register(wgroup, &fmap_widget->widget, name);
-
+
return (wmWidget *)fmap_widget;
}
+/** \} */ // Facemap Widget API
+/** \} */ // Facemap Widget
+
+
+/* -------------------------------------------------------------------- */
void fix_linking_widget_lib(void)
{
- (void) 0;
+ (void)0;
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 0f0e6c9b771..b0acc3c0f1e 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -5328,6 +5328,12 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_previews_ensure);
WM_operatortype_append(WM_OT_previews_clear);
WM_operatortype_append(WM_OT_doc_view_manual_ui_context);
+
+ /* widgets */
+ WM_operatortype_append(WIDGETGROUP_OT_widget_set_active);
+ WM_operatortype_append(WIDGETGROUP_OT_widget_set_select);
+ WM_operatortype_append(WIDGETGROUP_OT_widget_tweak);
+ WM_operatortype_append(WIDGETGROUP_OT_widget_tweak_cancel);
}
/* circleselect-like modal operators */
diff --git a/source/blender/windowmanager/intern/wm_widgets.c b/source/blender/windowmanager/intern/wm_widgets.c
index b32fa7b78e0..613d20c14f8 100644
--- a/source/blender/windowmanager/intern/wm_widgets.c
+++ b/source/blender/windowmanager/intern/wm_widgets.c
@@ -15,8 +15,7 @@
* 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) 2007 Blender Foundation but based
- * on ghostwinlay.c (C) 2001-2002 by NaN Holding BV
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
* All rights reserved.
*
* Contributor(s): Blender Foundation, 2008
@@ -70,6 +69,7 @@
#include "GPU_select.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "BPY_extern.h"
/**
@@ -101,60 +101,73 @@ static ListBase widgetmaptypes = {NULL, NULL};
wmWidgetGroupType *WM_widgetgrouptype_new(
int (*poll)(const bContext *C, wmWidgetGroupType *),
void (*create)(const bContext *, wmWidgetGroup *),
- const Main *bmain, const char *mapidname,
+ wmKeyMap *(*keymap_init)(wmKeyConfig *, const char *),
+ const Main *bmain, const char *mapidname, const char *name,
const short spaceid, const short regionid, const bool is_3d)
{
- bScreen *sc;
wmWidgetMapType *wmaptype = WM_widgetmaptype_find(mapidname, spaceid, regionid, is_3d, false);
wmWidgetGroupType *wgrouptype;
-
+ bScreen *sc;
+
if (!wmaptype) {
fprintf(stderr, "widgetgrouptype creation: widgetmap type does not exist");
return NULL;
}
-
+
wgrouptype = MEM_callocN(sizeof(wmWidgetGroupType), "widgetgroup");
-
+
wgrouptype->poll = poll;
wgrouptype->create = create;
+ wgrouptype->keymap_init = keymap_init;
wgrouptype->spaceid = spaceid;
wgrouptype->regionid = regionid;
wgrouptype->is_3d = is_3d;
- BLI_strncpy(wgrouptype->mapidname, mapidname, 64);
+ BLI_strncpy(wgrouptype->name, name, MAX_NAME);
+ BLI_strncpy(wgrouptype->mapidname, mapidname, MAX_NAME);
/* add the type for future created areas of the same type */
BLI_addtail(&wmaptype->widgetgrouptypes, wgrouptype);
-
- /* now create a widget for all existing areas. (main is missing when we create new areas so not needed) */
- if (bmain) {
- for (sc = bmain->screen.first; sc; sc = sc->id.next) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
-
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- ARegion *ar;
- ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
-
- for (ar = lb->first; ar; ar = ar->next) {
- wmWidgetMap *wmap;
- for (wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) {
- if (wmap->type == wmaptype) {
- wmWidgetGroup *wgroup = MEM_callocN(sizeof(wmWidgetGroup), "widgetgroup");
- wgroup->type = wgrouptype;
-
- /* just add here, drawing will occur on next update */
- BLI_addtail(&wmap->widgetgroups, wgroup);
- wm_widgetmap_set_highlighted_widget(wmap, NULL, NULL, 0);
- ED_region_tag_redraw(ar);
- }
+
+ /* Main is missing on startup when we create new areas.
+ * So this is only called for widgets initialized on runtime */
+ if (!bmain)
+ return wgrouptype;
+
+
+ /* init keymap - on startup there's an extra call to init keymaps for 'permanent' widget-groups */
+ wm_widgetgrouptype_keymap_init(wgrouptype, ((wmWindowManager *)bmain->wm.first)->defaultconf);
+
+ /* now create a widget for all existing areas */
+ for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ ARegion *ar;
+ ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+
+ for (ar = lb->first; ar; ar = ar->next) {
+ wmWidgetMap *wmap;
+
+ for (wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) {
+ if (wmap->type == wmaptype) {
+ wmWidgetGroup *wgroup = MEM_callocN(sizeof(wmWidgetGroup), "widgetgroup");
+
+ wgroup->type = wgrouptype;
+
+ /* just add here, drawing will occur on next update */
+ BLI_addtail(&wmap->widgetgroups, wgroup);
+ wm_widgetmap_set_highlighted_widget(wmap, NULL, NULL, 0);
+ ED_region_tag_redraw(ar);
}
}
}
}
}
}
-
+
return wgrouptype;
}
@@ -164,9 +177,9 @@ wmWidget *WM_widget_new(void (*draw)(const bContext *C, wmWidget *customdata),
int (*handler)(bContext *C, const wmEvent *event, wmWidget *widget))
{
wmWidget *widget;
-
+
widget = MEM_callocN(sizeof(wmWidget), "widget");
-
+
widget->draw = draw;
widget->handler = handler;
widget->intersect = intersect;
@@ -175,50 +188,6 @@ wmWidget *WM_widget_new(void (*draw)(const bContext *C, wmWidget *customdata),
return widget;
}
-void WM_widget_property(wmWidget *widget, const int slot, PointerRNA *ptr, const char *propname)
-{
- if (slot < 0 || slot >= widget->max_prop) {
- fprintf(stderr, "invalid index %d when binding property for widget type %s\n", slot, widget->idname);
- return;
- }
-
- /* if widget evokes an operator we cannot use it for property manipulation */
- widget->opname = NULL;
- widget->ptr[slot] = *ptr;
- widget->props[slot] = RNA_struct_find_property(ptr, propname);
-
- if (widget->bind_to_prop)
- widget->bind_to_prop(widget, slot);
-}
-
-PointerRNA *WM_widget_operator(wmWidget *widget, const char *opname)
-{
- wmOperatorType *ot = WM_operatortype_find(opname, 0);
-
- if (ot) {
- widget->opname = opname;
-
- WM_operator_properties_create_ptr(&widget->opptr, ot);
-
- return &widget->opptr;
- }
- else {
- fprintf(stderr, "Error binding operator to widget: operator %s not found!\n", opname);
- }
-
- return NULL;
-}
-
-void WM_widgetgroup_customdata_set(wmWidgetGroup *wgroup, void *data)
-{
- wgroup->customdata = data;
-}
-
-void *WM_widgetgroup_customdata(const wmWidgetGroup *wgroup)
-{
- return wgroup->customdata;
-}
-
static void wm_widget_delete(ListBase *widgetlist, wmWidget *widget)
{
@@ -228,7 +197,7 @@ static void wm_widget_delete(ListBase *widgetlist, wmWidget *widget)
MEM_freeN(widget->props);
MEM_freeN(widget->ptr);
-
+
BLI_freelinkN(widgetlist, widget);
}
@@ -239,8 +208,6 @@ static void widget_calculate_scale(wmWidget *widget, const bContext *C)
float scale = 1.0f;
if (rv3d && (U.tw_flag & V3D_3D_WIDGETS) == 0 && (widget->flag & WM_WIDGET_SCALE_3D)) {
- ED_view3d_update_viewmat(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), NULL, NULL);
-
if (widget->get_final_position) {
float position[3];
@@ -255,7 +222,22 @@ static void widget_calculate_scale(wmWidget *widget, const bContext *C)
widget->scale = scale * widget->user_scale;
}
-static bool widgets_compare(const wmWidget *a, const wmWidget *b)
+/**
+ * Initialize keymaps for all existing widget-groups
+ */
+void wm_widgets_keymap(wmKeyConfig *keyconf)
+{
+ wmWidgetMapType *wmaptype;
+ wmWidgetGroupType *wgrouptype;
+
+ for (wmaptype = widgetmaptypes.first; wmaptype; wmaptype = wmaptype->next) {
+ for (wgrouptype = wmaptype->widgetgrouptypes.first; wgrouptype; wgrouptype = wgrouptype->next) {
+ wm_widgetgrouptype_keymap_init(wgrouptype, keyconf);
+ }
+ }
+}
+
+BLI_INLINE bool widgets_compare(const wmWidget *a, const wmWidget *b)
{
return STREQ(a->idname, b->idname);
}
@@ -276,16 +258,18 @@ void WM_widgets_update(const bContext *C, wmWidgetMap *wmap)
wmWidgetGroup *wgroup;
for (wgroup = wmap->widgetgroups.first; wgroup; wgroup = wgroup->next) {
- if (!wgroup->type->poll || wgroup->type->poll(C, wgroup->type))
- {
+ if (!wgroup->type->poll || wgroup->type->poll(C, wgroup->type)) {
wmWidget *highlighted = NULL;
/* first delete and recreate the widgets */
for (widget = wgroup->widgets.first; widget;) {
wmWidget *widget_next = widget->next;
+ if (widget == wmap->selected_widget) {
+ /* skip */
+ }
/* do not delete the highlighted widget, instead keep it to compare with the new one */
- if (widget->flag & WM_WIDGET_HIGHLIGHT) {
+ else if (widget->flag & WM_WIDGET_HIGHLIGHT) {
highlighted = widget;
BLI_remlink(&wgroup->widgets, widget);
widget->next = widget->prev = NULL;
@@ -356,17 +340,18 @@ void WM_widgets_draw(const bContext *C, const wmWidgetMap *wmap, const bool in_s
widget = wmap->active_widget;
- if (widget && in_scene == ((widget->flag & WM_WIDGET_SCENE_DEPTH)!= 0)) {
- /* notice that we don't update the widgetgroup, widget is now on its own, it should have all
- * relevant data to update itself */
- widget->draw(C, widget);
+ if (widget && in_scene == ((widget->flag & WM_WIDGET_SCENE_DEPTH) != 0)) {
+ if (widget->flag & WM_WIDGET_DRAW_ACTIVE) {
+ /* notice that we don't update the widgetgroup, widget is now on
+ * its own, it should have all relevant data to update itself */
+ widget->draw(C, widget);
+ }
}
else if (wmap->widgetgroups.first) {
wmWidgetGroup *wgroup;
-
+
for (wgroup = wmap->widgetgroups.first; wgroup; wgroup = wgroup->next) {
- if (!wgroup->type->poll || wgroup->type->poll(C, wgroup->type))
- {
+ if (!wgroup->type->poll || wgroup->type->poll(C, wgroup->type)) {
for (widget = wgroup->widgets.first; widget; widget = widget->next) {
if ((widget->flag & WM_WIDGET_HIDDEN) == 0 &&
(!(widget->flag & WM_WIDGET_DRAW_HOVER) || (widget->flag & WM_WIDGET_HIGHLIGHT)) &&
@@ -379,6 +364,13 @@ void WM_widgets_draw(const bContext *C, const wmWidgetMap *wmap, const bool in_s
}
}
+ /* draw selected widgets last */
+ if ((widget = wmap->selected_widget) && in_scene == ((widget->flag & WM_WIDGET_SCENE_DEPTH) != 0)) {
+ /* notice that we don't update the widgetgroup, widget is now on
+ * its own, it should have all relevant data to update itself */
+ widget->draw(C, widget);
+ }
+
if (use_lighting)
glPopAttrib();
}
@@ -387,10 +379,10 @@ void WM_event_add_area_widgetmap_handlers(ARegion *ar)
{
wmWidgetMap *wmap;
wmEventHandler *handler;
-
+
for (wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) {
handler = MEM_callocN(sizeof(wmEventHandler), "widget handler");
-
+
handler->widgetmap = wmap;
BLI_addtail(&ar->handlers, handler);
}
@@ -411,7 +403,7 @@ void WM_modal_handler_attach_widgetgroup(
wmWidgetMap *wmap;
for (wmap = handler->op_region->widgetmaps.first; wmap; wmap = wmap->next) {
wmWidgetMapType *wmaptype = wmap->type;
-
+
if (wmaptype->spaceid == wgrouptype->spaceid && wmaptype->regionid == wgrouptype->regionid) {
handler->widgetmap = wmap;
}
@@ -435,6 +427,21 @@ static void widget_unique_idname_set(wmWidgetGroup *wgroup, wmWidget *widget, co
}
/**
+ * Search for an active widget in region \a ar
+ */
+static wmWidget *widget_find_active_in_region(const ARegion *ar, wmWidgetMap **r_wmap)
+{
+ for (*r_wmap = ar->widgetmaps.first; *r_wmap; *r_wmap = (*r_wmap)->next) {
+ if ((*r_wmap)->active_widget) {
+ return (*r_wmap)->active_widget;
+ }
+ }
+
+ *r_wmap = NULL;
+ return NULL;
+}
+
+/**
* Register \a widget
*
* \param name name used to create a unique idname for \a widget in \a wgroup
@@ -456,60 +463,70 @@ bool wm_widget_register(wmWidgetGroup *wgroup, wmWidget *widget, const char *nam
if (widget->max_prop == 0) {
widget->max_prop = 1;
}
-
+
widget->props = MEM_callocN(sizeof(PropertyRNA *) * widget->max_prop, "widget->props");
widget->ptr = MEM_callocN(sizeof(PointerRNA) * widget->max_prop, "widget->ptr");
-
+
+ widget->wgroup = wgroup;
+
BLI_addtail(&wgroup->widgets, widget);
return true;
}
-void WM_widget_set_origin(wmWidget *widget, const float origin[3])
+void WM_widget_set_property(wmWidget *widget, const int slot, PointerRNA *ptr, const char *propname)
{
- copy_v3_v3(widget->origin, origin);
+ if (slot < 0 || slot >= widget->max_prop) {
+ fprintf(stderr, "invalid index %d when binding property for widget type %s\n", slot, widget->idname);
+ return;
+ }
+
+ /* if widget evokes an operator we cannot use it for property manipulation */
+ widget->opname = NULL;
+ widget->ptr[slot] = *ptr;
+ widget->props[slot] = RNA_struct_find_property(ptr, propname);
+
+ if (widget->bind_to_prop)
+ widget->bind_to_prop(widget, slot);
}
-void WM_widget_set_3d_scale(wmWidget *widget, const bool scale)
+PointerRNA *WM_widget_set_operator(wmWidget *widget, const char *opname)
{
- if (scale) {
- widget->flag |= WM_WIDGET_SCALE_3D;
+ wmOperatorType *ot = WM_operatortype_find(opname, 0);
+
+ if (ot) {
+ widget->opname = opname;
+
+ WM_operator_properties_create_ptr(&widget->opptr, ot);
+
+ return &widget->opptr;
}
else {
- widget->flag &= ~WM_WIDGET_SCALE_3D;
+ fprintf(stderr, "Error binding operator to widget: operator %s not found!\n", opname);
}
+
+ return NULL;
}
-void WM_widget_flag_set(wmWidget *widget, const int flag, const bool enable)
+void WM_widget_set_origin(wmWidget *widget, const float origin[3])
{
- if (enable) {
- widget->flag |= flag;
- }
- else {
- widget->flag &= ~flag;
- }
+ copy_v3_v3(widget->origin, origin);
}
-void WM_widget_set_draw_on_hover_only(wmWidget *widget, const bool draw)
+void WM_widget_set_offset(wmWidget *widget, const float offset[3])
{
- if (draw) {
- widget->flag |= WM_WIDGET_DRAW_HOVER;
- }
- else {
- widget->flag &= ~WM_WIDGET_DRAW_HOVER;
- }
+ copy_v3_v3(widget->offset, offset);
}
-void WM_widget_set_scene_depth(wmWidget *widget, const bool scene)
+void WM_widget_set_flag(wmWidget *widget, const int flag, const bool enable)
{
- if (scene) {
- widget->flag |= WM_WIDGET_SCENE_DEPTH;
+ if (enable) {
+ widget->flag |= flag;
}
else {
- widget->flag &= ~WM_WIDGET_SCENE_DEPTH;
+ widget->flag &= ~flag;
}
}
-
void WM_widget_set_scale(wmWidget *widget, const float scale)
{
widget->user_scale = scale;
@@ -524,7 +541,7 @@ void WM_widget_set_line_width(wmWidget *widget, const float line_width)
* Set widget rgba colors
*
* \param col Normal state color
- * \param col_hi Highlighted state color
+ * \param col_hi Highlighted state color
*/
void WM_widget_set_colors(wmWidget *widget, const float col[4], const float col_hi[4])
{
@@ -533,14 +550,173 @@ void WM_widget_set_colors(wmWidget *widget, const float col[4], const float col_
}
+/** \name Widget operators
+ *
+ * Basic operators for widget interaction with user configurable keymaps.
+ *
+ * \{ */
+
+static int widget_set_active_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ wmWidgetMap *wmap;
+ const bool deactivate = RNA_boolean_get(op->ptr, "deactivate");
+
+ for (wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) {
+ if (deactivate) {
+ wm_widgetmap_set_active_widget(wmap, C, event, NULL);
+
+ /* ugly hack - send widget release event */
+ ((wmEvent *)event)->type = EVT_WIDGET_RELEASED;
+ }
+ else {
+ wmWidget *widget = wmap->highlighted_widget;
+ if (widget) {
+ wm_widgetmap_set_active_widget(wmap, C, event, widget);
+ break;
+ }
+ else {
+ BLI_assert(0);
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void WIDGETGROUP_OT_widget_set_active(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Widget Activate";
+ ot->description = "Activate the currently highlighted widget";
+ ot->idname = "WIDGETGROUP_OT_widget_set_active";
+
+ /* api callbacks */
+ ot->invoke = widget_set_active_invoke;
+
+ ot->flag = OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "deactivate", 0, "Deactivate", "Deactivate currently active widget");
+}
+
+static int widget_set_select_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+{
+ ARegion *ar = CTX_wm_region(C);
+ wmWidgetMap *wmap;
+
+ for (wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) {
+ wmWidget *widget = wmap->highlighted_widget;
+ if (widget) {
+ if (widget->flag & WM_WIDGET_SELECTABLE) {
+ wm_widgetmap_set_selected_widget(C, wmap, widget);
+ }
+ break;
+ }
+ else {
+ BLI_assert(0);
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void WIDGETGROUP_OT_widget_set_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Widget Select";
+ ot->description = "Select the currently highlighted widget";
+ ot->idname = "WIDGETGROUP_OT_widget_set_select";
+
+ /* api callbacks */
+ ot->invoke = widget_set_select_invoke;
+
+ ot->flag = OPTYPE_UNDO;
+
+ /* TODO - more fancy selections are not implemented yet */
+// RNA_def_boolean(ot->srna, "deactivate", 0, "Deactivate", "Deactivate currently active widget");
+}
+
+static int widget_tweak_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ wmWidgetMap *wmap;
+ wmWidget *widget = widget_find_active_in_region(ar, &wmap);
+
+ if (!widget) {
+ BLI_assert(0);
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ /* handle widget */
+ widget->handler(C, event, widget);
+
+ /* ugly hack - send widget update event */
+ ((wmEvent *)event)->type = EVT_WIDGET_UPDATE;
+
+ return OPERATOR_FINISHED;
+}
+
+void WIDGETGROUP_OT_widget_tweak(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Widget Tweak";
+ ot->description = "Tweak the active widget";
+ ot->idname = "WIDGETGROUP_OT_widget_tweak";
+
+ /* api callbacks */
+ ot->invoke = widget_tweak_invoke;
+}
+
+static int widget_cancel_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ wmWidgetMap *wmap;
+ wmWidget *widget = widget_find_active_in_region(ar, &wmap);
+
+ if (!widget) {
+ /* don't assert(0) here, this might be called if modal handler
+ * which has widget attached uses same shortcut as widget-cancel */
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ if (widget->cancel) {
+ widget->cancel(C, widget);
+ }
+ wm_widgetmap_set_active_widget(wmap, C, event, NULL);
+
+ /* ugly hack - send widget release event */
+ ((wmEvent *)event)->type = EVT_WIDGET_RELEASED;
+
+ return OPERATOR_FINISHED;
+}
+
+void WIDGETGROUP_OT_widget_tweak_cancel(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Widget Tweak Cancel";
+ ot->description = "Cancel tweaking of active widget";
+ ot->idname = "WIDGETGROUP_OT_widget_tweak_cancel";
+
+ /* api callbacks */
+ ot->invoke = widget_cancel_invoke;
+}
+
+/** \} */ // Widget operators
+
+
wmWidgetMapType *WM_widgetmaptype_find(
const char *idname, const int spaceid, const int regionid, const bool is_3d, const bool create)
{
wmWidgetMapType *wmaptype;
for (wmaptype = widgetmaptypes.first; wmaptype; wmaptype = wmaptype->next) {
- if (wmaptype->spaceid == spaceid && wmaptype->regionid == regionid && wmaptype->is_3d == is_3d
- && strcmp(wmaptype->idname, idname) == 0) {
+ if (wmaptype->spaceid == spaceid &&
+ wmaptype->regionid == regionid &&
+ wmaptype->is_3d == is_3d &&
+ STREQ(wmaptype->idname, idname))
+ {
return wmaptype;
}
}
@@ -553,14 +729,14 @@ wmWidgetMapType *WM_widgetmaptype_find(
wmaptype->is_3d = is_3d;
BLI_strncpy(wmaptype->idname, idname, 64);
BLI_addhead(&widgetmaptypes, wmaptype);
-
+
return wmaptype;
}
void WM_widgetmaptypes_free(void)
{
wmWidgetMapType *wmaptype;
-
+
for (wmaptype = widgetmaptypes.first; wmaptype; wmaptype = wmaptype->next) {
BLI_freelistN(&wmaptype->widgetgrouptypes);
}
@@ -602,38 +778,38 @@ static int wm_widget_find_highlighted_3D_intern(
const bool do_passes = GPU_select_query_check_active();
extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, rctf *rect);
-
+
+
rect.xmin = event->mval[0] - hotspot;
rect.xmax = event->mval[0] + hotspot;
rect.ymin = event->mval[1] - hotspot;
rect.ymax = event->mval[1] + hotspot;
-
+
selrect = rect;
-
+
view3d_winmatrix_set(ar, v3d, &rect);
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
-
+
if (do_passes)
GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
else
GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_ALL, 0);
/* do the drawing */
widget_find_active_3D_loop(C, visible_widgets);
-
+
hits = GPU_select_end();
-
+
if (do_passes) {
GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
widget_find_active_3D_loop(C, visible_widgets);
GPU_select_end();
}
-
+
view3d_winmatrix_set(ar, v3d, NULL);
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
if (hits == 1) {
return buffer[3];
-
}
/* find the widget the value belongs to */
else if (hits > 1) {
@@ -655,6 +831,7 @@ static int wm_widget_find_highlighted_3D_intern(
return minval;
}
+
return -1;
}
@@ -686,24 +863,24 @@ wmWidget *wm_widget_find_highlighted_3D(wmWidgetMap *wmap, bContext *C, const wm
*part = 0;
/* set up view matrices */
view3d_operator_needs_opengl(C);
-
+
ret = wm_widget_find_highlighted_3D_intern(&visible_widgets, C, event, 0.5f * hotspot);
-
+
if (ret != -1) {
LinkData *link;
int retsec;
retsec = wm_widget_find_highlighted_3D_intern(&visible_widgets, C, event, 0.2f * hotspot);
-
+
if (retsec != -1)
ret = retsec;
-
+
link = BLI_findlink(&visible_widgets, ret >> 8);
*part = ret & 255;
result = link->data;
}
BLI_freelistN(&visible_widgets);
-
+
return result;
}
@@ -735,7 +912,7 @@ bool WM_widgetmap_cursor_set(const wmWidgetMap *wmap, wmWindow *win)
return true;
}
}
-
+
return false;
}
@@ -746,23 +923,27 @@ void wm_widgetmap_set_highlighted_widget(wmWidgetMap *wmap, bContext *C, wmWidge
wmap->highlighted_widget->flag &= ~WM_WIDGET_HIGHLIGHT;
wmap->highlighted_widget->highlighted_part = 0;
}
-
+
wmap->highlighted_widget = widget;
-
+
if (widget) {
widget->flag |= WM_WIDGET_HIGHLIGHT;
widget->highlighted_part = part;
-
+ wmap->activegroup = widget->wgroup;
+
if (C && widget->get_cursor) {
wmWindow *win = CTX_wm_window(C);
WM_cursor_set(win, widget->get_cursor(widget));
}
}
- else if (C) {
- wmWindow *win = CTX_wm_window(C);
- WM_cursor_set(win, CURSOR_STD);
+ else {
+ wmap->activegroup = NULL;
+ if (C) {
+ wmWindow *win = CTX_wm_window(C);
+ WM_cursor_set(win, CURSOR_STD);
+ }
}
-
+
/* tag the region for redraw */
if (C) {
ARegion *ar = CTX_wm_region(C);
@@ -778,35 +959,23 @@ wmWidget *wm_widgetmap_get_highlighted_widget(wmWidgetMap *wmap)
void wm_widgetmap_set_active_widget(
wmWidgetMap *wmap, bContext *C,
- wmEvent *event, wmWidget *widget,
- const bool call_op)
+ const wmEvent *event, wmWidget *widget)
{
if (widget) {
- if (call_op) {
+ if (widget->opname) {
wmOperatorType *ot;
- const bool has_custom_op = widget->opname != NULL;
- const char *opname = has_custom_op ? widget->opname : "WM_OT_widget_tweak";
- ot = WM_operatortype_find(opname, 0);
+ ot = WM_operatortype_find(widget->opname, 0);
if (ot) {
/* first activate the widget itself */
if (widget->invoke && widget->handler) {
widget->flag |= WM_WIDGET_ACTIVE;
widget->invoke(C, event, widget);
- wmap->active_widget = widget;
}
+ wmap->active_widget = widget;
- /* if operator runs modal, we will need to activate the current widgetmap on the operator handler,
- * so it can process events first, then pass them on to the operator */
- if (WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &widget->opptr) == OPERATOR_RUNNING_MODAL) {
- /* check if operator added a a modal event handler */
- wmEventHandler *handler = CTX_wm_window(C)->modalhandlers.first;
-
- if (has_custom_op == false && handler && handler->op && handler->op->type == ot) {
- handler->widgetmap = wmap;
- }
- }
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &widget->opptr);
/* we failed to hook the widget to the operator handler or operator was cancelled, return */
if (!wmap->active_widget) {
@@ -846,7 +1015,7 @@ void wm_widgetmap_set_active_widget(
}
}
wmap->active_widget = NULL;
-
+
if (C) {
ARegion *ar = CTX_wm_region(C);
ED_region_tag_redraw(ar);
@@ -855,6 +1024,33 @@ void wm_widgetmap_set_active_widget(
}
}
+wmWidget *wm_widgetmap_get_selected_widget(wmWidgetMap *wmap)
+{
+ return wmap->selected_widget;
+}
+
+void wm_widgetmap_set_selected_widget(bContext *C, wmWidgetMap *wmap, wmWidget *widget)
+{
+ if (widget) {
+ wmap->selected_widget = widget;
+ widget->flag |= WM_WIDGET_SELECTED;
+ wm_widgetmap_set_highlighted_widget(wmap, C, NULL, wmap->highlighted_widget->highlighted_part);
+ }
+ else {
+ widget = wmap->selected_widget;
+ if (widget) {
+ wmap->selected_widget = NULL;
+ widget->flag &= ~WM_WIDGET_SELECTED;
+ }
+ }
+
+ /* tag the region for redraw */
+ if (C) {
+ ARegion *ar = CTX_wm_region(C);
+ ED_region_tag_redraw(ar);
+ }
+}
+
void wm_widgetmap_handler_context(bContext *C, wmEventHandler *handler)
{
bScreen *screen = CTX_wm_screen(C);
@@ -915,7 +1111,7 @@ void wm_widget_handler_modal_update(bContext *C, wmEvent *event, wmEventHandler
}
/* operator not running anymore */
else {
- wm_widgetmap_set_active_widget(wmap, C, event, NULL, false);
+ wm_widgetmap_set_active_widget(wmap, C, event, NULL);
}
/* restore the area */
@@ -959,7 +1155,7 @@ void WM_widgetmap_delete(wmWidgetMap *wmap)
for (wgroup = wmap->widgetgroups.first; wgroup; wgroup = wgroup->next) {
wmWidget *widget;
-
+
for (widget = wgroup->widgets.first; widget;) {
wmWidget *widget_next = widget->next;
wm_widget_delete(&wgroup->widgets, widget);
@@ -981,7 +1177,7 @@ static void wm_widgetgroup_free(bContext *C, wmWidgetMap *wmap, wmWidgetGroup *w
wm_widgetmap_set_highlighted_widget(wmap, C, NULL, 0);
}
if (widget->flag & WM_WIDGET_ACTIVE) {
- wm_widgetmap_set_active_widget(wmap, C, NULL, NULL, false);
+ wm_widgetmap_set_active_widget(wmap, C, NULL, NULL);
}
wm_widget_delete(&wgroup->widgets, widget);
widget = widget_next;
@@ -1004,6 +1200,34 @@ static void wm_widgetgroup_free(bContext *C, wmWidgetMap *wmap, wmWidgetGroup *w
MEM_freeN(wgroup);
}
+/**
+ * Common default keymap for widget groups
+ */
+wmKeyMap *WM_widgetgroup_keymap_common(wmKeyConfig *config, const char *wgroupname)
+{
+ wmKeyMap *km = WM_keymap_find(config, wgroupname, 0, 0);
+ wmKeyMapItem *kmi;
+
+ kmi = WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_set_active", ACTIONMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "deactivate", false);
+ kmi = WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_set_active", ACTIONMOUSE, KM_RELEASE, 0, 0);
+ RNA_boolean_set(kmi->ptr, "deactivate", true);
+
+ WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_tweak", MOUSEMOVE, KM_ANY, KM_ANY, 0);
+
+ WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_tweak_cancel", RIGHTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_tweak_cancel", ESCKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_set_select", SELECTMOUSE, KM_PRESS, 0, 0);
+
+ return km;
+}
+
+void wm_widgetgrouptype_keymap_init(wmWidgetGroupType *wgrouptype, wmKeyConfig *keyconf)
+{
+ wgrouptype->keymap = wgrouptype->keymap_init(keyconf, wgrouptype->name);
+}
+
void WM_widgetgrouptype_unregister(bContext *C, Main *bmain, wmWidgetGroupType *wgrouptype)
{
bScreen *sc;
@@ -1036,8 +1260,10 @@ void WM_widgetgrouptype_unregister(bContext *C, Main *bmain, wmWidgetGroupType *
}
wmaptype = WM_widgetmaptype_find(wgrouptype->mapidname, wgrouptype->spaceid, wgrouptype->regionid, wgrouptype->is_3d, false);
+
BLI_remlink(&wmaptype->widgetgrouptypes, wgrouptype);
wgrouptype->prev = wgrouptype->next = NULL;
+
MEM_freeN(wgrouptype);
}
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index c5a1d5f7f6d..f2bed99815d 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -49,12 +49,15 @@ typedef struct wmPaintCursor {
void (*draw)(bContext *C, int, int, void *customdata);
} wmPaintCursor;
-/* widgets are set per screen/area/region by registering them on widgetmaps */
+/* widgets are set per region by registering them on widgetmaps */
typedef struct wmWidget {
struct wmWidget *next, *prev;
-
+
char idname[MAX_NAME + 4]; /* + 4 for unique '.001', '.002', etc suffix */
+ /* pointer back to parent widget group */
+ wmWidgetGroup *wgroup;
+
/* draw widget */
void (*draw)(const struct bContext *C, struct wmWidget *widget);
/* determine if the mouse intersects with the widget. The calculation should be done in the callback itself */
@@ -76,14 +79,19 @@ typedef struct wmWidget {
/* activate a widget state when the user clicks on it */
int (*invoke)(struct bContext *C, const struct wmEvent *event, struct wmWidget *widget);
+ /* called after canceling widget handling - used to reset property */
+ void (*cancel)(struct bContext *C, struct wmWidget *widget);
+
int (*get_cursor)(struct wmWidget *widget);
-
- int flag; /* flags set by drawing and interaction, such as highlighting */
+
+ int flag; /* flags set by drawing and interaction, such as highlighting */
unsigned char highlighted_part;
/* center of widget in space, 2d or 3d */
float origin[3];
+ /* custom offset from origin */
+ float offset[3];
/* runtime property, set the scale while drawing on the viewport */
float scale;
@@ -104,26 +112,16 @@ typedef struct wmWidget {
const char *opname;
/* operator properties if widget spawns and controls an operator, or owner pointer if widget spawns and controls a property */
- struct PointerRNA opptr;
+ PointerRNA opptr;
/* maximum number of properties attached to the widget */
int max_prop;
-
+
/* arrays of properties attached to various widget parameters. As the widget is interacted with, those properties get updated */
- struct PointerRNA *ptr;
- struct PropertyRNA **props;
+ PointerRNA *ptr;
+ PropertyRNA **props;
} wmWidget;
-/* wmWidget->flag */
-enum widgetflags {
- /* states */
- WM_WIDGET_HIGHLIGHT = (1 << 0),
- WM_WIDGET_ACTIVE = (1 << 1),
- WM_WIDGET_DRAW_HOVER = (1 << 2),
- WM_WIDGET_SCALE_3D = (1 << 3),
- WM_WIDGET_SCENE_DEPTH = (1 << 4), /* widget is depth culled with scene objects*/
- WM_WIDGET_HIDDEN = (1 << 5),
-};
extern void wm_close_and_free(bContext *C, wmWindowManager *);
extern void wm_close_and_free_all(bContext *C, ListBase *);
@@ -171,8 +169,14 @@ void wm_open_init_load_ui(wmOperator *op, bool use_prefs);
void wm_open_init_use_scripts(wmOperator *op, bool use_prefs);
/* wm_widgets.c */
-bool wm_widgetmap_is_3d(const struct wmWidgetMap *wmap);
-bool wm_widget_register(struct wmWidgetGroup *wgroup, struct wmWidget *widget, const char *name);
+bool wm_widgetmap_is_3d(const wmWidgetMap *wmap);
+bool wm_widget_register(wmWidgetGroup *wgroup, wmWidget *widget, const char *name);
+void wm_widgets_keymap(wmKeyConfig *keyconf);
+
+void WIDGETGROUP_OT_widget_set_active(wmOperatorType *ot);
+void WIDGETGROUP_OT_widget_set_select(wmOperatorType *ot);
+void WIDGETGROUP_OT_widget_tweak(wmOperatorType *ot);
+void WIDGETGROUP_OT_widget_tweak_cancel(wmOperatorType *ot);
/* hack to store circle select size - campbell, must replace with nice operator memory */
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index 46ebc15e165..2d9e5dbfc54 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -104,13 +104,18 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect);
void wm_widget_handler_modal_update(bContext *C, wmEvent *event, wmEventHandler *handler);
void wm_widgetmap_handler_context(bContext *C, wmEventHandler *handler);
-struct wmWidget *wm_widget_find_highlighted_3D(struct wmWidgetMap *wmap, struct bContext *C, const struct wmEvent *event, unsigned char *part);
-wmWidget *wm_widget_find_highlighted(struct wmWidgetMap *wmap, bContext *C, const struct wmEvent *event, unsigned char *part);
-void wm_widgetmap_set_highlighted_widget(struct wmWidgetMap *wmap, struct bContext *C, struct wmWidget *widget, unsigned char part);
-struct wmWidget *wm_widgetmap_get_highlighted_widget(struct wmWidgetMap *wmap);
+void wm_widgetgrouptype_keymap_init(wmWidgetGroupType *wgrouptype, wmKeyConfig *keyconf);
-void wm_widgetmap_set_active_widget(struct wmWidgetMap *wmap, struct bContext *C, struct wmEvent *event, struct wmWidget *widget, const bool call_op);
-struct wmWidget *wm_widgetmap_get_active_widget(struct wmWidgetMap *wmap);
+wmWidget *wm_widget_find_highlighted_3D(wmWidgetMap *wmap, bContext *C, const wmEvent *event, unsigned char *part);
+wmWidget *wm_widget_find_highlighted(wmWidgetMap *wmap, bContext *C, const wmEvent *event, unsigned char *part);
+void wm_widgetmap_set_highlighted_widget(wmWidgetMap *wmap, bContext *C, wmWidget *widget, unsigned char part);
+wmWidget *wm_widgetmap_get_highlighted_widget(wmWidgetMap *wmap);
+
+void wm_widgetmap_set_active_widget(wmWidgetMap *wmap, bContext *C, const wmEvent *event, wmWidget *widget);
+wmWidget *wm_widgetmap_get_active_widget(wmWidgetMap *wmap);
+
+void wm_widgetmap_set_selected_widget(bContext *C, wmWidgetMap *wmap, wmWidget *widget);
+wmWidget *wm_widgetmap_get_selected_widget(wmWidgetMap *wmap);
#endif /* __WM_EVENT_SYSTEM_H__ */