Initially add widget files and get them compiling
Another temp_ branch :S This time for preparing custom manipulators core code for merge.
This commit is contained in:
@@ -87,6 +87,7 @@ set(SRC_DNA_INC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_vfont_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_view2d_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_view3d_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_widget_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_windowmanager_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_world_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_movieclip_types.h
|
||||
|
@@ -304,6 +304,7 @@ void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3]);
|
||||
void ortho_v3_v3(float out[3], const float v[3]);
|
||||
void ortho_v2_v2(float out[2], const float v[2]);
|
||||
void bisect_v3_v3v3v3(float r[3], const float a[3], const float b[3], const float c[3]);
|
||||
void rotate_v2_v2fl(float r[2], const float p[2], const float angle);
|
||||
void rotate_v3_v3v3fl(float v[3], const float p[3], const float axis[3], const float angle);
|
||||
void rotate_normalized_v3_v3v3fl(float out[3], const float p[3], const float axis[3], const float angle);
|
||||
|
||||
|
@@ -771,6 +771,20 @@ void ortho_v2_v2(float out[2], const float v[2])
|
||||
out[1] = v[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate a point \a p by \a angle around origin (0, 0)
|
||||
*/
|
||||
void rotate_v2_v2fl(float r[2], const float p[2], const float angle)
|
||||
{
|
||||
const float co = cosf(angle);
|
||||
const float si = sinf(angle);
|
||||
|
||||
BLI_assert(r != p);
|
||||
|
||||
r[0] = co * p[0] - si * p[1];
|
||||
r[1] = si * p[0] + co * p[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate a point \a p by \a angle around an arbitrary unit length \a axis.
|
||||
* http://local.wasp.uwa.edu.au/~pbourke/geometry/
|
||||
|
@@ -1656,6 +1656,8 @@ void init_userdef_do_versions(void)
|
||||
U.tw_size = 25; /* percentage of window size */
|
||||
U.tw_handlesize = 16; /* percentage of widget radius */
|
||||
}
|
||||
if (U.widget_scale == 0)
|
||||
U.widget_scale = 75;
|
||||
if (U.pad_rot_angle == 0.0f)
|
||||
U.pad_rot_angle = 15.0f;
|
||||
|
||||
|
@@ -264,6 +264,7 @@ typedef struct ARegion {
|
||||
ListBase ui_lists; /* uiList */
|
||||
ListBase ui_previews; /* uiPreview */
|
||||
ListBase handlers; /* wmEventHandler */
|
||||
ListBase widgetmaps; /* widgetmaps */
|
||||
ListBase panels_category; /* Panel categories runtime */
|
||||
|
||||
struct wmTimer *regiontimer; /* blend in/out */
|
||||
|
@@ -46,6 +46,7 @@
|
||||
#include "DNA_node_types.h" /* for bNodeInstanceKey */
|
||||
/* Hum ... Not really nice... but needed for spacebuts. */
|
||||
#include "DNA_view2d_types.h"
|
||||
#include "DNA_widget_types.h"
|
||||
|
||||
struct ID;
|
||||
struct Text;
|
||||
|
@@ -490,6 +490,8 @@ typedef struct UserDef {
|
||||
short tb_leftmouse, tb_rightmouse;
|
||||
struct SolidLight light[3];
|
||||
short tw_hotspot, tw_flag, tw_handlesize, tw_size;
|
||||
short widget_flag, widget_scale;
|
||||
int pad3;
|
||||
short textimeout, texcollectrate;
|
||||
short wmdrawmethod; /* removed wmpad */
|
||||
short dragthreshold;
|
||||
|
@@ -368,6 +368,8 @@ enum {
|
||||
#define V3D_USE_MANIPULATOR 1
|
||||
#define V3D_DRAW_MANIPULATOR 2
|
||||
/* #define V3D_CALC_MANIPULATOR 4 */ /*UNUSED*/
|
||||
#define V3D_3D_WIDGETS (1 << 2)
|
||||
#define V3D_SHADED_WIDGETS (1 << 3)
|
||||
|
||||
/* BGPic->flag */
|
||||
/* may want to use 1 for select ? */
|
||||
|
57
source/blender/makesdna/DNA_widget_types.h
Normal file
57
source/blender/makesdna/DNA_widget_types.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file DNA_widget_types.h
|
||||
* \ingroup DNA
|
||||
*/
|
||||
|
||||
#ifndef __DNA_WIDGET_TYPES_H__
|
||||
#define __DNA_WIDGET_TYPES_H__
|
||||
|
||||
typedef enum WidgetType {
|
||||
WT_TRANSLATE = 0,
|
||||
WT_ROTATE = 1,
|
||||
WT_SCALE = 2,
|
||||
WT_CUSTOM = 3,
|
||||
} WidgetType;
|
||||
|
||||
typedef struct wmWidgetGroup {
|
||||
struct wmWidgetGroup *next, *prev;
|
||||
|
||||
struct wmWidgetGroupType *type;
|
||||
ListBase widgets;
|
||||
|
||||
void *py_instance; /* python stores the class instance here */
|
||||
struct ReportList *reports; /* errors and warnings storage */
|
||||
|
||||
void *customdata;
|
||||
void (*customdata_free)(void *); /* for freeing customdata from above */
|
||||
int flag;
|
||||
int pad;
|
||||
} wmWidgetGroup;
|
||||
|
||||
#endif /* __DNA_WIDGET_TYPES_H__ */
|
@@ -118,6 +118,7 @@ static const char *includefiles[] = {
|
||||
"DNA_cloth_types.h",
|
||||
"DNA_gpencil_types.h",
|
||||
"DNA_windowmanager_types.h",
|
||||
"DNA_widget_types.h",
|
||||
"DNA_anim_types.h",
|
||||
"DNA_boid_types.h",
|
||||
"DNA_smoke_types.h",
|
||||
@@ -1330,6 +1331,7 @@ int main(int argc, char **argv)
|
||||
#include "DNA_cloth_types.h"
|
||||
#include "DNA_gpencil_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
#include "DNA_widget_types.h"
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_boid_types.h"
|
||||
#include "DNA_smoke_types.h"
|
||||
|
@@ -25,6 +25,8 @@
|
||||
|
||||
set(INC
|
||||
.
|
||||
widgets
|
||||
widgets/intern
|
||||
../blenfont
|
||||
../blenkernel
|
||||
../blenlib
|
||||
@@ -68,6 +70,18 @@ set(SRC
|
||||
intern/wm_subwindow.c
|
||||
intern/wm_window.c
|
||||
intern/wm_stereo.c
|
||||
widgets/intern/wm_widget.c
|
||||
widgets/intern/wm_widgetgroup.c
|
||||
widgets/intern/wm_widgetmap.c
|
||||
widgets/intern/widget_library/arrow_widget.c
|
||||
widgets/intern/widget_library/arrow2d_widget.c
|
||||
widgets/intern/widget_library/cage_widget.c
|
||||
widgets/intern/widget_library/dial_widget.c
|
||||
widgets/intern/widget_library/primitive_widget.c
|
||||
widgets/intern/widget_library/geom_arrow_widget.c
|
||||
widgets/intern/widget_library/geom_cube_widget
|
||||
widgets/intern/widget_library/geom_dial_widget.c
|
||||
widgets/intern/widget_library/widget_library_utils.c
|
||||
|
||||
WM_api.h
|
||||
WM_keymap.h
|
||||
@@ -80,6 +94,13 @@ set(SRC
|
||||
wm_files.h
|
||||
wm_subwindow.h
|
||||
wm_window.h
|
||||
widgets/WM_widget_api.h
|
||||
widgets/WM_widget_types.h
|
||||
widgets/WM_widget_library.h
|
||||
widgets/wm_widget_wmapi.h
|
||||
widgets/intern/wm_widget_intern.h
|
||||
widgets/intern/widget_library/widget_geometry.h
|
||||
widgets/intern/widget_library/widget_library_intern.h
|
||||
)
|
||||
|
||||
if(WITH_AUDASPACE)
|
||||
|
@@ -42,6 +42,10 @@
|
||||
#include "WM_keymap.h"
|
||||
#include "BLI_compiler_attrs.h"
|
||||
|
||||
/* Include external widget API's */
|
||||
#include "widgets/WM_widget_api.h"
|
||||
#include "widgets/WM_widget_library.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -70,6 +74,8 @@ struct wmNDOFMotionData;
|
||||
#endif
|
||||
|
||||
typedef struct wmJob wmJob;
|
||||
typedef struct wmWidget wmWidget;
|
||||
typedef struct wmWidgetMapType wmWidgetMapType;
|
||||
|
||||
/* general API */
|
||||
void WM_init_state_size_set (int stax, int stay, int sizx, int sizy);
|
||||
|
@@ -119,6 +119,7 @@ struct ImBuf;
|
||||
/* exported types for WM */
|
||||
#include "wm_cursors.h"
|
||||
#include "wm_event_types.h"
|
||||
#include "widgets/WM_widget_types.h"
|
||||
|
||||
/* ************** wmOperatorType ************************ */
|
||||
|
||||
@@ -566,6 +567,9 @@ typedef struct wmOperatorType {
|
||||
/* pointer to modal keymap, do not free! */
|
||||
struct wmKeyMap *modalkeymap;
|
||||
|
||||
/* widget group that is accessible while operator runs */
|
||||
wmWidgetGroupType *wgrouptype;
|
||||
|
||||
/* python needs the operator type as well */
|
||||
int (*pyop_poll)(struct bContext *, struct wmOperatorType *ot) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
|
118
source/blender/windowmanager/widgets/WM_widget_api.h
Normal file
118
source/blender/windowmanager/widgets/WM_widget_api.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/WM_widget_api.h
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name Widget API
|
||||
* \brief API for external use of wmWidget types.
|
||||
*
|
||||
* Only included in WM_api.h
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __WM_WIDGET_API_H__
|
||||
#define __WM_WIDGET_API_H__
|
||||
|
||||
struct ARegion;
|
||||
struct Main;
|
||||
struct wmEventHandler;
|
||||
struct wmKeyConfig;
|
||||
struct wmKeyMap;
|
||||
struct wmOperator;
|
||||
struct wmWidgetGroup;
|
||||
struct wmWidgetGroupType;
|
||||
struct wmWidgetMap;
|
||||
struct wmWidgetMapType;
|
||||
struct wmWidgetMapType_Params;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* wmWidget */
|
||||
|
||||
struct wmWidget *WM_widget_new(
|
||||
void (*draw)(const struct bContext *, struct wmWidget *),
|
||||
void (*render_3d_intersection)(const struct bContext *, struct wmWidget *, int),
|
||||
int (*intersect)(struct bContext *, const struct wmEvent *, struct wmWidget *),
|
||||
int (*handler)(struct bContext *, const struct wmEvent *, struct wmWidget *, const int));
|
||||
void WM_widget_delete(ListBase *widgetlist, struct wmWidgetMap *wmap, struct wmWidget *widget, struct bContext *C);
|
||||
|
||||
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_func_select(
|
||||
struct wmWidget *widget,
|
||||
void (*select)(struct bContext *, struct wmWidget *, const int action)); /* wmWidgetSelectFunc */
|
||||
void WM_widget_set_origin(struct wmWidget *widget, const float origin[3]);
|
||||
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]);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* wmWidgetGroup */
|
||||
|
||||
struct wmWidgetGroupType *WM_widgetgrouptype_append(
|
||||
struct wmWidgetMapType *wmaptype,
|
||||
void (*wgrouptype_func)(struct wmWidgetGroupType *));
|
||||
struct wmWidgetGroupType *WM_widgetgrouptype_append_runtime(
|
||||
const struct Main *main, struct wmWidgetMapType *wmaptype,
|
||||
void (*wgrouptype_func)(struct wmWidgetGroupType *));
|
||||
void WM_widgetgrouptype_init_runtime(
|
||||
const struct Main *bmain, struct wmWidgetMapType *wmaptype,
|
||||
struct wmWidgetGroupType *wgrouptype);
|
||||
void WM_widgetgrouptype_unregister(struct bContext *C, struct Main *bmain, struct wmWidgetGroupType *wgroup);
|
||||
|
||||
struct wmKeyMap *WM_widgetgroup_keymap_common(
|
||||
const struct wmWidgetGroupType *wgrouptype, struct wmKeyConfig *config);
|
||||
struct wmKeyMap *WM_widgetgroup_keymap_common_sel(
|
||||
const struct wmWidgetGroupType *wgrouptype, struct wmKeyConfig *config);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* wmWidgetMap */
|
||||
|
||||
struct wmWidgetMapType *WM_widgetmaptype_find(const struct wmWidgetMapType_Params *wmap_params);
|
||||
struct wmWidgetMapType *WM_widgetmaptype_ensure(const struct wmWidgetMapType_Params *wmap_params);
|
||||
struct wmWidgetMap *WM_widgetmap_from_type(const struct wmWidgetMapType_Params *wmap_params);
|
||||
struct wmWidgetMap *WM_widgetmap_find(const struct ARegion *ar, const struct wmWidgetMapType_Params *wmap_params);
|
||||
|
||||
void WM_widgetmap_delete(struct wmWidgetMap *wmap);
|
||||
void WM_widgetmaptypes_free(void);
|
||||
|
||||
void WM_widgetmap_tag_refresh(struct wmWidgetMap *wmap);
|
||||
void WM_widgetmap_widgets_update(const struct bContext *C, struct wmWidgetMap *wmap);
|
||||
void WM_widgetmap_widgets_draw(
|
||||
const struct bContext *C, const struct wmWidgetMap *wmap,
|
||||
const bool in_scene, const bool free_drawwidgets);
|
||||
|
||||
void WM_widgetmaps_add_handlers(struct ARegion *ar);
|
||||
|
||||
bool WM_widgetmap_select_all(struct bContext *C, struct wmWidgetMap *wmap, const int action);
|
||||
|
||||
bool WM_widgetmap_cursor_set(const struct wmWidgetMap *wmap, struct wmWindow *win);
|
||||
|
||||
#endif /* __WM_WIDGET_API_H__ */
|
||||
|
126
source/blender/windowmanager/widgets/WM_widget_library.h
Normal file
126
source/blender/windowmanager/widgets/WM_widget_library.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/WM_widget_library.h
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name Generic Widget Library
|
||||
*
|
||||
* Only included in WM_api.h and lower level files.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __WM_WIDGET_LIBRARY_H__
|
||||
#define __WM_WIDGET_LIBRARY_H__
|
||||
|
||||
struct wmWidgetGroup;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* 3D Arrow Widget */
|
||||
|
||||
enum {
|
||||
WIDGET_ARROW_STYLE_NORMAL = 1,
|
||||
WIDGET_ARROW_STYLE_NO_AXIS = (1 << 1),
|
||||
WIDGET_ARROW_STYLE_CROSS = (1 << 2),
|
||||
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),
|
||||
};
|
||||
|
||||
/* slots for properties */
|
||||
enum {
|
||||
ARROW_SLOT_OFFSET_WORLD_SPACE = 0
|
||||
};
|
||||
|
||||
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_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]);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* 2D Arrow Widget */
|
||||
|
||||
struct wmWidget *WIDGET_arrow2d_new(struct wmWidgetGroup *wgroup, const char *name);
|
||||
void WIDGET_arrow2d_set_angle(struct wmWidget *widget, const float rot_fac);
|
||||
void WIDGET_arrow2d_set_line_len(struct wmWidget *widget, const float len);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Cage Widget */
|
||||
|
||||
enum {
|
||||
WIDGET_RECT_TRANSFORM_STYLE_TRANSLATE = 1, /* widget translates */
|
||||
WIDGET_RECT_TRANSFORM_STYLE_ROTATE = (1 << 1), /* widget rotates */
|
||||
WIDGET_RECT_TRANSFORM_STYLE_SCALE = (1 << 2), /* widget scales */
|
||||
WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM = (1 << 3), /* widget scales uniformly */
|
||||
};
|
||||
|
||||
enum {
|
||||
RECT_TRANSFORM_SLOT_OFFSET = 0,
|
||||
RECT_TRANSFORM_SLOT_SCALE = 1
|
||||
};
|
||||
|
||||
struct wmWidget *WIDGET_rect_transform_new(struct wmWidgetGroup *wgroup, const char *name, const int style);
|
||||
void WIDGET_rect_transform_set_dimensions(struct wmWidget *widget, const float width, const float height);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Dial Widget */
|
||||
|
||||
enum {
|
||||
WIDGET_DIAL_STYLE_RING = 0,
|
||||
WIDGET_DIAL_STYLE_RING_CLIPPED = 1,
|
||||
WIDGET_DIAL_STYLE_RING_FILLED = 2,
|
||||
};
|
||||
|
||||
struct wmWidget *WIDGET_dial_new(struct wmWidgetGroup *wgroup, const char *name, const int style);
|
||||
void WIDGET_dial_set_up_vector(struct wmWidget *widget, const float direction[3]);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Facemap Widget */
|
||||
|
||||
struct wmWidget *WIDGET_facemap_new(
|
||||
struct wmWidgetGroup *wgroup, const char *name, const int style,
|
||||
struct Object *ob, const int facemap);
|
||||
struct bFaceMap *WIDGET_facemap_get_fmap(struct wmWidget *widget);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Primitive Widget */
|
||||
|
||||
enum {
|
||||
WIDGET_PRIMITIVE_STYLE_PLANE = 0,
|
||||
};
|
||||
|
||||
struct wmWidget *WIDGET_primitive_new(struct wmWidgetGroup *wgroup, const char *name, const int style);
|
||||
void WIDGET_primitive_set_direction(struct wmWidget *widget, const float direction[3]);
|
||||
void WIDGET_primitive_set_up_vector(struct wmWidget *widget, const float direction[3]);
|
||||
|
||||
#endif /* __WM_WIDGET_LIBRARY_H__ */
|
||||
|
166
source/blender/windowmanager/widgets/WM_widget_types.h
Normal file
166
source/blender/windowmanager/widgets/WM_widget_types.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/WM_widget_types.h
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name Widget Types
|
||||
* \brief Widget defines for external use.
|
||||
*
|
||||
* Only included in WM_types.h and lower level files.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __WM_WIDGET_TYPES_H__
|
||||
#define __WM_WIDGET_TYPES_H__
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
|
||||
struct wmWidgetGroupType;
|
||||
struct wmWidgetGroup;
|
||||
struct wmKeyConfig;
|
||||
|
||||
typedef int (*wmWidgetGroupPollFunc)(const struct bContext *, struct wmWidgetGroupType *) ATTR_WARN_UNUSED_RESULT; /* TODO use bool */
|
||||
typedef void (*wmWidgetGroupInitFunc)(const struct bContext *, struct wmWidgetGroup *);
|
||||
typedef void (*wmWidgetGroupRefreshFunc)(const struct bContext *, struct wmWidgetGroup *);
|
||||
typedef void (*wmWidgetGroupDrawPrepareFunc)(const struct bContext *, struct wmWidgetGroup *);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/* 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 */
|
||||
const char *name; /* widget group name - displayed in UI (keymap editor) */
|
||||
|
||||
/* poll if widgetmap should be active */
|
||||
wmWidgetGroupPollFunc poll;
|
||||
/* initially create widgets, set permanent data stuff you only need to do once */
|
||||
wmWidgetGroupInitFunc init;
|
||||
/* refresh data, only called if recreate flag is set (WM_widgetmap_tag_refresh) */
|
||||
wmWidgetGroupRefreshFunc refresh;
|
||||
/* refresh data for drawing, called before each redraw */
|
||||
wmWidgetGroupDrawPrepareFunc draw_prepare;
|
||||
|
||||
/* keymap init callback for this widgetgroup */
|
||||
struct wmKeyMap *(*keymap_init)(const struct wmWidgetGroupType *, struct wmKeyConfig *);
|
||||
/* keymap created with callback from above */
|
||||
struct wmKeyMap *keymap;
|
||||
|
||||
/* rna for properties */
|
||||
struct StructRNA *srna;
|
||||
|
||||
/* RNA integration */
|
||||
ExtensionRNA ext;
|
||||
|
||||
/* widgetTypeflags (includes copy of wmWidgetMapType.flag - used for comparisons) */
|
||||
int flag;
|
||||
|
||||
/* if type is spawned from operator this is set here */
|
||||
void *op;
|
||||
|
||||
/* same as widgetmaps, so registering/unregistering goes to the correct region */
|
||||
short spaceid, regionid;
|
||||
char mapidname[64];
|
||||
} wmWidgetGroupType;
|
||||
|
||||
|
||||
typedef struct wmWidgetMap {
|
||||
struct wmWidgetMap *next, *prev;
|
||||
|
||||
struct wmWidgetMapType *type;
|
||||
ListBase widgetgroups;
|
||||
|
||||
char update_flag; /* private, update tagging */
|
||||
|
||||
/**
|
||||
* \brief Widget map runtime context
|
||||
*
|
||||
* Contains information about this widget map. Currently
|
||||
* highlighted widget, currently selected widgets, ...
|
||||
*/
|
||||
struct {
|
||||
/* we redraw the widgetmap when this changes */
|
||||
struct wmWidget *highlighted_widget;
|
||||
/* user has clicked this widget and it gets all input */
|
||||
struct wmWidget *active_widget;
|
||||
/* array for all selected widgets
|
||||
* TODO check on using BLI_array */
|
||||
struct wmWidget **selected_widgets;
|
||||
int tot_selected;
|
||||
|
||||
/* set while widget is highlighted/active */
|
||||
struct wmWidgetGroup *activegroup;
|
||||
} wmap_context;
|
||||
} wmWidgetMap;
|
||||
|
||||
|
||||
struct wmWidgetMapType_Params {
|
||||
const char *idname;
|
||||
const int spaceid;
|
||||
const int regionid;
|
||||
const int flag;
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple utility wrapper for storing a single widget as wmWidgetGroup.customdata (which gets freed).
|
||||
*/
|
||||
typedef struct wmWidgetWrapper {
|
||||
struct wmWidget *widget;
|
||||
} wmWidgetWrapper;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/* wmWidget->flag */
|
||||
enum eWidgetFlag {
|
||||
/* 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_DRAW_VALUE = (1 << 5), /* draw a indicator for the current value while dragging */
|
||||
WM_WIDGET_SCALE_3D = (1 << 6),
|
||||
WM_WIDGET_SCENE_DEPTH = (1 << 7), /* widget is depth culled with scene objects*/
|
||||
WM_WIDGET_HIDDEN = (1 << 8),
|
||||
WM_WIDGET_SELECTABLE = (1 << 9),
|
||||
};
|
||||
|
||||
/* wmWidgetMapType->flag */
|
||||
enum eWidgetMapTypeFlag {
|
||||
/**
|
||||
* Check if widgetmap does 3D drawing
|
||||
* (uses a different kind of interaction),
|
||||
* - 3d: use glSelect buffer.
|
||||
* - 2d: use simple cursor position intersection test. */
|
||||
WM_WIDGETMAPTYPE_3D = (1 << 0),
|
||||
};
|
||||
|
||||
#endif /* __WM_WIDGET_TYPES_H__ */
|
||||
|
@@ -0,0 +1,222 @@
|
||||
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/widget_library/arrow2d_widget.c
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name 2D Arrow Widget
|
||||
*
|
||||
* 2D Widget
|
||||
*
|
||||
* \brief Simple arrow widget which is dragged into a certain direction.
|
||||
*/
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_rect.h"
|
||||
|
||||
#include "DNA_widget_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
|
||||
/* own includes */
|
||||
#include "WM_widget_types.h"
|
||||
#include "wm_widget_wmapi.h"
|
||||
#include "WM_widget_library.h"
|
||||
#include "wm_widget_intern.h"
|
||||
#include "widget_library_intern.h"
|
||||
|
||||
|
||||
typedef struct ArrowWidget2D {
|
||||
wmWidget widget;
|
||||
|
||||
float angle;
|
||||
float line_len;
|
||||
} ArrowWidget2D;
|
||||
|
||||
|
||||
static void arrow2d_draw_geom(ArrowWidget2D *arrow, const float origin[2])
|
||||
{
|
||||
const float size = 0.11f;
|
||||
const float size_h = size / 2.0f;
|
||||
const float len = arrow->line_len;
|
||||
const float draw_line_ofs = (arrow->widget.line_width * 0.5f) / arrow->widget.scale;
|
||||
|
||||
glPushMatrix();
|
||||
glTranslate2fv(origin);
|
||||
glScalef(arrow->widget.scale, arrow->widget.scale, 0.0f);
|
||||
glRotatef(RAD2DEGF(arrow->angle), 0.0f, 0.0f, 1.0f);
|
||||
/* local offset */
|
||||
glTranslatef(arrow->widget.offset[0] + draw_line_ofs, arrow->widget.offset[1], 0.0f);
|
||||
|
||||
/* TODO get rid of immediate mode */
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(0.0f, 0.0f);
|
||||
glVertex2f(0.0f, len);
|
||||
glEnd();
|
||||
glBegin(GL_TRIANGLES);
|
||||
glVertex2f(size_h, len);
|
||||
glVertex2f(-size_h, len);
|
||||
glVertex2f(0.0f, len + size * 1.7f);
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
static void widget_arrow2d_draw(const bContext *UNUSED(C), wmWidget *widget)
|
||||
{
|
||||
ArrowWidget2D *arrow = (ArrowWidget2D *)widget;
|
||||
const float *col = widget_color_get(widget, widget->flag & WM_WIDGET_HIGHLIGHT);
|
||||
|
||||
glColor4fv(col);
|
||||
glLineWidth(widget->line_width);
|
||||
glEnable(GL_BLEND);
|
||||
arrow2d_draw_geom(arrow, widget->origin);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
if (arrow->widget.interaction_data) {
|
||||
WidgetInteraction *inter = arrow->widget.interaction_data;
|
||||
|
||||
glColor4f(0.5f, 0.5f, 0.5f, 0.5f);
|
||||
glEnable(GL_BLEND);
|
||||
arrow2d_draw_geom(arrow, inter->init_origin);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
static int widget_arrow2d_invoke(bContext *UNUSED(C), const wmEvent *UNUSED(event), wmWidget *widget)
|
||||
{
|
||||
WidgetInteraction *inter = MEM_callocN(sizeof(WidgetInteraction), __func__);
|
||||
|
||||
copy_v2_v2(inter->init_origin, widget->origin);
|
||||
widget->interaction_data = inter;
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int widget_arrow2d_intersect(bContext *UNUSED(C), const wmEvent *event, wmWidget *widget)
|
||||
{
|
||||
ArrowWidget2D *arrow = (ArrowWidget2D *)widget;
|
||||
const float mval[2] = {event->mval[0], event->mval[1]};
|
||||
const float line_len = arrow->line_len * widget->scale;
|
||||
float mval_local[2];
|
||||
|
||||
copy_v2_v2(mval_local, mval);
|
||||
sub_v2_v2(mval_local, widget->origin);
|
||||
|
||||
float line[2][2];
|
||||
line[0][0] = line[0][1] = line[1][0] = 0.0f;
|
||||
line[1][1] = line_len;
|
||||
|
||||
/* rotate only if needed */
|
||||
if (arrow->angle != 0.0f) {
|
||||
float rot_point[2];
|
||||
copy_v2_v2(rot_point, line[1]);
|
||||
rotate_v2_v2fl(line[1], rot_point, arrow->angle);
|
||||
}
|
||||
|
||||
/* arrow line intersection check */
|
||||
float isect_1[2], isect_2[2];
|
||||
const int isect = isect_line_sphere_v2(
|
||||
line[0], line[1], mval_local, WIDGET_HOTSPOT + widget->line_width * 0.5f,
|
||||
isect_1, isect_2);
|
||||
|
||||
if (isect > 0) {
|
||||
float line_ext[2][2]; /* extended line for segment check including hotspot */
|
||||
copy_v2_v2(line_ext[0], line[0]);
|
||||
line_ext[1][0] = line[1][0] + WIDGET_HOTSPOT * ((line[1][0] - line[0][0]) / line_len);
|
||||
line_ext[1][1] = line[1][1] + WIDGET_HOTSPOT * ((line[1][1] - line[0][1]) / line_len);
|
||||
|
||||
const float lambda_1 = line_point_factor_v2(isect_1, line_ext[0], line_ext[1]);
|
||||
if (isect == 1) {
|
||||
return IN_RANGE_INCL(lambda_1, 0.0f, 1.0f);
|
||||
}
|
||||
else {
|
||||
BLI_assert(isect == 2);
|
||||
const float lambda_2 = line_point_factor_v2(isect_2, line_ext[0], line_ext[1]);
|
||||
return IN_RANGE_INCL(lambda_1, 0.0f, 1.0f) && IN_RANGE_INCL(lambda_2, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name 2D Arrow Widget API
|
||||
*
|
||||
* \{ */
|
||||
|
||||
wmWidget *WIDGET_arrow2d_new(wmWidgetGroup *wgroup, const char *name)
|
||||
{
|
||||
ArrowWidget2D *arrow = MEM_callocN(sizeof(ArrowWidget2D), __func__);
|
||||
|
||||
arrow->widget.draw = widget_arrow2d_draw;
|
||||
arrow->widget.invoke = widget_arrow2d_invoke;
|
||||
// arrow->widget.bind_to_prop = widget_arrow2d_bind_to_prop;
|
||||
// arrow->widget.handler = widget_arrow2d_handler;
|
||||
arrow->widget.intersect = widget_arrow2d_intersect;
|
||||
// arrow->widget.exit = widget_arrow2d_exit;
|
||||
arrow->widget.flag |= WM_WIDGET_DRAW_ACTIVE;
|
||||
|
||||
arrow->line_len = 1.0f;
|
||||
|
||||
wm_widget_register(wgroup, &arrow->widget, name);
|
||||
|
||||
return (wmWidget *)arrow;
|
||||
}
|
||||
|
||||
void WIDGET_arrow2d_set_angle(wmWidget *widget, const float angle)
|
||||
{
|
||||
ArrowWidget2D *arrow = (ArrowWidget2D *)widget;
|
||||
arrow->angle = angle;
|
||||
}
|
||||
|
||||
void WIDGET_arrow2d_set_line_len(wmWidget *widget, const float len)
|
||||
{
|
||||
ArrowWidget2D *arrow = (ArrowWidget2D *)widget;
|
||||
arrow->line_len = len;
|
||||
}
|
||||
|
||||
/** \} */ /* Arrow Widget API */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
void fix_linking_widget_arrow2d(void)
|
||||
{
|
||||
(void)0;
|
||||
}
|
@@ -0,0 +1,577 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2014 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/widget_library/arrow_widget.c
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name Arrow Widget
|
||||
*
|
||||
* 3D Widget
|
||||
*
|
||||
* \brief Simple arrow widget which is dragged into a certain direction.
|
||||
* The arrow head can have varying shapes, e.g. cone, box, etc.
|
||||
*/
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "DNA_view3d_types.h"
|
||||
|
||||
#include "ED_view3d.h"
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "GPU_select.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
#include "WM_api.h"
|
||||
|
||||
/* own includes */
|
||||
#include "wm_widget_wmapi.h"
|
||||
#include "wm_widget_intern.h"
|
||||
#include "widget_geometry.h"
|
||||
#include "widget_library_intern.h"
|
||||
|
||||
|
||||
/* to use custom arrows exported to arrow_widget.c */
|
||||
//#define WIDGET_USE_CUSTOM_ARROWS
|
||||
|
||||
#ifdef WIDGET_USE_CUSTOM_ARROWS
|
||||
WidgetDrawInfo arrow_head_draw_info = {0};
|
||||
#endif
|
||||
WidgetDrawInfo cube_draw_info = {0};
|
||||
|
||||
/* ArrowWidget->flag */
|
||||
enum {
|
||||
ARROW_UP_VECTOR_SET = (1 << 0),
|
||||
ARROW_CUSTOM_RANGE_SET = (1 << 1),
|
||||
};
|
||||
|
||||
typedef struct ArrowWidget {
|
||||
wmWidget widget;
|
||||
|
||||
WidgetCommonData data;
|
||||
|
||||
int style;
|
||||
int flag;
|
||||
|
||||
float len; /* arrow line length */
|
||||
float direction[3];
|
||||
float up[3];
|
||||
float aspect[2]; /* cone style only */
|
||||
} ArrowWidget;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void widget_arrow_get_final_pos(wmWidget *widget, float r_pos[3])
|
||||
{
|
||||
ArrowWidget *arrow = (ArrowWidget *)widget;
|
||||
|
||||
mul_v3_v3fl(r_pos, arrow->direction, arrow->data.offset);
|
||||
add_v3_v3(r_pos, arrow->widget.origin);
|
||||
}
|
||||
|
||||
static void arrow_draw_geom(const ArrowWidget *arrow, const bool select)
|
||||
{
|
||||
if (arrow->style & WIDGET_ARROW_STYLE_CROSS) {
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
glDisable(GL_LIGHTING);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(-1.0, 0.f);
|
||||
glVertex2f(1.0, 0.f);
|
||||
glVertex2f(0.f, -1.0);
|
||||
glVertex2f(0.f, 1.0);
|
||||
glEnd();
|
||||
|
||||
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, vec);
|
||||
glDrawArrays(GL_LINE_STRIP, 0, ARRAY_SIZE(vec));
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glLineWidth(1.0);
|
||||
|
||||
|
||||
/* *** draw arrow head *** */
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
if (arrow->style & WIDGET_ARROW_STYLE_BOX) {
|
||||
const float size = 0.05f;
|
||||
|
||||
/* 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 {
|
||||
const float len = 0.25f;
|
||||
const float width = 0.06f;
|
||||
const bool use_lighting = select == false && ((U.widget_flag & V3D_SHADED_WIDGETS) != 0);
|
||||
|
||||
/* translate to line end */
|
||||
glTranslatef(0.0f, 0.0f, arrow->len);
|
||||
|
||||
if (use_lighting) {
|
||||
glShadeModel(GL_SMOOTH);
|
||||
}
|
||||
|
||||
GLUquadricObj *qobj = gluNewQuadric();
|
||||
gluQuadricDrawStyle(qobj, GLU_FILL);
|
||||
gluQuadricOrientation(qobj, GLU_INSIDE);
|
||||
gluDisk(qobj, 0.0, width, 8, 1);
|
||||
gluQuadricOrientation(qobj, GLU_OUTSIDE);
|
||||
gluCylinder(qobj, width, 0.0, len, 8, 1);
|
||||
gluDeleteQuadric(qobj);
|
||||
|
||||
if (use_lighting) {
|
||||
glShadeModel(GL_FLAT);
|
||||
}
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void arrow_draw_intern(ArrowWidget *arrow, const bool select, const bool highlight)
|
||||
{
|
||||
const float up[3] = {0.0f, 0.0f, 1.0f};
|
||||
float rot[3][3];
|
||||
float mat[4][4];
|
||||
float final_pos[3];
|
||||
|
||||
widget_arrow_get_final_pos(&arrow->widget, final_pos);
|
||||
|
||||
if (arrow->flag & ARROW_UP_VECTOR_SET) {
|
||||
copy_v3_v3(rot[2], arrow->direction);
|
||||
copy_v3_v3(rot[1], arrow->up);
|
||||
cross_v3_v3v3(rot[0], arrow->up, arrow->direction);
|
||||
}
|
||||
else {
|
||||
rotation_between_vecs_to_mat3(rot, up, arrow->direction);
|
||||
}
|
||||
copy_m4_m3(mat, rot);
|
||||
copy_v3_v3(mat[3], final_pos);
|
||||
mul_mat3_m4_fl(mat, arrow->widget.scale);
|
||||
|
||||
glPushMatrix();
|
||||
glMultMatrixf(mat);
|
||||
|
||||
if (highlight && !(arrow->widget.flag & WM_WIDGET_DRAW_HOVER)) {
|
||||
glColor4fv(arrow->widget.col_hi);
|
||||
}
|
||||
else {
|
||||
glColor4fv(arrow->widget.col);
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glTranslate3fv(arrow->widget.offset);
|
||||
arrow_draw_geom(arrow, select);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
if (arrow->widget.interaction_data) {
|
||||
WidgetInteraction *inter = arrow->widget.interaction_data;
|
||||
|
||||
copy_m4_m3(mat, rot);
|
||||
copy_v3_v3(mat[3], inter->init_origin);
|
||||
mul_mat3_m4_fl(mat, inter->init_scale);
|
||||
|
||||
glPushMatrix();
|
||||
glMultMatrixf(mat);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
static void widget_arrow_render_3d_intersect(const bContext *UNUSED(C), wmWidget *widget, int selectionbase)
|
||||
{
|
||||
GPU_select_load_id(selectionbase);
|
||||
arrow_draw_intern((ArrowWidget *)widget, true, false);
|
||||
}
|
||||
|
||||
static void widget_arrow_draw(const bContext *UNUSED(C), wmWidget *widget)
|
||||
{
|
||||
arrow_draw_intern((ArrowWidget *)widget, false, (widget->flag & WM_WIDGET_HIGHLIGHT) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, const int flag)
|
||||
{
|
||||
ArrowWidget *arrow = (ArrowWidget *)widget;
|
||||
WidgetInteraction *inter = widget->interaction_data;
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
|
||||
float orig_origin[4];
|
||||
float viewvec[3], tangent[3], plane[3];
|
||||
float offset[4];
|
||||
float m_diff[2];
|
||||
float dir_2d[2], dir2d_final[2];
|
||||
float facdir = 1.0f;
|
||||
bool use_vertical = false;
|
||||
|
||||
|
||||
copy_v3_v3(orig_origin, inter->init_origin);
|
||||
orig_origin[3] = 1.0f;
|
||||
add_v3_v3v3(offset, orig_origin, arrow->direction);
|
||||
offset[3] = 1.0f;
|
||||
|
||||
/* calculate view vector */
|
||||
if (rv3d->is_persp) {
|
||||
sub_v3_v3v3(viewvec, orig_origin, rv3d->viewinv[3]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(viewvec, rv3d->viewinv[2]);
|
||||
}
|
||||
normalize_v3(viewvec);
|
||||
|
||||
/* first determine if view vector is really close to the direction. If it is, we use
|
||||
* vertical movement to determine offset, just like transform system does */
|
||||
if (RAD2DEG(acos(dot_v3v3(viewvec, arrow->direction))) > 5.0f) {
|
||||
/* multiply to projection space */
|
||||
mul_m4_v4(rv3d->persmat, orig_origin);
|
||||
mul_v4_fl(orig_origin, 1.0f / orig_origin[3]);
|
||||
mul_m4_v4(rv3d->persmat, offset);
|
||||
mul_v4_fl(offset, 1.0f / offset[3]);
|
||||
|
||||
sub_v2_v2v2(dir_2d, offset, orig_origin);
|
||||
dir_2d[0] *= ar->winx;
|
||||
dir_2d[1] *= ar->winy;
|
||||
normalize_v2(dir_2d);
|
||||
}
|
||||
else {
|
||||
dir_2d[0] = 0.0f;
|
||||
dir_2d[1] = 1.0f;
|
||||
use_vertical = true;
|
||||
}
|
||||
|
||||
/* find mouse difference */
|
||||
m_diff[0] = event->mval[0] - inter->init_mval[0];
|
||||
m_diff[1] = event->mval[1] - inter->init_mval[1];
|
||||
|
||||
/* project the displacement on the screen space arrow direction */
|
||||
project_v2_v2v2(dir2d_final, m_diff, dir_2d);
|
||||
|
||||
float zfac = ED_view3d_calc_zfac(rv3d, orig_origin, NULL);
|
||||
ED_view3d_win_to_delta(ar, dir2d_final, offset, zfac);
|
||||
|
||||
add_v3_v3v3(orig_origin, offset, inter->init_origin);
|
||||
|
||||
/* calculate view vector for the new position */
|
||||
if (rv3d->is_persp) {
|
||||
sub_v3_v3v3(viewvec, orig_origin, rv3d->viewinv[3]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(viewvec, rv3d->viewinv[2]);
|
||||
}
|
||||
|
||||
normalize_v3(viewvec);
|
||||
if (!use_vertical) {
|
||||
float fac;
|
||||
/* now find a plane parallel to the view vector so we can intersect with the arrow direction */
|
||||
cross_v3_v3v3(tangent, viewvec, offset);
|
||||
cross_v3_v3v3(plane, tangent, viewvec);
|
||||
fac = dot_v3v3(plane, offset) / dot_v3v3(arrow->direction, plane);
|
||||
|
||||
facdir = (fac < 0.0) ? -1.0 : 1.0;
|
||||
mul_v3_v3fl(offset, arrow->direction, fac);
|
||||
}
|
||||
else {
|
||||
facdir = (m_diff[1] < 0.0) ? -1.0 : 1.0;
|
||||
}
|
||||
|
||||
|
||||
WidgetCommonData *data = &arrow->data;
|
||||
const float ofs_new = facdir * len_v3(offset);
|
||||
const int slot = ARROW_SLOT_OFFSET_WORLD_SPACE;
|
||||
|
||||
/* set the property for the operator and call its modal function */
|
||||
if (widget->props[slot]) {
|
||||
const bool constrained = arrow->style & WIDGET_ARROW_STYLE_CONSTRAINED;
|
||||
const bool inverted = arrow->style & WIDGET_ARROW_STYLE_INVERTED;
|
||||
const bool use_precision = flag & WM_WIDGET_TWEAK_PRECISE;
|
||||
float value = widget_value_from_offset(data, inter, ofs_new, constrained, inverted, use_precision);
|
||||
|
||||
widget_property_value_set(C, widget, slot, value);
|
||||
/* get clamped value */
|
||||
value = widget_property_value_get(widget, slot);
|
||||
|
||||
data->offset = widget_offset_from_value(data, value, constrained, inverted);
|
||||
}
|
||||
else {
|
||||
data->offset = ofs_new;
|
||||
}
|
||||
|
||||
/* tag the region for redraw */
|
||||
ED_region_tag_redraw(ar);
|
||||
WM_event_add_mousemove(C);
|
||||
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
|
||||
static int widget_arrow_invoke(bContext *UNUSED(C), const wmEvent *event, wmWidget *widget)
|
||||
{
|
||||
ArrowWidget *arrow = (ArrowWidget *)widget;
|
||||
WidgetInteraction *inter = MEM_callocN(sizeof(WidgetInteraction), __func__);
|
||||
PointerRNA ptr = widget->ptr[ARROW_SLOT_OFFSET_WORLD_SPACE];
|
||||
PropertyRNA *prop = widget->props[ARROW_SLOT_OFFSET_WORLD_SPACE];
|
||||
|
||||
if (prop) {
|
||||
inter->init_value = RNA_property_float_get(&ptr, prop);
|
||||
}
|
||||
|
||||
inter->init_offset = arrow->data.offset;
|
||||
|
||||
inter->init_mval[0] = event->mval[0];
|
||||
inter->init_mval[1] = event->mval[1];
|
||||
|
||||
inter->init_scale = widget->scale;
|
||||
|
||||
widget_arrow_get_final_pos(widget, inter->init_origin);
|
||||
|
||||
widget->interaction_data = inter;
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static void widget_arrow_prop_data_update(wmWidget *widget, const int slot)
|
||||
{
|
||||
ArrowWidget *arrow = (ArrowWidget *)widget;
|
||||
widget_property_data_update(
|
||||
widget, &arrow->data, slot,
|
||||
arrow->style & WIDGET_ARROW_STYLE_CONSTRAINED,
|
||||
arrow->style & WIDGET_ARROW_STYLE_INVERTED);
|
||||
}
|
||||
|
||||
static void widget_arrow_exit(bContext *C, wmWidget *widget, const bool cancel)
|
||||
{
|
||||
if (!cancel)
|
||||
return;
|
||||
|
||||
ArrowWidget *arrow = (ArrowWidget *)widget;
|
||||
WidgetCommonData *data = &arrow->data;
|
||||
WidgetInteraction *inter = widget->interaction_data;
|
||||
|
||||
widget_property_value_reset(C, widget, inter, ARROW_SLOT_OFFSET_WORLD_SPACE);
|
||||
data->offset = inter->init_offset;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Arrow Widget API
|
||||
*
|
||||
* \{ */
|
||||
|
||||
wmWidget *WIDGET_arrow_new(wmWidgetGroup *wgroup, const char *name, const int style)
|
||||
{
|
||||
int real_style = style;
|
||||
|
||||
#ifdef WIDGET_USE_CUSTOM_ARROWS
|
||||
if (!arrow_head_draw_info.init) {
|
||||
arrow_head_draw_info.nverts = _WIDGET_nverts_arrow,
|
||||
arrow_head_draw_info.ntris = _WIDGET_ntris_arrow,
|
||||
arrow_head_draw_info.verts = _WIDGET_verts_arrow,
|
||||
arrow_head_draw_info.normals = _WIDGET_normals_arrow,
|
||||
arrow_head_draw_info.indices = _WIDGET_indices_arrow,
|
||||
arrow_head_draw_info.init = true;
|
||||
}
|
||||
#endif
|
||||
if (!cube_draw_info.init) {
|
||||
cube_draw_info.nverts = _WIDGET_nverts_cube,
|
||||
cube_draw_info.ntris = _WIDGET_ntris_cube,
|
||||
cube_draw_info.verts = _WIDGET_verts_cube,
|
||||
cube_draw_info.normals = _WIDGET_normals_cube,
|
||||
cube_draw_info.indices = _WIDGET_indices_cube,
|
||||
cube_draw_info.init = true;
|
||||
}
|
||||
|
||||
/* inverted only makes sense in a constrained arrow */
|
||||
if (real_style & WIDGET_ARROW_STYLE_INVERTED) {
|
||||
real_style |= WIDGET_ARROW_STYLE_CONSTRAINED;
|
||||
}
|
||||
|
||||
|
||||
ArrowWidget *arrow = MEM_callocN(sizeof(ArrowWidget), name);
|
||||
const float dir_default[3] = {0.0f, 0.0f, 1.0f};
|
||||
|
||||
arrow->widget.draw = widget_arrow_draw;
|
||||
arrow->widget.get_final_position = widget_arrow_get_final_pos;
|
||||
arrow->widget.intersect = NULL;
|
||||
arrow->widget.handler = widget_arrow_handler;
|
||||
arrow->widget.invoke = widget_arrow_invoke;
|
||||
arrow->widget.render_3d_intersection = widget_arrow_render_3d_intersect;
|
||||
arrow->widget.prop_data_update = widget_arrow_prop_data_update;
|
||||
arrow->widget.exit = widget_arrow_exit;
|
||||
arrow->widget.flag |= (WM_WIDGET_SCALE_3D | WM_WIDGET_DRAW_ACTIVE);
|
||||
|
||||
arrow->style = real_style;
|
||||
arrow->len = 1.0f;
|
||||
arrow->data.range_fac = 1.0f;
|
||||
copy_v3_v3(arrow->direction, dir_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;
|
||||
|
||||
if (direction) {
|
||||
copy_v3_v3(arrow->up, direction);
|
||||
normalize_v3(arrow->up);
|
||||
arrow->flag |= ARROW_UP_VECTOR_SET;
|
||||
}
|
||||
else {
|
||||
arrow->flag &= ~ARROW_UP_VECTOR_SET;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->data.range = max - min;
|
||||
arrow->data.min = min;
|
||||
arrow->data.flag |= WIDGET_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->data.range_fac = range_fac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define xy-aspect for arrow cone
|
||||
*/
|
||||
void WIDGET_arrow_cone_set_aspect(wmWidget *widget, const float aspect[2])
|
||||
{
|
||||
ArrowWidget *arrow = (ArrowWidget *)widget;
|
||||
|
||||
copy_v2_v2(arrow->aspect, aspect);
|
||||
}
|
||||
|
||||
/** \} */ /* Arrow Widget API */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
void fix_linking_widget_arrow(void)
|
||||
{
|
||||
(void)0;
|
||||
}
|
@@ -0,0 +1,559 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2014 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/widget_library/cage_widget.c
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name Cage Widget
|
||||
*
|
||||
* 2D Widget
|
||||
*
|
||||
* \brief Rectangular widget acting as a 'cage' around its content.
|
||||
* Interacting scales or translates the widget.
|
||||
*/
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_rect.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
/* own includes */
|
||||
#include "wm_widget_wmapi.h"
|
||||
#include "wm_widget_intern.h"
|
||||
|
||||
|
||||
/* wmWidget->highlighted_part */
|
||||
enum {
|
||||
WIDGET_RECT_TRANSFORM_INTERSECT_TRANSLATE = 1,
|
||||
WIDGET_RECT_TRANSFORM_INTERSECT_SCALEX_LEFT = 2,
|
||||
WIDGET_RECT_TRANSFORM_INTERSECT_SCALEX_RIGHT = 3,
|
||||
WIDGET_RECT_TRANSFORM_INTERSECT_SCALEY_UP = 4,
|
||||
WIDGET_RECT_TRANSFORM_INTERSECT_SCALEY_DOWN = 5
|
||||
};
|
||||
|
||||
#define WIDGET_RECT_MIN_WIDTH 15.0f
|
||||
#define WIDGET_RESIZER_WIDTH 20.0f
|
||||
|
||||
typedef struct RectTransformWidget {
|
||||
wmWidget widget;
|
||||
float w, h; /* dimensions of widget */
|
||||
float rotation; /* rotation of the rectangle */
|
||||
float scale[2]; /* scaling for the widget for non-destructive editing. */
|
||||
int style;
|
||||
} RectTransformWidget;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void rect_transform_draw_corners(rctf *r, const float offsetx, const float offsety)
|
||||
{
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(r->xmin, r->ymin + offsety);
|
||||
glVertex2f(r->xmin, r->ymin);
|
||||
glVertex2f(r->xmin, r->ymin);
|
||||
glVertex2f(r->xmin + offsetx, r->ymin);
|
||||
|
||||
glVertex2f(r->xmax, r->ymin + offsety);
|
||||
glVertex2f(r->xmax, r->ymin);
|
||||
glVertex2f(r->xmax, r->ymin);
|
||||
glVertex2f(r->xmax - offsetx, r->ymin);
|
||||
|
||||
glVertex2f(r->xmax, r->ymax - offsety);
|
||||
glVertex2f(r->xmax, r->ymax);
|
||||
glVertex2f(r->xmax, r->ymax);
|
||||
glVertex2f(r->xmax - offsetx, r->ymax);
|
||||
|
||||
glVertex2f(r->xmin, r->ymax - offsety);
|
||||
glVertex2f(r->xmin, r->ymax);
|
||||
glVertex2f(r->xmin, r->ymax);
|
||||
glVertex2f(r->xmin + offsetx, r->ymax);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void rect_transform_draw_interaction(
|
||||
const float col[4], const int highlighted,
|
||||
const float half_w, const float half_h,
|
||||
const float w, const float h, const float line_width)
|
||||
{
|
||||
float verts[4][2];
|
||||
|
||||
switch (highlighted) {
|
||||
case WIDGET_RECT_TRANSFORM_INTERSECT_SCALEX_LEFT:
|
||||
verts[0][0] = -half_w + w;
|
||||
verts[0][1] = -half_h;
|
||||
verts[1][0] = -half_w;
|
||||
verts[1][1] = -half_h;
|
||||
verts[2][0] = -half_w;
|
||||
verts[2][1] = half_h;
|
||||
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;
|
||||
verts[1][0] = half_w;
|
||||
verts[1][1] = -half_h;
|
||||
verts[2][0] = half_w;
|
||||
verts[2][1] = half_h;
|
||||
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;
|
||||
verts[1][0] = -half_w;
|
||||
verts[1][1] = -half_h;
|
||||
verts[2][0] = half_w;
|
||||
verts[2][1] = -half_h;
|
||||
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;
|
||||
verts[1][0] = -half_w;
|
||||
verts[1][1] = half_h;
|
||||
verts[2][0] = half_w;
|
||||
verts[2][1] = half_h;
|
||||
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);
|
||||
glColor3f(0.0, 0.0, 0.0);
|
||||
glDrawArrays(GL_LINE_STRIP, 0, 3);
|
||||
glLineWidth(line_width);
|
||||
glColor3fv(col);
|
||||
glDrawArrays(GL_LINE_STRIP, 0, 3);
|
||||
glLineWidth(1.0);
|
||||
}
|
||||
|
||||
static void widget_rect_transform_draw(const bContext *UNUSED(C), wmWidget *widget)
|
||||
{
|
||||
RectTransformWidget *cage = (RectTransformWidget *)widget;
|
||||
rctf r;
|
||||
float w = cage->w;
|
||||
float h = cage->h;
|
||||
float aspx = 1.0f, aspy = 1.0f;
|
||||
const float half_w = w / 2.0f;
|
||||
const float half_h = h / 2.0f;
|
||||
|
||||
r.xmin = -half_w;
|
||||
r.ymin = -half_h;
|
||||
r.xmax = half_w;
|
||||
r.ymax = half_h;
|
||||
|
||||
glPushMatrix();
|
||||
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
|
||||
glScalef(cage->scale[0], cage->scale[1], 1.0);
|
||||
|
||||
if (w > h)
|
||||
aspx = h / w;
|
||||
else
|
||||
aspy = w / h;
|
||||
w = min_ff(aspx * w / WIDGET_RESIZER_WIDTH, WIDGET_RESIZER_WIDTH / cage->scale[0]);
|
||||
h = min_ff(aspy * h / WIDGET_RESIZER_WIDTH, WIDGET_RESIZER_WIDTH /
|
||||
((cage->style & WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) ? cage->scale[0] : cage->scale[1]));
|
||||
|
||||
/* corner widgets */
|
||||
glColor3f(0.0, 0.0, 0.0);
|
||||
glLineWidth(cage->widget.line_width + 3.0f);
|
||||
|
||||
rect_transform_draw_corners(&r, w, h);
|
||||
|
||||
/* corner widgets */
|
||||
glColor3fv(widget->col);
|
||||
glLineWidth(cage->widget.line_width);
|
||||
rect_transform_draw_corners(&r, w, h);
|
||||
|
||||
rect_transform_draw_interaction(widget->col, widget->highlighted_part, half_w, half_h,
|
||||
w, h, cage->widget.line_width);
|
||||
|
||||
glLineWidth(1.0);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
static int widget_rect_transform_get_cursor(wmWidget *widget)
|
||||
{
|
||||
switch (widget->highlighted_part) {
|
||||
case WIDGET_RECT_TRANSFORM_INTERSECT_TRANSLATE:
|
||||
return BC_HANDCURSOR;
|
||||
case WIDGET_RECT_TRANSFORM_INTERSECT_SCALEX_LEFT:
|
||||
case WIDGET_RECT_TRANSFORM_INTERSECT_SCALEX_RIGHT:
|
||||
return CURSOR_X_MOVE;
|
||||
case WIDGET_RECT_TRANSFORM_INTERSECT_SCALEY_DOWN:
|
||||
case WIDGET_RECT_TRANSFORM_INTERSECT_SCALEY_UP:
|
||||
return CURSOR_Y_MOVE;
|
||||
default:
|
||||
return CURSOR_STD;
|
||||
}
|
||||
}
|
||||
|
||||
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]};
|
||||
//float matrot[2][2];
|
||||
float point_local[2];
|
||||
float w = cage->w;
|
||||
float h = cage->h;
|
||||
float half_w = w / 2.0f;
|
||||
float half_h = h / 2.0f;
|
||||
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] -= widget->offset[0];
|
||||
point_local[1] -= widget->offset[1];
|
||||
//rotate_m2(matrot, -cage->transform.rotation);
|
||||
|
||||
if (cage->style & WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM)
|
||||
mul_v2_fl(point_local, 1.0f / cage->scale[0]);
|
||||
else {
|
||||
point_local[0] /= cage->scale[0];
|
||||
point_local[1] /= cage->scale[0];
|
||||
}
|
||||
|
||||
if (cage->w > cage->h)
|
||||
aspx = h / w;
|
||||
else
|
||||
aspy = w / h;
|
||||
w = min_ff(aspx * w / WIDGET_RESIZER_WIDTH, WIDGET_RESIZER_WIDTH / cage->scale[0]);
|
||||
h = min_ff(aspy * h / WIDGET_RESIZER_WIDTH, WIDGET_RESIZER_WIDTH /
|
||||
((cage->style & WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) ? cage->scale[0] : cage->scale[1]));
|
||||
|
||||
|
||||
rctf r;
|
||||
|
||||
r.xmin = -half_w + w;
|
||||
r.ymin = -half_h + h;
|
||||
r.xmax = half_w - w;
|
||||
r.ymax = half_h - h;
|
||||
|
||||
bool isect = BLI_rctf_isect_pt_v(&r, point_local);
|
||||
|
||||
if (isect)
|
||||
return WIDGET_RECT_TRANSFORM_INTERSECT_TRANSLATE;
|
||||
|
||||
/* if widget does not have a scale intersection, don't do it */
|
||||
if (cage->style & (WIDGET_RECT_TRANSFORM_STYLE_SCALE | WIDGET_RECT_TRANSFORM_STYLE_SCALE_UNIFORM)) {
|
||||
r.xmin = -half_w;
|
||||
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;
|
||||
}
|
||||
|
||||
typedef struct RectTransformInteraction {
|
||||
float orig_mouse[2];
|
||||
float orig_offset[2];
|
||||
float orig_scale[2];
|
||||
} RectTransformInteraction;
|
||||
|
||||
static bool widget_rect_transform_get_prop_value(wmWidget *widget, const int slot, float *value)
|
||||
{
|
||||
PropertyType type = RNA_property_type(widget->props[slot]);
|
||||
|
||||
if (type != PROP_FLOAT) {
|
||||
fprintf(stderr, "Rect Transform widget can only be bound to float properties");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (slot == RECT_TRANSFORM_SLOT_OFFSET) {
|
||||
if (RNA_property_array_length(&widget->ptr[slot], widget->props[slot]) != 2) {
|
||||
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) {
|
||||
*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");
|
||||
return false;
|
||||
}
|
||||
RNA_property_float_get_array(&widget->ptr[slot], widget->props[slot], value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int widget_rect_transform_invoke(bContext *UNUSED(C), const wmEvent *event, wmWidget *widget)
|
||||
{
|
||||
RectTransformWidget *cage = (RectTransformWidget *)widget;
|
||||
RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction), "cage_interaction");
|
||||
|
||||
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, const int UNUSED(flag))
|
||||
{
|
||||
RectTransformWidget *cage = (RectTransformWidget *)widget;
|
||||
RectTransformInteraction *data = widget->interaction_data;
|
||||
/* needed here as well in case clamping occurs */
|
||||
const float orig_ofx = widget->offset[0], orig_ofy = widget->offset[1];
|
||||
|
||||
const float valuex = (event->mval[0] - data->orig_mouse[0]);
|
||||
const float valuey = (event->mval[1] - data->orig_mouse[1]);
|
||||
|
||||
|
||||
if (widget->highlighted_part == WIDGET_RECT_TRANSFORM_INTERSECT_TRANSLATE) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
else {
|
||||
cage->scale[1] = (cage->h * data->orig_scale[1] - valuey) / cage->h;
|
||||
}
|
||||
}
|
||||
else if (widget->highlighted_part == WIDGET_RECT_TRANSFORM_INTERSECT_SCALEY_UP) {
|
||||
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;
|
||||
}
|
||||
else {
|
||||
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);
|
||||
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;
|
||||
widget->offset[0] = orig_ofx;
|
||||
}
|
||||
if (cage->scale[1] < WIDGET_RECT_MIN_WIDTH / cage->h) {
|
||||
cage->scale[1] = WIDGET_RECT_MIN_WIDTH / cage->h;
|
||||
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, widget->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, cage->scale[0]);
|
||||
}
|
||||
else {
|
||||
RNA_property_float_set_array(&ptr, prop, cage->scale);
|
||||
}
|
||||
RNA_property_update(C, &ptr, prop);
|
||||
}
|
||||
|
||||
/* tag the region for redraw */
|
||||
ED_region_tag_redraw(CTX_wm_region(C));
|
||||
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
static void widget_rect_transform_prop_data_update(wmWidget *widget, const int slot)
|
||||
{
|
||||
RectTransformWidget *cage = (RectTransformWidget *)widget;
|
||||
|
||||
if (slot == RECT_TRANSFORM_SLOT_OFFSET)
|
||||
widget_rect_transform_get_prop_value(widget, RECT_TRANSFORM_SLOT_OFFSET, widget->offset);
|
||||
if (slot == RECT_TRANSFORM_SLOT_SCALE)
|
||||
widget_rect_transform_get_prop_value(widget, RECT_TRANSFORM_SLOT_SCALE, cage->scale);
|
||||
}
|
||||
|
||||
static void widget_rect_transform_exit(bContext *C, wmWidget *widget, const bool cancel)
|
||||
{
|
||||
RectTransformWidget *cage = (RectTransformWidget *)widget;
|
||||
RectTransformInteraction *data = widget->interaction_data;
|
||||
|
||||
if (!cancel)
|
||||
return;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
RectTransformWidget *cage = MEM_callocN(sizeof(RectTransformWidget), name);
|
||||
|
||||
cage->widget.draw = widget_rect_transform_draw;
|
||||
cage->widget.invoke = widget_rect_transform_invoke;
|
||||
cage->widget.prop_data_update = widget_rect_transform_prop_data_update;
|
||||
cage->widget.handler = widget_rect_transform_handler;
|
||||
cage->widget.intersect = widget_rect_transform_intersect;
|
||||
cage->widget.exit = widget_rect_transform_exit;
|
||||
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;
|
||||
|
||||
wm_widget_register(wgroup, &cage->widget, name);
|
||||
|
||||
return (wmWidget *)cage;
|
||||
}
|
||||
|
||||
void WIDGET_rect_transform_set_dimensions(wmWidget *widget, const float width, const float height)
|
||||
{
|
||||
RectTransformWidget *cage = (RectTransformWidget *)widget;
|
||||
cage->w = width;
|
||||
cage->h = height;
|
||||
}
|
||||
|
||||
/** \} */ // Cage Widget API
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
void fix_linking_widget_cage(void)
|
||||
{
|
||||
(void)0;
|
||||
}
|
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2014 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/widget_library/dial_widget.c
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name Dial Widget
|
||||
*
|
||||
* 3D Widget
|
||||
*
|
||||
* \brief Circle shaped widget for circular interaction.
|
||||
* Currently no own handling, use with operator only.
|
||||
*/
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "GPU_select.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
/* own includes */
|
||||
#include "WM_widget_types.h"
|
||||
#include "WM_widget_library.h"
|
||||
#include "wm_widget_wmapi.h"
|
||||
#include "wm_widget_intern.h"
|
||||
#include "widget_geometry.h"
|
||||
#include "widget_library_intern.h"
|
||||
|
||||
|
||||
/* to use custom dials exported to dial_widget.c */
|
||||
//#define WIDGET_USE_CUSTOM_DIAS
|
||||
|
||||
#ifdef WIDGET_USE_CUSTOM_DIAS
|
||||
WidgetDrawInfo dial_draw_info = {0};
|
||||
#endif
|
||||
|
||||
typedef struct DialWidget {
|
||||
wmWidget widget;
|
||||
int style;
|
||||
float direction[3];
|
||||
} DialWidget;
|
||||
|
||||
typedef struct DialInteraction {
|
||||
float init_mval[2];
|
||||
|
||||
/* cache the last angle to detect rotations bigger than -/+ PI */
|
||||
float last_angle;
|
||||
/* number of full rotations */
|
||||
int rotations;
|
||||
} DialInteraction;
|
||||
|
||||
#define DIAL_WIDTH 1.0f
|
||||
#define DIAL_RESOLUTION 32
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void dial_geom_draw(const DialWidget *dial, const float col[4], const bool select)
|
||||
{
|
||||
#ifdef WIDGET_USE_CUSTOM_DIAS
|
||||
widget_draw_intern(&dial_draw_info, select);
|
||||
#else
|
||||
const bool filled = (dial->style == WIDGET_DIAL_STYLE_RING_FILLED);
|
||||
|
||||
glLineWidth(dial->widget.line_width);
|
||||
glColor4fv(col);
|
||||
|
||||
GLUquadricObj *qobj = gluNewQuadric();
|
||||
gluQuadricDrawStyle(qobj, filled ? GLU_FILL : GLU_SILHOUETTE);
|
||||
/* inner at 0.0 with silhouette drawing confuses OGL selection, so draw it at width */
|
||||
gluDisk(qobj, filled ? 0.0 : DIAL_WIDTH, DIAL_WIDTH, DIAL_RESOLUTION, 1);
|
||||
gluDeleteQuadric(qobj);
|
||||
|
||||
UNUSED_VARS(select);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a line from (0, 0, 0) to \a co_outer, at \a angle.
|
||||
*/
|
||||
static void dial_ghostarc_draw_helpline(const float angle, const float co_outer[3])
|
||||
{
|
||||
glLineWidth(1.0f);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(RAD2DEGF(angle), 0.0f, 0.0f, -1.0f);
|
||||
// glScalef(0.0f, DIAL_WIDTH - dial->widget.line_width * 0.5f / U.widget_scale, 0.0f);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
glVertex3fv(co_outer);
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
static void dial_ghostarc_draw(const DialWidget *dial, const float angle_ofs, const float angle_delta)
|
||||
{
|
||||
GLUquadricObj *qobj = gluNewQuadric();
|
||||
const float width_inner = DIAL_WIDTH - dial->widget.line_width * 0.5f / U.widget_scale;
|
||||
|
||||
gluQuadricDrawStyle(qobj, GLU_FILL);
|
||||
gluPartialDisk(qobj, 0.0, width_inner, DIAL_RESOLUTION, 1, RAD2DEGF(angle_ofs), RAD2DEGF(angle_delta));
|
||||
gluDeleteQuadric(qobj);
|
||||
}
|
||||
|
||||
static void dial_ghostarc_get_angles(
|
||||
const DialWidget *dial, const wmEvent *event, const ARegion *ar,
|
||||
float mat[4][4], const float co_outer[3],
|
||||
float *r_start, float *r_delta)
|
||||
{
|
||||
DialInteraction *inter = dial->widget.interaction_data;
|
||||
const RegionView3D *rv3d = ar->regiondata;
|
||||
const float mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin};
|
||||
bool inv = false;
|
||||
|
||||
/* we might need to invert the direction of the angles */
|
||||
float view_vec[3], axis_vec[3];
|
||||
ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], view_vec);
|
||||
normalize_v3_v3(axis_vec, dial->direction);
|
||||
if (dot_v3v3(view_vec, axis_vec) < 0.0f) {
|
||||
inv = true;
|
||||
}
|
||||
|
||||
float co[3], origin2d[2], co2d[2];
|
||||
mul_v3_project_m4_v3(co, mat, co_outer);
|
||||
/* project 3d coordinats to 2d viewplane */
|
||||
ED_view3d_project_float_global(ar, dial->widget.origin, origin2d, V3D_PROJ_TEST_NOP);
|
||||
ED_view3d_project_float_global(ar, co, co2d, V3D_PROJ_TEST_NOP);
|
||||
|
||||
/* convert to widget relative space */
|
||||
float rel_initmval[2], rel_mval[2], rel_co[2];
|
||||
sub_v2_v2v2(rel_initmval, inter->init_mval, origin2d);
|
||||
sub_v2_v2v2(rel_mval, mval, origin2d);
|
||||
sub_v2_v2v2(rel_co, co2d, origin2d);
|
||||
|
||||
/* return angles */
|
||||
const float start = angle_signed_v2v2(rel_co, rel_initmval) * (inv ? -1 : 1);
|
||||
const float delta = angle_signed_v2v2(rel_initmval, rel_mval) * (inv ? -1 : 1);
|
||||
|
||||
/* Change of sign, we passed the 180 degree threshold. This means we need to add a turn
|
||||
* to distinguish between transition from 0 to -1 and -PI to +PI, use comparison with PI/2.
|
||||
* Logic taken from BLI_dial_angle */
|
||||
if ((delta * inter->last_angle < 0.0f) &&
|
||||
(fabsf(inter->last_angle) > (float)M_PI_2))
|
||||
{
|
||||
if (inter->last_angle < 0.0f)
|
||||
inter->rotations--;
|
||||
else
|
||||
inter->rotations++;
|
||||
}
|
||||
inter->last_angle = delta;
|
||||
|
||||
*r_start = start;
|
||||
*r_delta = fmod(delta + 2.0f * (float)M_PI * inter->rotations, 2 * (float)M_PI);
|
||||
}
|
||||
|
||||
static void dial_draw_intern(const bContext *C, DialWidget *dial, const bool select, const bool highlight)
|
||||
{
|
||||
float rot[3][3];
|
||||
float mat[4][4];
|
||||
const float up[3] = {0.0f, 0.0f, 1.0f};
|
||||
const float *col = widget_color_get(&dial->widget, highlight);
|
||||
|
||||
BLI_assert(CTX_wm_area(C)->spacetype == SPACE_VIEW3D);
|
||||
|
||||
rotation_between_vecs_to_mat3(rot, up, dial->direction);
|
||||
copy_m4_m3(mat, rot);
|
||||
copy_v3_v3(mat[3], dial->widget.origin);
|
||||
mul_mat3_m4_fl(mat, dial->widget.scale);
|
||||
|
||||
glPushMatrix();
|
||||
glMultMatrixf(mat);
|
||||
glTranslate3fv(dial->widget.offset);
|
||||
|
||||
/* draw rotation indicator arc first */
|
||||
if ((dial->widget.flag & WM_WIDGET_DRAW_VALUE) && (dial->widget.flag & WM_WIDGET_ACTIVE)) {
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f}; /* coordinate at which the arc drawing will be started */
|
||||
float angle_ofs, angle_delta;
|
||||
|
||||
dial_ghostarc_get_angles(dial, win->eventstate, CTX_wm_region(C), mat, co_outer, &angle_ofs, &angle_delta);
|
||||
/* draw! */
|
||||
glColor4f(0.8f, 0.8f, 0.8f, 0.4f);
|
||||
dial_ghostarc_draw(dial, angle_ofs, angle_delta);
|
||||
|
||||
glColor4fv(col);
|
||||
dial_ghostarc_draw_helpline(angle_ofs, co_outer); /* starting position */
|
||||
dial_ghostarc_draw_helpline(angle_ofs + angle_delta, co_outer); /* starting position + current value */
|
||||
}
|
||||
|
||||
/* draw actual dial widget */
|
||||
dial_geom_draw(dial, col, select);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
}
|
||||
|
||||
static void widget_dial_render_3d_intersect(const bContext *C, wmWidget *widget, int selectionbase)
|
||||
{
|
||||
DialWidget *dial = (DialWidget *)widget;
|
||||
|
||||
/* enable clipping if needed */
|
||||
if (dial->style == WIDGET_DIAL_STYLE_RING_CLIPPED) {
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
double plane[4];
|
||||
|
||||
copy_v3db_v3fl(plane, rv3d->viewinv[2]);
|
||||
plane[3] = -dot_v3v3(rv3d->viewinv[2], widget->origin);
|
||||
glClipPlane(GL_CLIP_PLANE0, plane);
|
||||
glEnable(GL_CLIP_PLANE0);
|
||||
}
|
||||
|
||||
GPU_select_load_id(selectionbase);
|
||||
dial_draw_intern(C, dial, true, false);
|
||||
|
||||
if (dial->style == WIDGET_DIAL_STYLE_RING_CLIPPED) {
|
||||
glDisable(GL_CLIP_PLANE0);
|
||||
}
|
||||
}
|
||||
|
||||
static void widget_dial_draw(const bContext *C, wmWidget *widget)
|
||||
{
|
||||
DialWidget *dial = (DialWidget *)widget;
|
||||
const bool active = widget->flag & WM_WIDGET_ACTIVE;
|
||||
|
||||
/* enable clipping if needed */
|
||||
if (!active && dial->style == WIDGET_DIAL_STYLE_RING_CLIPPED) {
|
||||
double plane[4];
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
|
||||
copy_v3db_v3fl(plane, rv3d->viewinv[2]);
|
||||
plane[3] = -dot_v3v3(rv3d->viewinv[2], widget->origin);
|
||||
glClipPlane(GL_CLIP_PLANE0, plane);
|
||||
glEnable(GL_CLIP_PLANE0);
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
dial_draw_intern(C, dial, false, (widget->flag & WM_WIDGET_HIGHLIGHT) != 0);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
if (!active && dial->style == WIDGET_DIAL_STYLE_RING_CLIPPED) {
|
||||
glDisable(GL_CLIP_PLANE0);
|
||||
}
|
||||
}
|
||||
|
||||
static int widget_dial_invoke(bContext *UNUSED(C), const wmEvent *event, wmWidget *widget)
|
||||
{
|
||||
DialInteraction *inter = MEM_callocN(sizeof(DialInteraction), __func__);
|
||||
|
||||
inter->init_mval[0] = event->mval[0];
|
||||
inter->init_mval[1] = event->mval[1];
|
||||
|
||||
widget->interaction_data = inter;
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Dial Widget API
|
||||
*
|
||||
* \{ */
|
||||
|
||||
wmWidget *WIDGET_dial_new(wmWidgetGroup *wgroup, const char *name, const int style)
|
||||
{
|
||||
DialWidget *dial = MEM_callocN(sizeof(DialWidget), name);
|
||||
const float dir_default[3] = {0.0f, 0.0f, 1.0f};
|
||||
|
||||
#ifdef WIDGET_USE_CUSTOM_DIAS
|
||||
if (!dial_draw_info.init) {
|
||||
dial_draw_info.nverts = _WIDGET_nverts_dial,
|
||||
dial_draw_info.ntris = _WIDGET_ntris_dial,
|
||||
dial_draw_info.verts = _WIDGET_verts_dial,
|
||||
dial_draw_info.normals = _WIDGET_normals_dial,
|
||||
dial_draw_info.indices = _WIDGET_indices_dial,
|
||||
dial_draw_info.init = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
dial->widget.draw = widget_dial_draw;
|
||||
dial->widget.intersect = NULL;
|
||||
dial->widget.render_3d_intersection = widget_dial_render_3d_intersect;
|
||||
dial->widget.invoke = widget_dial_invoke;
|
||||
dial->widget.flag |= WM_WIDGET_SCALE_3D;
|
||||
|
||||
dial->style = style;
|
||||
|
||||
/* defaults */
|
||||
copy_v3_v3(dial->direction, dir_default);
|
||||
|
||||
wm_widget_register(wgroup, &dial->widget, name);
|
||||
|
||||
return (wmWidget *)dial;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define up-direction of the dial widget
|
||||
*/
|
||||
void WIDGET_dial_set_up_vector(wmWidget *widget, const float direction[3])
|
||||
{
|
||||
DialWidget *dial = (DialWidget *)widget;
|
||||
|
||||
copy_v3_v3(dial->direction, direction);
|
||||
normalize_v3(dial->direction);
|
||||
}
|
||||
|
||||
/** \} */ // Dial Widget API
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
void fix_linking_widget_dial(void)
|
||||
{
|
||||
(void)0;
|
||||
}
|
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/widget_library/geom_arrow_widget.c
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
int _WIDGET_nverts_arrow = 25;
|
||||
int _WIDGET_ntris_arrow = 46;
|
||||
|
||||
float _WIDGET_verts_arrow[][3] = {
|
||||
{-0.000000, 0.012320, 0.000000},
|
||||
{-0.000000, 0.012320, 0.974306},
|
||||
{0.008711, 0.008711, 0.000000},
|
||||
{0.008711, 0.008711, 0.974306},
|
||||
{0.012320, -0.000000, 0.000000},
|
||||
{0.012320, -0.000000, 0.974306},
|
||||
{0.008711, -0.008711, 0.000000},
|
||||
{0.008711, -0.008711, 0.974306},
|
||||
{-0.000000, -0.012320, 0.000000},
|
||||
{-0.000000, -0.012320, 0.974306},
|
||||
{-0.008711, -0.008711, 0.000000},
|
||||
{-0.008711, -0.008711, 0.974306},
|
||||
{-0.012320, 0.000000, 0.000000},
|
||||
{-0.012320, 0.000000, 0.974306},
|
||||
{-0.008711, 0.008711, 0.000000},
|
||||
{-0.008711, 0.008711, 0.974306},
|
||||
{0.000000, 0.072555, 0.974306},
|
||||
{0.051304, 0.051304, 0.974306},
|
||||
{0.072555, -0.000000, 0.974306},
|
||||
{0.051304, -0.051304, 0.974306},
|
||||
{-0.000000, -0.072555, 0.974306},
|
||||
{-0.051304, -0.051304, 0.974306},
|
||||
{-0.072555, 0.000000, 0.974306},
|
||||
{-0.051304, 0.051304, 0.974306},
|
||||
{0.000000, -0.000000, 1.268098},
|
||||
};
|
||||
|
||||
float _WIDGET_normals_arrow[][3] = {
|
||||
{0.000000, 0.776360, -0.630238},
|
||||
{0.000000, 0.594348, -0.804163},
|
||||
{0.548967, 0.548967, -0.630238},
|
||||
{0.420270, 0.420270, -0.804163},
|
||||
{0.776360, 0.000000, -0.630238},
|
||||
{0.594378, 0.000000, -0.804163},
|
||||
{0.548967, -0.548967, -0.630238},
|
||||
{0.420270, -0.420270, -0.804163},
|
||||
{0.000000, -0.776360, -0.630238},
|
||||
{0.000000, -0.594378, -0.804163},
|
||||
{-0.548967, -0.548967, -0.630238},
|
||||
{-0.420270, -0.420270, -0.804163},
|
||||
{-0.776360, 0.000000, -0.630238},
|
||||
{-0.594378, 0.000000, -0.804163},
|
||||
{-0.548967, 0.548967, -0.630238},
|
||||
{-0.420270, 0.420270, -0.804163},
|
||||
{0.000000, 0.843226, -0.537492},
|
||||
{0.596271, 0.596271, -0.537492},
|
||||
{0.843226, 0.000000, -0.537492},
|
||||
{0.596271, -0.596271, -0.537492},
|
||||
{0.000000, -0.843226, -0.537492},
|
||||
{-0.596271, -0.596271, -0.537492},
|
||||
{-0.843226, 0.000000, -0.537492},
|
||||
{-0.596271, 0.596271, -0.537492},
|
||||
{0.000000, 0.000000, 1.000000},
|
||||
};
|
||||
|
||||
unsigned short _WIDGET_indices_arrow[] = {
|
||||
1, 3, 2,
|
||||
3, 5, 4,
|
||||
5, 7, 6,
|
||||
7, 9, 8,
|
||||
9, 11, 10,
|
||||
11, 13, 12,
|
||||
5, 18, 19,
|
||||
15, 1, 0,
|
||||
13, 15, 14,
|
||||
6, 10, 14,
|
||||
11, 21, 22,
|
||||
7, 19, 20,
|
||||
13, 22, 23,
|
||||
3, 17, 18,
|
||||
9, 20, 21,
|
||||
15, 23, 16,
|
||||
1, 16, 17,
|
||||
23, 22, 24,
|
||||
21, 20, 24,
|
||||
19, 18, 24,
|
||||
17, 16, 24,
|
||||
16, 23, 24,
|
||||
22, 21, 24,
|
||||
20, 19, 24,
|
||||
18, 17, 24,
|
||||
0, 1, 2,
|
||||
2, 3, 4,
|
||||
4, 5, 6,
|
||||
6, 7, 8,
|
||||
8, 9, 10,
|
||||
10, 11, 12,
|
||||
7, 5, 19,
|
||||
14, 15, 0,
|
||||
12, 13, 14,
|
||||
14, 0, 2,
|
||||
2, 4, 6,
|
||||
6, 8, 10,
|
||||
10, 12, 14,
|
||||
14, 2, 6,
|
||||
13, 11, 22,
|
||||
9, 7, 20,
|
||||
15, 13, 23,
|
||||
5, 3, 18,
|
||||
11, 9, 21,
|
||||
1, 15, 16,
|
||||
3, 1, 17,
|
||||
};
|
||||
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/widget_library/geom_cube_widget.c
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
int _WIDGET_nverts_cube = 8;
|
||||
int _WIDGET_ntris_cube = 12;
|
||||
|
||||
float _WIDGET_verts_cube[][3] = {
|
||||
{1.000000, 1.000000, -1.000000},
|
||||
{1.000000, -1.000000, -1.000000},
|
||||
{-1.000000, -1.000000, -1.000000},
|
||||
{-1.000000, 1.000000, -1.000000},
|
||||
{1.000000, 1.000000, 1.000000},
|
||||
{0.999999, -1.000001, 1.000000},
|
||||
{-1.000000, -1.000000, 1.000000},
|
||||
{-1.000000, 1.000000, 1.000000},
|
||||
};
|
||||
|
||||
float _WIDGET_normals_cube[][3] = {
|
||||
{0.577349, 0.577349, -0.577349},
|
||||
{0.577349, -0.577349, -0.577349},
|
||||
{-0.577349, -0.577349, -0.577349},
|
||||
{-0.577349, 0.577349, -0.577349},
|
||||
{0.577349, 0.577349, 0.577349},
|
||||
{0.577349, -0.577349, 0.577349},
|
||||
{-0.577349, -0.577349, 0.577349},
|
||||
{-0.577349, 0.577349, 0.577349},
|
||||
};
|
||||
|
||||
unsigned short _WIDGET_indices_cube[] = {
|
||||
1, 2, 3,
|
||||
7, 6, 5,
|
||||
4, 5, 1,
|
||||
5, 6, 2,
|
||||
2, 6, 7,
|
||||
0, 3, 7,
|
||||
0, 1, 3,
|
||||
4, 7, 5,
|
||||
0, 4, 1,
|
||||
1, 5, 2,
|
||||
3, 2, 7,
|
||||
4, 0, 7,
|
||||
};
|
||||
|
@@ -0,0 +1,809 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/widget_library/geom_dial_widget.c
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
int _WIDGET_nverts_dial = 192;
|
||||
int _WIDGET_ntris_dial = 384;
|
||||
|
||||
float _WIDGET_verts_dial[][3] = {
|
||||
{1.034000, 0.000000, 0.000000},
|
||||
{1.017000, 0.000000, 0.029445},
|
||||
{0.983000, 0.000000, 0.029445},
|
||||
{0.966000, 0.000000, 0.000000},
|
||||
{0.983000, 0.000000, -0.029445},
|
||||
{1.017000, 0.000000, -0.029445},
|
||||
{1.014132, 0.201723, 0.000000},
|
||||
{0.997459, 0.198407, 0.029445},
|
||||
{0.964112, 0.191774, 0.029445},
|
||||
{0.947439, 0.188457, 0.000000},
|
||||
{0.964112, 0.191774, -0.029445},
|
||||
{0.997459, 0.198407, -0.029445},
|
||||
{0.955292, 0.395695, 0.000000},
|
||||
{0.939586, 0.389189, 0.029445},
|
||||
{0.908174, 0.376178, 0.029445},
|
||||
{0.892468, 0.369672, 0.000000},
|
||||
{0.908174, 0.376178, -0.029445},
|
||||
{0.939586, 0.389189, -0.029445},
|
||||
{0.859740, 0.574460, 0.000000},
|
||||
{0.845605, 0.565015, 0.029445},
|
||||
{0.817335, 0.546126, 0.029445},
|
||||
{0.803200, 0.536681, 0.000000},
|
||||
{0.817335, 0.546126, -0.029445},
|
||||
{0.845605, 0.565015, -0.029445},
|
||||
{0.731148, 0.731148, 0.000000},
|
||||
{0.719128, 0.719128, 0.029445},
|
||||
{0.695086, 0.695086, 0.029445},
|
||||
{0.683065, 0.683065, 0.000000},
|
||||
{0.695086, 0.695086, -0.029445},
|
||||
{0.719128, 0.719128, -0.029445},
|
||||
{0.574460, 0.859740, 0.000000},
|
||||
{0.565015, 0.845605, 0.029445},
|
||||
{0.546125, 0.817335, 0.029445},
|
||||
{0.536681, 0.803200, 0.000000},
|
||||
{0.546125, 0.817335, -0.029445},
|
||||
{0.565015, 0.845605, -0.029445},
|
||||
{0.395695, 0.955291, 0.000000},
|
||||
{0.389189, 0.939585, 0.029445},
|
||||
{0.376178, 0.908173, 0.029445},
|
||||
{0.369672, 0.892467, 0.000000},
|
||||
{0.376178, 0.908173, -0.029445},
|
||||
{0.389189, 0.939585, -0.029445},
|
||||
{0.201724, 1.014132, 0.000000},
|
||||
{0.198407, 0.997459, 0.029445},
|
||||
{0.191774, 0.964112, 0.029445},
|
||||
{0.188457, 0.947439, 0.000000},
|
||||
{0.191774, 0.964112, -0.029445},
|
||||
{0.198407, 0.997459, -0.029445},
|
||||
{0.000000, 1.034000, 0.000000},
|
||||
{0.000000, 1.017000, 0.029445},
|
||||
{0.000000, 0.983000, 0.029445},
|
||||
{0.000000, 0.966000, 0.000000},
|
||||
{0.000000, 0.983000, -0.029445},
|
||||
{0.000000, 1.017000, -0.029445},
|
||||
{-0.201723, 1.014132, 0.000000},
|
||||
{-0.198407, 0.997459, 0.029445},
|
||||
{-0.191774, 0.964112, 0.029445},
|
||||
{-0.188457, 0.947439, 0.000000},
|
||||
{-0.191774, 0.964112, -0.029445},
|
||||
{-0.198407, 0.997459, -0.029445},
|
||||
{-0.395695, 0.955291, 0.000000},
|
||||
{-0.389189, 0.939585, 0.029445},
|
||||
{-0.376178, 0.908174, 0.029445},
|
||||
{-0.369672, 0.892468, 0.000000},
|
||||
{-0.376178, 0.908174, -0.029445},
|
||||
{-0.389189, 0.939585, -0.029445},
|
||||
{-0.574459, 0.859740, 0.000000},
|
||||
{-0.565015, 0.845605, 0.029445},
|
||||
{-0.546125, 0.817335, 0.029445},
|
||||
{-0.536681, 0.803200, 0.000000},
|
||||
{-0.546125, 0.817335, -0.029445},
|
||||
{-0.565015, 0.845605, -0.029445},
|
||||
{-0.731149, 0.731148, 0.000000},
|
||||
{-0.719128, 0.719127, 0.029445},
|
||||
{-0.695086, 0.695086, 0.029445},
|
||||
{-0.683065, 0.683065, 0.000000},
|
||||
{-0.695086, 0.695086, -0.029445},
|
||||
{-0.719128, 0.719127, -0.029445},
|
||||
{-0.859740, 0.574460, 0.000000},
|
||||
{-0.845604, 0.565015, 0.029445},
|
||||
{-0.817335, 0.546126, 0.029445},
|
||||
{-0.803200, 0.536681, 0.000000},
|
||||
{-0.817335, 0.546126, -0.029445},
|
||||
{-0.845604, 0.565015, -0.029445},
|
||||
{-0.955291, 0.395695, 0.000000},
|
||||
{-0.939585, 0.389189, 0.029445},
|
||||
{-0.908173, 0.376178, 0.029445},
|
||||
{-0.892468, 0.369672, 0.000000},
|
||||
{-0.908173, 0.376178, -0.029445},
|
||||
{-0.939585, 0.389189, -0.029445},
|
||||
{-1.014132, 0.201723, 0.000000},
|
||||
{-0.997459, 0.198407, 0.029445},
|
||||
{-0.964112, 0.191774, 0.029445},
|
||||
{-0.947439, 0.188457, 0.000000},
|
||||
{-0.964112, 0.191774, -0.029445},
|
||||
{-0.997459, 0.198407, -0.029445},
|
||||
{-1.034000, 0.000000, 0.000000},
|
||||
{-1.017000, 0.000000, 0.029445},
|
||||
{-0.983000, 0.000000, 0.029445},
|
||||
{-0.966000, 0.000000, 0.000000},
|
||||
{-0.983000, 0.000000, -0.029445},
|
||||
{-1.017000, 0.000000, -0.029445},
|
||||
{-1.014132, -0.201723, 0.000000},
|
||||
{-0.997459, -0.198407, 0.029445},
|
||||
{-0.964112, -0.191774, 0.029445},
|
||||
{-0.947439, -0.188457, 0.000000},
|
||||
{-0.964112, -0.191774, -0.029445},
|
||||
{-0.997459, -0.198407, -0.029445},
|
||||
{-0.955292, -0.395694, 0.000000},
|
||||
{-0.939586, -0.389189, 0.029445},
|
||||
{-0.908174, -0.376177, 0.029445},
|
||||
{-0.892468, -0.369672, 0.000000},
|
||||
{-0.908174, -0.376177, -0.029445},
|
||||
{-0.939586, -0.389189, -0.029445},
|
||||
{-0.859740, -0.574460, 0.000000},
|
||||
{-0.845604, -0.565015, 0.029445},
|
||||
{-0.817335, -0.546126, 0.029445},
|
||||
{-0.803200, -0.536681, 0.000000},
|
||||
{-0.817335, -0.546126, -0.029445},
|
||||
{-0.845604, -0.565015, -0.029445},
|
||||
{-0.731149, -0.731148, 0.000000},
|
||||
{-0.719128, -0.719127, 0.029445},
|
||||
{-0.695086, -0.695086, 0.029445},
|
||||
{-0.683065, -0.683065, 0.000000},
|
||||
{-0.695086, -0.695086, -0.029445},
|
||||
{-0.719128, -0.719127, -0.029445},
|
||||
{-0.574460, -0.859739, 0.000000},
|
||||
{-0.565015, -0.845604, 0.029445},
|
||||
{-0.546126, -0.817334, 0.029445},
|
||||
{-0.536681, -0.803199, 0.000000},
|
||||
{-0.546126, -0.817334, -0.029445},
|
||||
{-0.565015, -0.845604, -0.029445},
|
||||
{-0.395695, -0.955291, 0.000000},
|
||||
{-0.389189, -0.939585, 0.029445},
|
||||
{-0.376178, -0.908174, 0.029445},
|
||||
{-0.369672, -0.892468, 0.000000},
|
||||
{-0.376178, -0.908174, -0.029445},
|
||||
{-0.389189, -0.939585, -0.029445},
|
||||
{-0.201724, -1.014132, 0.000000},
|
||||
{-0.198407, -0.997459, 0.029445},
|
||||
{-0.191774, -0.964112, 0.029445},
|
||||
{-0.188458, -0.947438, 0.000000},
|
||||
{-0.191774, -0.964112, -0.029445},
|
||||
{-0.198407, -0.997459, -0.029445},
|
||||
{0.000000, -1.034000, 0.000000},
|
||||
{0.000000, -1.017000, 0.029445},
|
||||
{0.000000, -0.983000, 0.029445},
|
||||
{0.000000, -0.966000, 0.000000},
|
||||
{0.000000, -0.983000, -0.029445},
|
||||
{0.000000, -1.017000, -0.029445},
|
||||
{0.201723, -1.014132, 0.000000},
|
||||
{0.198407, -0.997459, 0.029445},
|
||||
{0.191773, -0.964112, 0.029445},
|
||||
{0.188457, -0.947439, 0.000000},
|
||||
{0.191773, -0.964112, -0.029445},
|
||||
{0.198407, -0.997459, -0.029445},
|
||||
{0.395695, -0.955291, 0.000000},
|
||||
{0.389189, -0.939585, 0.029445},
|
||||
{0.376178, -0.908173, 0.029445},
|
||||
{0.369672, -0.892467, 0.000000},
|
||||
{0.376178, -0.908173, -0.029445},
|
||||
{0.389189, -0.939585, -0.029445},
|
||||
{0.574460, -0.859740, 0.000000},
|
||||
{0.565015, -0.845605, 0.029445},
|
||||
{0.546125, -0.817335, 0.029445},
|
||||
{0.536681, -0.803200, 0.000000},
|
||||
{0.546125, -0.817335, -0.029445},
|
||||
{0.565015, -0.845605, -0.029445},
|
||||
{0.731148, -0.731149, 0.000000},
|
||||
{0.719127, -0.719128, 0.029445},
|
||||
{0.695086, -0.695086, 0.029445},
|
||||
{0.683065, -0.683066, 0.000000},
|
||||
{0.695086, -0.695086, -0.029445},
|
||||
{0.719127, -0.719128, -0.029445},
|
||||
{0.859740, -0.574460, 0.000000},
|
||||
{0.845605, -0.565015, 0.029445},
|
||||
{0.817335, -0.546126, 0.029445},
|
||||
{0.803200, -0.536681, 0.000000},
|
||||
{0.817335, -0.546126, -0.029445},
|
||||
{0.845605, -0.565015, -0.029445},
|
||||
{0.955291, -0.395695, 0.000000},
|
||||
{0.939585, -0.389189, 0.029445},
|
||||
{0.908173, -0.376178, 0.029445},
|
||||
{0.892467, -0.369673, 0.000000},
|
||||
{0.908173, -0.376178, -0.029445},
|
||||
{0.939585, -0.389189, -0.029445},
|
||||
{1.014132, -0.201723, 0.000000},
|
||||
{0.997459, -0.198407, 0.029445},
|
||||
{0.964112, -0.191774, 0.029445},
|
||||
{0.947439, -0.188457, 0.000000},
|
||||
{0.964112, -0.191774, -0.029445},
|
||||
{0.997459, -0.198407, -0.029445},
|
||||
};
|
||||
|
||||
float _WIDGET_normals_dial[][3] = {
|
||||
{1.000000, 0.000000, 0.000000},
|
||||
{0.522691, 0.000000, 0.852504},
|
||||
{-0.475845, 0.000000, 0.879513},
|
||||
{-1.000000, 0.000000, 0.000000},
|
||||
{-0.475845, 0.000000, -0.879513},
|
||||
{0.522691, 0.000000, -0.852504},
|
||||
{0.980773, 0.195074, 0.000000},
|
||||
{0.512650, 0.101962, 0.852504},
|
||||
{-0.466689, -0.092807, 0.879513},
|
||||
{-0.980773, -0.195074, 0.000000},
|
||||
{-0.466689, -0.092807, -0.879513},
|
||||
{0.512650, 0.101962, -0.852504},
|
||||
{0.923856, 0.382672, 0.000000},
|
||||
{0.482894, 0.200018, 0.852504},
|
||||
{-0.439619, -0.182073, 0.879513},
|
||||
{-0.923856, -0.382672, 0.000000},
|
||||
{-0.439619, -0.182073, -0.879513},
|
||||
{0.482894, 0.200018, -0.852504},
|
||||
{0.831446, 0.555559, 0.000000},
|
||||
{0.434614, 0.290384, 0.852504},
|
||||
{-0.395642, -0.264351, 0.879513},
|
||||
{-0.831446, -0.555559, 0.000000},
|
||||
{-0.395642, -0.264351, -0.879513},
|
||||
{0.434614, 0.290384, -0.852504},
|
||||
{0.707083, 0.707083, 0.000000},
|
||||
{0.369610, 0.369610, 0.852504},
|
||||
{-0.336467, -0.336467, 0.879513},
|
||||
{-0.707083, -0.707083, 0.000000},
|
||||
{-0.336467, -0.336467, -0.879513},
|
||||
{0.369610, 0.369610, -0.852504},
|
||||
{0.555559, 0.831446, 0.000000},
|
||||
{0.290384, 0.434614, 0.852504},
|
||||
{-0.264351, -0.395642, 0.879513},
|
||||
{-0.555559, -0.831446, 0.000000},
|
||||
{-0.264351, -0.395642, -0.879513},
|
||||
{0.290384, 0.434614, -0.852504},
|
||||
{0.382672, 0.923856, 0.000000},
|
||||
{0.200018, 0.482894, 0.852504},
|
||||
{-0.182073, -0.439619, 0.879513},
|
||||
{-0.382672, -0.923856, 0.000000},
|
||||
{-0.182073, -0.439619, -0.879513},
|
||||
{0.200018, 0.482894, -0.852504},
|
||||
{0.195074, 0.980773, 0.000000},
|
||||
{0.101962, 0.512650, 0.852504},
|
||||
{-0.092807, -0.466689, 0.879513},
|
||||
{-0.195074, -0.980773, 0.000000},
|
||||
{-0.092807, -0.466689, -0.879513},
|
||||
{0.101962, 0.512650, -0.852504},
|
||||
{0.000000, 1.000000, 0.000000},
|
||||
{0.000000, 0.522691, 0.852504},
|
||||
{0.000000, -0.475845, 0.879513},
|
||||
{0.000000, -1.000000, 0.000000},
|
||||
{0.000000, -0.475845, -0.879513},
|
||||
{0.000000, 0.522691, -0.852504},
|
||||
{-0.195074, 0.980773, 0.000000},
|
||||
{-0.101962, 0.512650, 0.852504},
|
||||
{0.092807, -0.466689, 0.879513},
|
||||
{0.195074, -0.980773, 0.000000},
|
||||
{0.092807, -0.466689, -0.879513},
|
||||
{-0.101962, 0.512650, -0.852504},
|
||||
{-0.382672, 0.923856, 0.000000},
|
||||
{-0.200018, 0.482894, 0.852504},
|
||||
{0.182073, -0.439619, 0.879513},
|
||||
{0.382672, -0.923856, 0.000000},
|
||||
{0.182073, -0.439619, -0.879513},
|
||||
{-0.200018, 0.482894, -0.852504},
|
||||
{-0.555559, 0.831446, 0.000000},
|
||||
{-0.290384, 0.434614, 0.852504},
|
||||
{0.264351, -0.395642, 0.879513},
|
||||
{0.555559, -0.831446, 0.000000},
|
||||
{0.264351, -0.395642, -0.879513},
|
||||
{-0.290384, 0.434614, -0.852504},
|
||||
{-0.707083, 0.707083, 0.000000},
|
||||
{-0.369610, 0.369610, 0.852504},
|
||||
{0.336467, -0.336467, 0.879513},
|
||||
{0.707083, -0.707083, 0.000000},
|
||||
{0.336467, -0.336467, -0.879513},
|
||||
{-0.369610, 0.369610, -0.852504},
|
||||
{-0.831446, 0.555559, 0.000000},
|
||||
{-0.434614, 0.290384, 0.852504},
|
||||
{0.395642, -0.264351, 0.879513},
|
||||
{0.831446, -0.555559, 0.000000},
|
||||
{0.395642, -0.264351, -0.879513},
|
||||
{-0.434614, 0.290384, -0.852504},
|
||||
{-0.923856, 0.382672, 0.000000},
|
||||
{-0.482894, 0.200018, 0.852504},
|
||||
{0.439619, -0.182073, 0.879513},
|
||||
{0.923856, -0.382672, 0.000000},
|
||||
{0.439619, -0.182073, -0.879513},
|
||||
{-0.482894, 0.200018, -0.852504},
|
||||
{-0.980773, 0.195074, 0.000000},
|
||||
{-0.512650, 0.101962, 0.852504},
|
||||
{0.466689, -0.092807, 0.879513},
|
||||
{0.980773, -0.195074, 0.000000},
|
||||
{0.466689, -0.092807, -0.879513},
|
||||
{-0.512650, 0.101962, -0.852504},
|
||||
{-1.000000, 0.000000, 0.000000},
|
||||
{-0.522691, 0.000000, 0.852504},
|
||||
{0.475845, 0.000000, 0.879513},
|
||||
{1.000000, 0.000000, 0.000000},
|
||||
{0.475845, 0.000000, -0.879513},
|
||||
{-0.522691, 0.000000, -0.852504},
|
||||
{-0.980773, -0.195074, 0.000000},
|
||||
{-0.512650, -0.101962, 0.852504},
|
||||
{0.466689, 0.092807, 0.879513},
|
||||
{0.980773, 0.195074, 0.000000},
|
||||
{0.466689, 0.092807, -0.879513},
|
||||
{-0.512650, -0.101962, -0.852504},
|
||||
{-0.923856, -0.382672, 0.000000},
|
||||
{-0.482894, -0.200018, 0.852504},
|
||||
{0.439619, 0.182073, 0.879513},
|
||||
{0.923856, 0.382672, 0.000000},
|
||||
{0.439619, 0.182073, -0.879513},
|
||||
{-0.482894, -0.200018, -0.852504},
|
||||
{-0.831446, -0.555559, 0.000000},
|
||||
{-0.434614, -0.290384, 0.852504},
|
||||
{0.395642, 0.264351, 0.879513},
|
||||
{0.831446, 0.555559, 0.000000},
|
||||
{0.395642, 0.264351, -0.879513},
|
||||
{-0.434614, -0.290384, -0.852504},
|
||||
{-0.707083, -0.707083, 0.000000},
|
||||
{-0.369610, -0.369610, 0.852504},
|
||||
{0.336467, 0.336467, 0.879513},
|
||||
{0.707083, 0.707083, 0.000000},
|
||||
{0.336467, 0.336467, -0.879513},
|
||||
{-0.369610, -0.369610, -0.852504},
|
||||
{-0.555559, -0.831446, 0.000000},
|
||||
{-0.290384, -0.434614, 0.852504},
|
||||
{0.264351, 0.395642, 0.879513},
|
||||
{0.555559, 0.831446, 0.000000},
|
||||
{0.264351, 0.395642, -0.879513},
|
||||
{-0.290384, -0.434614, -0.852504},
|
||||
{-0.382672, -0.923856, 0.000000},
|
||||
{-0.200018, -0.482894, 0.852504},
|
||||
{0.182073, 0.439619, 0.879513},
|
||||
{0.382672, 0.923856, 0.000000},
|
||||
{0.182073, 0.439619, -0.879513},
|
||||
{-0.200018, -0.482894, -0.852504},
|
||||
{-0.195074, -0.980773, 0.000000},
|
||||
{-0.101962, -0.512650, 0.852504},
|
||||
{0.092807, 0.466689, 0.879513},
|
||||
{0.195074, 0.980773, 0.000000},
|
||||
{0.092807, 0.466689, -0.879513},
|
||||
{-0.101962, -0.512650, -0.852504},
|
||||
{0.000000, -1.000000, 0.000000},
|
||||
{0.000000, -0.522691, 0.852504},
|
||||
{0.000000, 0.475845, 0.879513},
|
||||
{0.000000, 1.000000, 0.000000},
|
||||
{0.000000, 0.475845, -0.879513},
|
||||
{0.000000, -0.522691, -0.852504},
|
||||
{0.195074, -0.980773, 0.000000},
|
||||
{0.101962, -0.512650, 0.852504},
|
||||
{-0.092807, 0.466689, 0.879513},
|
||||
{-0.195074, 0.980773, 0.000000},
|
||||
{-0.092807, 0.466689, -0.879513},
|
||||
{0.101962, -0.512650, -0.852504},
|
||||
{0.382672, -0.923856, 0.000000},
|
||||
{0.200018, -0.482894, 0.852504},
|
||||
{-0.182073, 0.439619, 0.879513},
|
||||
{-0.382672, 0.923856, 0.000000},
|
||||
{-0.182073, 0.439619, -0.879513},
|
||||
{0.200018, -0.482894, -0.852504},
|
||||
{0.555559, -0.831446, 0.000000},
|
||||
{0.290384, -0.434614, 0.852504},
|
||||
{-0.264351, 0.395642, 0.879513},
|
||||
{-0.555559, 0.831446, 0.000000},
|
||||
{-0.264351, 0.395642, -0.879513},
|
||||
{0.290384, -0.434614, -0.852504},
|
||||
{0.707083, -0.707083, 0.000000},
|
||||
{0.369610, -0.369610, 0.852504},
|
||||
{-0.336467, 0.336467, 0.879513},
|
||||
{-0.707083, 0.707083, 0.000000},
|
||||
{-0.336467, 0.336467, -0.879513},
|
||||
{0.369610, -0.369610, -0.852504},
|
||||
{0.831446, -0.555559, 0.000000},
|
||||
{0.434614, -0.290384, 0.852504},
|
||||
{-0.395642, 0.264351, 0.879513},
|
||||
{-0.831446, 0.555559, 0.000000},
|
||||
{-0.395642, 0.264351, -0.879513},
|
||||
{0.434614, -0.290384, -0.852504},
|
||||
{0.923856, -0.382672, 0.000000},
|
||||
{0.482894, -0.200018, 0.852504},
|
||||
{-0.439619, 0.182073, 0.879513},
|
||||
{-0.923856, 0.382672, 0.000000},
|
||||
{-0.439619, 0.182073, -0.879513},
|
||||
{0.482894, -0.200018, -0.852504},
|
||||
{0.980773, -0.195074, 0.000000},
|
||||
{0.512650, -0.101962, 0.852504},
|
||||
{-0.466689, 0.092807, 0.879513},
|
||||
{-0.980773, 0.195074, 0.000000},
|
||||
{-0.466689, 0.092807, -0.879513},
|
||||
{0.512650, -0.101962, -0.852504},
|
||||
};
|
||||
|
||||
unsigned short _WIDGET_indices_dial[] = {
|
||||
6, 7, 1,
|
||||
7, 8, 2,
|
||||
8, 9, 3,
|
||||
9, 10, 4,
|
||||
10, 11, 5,
|
||||
5, 11, 6,
|
||||
12, 13, 7,
|
||||
13, 14, 8,
|
||||
14, 15, 9,
|
||||
15, 16, 10,
|
||||
16, 17, 11,
|
||||
11, 17, 12,
|
||||
18, 19, 13,
|
||||
13, 19, 20,
|
||||
20, 21, 15,
|
||||
15, 21, 22,
|
||||
22, 23, 17,
|
||||
17, 23, 18,
|
||||
24, 25, 19,
|
||||
19, 25, 26,
|
||||
26, 27, 21,
|
||||
21, 27, 28,
|
||||
28, 29, 23,
|
||||
23, 29, 24,
|
||||
30, 31, 25,
|
||||
25, 31, 32,
|
||||
26, 32, 33,
|
||||
27, 33, 34,
|
||||
34, 35, 29,
|
||||
29, 35, 30,
|
||||
36, 37, 31,
|
||||
31, 37, 38,
|
||||
38, 39, 33,
|
||||
39, 40, 34,
|
||||
40, 41, 35,
|
||||
35, 41, 36,
|
||||
36, 42, 43,
|
||||
43, 44, 38,
|
||||
44, 45, 39,
|
||||
45, 46, 40,
|
||||
46, 47, 41,
|
||||
47, 42, 36,
|
||||
48, 49, 43,
|
||||
49, 50, 44,
|
||||
50, 51, 45,
|
||||
51, 52, 46,
|
||||
52, 53, 47,
|
||||
47, 53, 48,
|
||||
54, 55, 49,
|
||||
49, 55, 56,
|
||||
50, 56, 57,
|
||||
57, 58, 52,
|
||||
58, 59, 53,
|
||||
53, 59, 54,
|
||||
60, 61, 55,
|
||||
55, 61, 62,
|
||||
56, 62, 63,
|
||||
63, 64, 58,
|
||||
64, 65, 59,
|
||||
59, 65, 60,
|
||||
66, 67, 61,
|
||||
61, 67, 68,
|
||||
68, 69, 63,
|
||||
69, 70, 64,
|
||||
70, 71, 65,
|
||||
71, 66, 60,
|
||||
72, 73, 67,
|
||||
73, 74, 68,
|
||||
68, 74, 75,
|
||||
75, 76, 70,
|
||||
76, 77, 71,
|
||||
71, 77, 72,
|
||||
78, 79, 73,
|
||||
79, 80, 74,
|
||||
74, 80, 81,
|
||||
81, 82, 76,
|
||||
82, 83, 77,
|
||||
83, 78, 72,
|
||||
78, 84, 85,
|
||||
85, 86, 80,
|
||||
80, 86, 87,
|
||||
87, 88, 82,
|
||||
82, 88, 89,
|
||||
89, 84, 78,
|
||||
90, 91, 85,
|
||||
91, 92, 86,
|
||||
86, 92, 93,
|
||||
93, 94, 88,
|
||||
88, 94, 95,
|
||||
95, 90, 84,
|
||||
96, 97, 91,
|
||||
97, 98, 92,
|
||||
98, 99, 93,
|
||||
99, 100, 94,
|
||||
100, 101, 95,
|
||||
101, 96, 90,
|
||||
102, 103, 97,
|
||||
103, 104, 98,
|
||||
104, 105, 99,
|
||||
99, 105, 106,
|
||||
106, 107, 101,
|
||||
101, 107, 102,
|
||||
108, 109, 103,
|
||||
103, 109, 110,
|
||||
110, 111, 105,
|
||||
105, 111, 112,
|
||||
112, 113, 107,
|
||||
107, 113, 108,
|
||||
114, 115, 109,
|
||||
115, 116, 110,
|
||||
116, 117, 111,
|
||||
111, 117, 118,
|
||||
112, 118, 119,
|
||||
113, 119, 114,
|
||||
114, 120, 121,
|
||||
121, 122, 116,
|
||||
122, 123, 117,
|
||||
117, 123, 124,
|
||||
124, 125, 119,
|
||||
125, 120, 114,
|
||||
126, 127, 121,
|
||||
121, 127, 128,
|
||||
128, 129, 123,
|
||||
123, 129, 130,
|
||||
130, 131, 125,
|
||||
125, 131, 126,
|
||||
132, 133, 127,
|
||||
133, 134, 128,
|
||||
128, 134, 135,
|
||||
135, 136, 130,
|
||||
136, 137, 131,
|
||||
131, 137, 132,
|
||||
132, 138, 139,
|
||||
133, 139, 140,
|
||||
134, 140, 141,
|
||||
141, 142, 136,
|
||||
142, 143, 137,
|
||||
143, 138, 132,
|
||||
138, 144, 145,
|
||||
139, 145, 146,
|
||||
146, 147, 141,
|
||||
141, 147, 148,
|
||||
148, 149, 143,
|
||||
149, 144, 138,
|
||||
144, 150, 151,
|
||||
151, 152, 146,
|
||||
146, 152, 153,
|
||||
153, 154, 148,
|
||||
154, 155, 149,
|
||||
155, 150, 144,
|
||||
156, 157, 151,
|
||||
151, 157, 158,
|
||||
158, 159, 153,
|
||||
159, 160, 154,
|
||||
160, 161, 155,
|
||||
155, 161, 156,
|
||||
156, 162, 163,
|
||||
163, 164, 158,
|
||||
158, 164, 165,
|
||||
165, 166, 160,
|
||||
160, 166, 167,
|
||||
167, 162, 156,
|
||||
162, 168, 169,
|
||||
169, 170, 164,
|
||||
164, 170, 171,
|
||||
165, 171, 172,
|
||||
166, 172, 173,
|
||||
173, 168, 162,
|
||||
174, 175, 169,
|
||||
175, 176, 170,
|
||||
170, 176, 177,
|
||||
177, 178, 172,
|
||||
172, 178, 179,
|
||||
173, 179, 174,
|
||||
174, 180, 181,
|
||||
181, 182, 176,
|
||||
176, 182, 183,
|
||||
183, 184, 178,
|
||||
178, 184, 185,
|
||||
179, 185, 180,
|
||||
186, 187, 181,
|
||||
187, 188, 182,
|
||||
188, 189, 183,
|
||||
183, 189, 190,
|
||||
190, 191, 185,
|
||||
191, 186, 180,
|
||||
0, 1, 187,
|
||||
1, 2, 188,
|
||||
2, 3, 189,
|
||||
3, 4, 190,
|
||||
190, 4, 5,
|
||||
191, 5, 0,
|
||||
0, 6, 1,
|
||||
1, 7, 2,
|
||||
2, 8, 3,
|
||||
3, 9, 4,
|
||||
4, 10, 5,
|
||||
0, 5, 6,
|
||||
6, 12, 7,
|
||||
7, 13, 8,
|
||||
8, 14, 9,
|
||||
9, 15, 10,
|
||||
10, 16, 11,
|
||||
6, 11, 12,
|
||||
12, 18, 13,
|
||||
14, 13, 20,
|
||||
14, 20, 15,
|
||||
16, 15, 22,
|
||||
16, 22, 17,
|
||||
12, 17, 18,
|
||||
18, 24, 19,
|
||||
20, 19, 26,
|
||||
20, 26, 21,
|
||||
22, 21, 28,
|
||||
22, 28, 23,
|
||||
18, 23, 24,
|
||||
24, 30, 25,
|
||||
26, 25, 32,
|
||||
27, 26, 33,
|
||||
28, 27, 34,
|
||||
28, 34, 29,
|
||||
24, 29, 30,
|
||||
30, 36, 31,
|
||||
32, 31, 38,
|
||||
32, 38, 33,
|
||||
33, 39, 34,
|
||||
34, 40, 35,
|
||||
30, 35, 36,
|
||||
37, 36, 43,
|
||||
37, 43, 38,
|
||||
38, 44, 39,
|
||||
39, 45, 40,
|
||||
40, 46, 41,
|
||||
41, 47, 36,
|
||||
42, 48, 43,
|
||||
43, 49, 44,
|
||||
44, 50, 45,
|
||||
45, 51, 46,
|
||||
46, 52, 47,
|
||||
42, 47, 48,
|
||||
48, 54, 49,
|
||||
50, 49, 56,
|
||||
51, 50, 57,
|
||||
51, 57, 52,
|
||||
52, 58, 53,
|
||||
48, 53, 54,
|
||||
54, 60, 55,
|
||||
56, 55, 62,
|
||||
57, 56, 63,
|
||||
57, 63, 58,
|
||||
58, 64, 59,
|
||||
54, 59, 60,
|
||||
60, 66, 61,
|
||||
62, 61, 68,
|
||||
62, 68, 63,
|
||||
63, 69, 64,
|
||||
64, 70, 65,
|
||||
65, 71, 60,
|
||||
66, 72, 67,
|
||||
67, 73, 68,
|
||||
69, 68, 75,
|
||||
69, 75, 70,
|
||||
70, 76, 71,
|
||||
66, 71, 72,
|
||||
72, 78, 73,
|
||||
73, 79, 74,
|
||||
75, 74, 81,
|
||||
75, 81, 76,
|
||||
76, 82, 77,
|
||||
77, 83, 72,
|
||||
79, 78, 85,
|
||||
79, 85, 80,
|
||||
81, 80, 87,
|
||||
81, 87, 82,
|
||||
83, 82, 89,
|
||||
83, 89, 78,
|
||||
84, 90, 85,
|
||||
85, 91, 86,
|
||||
87, 86, 93,
|
||||
87, 93, 88,
|
||||
89, 88, 95,
|
||||
89, 95, 84,
|
||||
90, 96, 91,
|
||||
91, 97, 92,
|
||||
92, 98, 93,
|
||||
93, 99, 94,
|
||||
94, 100, 95,
|
||||
95, 101, 90,
|
||||
96, 102, 97,
|
||||
97, 103, 98,
|
||||
98, 104, 99,
|
||||
100, 99, 106,
|
||||
100, 106, 101,
|
||||
96, 101, 102,
|
||||
102, 108, 103,
|
||||
104, 103, 110,
|
||||
104, 110, 105,
|
||||
106, 105, 112,
|
||||
106, 112, 107,
|
||||
102, 107, 108,
|
||||
108, 114, 109,
|
||||
109, 115, 110,
|
||||
110, 116, 111,
|
||||
112, 111, 118,
|
||||
113, 112, 119,
|
||||
108, 113, 114,
|
||||
115, 114, 121,
|
||||
115, 121, 116,
|
||||
116, 122, 117,
|
||||
118, 117, 124,
|
||||
118, 124, 119,
|
||||
119, 125, 114,
|
||||
120, 126, 121,
|
||||
122, 121, 128,
|
||||
122, 128, 123,
|
||||
124, 123, 130,
|
||||
124, 130, 125,
|
||||
120, 125, 126,
|
||||
126, 132, 127,
|
||||
127, 133, 128,
|
||||
129, 128, 135,
|
||||
129, 135, 130,
|
||||
130, 136, 131,
|
||||
126, 131, 132,
|
||||
133, 132, 139,
|
||||
134, 133, 140,
|
||||
135, 134, 141,
|
||||
135, 141, 136,
|
||||
136, 142, 137,
|
||||
137, 143, 132,
|
||||
139, 138, 145,
|
||||
140, 139, 146,
|
||||
140, 146, 141,
|
||||
142, 141, 148,
|
||||
142, 148, 143,
|
||||
143, 149, 138,
|
||||
145, 144, 151,
|
||||
145, 151, 146,
|
||||
147, 146, 153,
|
||||
147, 153, 148,
|
||||
148, 154, 149,
|
||||
149, 155, 144,
|
||||
150, 156, 151,
|
||||
152, 151, 158,
|
||||
152, 158, 153,
|
||||
153, 159, 154,
|
||||
154, 160, 155,
|
||||
150, 155, 156,
|
||||
157, 156, 163,
|
||||
157, 163, 158,
|
||||
159, 158, 165,
|
||||
159, 165, 160,
|
||||
161, 160, 167,
|
||||
161, 167, 156,
|
||||
163, 162, 169,
|
||||
163, 169, 164,
|
||||
165, 164, 171,
|
||||
166, 165, 172,
|
||||
167, 166, 173,
|
||||
167, 173, 162,
|
||||
168, 174, 169,
|
||||
169, 175, 170,
|
||||
171, 170, 177,
|
||||
171, 177, 172,
|
||||
173, 172, 179,
|
||||
168, 173, 174,
|
||||
175, 174, 181,
|
||||
175, 181, 176,
|
||||
177, 176, 183,
|
||||
177, 183, 178,
|
||||
179, 178, 185,
|
||||
174, 179, 180,
|
||||
180, 186, 181,
|
||||
181, 187, 182,
|
||||
182, 188, 183,
|
||||
184, 183, 190,
|
||||
184, 190, 185,
|
||||
185, 191, 180,
|
||||
186, 0, 187,
|
||||
187, 1, 188,
|
||||
188, 2, 189,
|
||||
189, 3, 190,
|
||||
191, 190, 5,
|
||||
186, 191, 0,
|
||||
};
|
||||
|
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/widget_library/primitive_widget.c
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name Primitive Widget
|
||||
*
|
||||
* 3D Widget
|
||||
*
|
||||
* \brief Widget with primitive drawing type (plane, cube, etc.).
|
||||
* Currently only plane primitive supported without own handling, use with operator only.
|
||||
*/
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_widget_types.h"
|
||||
|
||||
#include "GPU_select.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
/* own includes */
|
||||
#include "WM_widget_types.h"
|
||||
#include "WM_widget_library.h"
|
||||
#include "wm_widget_wmapi.h"
|
||||
#include "wm_widget_intern.h"
|
||||
#include "widget_library_intern.h"
|
||||
|
||||
|
||||
/* PrimitiveWidget->flag */
|
||||
#define PRIM_UP_VECTOR_SET 1
|
||||
|
||||
typedef struct PrimitiveWidget {
|
||||
wmWidget widget;
|
||||
|
||||
float direction[3];
|
||||
float up[3];
|
||||
int style;
|
||||
int flag;
|
||||
} PrimitiveWidget;
|
||||
|
||||
|
||||
static float verts_plane[4][3] = {
|
||||
{-1, -1, 0},
|
||||
{ 1, -1, 0},
|
||||
{ 1, 1, 0},
|
||||
{-1, 1, 0},
|
||||
};
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void widget_primitive_draw_geom(const float col_inner[4], const float col_outer[4], const int style)
|
||||
{
|
||||
float (*verts)[3];
|
||||
float vert_count;
|
||||
|
||||
if (style == WIDGET_PRIMITIVE_STYLE_PLANE) {
|
||||
verts = verts_plane;
|
||||
vert_count = ARRAY_SIZE(verts_plane);
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, 0, verts);
|
||||
glColor4fv(col_inner);
|
||||
glDrawArrays(GL_QUADS, 0, vert_count);
|
||||
glColor4fv(col_outer);
|
||||
glDrawArrays(GL_LINE_LOOP, 0, vert_count);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
static void widget_primitive_draw_intern(PrimitiveWidget *prim, const bool UNUSED(select), const bool highlight)
|
||||
{
|
||||
float col_inner[4], col_outer[4];
|
||||
float rot[3][3];
|
||||
float mat[4][4];
|
||||
|
||||
if (prim->flag & PRIM_UP_VECTOR_SET) {
|
||||
copy_v3_v3(rot[2], prim->direction);
|
||||
copy_v3_v3(rot[1], prim->up);
|
||||
cross_v3_v3v3(rot[0], prim->up, prim->direction);
|
||||
}
|
||||
else {
|
||||
const float up[3] = {0.0f, 0.0f, 1.0f};
|
||||
rotation_between_vecs_to_mat3(rot, up, prim->direction);
|
||||
}
|
||||
|
||||
copy_m4_m3(mat, rot);
|
||||
copy_v3_v3(mat[3], prim->widget.origin);
|
||||
mul_mat3_m4_fl(mat, prim->widget.scale);
|
||||
|
||||
glPushMatrix();
|
||||
glMultMatrixf(mat);
|
||||
|
||||
if (highlight && (prim->widget.flag & WM_WIDGET_DRAW_HOVER) == 0) {
|
||||
copy_v4_v4(col_inner, prim->widget.col_hi);
|
||||
copy_v4_v4(col_outer, prim->widget.col_hi);
|
||||
}
|
||||
else {
|
||||
copy_v4_v4(col_inner, prim->widget.col);
|
||||
copy_v4_v4(col_outer, prim->widget.col);
|
||||
}
|
||||
col_inner[3] *= 0.5f;
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glTranslate3fv(prim->widget.offset);
|
||||
widget_primitive_draw_geom(col_inner, col_outer, prim->style);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
if (prim->widget.interaction_data) {
|
||||
WidgetInteraction *inter = prim->widget.interaction_data;
|
||||
|
||||
copy_v4_fl(col_inner, 0.5f);
|
||||
copy_v3_fl(col_outer, 0.5f);
|
||||
col_outer[3] = 0.8f;
|
||||
|
||||
copy_m4_m3(mat, rot);
|
||||
copy_v3_v3(mat[3], inter->init_origin);
|
||||
mul_mat3_m4_fl(mat, inter->init_scale);
|
||||
|
||||
glPushMatrix();
|
||||
glMultMatrixf(mat);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glTranslate3fv(prim->widget.offset);
|
||||
widget_primitive_draw_geom(col_inner, col_outer, prim->style);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
static void widget_primitive_render_3d_intersect(const bContext *UNUSED(C), wmWidget *widget, int selectionbase)
|
||||
{
|
||||
GPU_select_load_id(selectionbase);
|
||||
widget_primitive_draw_intern((PrimitiveWidget *)widget, true, false);
|
||||
}
|
||||
|
||||
static void widget_primitive_draw(const bContext *UNUSED(C), wmWidget *widget)
|
||||
{
|
||||
widget_primitive_draw_intern((PrimitiveWidget *)widget, false, (widget->flag & WM_WIDGET_HIGHLIGHT));
|
||||
}
|
||||
|
||||
static int widget_primitive_invoke(bContext *UNUSED(C), const wmEvent *UNUSED(event), wmWidget *widget)
|
||||
{
|
||||
WidgetInteraction *inter = MEM_callocN(sizeof(WidgetInteraction), __func__);
|
||||
|
||||
copy_v3_v3(inter->init_origin, widget->origin);
|
||||
inter->init_scale = widget->scale;
|
||||
|
||||
widget->interaction_data = inter;
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Primitive Widget API
|
||||
*
|
||||
* \{ */
|
||||
|
||||
wmWidget *WIDGET_primitive_new(wmWidgetGroup *wgroup, const char *name, const int style)
|
||||
{
|
||||
PrimitiveWidget *prim = MEM_callocN(sizeof(PrimitiveWidget), name);
|
||||
const float dir_default[3] = {0.0f, 0.0f, 1.0f};
|
||||
|
||||
prim->widget.draw = widget_primitive_draw;
|
||||
prim->widget.invoke = widget_primitive_invoke;
|
||||
prim->widget.intersect = NULL;
|
||||
prim->widget.render_3d_intersection = widget_primitive_render_3d_intersect;
|
||||
prim->widget.flag |= (WM_WIDGET_DRAW_ACTIVE | WM_WIDGET_SCALE_3D);
|
||||
prim->style = style;
|
||||
|
||||
/* defaults */
|
||||
copy_v3_v3(prim->direction, dir_default);
|
||||
|
||||
wm_widget_register(wgroup, &prim->widget, name);
|
||||
|
||||
return (wmWidget *)prim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define direction the primitive will point towards
|
||||
*/
|
||||
void WIDGET_primitive_set_direction(wmWidget *widget, const float direction[3])
|
||||
{
|
||||
PrimitiveWidget *prim = (PrimitiveWidget *)widget;
|
||||
|
||||
copy_v3_v3(prim->direction, direction);
|
||||
normalize_v3(prim->direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define up-direction of the primitive widget
|
||||
*/
|
||||
void WIDGET_primitive_set_up_vector(wmWidget *widget, const float direction[3])
|
||||
{
|
||||
PrimitiveWidget *prim = (PrimitiveWidget *)widget;
|
||||
|
||||
if (direction) {
|
||||
copy_v3_v3(prim->up, direction);
|
||||
normalize_v3(prim->up);
|
||||
prim->flag |= PRIM_UP_VECTOR_SET;
|
||||
}
|
||||
else {
|
||||
prim->flag &= ~PRIM_UP_VECTOR_SET;
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */ // Primitive Widget API
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
void fix_linking_widget_primitive(void)
|
||||
{
|
||||
(void)0;
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/widget_library/widget_geometry.h
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name Widget Geometry
|
||||
*
|
||||
* \brief Prototypes for arrays defining the widget geometry. The actual definitions can be found in files usually
|
||||
* called geom_xxx_widget.c
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __WIDGET_GEOMETRY_H__
|
||||
#define __WIDGET_GEOMETRY_H__
|
||||
|
||||
|
||||
/* arrow widget */
|
||||
extern int _WIDGET_nverts_arrow;
|
||||
extern int _WIDGET_ntris_arrow;
|
||||
|
||||
extern float _WIDGET_verts_arrow[][3];
|
||||
extern float _WIDGET_normals_arrow[][3];
|
||||
extern unsigned short _WIDGET_indices_arrow[];
|
||||
|
||||
|
||||
/* cube widget */
|
||||
extern int _WIDGET_nverts_cube;
|
||||
extern int _WIDGET_ntris_cube;
|
||||
|
||||
extern float _WIDGET_verts_cube[][3];
|
||||
extern float _WIDGET_normals_cube[][3];
|
||||
extern unsigned short _WIDGET_indices_cube[];
|
||||
|
||||
|
||||
/* dial widget */
|
||||
extern int _WIDGET_nverts_dial;
|
||||
extern int _WIDGET_ntris_dial;
|
||||
|
||||
extern float _WIDGET_verts_dial[][3];
|
||||
extern float _WIDGET_normals_dial[][3];
|
||||
extern unsigned short _WIDGET_indices_dial[];
|
||||
|
||||
#endif /* __WIDGET_GEOMETRY_H__ */
|
||||
|
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/widget_library/widget_library_intern.h
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __WIDGET_LIBRARY_INTERN_H__
|
||||
#define __WIDGET_LIBRARY_INTERN_H__
|
||||
|
||||
/* distance around which widgets respond to input (and get highlighted) */
|
||||
#define WIDGET_HOTSPOT 14.0f /* TODO use everywhere */
|
||||
|
||||
/**
|
||||
* Data for common interactions. Used in widget_library_utils.c functions.
|
||||
*/
|
||||
typedef struct WidgetCommonData {
|
||||
int flag;
|
||||
|
||||
float range_fac; /* factor for arrow min/max distance */
|
||||
float offset;
|
||||
|
||||
/* property range for constrained widgets */
|
||||
float range;
|
||||
/* min/max value for constrained widgets */
|
||||
float min, max;
|
||||
} WidgetCommonData;
|
||||
|
||||
typedef struct WidgetInteraction {
|
||||
float init_value; /* initial property value */
|
||||
float init_origin[3];
|
||||
float init_mval[2];
|
||||
float init_offset;
|
||||
float init_scale;
|
||||
|
||||
/* offset of last handling step */
|
||||
float prev_offset;
|
||||
/* Total offset added by precision tweaking.
|
||||
* Needed to allow toggling precision on/off without causing jumps */
|
||||
float precision_offset;
|
||||
} WidgetInteraction;
|
||||
|
||||
/* WidgetCommonData->flag */
|
||||
enum {
|
||||
WIDGET_CUSTOM_RANGE_SET = (1 << 0),
|
||||
};
|
||||
|
||||
|
||||
float widget_offset_from_value(
|
||||
WidgetCommonData *data, const float value,
|
||||
const bool constrained, const bool inverted);
|
||||
float widget_value_from_offset(
|
||||
WidgetCommonData *data, WidgetInteraction *inter, const float offset,
|
||||
const bool constrained, const bool inverted, const bool use_precision);
|
||||
|
||||
void widget_property_data_update(
|
||||
wmWidget *widget, WidgetCommonData *data, const int slot,
|
||||
const bool constrained, const bool inverted);
|
||||
|
||||
void widget_property_value_set(bContext *C, const wmWidget *widget, const int slot, const float value);
|
||||
float widget_property_value_get(const wmWidget *widget, const int slot);
|
||||
void widget_property_value_reset(bContext *C, const wmWidget *widget, WidgetInteraction *inter, const int slot);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
float *widget_color_get(wmWidget *widget, const bool highlight);
|
||||
|
||||
#endif /* __WIDGET_LIBRARY_INTERN_H__ */
|
||||
|
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2015 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/widget_library/widget_library_utils.c
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name Widget Library Utilities
|
||||
*
|
||||
* \brief This file contains functions for common behaviors of widgets.
|
||||
*/
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
/* own includes */
|
||||
#include "WM_widget_types.h"
|
||||
#include "wm_widget_wmapi.h"
|
||||
#include "widget_library_intern.h"
|
||||
|
||||
/* factor for precision tweaking */
|
||||
#define WIDGET_PRECISION_FAC 0.05f
|
||||
|
||||
|
||||
BLI_INLINE float widget_offset_from_value_constr(
|
||||
const float range_fac, const float min, const float range, const float value,
|
||||
const bool inverted)
|
||||
{
|
||||
return inverted ? (range_fac * (min + range - value) / range) : (range_fac * (value / range));
|
||||
}
|
||||
|
||||
BLI_INLINE float widget_value_from_offset_constr(
|
||||
const float range_fac, const float min, const float range, const float value,
|
||||
const bool inverted)
|
||||
{
|
||||
return inverted ? (min + range - (value * range / range_fac)) : (value * range / range_fac);
|
||||
}
|
||||
|
||||
float widget_offset_from_value(WidgetCommonData *data, const float value, const bool constrained, const bool inverted)
|
||||
{
|
||||
if (constrained)
|
||||
return widget_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float widget_value_from_offset(
|
||||
WidgetCommonData *data, WidgetInteraction *inter, const float offset,
|
||||
const bool constrained, const bool inverted, const bool use_precision)
|
||||
{
|
||||
const float max = data->min + data->range;
|
||||
|
||||
if (use_precision) {
|
||||
/* add delta offset of this step to total precision_offset */
|
||||
inter->precision_offset += offset - inter->prev_offset;
|
||||
}
|
||||
inter->prev_offset = offset;
|
||||
|
||||
float ofs_new = inter->init_offset + offset - inter->precision_offset * (1.0f - WIDGET_PRECISION_FAC);
|
||||
float value;
|
||||
|
||||
if (constrained) {
|
||||
value = widget_value_from_offset_constr(data->range_fac, data->min, data->range, ofs_new, inverted);
|
||||
}
|
||||
else {
|
||||
value = ofs_new;
|
||||
}
|
||||
|
||||
/* clamp to custom range */
|
||||
if (data->flag & WIDGET_CUSTOM_RANGE_SET) {
|
||||
CLAMP(value, data->min, max);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void widget_property_data_update(
|
||||
wmWidget *widget, WidgetCommonData *data, const int slot,
|
||||
const bool constrained, const bool inverted)
|
||||
{
|
||||
if (!widget->props[slot]) {
|
||||
data->offset = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
PointerRNA ptr = widget->ptr[slot];
|
||||
PropertyRNA *prop = widget->props[slot];
|
||||
float value = widget_property_value_get(widget, slot);
|
||||
|
||||
if (constrained) {
|
||||
if ((data->flag & WIDGET_CUSTOM_RANGE_SET) == 0) {
|
||||
float step, precision;
|
||||
float min, max;
|
||||
RNA_property_float_ui_range(&ptr, prop, &min, &max, &step, &precision);
|
||||
data->range = max - min;
|
||||
data->min = min;
|
||||
}
|
||||
data->offset = widget_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted);
|
||||
}
|
||||
else {
|
||||
data->offset = value;
|
||||
}
|
||||
}
|
||||
|
||||
void widget_property_value_set(bContext *C, const wmWidget *widget, const int slot, const float value)
|
||||
{
|
||||
PointerRNA ptr = widget->ptr[slot];
|
||||
PropertyRNA *prop = widget->props[slot];
|
||||
|
||||
/* reset property */
|
||||
RNA_property_float_set(&ptr, prop, value);
|
||||
RNA_property_update(C, &ptr, prop);
|
||||
}
|
||||
|
||||
float widget_property_value_get(const wmWidget *widget, const int slot)
|
||||
{
|
||||
BLI_assert(RNA_property_type(widget->props[slot]) == PROP_FLOAT);
|
||||
return RNA_property_float_get(&widget->ptr[slot], widget->props[slot]);
|
||||
}
|
||||
|
||||
void widget_property_value_reset(bContext *C, const wmWidget *widget, WidgetInteraction *inter, const int slot)
|
||||
{
|
||||
widget_property_value_set(C, widget, slot, inter->init_value);
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/* TODO use everywhere */
|
||||
float *widget_color_get(wmWidget *widget, const bool highlight)
|
||||
{
|
||||
return (highlight && !(widget->flag & WM_WIDGET_DRAW_HOVER)) ? widget->col_hi : widget->col;
|
||||
}
|
416
source/blender/windowmanager/widgets/intern/wm_widget.c
Normal file
416
source/blender/windowmanager/widgets/intern/wm_widget.c
Normal file
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2014 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/wm_widget.c
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "GL/glew.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
/* own includes */
|
||||
#include "wm_widget_wmapi.h"
|
||||
#include "wm_widget_intern.h"
|
||||
|
||||
/**
|
||||
* Main draw call for WidgetDrawInfo data
|
||||
*/
|
||||
void widget_draw_intern(WidgetDrawInfo *info, const bool select)
|
||||
{
|
||||
GLuint buf[3];
|
||||
|
||||
const bool use_lighting = !select && ((U.widget_flag & V3D_SHADED_WIDGETS) != 0);
|
||||
|
||||
if (use_lighting)
|
||||
glGenBuffers(3, buf);
|
||||
else
|
||||
glGenBuffers(2, buf);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buf[0]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * info->nverts, info->verts, GL_STATIC_DRAW);
|
||||
glVertexPointer(3, GL_FLOAT, 0, NULL);
|
||||
|
||||
if (use_lighting) {
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buf[2]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * info->nverts, info->normals, GL_STATIC_DRAW);
|
||||
glNormalPointer(GL_FLOAT, 0, NULL);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf[1]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * (3 * info->ntris), info->indices, GL_STATIC_DRAW);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, info->ntris * 3, GL_UNSIGNED_SHORT, NULL);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (use_lighting) {
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glShadeModel(GL_FLAT);
|
||||
glDeleteBuffers(3, buf);
|
||||
}
|
||||
else {
|
||||
glDeleteBuffers(2, buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Still unused */
|
||||
wmWidget *WM_widget_new(void (*draw)(const bContext *C, wmWidget *customdata),
|
||||
void (*render_3d_intersection)(const bContext *C, wmWidget *customdata, int selectionbase),
|
||||
int (*intersect)(bContext *C, const wmEvent *event, wmWidget *widget),
|
||||
int (*handler)(bContext *C, const wmEvent *event, wmWidget *widget, const int flag))
|
||||
{
|
||||
wmWidget *widget = MEM_callocN(sizeof(wmWidget), "widget");
|
||||
|
||||
widget->draw = draw;
|
||||
widget->handler = handler;
|
||||
widget->intersect = intersect;
|
||||
widget->render_3d_intersection = render_3d_intersection;
|
||||
|
||||
/* XXX */
|
||||
fix_linking_widget_arrow();
|
||||
fix_linking_widget_arrow2d();
|
||||
fix_linking_widget_cage();
|
||||
fix_linking_widget_dial();
|
||||
fix_linking_widget_facemap();
|
||||
fix_linking_widget_primitive();
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign an idname that is unique in \a wgroup to \a widget.
|
||||
*
|
||||
* \param rawname Name used as basis to define final unique idname.
|
||||
*/
|
||||
static void widget_unique_idname_set(wmWidgetGroup *wgroup, wmWidget *widget, const char *rawname)
|
||||
{
|
||||
if (wgroup->type->idname[0]) {
|
||||
BLI_snprintf(widget->idname, sizeof(widget->idname), "%s_%s", wgroup->type->idname, rawname);
|
||||
}
|
||||
else {
|
||||
BLI_strncpy(widget->idname, rawname, sizeof(widget->idname));
|
||||
}
|
||||
|
||||
/* ensure name is unique, append '.001', '.002', etc if not */
|
||||
BLI_uniquename(&wgroup->widgets, widget, "Widget", '.', offsetof(wmWidget, idname), sizeof(widget->idname));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register \a widget.
|
||||
*
|
||||
* \param name name used to create a unique idname for \a widget in \a wgroup
|
||||
*/
|
||||
bool wm_widget_register(wmWidgetGroup *wgroup, wmWidget *widget, const char *name)
|
||||
{
|
||||
const float col_default[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
||||
widget_unique_idname_set(wgroup, widget, name);
|
||||
|
||||
widget->user_scale = 1.0f;
|
||||
widget->line_width = 1.0f;
|
||||
|
||||
/* defaults */
|
||||
copy_v4_v4(widget->col, col_default);
|
||||
copy_v4_v4(widget->col_hi, col_default);
|
||||
|
||||
/* create at least one property for interaction */
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free \a widget and unlink from \a widgetlist.
|
||||
* \a widgetlist is allowed to be NULL.
|
||||
*/
|
||||
void WM_widget_delete(ListBase *widgetlist, wmWidgetMap *wmap, wmWidget *widget, bContext *C)
|
||||
{
|
||||
if (widget->flag & WM_WIDGET_HIGHLIGHT) {
|
||||
wm_widgetmap_set_highlighted_widget(wmap, C, NULL, 0);
|
||||
}
|
||||
if (widget->flag & WM_WIDGET_ACTIVE) {
|
||||
wm_widgetmap_set_active_widget(wmap, C, NULL, NULL);
|
||||
}
|
||||
if (widget->flag & WM_WIDGET_SELECTED) {
|
||||
wm_widget_deselect(wmap, widget);
|
||||
}
|
||||
|
||||
if (widget->opptr.data) {
|
||||
WM_operator_properties_free(&widget->opptr);
|
||||
}
|
||||
MEM_freeN(widget->props);
|
||||
MEM_freeN(widget->ptr);
|
||||
|
||||
if (widgetlist)
|
||||
BLI_remlink(widgetlist, widget);
|
||||
MEM_freeN(widget);
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Widget Creation API
|
||||
*
|
||||
* API for defining data on widget creation.
|
||||
*
|
||||
* \{ */
|
||||
|
||||
void WM_widget_set_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->prop_data_update)
|
||||
widget->prop_data_update(widget, slot);
|
||||
}
|
||||
|
||||
PointerRNA *WM_widget_set_operator(wmWidget *widget, const char *opname)
|
||||
{
|
||||
wmOperatorType *ot = WM_operatortype_find(opname, 0);
|
||||
|
||||
if (ot) {
|
||||
widget->opname = opname;
|
||||
|
||||
if (widget->opptr.data) {
|
||||
WM_operator_properties_free(&widget->opptr);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set widget select callback.
|
||||
*
|
||||
* Callback is called when widget gets selected/deselected.
|
||||
*/
|
||||
void WM_widget_set_func_select(wmWidget *widget, wmWidgetSelectFunc select)
|
||||
{
|
||||
widget->flag |= WM_WIDGET_SELECTABLE;
|
||||
widget->select = select;
|
||||
}
|
||||
|
||||
void WM_widget_set_origin(wmWidget *widget, const float origin[3])
|
||||
{
|
||||
copy_v3_v3(widget->origin, origin);
|
||||
}
|
||||
|
||||
void WM_widget_set_offset(wmWidget *widget, const float offset[3])
|
||||
{
|
||||
copy_v3_v3(widget->offset, offset);
|
||||
}
|
||||
|
||||
void WM_widget_set_flag(wmWidget *widget, const int flag, const bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
widget->flag |= flag;
|
||||
}
|
||||
else {
|
||||
widget->flag &= ~flag;
|
||||
}
|
||||
}
|
||||
|
||||
void WM_widget_set_scale(wmWidget *widget, const float scale)
|
||||
{
|
||||
widget->user_scale = scale;
|
||||
}
|
||||
|
||||
void WM_widget_set_line_width(wmWidget *widget, const float line_width)
|
||||
{
|
||||
widget->line_width = line_width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget rgba colors.
|
||||
*
|
||||
* \param col Normal state color.
|
||||
* \param col_hi Highlighted state color.
|
||||
*/
|
||||
void WM_widget_set_colors(wmWidget *widget, const float col[4], const float col_hi[4])
|
||||
{
|
||||
copy_v4_v4(widget->col, col);
|
||||
copy_v4_v4(widget->col_hi, col_hi);
|
||||
}
|
||||
|
||||
/** \} */ // Widget Creation API
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Remove \a widget from selection.
|
||||
* Reallocates memory for selected widgets so better not call for selecting multiple ones.
|
||||
*
|
||||
* \return if the selection has changed.
|
||||
*/
|
||||
bool wm_widget_deselect(wmWidgetMap *wmap, wmWidget *widget)
|
||||
{
|
||||
if (!wmap->wmap_context.selected_widgets)
|
||||
return false;
|
||||
|
||||
wmWidget ***sel = &wmap->wmap_context.selected_widgets;
|
||||
int *tot_selected = &wmap->wmap_context.tot_selected;
|
||||
bool changed = false;
|
||||
|
||||
/* caller should check! */
|
||||
BLI_assert(widget->flag & WM_WIDGET_SELECTED);
|
||||
|
||||
/* remove widget from selected_widgets array */
|
||||
for (int i = 0; i < (*tot_selected); i++) {
|
||||
if ((*sel)[i] == widget) {
|
||||
for (int j = i; j < ((*tot_selected) - 1); j++) {
|
||||
(*sel)[j] = (*sel)[j + 1];
|
||||
}
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* update array data */
|
||||
if ((*tot_selected) <= 1) {
|
||||
wm_widgetmap_selected_delete(wmap);
|
||||
}
|
||||
else {
|
||||
*sel = MEM_reallocN(*sel, sizeof(**sel) * (*tot_selected));
|
||||
(*tot_selected)--;
|
||||
}
|
||||
|
||||
widget->flag &= ~WM_WIDGET_SELECTED;
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add \a widget to selection.
|
||||
* Reallocates memory for selected widgets so better not call for selecting multiple ones.
|
||||
*
|
||||
* \return if the selection has changed.
|
||||
*/
|
||||
bool wm_widget_select(bContext *C, wmWidgetMap *wmap, wmWidget *widget)
|
||||
{
|
||||
wmWidget ***sel = &wmap->wmap_context.selected_widgets;
|
||||
int *tot_selected = &wmap->wmap_context.tot_selected;
|
||||
|
||||
if (!widget || (widget->flag & WM_WIDGET_SELECTED))
|
||||
return false;
|
||||
|
||||
(*tot_selected)++;
|
||||
|
||||
*sel = MEM_reallocN(*sel, sizeof(wmWidget *) * (*tot_selected));
|
||||
(*sel)[(*tot_selected) - 1] = widget;
|
||||
|
||||
widget->flag |= WM_WIDGET_SELECTED;
|
||||
if (widget->select) {
|
||||
widget->select(C, widget, SEL_SELECT);
|
||||
}
|
||||
wm_widgetmap_set_highlighted_widget(wmap, C, widget, widget->highlighted_part);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wm_widget_calculate_scale(wmWidget *widget, const bContext *C)
|
||||
{
|
||||
const RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||
float scale = 1.0f;
|
||||
|
||||
if (widget->flag & WM_WIDGET_SCALE_3D) {
|
||||
if (rv3d && (U.widget_flag & V3D_3D_WIDGETS) == 0) {
|
||||
if (widget->get_final_position) {
|
||||
float position[3];
|
||||
|
||||
widget->get_final_position(widget, position);
|
||||
scale = ED_view3d_pixel_size(rv3d, position) * (float)U.widget_scale;
|
||||
}
|
||||
else {
|
||||
scale = ED_view3d_pixel_size(rv3d, widget->origin) * (float)U.widget_scale;
|
||||
}
|
||||
}
|
||||
else {
|
||||
scale = U.widget_scale * 0.02f;
|
||||
}
|
||||
}
|
||||
|
||||
widget->scale = scale * widget->user_scale;
|
||||
}
|
||||
|
||||
void wm_widget_update_prop_data(wmWidget *widget)
|
||||
{
|
||||
/* widget property might have been changed, so update widget */
|
||||
if (widget->props && widget->prop_data_update) {
|
||||
for (int i = 0; i < widget->max_prop; i++) {
|
||||
if (widget->props[i]) {
|
||||
widget->prop_data_update(widget, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
116
source/blender/windowmanager/widgets/intern/wm_widget_intern.h
Normal file
116
source/blender/windowmanager/widgets/intern/wm_widget_intern.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/wm_widget_intern.h
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __WM_WIDGET_INTERN_H__
|
||||
#define __WM_WIDGET_INTERN_H__
|
||||
|
||||
struct wmKeyConfig;
|
||||
struct wmWidget;
|
||||
struct wmWidgetMap;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* wmWidget */
|
||||
|
||||
/**
|
||||
* \brief Widget tweak flag.
|
||||
* Bitflag passed to widget while tweaking.
|
||||
*/
|
||||
enum {
|
||||
/* drag with extra precision (shift)
|
||||
* NOTE: Widgets are responsible for handling this (widget->handler callback)! */
|
||||
WM_WIDGET_TWEAK_PRECISE = (1 << 0),
|
||||
};
|
||||
|
||||
bool wm_widget_register(wmWidgetGroup *wgroup, struct wmWidget *widget, const char *name);
|
||||
|
||||
bool wm_widget_deselect(struct wmWidgetMap *wmap, struct wmWidget *widget);
|
||||
bool wm_widget_select(bContext *C, struct wmWidgetMap *wmap, struct wmWidget *widget);
|
||||
|
||||
void wm_widget_calculate_scale(struct wmWidget *widget, const bContext *C);
|
||||
void wm_widget_update_prop_data(struct wmWidget *widget);
|
||||
|
||||
void fix_linking_widget_arrow(void);
|
||||
void fix_linking_widget_arrow2d(void);
|
||||
void fix_linking_widget_cage(void);
|
||||
void fix_linking_widget_dial(void);
|
||||
void fix_linking_widget_facemap(void);
|
||||
void fix_linking_widget_primitive(void);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* wmWidgetGroup */
|
||||
|
||||
enum {
|
||||
TWEAK_MODAL_CANCEL = 1,
|
||||
TWEAK_MODAL_CONFIRM,
|
||||
TWEAK_MODAL_PRECISION_ON,
|
||||
TWEAK_MODAL_PRECISION_OFF,
|
||||
};
|
||||
|
||||
void wm_widgetgroup_free(bContext *C, wmWidgetMap *wmap, struct wmWidgetGroup *wgroup);
|
||||
|
||||
void wm_widgetgrouptype_keymap_init(struct wmWidgetGroupType *wgrouptype, struct wmKeyConfig *keyconf);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* wmWidgetMap */
|
||||
|
||||
/**
|
||||
* This is a container for all widget types that can be instantiated in a region.
|
||||
* (similar to dropboxes).
|
||||
*
|
||||
* \note There is only ever one of these for every (area, region) combination.
|
||||
*/
|
||||
typedef struct wmWidgetMapType {
|
||||
struct wmWidgetMapType *next, *prev;
|
||||
char idname[64];
|
||||
short spaceid, regionid;
|
||||
/* widgetTypeflags */
|
||||
int flag;
|
||||
/* types of widgetgroups for this widgetmap type */
|
||||
ListBase widgetgrouptypes;
|
||||
} wmWidgetMapType;
|
||||
|
||||
void wm_widgetmap_selected_delete(wmWidgetMap *wmap);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Widget drawing */
|
||||
|
||||
typedef struct WidgetDrawInfo {
|
||||
int nverts;
|
||||
int ntris;
|
||||
float (*verts)[3];
|
||||
float (*normals)[3];
|
||||
unsigned short *indices;
|
||||
bool init;
|
||||
} WidgetDrawInfo;
|
||||
|
||||
void widget_draw_intern(WidgetDrawInfo *info, const bool select);
|
||||
|
||||
#endif /* __WM_WIDGET_INTERN_H__ */
|
||||
|
514
source/blender/windowmanager/widgets/intern/wm_widgetgroup.c
Normal file
514
source/blender/windowmanager/widgets/intern/wm_widgetgroup.c
Normal file
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2014 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/wm_widgetgroup.c
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name Widget Group
|
||||
*
|
||||
* WidgetGroups store and manage groups of widgets. They can be
|
||||
* attached to modal handlers and have on keymaps.
|
||||
*/
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "BPY_extern.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
#include "wm_event_system.h"
|
||||
|
||||
/* own includes */
|
||||
#include "wm_widget_wmapi.h"
|
||||
#include "wm_widget_intern.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name wmWidgetGroup
|
||||
*
|
||||
* \{ */
|
||||
|
||||
void wm_widgetgroup_free(bContext *C, wmWidgetMap *wmap, wmWidgetGroup *wgroup)
|
||||
{
|
||||
for (wmWidget *widget = wgroup->widgets.first; widget;) {
|
||||
wmWidget *widget_next = widget->next;
|
||||
WM_widget_delete(&wgroup->widgets, wmap, widget, C);
|
||||
widget = widget_next;
|
||||
}
|
||||
BLI_assert(BLI_listbase_is_empty(&wgroup->widgets));
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
if (wgroup->py_instance) {
|
||||
/* do this first in case there are any __del__ functions or
|
||||
* similar that use properties */
|
||||
BPY_DECREF_RNA_INVALIDATE(wgroup->py_instance);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wgroup->reports && (wgroup->reports->flag & RPT_FREE)) {
|
||||
BKE_reports_clear(wgroup->reports);
|
||||
MEM_freeN(wgroup->reports);
|
||||
}
|
||||
|
||||
if (wgroup->customdata_free) {
|
||||
wgroup->customdata_free(wgroup->customdata);
|
||||
}
|
||||
else {
|
||||
MEM_SAFE_FREE(wgroup->customdata);
|
||||
}
|
||||
|
||||
BLI_remlink(&wmap->widgetgroups, wgroup);
|
||||
MEM_freeN(wgroup);
|
||||
}
|
||||
|
||||
void wm_widgetgroup_attach_to_modal_handler(bContext *C, wmEventHandler *handler,
|
||||
wmWidgetGroupType *wgrouptype, wmOperator *op)
|
||||
{
|
||||
/* maybe overly careful, but widgetgrouptype could come from a failed creation */
|
||||
if (!wgrouptype) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* now instantiate the widgetmap */
|
||||
wgrouptype->op = op;
|
||||
|
||||
if (handler->op_region && !BLI_listbase_is_empty(&handler->op_region->widgetmaps)) {
|
||||
for (wmWidgetMap *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;
|
||||
}
|
||||
}
|
||||
|
||||
ED_region_tag_redraw(handler->op_region);
|
||||
}
|
||||
|
||||
WM_event_add_mousemove(C);
|
||||
}
|
||||
|
||||
/** \name Widget operators
|
||||
*
|
||||
* Basic operators for widget interaction with user configurable keymaps.
|
||||
*
|
||||
* \{ */
|
||||
|
||||
static int widget_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
|
||||
{
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
|
||||
bool extend = RNA_boolean_get(op->ptr, "extend");
|
||||
bool deselect = RNA_boolean_get(op->ptr, "deselect");
|
||||
bool toggle = RNA_boolean_get(op->ptr, "toggle");
|
||||
|
||||
|
||||
for (wmWidgetMap *wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) {
|
||||
wmWidget ***sel = &wmap->wmap_context.selected_widgets;
|
||||
wmWidget *highlighted = wmap->wmap_context.highlighted_widget;
|
||||
|
||||
/* deselect all first */
|
||||
if (extend == false && deselect == false && toggle == false) {
|
||||
wm_widgetmap_deselect_all(wmap, sel);
|
||||
BLI_assert(*sel == NULL && wmap->wmap_context.tot_selected == 0);
|
||||
}
|
||||
|
||||
if (highlighted) {
|
||||
const bool is_selected = (highlighted->flag & WM_WIDGET_SELECTED);
|
||||
bool redraw = false;
|
||||
|
||||
if (toggle) {
|
||||
/* toggle: deselect if already selected, else select */
|
||||
deselect = is_selected;
|
||||
}
|
||||
|
||||
if (deselect) {
|
||||
if (is_selected && wm_widget_deselect(wmap, highlighted)) {
|
||||
redraw = true;
|
||||
}
|
||||
}
|
||||
else if (wm_widget_select(C, wmap, highlighted)) {
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
else {
|
||||
BLI_assert(0);
|
||||
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
|
||||
}
|
||||
}
|
||||
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
void WIDGETGROUP_OT_widget_select(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Widget Select";
|
||||
ot->description = "Select the currently highlighted widget";
|
||||
ot->idname = "WIDGETGROUP_OT_widget_select";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = widget_select_invoke;
|
||||
|
||||
ot->flag = OPTYPE_UNDO;
|
||||
|
||||
WM_operator_properties_mouse_select(ot);
|
||||
}
|
||||
|
||||
typedef struct WidgetTweakData {
|
||||
wmWidgetMap *wmap;
|
||||
wmWidget *active;
|
||||
|
||||
int init_event; /* initial event type */
|
||||
int flag; /* tweak flags */
|
||||
} WidgetTweakData;
|
||||
|
||||
static void widget_tweak_finish(bContext *C, wmOperator *op, const bool cancel)
|
||||
{
|
||||
WidgetTweakData *wtweak = op->customdata;
|
||||
if (wtweak->active->exit) {
|
||||
wtweak->active->exit(C, wtweak->active, cancel);
|
||||
}
|
||||
wm_widgetmap_set_active_widget(wtweak->wmap, C, NULL, NULL);
|
||||
MEM_freeN(wtweak);
|
||||
}
|
||||
|
||||
static int widget_tweak_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
WidgetTweakData *wtweak = op->customdata;
|
||||
wmWidget *widget = wtweak->active;
|
||||
|
||||
if (!widget) {
|
||||
BLI_assert(0);
|
||||
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
|
||||
}
|
||||
|
||||
if (event->type == wtweak->init_event && event->val == KM_RELEASE) {
|
||||
widget_tweak_finish(C, op, false);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
||||
if (event->type == EVT_MODAL_MAP) {
|
||||
switch (event->val) {
|
||||
case TWEAK_MODAL_CANCEL:
|
||||
widget_tweak_finish(C, op, true);
|
||||
return OPERATOR_CANCELLED;
|
||||
case TWEAK_MODAL_CONFIRM:
|
||||
widget_tweak_finish(C, op, false);
|
||||
return OPERATOR_FINISHED;
|
||||
case TWEAK_MODAL_PRECISION_ON:
|
||||
wtweak->flag |= WM_WIDGET_TWEAK_PRECISE;
|
||||
break;
|
||||
case TWEAK_MODAL_PRECISION_OFF:
|
||||
wtweak->flag &= ~WM_WIDGET_TWEAK_PRECISE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle widget */
|
||||
if (widget->handler) {
|
||||
widget->handler(C, event, widget, wtweak->flag);
|
||||
}
|
||||
|
||||
/* Ugly hack to send widget events */
|
||||
((wmEvent *)event)->type = EVT_WIDGET_UPDATE;
|
||||
|
||||
/* always return PASS_THROUGH so modal handlers
|
||||
* with widgets attached can update */
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
static int widget_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
wmWidgetMap *wmap;
|
||||
wmWidget *widget;
|
||||
|
||||
for (wmap = ar->widgetmaps.first; wmap; wmap = wmap->next)
|
||||
if ((widget = wmap->wmap_context.highlighted_widget))
|
||||
break;
|
||||
|
||||
if (!widget) {
|
||||
/* wm_handlers_do_intern shouldn't let this happen */
|
||||
BLI_assert(0);
|
||||
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
|
||||
}
|
||||
|
||||
|
||||
/* activate highlighted widget */
|
||||
wm_widgetmap_set_active_widget(wmap, C, event, widget);
|
||||
|
||||
/* XXX temporary workaround for modal widget operator
|
||||
* conflicting with modal operator attached to widget */
|
||||
if (widget->opname) {
|
||||
wmOperatorType *ot = WM_operatortype_find(widget->opname, true);
|
||||
if (ot->modal) {
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WidgetTweakData *wtweak = MEM_mallocN(sizeof(WidgetTweakData), __func__);
|
||||
|
||||
wtweak->init_event = event->type;
|
||||
wtweak->active = wmap->wmap_context.highlighted_widget;
|
||||
wtweak->wmap = wmap;
|
||||
wtweak->flag = 0;
|
||||
|
||||
op->customdata = wtweak;
|
||||
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
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;
|
||||
ot->modal = widget_tweak_modal;
|
||||
|
||||
ot->flag = OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/** \} */ // Widget operators
|
||||
|
||||
|
||||
static wmKeyMap *widgetgroup_tweak_modal_keymap(wmKeyConfig *keyconf, const char *wgroupname)
|
||||
{
|
||||
wmKeyMap *keymap;
|
||||
char name[KMAP_MAX_NAME];
|
||||
|
||||
static EnumPropertyItem modal_items[] = {
|
||||
{TWEAK_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
|
||||
{TWEAK_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
|
||||
{TWEAK_MODAL_PRECISION_ON, "PRECISION_ON", 0, "Enable Precision", ""},
|
||||
{TWEAK_MODAL_PRECISION_OFF, "PRECISION_OFF", 0, "Disable Precision", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
BLI_snprintf(name, sizeof(name), "%s Tweak Modal Map", wgroupname);
|
||||
keymap = WM_modalkeymap_get(keyconf, name);
|
||||
|
||||
/* this function is called for each spacetype, only needs to add map once */
|
||||
if (keymap && keymap->modal_items)
|
||||
return NULL;
|
||||
|
||||
keymap = WM_modalkeymap_add(keyconf, name, modal_items);
|
||||
|
||||
|
||||
/* items for modal map */
|
||||
WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_CANCEL);
|
||||
WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_CANCEL);
|
||||
|
||||
WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_CONFIRM);
|
||||
WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_CONFIRM);
|
||||
|
||||
WM_modalkeymap_add_item(keymap, RIGHTSHIFTKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_PRECISION_ON);
|
||||
WM_modalkeymap_add_item(keymap, RIGHTSHIFTKEY, KM_RELEASE, KM_ANY, 0, TWEAK_MODAL_PRECISION_OFF);
|
||||
WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_PRECISION_ON);
|
||||
WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, TWEAK_MODAL_PRECISION_OFF);
|
||||
|
||||
|
||||
WM_modalkeymap_assign(keymap, "WIDGETGROUP_OT_widget_tweak");
|
||||
|
||||
return keymap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common default keymap for widget groups
|
||||
*/
|
||||
wmKeyMap *WM_widgetgroup_keymap_common(const struct wmWidgetGroupType *wgrouptype, wmKeyConfig *config)
|
||||
{
|
||||
/* Use area and region id since we might have multiple widgets with the same name in different areas/regions */
|
||||
wmKeyMap *km = WM_keymap_find(config, wgrouptype->name, wgrouptype->spaceid, wgrouptype->regionid);
|
||||
|
||||
WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_tweak", ACTIONMOUSE, KM_PRESS, KM_ANY, 0);
|
||||
widgetgroup_tweak_modal_keymap(config, wgrouptype->name);
|
||||
|
||||
return km;
|
||||
}
|
||||
|
||||
/**
|
||||
* Variation of #WM_widgetgroup_keymap_common but with keymap items for selection
|
||||
*/
|
||||
wmKeyMap *WM_widgetgroup_keymap_common_sel(const struct wmWidgetGroupType *wgrouptype, wmKeyConfig *config)
|
||||
{
|
||||
/* Use area and region id since we might have multiple widgets with the same name in different areas/regions */
|
||||
wmKeyMap *km = WM_keymap_find(config, wgrouptype->name, wgrouptype->spaceid, wgrouptype->regionid);
|
||||
|
||||
WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_tweak", ACTIONMOUSE, KM_PRESS, KM_ANY, 0);
|
||||
widgetgroup_tweak_modal_keymap(config, wgrouptype->name);
|
||||
|
||||
wmKeyMapItem *kmi = WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_select", SELECTMOUSE, KM_PRESS, 0, 0);
|
||||
RNA_boolean_set(kmi->ptr, "extend", false);
|
||||
RNA_boolean_set(kmi->ptr, "deselect", false);
|
||||
RNA_boolean_set(kmi->ptr, "toggle", false);
|
||||
kmi = WM_keymap_add_item(km, "WIDGETGROUP_OT_widget_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
|
||||
RNA_boolean_set(kmi->ptr, "extend", false);
|
||||
RNA_boolean_set(kmi->ptr, "deselect", false);
|
||||
RNA_boolean_set(kmi->ptr, "toggle", true);
|
||||
|
||||
return km;
|
||||
}
|
||||
|
||||
/** \} */ /* wmWidgetGroup */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name wmWidgetGroupType
|
||||
*
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Use this for registering widgets on startup. For runtime, use #WM_widgetgrouptype_append_runtime.
|
||||
*/
|
||||
wmWidgetGroupType *WM_widgetgrouptype_append(wmWidgetMapType *wmaptype, void (*wgrouptype_func)(wmWidgetGroupType *))
|
||||
{
|
||||
wmWidgetGroupType *wgrouptype = MEM_callocN(sizeof(wmWidgetGroupType), "widgetgroup");
|
||||
|
||||
wgrouptype_func(wgrouptype);
|
||||
wgrouptype->spaceid = wmaptype->spaceid;
|
||||
wgrouptype->regionid = wmaptype->regionid;
|
||||
wgrouptype->flag = wmaptype->flag;
|
||||
BLI_strncpy(wgrouptype->mapidname, wmaptype->idname, MAX_NAME);
|
||||
/* if not set, use default */
|
||||
if (!wgrouptype->keymap_init) {
|
||||
wgrouptype->keymap_init = WM_widgetgroup_keymap_common;
|
||||
}
|
||||
|
||||
/* add the type for future created areas of the same type */
|
||||
BLI_addtail(&wmaptype->widgetgrouptypes, wgrouptype);
|
||||
return wgrouptype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this for registering widgets on runtime.
|
||||
*/
|
||||
wmWidgetGroupType *WM_widgetgrouptype_append_runtime(
|
||||
const Main *main, wmWidgetMapType *wmaptype,
|
||||
void (*wgrouptype_func)(wmWidgetGroupType *))
|
||||
{
|
||||
wmWidgetGroupType *wgrouptype = WM_widgetgrouptype_append(wmaptype, wgrouptype_func);
|
||||
|
||||
/* Main is missing on startup when we create new areas.
|
||||
* So this is only called for widgets initialized on runtime */
|
||||
WM_widgetgrouptype_init_runtime(main, wmaptype, wgrouptype);
|
||||
|
||||
return wgrouptype;
|
||||
}
|
||||
|
||||
void WM_widgetgrouptype_init_runtime(
|
||||
const Main *bmain, wmWidgetMapType *wmaptype,
|
||||
wmWidgetGroupType *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 (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
|
||||
for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
|
||||
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
|
||||
ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
|
||||
for (ARegion *ar = lb->first; ar; ar = ar->next) {
|
||||
for (wmWidgetMap *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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WM_widgetgrouptype_unregister(bContext *C, Main *bmain, wmWidgetGroupType *wgrouptype)
|
||||
{
|
||||
for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
|
||||
for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
|
||||
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
|
||||
ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
|
||||
for (ARegion *ar = lb->first; ar; ar = ar->next) {
|
||||
for (wmWidgetMap *wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) {
|
||||
wmWidgetGroup *wgroup, *wgroup_next;
|
||||
|
||||
for (wgroup = wmap->widgetgroups.first; wgroup; wgroup = wgroup_next) {
|
||||
wgroup_next = wgroup->next;
|
||||
if (wgroup->type == wgrouptype) {
|
||||
wm_widgetgroup_free(C, wmap, wgroup);
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wmWidgetMapType *wmaptype = WM_widgetmaptype_find(&(const struct wmWidgetMapType_Params) {
|
||||
wgrouptype->mapidname, wgrouptype->spaceid,
|
||||
wgrouptype->regionid, wgrouptype->flag});
|
||||
|
||||
BLI_remlink(&wmaptype->widgetgrouptypes, wgrouptype);
|
||||
wgrouptype->prev = wgrouptype->next = NULL;
|
||||
|
||||
MEM_freeN(wgrouptype);
|
||||
}
|
||||
|
||||
void wm_widgetgrouptype_keymap_init(wmWidgetGroupType *wgrouptype, wmKeyConfig *keyconf)
|
||||
{
|
||||
wgrouptype->keymap = wgrouptype->keymap_init(wgrouptype, keyconf);
|
||||
}
|
||||
|
||||
/** \} */ /* wmWidgetGroupType */
|
826
source/blender/windowmanager/widgets/intern/wm_widgetmap.c
Normal file
826
source/blender/windowmanager/widgets/intern/wm_widgetmap.c
Normal file
@@ -0,0 +1,826 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2014 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/intern/wm_widgetmap.c
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_ghash.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "GL/glew.h"
|
||||
#include "GPU_select.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
#include "wm_event_system.h"
|
||||
|
||||
/* own includes */
|
||||
#include "wm_widget_wmapi.h"
|
||||
#include "wm_widget_intern.h"
|
||||
|
||||
/**
|
||||
* Store all widgetboxmaps here. Anyone who wants to register a widget for a certain
|
||||
* area type can query the widget map to do so.
|
||||
*/
|
||||
static ListBase widgetmaptypes = {NULL, NULL};
|
||||
|
||||
/**
|
||||
* List of all visible widgets to avoid unnecessary loops and wmWidgetGroupType->poll checks.
|
||||
* Collected in WM_widgets_update.
|
||||
*/
|
||||
static ListBase draw_widgets = {NULL, NULL};
|
||||
|
||||
/**
|
||||
* Widget map update/init tagging.
|
||||
*/
|
||||
enum eWidgetMapUpdateFlags {
|
||||
/* Set to init widget map. Should only be the case on first draw. */
|
||||
WIDGETMAP_INIT = (1 << 0),
|
||||
/* Tag widget map for refresh. */
|
||||
WIDGETMAP_REFRESH = (1 << 1),
|
||||
};
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name wmWidgetMap
|
||||
*
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* creates a widgetmap with all registered widgets for that type
|
||||
*/
|
||||
wmWidgetMap *WM_widgetmap_from_type(const struct wmWidgetMapType_Params *wmap_params)
|
||||
{
|
||||
wmWidgetMapType *wmaptype = WM_widgetmaptype_ensure(wmap_params);
|
||||
wmWidgetMap *wmap;
|
||||
|
||||
wmap = MEM_callocN(sizeof(wmWidgetMap), "WidgetMap");
|
||||
wmap->type = wmaptype;
|
||||
wmap->update_flag |= (WIDGETMAP_INIT | WIDGETMAP_REFRESH);
|
||||
|
||||
/* create all widgetgroups for this widgetmap. We may create an empty one
|
||||
* too in anticipation of widgets from operators etc */
|
||||
for (wmWidgetGroupType *wgrouptype = wmaptype->widgetgrouptypes.first; wgrouptype; wgrouptype = wgrouptype->next) {
|
||||
wmWidgetGroup *wgroup = MEM_callocN(sizeof(wmWidgetGroup), "widgetgroup");
|
||||
wgroup->type = wgrouptype;
|
||||
BLI_addtail(&wmap->widgetgroups, wgroup);
|
||||
}
|
||||
|
||||
return wmap;
|
||||
}
|
||||
|
||||
void wm_widgetmap_selected_delete(wmWidgetMap *wmap)
|
||||
{
|
||||
MEM_SAFE_FREE(wmap->wmap_context.selected_widgets);
|
||||
wmap->wmap_context.tot_selected = 0;
|
||||
}
|
||||
|
||||
void WM_widgetmap_delete(wmWidgetMap *wmap)
|
||||
{
|
||||
if (!wmap)
|
||||
return;
|
||||
|
||||
for (wmWidgetGroup *wgroup = wmap->widgetgroups.first, *wgroup_next; wgroup; wgroup = wgroup_next) {
|
||||
wgroup_next = wgroup->next;
|
||||
wm_widgetgroup_free(NULL, wmap, wgroup);
|
||||
}
|
||||
BLI_assert(BLI_listbase_is_empty(&wmap->widgetgroups));
|
||||
|
||||
wm_widgetmap_selected_delete(wmap);
|
||||
|
||||
MEM_freeN(wmap);
|
||||
}
|
||||
|
||||
wmWidgetMap *WM_widgetmap_find(
|
||||
const ARegion *ar, const struct wmWidgetMapType_Params *wmap_params)
|
||||
{
|
||||
for (wmWidgetMap *wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) {
|
||||
const wmWidgetMapType *wmaptype = wmap->type;
|
||||
|
||||
if (wmaptype->spaceid == wmap_params->spaceid &&
|
||||
wmaptype->regionid == wmap_params->regionid &&
|
||||
STREQ(wmaptype->idname, wmap_params->idname))
|
||||
{
|
||||
return wmap;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns idname hash table for (visible) widgets in \a wmap
|
||||
*
|
||||
* \param poll Polling function for excluding widgets.
|
||||
* \param data Custom data passed to \a poll
|
||||
*/
|
||||
static GHash *wm_widgetmap_widget_hash_new(
|
||||
const bContext *C, wmWidgetMap *wmap,
|
||||
bool (*poll)(const wmWidget *, void *),
|
||||
void *data, const bool include_hidden)
|
||||
{
|
||||
GHash *hash = BLI_ghash_str_new(__func__);
|
||||
|
||||
/* collect widgets */
|
||||
for (wmWidgetGroup *wgroup = wmap->widgetgroups.first; wgroup; wgroup = wgroup->next) {
|
||||
if (!wgroup->type->poll || wgroup->type->poll(C, wgroup->type)) {
|
||||
for (wmWidget *widget = wgroup->widgets.first; widget; widget = widget->next) {
|
||||
if ((include_hidden || (widget->flag & WM_WIDGET_HIDDEN) == 0) &&
|
||||
(!poll || poll(widget, data)))
|
||||
{
|
||||
BLI_ghash_insert(hash, widget->idname, widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
void WM_widgetmap_tag_refresh(wmWidgetMap *wmap)
|
||||
{
|
||||
if (wmap) {
|
||||
wmap->update_flag |= WIDGETMAP_REFRESH;
|
||||
}
|
||||
}
|
||||
|
||||
void WM_widgetmap_widgets_update(const bContext *C, wmWidgetMap *wmap)
|
||||
{
|
||||
if (!wmap || BLI_listbase_is_empty(&wmap->widgetgroups))
|
||||
return;
|
||||
|
||||
/* only active widget needs updating */
|
||||
if (wmap->wmap_context.active_widget) {
|
||||
wm_widget_calculate_scale(wmap->wmap_context.active_widget, C);
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (wmWidgetGroup *wgroup = wmap->widgetgroups.first; wgroup; wgroup = wgroup->next) {
|
||||
if ((wgroup->type->flag & WM_WIDGETGROUPTYPE_OP && !wgroup->type->op) || /* only while operator runs */
|
||||
(wgroup->type->poll && !wgroup->type->poll(C, wgroup->type)))
|
||||
continue;
|
||||
|
||||
/* prepare for first draw */
|
||||
if (UNLIKELY((wgroup->flag & WM_WIDGETGROUP_INITIALIZED) == 0)) {
|
||||
wgroup->type->init(C, wgroup);
|
||||
wgroup->flag |= WM_WIDGETGROUP_INITIALIZED;
|
||||
}
|
||||
/* update data if needed */
|
||||
if (wmap->update_flag & WIDGETMAP_REFRESH && wgroup->type->refresh) {
|
||||
wgroup->type->refresh(C, wgroup);
|
||||
}
|
||||
/* prepare drawing */
|
||||
if (wgroup->type->draw_prepare) {
|
||||
wgroup->type->draw_prepare(C, wgroup);
|
||||
}
|
||||
|
||||
for (wmWidget *widget = wgroup->widgets.first; widget; widget = widget->next) {
|
||||
if (widget->flag & WM_WIDGET_HIDDEN)
|
||||
continue;
|
||||
if (wmap->update_flag & WIDGETMAP_REFRESH) {
|
||||
wm_widget_update_prop_data(widget);
|
||||
}
|
||||
wm_widget_calculate_scale(widget, C);
|
||||
BLI_addhead(&draw_widgets, BLI_genericNodeN(widget));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
done:
|
||||
/* done updating */
|
||||
wmap->update_flag = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw all visible widgets in \a wmap.
|
||||
* Uses global draw_widgets listbase.
|
||||
*
|
||||
* \param in_scene draw depth-culled widgets (wmWidget->flag WM_WIDGET_SCENE_DEPTH) - TODO
|
||||
* \param free_drawwidgets free global draw_widgets listbase (always enable for last draw call in region!).
|
||||
*/
|
||||
void WM_widgetmap_widgets_draw(
|
||||
const bContext *C, const wmWidgetMap *wmap,
|
||||
const bool in_scene, const bool free_drawwidgets)
|
||||
{
|
||||
BLI_assert(!BLI_listbase_is_empty(&wmap->widgetgroups));
|
||||
if (!wmap)
|
||||
return;
|
||||
|
||||
const bool draw_multisample = (U.ogl_multisamples != USER_MULTISAMPLE_NONE);
|
||||
const bool use_lighting = (U.widget_flag & V3D_SHADED_WIDGETS) != 0;
|
||||
|
||||
/* enable multisampling */
|
||||
if (draw_multisample) {
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
}
|
||||
if (use_lighting) {
|
||||
const float lightpos[4] = {0.0, 0.0, 1.0, 0.0};
|
||||
const float diffuse[4] = {1.0, 1.0, 1.0, 0.0};
|
||||
|
||||
glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
wmWidget *widget = wmap->wmap_context.active_widget;
|
||||
|
||||
/* draw active widget */
|
||||
if (widget && in_scene == (widget->flag & WM_WIDGET_SCENE_DEPTH)) {
|
||||
if (widget->flag & (WM_WIDGET_DRAW_ACTIVE | WM_WIDGET_DRAW_VALUE)) {
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw selected widgets */
|
||||
if (wmap->wmap_context.selected_widgets) {
|
||||
for (int i = 0; i < wmap->wmap_context.tot_selected; i++) {
|
||||
widget = wmap->wmap_context.selected_widgets[i];
|
||||
if ((widget != NULL) &&
|
||||
(widget->flag & WM_WIDGET_HIDDEN) == 0 &&
|
||||
(in_scene == (widget->flag & WM_WIDGET_SCENE_DEPTH)))
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* draw other widgets */
|
||||
if (!wmap->wmap_context.active_widget) {
|
||||
/* draw_widgets excludes hidden widgets */
|
||||
for (LinkData *link = draw_widgets.first; link; link = link->next) {
|
||||
widget = link->data;
|
||||
if ((in_scene == (widget->flag & WM_WIDGET_SCENE_DEPTH)) &&
|
||||
((widget->flag & WM_WIDGET_SELECTED) == 0) && /* selected were drawn already */
|
||||
((widget->flag & WM_WIDGET_DRAW_HOVER) == 0 || (widget->flag & WM_WIDGET_HIGHLIGHT)))
|
||||
{
|
||||
widget->draw(C, widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (draw_multisample)
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
if (use_lighting)
|
||||
glPopAttrib();
|
||||
|
||||
if (free_drawwidgets) {
|
||||
BLI_freelistN(&draw_widgets);
|
||||
}
|
||||
}
|
||||
|
||||
static void widget_find_active_3D_loop(const bContext *C, ListBase *visible_widgets)
|
||||
{
|
||||
int selectionbase = 0;
|
||||
wmWidget *widget;
|
||||
|
||||
for (LinkData *link = visible_widgets->first; link; link = link->next) {
|
||||
widget = link->data;
|
||||
/* pass the selection id shifted by 8 bits. Last 8 bits are used for selected widget part id */
|
||||
widget->render_3d_intersection(C, widget, selectionbase << 8);
|
||||
|
||||
selectionbase++;
|
||||
}
|
||||
}
|
||||
|
||||
static int widget_find_highlighted_3D_intern(
|
||||
ListBase *visible_widgets, const bContext *C, const wmEvent *event, const float hotspot)
|
||||
{
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
View3D *v3d = sa->spacedata.first;
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
rctf rect, selrect;
|
||||
GLuint buffer[64]; // max 4 items per select, so large enuf
|
||||
short hits;
|
||||
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, ARRAY_SIZE(buffer), &selrect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
|
||||
else
|
||||
GPU_select_begin(buffer, ARRAY_SIZE(buffer), &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, ARRAY_SIZE(buffer), &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);
|
||||
|
||||
return hits > 0 ? buffer[3] : -1;
|
||||
}
|
||||
|
||||
static void widgets_prepare_visible_3D(wmWidgetMap *wmap, ListBase *visible_widgets, bContext *C)
|
||||
{
|
||||
wmWidget *widget;
|
||||
|
||||
for (wmWidgetGroup *wgroup = wmap->widgetgroups.first; wgroup; wgroup = wgroup->next) {
|
||||
if (!wgroup->type->poll || wgroup->type->poll(C, wgroup->type)) {
|
||||
for (widget = wgroup->widgets.first; widget; widget = widget->next) {
|
||||
if (widget->render_3d_intersection && (widget->flag & WM_WIDGET_HIDDEN) == 0) {
|
||||
BLI_addhead(visible_widgets, BLI_genericNodeN(widget));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wmWidget *wm_widgetmap_find_highlighted_3D(wmWidgetMap *wmap, bContext *C, const wmEvent *event, unsigned char *part)
|
||||
{
|
||||
wmWidget *result = NULL;
|
||||
ListBase visible_widgets = {0};
|
||||
const float hotspot = 14.0f;
|
||||
int ret;
|
||||
|
||||
widgets_prepare_visible_3D(wmap, &visible_widgets, C);
|
||||
|
||||
*part = 0;
|
||||
/* set up view matrices */
|
||||
view3d_operator_needs_opengl(C);
|
||||
|
||||
ret = widget_find_highlighted_3D_intern(&visible_widgets, C, event, 0.5f * hotspot);
|
||||
|
||||
if (ret != -1) {
|
||||
LinkData *link;
|
||||
int retsec;
|
||||
retsec = 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;
|
||||
}
|
||||
|
||||
void WM_widgetmaps_add_handlers(ARegion *ar)
|
||||
{
|
||||
for (wmWidgetMap *wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) {
|
||||
wmEventHandler *handler = MEM_callocN(sizeof(wmEventHandler), "widget handler");
|
||||
|
||||
handler->widgetmap = wmap;
|
||||
BLI_addtail(&ar->handlers, handler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void wm_widgetmaps_handled_modal_update(
|
||||
bContext *C, wmEvent *event, wmEventHandler *handler,
|
||||
const wmOperatorType *ot)
|
||||
{
|
||||
const bool modal_running = (handler->op != NULL);
|
||||
|
||||
/* happens on render */
|
||||
if (!handler->op_region)
|
||||
return;
|
||||
|
||||
/* hide operator widgets */
|
||||
if (!modal_running && ot->wgrouptype) {
|
||||
ot->wgrouptype->op = NULL;
|
||||
}
|
||||
|
||||
for (wmWidgetMap *wmap = handler->op_region->widgetmaps.first; wmap; wmap = wmap->next) {
|
||||
wmWidget *widget = wm_widgetmap_get_active_widget(wmap);
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
|
||||
wm_widgetmap_handler_context(C, handler);
|
||||
|
||||
/* regular update for running operator */
|
||||
if (modal_running) {
|
||||
if (widget && widget->handler && widget->opname && STREQ(widget->opname, handler->op->idname)) {
|
||||
widget->handler(C, event, widget, 0);
|
||||
}
|
||||
}
|
||||
/* operator not running anymore */
|
||||
else {
|
||||
wm_widgetmap_set_highlighted_widget(wmap, C, NULL, 0);
|
||||
wm_widgetmap_set_active_widget(wmap, C, event, NULL);
|
||||
}
|
||||
|
||||
/* restore the area */
|
||||
CTX_wm_area_set(C, area);
|
||||
CTX_wm_region_set(C, region);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deselect all selected widgets in \a wmap.
|
||||
* \return if selection has changed.
|
||||
*/
|
||||
bool wm_widgetmap_deselect_all(wmWidgetMap *wmap, wmWidget ***sel)
|
||||
{
|
||||
if (*sel == NULL || wmap->wmap_context.tot_selected == 0)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < wmap->wmap_context.tot_selected; i++) {
|
||||
(*sel)[i]->flag &= ~WM_WIDGET_SELECTED;
|
||||
(*sel)[i] = NULL;
|
||||
}
|
||||
wm_widgetmap_selected_delete(wmap);
|
||||
|
||||
/* always return true, we already checked
|
||||
* if there's anything to deselect */
|
||||
return true;
|
||||
}
|
||||
|
||||
BLI_INLINE bool widget_selectable_poll(const wmWidget *widget, void *UNUSED(data))
|
||||
{
|
||||
return (widget->flag & WM_WIDGET_SELECTABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select all selectable widgets in \a wmap.
|
||||
* \return if selection has changed.
|
||||
*/
|
||||
static bool wm_widgetmap_select_all_intern(bContext *C, wmWidgetMap *wmap, wmWidget ***sel, const int action)
|
||||
{
|
||||
/* GHash is used here to avoid having to loop over all widgets twice (once to
|
||||
* get tot_sel for allocating, once for actually selecting). Instead we collect
|
||||
* selectable widgets in hash table and use this to get tot_sel and do selection */
|
||||
|
||||
GHash *hash = wm_widgetmap_widget_hash_new(C, wmap, widget_selectable_poll, NULL, true);
|
||||
GHashIterator gh_iter;
|
||||
int i, *tot_sel = &wmap->wmap_context.tot_selected;
|
||||
bool changed = false;
|
||||
|
||||
*tot_sel = BLI_ghash_size(hash);
|
||||
*sel = MEM_reallocN(*sel, sizeof(**sel) * (*tot_sel));
|
||||
|
||||
GHASH_ITER_INDEX (gh_iter, hash, i) {
|
||||
wmWidget *widget_iter = BLI_ghashIterator_getValue(&gh_iter);
|
||||
|
||||
if ((widget_iter->flag & WM_WIDGET_SELECTED) == 0) {
|
||||
changed = true;
|
||||
}
|
||||
widget_iter->flag |= WM_WIDGET_SELECTED;
|
||||
if (widget_iter->select) {
|
||||
widget_iter->select(C, widget_iter, action);
|
||||
}
|
||||
(*sel)[i] = widget_iter;
|
||||
BLI_assert(i < (*tot_sel));
|
||||
}
|
||||
/* highlight first widget */
|
||||
wm_widgetmap_set_highlighted_widget(wmap, C, (*sel)[0], (*sel)[0]->highlighted_part);
|
||||
|
||||
BLI_ghash_free(hash, NULL, NULL);
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select/Deselect all selectable widgets in \a wmap.
|
||||
* \return if selection has changed.
|
||||
*
|
||||
* TODO select all by type
|
||||
*/
|
||||
bool WM_widgetmap_select_all(bContext *C, wmWidgetMap *wmap, const int action)
|
||||
{
|
||||
wmWidget ***sel = &wmap->wmap_context.selected_widgets;
|
||||
bool changed = false;
|
||||
|
||||
switch (action) {
|
||||
case SEL_SELECT:
|
||||
changed = wm_widgetmap_select_all_intern(C, wmap, sel, action);
|
||||
break;
|
||||
case SEL_DESELECT:
|
||||
changed = wm_widgetmap_deselect_all(wmap, sel);
|
||||
break;
|
||||
default:
|
||||
BLI_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
WM_event_add_mousemove(C);
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool wm_widgetmap_is_3d(const wmWidgetMap *wmap)
|
||||
{
|
||||
return (wmap->type->flag & WM_WIDGETMAPTYPE_3D) != 0;
|
||||
}
|
||||
|
||||
void wm_widgetmap_handler_context(bContext *C, wmEventHandler *handler)
|
||||
{
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
|
||||
if (screen) {
|
||||
if (handler->op_area == NULL) {
|
||||
/* do nothing in this context */
|
||||
}
|
||||
else {
|
||||
ScrArea *sa;
|
||||
|
||||
for (sa = screen->areabase.first; sa; sa = sa->next)
|
||||
if (sa == handler->op_area)
|
||||
break;
|
||||
if (sa == NULL) {
|
||||
/* when changing screen layouts with running modal handlers (like render display), this
|
||||
* is not an error to print */
|
||||
if (handler->widgetmap == NULL)
|
||||
printf("internal error: modal widgetmap handler has invalid area\n");
|
||||
}
|
||||
else {
|
||||
ARegion *ar;
|
||||
CTX_wm_area_set(C, sa);
|
||||
for (ar = sa->regionbase.first; ar; ar = ar->next)
|
||||
if (ar == handler->op_region)
|
||||
break;
|
||||
/* XXX no warning print here, after full-area and back regions are remade */
|
||||
if (ar)
|
||||
CTX_wm_region_set(C, ar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wmWidget *wm_widgetmap_find_highlighted_widget(wmWidgetMap *wmap, bContext *C, const wmEvent *event, unsigned char *part)
|
||||
{
|
||||
wmWidget *widget;
|
||||
|
||||
for (wmWidgetGroup *wgroup = wmap->widgetgroups.first; wgroup; wgroup = wgroup->next) {
|
||||
if (!wgroup->type->poll || wgroup->type->poll(C, wgroup->type)) {
|
||||
for (widget = wgroup->widgets.first; widget; widget = widget->next) {
|
||||
if (widget->intersect) {
|
||||
if ((*part = widget->intersect(C, event, widget)))
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool WM_widgetmap_cursor_set(const wmWidgetMap *wmap, wmWindow *win)
|
||||
{
|
||||
for (; wmap; wmap = wmap->next) {
|
||||
wmWidget *widget = wmap->wmap_context.highlighted_widget;
|
||||
if (widget && widget->get_cursor) {
|
||||
WM_cursor_set(win, widget->get_cursor(widget));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void wm_widgetmap_set_highlighted_widget(wmWidgetMap *wmap, const bContext *C, wmWidget *widget, unsigned char part)
|
||||
{
|
||||
if ((widget != wmap->wmap_context.highlighted_widget) || (widget && part != widget->highlighted_part)) {
|
||||
if (wmap->wmap_context.highlighted_widget) {
|
||||
wmap->wmap_context.highlighted_widget->flag &= ~WM_WIDGET_HIGHLIGHT;
|
||||
wmap->wmap_context.highlighted_widget->highlighted_part = 0;
|
||||
}
|
||||
|
||||
wmap->wmap_context.highlighted_widget = widget;
|
||||
|
||||
if (widget) {
|
||||
widget->flag |= WM_WIDGET_HIGHLIGHT;
|
||||
widget->highlighted_part = part;
|
||||
wmap->wmap_context.activegroup = widget->wgroup;
|
||||
|
||||
if (C && widget->get_cursor) {
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
WM_cursor_set(win, widget->get_cursor(widget));
|
||||
}
|
||||
}
|
||||
else {
|
||||
wmap->wmap_context.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);
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wmWidget *wm_widgetmap_get_highlighted_widget(wmWidgetMap *wmap)
|
||||
{
|
||||
return wmap->wmap_context.highlighted_widget;
|
||||
}
|
||||
|
||||
void wm_widgetmap_set_active_widget(wmWidgetMap *wmap, bContext *C, const wmEvent *event, wmWidget *widget)
|
||||
{
|
||||
if (widget && C) {
|
||||
widget->flag |= WM_WIDGET_ACTIVE;
|
||||
wmap->wmap_context.active_widget = widget;
|
||||
|
||||
if (widget->opname) {
|
||||
wmOperatorType *ot = WM_operatortype_find(widget->opname, 0);
|
||||
|
||||
if (ot) {
|
||||
/* first activate the widget itself */
|
||||
if (widget->invoke && widget->handler) {
|
||||
widget->invoke(C, event, widget);
|
||||
}
|
||||
|
||||
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->wmap_context.active_widget) {
|
||||
widget->flag &= ~WM_WIDGET_ACTIVE;
|
||||
/* first activate the widget itself */
|
||||
if (widget->interaction_data) {
|
||||
MEM_freeN(widget->interaction_data);
|
||||
widget->interaction_data = NULL;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
printf("Widget error: operator not found");
|
||||
wmap->wmap_context.active_widget = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (widget->invoke && widget->handler) {
|
||||
widget->invoke(C, event, widget);
|
||||
}
|
||||
}
|
||||
WM_cursor_grab_enable(CTX_wm_window(C), true, true, NULL);
|
||||
}
|
||||
else {
|
||||
widget = wmap->wmap_context.active_widget;
|
||||
|
||||
|
||||
/* deactivate, widget but first take care of some stuff */
|
||||
if (widget) {
|
||||
widget->flag &= ~WM_WIDGET_ACTIVE;
|
||||
/* first activate the widget itself */
|
||||
if (widget->interaction_data) {
|
||||
MEM_freeN(widget->interaction_data);
|
||||
widget->interaction_data = NULL;
|
||||
}
|
||||
}
|
||||
wmap->wmap_context.active_widget = NULL;
|
||||
|
||||
if (C) {
|
||||
WM_cursor_grab_disable(CTX_wm_window(C), NULL);
|
||||
ED_region_tag_redraw(CTX_wm_region(C));
|
||||
WM_event_add_mousemove(C);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wmWidget *wm_widgetmap_get_active_widget(wmWidgetMap *wmap)
|
||||
{
|
||||
return wmap->wmap_context.active_widget;
|
||||
}
|
||||
|
||||
/** \} */ /* wmWidgetMap */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name wmWidgetMapType
|
||||
*
|
||||
* \{ */
|
||||
|
||||
wmWidgetMapType *WM_widgetmaptype_find(
|
||||
const struct wmWidgetMapType_Params *wmap_params)
|
||||
{
|
||||
wmWidgetMapType *wmaptype;
|
||||
/* flags which differentiates widget groups */
|
||||
const int flag_cmp = WM_WIDGETMAPTYPE_3D;
|
||||
const int flag_test = wmap_params->flag & flag_cmp;
|
||||
|
||||
for (wmaptype = widgetmaptypes.first; wmaptype; wmaptype = wmaptype->next) {
|
||||
if (wmaptype->spaceid == wmap_params->spaceid &&
|
||||
wmaptype->regionid == wmap_params->regionid &&
|
||||
((wmaptype->flag & flag_cmp) == flag_test) &&
|
||||
STREQ(wmaptype->idname, wmap_params->idname))
|
||||
{
|
||||
return wmaptype;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wmWidgetMapType *WM_widgetmaptype_ensure(
|
||||
const struct wmWidgetMapType_Params *wmap_params)
|
||||
{
|
||||
wmWidgetMapType *wmaptype = WM_widgetmaptype_find(wmap_params);
|
||||
|
||||
if (wmaptype) {
|
||||
return wmaptype;
|
||||
}
|
||||
|
||||
wmaptype = MEM_callocN(sizeof(wmWidgetMapType), "widgettype list");
|
||||
wmaptype->spaceid = wmap_params->spaceid;
|
||||
wmaptype->regionid = wmap_params->regionid;
|
||||
wmaptype->flag = wmap_params->flag;
|
||||
BLI_strncpy(wmaptype->idname, wmap_params->idname, sizeof(wmaptype->idname));
|
||||
BLI_addhead(&widgetmaptypes, wmaptype);
|
||||
|
||||
return wmaptype;
|
||||
}
|
||||
|
||||
void WM_widgetmaptypes_free(void)
|
||||
{
|
||||
for (wmWidgetMapType *wmaptype = widgetmaptypes.first; wmaptype; wmaptype = wmaptype->next) {
|
||||
BLI_freelistN(&wmaptype->widgetgrouptypes);
|
||||
}
|
||||
BLI_freelistN(&widgetmaptypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize keymaps for all existing widget-groups
|
||||
*/
|
||||
void wm_widgets_keymap(wmKeyConfig *keyconf)
|
||||
{
|
||||
wmWidgetMapType *wmaptype;
|
||||
wmWidgetGroupType *wgrouptype;
|
||||
|
||||
/* we add this item-less keymap once and use it to group widgetgroup keymaps into it */
|
||||
WM_keymap_find(keyconf, "Widgets", 0, 0);
|
||||
|
||||
for (wmaptype = widgetmaptypes.first; wmaptype; wmaptype = wmaptype->next) {
|
||||
for (wgrouptype = wmaptype->widgetgrouptypes.first; wgrouptype; wgrouptype = wgrouptype->next) {
|
||||
wm_widgetgrouptype_keymap_init(wgrouptype, keyconf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */ /* wmWidgetMapType */
|
||||
|
167
source/blender/windowmanager/widgets/wm_widget_wmapi.h
Normal file
167
source/blender/windowmanager/widgets/wm_widget_wmapi.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/windowmanager/widgets/wm_widget_wmapi.h
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name Widgets Window Manager API
|
||||
* \brief API for usage in window manager code only.
|
||||
*
|
||||
* Only included in wm.h and lower level files.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __WM_WIDGET_WMAPI_H__
|
||||
#define __WM_WIDGET_WMAPI_H__
|
||||
|
||||
struct wmEventHandler;
|
||||
struct wmOperatorType;
|
||||
struct wmOperator;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* wmWidget */
|
||||
|
||||
typedef void (*wmWidgetSelectFunc)(struct bContext *, struct wmWidget *, const int);
|
||||
|
||||
|
||||
/* 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 */
|
||||
struct wmWidgetGroup *wgroup;
|
||||
|
||||
/* could become wmWidgetType */
|
||||
/* 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 */
|
||||
int (*intersect)(struct bContext *C, const struct wmEvent *event, struct wmWidget *widget);
|
||||
|
||||
/* determines 3d intersection by rendering the widget in a selection routine. */
|
||||
void (*render_3d_intersection)(const struct bContext *C, struct wmWidget *widget, int selectionbase);
|
||||
|
||||
/* handler used by the widget. Usually handles interaction tied to a widget type */
|
||||
int (*handler)(struct bContext *C, const struct wmEvent *event, struct wmWidget *widget, const int flag);
|
||||
|
||||
/* widget-specific handler to update widget attributes based on the property value */
|
||||
void (*prop_data_update)(struct wmWidget *widget, int slot);
|
||||
|
||||
/* returns the final position which may be different from the origin, depending on the widget.
|
||||
* used in calculations of scale */
|
||||
void (*get_final_position)(struct wmWidget *widget, float vec[3]);
|
||||
|
||||
/* activate a widget state when the user clicks on it */
|
||||
int (*invoke)(struct bContext *C, const struct wmEvent *event, struct wmWidget *widget);
|
||||
|
||||
/* called when widget tweaking is done - used to free data and reset property when cancelling */
|
||||
void (*exit)(bContext *C, struct wmWidget *widget, const bool cancel);
|
||||
|
||||
int (*get_cursor)(struct wmWidget *widget);
|
||||
|
||||
/* called when widget selection state changes */
|
||||
wmWidgetSelectFunc select;
|
||||
|
||||
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;
|
||||
/* user defined scale, in addition to the original one */
|
||||
float user_scale;
|
||||
/* user defined width for line drawing */
|
||||
float line_width;
|
||||
/* widget colors (uses default fallbacks if not defined) */
|
||||
float col[4], col_hi[4];
|
||||
|
||||
/* data used during interaction */
|
||||
void *interaction_data;
|
||||
|
||||
/* name of operator to spawn when activating the widget */
|
||||
const char *opname;
|
||||
/* operator properties if widget spawns and controls an operator, or owner pointer if widget spawns and controls a property */
|
||||
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 */
|
||||
PointerRNA *ptr;
|
||||
PropertyRNA **props;
|
||||
} wmWidget;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* wmWidgetGroup */
|
||||
|
||||
void WIDGETGROUP_OT_widget_select(struct wmOperatorType *ot);
|
||||
void WIDGETGROUP_OT_widget_tweak(struct wmOperatorType *ot);
|
||||
|
||||
void wm_widgetgroup_attach_to_modal_handler(struct bContext *C, struct wmEventHandler *handler,
|
||||
struct wmWidgetGroupType *wgrouptype, struct wmOperator *op);
|
||||
|
||||
/* wmWidgetGroupType->flag */
|
||||
enum {
|
||||
WM_WIDGETGROUPTYPE_3D = (1 << 0), /* WARNING: Don't change this! Bit used for wmWidgetMapType comparisons! */
|
||||
/* widget group is attached to operator, and is only accessible as long as this runs */
|
||||
WM_WIDGETGROUPTYPE_OP = (1 << 10),
|
||||
WM_WIDGETGROUP_INITIALIZED = (1 << 11), /* wgroup has been initialized */
|
||||
};
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* wmWidgetMap */
|
||||
|
||||
void wm_widgets_keymap(struct wmKeyConfig *keyconf);
|
||||
|
||||
bool wm_widgetmap_is_3d(const struct wmWidgetMap *wmap);
|
||||
|
||||
void wm_widgetmaps_handled_modal_update(
|
||||
bContext *C, struct wmEvent *event, struct wmEventHandler *handler,
|
||||
const struct wmOperatorType *ot);
|
||||
void wm_widgetmap_handler_context(bContext *C, struct wmEventHandler *handler);
|
||||
|
||||
wmWidget *wm_widgetmap_find_highlighted_3D(struct wmWidgetMap *wmap, bContext *C,
|
||||
const struct wmEvent *event, unsigned char *part);
|
||||
wmWidget *wm_widgetmap_find_highlighted_widget(struct wmWidgetMap *wmap, bContext *C,
|
||||
const struct wmEvent *event, unsigned char *part);
|
||||
void wm_widgetmap_set_highlighted_widget(struct wmWidgetMap *wmap, const bContext *C,
|
||||
wmWidget *widget, unsigned char part);
|
||||
wmWidget *wm_widgetmap_get_highlighted_widget(struct wmWidgetMap *wmap);
|
||||
void wm_widgetmap_set_active_widget(struct wmWidgetMap *wmap, bContext *C,
|
||||
const struct wmEvent *event, wmWidget *widget);
|
||||
wmWidget *wm_widgetmap_get_active_widget(struct wmWidgetMap *wmap);
|
||||
|
||||
bool wm_widgetmap_deselect_all(struct wmWidgetMap *wmap, wmWidget ***sel);
|
||||
|
||||
#endif /* __WM_WIDGET_WMAPI_H__ */
|
||||
|
@@ -68,6 +68,8 @@ typedef struct wmEventHandler {
|
||||
|
||||
/* drop box handler */
|
||||
ListBase *dropboxes;
|
||||
/* widget handler */
|
||||
struct wmWidgetMap *widgetmap;
|
||||
|
||||
} wmEventHandler;
|
||||
|
||||
|
@@ -339,6 +339,8 @@ enum {
|
||||
EVT_DROP = 0x5023,
|
||||
EVT_BUT_CANCEL = 0x5024,
|
||||
|
||||
/* could become widget callback */
|
||||
EVT_WIDGET_UPDATE = 0x5024,
|
||||
/* ********** End of Blender internal events. ********** */
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user