diff --git a/source/blender/editors/include/BIF_interface_icons.h b/source/blender/editors/include/BIF_interface_icons.h index 63ce89eef62..e69de29bb2d 100644 --- a/source/blender/editors/include/BIF_interface_icons.h +++ b/source/blender/editors/include/BIF_interface_icons.h @@ -1,72 +0,0 @@ -/** - * $Id: BIF_interface_icons.h 11920 2007-09-02 17:25:03Z elubie $ - * - * ***** BEGIN GPL/BL DUAL 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. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef BIF_PREVIEW_ICONS_H -#define BIF_PREVIEW_ICONS_H - -struct Image; -struct ImBuf; -struct World; -struct Tex; -struct Lamp; -struct Material; - -typedef struct IconFile { - struct IconFile *next, *prev; - char filename[80]; // FILE_MAXFILE size - int index; -} IconFile; - - -#define ICON_DEFAULT_HEIGHT 16 -#define PREVIEW_DEFAULT_HEIGHT 96 - -/* - Resizable Icons for Blender -*/ -void BIF_icons_init(int first_dyn_id); -int BIF_icon_get_width(int icon_id); -int BIF_icon_get_height(int icon_id); - -void BIF_icon_draw(float x, float y, int icon_id); -void BIF_icon_draw_preview(float x, float y, int icon_id, int nocreate); - -void BIF_icon_draw_aspect(float x, float y, int icon_id, float aspect); -void BIF_icon_draw_aspect_blended(float x, float y, int icon_id, float aspect, int shade); -void BIF_icons_free(); -void BIF_icons_free_drawinfo(void *drawinfo); - -struct ListBase *BIF_iconfile_list(void); -int BIF_iconfile_get_index(char *filename); - - -#endif /* BIF_ICONS_H */ diff --git a/source/blender/editors/include/BIF_resources.h b/source/blender/editors/include/BIF_resources.h index 38540f1ba39..e69de29bb2d 100644 --- a/source/blender/editors/include/BIF_resources.h +++ b/source/blender/editors/include/BIF_resources.h @@ -1,600 +0,0 @@ -/** - * $Id: BIF_resources.h 13057 2007-12-30 12:08:28Z aligorith $ - * - * ***** BEGIN GPL/BL DUAL 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. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef BIF_RESOURCES_H -#define BIF_RESOURCES_H - -/* elubie: TODO: move the typedef for icons to BIF_interface_icons.h */ -/* and add/replace include of BIF_resources.h by BIF_interface_icons.h */ -typedef enum { -#define BIFICONID_FIRST (ICON_VIEW3D) - ICON_VIEW3D, - ICON_IPO, - ICON_OOPS, - ICON_BUTS, - ICON_FILESEL, - ICON_IMAGE_COL, - ICON_INFO, - ICON_SEQUENCE, - ICON_TEXT, - ICON_IMASEL, - ICON_SOUND, - ICON_ACTION, - ICON_NLA, - ICON_SCRIPTWIN, - ICON_TIME, - ICON_NODE, - ICON_SPACE2, - ICON_SPACE3, - ICON_SPACE4, - ICON_TRIA_LEFT, - ICON_TRIA_UP, - ICON_FONTPREVIEW, - ICON_BLANK4, - ICON_BLANK5, - ICON_BLANK6, - - ICON_ORTHO, - ICON_PERSP, - ICON_CAMERA, - ICON_PARTICLES, - ICON_BBOX, - ICON_WIRE, - ICON_SOLID, - ICON_SMOOTH, - ICON_POTATO, - ICON_MARKER_HLT, - ICON_PMARKER_ACT, - ICON_PMARKER_SEL, - ICON_PMARKER, - ICON_VIEWZOOM, - ICON_SORTALPHA, - ICON_SORTTIME, - ICON_SORTSIZE, - ICON_LONGDISPLAY, - ICON_SHORTDISPLAY, - ICON_TRIA_DOWN, - ICON_TRIA_RIGHT, - ICON_BLANK7, - ICON_BLANK8, - ICON_BLANK9, - ICON_BLANK10, - - ICON_VIEW_AXIS_ALL, - ICON_VIEW_AXIS_NONE, - ICON_VIEW_AXIS_NONE2, - ICON_VIEW_AXIS_TOP, - ICON_VIEW_AXIS_FRONT, - ICON_VIEW_AXIS_SIDE, - ICON_POSE_DEHLT, - ICON_POSE_HLT, - ICON_BORDERMOVE, - ICON_MAYBE_ITS_A_LASSO, - ICON_BLANK1, /* ATTENTION, someone decided to use this throughout blender - and didn't care to neither rename it nor update the PNG */ - ICON_VERSE, - ICON_MOD_BOOLEAN, - ICON_ARMATURE, - ICON_PAUSE, - ICON_ALIGN, - ICON_REC, - ICON_PLAY, - ICON_FF, - ICON_REW, - ICON_PYTHON, - ICON_BLANK11, - ICON_BLANK12, - ICON_BLANK13, - ICON_BLANK14, - - - ICON_DOTSUP, - ICON_DOTSDOWN, - ICON_MENU_PANEL, - ICON_AXIS_SIDE, - ICON_AXIS_FRONT, - ICON_AXIS_TOP, - ICON_STICKY_UVS_LOC, - ICON_STICKY_UVS_DISABLE, - ICON_STICKY_UVS_VERT, - ICON_PREV_KEYFRAME, - ICON_NEXT_KEYFRAME, - ICON_ENVMAP, - ICON_TRANSP_HLT, - ICON_TRANSP_DEHLT, - ICON_CIRCLE_DEHLT, - ICON_CIRCLE_HLT, - ICON_TPAINT_DEHLT, - ICON_TPAINT_HLT, - ICON_WPAINT_DEHLT, - ICON_WPAINT_HLT, - ICON_MARKER, - ICON_BLANK15, - ICON_BLANK16, - ICON_BLANK17, - ICON_BLANK18, - - ICON_X, - ICON_GO_LEFT, - ICON_NO_GO_LEFT, - ICON_UNLOCKED, - ICON_LOCKED, - ICON_PARLIB, - ICON_DATALIB, - ICON_AUTO, - ICON_MATERIAL_DEHLT2, - ICON_RING, - ICON_GRID, - ICON_PROPEDIT, - ICON_KEEPRECT, - ICON_DESEL_CUBE_VERTS, - ICON_EDITMODE_DEHLT, - ICON_EDITMODE_HLT, - ICON_VPAINT_DEHLT, - ICON_VPAINT_HLT, - ICON_FACESEL_DEHLT, - ICON_FACESEL_HLT, - ICON_EDIT_DEHLT, - ICON_BOOKMARKS, - ICON_BLANK20, - ICON_BLANK21, - ICON_BLANK22, - - ICON_HELP, - ICON_ERROR, - ICON_FOLDER_DEHLT, - ICON_FOLDER_HLT, - ICON_BLUEIMAGE_DEHLT, - ICON_BLUEIMAGE_HLT, - ICON_BPIBFOLDER_DEHLT, - ICON_BPIBFOLDER_HLT, - ICON_BPIBFOLDER_ERR, - ICON_UGLY_GREEN_RING, - ICON_GHOST, - ICON_SORTBYEXT, - ICON_SCULPTMODE_HLT, - ICON_VERTEXSEL, - ICON_EDGESEL, - ICON_FACESEL, - ICON_PLUS, - ICON_BPIBFOLDER_X, - ICON_BPIBFOLDERGREY, - ICON_MAGNIFY, - ICON_INFO2, - ICON_BLANK23, - ICON_BLANK24, - ICON_BLANK25, - ICON_BLANK26, - - ICON_RIGHTARROW, - ICON_DOWNARROW_HLT, - ICON_ROUNDBEVELTHING, - ICON_FULLTEXTURE, - ICON_HOOK, - ICON_DOT, - ICON_WORLD_DEHLT, - ICON_CHECKBOX_DEHLT, - ICON_CHECKBOX_HLT, - ICON_LINK, - ICON_INLINK, - ICON_ZOOMIN, - ICON_ZOOMOUT, - ICON_PASTEDOWN, - ICON_COPYDOWN, - ICON_CONSTANT, - ICON_LINEAR, - ICON_CYCLIC, - ICON_KEY_DEHLT, - ICON_KEY_HLT, - ICON_GRID2, - ICON_BLANK27, - ICON_BLANK28, - ICON_BLANK29, - ICON_BLANK30, - - ICON_EYE, - ICON_LAMP, - ICON_MATERIAL, - ICON_TEXTURE, - ICON_ANIM, - ICON_WORLD, - ICON_SCENE, - ICON_EDIT, - ICON_GAME, - ICON_PAINT, - ICON_RADIO, - ICON_SCRIPT, - ICON_SPEAKER, - ICON_PASTEUP, - ICON_COPYUP, - ICON_PASTEFLIPUP, - ICON_PASTEFLIPDOWN, - ICON_CYCLICLINEAR, - ICON_PIN_DEHLT, - ICON_PIN_HLT, - ICON_LITTLEGRID, - ICON_BLANK31, - ICON_BLANK32, - ICON_BLANK33, - ICON_BLANK34, - - ICON_FULLSCREEN, - ICON_SPLITSCREEN, - ICON_RIGHTARROW_THIN, - ICON_DISCLOSURE_TRI_RIGHT, - ICON_DISCLOSURE_TRI_DOWN, - ICON_SCENE_SEPIA, - ICON_SCENE_DEHLT, - ICON_OBJECT, - ICON_MESH, - ICON_CURVE, - ICON_MBALL, - ICON_LATTICE, - ICON_LAMP_DEHLT, - ICON_MATERIAL_DEHLT, - ICON_TEXTURE_DEHLT, - ICON_IPO_DEHLT, - ICON_LIBRARY_DEHLT, - ICON_IMAGE_DEHLT, - ICON_EYEDROPPER, - ICON_WINDOW_WINDOW, - ICON_PANEL_CLOSE, - ICON_PHYSICS, - ICON_BLANK36, - ICON_BLANK37, - ICON_BLANK38, - - ICON_BLENDER, - ICON_PACKAGE, - ICON_UGLYPACKAGE, - ICON_MATPLANE, - ICON_MATSPHERE, - ICON_MATCUBE, - ICON_SCENE_HLT, - ICON_OBJECT_HLT, - ICON_MESH_HLT, - ICON_CURVE_HLT, - ICON_MBALL_HLT, - ICON_LATTICE_HLT, - ICON_LAMP_HLT, - ICON_MATERIAL_HLT, - ICON_TEXTURE_HLT, - ICON_IPO_HLT, - ICON_LIBRARY_HLT, - ICON_IMAGE_HLT, - ICON_CONSTRAINT, - ICON_CAMERA_DEHLT, - ICON_ARMATURE_DEHLT, - ICON_SNAP_GEAR, - ICON_SNAP_GEO, - ICON_BLANK41, - ICON_BLANK42, - - ICON_SMOOTHCURVE, - ICON_SPHERECURVE, - ICON_ROOTCURVE, - ICON_SHARPCURVE, - ICON_LINCURVE, - ICON_NOCURVE, - ICON_RNDCURVE, - ICON_PROP_OFF, - ICON_PROP_ON, - ICON_PROP_CON, - ICON_SYNTAX, - ICON_SYNTAX_OFF, - ICON_MONKEY, - ICON_HAIR, - ICON_VIEWMOVE, - ICON_HOME, - ICON_CLIPUV_DEHLT, - ICON_CLIPUV_HLT, - ICON_BLANK2, - ICON_BLANK3, - ICON_VPAINT_COL, - ICON_RESTRICT_SELECT_OFF, - ICON_RESTRICT_SELECT_ON, - ICON_MUTE_IPO_OFF, - ICON_MUTE_IPO_ON, - - ICON_MAN_TRANS, - ICON_MAN_ROT, - ICON_MAN_SCALE, - ICON_MANIPUL, - ICON_BLANK_47, - ICON_MODIFIER, - ICON_MOD_WAVE, - ICON_MOD_BUILD, - ICON_MOD_DECIM, - ICON_MOD_MIRROR, - ICON_MOD_SOFT, - ICON_MOD_SUBSURF, - ICON_SEQ_SEQUENCER, - ICON_SEQ_PREVIEW, - ICON_SEQ_LUMA_WAVEFORM, - ICON_SEQ_CHROMA_SCOPE, - ICON_ROTATE, - ICON_CURSOR, - ICON_ROTATECOLLECTION, - ICON_ROTATECENTER, - ICON_ROTACTIVE, - ICON_RESTRICT_VIEW_OFF, - ICON_RESTRICT_VIEW_ON, - ICON_RESTRICT_RENDER_OFF, - ICON_RESTRICT_RENDER_ON, - - VICON_VIEW3D, - VICON_EDIT, - VICON_EDITMODE_DEHLT, - VICON_EDITMODE_HLT, - VICON_DISCLOSURE_TRI_RIGHT, - VICON_DISCLOSURE_TRI_DOWN, - VICON_MOVE_UP, - VICON_MOVE_DOWN, - VICON_X - -#define BIFICONID_LAST (VICON_X) -#define BIFNICONIDS (BIFICONID_LAST-BIFICONID_FIRST + 1) -} BIFIconID; - -typedef enum { -#define BIFCOLORSHADE_FIRST (COLORSHADE_DARK) - COLORSHADE_DARK, - COLORSHADE_GREY, - COLORSHADE_MEDIUM, - COLORSHADE_HILITE, - COLORSHADE_LIGHT, - COLORSHADE_WHITE -#define BIFCOLORSHADE_LAST (COLORSHADE_WHITE) -#define BIFNCOLORSHADES (BIFCOLORSHADE_LAST-BIFCOLORSHADE_FIRST + 1) -} BIFColorShade; - -typedef enum { -#define BIFCOLORID_FIRST (BUTGREY) - BUTGREY = 0, - BUTGREEN, - BUTBLUE, - BUTSALMON, - MIDGREY, - BUTPURPLE, - BUTYELLOW, - REDALERT, - BUTRUST, - BUTWHITE, - BUTDBLUE, - BUTPINK, - BUTDPINK, - BUTMACTIVE, - - BUTIPO, - BUTAUDIO, - BUTCAMERA, - BUTRANDOM, - BUTEDITOBJECT, - BUTPROPERTY, - BUTSCENE, - BUTMOTION, - BUTMESSAGE, - BUTACTION, - BUTCD, - BUTGAME, - BUTVISIBILITY, - BUTYUCK, - BUTSEASICK, - BUTCHOKE, - BUTIMPERIAL, - - BUTTEXTCOLOR, - BUTTEXTPRESSED, - BUTSBACKGROUND, - - VIEWPORTBACKCOLOR, - VIEWPORTGRIDCOLOR, - VIEWPORTACTIVECOLOR, - VIEWPORTSELECTEDCOLOR, - VIEWPORTUNSELCOLOR, - - EDITVERTSEL, - EDITVERTUNSEL, - EDITEDGESEL, - EDITEDGEUNSEL - -#define BIFCOLORID_LAST (EDITEDGEUNSEL) -#define BIFNCOLORIDS (BIFCOLORID_LAST-BIFCOLORID_FIRST + 1) - -} BIFColorID; - -/* XXX WARNING: this is saved in file, so do not change order! */ -enum { - TH_AUTO, /* for buttons, to signal automatic color assignment */ - -// uibutton colors - TH_BUT_OUTLINE, - TH_BUT_NEUTRAL, - TH_BUT_ACTION, - TH_BUT_SETTING, - TH_BUT_SETTING1, - TH_BUT_SETTING2, - TH_BUT_NUM, - TH_BUT_TEXTFIELD, - TH_BUT_POPUP, - TH_BUT_TEXT, - TH_BUT_TEXT_HI, - TH_MENU_BACK, - TH_MENU_ITEM, - TH_MENU_HILITE, - TH_MENU_TEXT, - TH_MENU_TEXT_HI, - - TH_BUT_DRAWTYPE, - - TH_REDALERT, - TH_CUSTOM, - - TH_BUT_TEXTFIELD_HI, - TH_ICONFILE, - - TH_THEMEUI, -// common colors among spaces - - TH_BACK, - TH_TEXT, - TH_TEXT_HI, - TH_HEADER, - TH_HEADERDESEL, - TH_PANEL, - TH_SHADE1, - TH_SHADE2, - TH_HILITE, - - TH_GRID, - TH_WIRE, - TH_SELECT, - TH_ACTIVE, - TH_GROUP, - TH_GROUP_ACTIVE, - TH_TRANSFORM, - TH_VERTEX, - TH_VERTEX_SELECT, - TH_VERTEX_SIZE, - TH_EDGE, - TH_EDGE_SELECT, - TH_EDGE_SEAM, - TH_EDGE_FACESEL, - TH_FACE, - TH_FACE_SELECT, - TH_NORMAL, - TH_FACE_DOT, - TH_FACEDOT_SIZE, - TH_CFRAME, - - TH_SYNTAX_B, - TH_SYNTAX_V, - TH_SYNTAX_C, - TH_SYNTAX_L, - TH_SYNTAX_N, - - TH_BONE_SOLID, - TH_BONE_POSE, - - TH_STRIP, - TH_STRIP_SELECT, - - TH_LAMP, - - TH_NODE, - TH_NODE_IN_OUT, - TH_NODE_OPERATOR, - TH_NODE_CONVERTOR, - TH_NODE_GROUP, - - TH_SEQ_MOVIE, - TH_SEQ_IMAGE, - TH_SEQ_SCENE, - TH_SEQ_AUDIO, - TH_SEQ_EFFECT, - TH_SEQ_PLUGIN, - TH_SEQ_TRANSITION, - TH_SEQ_META, - - TH_EDGE_SHARP, - TH_EDITMESH_ACTIVE, -}; -/* XXX WARNING: previous is saved in file, so do not change order! */ - -/* theme drawtypes */ -#define TH_MINIMAL 0 -#define TH_SHADED 1 -#define TH_ROUNDED 2 -#define TH_OLDSKOOL 3 - -/* specific defines per space should have higher define values */ - -struct bTheme; - -// THE CODERS API FOR THEMES: - -// sets the color -void BIF_ThemeColor(int colorid); - -// sets the color plus alpha -void BIF_ThemeColor4(int colorid); - -// sets color plus offset for shade -void BIF_ThemeColorShade(int colorid, int offset); - -// sets color plus offset for alpha -void BIF_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset); - -// sets color, which is blend between two theme colors -void BIF_ThemeColorBlend(int colorid1, int colorid2, float fac); -// same, with shade offset -void BIF_ThemeColorBlendShade(int colorid1, int colorid2, float fac, int offset); - -// returns one value, not scaled -float BIF_GetThemeValuef(int colorid); -int BIF_GetThemeValue(int colorid); - -// get three color values, scaled to 0.0-1.0 range -void BIF_GetThemeColor3fv(int colorid, float *col); - -// get the 3 or 4 byte values -void BIF_GetThemeColor3ubv(int colorid, char *col); -void BIF_GetThemeColor4ubv(int colorid, char *col); - -// get a theme color from specified space type -void BIF_GetThemeColorType4ubv(int colorid, int spacetype, char *col); - -// blends and shades between two color pointers -void BIF_ColorPtrBlendShade3ubv(char *cp1, char *cp2, float fac, int offset); - -// get a 3 byte color, blended and shaded between two other char color pointers -void BIF_GetColorPtrBlendShade3ubv(char *cp1, char *cp2, char *col, float fac, int offset); - - -struct ScrArea; - -// internal (blender) usage only, for init and set active -void BIF_InitTheme(void); -void BIF_SetTheme(struct ScrArea *sa); -void BIF_resources_init (void); -void BIF_resources_free (void); -void BIF_colors_init (void); -void BIF_load_ui_colors (void); - -/* only for buttons in theme editor! */ -char *BIF_ThemeGetColorPtr(struct bTheme *btheme, int spacetype, int colorid); -char *BIF_ThemeColorsPup(int spacetype); - - -void BIF_def_color (BIFColorID colorid, unsigned char r, unsigned char g, unsigned char b); - -#endif /* BIF_ICONS_H */ diff --git a/source/blender/editors/include/BIF_view2d.h b/source/blender/editors/include/BIF_view2d.h index ed86a1cf9c3..e69de29bb2d 100644 --- a/source/blender/editors/include/BIF_view2d.h +++ b/source/blender/editors/include/BIF_view2d.h @@ -1,68 +0,0 @@ -/** - * $Id: - * - * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - * - * - * Contributor(s): Blender Foundation - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef BIF_VIEW2D_H -#define BIF_VIEW2D_H - -/* start of a generic 2d view with should allow drawing grids, - * panning, zooming, scrolling, .. */ - -#define V2D_UNIT_SECONDS 0 -#define V2D_UNIT_FRAMES 1 - -#define V2D_GRID_CLAMP 0 -#define V2D_GRID_NOCLAMP 1 - -#define V2D_IS_CLIPPED 12000 - -#define V2D_HORIZONTAL_LINES 1 -#define V2D_VERTICAL_LINES 2 -#define V2D_HORIZONTAL_AXIS 4 -#define V2D_VERTICAL_AXIS 8 - -struct View2D; -struct View2DGrid; -struct bContext; - -typedef struct View2DGrid View2DGrid; - -/* opengl drawing setup */ -void BIF_view2d_ortho(const struct bContext *C, struct View2D *v2d); - -/* grid drawing */ -View2DGrid *BIF_view2d_calc_grid(const struct bContext *C, struct View2D *v2d, int unit, int type, int winx, int winy); -void BIF_view2d_draw_grid(const struct bContext *C, struct View2D *v2d, View2DGrid *grid, int flag); -void BIF_view2d_free_grid(View2DGrid *grid); - -/* coordinate conversion */ -void BIF_view2d_region_to_view(struct View2D *v2d, short x, short y, float *viewx, float *viewy); -void BIF_view2d_view_to_region(struct View2D *v2d, float x, float y, short *regionx, short *regiony); -void BIF_view2d_to_region_no_clip(struct View2D *v2d, float x, float y, short *regionx, short *region_y); - -#endif /* BIF_VIEW2D_H */ - diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h new file mode 100644 index 00000000000..ddf3f0c9468 --- /dev/null +++ b/source/blender/editors/include/ED_datafiles.h @@ -0,0 +1,50 @@ +/** + * $Id$ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef ED_DATAFILES_H +#define ED_DATAFILES_H + +/* Datafiles embedded in Blender */ + +extern int datatoc_B_blend_size; +extern char datatoc_B_blend[]; + +extern int datatoc_blenderbuttons_size; +extern char datatoc_blenderbuttons[]; + +extern int datatoc_splash_jpg_size; +extern char datatoc_splash_jpg[]; + +extern int datatoc_Bfont_size; +extern char datatoc_Bfont; + +extern int datatoc_bfont_ttf_size; +extern char datatoc_bfont_ttf[]; + +#endif /* ED_DATAFILES_H */ + diff --git a/source/blender/editors/include/ED_interface.h b/source/blender/editors/include/ED_interface.h index d0f3078ce62..e69de29bb2d 100644 --- a/source/blender/editors/include/ED_interface.h +++ b/source/blender/editors/include/ED_interface.h @@ -1,33 +0,0 @@ -/** - * $Id: - * - * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - * - * - * Contributor(s): Blender Foundation - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef ED_INTERFACE_H -#define ED_INTERFACE_H - - -#endif /* ED_INTERFACE_H */ - diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h new file mode 100644 index 00000000000..a4f29e37e34 --- /dev/null +++ b/source/blender/editors/include/UI_interface.h @@ -0,0 +1,350 @@ +/** + * $Id$ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 ***** + */ + +#ifndef UI_INTERFACE_H +#define UI_INTERFACE_H + +struct ID; +struct ListBase; +struct ARegion; +struct wmWindow; +struct wmWindowManager; +struct AutoComplete; +struct bContext; + +/* uiBlock->dt */ +#define UI_EMBOSS 0 /* use one of the themes for drawing */ +#define UI_EMBOSSN 1 /* Nothing */ +#define UI_EMBOSSM 2 /* Minimal builtin emboss, also for logic buttons */ +#define UI_EMBOSSP 3 /* Pulldown */ +#define UI_EMBOSSR 4 /* Rounded */ +#define UI_EMBOSST 5 /* Table */ + +#define UI_EMBOSSX 0 /* for a python file, which i can't change.... duh! */ + +/* uiBlock->direction */ +#define UI_TOP 1 +#define UI_DOWN 2 +#define UI_LEFT 4 +#define UI_RIGHT 8 +#define UI_DIRECTION 15 +#define UI_CENTER 16 +#define UI_SHIFT_FLIPPED 32 + +/* uiBlock->autofill */ +#define UI_BLOCK_COLLUMNS 1 +#define UI_BLOCK_ROWS 2 + +/* uiBlock->flag (controls) */ +#define UI_BLOCK_LOOP 1 +#define UI_BLOCK_REDRAW 2 +#define UI_BLOCK_RET_1 4 /* XXX 2.5 not implemented */ +#define UI_BLOCK_NUMSELECT 8 +#define UI_BLOCK_ENTER_OK 16 +#define UI_BLOCK_NOSHADOW 32 +#define UI_BLOCK_NO_HILITE 64 /* XXX 2.5 not implemented */ +#define UI_BLOCK_MOVEMOUSE_QUIT 128 +#define UI_BLOCK_KEEP_OPEN 256 + +/* uiMenuBlockHandle->blockretval */ +#define UI_RETURN_CANCEL 1 /* cancel all menus cascading */ +#define UI_RETURN_OK 2 /* choice made */ +#define UI_RETURN_OUT 4 /* left the menu */ + + /* block->flag bits 12-15 are identical to but->flag bits */ + +/* block->font, for now: bold = medium+1 */ +#define UI_HELV 0 +#define UI_HELVB 1 + +/* panel controls */ +#define UI_PNL_TRANSP 1 +#define UI_PNL_SOLID 2 + +#define UI_PNL_CLOSE 32 +#define UI_PNL_STOW 64 +#define UI_PNL_TO_MOUSE 128 +#define UI_PNL_UNSTOW 256 +#define UI_PNL_SCALE 512 + +/* warning the first 4 flags are internal */ +/* but->flag */ +#define UI_TEXT_LEFT 16 +#define UI_ICON_LEFT 32 +#define UI_ICON_RIGHT 64 + /* control for button type block */ +#define UI_MAKE_TOP 128 +#define UI_MAKE_DOWN 256 +#define UI_MAKE_LEFT 512 +#define UI_MAKE_RIGHT 1024 + /* dont draw hilite on mouse over */ +#define UI_NO_HILITE 2048 + /* button align flag, for drawing groups together */ +#define UI_BUT_ALIGN (15<<12) +#define UI_BUT_ALIGN_TOP (1<<12) +#define UI_BUT_ALIGN_LEFT (1<<13) +#define UI_BUT_ALIGN_RIGHT (1<<14) +#define UI_BUT_ALIGN_DOWN (1<<15) + + +/* Button types, bits stored in 1 value... and a short even! +- bits 0-4: bitnr (0-31) +- bits 5-7: pointer type +- bit 8: for 'bit' +- bit 9-15: button type (now 6 bits, 64 types) +*/ + +#define CHA 32 +#define SHO 64 +#define INT 96 +#define FLO 128 +#define FUN 192 +#define BIT 256 + +#define BUTPOIN (128+64+32) + +#define BUT (1<<9) +#define ROW (2<<9) +#define TOG (3<<9) +#define SLI (4<<9) +#define NUM (5<<9) +#define TEX (6<<9) +#define TOG3 (7<<9) +#define TOGR (8<<9) +#define TOGN (9<<9) +#define LABEL (10<<9) +#define MENU (11<<9) +#define ICONROW (12<<9) +#define ICONTOG (13<<9) +#define NUMSLI (14<<9) +#define COL (15<<9) +#define IDPOIN (16<<9) +#define HSVSLI (17<<9) +#define SCROLL (18<<9) +#define BLOCK (19<<9) +#define BUTM (20<<9) +#define SEPR (21<<9) +#define LINK (22<<9) +#define INLINK (23<<9) +#define KEYEVT (24<<9) +#define ICONTEXTROW (25<<9) +#define HSVCUBE (26<<9) +#define PULLDOWN (27<<9) +#define ROUNDBOX (28<<9) +#define CHARTAB (29<<9) +#define BUT_COLORBAND (30<<9) +#define BUT_NORMAL (31<<9) +#define BUT_CURVE (32<<9) +#define BUT_TOGDUAL (33<<9) +#define ICONTOGN (34<<9) +#define FTPREVIEW (35<<9) +#define NUMABS (36<<9) +#define BUTTYPE (63<<9) + +/* Menu Block Handle */ +typedef struct uiMenuBlockHandle { + struct ARegion *region; + int butretval; + int blockretval; + + float retvalue; + float retvec[3]; +} uiMenuBlockHandle; + +typedef struct uiBut uiBut; +typedef struct uiBlock uiBlock; + +void uiEmboss(float x1, float y1, float x2, float y2, int sel); +void uiRoundBoxEmboss(float minx, float miny, float maxx, float maxy, float rad, int active); +void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad); +void uiSetRoundBox(int type); +void uiRoundRect(float minx, float miny, float maxx, float maxy, float rad); + +void uiDrawMenuBox(float minx, float miny, float maxx, float maxy, short flag); +void uiTextBoundsBlock(uiBlock *block, int addval); +void uiBoundsBlock(struct uiBlock *block, int addval); +void uiDrawBlock(struct uiBlock *block); +void uiGetMouse(int win, short *adr); +void uiComposeLinks(uiBlock *block); +void uiSetButLock(int val, char *lockstr); +uiBut *uiFindInlink(uiBlock *block, void *poin); +void uiClearButLock(void); +int uiDoBlocks(struct ListBase *lb, int event, int movemouse_quit); +void uiSetCurFont(uiBlock *block, int index); +void uiDefFont(unsigned int index, void *xl, void *large, void *medium, void *small); +void uiFreeBlock(uiBlock *block); +void uiFreeBlocks(struct ListBase *lb); +uiBlock *uiBeginBlock(struct wmWindow *window, struct ARegion *region, char *name, short dt, short font); +void uiEndBlock(uiBlock *block); +uiBlock *uiGetBlock(char *name, struct ARegion *ar); + +void uiBlockPickerButtons(struct uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval); + + +/* automatic aligning, horiz or verical */ +void uiBlockBeginAlign(uiBlock *block); +void uiBlockEndAlign(uiBlock *block); + +uiBut *uiDefBut(uiBlock *block, + int type, int retval, char *str, + short x1, short y1, + short x2, short y2, + void *poin, + float min, float max, + float a1, float a2, char *tip); +uiBut *uiDefButF(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefButBitF(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefButI(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefButBitI(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefButS(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefButBitS(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefButC(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefButBitC(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip); + +uiBut *uiDefIconBut(uiBlock *block, + int type, int retval, int icon, + short x1, short y1, + short x2, short y2, + void *poin, + float min, float max, + float a1, float a2, char *tip); +uiBut *uiDefIconButF(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconButBitF(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconButI(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconButBitI(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconButS(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconButBitS(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconButC(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconButBitC(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip); + +uiBut *uiDefIconTextBut(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip); + +uiBut *uiDefIconTextButF(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconTextButBitF(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconTextButI(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconTextButBitI(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconTextButS(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconTextButBitS(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconTextButC(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip); +uiBut *uiDefIconTextButBitC(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip); + +typedef void (*uiIDPoinFuncFP) (char *str, struct ID **idpp); +uiBut *uiDefIDPoinBut(struct uiBlock *block, uiIDPoinFuncFP func, short blocktype, int retval, char *str, + short x1, short y1, short x2, short y2, void *idpp, char *tip); + +typedef uiBlock* (*uiBlockFuncFP) (struct wmWindow *window, struct uiMenuBlockHandle *handle, void *arg1); +uiBut *uiDefBlockBut(uiBlock *block, uiBlockFuncFP func, void *func_arg1, char *str, short x1, short y1, short x2, short y2, char *tip); +uiBut *uiDefPulldownBut(uiBlock *block, uiBlockFuncFP func, void *func_arg1, char *str, short x1, short y1, short x2, short y2, char *tip); + +uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int icon, char *str, short x1, short y1, short x2, short y2, char *tip); +uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int retval, int icon, short x1, short y1, short x2, short y2, char *tip); + +void uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *spoin, char *tip); + +struct PointerRNA; +struct PropertyRNA; +uiBut *uiDefRNABut(uiBlock *block, int retval, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, short x1, short y1, short x2, short y2); +void uiButSetFunc3(uiBut *but, void (*func)(void *arg1, void *arg2, void *arg3), void *arg1, void *arg2, void *arg3); + +void uiAutoBlock(struct uiBlock *block, + float minx, float miny, + float sizex, float sizey, int flag); +void uiSetButLink(struct uiBut *but, + void **poin, + void ***ppoin, + short *tot, + int from, int to); + +int uiBlocksGetYMin (ListBase *lb); +int uiBlockGetCol (uiBlock *block); +void* uiBlockGetCurFont (uiBlock *block); + +void uiBlockSetCol (uiBlock *block, int col); +void uiBlockSetEmboss (uiBlock *block, int emboss); +void uiBlockSetDirection (uiBlock *block, int direction); +void uiBlockFlipOrder (uiBlock *block); +void uiBlockSetFlag (uiBlock *block, int flag); +void uiBlockSetXOfs (uiBlock *block, int xofs); + +int uiButGetRetVal (uiBut *but); + +void uiButSetFlag (uiBut *but, int flag); +void uiButClearFlag (uiBut *but, int flag); + +void uiBlockSetButmFunc (uiBlock *block, void (*butmfunc)(void *arg, int but_a2), void *arg); + +void uiBlockSetFunc (uiBlock *block, void (*func)(void *arg1, void *arg2), void *arg1, void *arg2); +void uiButSetFunc (uiBut *but, void (*func)(void *arg1, void *arg2), void *arg1, void *arg2); + +void uiButSetCompleteFunc(uiBut *but, void (*func)(char *str, void *arg), void *arg); + +void uiBlockSetDrawExtraFunc(uiBlock *block, void (*func)(struct ScrArea *sa, uiBlock *block)); + + +extern void pupmenu_set_active(int val); +extern uiMenuBlockHandle *pupmenu_col(struct bContext *C, char *instr, int mx, int my, int maxrow); +extern uiMenuBlockHandle *pupmenu(struct bContext *C, char *instr, int mx, int my); +extern void pupmenu_free(struct bContext *C, uiMenuBlockHandle *handle); + +extern void uiFreePanels(struct ListBase *lb); +extern void uiNewPanelTabbed(char *, char *); +extern int uiNewPanel(struct ScrArea *sa, struct uiBlock *block, char *panelname, char *tabname, int ofsx, int ofsy, int sizex, int sizey); + +extern void uiSetPanel_view2d(struct ScrArea *sa); +extern void uiMatchPanel_view2d(struct ScrArea *sa); + +extern void uiDrawBlocksPanels(struct ScrArea *sa, int re_align); +extern void uiNewPanelHeight(struct uiBlock *block, int sizey); +extern void uiNewPanelTitle(struct uiBlock *block, char *str); +extern void uiPanelPush(struct uiBlock *block); +extern void uiPanelPop(struct uiBlock *block); +extern uiBlock *uiFindOpenPanelBlockName(ListBase *lb, char *name); +extern int uiAlignPanelStep(struct ScrArea *sa, float fac); +extern void uiPanelControl(int); +extern void uiSetPanelHandler(int); + +extern void uiDrawBoxShadow(unsigned char alpha, float minx, float miny, float maxx, float maxy); +extern void *uiSetCurFont_ext(float aspect); + +typedef struct AutoComplete AutoComplete; + +AutoComplete *autocomplete_begin(char *startname, int maxlen); +void autocomplete_do_name(AutoComplete *autocpl, const char *name); +void autocomplete_end(AutoComplete *autocpl, char *autoname); + +void uiTestRegion(const struct bContext *C); /* XXX 2.50 temporary test */ + +void UI_keymap(struct wmWindowManager *wm); + +void UI_init(void); +void UI_init_userdef(void); +void UI_exit(void); + +#endif /* UI_INTERFACE_H */ + diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h new file mode 100644 index 00000000000..f30e5531f41 --- /dev/null +++ b/source/blender/editors/include/UI_resources.h @@ -0,0 +1,595 @@ +/** + * $Id: UI_resources.h 13057 2007-12-30 12:08:28Z aligorith $ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef UI_RESOURCES_H +#define UI_RESOURCES_H + +/* elubie: TODO: move the typedef for icons to UI_interface_icons.h */ +/* and add/replace include of UI_resources.h by UI_interface_icons.h */ +typedef enum { +#define BIFICONID_FIRST (ICON_VIEW3D) + ICON_VIEW3D, + ICON_IPO, + ICON_OOPS, + ICON_BUTS, + ICON_FILESEL, + ICON_IMAGE_COL, + ICON_INFO, + ICON_SEQUENCE, + ICON_TEXT, + ICON_IMASEL, + ICON_SOUND, + ICON_ACTION, + ICON_NLA, + ICON_SCRIPTWIN, + ICON_TIME, + ICON_NODE, + ICON_SPACE2, + ICON_SPACE3, + ICON_SPACE4, + ICON_TRIA_LEFT, + ICON_TRIA_UP, + ICON_FONTPREVIEW, + ICON_BLANK4, + ICON_BLANK5, + ICON_BLANK6, + + ICON_ORTHO, + ICON_PERSP, + ICON_CAMERA, + ICON_PARTICLES, + ICON_BBOX, + ICON_WIRE, + ICON_SOLID, + ICON_SMOOTH, + ICON_POTATO, + ICON_MARKER_HLT, + ICON_PMARKER_ACT, + ICON_PMARKER_SEL, + ICON_PMARKER, + ICON_VIEWZOOM, + ICON_SORTALPHA, + ICON_SORTTIME, + ICON_SORTSIZE, + ICON_LONGDISPLAY, + ICON_SHORTDISPLAY, + ICON_TRIA_DOWN, + ICON_TRIA_RIGHT, + ICON_BLANK7, + ICON_BLANK8, + ICON_BLANK9, + ICON_BLANK10, + + ICON_VIEW_AXIS_ALL, + ICON_VIEW_AXIS_NONE, + ICON_VIEW_AXIS_NONE2, + ICON_VIEW_AXIS_TOP, + ICON_VIEW_AXIS_FRONT, + ICON_VIEW_AXIS_SIDE, + ICON_POSE_DEHLT, + ICON_POSE_HLT, + ICON_BORDERMOVE, + ICON_MAYBE_ITS_A_LASSO, + ICON_BLANK1, /* ATTENTION, someone decided to use this throughout blender + and didn't care to neither rename it nor update the PNG */ + ICON_VERSE, + ICON_MOD_BOOLEAN, + ICON_ARMATURE, + ICON_PAUSE, + ICON_ALIGN, + ICON_REC, + ICON_PLAY, + ICON_FF, + ICON_REW, + ICON_PYTHON, + ICON_BLANK11, + ICON_BLANK12, + ICON_BLANK13, + ICON_BLANK14, + + + ICON_DOTSUP, + ICON_DOTSDOWN, + ICON_MENU_PANEL, + ICON_AXIS_SIDE, + ICON_AXIS_FRONT, + ICON_AXIS_TOP, + ICON_STICKY_UVS_LOC, + ICON_STICKY_UVS_DISABLE, + ICON_STICKY_UVS_VERT, + ICON_PREV_KEYFRAME, + ICON_NEXT_KEYFRAME, + ICON_ENVMAP, + ICON_TRANSP_HLT, + ICON_TRANSP_DEHLT, + ICON_CIRCLE_DEHLT, + ICON_CIRCLE_HLT, + ICON_TPAINT_DEHLT, + ICON_TPAINT_HLT, + ICON_WPAINT_DEHLT, + ICON_WPAINT_HLT, + ICON_MARKER, + ICON_BLANK15, + ICON_BLANK16, + ICON_BLANK17, + ICON_BLANK18, + + ICON_X, + ICON_GO_LEFT, + ICON_NO_GO_LEFT, + ICON_UNLOCKED, + ICON_LOCKED, + ICON_PARLIB, + ICON_DATALIB, + ICON_AUTO, + ICON_MATERIAL_DEHLT2, + ICON_RING, + ICON_GRID, + ICON_PROPEDIT, + ICON_KEEPRECT, + ICON_DESEL_CUBE_VERTS, + ICON_EDITMODE_DEHLT, + ICON_EDITMODE_HLT, + ICON_VPAINT_DEHLT, + ICON_VPAINT_HLT, + ICON_FACESEL_DEHLT, + ICON_FACESEL_HLT, + ICON_EDIT_DEHLT, + ICON_BOOKMARKS, + ICON_BLANK20, + ICON_BLANK21, + ICON_BLANK22, + + ICON_HELP, + ICON_ERROR, + ICON_FOLDER_DEHLT, + ICON_FOLDER_HLT, + ICON_BLUEIMAGE_DEHLT, + ICON_BLUEIMAGE_HLT, + ICON_BPIBFOLDER_DEHLT, + ICON_BPIBFOLDER_HLT, + ICON_BPIBFOLDER_ERR, + ICON_UGLY_GREEN_RING, + ICON_GHOST, + ICON_SORTBYEXT, + ICON_SCULPTMODE_HLT, + ICON_VERTEXSEL, + ICON_EDGESEL, + ICON_FACESEL, + ICON_PLUS, + ICON_BPIBFOLDER_X, + ICON_BPIBFOLDERGREY, + ICON_MAGNIFY, + ICON_INFO2, + ICON_BLANK23, + ICON_BLANK24, + ICON_BLANK25, + ICON_BLANK26, + + ICON_RIGHTARROW, + ICON_DOWNARROW_HLT, + ICON_ROUNDBEVELTHING, + ICON_FULLTEXTURE, + ICON_HOOK, + ICON_DOT, + ICON_WORLD_DEHLT, + ICON_CHECKBOX_DEHLT, + ICON_CHECKBOX_HLT, + ICON_LINK, + ICON_INLINK, + ICON_ZOOMIN, + ICON_ZOOMOUT, + ICON_PASTEDOWN, + ICON_COPYDOWN, + ICON_CONSTANT, + ICON_LINEAR, + ICON_CYCLIC, + ICON_KEY_DEHLT, + ICON_KEY_HLT, + ICON_GRID2, + ICON_BLANK27, + ICON_BLANK28, + ICON_BLANK29, + ICON_BLANK30, + + ICON_EYE, + ICON_LAMP, + ICON_MATERIAL, + ICON_TEXTURE, + ICON_ANIM, + ICON_WORLD, + ICON_SCENE, + ICON_EDIT, + ICON_GAME, + ICON_PAINT, + ICON_RADIO, + ICON_SCRIPT, + ICON_SPEAKER, + ICON_PASTEUP, + ICON_COPYUP, + ICON_PASTEFLIPUP, + ICON_PASTEFLIPDOWN, + ICON_CYCLICLINEAR, + ICON_PIN_DEHLT, + ICON_PIN_HLT, + ICON_LITTLEGRID, + ICON_BLANK31, + ICON_BLANK32, + ICON_BLANK33, + ICON_BLANK34, + + ICON_FULLSCREEN, + ICON_SPLITSCREEN, + ICON_RIGHTARROW_THIN, + ICON_DISCLOSURE_TRI_RIGHT, + ICON_DISCLOSURE_TRI_DOWN, + ICON_SCENE_SEPIA, + ICON_SCENE_DEHLT, + ICON_OBJECT, + ICON_MESH, + ICON_CURVE, + ICON_MBALL, + ICON_LATTICE, + ICON_LAMP_DEHLT, + ICON_MATERIAL_DEHLT, + ICON_TEXTURE_DEHLT, + ICON_IPO_DEHLT, + ICON_LIBRARY_DEHLT, + ICON_IMAGE_DEHLT, + ICON_EYEDROPPER, + ICON_WINDOW_WINDOW, + ICON_PANEL_CLOSE, + ICON_PHYSICS, + ICON_BLANK36, + ICON_BLANK37, + ICON_BLANK38, + + ICON_BLENDER, + ICON_PACKAGE, + ICON_UGLYPACKAGE, + ICON_MATPLANE, + ICON_MATSPHERE, + ICON_MATCUBE, + ICON_SCENE_HLT, + ICON_OBJECT_HLT, + ICON_MESH_HLT, + ICON_CURVE_HLT, + ICON_MBALL_HLT, + ICON_LATTICE_HLT, + ICON_LAMP_HLT, + ICON_MATERIAL_HLT, + ICON_TEXTURE_HLT, + ICON_IPO_HLT, + ICON_LIBRARY_HLT, + ICON_IMAGE_HLT, + ICON_CONSTRAINT, + ICON_CAMERA_DEHLT, + ICON_ARMATURE_DEHLT, + ICON_SNAP_GEAR, + ICON_SNAP_GEO, + ICON_BLANK41, + ICON_BLANK42, + + ICON_SMOOTHCURVE, + ICON_SPHERECURVE, + ICON_ROOTCURVE, + ICON_SHARPCURVE, + ICON_LINCURVE, + ICON_NOCURVE, + ICON_RNDCURVE, + ICON_PROP_OFF, + ICON_PROP_ON, + ICON_PROP_CON, + ICON_SYNTAX, + ICON_SYNTAX_OFF, + ICON_MONKEY, + ICON_HAIR, + ICON_VIEWMOVE, + ICON_HOME, + ICON_CLIPUV_DEHLT, + ICON_CLIPUV_HLT, + ICON_BLANK2, + ICON_BLANK3, + ICON_VPAINT_COL, + ICON_RESTRICT_SELECT_OFF, + ICON_RESTRICT_SELECT_ON, + ICON_MUTE_IPO_OFF, + ICON_MUTE_IPO_ON, + + ICON_MAN_TRANS, + ICON_MAN_ROT, + ICON_MAN_SCALE, + ICON_MANIPUL, + ICON_BLANK_47, + ICON_MODIFIER, + ICON_MOD_WAVE, + ICON_MOD_BUILD, + ICON_MOD_DECIM, + ICON_MOD_MIRROR, + ICON_MOD_SOFT, + ICON_MOD_SUBSURF, + ICON_SEQ_SEQUENCER, + ICON_SEQ_PREVIEW, + ICON_SEQ_LUMA_WAVEFORM, + ICON_SEQ_CHROMA_SCOPE, + ICON_ROTATE, + ICON_CURSOR, + ICON_ROTATECOLLECTION, + ICON_ROTATECENTER, + ICON_ROTACTIVE, + ICON_RESTRICT_VIEW_OFF, + ICON_RESTRICT_VIEW_ON, + ICON_RESTRICT_RENDER_OFF, + ICON_RESTRICT_RENDER_ON, + + VICON_VIEW3D, + VICON_EDIT, + VICON_EDITMODE_DEHLT, + VICON_EDITMODE_HLT, + VICON_DISCLOSURE_TRI_RIGHT, + VICON_DISCLOSURE_TRI_DOWN, + VICON_MOVE_UP, + VICON_MOVE_DOWN, + VICON_X + +#define BIFICONID_LAST (VICON_X) +#define BIFNICONIDS (BIFICONID_LAST-BIFICONID_FIRST + 1) +} BIFIconID; + +typedef enum { +#define BIFCOLORSHADE_FIRST (COLORSHADE_DARK) + COLORSHADE_DARK, + COLORSHADE_GREY, + COLORSHADE_MEDIUM, + COLORSHADE_HILITE, + COLORSHADE_LIGHT, + COLORSHADE_WHITE +#define BIFCOLORSHADE_LAST (COLORSHADE_WHITE) +#define BIFNCOLORSHADES (BIFCOLORSHADE_LAST-BIFCOLORSHADE_FIRST + 1) +} BIFColorShade; + +typedef enum { +#define BIFCOLORID_FIRST (BUTGREY) + BUTGREY = 0, + BUTGREEN, + BUTBLUE, + BUTSALMON, + MIDGREY, + BUTPURPLE, + BUTYELLOW, + REDALERT, + BUTRUST, + BUTWHITE, + BUTDBLUE, + BUTPINK, + BUTDPINK, + BUTMACTIVE, + + BUTIPO, + BUTAUDIO, + BUTCAMERA, + BUTRANDOM, + BUTEDITOBJECT, + BUTPROPERTY, + BUTSCENE, + BUTMOTION, + BUTMESSAGE, + BUTACTION, + BUTCD, + BUTGAME, + BUTVISIBILITY, + BUTYUCK, + BUTSEASICK, + BUTCHOKE, + BUTIMPERIAL, + + BUTTEXTCOLOR, + BUTTEXTPRESSED, + BUTSBACKGROUND, + + VIEWPORTBACKCOLOR, + VIEWPORTGRIDCOLOR, + VIEWPORTACTIVECOLOR, + VIEWPORTSELECTEDCOLOR, + VIEWPORTUNSELCOLOR, + + EDITVERTSEL, + EDITVERTUNSEL, + EDITEDGESEL, + EDITEDGEUNSEL + +#define BIFCOLORID_LAST (EDITEDGEUNSEL) +#define BIFNCOLORIDS (BIFCOLORID_LAST-BIFCOLORID_FIRST + 1) + +} BIFColorID; + +/* XXX WARNING: this is saved in file, so do not change order! */ +enum { + TH_AUTO, /* for buttons, to signal automatic color assignment */ + +// uibutton colors + TH_BUT_OUTLINE, + TH_BUT_NEUTRAL, + TH_BUT_ACTION, + TH_BUT_SETTING, + TH_BUT_SETTING1, + TH_BUT_SETTING2, + TH_BUT_NUM, + TH_BUT_TEXTFIELD, + TH_BUT_POPUP, + TH_BUT_TEXT, + TH_BUT_TEXT_HI, + TH_MENU_BACK, + TH_MENU_ITEM, + TH_MENU_HILITE, + TH_MENU_TEXT, + TH_MENU_TEXT_HI, + + TH_BUT_DRAWTYPE, + + TH_REDALERT, + TH_CUSTOM, + + TH_BUT_TEXTFIELD_HI, + TH_ICONFILE, + + TH_THEMEUI, +// common colors among spaces + + TH_BACK, + TH_TEXT, + TH_TEXT_HI, + TH_HEADER, + TH_HEADERDESEL, + TH_PANEL, + TH_SHADE1, + TH_SHADE2, + TH_HILITE, + + TH_GRID, + TH_WIRE, + TH_SELECT, + TH_ACTIVE, + TH_GROUP, + TH_GROUP_ACTIVE, + TH_TRANSFORM, + TH_VERTEX, + TH_VERTEX_SELECT, + TH_VERTEX_SIZE, + TH_EDGE, + TH_EDGE_SELECT, + TH_EDGE_SEAM, + TH_EDGE_FACESEL, + TH_FACE, + TH_FACE_SELECT, + TH_NORMAL, + TH_FACE_DOT, + TH_FACEDOT_SIZE, + TH_CFRAME, + + TH_SYNTAX_B, + TH_SYNTAX_V, + TH_SYNTAX_C, + TH_SYNTAX_L, + TH_SYNTAX_N, + + TH_BONE_SOLID, + TH_BONE_POSE, + + TH_STRIP, + TH_STRIP_SELECT, + + TH_LAMP, + + TH_NODE, + TH_NODE_IN_OUT, + TH_NODE_OPERATOR, + TH_NODE_CONVERTOR, + TH_NODE_GROUP, + + TH_SEQ_MOVIE, + TH_SEQ_IMAGE, + TH_SEQ_SCENE, + TH_SEQ_AUDIO, + TH_SEQ_EFFECT, + TH_SEQ_PLUGIN, + TH_SEQ_TRANSITION, + TH_SEQ_META, + + TH_EDGE_SHARP, + TH_EDITMESH_ACTIVE, +}; +/* XXX WARNING: previous is saved in file, so do not change order! */ + +/* theme drawtypes */ +#define TH_MINIMAL 0 +#define TH_SHADED 1 +#define TH_ROUNDED 2 +#define TH_OLDSKOOL 3 + +/* specific defines per space should have higher define values */ + +struct bTheme; + +// THE CODERS API FOR THEMES: + +// sets the color +void UI_ThemeColor(int colorid); + +// sets the color plus alpha +void UI_ThemeColor4(int colorid); + +// sets color plus offset for shade +void UI_ThemeColorShade(int colorid, int offset); + +// sets color plus offset for alpha +void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset); + +// sets color, which is blend between two theme colors +void UI_ThemeColorBlend(int colorid1, int colorid2, float fac); +// same, with shade offset +void UI_ThemeColorBlendShade(int colorid1, int colorid2, float fac, int offset); + +// returns one value, not scaled +float UI_GetThemeValuef(int colorid); +int UI_GetThemeValue(int colorid); + +// get three color values, scaled to 0.0-1.0 range +void UI_GetThemeColor3fv(int colorid, float *col); + +// get the 3 or 4 byte values +void UI_GetThemeColor3ubv(int colorid, char *col); +void UI_GetThemeColor4ubv(int colorid, char *col); + +// get a theme color from specified space type +void UI_GetThemeColorType4ubv(int colorid, int spacetype, char *col); + +// blends and shades between two color pointers +void UI_ColorPtrBlendShade3ubv(char *cp1, char *cp2, float fac, int offset); + +// get a 3 byte color, blended and shaded between two other char color pointers +void UI_GetColorPtrBlendShade3ubv(char *cp1, char *cp2, char *col, float fac, int offset); + + +struct ScrArea; + +// internal (blender) usage only, for init and set active +void UI_SetTheme(struct ScrArea *sa); +void ui_theme_init_userdef (void); +void ui_resources_init (void); +void ui_resources_free (void); + +/* only for buttons in theme editor! */ +char *UI_ThemeGetColorPtr(struct bTheme *btheme, int spacetype, int colorid); +char *UI_ThemeColorsPup(int spacetype); + +#endif /* UI_ICONS_H */ diff --git a/source/blender/editors/include/UI_text.h b/source/blender/editors/include/UI_text.h new file mode 100644 index 00000000000..03a51f5ee49 --- /dev/null +++ b/source/blender/editors/include/UI_text.h @@ -0,0 +1,67 @@ +/** + * $Id$ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 ***** + */ + +#ifndef UI_TEXT_H +#define UI_TEXT_H + +struct BMF_Font; + +int read_languagefile(void); /* usiblender.c */ +void free_languagemenu(void); /* usiblender.c */ + +void set_interface_font(char *str); /* headerbuttons.c */ +void start_interface_font(void); /* headerbuttons.c */ +void lang_setlanguage(void); /* usiblender.c */ + +char *language_pup(void); +char *fontsize_pup(void); + +int UI_DrawString(struct BMF_Font* font, char *str, int translate); +float UI_GetStringWidth(struct BMF_Font* font, char *str, int translate); +void UI_GetBoundingBox(struct BMF_Font* font, char* str, int translate, rctf* bbox); + +void UI_set_international(int international); +int UI_get_international(void); + +void UI_RasterPos(float x, float y); +void UI_SetScale(float aspect); +void ui_text_init_userdef(void); + +struct LANGMenuEntry { + struct LANGMenuEntry *next; + char *line; + char *language; + char *code; + int id; +}; + +struct LANGMenuEntry *find_language(short langid); + +#endif /* UI_TEXT_H */ + diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h new file mode 100644 index 00000000000..481d96952e9 --- /dev/null +++ b/source/blender/editors/include/UI_view2d.h @@ -0,0 +1,69 @@ +/** + * $Id$ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef UI_VIEW2D_H +#define UI_VIEW2D_H + +/* start of a generic 2d view with should allow drawing grids, + * panning, zooming, scrolling, .. */ + +#define V2D_UNIT_SECONDS 0 +#define V2D_UNIT_FRAMES 1 + +#define V2D_GRID_CLAMP 0 +#define V2D_GRID_NOCLAMP 1 + +#define V2D_IS_CLIPPED 12000 + +#define V2D_HORIZONTAL_LINES 1 +#define V2D_VERTICAL_LINES 2 +#define V2D_HORIZONTAL_AXIS 4 +#define V2D_VERTICAL_AXIS 8 + +struct View2D; +struct View2DGrid; +struct bContext; + +typedef struct View2DGrid View2DGrid; + +/* setup */ +void UI_view2d_ortho(const struct bContext *C, struct View2D *v2d); +void UI_view2d_update_size(struct View2D *v2d, int winx, int winy); + +/* grid drawing */ +View2DGrid *UI_view2d_calc_grid(const struct bContext *C, struct View2D *v2d, int unit, int type, int winx, int winy); +void UI_view2d_draw_grid(const struct bContext *C, struct View2D *v2d, View2DGrid *grid, int flag); +void UI_view2d_free_grid(View2DGrid *grid); + +/* coordinate conversion */ +void UI_view2d_region_to_view(struct View2D *v2d, short x, short y, float *viewx, float *viewy); +void UI_view2d_view_to_region(struct View2D *v2d, float x, float y, short *regionx, short *regiony); +void UI_view2d_to_region_no_clip(struct View2D *v2d, float x, float y, short *regionx, short *region_y); + +#endif /* UI_VIEW2D_H */ + diff --git a/source/blender/editors/interface/Makefile b/source/blender/editors/interface/Makefile index d029ef88851..39bb651a616 100644 --- a/source/blender/editors/interface/Makefile +++ b/source/blender/editors/interface/Makefile @@ -45,7 +45,9 @@ CPPFLAGS += -I../../blenkernel CPPFLAGS += -I../../blenloader CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../makesdna +CPPFLAGS += -I../../makesrna CPPFLAGS += -I../../imbuf +CPPFLAGS += -I../../ftfont # own include diff --git a/source/blender/editors/interface/SConscript b/source/blender/editors/interface/SConscript index 6602bba014f..0586d07d945 100644 --- a/source/blender/editors/interface/SConscript +++ b/source/blender/editors/interface/SConscript @@ -4,6 +4,6 @@ Import ('env') sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' -incs += ' ../../windowmanager #/intern/guardedalloc' +incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc #intern/bmfont' env.BlenderLib ( 'bf_editors_interface', sources, Split(incs), [], libtype=['core','intern'], priority=[40, 45] ) diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c new file mode 100644 index 00000000000..7fa9615f64c --- /dev/null +++ b/source/blender/editors/interface/interface.c @@ -0,0 +1,2573 @@ +/** + * $Id: interface.c 16882 2008-10-02 12:29:45Z ton $ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 ***** + */ + +#include +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_ID.h" +#include "DNA_listBase.h" +#include "DNA_screen_types.h" +#include "DNA_texture_types.h" +#include "DNA_userdef_types.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_dynstr.h" + +#include "BKE_global.h" +#include "BKE_screen.h" +#include "BKE_texture.h" +#include "BKE_utildefines.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "UI_interface.h" +#include "UI_text.h" + +#include "BMF_Api.h" +#ifdef INTERNATIONAL +#include "FTF_Api.h" +#endif + +#include "ED_screen.h" + +#include "WM_api.h" +#include "WM_types.h" +#include "wm_subwindow.h" +#include "wm_window.h" + +#include "RNA_access.h" +#include "RNA_types.h" + +#include "interface.h" + +/* + * a full doc with API notes can be found in bf-blender/blender/doc/interface_API.txt + * + * uiBlahBlah() external function + * ui_blah_blah() internal function + */ + +static void ui_free_but(uiBut *but); + +/* ************ GLOBALS ************* */ + +static uiFont UIfont[UI_ARRAY]; // no init needed + +/* ************* translation ************** */ + +/* XXX 2.50 missing from context */ +int ui_translate_buttons() +{ + return (U.transopts & USER_TR_BUTTONS); +} + +int ui_translate_menus() +{ + return (U.transopts & USER_TR_MENUS); +} + +int ui_translate_tooltips() +{ + return (U.transopts & USER_TR_TOOLTIPS); +} + +/* ************* window matrix ************** */ + +void ui_block_to_window_fl(const ARegion *ar, uiBlock *block, float *x, float *y) +{ + float gx, gy; + int sx, sy, getsizex, getsizey; + + getsizex= ar->winrct.xmax-ar->winrct.xmin; + getsizey= ar->winrct.ymax-ar->winrct.ymin; + sx= ar->winrct.xmin; + sy= ar->winrct.ymin; + + gx= *x; + gy= *y; + *x= ((float)sx) + ((float)getsizex)*(0.5+ 0.5*(gx*block->winmat[0][0]+ gy*block->winmat[1][0]+ block->winmat[3][0])); + *y= ((float)sy) + ((float)getsizey)*(0.5+ 0.5*(gx*block->winmat[0][1]+ gy*block->winmat[1][1]+ block->winmat[3][1])); +} + +void ui_block_to_window(const ARegion *ar, uiBlock *block, int *x, int *y) +{ + float fx, fy; + + fx= *x; + fy= *y; + + ui_block_to_window_fl(ar, block, &fx, &fy); + + *x= (int)(fx+0.5f); + *y= (int)(fy+0.5f); +} + +void ui_block_to_window_rct(const ARegion *ar, uiBlock *block, rctf *graph, rcti *winr) +{ + rctf tmpr; + + tmpr= *graph; + ui_block_to_window_fl(ar, block, &tmpr.xmin, &tmpr.ymin); + ui_block_to_window_fl(ar, block, &tmpr.xmax, &tmpr.ymax); + + winr->xmin= tmpr.xmin; + winr->ymin= tmpr.ymin; + winr->xmax= tmpr.xmax; + winr->ymax= tmpr.ymax; +} + +void ui_window_to_block_fl(const ARegion *ar, uiBlock *block, float *x, float *y) /* for mouse cursor */ +{ + float a, b, c, d, e, f, px, py; + int sx, sy, getsizex, getsizey; + + getsizex= ar->winrct.xmax-ar->winrct.xmin; + getsizey= ar->winrct.ymax-ar->winrct.ymin; + sx= ar->winrct.xmin; + sy= ar->winrct.ymin; + + a= .5*((float)getsizex)*block->winmat[0][0]; + b= .5*((float)getsizex)*block->winmat[1][0]; + c= .5*((float)getsizex)*(1.0+block->winmat[3][0]); + + d= .5*((float)getsizey)*block->winmat[0][1]; + e= .5*((float)getsizey)*block->winmat[1][1]; + f= .5*((float)getsizey)*(1.0+block->winmat[3][1]); + + px= *x - sx; + py= *y - sy; + + *y= (a*(py-f) + d*(c-px))/(a*e-d*b); + *x= (px- b*(*y)- c)/a; +} + +void ui_window_to_block(const ARegion *ar, uiBlock *block, int *x, int *y) +{ + float fx, fy; + + fx= *x; + fy= *y; + + ui_window_to_block_fl(ar, block, &fx, &fy); + + *x= (int)(fx+0.5f); + *y= (int)(fy+0.5f); +} + +/* ******************* block calc ************************* */ + +/* only for pulldowns */ +void uiTextBoundsBlock(uiBlock *block, int addval) +{ + uiBut *bt; + int i = 0, j, x1addval= 0, nextcol; + + bt= block->buttons.first; + while(bt) { + if(bt->type!=SEPR) { + int transopts= ui_translate_buttons(); + if(bt->type==TEX || bt->type==IDPOIN) transopts= 0; + j= UI_GetStringWidth(bt->font, bt->drawstr, transopts); + + if(j > i) i = j; + } + bt= bt->next; + } + + /* cope with multi collumns */ + bt= block->buttons.first; + while(bt) { + if(bt->next && bt->x1 < bt->next->x1) + nextcol= 1; + else nextcol= 0; + + bt->x1 = x1addval; + bt->x2 = bt->x1 + i + addval; + + ui_check_but(bt); // clips text again + + if(nextcol) + x1addval+= i + addval; + + bt= bt->next; + } +} + +void uiBoundsBlock(uiBlock *block, int addval) +{ + uiBut *bt; + int xof; + + if(block==NULL) + return; + + if(block->buttons.first==NULL) { + if(block->panel) { + block->minx= 0.0; block->maxx= block->panel->sizex; + block->miny= 0.0; block->maxy= block->panel->sizey; + } + } + else { + + block->minx= block->miny= 10000; + block->maxx= block->maxy= -10000; + + bt= block->buttons.first; + while(bt) { + if(bt->x1 < block->minx) block->minx= bt->x1; + if(bt->y1 < block->miny) block->miny= bt->y1; + + if(bt->x2 > block->maxx) block->maxx= bt->x2; + if(bt->y2 > block->maxy) block->maxy= bt->y2; + + bt= bt->next; + } + + block->minx -= addval; + block->miny -= addval; + block->maxx += addval; + block->maxy += addval; + } + + /* hardcoded exception... but that one is annoying with larger safety */ + bt= block->buttons.first; + if(bt && strncmp(bt->str, "ERROR", 5)==0) xof= 10; + else xof= 40; + + block->safety.xmin= block->minx-xof; + block->safety.ymin= block->miny-xof; + block->safety.xmax= block->maxx+xof; + block->safety.ymax= block->maxy+xof; +} + +void uiBlockTranslate(uiBlock *block, int x, int y) +{ + uiBut *bt; + + for(bt= block->buttons.first; bt; bt=bt->next) { + bt->x1 += x; + bt->y1 += y; + bt->x2 += x; + bt->y2 += y; + } + + block->minx += x; + block->miny += y; + block->maxx += x; + block->maxy += y; +} + +void uiBlockOrigin(uiBlock *block) +{ + uiBut *bt; + int minx= 10000, miny= 10000; + + for(bt= block->buttons.first; bt; bt=bt->next) { + if(bt->x1 < minx) minx= bt->x1; + if(bt->y1 < miny) miny= bt->y1; + } + + uiBlockTranslate(block, -minx, -miny); +} + +void ui_autofill(uiBlock *block) +{ + uiBut *but; + float *maxw, *maxh, startx = 0, starty, height = 0; + float totmaxh; + int rows=0, /* cols=0, */ i, lasti; + + /* first count rows */ + but= block->buttons.last; + rows= but->x1+1; + + /* calculate max width / height for each row */ + maxw= MEM_callocN(sizeof(float)*rows, "maxw"); + maxh= MEM_callocN(sizeof(float)*rows, "maxh"); + but= block->buttons.first; + while(but) { + i= but->x1; + if( maxh[i] < but->y2) maxh[i]= but->y2; + maxw[i] += but->x2; + but= but->next; + } + + totmaxh= 0.0; + for(i=0; imaxy; + but= block->buttons.first; + lasti= -1; + while(but) { + // signal for aligning code + but->flag |= UI_BUT_ALIGN_DOWN; + + i= but->x1; + + if(i!=lasti) { + startx= block->minx; + height= (maxh[i]*(block->maxy-block->miny))/totmaxh; + starty-= height; + lasti= i; + } + + but->y1= starty+but->aspect; + but->y2= but->y1+height-but->aspect; + + but->x2= (but->x2*(block->maxx-block->minx))/maxw[i]; + but->x1= startx+but->aspect; + + startx+= but->x2; + but->x2+= but->x1-but->aspect; + + ui_check_but(but); + + but= but->next; + } + + uiBlockEndAlign(block); + + MEM_freeN(maxw); MEM_freeN(maxh); + block->autofill= 0; +} + +/* ************** LINK LINE DRAWING ************* */ + +/* link line drawing is not part of buttons or theme.. so we stick with it here */ + +static void ui_draw_linkline(uiBut *but, uiLinkLine *line) +{ + float vec1[2], vec2[2]; + + if(line->from==NULL || line->to==NULL) return; + + vec1[0]= (line->from->x1+line->from->x2)/2.0; + vec1[1]= (line->from->y1+line->from->y2)/2.0; + vec2[0]= (line->to->x1+line->to->x2)/2.0; + vec2[1]= (line->to->y1+line->to->y2)/2.0; + + if(line->flag & UI_SELECT) UI_ThemeColorShade(but->themecol, 80); + else glColor3ub(0,0,0); + fdrawline(vec1[0], vec1[1], vec2[0], vec2[1]); +} + +static void ui_draw_links(uiBlock *block) +{ + uiBut *but; + uiLinkLine *line; + + but= block->buttons.first; + while(but) { + if(but->type==LINK && but->link) { + line= but->link->lines.first; + while(line) { + ui_draw_linkline(but, line); + line= line->next; + } + } + but= but->next; + } +} + +/* ************** BLOCK ENDING FUNCTION ************* */ + +static int ui_but_equals_old(uiBut *but, uiBut *oldbut) +{ + /* various properties are being compared here, hopfully sufficient + * to catch all cases, but it is simple to add more checks later */ + if(but->retval != oldbut->retval) return 0; + if(but->poin != oldbut->poin || but->pointype != oldbut->pointype) return 0; + if(but->rnapoin.data != oldbut->rnapoin.data) return 0; + if(but->rnaprop != oldbut->rnaprop) + if(but->rnaindex != oldbut->rnaindex) return 0; + if(but->func != oldbut->func) return 0; + if(but->func_arg1 != oldbut->func_arg1) return 0; + if(but->func_arg2 != oldbut->func_arg2) return 0; + if(but->func_arg3 != oldbut->func_arg3) return 0; + + return 1; +} + +static int ui_but_update_from_old_block(uiBlock *block, uiBut *but) +{ + uiBlock *oldblock; + uiBut *oldbut; + int found= 0; + + oldblock= block->oldblock; + if(!oldblock) + return found; + + for(oldbut=oldblock->buttons.first; oldbut; oldbut=oldbut->next) { + if(ui_but_equals_old(oldbut, but)) { + if(oldbut->activate) { + but->flag= oldbut->flag; + but->activate= oldbut->activate; + but->pos= oldbut->pos; + but->editstr= oldbut->editstr; + but->editval= oldbut->editval; + but->editvec= oldbut->editvec; + but->editcoba= oldbut->editcoba; + but->editcumap= oldbut->editcumap; + but->selsta= oldbut->selsta; + but->selend= oldbut->selend; + found= 1; + } + + /* ensures one button can get activated, and in case the buttons + * draw are the same this gives O(1) lookup for each button */ + BLI_remlink(&oldblock->buttons, oldbut); + ui_free_but(oldbut); + + break; + } + } + + return found; +} + +void uiEndBlock(uiBlock *block) +{ + uiBut *but; + + /* inherit flags from 'old' buttons that was drawn here previous, based + * on matching buttons, we need this to make button event handling non + * blocking, while still alowing buttons to be remade each redraw as it + * is expected by blender code */ + for(but=block->buttons.first; but; but=but->next) + if(ui_but_update_from_old_block(block, but)) + ui_check_but(but); + + if(block->oldblock) { + block->auto_open= block->oldblock->auto_open; + block->auto_open_last= block->oldblock->auto_open_last; + + uiFreeBlock(block->oldblock); + block->oldblock= NULL; + } + + /* handle pending stuff */ + if(block->autofill) ui_autofill(block); + if(block->minx==0.0 && block->maxx==0.0) uiBoundsBlock(block, 0); + if(block->flag & UI_BUT_ALIGN) uiBlockEndAlign(block); +} + +/* ************** BLOCK DRAWING FUNCTION ************* */ + +void uiDrawBlock(uiBlock *block) +{ + uiBut *but; + + /* we set this only once */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + /* XXX 2.50 no panels yet */ + //uiPanelPush(block); // panel matrix + + if(block->flag & UI_BLOCK_LOOP) { + uiDrawMenuBox(block->minx, block->miny, block->maxx, block->maxy, block->flag); + } + else { + /* XXX 2.50 no panels yet */ + //if(block->panel) ui_draw_panel(block); + } + + /* XXX 2.50 need context here? */ + //if(block->drawextra) block->drawextra(curarea, block); + + for (but= block->buttons.first; but; but= but->next) + ui_draw_but(but); + + ui_draw_links(block); + + /* XXX 2.50 no panels yet */ + //uiPanelPop(block); // matrix restored +} + +/* ************* EVENTS ************* */ + +static void ui_is_but_sel(uiBut *but) +{ + double value; + int lvalue; + short push=0, true=1; + + value= ui_get_but_val(but); + + if( but->type==TOGN || but->type==ICONTOGN) true= 0; + + if( but->bit ) { + lvalue= (int)value; + if( BTST(lvalue, (but->bitnr)) ) push= true; + else push= !true; + } + else { + switch(but->type) { + case BUT: + push= 2; + break; + case KEYEVT: + if (value==-1) push= 1; + break; + case TOG: + case TOGR: + case TOG3: + case BUT_TOGDUAL: + case ICONTOG: + if(value!=but->min) push= 1; + break; + case ICONTOGN: + case TOGN: + if(value==0.0) push= 1; + break; + case ROW: + if(value == but->max) push= 1; + break; + case COL: + push= 1; + break; + default: + push= 2; + break; + } + } + + if(push==2); + else if(push==1) but->flag |= UI_SELECT; + else but->flag &= ~UI_SELECT; +} + +/* XXX 2.50 no links supported yet */ + +#if 0 +static uiBut *ui_get_valid_link_button(uiBlock *block, uiBut *but, short *mval) +{ + uiBut *bt; + + /* find button to link to */ + for (bt= block->buttons.first; bt; bt= bt->next) + if(bt!=but && uibut_contains_pt(bt, mval)) + break; + + if (bt) { + if (but->type==LINK && bt->type==INLINK) { + if( but->link->tocode == (int)bt->min ) { + return bt; + } + } + else if(but->type==INLINK && bt->type==LINK) { + if( bt->link->tocode == (int)but->min ) { + return bt; + } + } + } + + return NULL; +} + +static int ui_is_a_link(uiBut *from, uiBut *to) +{ + uiLinkLine *line; + uiLink *link; + + link= from->link; + if(link) { + line= link->lines.first; + while(line) { + if(line->from==from && line->to==to) return 1; + line= line->next; + } + } + return 0; +} + +static uiBut *ui_find_inlink(uiBlock *block, void *poin) +{ + uiBut *but; + + but= block->buttons.first; + while(but) { + if(but->type==INLINK) { + if(but->poin == poin) return but; + } + but= but->next; + } + return NULL; +} + +static void ui_add_link_line(ListBase *listb, uiBut *but, uiBut *bt) +{ + uiLinkLine *line; + + line= MEM_callocN(sizeof(uiLinkLine), "linkline"); + BLI_addtail(listb, line); + line->from= but; + line->to= bt; +} + +uiBut *uiFindInlink(uiBlock *block, void *poin) +{ + return ui_find_inlink(block, poin); +} + +void uiComposeLinks(uiBlock *block) +{ + uiBut *but, *bt; + uiLink *link; + void ***ppoin; + int a; + + but= block->buttons.first; + while(but) { + if(but->type==LINK) { + link= but->link; + + /* for all pointers in the array */ + if(link) { + if(link->ppoin) { + ppoin= link->ppoin; + for(a=0; a < *(link->totlink); a++) { + bt= ui_find_inlink(block, (*ppoin)[a] ); + if(bt) { + ui_add_link_line(&link->lines, but, bt); + } + } + } + else if(link->poin) { + bt= ui_find_inlink(block, *(link->poin) ); + if(bt) { + ui_add_link_line(&link->lines, but, bt); + } + } + } + } + but= but->next; + } +} + +static void ui_add_link(uiBut *from, uiBut *to) +{ + /* in 'from' we have to add a link to 'to' */ + uiLink *link; + void **oldppoin; + int a; + + if(ui_is_a_link(from, to)) { + printf("already exists\n"); + return; + } + + link= from->link; + + /* are there more pointers allowed? */ + if(link->ppoin) { + oldppoin= *(link->ppoin); + + (*(link->totlink))++; + *(link->ppoin)= MEM_callocN( *(link->totlink)*sizeof(void *), "new link"); + + for(a=0; a< (*(link->totlink))-1; a++) { + (*(link->ppoin))[a]= oldppoin[a]; + } + (*(link->ppoin))[a]= to->poin; + + if(oldppoin) MEM_freeN(oldppoin); + } + else { + *(link->poin)= to->poin; + } + +} + +static int ui_do_but_LINK(uiBlock *block, uiBut *but) +{ + /* + * This button only visualizes, the dobutton mode + * can add a new link, but then the whole system + * should be redrawn/initialized. + * + */ + uiBut *bt=0, *bto=NULL; + short sval[2], mval[2], mvalo[2], first= 1; + + uiGetMouse(curarea->win, sval); + mvalo[0]= sval[0]; + mvalo[1]= sval[1]; + + while (get_mbut() & L_MOUSE) { + uiGetMouse(curarea->win, mval); + + if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || first) { + /* clear completely, because of drawbuttons */ + bt= ui_get_valid_link_button(block, but, mval); + if(bt) { + bt->flag |= UI_ACTIVE; + ui_draw_but(bt); + } + if(bto && bto!=bt) { + bto->flag &= ~UI_ACTIVE; + ui_draw_but(bto); + } + bto= bt; + + if (!first) { + glutil_draw_front_xor_line(sval[0], sval[1], mvalo[0], mvalo[1]); + } + glutil_draw_front_xor_line(sval[0], sval[1], mval[0], mval[1]); + + mvalo[0]= mval[0]; + mvalo[1]= mval[1]; + + first= 0; + } + else UI_wait_for_statechange(); + } + + if (!first) { + glutil_draw_front_xor_line(sval[0], sval[1], mvalo[0], mvalo[1]); + } + + if(bt) { + if(but->type==LINK) ui_add_link(but, bt); + else ui_add_link(bt, but); + + scrarea_queue_winredraw(curarea); + } + + return 0; +} +#endif + +/* ************************************************ */ + +void uiBlockSetButLock(uiBlock *block, int val, char *lockstr) +{ + block->lock |= val; + if(val) block->lockstr= lockstr; +} + +void uiBlockClearButLock(uiBlock *block) +{ + block->lock= 0; + block->lockstr= NULL; +} + +/* *************************************************************** */ + +/* XXX 2.50 no button editing */ + +#if 0 +static void setup_file(uiBlock *block) +{ + uiBut *but; + FILE *fp; + + fp= fopen("butsetup","w"); + if(fp==NULL); + else { + but= block->buttons.first; + while(but) { + ui_check_but(but); + fprintf(fp,"%d,%d,%d,%d %s %s\n", (int)but->x1, (int)but->y1, (int)( but->x2-but->x1), (int)(but->y2-but->y1), but->str, but->tip); + but= but->next; + } + fclose(fp); + } +} + + +static void edit_but(uiBlock *block, uiBut *but, uiEvent *uevent) +{ + short dx, dy, mval[2], mvalo[2], didit=0; + + getmouseco_sc(mvalo); + while(TRUE) { + if( !(get_mbut() & L_MOUSE) ) break; + + getmouseco_sc(mval); + dx= (mval[0]-mvalo[0]); + dy= (mval[1]-mvalo[1]); + + if(dx!=0 || dy!=0) { + mvalo[0]= mval[0]; + mvalo[1]= mval[1]; + + cpack(0xc0c0c0); + glRectf(but->x1-2, but->y1-2, but->x2+2, but->y2+2); + + if((uevent->qual & LR_SHIFTKEY)==0) { + but->x1 += dx; + but->y1 += dy; + } + but->x2 += dx; + but->y2 += dy; + + ui_draw_but(but); + ui_block_flush_back(but->block); + didit= 1; + + } + /* idle for this poor code */ + else PIL_sleep_ms(30); + } + if(didit) setup_file(block); +} +#endif + +/* XXX 2.50 no links supported yet */ +#if 0 +static void ui_delete_active_linkline(uiBlock *block) +{ + uiBut *but; + uiLink *link; + uiLinkLine *line, *nline; + int a, b; + + but= block->buttons.first; + while(but) { + if(but->type==LINK && but->link) { + line= but->link->lines.first; + while(line) { + + nline= line->next; + + if(line->flag & UI_SELECT) { + BLI_remlink(&but->link->lines, line); + + link= line->from->link; + + /* are there more pointers allowed? */ + if(link->ppoin) { + + if(*(link->totlink)==1) { + *(link->totlink)= 0; + MEM_freeN(*(link->ppoin)); + *(link->ppoin)= NULL; + } + else { + b= 0; + for(a=0; a< (*(link->totlink)); a++) { + + if( (*(link->ppoin))[a] != line->to->poin ) { + (*(link->ppoin))[b]= (*(link->ppoin))[a]; + b++; + } + } + (*(link->totlink))--; + } + } + else { + *(link->poin)= NULL; + } + + MEM_freeN(line); + } + line= nline; + } + } + but= but->next; + } + + /* temporal! these buttons can be everywhere... */ + allqueue(REDRAWBUTSLOGIC, 0); +} + +static void ui_do_active_linklines(uiBlock *block, short *mval) +{ + uiBut *but; + uiLinkLine *line, *act= NULL; + float mindist= 12.0, fac, v1[2], v2[2], v3[3]; + int foundone= 0; + + if(mval) { + v1[0]= mval[0]; + v1[1]= mval[1]; + + /* find a line close to the mouse */ + but= block->buttons.first; + while(but) { + if(but->type==LINK && but->link) { + foundone= 1; + line= but->link->lines.first; + while(line) { + v2[0]= line->from->x2; + v2[1]= (line->from->y1+line->from->y2)/2.0; + v3[0]= line->to->x1; + v3[1]= (line->to->y1+line->to->y2)/2.0; + + fac= PdistVL2Dfl(v1, v2, v3); + if(fac < mindist) { + mindist= fac; + act= line; + } + line= line->next; + } + } + but= but->next; + } + } + + /* check for a 'found one' to prevent going to 'frontbuffer' mode. + this slows done gfx quite some, and at OSX the 'finish' forces a swapbuffer */ + if(foundone) { + glDrawBuffer(GL_FRONT); + + /* draw */ + but= block->buttons.first; + while(but) { + if(but->type==LINK && but->link) { + line= but->link->lines.first; + while(line) { + if(line==act) { + if((line->flag & UI_SELECT)==0) { + line->flag |= UI_SELECT; + ui_draw_linkline(but, line); + } + } + else if(line->flag & UI_SELECT) { + line->flag &= ~UI_SELECT; + ui_draw_linkline(but, line); + } + line= line->next; + } + } + but= but->next; + } + bglFlush(); + glDrawBuffer(GL_BACK); + } +} +#endif + +/* ******************************************************* */ + +/* XXX 2.50 no screendump supported yet */ + +#if 0 +/* nasty but safe way to store screendump rect */ +static int scr_x=0, scr_y=0, scr_sizex=0, scr_sizey=0; + +static void ui_set_screendump_bbox(uiBlock *block) +{ + if(block) { + scr_x= block->minx; + scr_y= block->miny; + scr_sizex= block->maxx - block->minx; + scr_sizey= block->maxy - block->miny; + } + else { + scr_sizex= scr_sizey= 0; + } +} + +/* used for making screenshots for menus, called in screendump.c */ +int uiIsMenu(int *x, int *y, int *sizex, int *sizey) +{ + if(scr_sizex!=0 && scr_sizey!=0) { + *x= scr_x; + *y= scr_y; + *sizex= scr_sizex; + *sizey= scr_sizey; + return 1; + } + + return 0; +} +#endif + +/* *********************** data get/set *********************** + * this either works with the pointed to data, or can work with + * an edit override pointer while dragging for example */ + +/* for buttons pointing to color for example */ +void ui_get_but_vectorf(uiBut *but, float *vec) +{ + void *poin; + int pointype; + + poin= (but->editvec)? (void*)but->editvec: but->poin; + pointype= (but->editvec)? FLO: but->pointype; + + if(!but->editvec && pointype == CHA) { + char *cp= (char *)poin; + vec[0]= ((float)cp[0])/255.0; + vec[1]= ((float)cp[1])/255.0; + vec[2]= ((float)cp[2])/255.0; + } + else if(pointype == FLO) { + float *fp= (float *)poin; + VECCOPY(vec, fp); + } +} + +/* for buttons pointing to color for example */ +void ui_set_but_vectorf(uiBut *but, float *vec) +{ + void *poin; + int pointype; + + poin= (but->editvec)? (void*)but->editvec: but->poin; + pointype= (but->editvec)? FLO: but->pointype; + + if(!but->editvec && but->pointype == CHA) { + char *cp= (char *)poin; + cp[0]= (char)(0.5 +vec[0]*255.0); + cp[1]= (char)(0.5 +vec[1]*255.0); + cp[2]= (char)(0.5 +vec[2]*255.0); + } + else if( but->pointype == FLO ) { + float *fp= (float *)poin; + VECCOPY(fp, vec); + } +} + +int ui_is_but_float(uiBut *but) +{ + if(but->pointype==FLO && but->poin) + return 1; + + if(but->rnaprop && but->rnaprop->type==PROP_FLOAT && but->rnapoin.data) + return 1; + + return 0; +} + +double ui_get_but_val(uiBut *but) +{ + PropertyRNA *prop; + double value = 0.0; + + if(but->editval) { return *(but->editval); } + if(but->poin==NULL && but->rnapoin.data==NULL) return 0.0; + + if(but->rnaprop) { + prop= but->rnaprop; + + switch(prop->type) { + case PROP_BOOLEAN: + if(prop->arraylength) + value= RNA_property_boolean_get_array(prop, &but->rnapoin, but->rnaindex); + else + value= RNA_property_boolean_get(prop, &but->rnapoin); + break; + case PROP_INT: + if(prop->arraylength) + value= RNA_property_int_get_array(prop, &but->rnapoin, but->rnaindex); + else + value= RNA_property_int_get(prop, &but->rnapoin); + break; + case PROP_FLOAT: + if(prop->arraylength) + value= RNA_property_float_get_array(prop, &but->rnapoin, but->rnaindex); + else + value= RNA_property_float_get(prop, &but->rnapoin); + break; + case PROP_ENUM: + value= RNA_property_enum_get(prop, &but->rnapoin); + break; + default: + value= 0.0; + break; + } + } + else if(but->type== HSVSLI) { + float h, s, v, *fp; + + fp= (but->editvec)? but->editvec: (float *)but->poin; + rgb_to_hsv(fp[0], fp[1], fp[2], &h, &s, &v); + + switch(but->str[0]) { + case 'H': value= h; break; + case 'S': value= s; break; + case 'V': value= v; break; + } + } + else if( but->pointype == CHA ) { + value= *(char *)but->poin; + } + else if( but->pointype == SHO ) { + value= *(short *)but->poin; + } + else if( but->pointype == INT ) { + value= *(int *)but->poin; + } + else if( but->pointype == FLO ) { + value= *(float *)but->poin; + } + + return value; +} + +void ui_set_but_val(uiBut *but, double value) +{ + PropertyRNA *prop; + + /* value is a hsv value: convert to rgb */ + if(but->rnaprop) { + prop= but->rnaprop; + + switch(prop->type) { + case PROP_BOOLEAN: + if(prop->arraylength) + RNA_property_boolean_set_array(prop, &but->rnapoin, but->rnaindex, value); + else + RNA_property_boolean_set(prop, &but->rnapoin, value); + break; + case PROP_INT: + if(prop->arraylength) + RNA_property_int_set_array(prop, &but->rnapoin, but->rnaindex, value); + else + RNA_property_int_set(prop, &but->rnapoin, value); + break; + case PROP_FLOAT: + if(prop->arraylength) + RNA_property_float_set_array(prop, &but->rnapoin, but->rnaindex, value); + else + RNA_property_float_set(prop, &but->rnapoin, value); + break; + case PROP_ENUM: + RNA_property_enum_set(prop, &but->rnapoin, value); + break; + default: + break; + } + } + else if(but->pointype==0); + else if(but->type==HSVSLI ) { + float h, s, v, *fp; + + fp= (but->editvec)? but->editvec: (float *)but->poin; + rgb_to_hsv(fp[0], fp[1], fp[2], &h, &s, &v); + + switch(but->str[0]) { + case 'H': h= value; break; + case 'S': s= value; break; + case 'V': v= value; break; + } + + hsv_to_rgb(h, s, v, fp, fp+1, fp+2); + + } + else { + /* first do rounding */ + if(but->pointype==CHA) + value= (char)floor(value+0.5); + else if(but->pointype==SHO ) { + /* gcc 3.2.1 seems to have problems + * casting a double like 32772.0 to + * a short so we cast to an int, then + to a short */ + int gcckludge; + gcckludge = (int) floor(value+0.5); + value= (short)gcckludge; + } + else if(but->pointype==INT ) + value= (int)floor(value+0.5); + else if(but->pointype==FLO ) { + float fval= (float)value; + if(fval>= -0.00001f && fval<= 0.00001f) fval= 0.0f; /* prevent negative zero */ + value= fval; + } + + /* then set value with possible edit override */ + if(but->editval) + *but->editval= value; + else if(but->pointype==CHA) + *((char *)but->poin)= (char)value; + else if(but->pointype==SHO) + *((short *)but->poin)= (short)value; + else if(but->pointype==INT) + *((int *)but->poin)= (int)value; + else if(but->pointype==FLO) + *((float *)but->poin)= (float)value; + } + + /* update select flag */ + ui_is_but_sel(but); +} + +void ui_get_but_string(uiBut *but, char *str, int maxlen) +{ + if(but->rnaprop) { + char *buf; + + buf= RNA_property_string_get_alloc(but->rnaprop, &but->rnapoin, str, maxlen); + + if(buf != str) { + /* string was too long, we have to truncate */ + BLI_strncpy(str, buf, maxlen); + MEM_freeN(buf); + } + } + else + BLI_strncpy(str, but->poin, maxlen); + +} + +void ui_set_but_string(uiBut *but, const char *str) +{ + if(but->rnaprop) + RNA_property_string_set(but->rnaprop, &but->rnapoin, str); + else + BLI_strncpy(but->poin, str, but->max); +} + +/* ******************* Font ********************/ + +static void ui_set_ftf_font(float aspect) +{ +#ifdef INTERNATIONAL + if(aspect<1.15) { + FTF_SetFontSize('l'); + } + else if(aspect<1.59) { + FTF_SetFontSize('m'); + } + else { + FTF_SetFontSize('s'); + } +#endif +} + +void uiSetCurFont(uiBlock *block, int index) +{ + ui_set_ftf_font(block->aspect); + + if(block->aspect<0.60) { + block->curfont= UIfont[index].xl; + } + else if(block->aspect<1.15) { + block->curfont= UIfont[index].large; + } + else if(block->aspect<1.59) { + block->curfont= UIfont[index].medium; + } + else { + block->curfont= UIfont[index].small; + } + + if(block->curfont==NULL) block->curfont= UIfont[index].large; + if(block->curfont==NULL) block->curfont= UIfont[index].medium; + if(block->curfont==NULL) printf("error block no font %s\n", block->name); + +} + +/* called by node editor */ +void *uiSetCurFont_ext(float aspect) +{ + void *curfont; + + ui_set_ftf_font(aspect); + + if(aspect<0.60) { + curfont= UIfont[0].xl; + } + else if(aspect<1.15) { + curfont= UIfont[0].large; + } + else if(aspect<1.59) { + curfont= UIfont[0].medium; + } + else { + curfont= UIfont[0].small; + } + + if(curfont==NULL) curfont= UIfont[0].large; + if(curfont==NULL) curfont= UIfont[0].medium; + + return curfont; +} + +void uiDefFont(unsigned int index, void *xl, void *large, void *medium, void *small) +{ + if(index>=UI_ARRAY) return; + + UIfont[index].xl= xl; + UIfont[index].large= large; + UIfont[index].medium= medium; + UIfont[index].small= small; +} + +/* ******************* Free ********************/ + +static void ui_free_link(uiLink *link) +{ + if(link) { + BLI_freelistN(&link->lines); + MEM_freeN(link); + } +} + +static void ui_free_but(uiBut *but) +{ + if(but->str && but->str != but->strdata) MEM_freeN(but->str); + ui_free_link(but->link); + + MEM_freeN(but); +} + +void uiFreeBlock(uiBlock *block) +{ + uiBut *but; + + while( (but= block->buttons.first) ) { + BLI_remlink(&block->buttons, but); + ui_free_but(but); + } + + if(block->panel) block->panel->active= 0; + BLI_freelistN(&block->saferct); + + + MEM_freeN(block); +} + +void uiFreeBlocks(ListBase *lb) +{ + uiBlock *block; + + while( (block= lb->first) ) { + BLI_remlink(lb, block); + uiFreeBlock(block); + } +} + +uiBlock *uiBeginBlock(wmWindow *window, ARegion *region, char *name, short dt, short font) +{ + ListBase *lb; + uiBlock *block, *oldblock= NULL; + int getsizex, getsizey; + + lb= ®ion->uiblocks; + + /* each listbase only has one block with this name, free block + * if is already there so it can be rebuilt from scratch */ + if(lb) { + for (oldblock= lb->first; oldblock; oldblock= oldblock->next) + if (BLI_streq(oldblock->name, name)) + break; + + if (oldblock) + BLI_remlink(lb, oldblock); + } + + block= MEM_callocN(sizeof(uiBlock), "uiBlock"); + block->oldblock= oldblock; + + /* at the beginning of the list! for dynamical menus/blocks */ + if(lb) + BLI_addhead(lb, block); + + BLI_strncpy(block->name, name, sizeof(block->name)); + +#if 0 + /* draw win */ + block->win= win; + /* window where queue event should be added, pretty weak this way! + this is because the 'mainwin' pup menu's */ + block->winq= mywinget(); +#endif + + block->dt= dt; + block->themecol= TH_AUTO; + + /* window matrix and aspect */ + if(region->swinid) { + wm_subwindow_getmatrix(window, region->swinid, block->winmat); + wm_subwindow_getsize(window, region->swinid, &getsizex, &getsizey); + + /* TODO - investigate why block->winmat[0][0] is negative + * in the image view when viewRedrawForce is called */ + block->aspect= 2.0/fabs( (getsizex)*block->winmat[0][0]); + } + else { + /* no subwindow created yet, for menus for example, so we + * use the main window instead, since buttons are created + * there anyway */ + wm_subwindow_getmatrix(window, window->winid, block->winmat); + wm_subwindow_getsize(window, window->winid, &getsizex, &getsizey); + + block->aspect= 2.0/fabs(getsizex*block->winmat[0][0]); + block->auto_open= 2; + } + + uiSetCurFont(block, font); + + return block; +} + +uiBlock *uiGetBlock(char *name, ARegion *ar) +{ + uiBlock *block= ar->uiblocks.first; + + while(block) { + if( strcmp(name, block->name)==0 ) return block; + block= block->next; + } + + return NULL; +} + +void ui_check_but(uiBut *but) +{ + /* if something changed in the button */ + ID *id; + double value; + float okwidth; + int transopts= ui_translate_buttons(); + short pos; + + ui_is_but_sel(but); + + if(but->type==TEX || but->type==IDPOIN) transopts= 0; + + /* test for min and max, icon sliders, etc */ + switch( but->type ) { + case NUM: + case SLI: + case SCROLL: + case NUMSLI: + case HSVSLI: + value= ui_get_but_val(but); + if(value < but->min) ui_set_but_val(but, but->min); + else if(value > but->max) ui_set_but_val(but, but->max); + break; + + case NUMABS: + value= fabs( ui_get_but_val(but) ); + if(value < but->min) ui_set_but_val(but, but->min); + else if(value > but->max) ui_set_but_val(but, but->max); + break; + + case ICONTOG: + case ICONTOGN: + if(but->flag & UI_SELECT) but->iconadd= 1; + else but->iconadd= 0; + break; + + case ICONROW: + value= ui_get_but_val(but); + but->iconadd= (int)value- (int)(but->min); + break; + + case ICONTEXTROW: + value= ui_get_but_val(but); + but->iconadd= (int)value- (int)(but->min); + break; + } + + + /* safety is 4 to enable small number buttons (like 'users') */ + if(but->type==NUMSLI || but->type==HSVSLI) + okwidth= -4 + (but->x2 - but->x1)/2.0; + else + okwidth= -4 + (but->x2 - but->x1); + + /* name: */ + switch( but->type ) { + + case MENU: + case ICONTEXTROW: + + if(but->x2 - but->x1 > 24) { + value= ui_get_but_val(but); + ui_set_name_menu(but, (int)value); + } + break; + + case NUM: + case NUMSLI: + case HSVSLI: + case NUMABS: + + value= ui_get_but_val(but); + + if(ui_is_but_float(but)) { + if(but->a2) { /* amount of digits defined */ + if(but->a2==1) sprintf(but->drawstr, "%s%.1f", but->str, value); + else if(but->a2==2) sprintf(but->drawstr, "%s%.2f", but->str, value); + else if(but->a2==3) sprintf(but->drawstr, "%s%.3f", but->str, value); + else sprintf(but->drawstr, "%s%.4f", but->str, value); + } + else { + if(but->max<10.001) sprintf(but->drawstr, "%s%.3f", but->str, value); + else sprintf(but->drawstr, "%s%.2f", but->str, value); + } + } + else { + sprintf(but->drawstr, "%s%d", but->str, (int)value); + } + break; + + case LABEL: + if(ui_is_but_float(but)) { + value= ui_get_but_val(but); + if(but->a2) { /* amount of digits defined */ + if(but->a2==1) sprintf(but->drawstr, "%s%.1f", but->str, value); + else if(but->a2==2) sprintf(but->drawstr, "%s%.2f", but->str, value); + else if(but->a2==3) sprintf(but->drawstr, "%s%.3f", but->str, value); + else sprintf(but->drawstr, "%s%.4f", but->str, value); + } + else { + sprintf(but->drawstr, "%s%.2f", but->str, value); + } + } + else strcpy(but->drawstr, but->str); + + break; + + case IDPOIN: + id= *(but->idpoin_idpp); + strcpy(but->drawstr, but->str); + if(id) strcat(but->drawstr, id->name+2); + break; + + case TEX: + if(!but->editstr) { + char str[UI_MAX_DRAW_STR]; + + ui_get_but_string(but, str, UI_MAX_DRAW_STR-strlen(but->str)); + + strcpy(but->drawstr, but->str); + strcat(but->drawstr, str); + } + break; + + case KEYEVT: + strcpy(but->drawstr, but->str); + if (but->flag & UI_SELECT) { + strcat(but->drawstr, "Press a key"); + } else { + /* XXX 2.50 function not supported */ + /* strcat(but->drawstr, key_event_to_string((short) ui_get_but_val(but))); */ + } + break; + + case BUT_TOGDUAL: + /* trying to get the dual-icon to left of text... not very nice */ + if(but->str[0]) { + strcpy(but->drawstr, " "); + strcpy(but->drawstr+2, but->str); + } + break; + default: + strcpy(but->drawstr, but->str); + + } + + /* if we are doing text editing, this will override the drawstr */ + if(but->editstr) { + strcpy(but->drawstr, but->str); + strcat(but->drawstr, but->editstr); + } + + if(but->drawstr[0]) { + but->strwidth= but->aspect*UI_GetStringWidth(but->font, but->drawstr, transopts); + // here should be check for less space for icon offsets... + if(but->type==MENU) okwidth -= 15; + } + else + but->strwidth= 0; + + /* automatic width */ + if(but->x2==0.0f && but->x1 > 0.0f) { + but->x2= (but->x1+but->strwidth+6); + } + + if(but->strwidth==0) but->drawstr[0]= 0; + else if(but->type==BUTM || but->type==BLOCK); // no clip string, uiTextBoundsBlock is used (hack!) + else { + + /* calc but->ofs, to draw the string shorter if too long */ + but->ofs= 0; + + while(but->strwidth > (int)okwidth ) { + + if ELEM3(but->type, NUM, NUMABS, TEX) { // only these cut off left + but->ofs++; + but->strwidth= but->aspect*UI_GetStringWidth(but->font, but->drawstr+but->ofs, transopts); + + /* textbut exception */ + if(but->editstr && but->pos != -1) { + pos= but->pos+strlen(but->str); + if(pos-1 < but->ofs) { + pos= but->ofs-pos+1; + but->ofs -= pos; + if(but->ofs<0) { + but->ofs= 0; + pos--; + } + but->drawstr[ strlen(but->drawstr)-pos ]= 0; + } + } + } + else { + but->drawstr[ strlen(but->drawstr)-1 ]= 0; + but->strwidth= but->aspect*UI_GetStringWidth(but->font, but->drawstr, transopts); + } + + if(but->strwidth < 10) break; + } + } +} + +static int ui_auto_themecol(uiBut *but) +{ + + switch(but->type) { + case BUT: + return TH_BUT_ACTION; + case ROW: + case TOG: + case TOG3: + case TOGR: + case TOGN: + case BUT_TOGDUAL: + return TH_BUT_SETTING; + case SLI: + case NUM: + case NUMSLI: + case NUMABS: + case HSVSLI: + return TH_BUT_NUM; + case TEX: + return TH_BUT_TEXTFIELD; + case PULLDOWN: + case BLOCK: + case MENU: + case BUTM: + // (weak!) detect if it is a blockloop + if(but->block->dt == UI_EMBOSSP) return TH_MENU_ITEM; + return TH_BUT_POPUP; + case ROUNDBOX: + return TH_PANEL; + default: + return TH_BUT_NEUTRAL; + } +} + +void uiBlockBeginAlign(uiBlock *block) +{ + /* if other align was active, end it */ + if(block->flag & UI_BUT_ALIGN) uiBlockEndAlign(block); + + block->flag |= UI_BUT_ALIGN_DOWN; + /* buttons declared after this call will this align flag */ +} + +static int buts_are_horiz(uiBut *but1, uiBut *but2) +{ + float dx, dy; + + dx= fabs( but1->x2 - but2->x1); + dy= fabs( but1->y1 - but2->y2); + + if(dx > dy) return 0; + return 1; +} + +void uiBlockEndAlign(uiBlock *block) +{ + uiBut *prev, *but=NULL, *next; + int flag= 0, cols=0, rows=0; + int theme= UI_GetThemeValue(TH_BUT_DRAWTYPE); + + if ( !(ELEM3(theme, TH_MINIMAL, TH_SHADED, TH_ROUNDED)) ) { + block->flag &= ~UI_BUT_ALIGN; // all 4 flags + return; + } + + /* auto align: + - go back to first button of align start (ALIGN_DOWN) + - compare triples, and define flags + */ + prev= block->buttons.last; + while(prev) { + if( (prev->flag & UI_BUT_ALIGN_DOWN)) but= prev; + else break; + + if(but && but->next) { + if(buts_are_horiz(but, but->next)) cols++; + else rows++; + } + + prev= prev->prev; + } + if(but==NULL) return; + + /* rows==0: 1 row, cols==0: 1 collumn */ + + /* note; how it uses 'flag' in loop below (either set it, or OR it) is confusing */ + prev= NULL; + while(but) { + next= but->next; + + /* clear old flag */ + but->flag &= ~UI_BUT_ALIGN_DOWN; + + if(flag==0) { /* first case */ + if(next) { + if(buts_are_horiz(but, next)) { + if(rows==0) + flag= UI_BUT_ALIGN_RIGHT; + else + flag= UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT; + } + else { + flag= UI_BUT_ALIGN_DOWN; + } + } + } + else if(next==NULL) { /* last case */ + if(prev) { + if(buts_are_horiz(prev, but)) { + if(rows==0) + flag= UI_BUT_ALIGN_LEFT; + else + flag= UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT; + } + else flag= UI_BUT_ALIGN_TOP; + } + } + else if(buts_are_horiz(but, next)) { + /* check if this is already second row */ + if( prev && buts_are_horiz(prev, but)==0) { + flag |= UI_BUT_ALIGN_TOP; + /* exception case: bottom row */ + if(rows>0) { + uiBut *bt= but; + while(bt) { + if(bt->next && buts_are_horiz(bt, bt->next)==0 ) break; + bt= bt->next; + } + if(bt==0) flag= UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT; + } + } + else flag |= UI_BUT_ALIGN_LEFT; + } + else { + if(cols==0) { + flag |= UI_BUT_ALIGN_TOP; + } + else { /* next button switches to new row */ + if( (flag & UI_BUT_ALIGN_TOP)==0) { /* stil top row */ + if(prev) + flag= UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT; + else + flag |= UI_BUT_ALIGN_DOWN; + } + else + flag |= UI_BUT_ALIGN_TOP; + } + } + + but->flag |= flag; + + /* merge coordinates */ + if(prev) { + // simple cases + if(rows==0) { + but->x1= (prev->x2+but->x1)/2.0; + prev->x2= but->x1; + } + else if(cols==0) { + but->y2= (prev->y1+but->y2)/2.0; + prev->y1= but->y2; + } + else { + if(buts_are_horiz(prev, but)) { + but->x1= (prev->x2+but->x1)/2.0; + prev->x2= but->x1; + /* copy height too */ + but->y2= prev->y2; + } + else if(prev->prev && buts_are_horiz(prev->prev, prev)==0) { + /* the previous button is a single one in its row */ + but->y2= (prev->y1+but->y2)/2.0; + prev->y1= but->y2; + } + else { + /* the previous button is not a single one in its row */ + but->y2= prev->y1; + } + } + } + + prev= but; + but= next; + } + + block->flag &= ~UI_BUT_ALIGN; // all 4 flags +} + +#if 0 +static void uiBlockEndAligno(uiBlock *block) +{ + uiBut *but; + + /* correct last defined button */ + but= block->buttons.last; + if(but) { + /* vertical align case */ + if( (block->flag & UI_BUT_ALIGN) == (UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_DOWN) ) { + but->flag &= ~UI_BUT_ALIGN_DOWN; + } + /* horizontal align case */ + if( (block->flag & UI_BUT_ALIGN) == (UI_BUT_ALIGN_LEFT|UI_BUT_ALIGN_RIGHT) ) { + but->flag &= ~UI_BUT_ALIGN_RIGHT; + } + /* else do nothing, manually provided flags */ + } + block->flag &= ~UI_BUT_ALIGN; // all 4 flags +} +#endif + +/* +ui_def_but is the function that draws many button types + +for float buttons: + "a1" Click Step (how much to change the value each click) + "a2" Number of decimal point values to display. 0 defaults to 3 (0.000) 1,2,3, and a maximum of 4, + all greater values will be clamped to 4. + +*/ +static uiBut *ui_def_but(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip) +{ + uiBut *but; + short slen; + + if(type & BUTPOIN) { /* a pointer is required */ + if(poin==NULL) { + /* if pointer is zero, button is removed and not drawn */ + UI_ThemeColor(block->themecol); + glRects(x1, y1, x1+x2, y1+y2); + return NULL; + } + } + + but= MEM_callocN(sizeof(uiBut), "uiBut"); + + but->type= type & BUTTYPE; + but->pointype= type & BUTPOIN; + but->bit= type & BIT; + but->bitnr= type & 31; + but->icon = 0; + + BLI_addtail(&block->buttons, but); + + but->retval= retval; + if( strlen(str)>=UI_MAX_NAME_STR-1 ) { + but->str= MEM_callocN( strlen(str)+2, "uiDefBut"); + strcpy(but->str, str); + } + else { + but->str= but->strdata; + strcpy(but->str, str); + } + but->x1= x1; + but->y1= y1; + if(block->autofill) { + but->x2= x2; + but->y2= y2; + } + else { + but->x2= (x1+x2); + but->y2= (y1+y2); + } + but->poin= poin; + but->min= min; + but->max= max; + but->a1= a1; + but->a2= a2; + but->tip= tip; + + but->font= block->curfont; + + but->lock= block->lock; + but->lockstr= block->lockstr; + + but->aspect= block->aspect; + but->win= block->win; + but->block= block; // pointer back, used for frontbuffer status, and picker + + if(block->themecol==TH_AUTO) but->themecol= ui_auto_themecol(but); + else but->themecol= block->themecol; + + if (but->type==BUTM) { + but->butm_func= block->butm_func; + but->butm_func_arg= block->butm_func_arg; + } else { + but->func= block->func; + but->func_arg1= block->func_arg1; + but->func_arg2= block->func_arg2; + } + + ui_set_embossfunc(but, block->dt); + + but->pos= -1; /* cursor invisible */ + + if(ELEM(but->type, NUM, NUMABS)) { /* add a space to name */ + slen= strlen(but->str); + if(slen>0 && slenstr[slen-1]!=' ') { + but->str[slen]= ' '; + but->str[slen+1]= 0; + } + } + } + + if(but->type==HSVCUBE) { /* hsv buttons temp storage */ + float rgb[3]; + ui_get_but_vectorf(but, rgb); + rgb_to_hsv(rgb[0], rgb[1], rgb[2], but->hsv, but->hsv+1, but->hsv+2); + } + + if ELEM8(but->type, HSVSLI , NUMSLI, MENU, TEX, LABEL, IDPOIN, BLOCK, BUTM) { + but->flag |= UI_TEXT_LEFT; + } + + if(but->type==BUT_TOGDUAL) { + but->flag |= UI_ICON_LEFT; + } + + if(but->type==ROUNDBOX) + but->flag |= UI_NO_HILITE; + + but->flag |= (block->flag & UI_BUT_ALIGN); + if(block->flag & UI_BLOCK_NO_HILITE) + but->flag |= UI_NO_HILITE; + + return but; +} + +uiBut *uiDefBut(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip) +{ + uiBut *but= ui_def_but(block, type, retval, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip); + + ui_check_but(but); + + return but; +} + + /* if _x_ is a power of two (only one bit) return the power, + * otherwise return -1. + * (1<>=16; + if (x&0xFF00) idx+=8, x>>=8; + if (x&0xF0) idx+=4, x>>=4; + if (x&0xC) idx+=2, x>>=2; + if (x&0x2) idx+=1; + + return idx; + } +} + +/* autocomplete helper functions */ +struct AutoComplete { + int maxlen; + char *truncate; + char *startname; +}; + +AutoComplete *autocomplete_begin(char *startname, int maxlen) +{ + AutoComplete *autocpl; + + autocpl= MEM_callocN(sizeof(AutoComplete), "AutoComplete"); + autocpl->maxlen= maxlen; + autocpl->truncate= MEM_callocN(sizeof(char)*maxlen, "AutoCompleteTruncate"); + autocpl->startname= startname; + + return autocpl; +} + +void autocomplete_do_name(AutoComplete *autocpl, const char *name) +{ + char *truncate= autocpl->truncate; + char *startname= autocpl->startname; + int a; + + for(a=0; amaxlen-1; a++) { + if(startname[a]==0 || startname[a]!=name[a]) + break; + } + /* found a match */ + if(startname[a]==0) { + /* first match */ + if(truncate[0]==0) + BLI_strncpy(truncate, name, autocpl->maxlen); + else { + /* remove from truncate what is not in bone->name */ + for(a=0; amaxlen-1; a++) { + if(truncate[a]!=name[a]) + truncate[a]= 0; + } + } + } +} + +void autocomplete_end(AutoComplete *autocpl, char *autoname) +{ + if(autocpl->truncate[0]) + BLI_strncpy(autoname, autocpl->truncate, autocpl->maxlen); + else + BLI_strncpy(autoname, autocpl->startname, autocpl->maxlen); + + MEM_freeN(autocpl->truncate); + MEM_freeN(autocpl); +} + +/* autocomplete callback for ID buttons */ +static void autocomplete_id(char *str, void *arg_v) +{ + /* XXX 2.48 int blocktype= (intptr_t)arg_v; */ + ListBase *listb= NULL /* XXX 2.50 needs context, wich_libbase(G.main, blocktype) */; + + if(listb==NULL) return; + + /* search if str matches the beginning of an ID struct */ + if(str[0]) { + AutoComplete *autocpl= autocomplete_begin(str, 22); + ID *id; + + for(id= listb->first; id; id= id->next) + autocomplete_do_name(autocpl, id->name+2); + + autocomplete_end(autocpl, str); + } +} + +static uiBut *uiDefButBit(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip) +{ + int bitIdx= findBitIndex(bit); + if (bitIdx==-1) { + return NULL; + } else { + return uiDefBut(block, type|BIT|bitIdx, retval, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip); + } +} +uiBut *uiDefButF(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefBut(block, type|FLO, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefButBitF(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefButBit(block, type|FLO, bit, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefButI(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefBut(block, type|INT, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefButBitI(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefButBit(block, type|INT, bit, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefButS(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefBut(block, type|SHO, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefButBitS(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefButBit(block, type|SHO, bit, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefButC(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefBut(block, type|CHA, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefButBitC(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefButBit(block, type|CHA, bit, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} + +uiBut *uiDefIconBut(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip) +{ + uiBut *but= ui_def_but(block, type, retval, "", x1, y1, x2, y2, poin, min, max, a1, a2, tip); + + but->icon= (BIFIconID) icon; + but->flag|= UI_HAS_ICON; + + ui_check_but(but); + + return but; +} +static uiBut *uiDefIconButBit(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip) +{ + int bitIdx= findBitIndex(bit); + if (bitIdx==-1) { + return NULL; + } else { + return uiDefIconBut(block, type|BIT|bitIdx, retval, icon, x1, y1, x2, y2, poin, min, max, a1, a2, tip); + } +} + +uiBut *uiDefIconButF(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconBut(block, type|FLO, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconButBitF(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconButBit(block, type|FLO, bit, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconButI(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconBut(block, type|INT, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconButBitI(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconButBit(block, type|INT, bit, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconButS(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconBut(block, type|SHO, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconButBitS(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconButBit(block, type|SHO, bit, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconButC(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconBut(block, type|CHA, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconButBitC(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconButBit(block, type|CHA, bit, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} + +/* Button containing both string label and icon */ +uiBut *uiDefIconTextBut(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip) +{ + uiBut *but= ui_def_but(block, type, retval, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip); + + but->icon= (BIFIconID) icon; + but->flag|= UI_HAS_ICON; + + but->flag|= UI_ICON_LEFT; + + ui_check_but(but); + + return but; +} +static uiBut *uiDefIconTextButBit(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip) +{ + int bitIdx= findBitIndex(bit); + if (bitIdx==-1) { + return NULL; + } else { + return uiDefIconTextBut(block, type|BIT|bitIdx, retval, icon, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip); + } +} + +uiBut *uiDefIconTextButF(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconTextBut(block, type|FLO, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconTextButBitF(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconTextButBit(block, type|FLO, bit, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconTextButI(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconTextBut(block, type|INT, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconTextButBitI(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconTextButBit(block, type|INT, bit, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconTextButS(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconTextBut(block, type|SHO, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconTextButBitS(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconTextButBit(block, type|SHO, bit, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconTextButC(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconTextBut(block, type|CHA, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} +uiBut *uiDefIconTextButBitC(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip) +{ + return uiDefIconTextButBit(block, type|CHA, bit, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip); +} + +uiBut *uiDefRNABut(uiBlock *block, int retval, PointerRNA *ptr, PropertyRNA *prop, int index, short x1, short y1, short x2, short y2) +{ + uiBut *but; + + switch(prop->type) { + case PROP_BOOLEAN: { + int value; + + if(prop->arraylength) + value= RNA_property_boolean_get_array(prop, ptr, index); + else + value= RNA_property_boolean_get(prop, ptr); + + but= ui_def_but(block, TOG, 0, (value)? "True": "False", x1, y1, x2, y2, NULL, 0, 0, 0, 0, (char*)prop->description); + break; + } + case PROP_INT: { + IntPropertyRNA *iprop= (IntPropertyRNA*)prop; + but= ui_def_but(block, NUM, 0, "", x1, y1, x2, y2, NULL, iprop->softmin, iprop->softmax, iprop->step, 0, (char*)prop->description); + break; + } + case PROP_FLOAT: { + FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop; + but= ui_def_but(block, NUM, 0, "", x1, y1, x2, y2, NULL, fprop->softmin, fprop->softmax, fprop->step, fprop->precision, (char*)prop->description); + break; + } + case PROP_ENUM: { + EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop; + DynStr *dynstr; + char *menu; + int i; + + dynstr= BLI_dynstr_new(); + BLI_dynstr_appendf(dynstr, "%s%%t", prop->name); + for(i=0; itotitem; i++) + BLI_dynstr_appendf(dynstr, "|%s %%x%d", eprop->item[i].name, eprop->item[i].value); + menu= BLI_dynstr_get_cstring(dynstr); + BLI_dynstr_free(dynstr); + + but= ui_def_but(block, MENU, 0, menu, x1, y1, x2, y2, NULL, 0, 0, 0, 0, (char*)prop->description); + MEM_freeN(menu); + break; + } + case PROP_STRING: { + StringPropertyRNA *sprop= (StringPropertyRNA*)prop; + but= ui_def_but(block, TEX, 0, "", x1, y1, x2, y2, NULL, 0, sprop->maxlength, 0, 0, (char*)prop->description); + break; + } + case PROP_POINTER: { + PointerRNA pptr; + char name[256]= "", *nameptr= name; + + RNA_property_pointer_get(prop, ptr, &pptr); + + if(pptr.data) { + if(pptr.type && pptr.type->nameproperty) + nameptr= RNA_property_string_get_alloc(pptr.type->nameproperty, &pptr, name, sizeof(name)); + else + strcpy(nameptr, "unknown"); + } + + but= ui_def_but(block, BUT, 0, nameptr, x1, y1, x2, y2, NULL, 0, 0, 0, 0, (char*)prop->description); + but->flag |= UI_TEXT_LEFT; + + if(nameptr != name) + MEM_freeN(nameptr); + + break; + } + default: + but= NULL; + break; + } + + if(but) { + but->rnapoin= *ptr; + but->rnaprop= prop; + but->rnaindex= index; + + ui_check_but(but); + } + + return but; +} + +/* END Button containing both string label and icon */ + +void uiAutoBlock(uiBlock *block, float minx, float miny, float sizex, float sizey, int flag) +{ + block->minx= minx; + block->maxx= minx+sizex; + block->miny= miny; + block->maxy= miny+sizey; + + block->autofill= flag; /* also check for if it has to be done */ + +} + +void uiSetButLink(uiBut *but, void **poin, void ***ppoin, short *tot, int from, int to) +{ + uiLink *link; + + link= but->link= MEM_callocN(sizeof(uiLink), "new uilink"); + + link->poin= poin; + link->ppoin= ppoin; + link->totlink= tot; + link->fromcode= from; + link->tocode= to; +} + +/* cruft to make uiBlock and uiBut private */ + +int uiBlocksGetYMin(ListBase *lb) +{ + uiBlock *block; + int min= 0; + + for (block= lb->first; block; block= block->next) + if (block==lb->first || block->minyminy; + + return min; +} + +int uiBlockGetCol(uiBlock *block) +{ + return block->themecol; +} +void uiBlockSetCol(uiBlock *block, int col) +{ + block->themecol= col; +} +void uiBlockSetEmboss(uiBlock *block, int emboss) +{ + block->dt= emboss; +} +void uiBlockSetDirection(uiBlock *block, int direction) +{ + block->direction= direction; +} + +/* this call escapes if there's alignment flags */ +void uiBlockFlipOrder(uiBlock *block) +{ + ListBase lb; + uiBut *but, *next; + float centy, miny=10000, maxy= -10000; + +// if(U.uiflag & USER_PLAINMENUS) +// return; + + for(but= block->buttons.first; but; but= but->next) { + if(but->flag & UI_BUT_ALIGN) return; + if(but->y1 < miny) miny= but->y1; + if(but->y2 > maxy) maxy= but->y2; + } + /* mirror trick */ + centy= (miny+maxy)/2.0; + for(but= block->buttons.first; but; but= but->next) { + but->y1 = centy-(but->y1-centy); + but->y2 = centy-(but->y2-centy); + SWAP(float, but->y1, but->y2); + } + + /* also flip order in block itself, for example for arrowkey */ + lb.first= lb.last= NULL; + but= block->buttons.first; + while(but) { + next= but->next; + BLI_remlink(&block->buttons, but); + BLI_addtail(&lb, but); + but= next; + } + block->buttons= lb; +} + + +void uiBlockSetFlag(uiBlock *block, int flag) +{ + block->flag= flag; +} +void uiBlockSetXOfs(uiBlock *block, int xofs) +{ + block->xofs= xofs; +} +void* uiBlockGetCurFont(uiBlock *block) +{ + return block->curfont; +} + +void uiButSetFlag(uiBut *but, int flag) +{ + but->flag|= flag; +} +void uiButClearFlag(uiBut *but, int flag) +{ + but->flag&= ~flag; +} + +int uiButGetRetVal(uiBut *but) +{ + return but->retval; +} + +/* Call this function BEFORE adding buttons to the block */ +void uiBlockSetButmFunc(uiBlock *block, void (*menufunc)(void *arg, int event), void *arg) +{ + block->butm_func= menufunc; + block->butm_func_arg= arg; +} + +void uiBlockSetFunc(uiBlock *block, void (*func)(void *arg1, void *arg2), void *arg1, void *arg2) +{ + block->func= func; + block->func_arg1= arg1; + block->func_arg2= arg2; +} + +void uiBlockSetDrawExtraFunc(uiBlock *block, void (*func)()) +{ + block->drawextra= func; +} + +void uiButSetFunc(uiBut *but, void (*func)(void *arg1, void *arg2), void *arg1, void *arg2) +{ + but->func= func; + but->func_arg1= arg1; + but->func_arg2= arg2; +} + +void uiButSetFunc3(uiBut *but, void (*func)(void *arg1, void *arg2, void *arg3), void *arg1, void *arg2, void *arg3) +{ + but->func3= func; + but->func_arg1= arg1; + but->func_arg2= arg2; + but->func_arg3= arg3; +} + +void uiButSetCompleteFunc(uiBut *but, void (*func)(char *str, void *arg), void *arg) +{ + but->autocomplete_func= func; + but->autofunc_arg= arg; +} + +uiBut *uiDefIDPoinBut(uiBlock *block, uiIDPoinFuncFP func, short blocktype, int retval, char *str, short x1, short y1, short x2, short y2, void *idpp, char *tip) +{ + uiBut *but= ui_def_but(block, IDPOIN, retval, str, x1, y1, x2, y2, NULL, 0.0, 0.0, 0.0, 0.0, tip); + but->idpoin_func= func; + but->idpoin_idpp= (ID**) idpp; + ui_check_but(but); + + if(blocktype) + uiButSetCompleteFunc(but, autocomplete_id, 0 /* XXX 2.48 (void *)(intptr_t)blocktype*/); + + return but; +} + +uiBut *uiDefBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip) +{ + uiBut *but= ui_def_but(block, BLOCK, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip); + but->block_func= func; + ui_check_but(but); + return but; +} + +uiBut *uiDefPulldownBut(uiBlock *block, uiBlockFuncFP func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip) +{ + uiBut *but= ui_def_but(block, PULLDOWN, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip); + but->block_func= func; + ui_check_but(but); + return but; +} + +/* Block button containing both string label and icon */ +uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int icon, char *str, short x1, short y1, short x2, short y2, char *tip) +{ + uiBut *but= ui_def_but(block, BLOCK, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip); + + but->icon= (BIFIconID) icon; + but->flag|= UI_HAS_ICON; + + but->flag|= UI_ICON_LEFT; + but->flag|= UI_ICON_RIGHT; + + but->block_func= func; + ui_check_but(but); + + return but; +} + +/* Block button containing icon */ +uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int retval, int icon, short x1, short y1, short x2, short y2, char *tip) +{ + uiBut *but= ui_def_but(block, BLOCK, retval, "", x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip); + + but->icon= (BIFIconID) icon; + but->flag|= UI_HAS_ICON; + + but->flag|= UI_ICON_LEFT; + but->flag|= UI_ICON_RIGHT; + + but->block_func= func; + ui_check_but(but); + + return but; +} + +void uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *spoin, char *tip) +{ + uiBut *but= ui_def_but(block, KEYEVT|SHO, retval, str, x1, y1, x2, y2, spoin, 0.0, 0.0, 0.0, 0.0, tip); + ui_check_but(but); +} + +/* Program Init/Exit */ + +void UI_init(void) +{ + uiDefFont(UI_HELVB, + BMF_GetFont(BMF_kHelveticaBold14), + BMF_GetFont(BMF_kHelveticaBold12), + BMF_GetFont(BMF_kHelveticaBold10), + BMF_GetFont(BMF_kHelveticaBold8)); + uiDefFont(UI_HELV, + BMF_GetFont(BMF_kHelvetica12), + BMF_GetFont(BMF_kHelvetica12), + BMF_GetFont(BMF_kHelvetica10), + BMF_GetFont(BMF_kHelveticaBold8)); + + ui_resources_init(); +} + +void UI_init_userdef() +{ + ui_text_init_userdef(); + ui_theme_init_userdef(); +} + +void UI_exit(void) +{ + ui_resources_free(); +} + diff --git a/source/blender/editors/interface/interface.h b/source/blender/editors/interface/interface.h new file mode 100644 index 00000000000..2df65e3ef3b --- /dev/null +++ b/source/blender/editors/interface/interface.h @@ -0,0 +1,292 @@ +/** + * $Id: interface.h 14444 2008-04-16 22:40:48Z hos $ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 ***** + */ + +#ifndef INTERFACE_H +#define INTERFACE_H + +#include "UI_resources.h" +#include "RNA_types.h" + +struct uiActivateBut; +struct wmWindow; +struct ARegion; + +/* general defines */ + +#define UI_MAX_DRAW_STR 400 +#define UI_MAX_NAME_STR 64 +#define UI_ARRAY 29 + +/* panel limits */ +#define UI_PANEL_MINX 100 +#define UI_PANEL_MINY 70 + +/* uiBut->flag */ +#define UI_SELECT 1 +#define UI_MOUSE_OVER 2 +#define UI_ACTIVE 4 +#define UI_HAS_ICON 8 +/* warn: rest of uiBut->flag in BIF_interface.c */ + +/* uiBut->activateflag */ +#define UI_ACTIVATE 1 +#define UI_ACTIVATE_APPLY 2 +#define UI_ACTIVATE_TEXT_EDITING 4 +#define UI_ACTIVATE_OPEN 8 + +/* internal panel drawing defines */ +#define PNL_GRID 4 +#define PNL_DIST 8 +#define PNL_SAFETY 8 +#define PNL_HEADER 20 + +/* panel->flag */ +#define PNL_SELECT 1 +#define PNL_CLOSEDX 2 +#define PNL_CLOSEDY 4 +#define PNL_CLOSED 6 +#define PNL_TABBED 8 +#define PNL_OVERLAP 16 + +/* Button text selection: + * extension direction, selextend, inside ui_do_but_TEX */ +#define EXTEND_LEFT 1 +#define EXTEND_RIGHT 2 + +typedef struct { + short xim, yim; + unsigned int *rect; + short xofs, yofs; +} uiIconImage; + +typedef struct { + short mval[2]; + short qual, val; + int event; +} uiEvent; + +typedef struct { + void *xl, *large, *medium, *small; +} uiFont; + +typedef struct uiLinkLine { /* only for draw/edit */ + struct uiLinkLine *next, *prev; + + short flag, pad; + + struct uiBut *from, *to; +} uiLinkLine; + +typedef struct { + void **poin; /* pointer to original pointer */ + void ***ppoin; /* pointer to original pointer-array */ + short *totlink; /* if pointer-array, here is the total */ + + short maxlink, pad; + short fromcode, tocode; + + ListBase lines; +} uiLink; + +struct uiBut { + struct uiBut *next, *prev; + short type, pointype, bit, bitnr, retval, strwidth, ofs, pos, selsta, selend; + int flag; + + char *str; + char strdata[UI_MAX_NAME_STR]; + char drawstr[UI_MAX_DRAW_STR]; + + float x1, y1, x2, y2; + + char *poin; + float min, max; + float a1, a2, hsv[3]; // hsv is temp memory for hsv buttons + float aspect; + + void (*func)(void *, void *); + void (*func3)(void *, void *, void *); /* XXX remove */ + void *func_arg1; + void *func_arg2; + void *func_arg3; /* XXX remove */ + + void (*embossfunc)(int , int , float, float, float, float, float, int); + void (*sliderfunc)(int , float, float, float, float, float, float, int); + + void (*autocomplete_func)(char *, void *); + void *autofunc_arg; + + uiLink *link; + + char *tip, *lockstr; + + int themecol; /* themecolor id */ + void *font; + + BIFIconID icon; + short but_align; /* aligning buttons, horiz/vertical */ + short lock, win; + short iconadd, dt; + + /* IDPOIN data */ + uiIDPoinFuncFP idpoin_func; + ID **idpoin_idpp; + + /* BLOCK data */ + uiBlockFuncFP block_func; + + /* BUTM data */ + void (*butm_func)(void *arg, int event); + void *butm_func_arg; + + /* RNA */ + struct PointerRNA rnapoin; + struct PropertyRNA *rnaprop; + int rnaindex; + + /* Activation data */ + struct uiActivateBut *activate; + int activateflag; + + char *editstr; + double *editval; + float *editvec; + void *editcoba; + void *editcumap; + + /* pointer back */ + uiBlock *block; +}; + +struct uiBlock { + uiBlock *next, *prev; + + ListBase buttons; + Panel *panel; + uiBlock *oldblock; + + char name[UI_MAX_NAME_STR]; + + float winmat[4][4]; + + float minx, miny, maxx, maxy; + float aspect; + + void (*butm_func)(void *arg, int event); + void *butm_func_arg; + + void (*func)(void *arg1, void *arg2); + void *func_arg1; + void *func_arg2; + + /* extra draw function for custom blocks */ + void (*drawextra)(); + + int themecol; /* themecolor id */ + + short font; /* indices */ + int afterval, flag; + void *curfont; + + short autofill, win, winq, direction, dt; + short auto_open, in_use, pad; + double auto_open_last; + + int lock; + char *lockstr; + + float xofs, yofs; // offset to parent button + rctf safety; // pulldowns, to detect outside, can differ per case how it is created + ListBase saferct; // uiSafetyRct list + uiMenuBlockHandle *handle; // handle +}; + +typedef struct uiSafetyRct { + struct uiSafetyRct *next, *prev; + rctf parent; + rctf safety; +} uiSafetyRct; + +/* interface.c */ + +extern int ui_translate_buttons(void); +extern int ui_translate_menus(void); +extern int ui_translate_tooltips(void); + +extern void ui_block_to_window_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y); +extern void ui_block_to_window(const struct ARegion *ar, uiBlock *block, int *x, int *y); +extern void ui_block_to_window_rct(const struct ARegion *ar, uiBlock *block, rctf *graph, rcti *winr); +extern void ui_window_to_block_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y); +extern void ui_window_to_block(const struct ARegion *ar, uiBlock *block, int *x, int *y); + +extern double ui_get_but_val(uiBut *but); +extern void ui_set_but_val(uiBut *but, double value); +extern void ui_set_but_hsv(uiBut *but); +extern void ui_get_but_vectorf(uiBut *but, float *vec); +extern void ui_set_but_vectorf(uiBut *but, float *vec); +extern void ui_get_but_string(uiBut *but, char *str, int maxlen); +extern void ui_set_but_string(uiBut *but, const char *str); + +extern void ui_check_but(uiBut *but); +extern void ui_autofill(uiBlock *block); +extern int ui_is_but_float(uiBut *but); +extern void ui_update_block_buts_hsv(uiBlock *block, float *hsv); + +/* interface_regions.c */ +uiBlock *ui_block_func_MENU(struct wmWindow *window, uiMenuBlockHandle *handle, void *arg_but); +uiBlock *ui_block_func_ICONROW(struct wmWindow *window, uiMenuBlockHandle *handle, void *arg_but); +uiBlock *ui_block_func_ICONTEXTROW(struct wmWindow *window, uiMenuBlockHandle *handle, void *arg_but); +uiBlock *ui_block_func_COL(struct wmWindow *window, uiMenuBlockHandle *handle, void *arg_but); + +struct ARegion *ui_tooltip_create(struct bContext *C, struct ARegion *butregion, uiBut *but); +void ui_tooltip_free(struct bContext *C, struct ARegion *ar); + +uiMenuBlockHandle *ui_menu_block_create(struct bContext *C, struct ARegion *butregion, uiBut *but, + uiBlockFuncFP block_func, void *arg); +void ui_menu_block_free(struct bContext *C, uiMenuBlockHandle *handle); + +void ui_set_name_menu(uiBut *but, int value); + +/* interface_panel.c */ +extern void ui_draw_panel(uiBlock *block); +extern void ui_do_panel(uiBlock *block, uiEvent *uevent); +extern void ui_scale_panel(uiBlock *block); +extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad); +extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown); + +/* interface_draw.c */ +extern void ui_set_embossfunc(uiBut *but, int drawtype); +extern void ui_draw_but(uiBut *but); +extern void ui_rasterpos_safe(float x, float y, float aspect); +extern void ui_draw_tria_icon(float x, float y, float aspect, char dir); +extern void ui_draw_anti_x(float x1, float y1, float x2, float y2); +extern void ui_dropshadow(rctf *rct, float radius, float aspect, int select); + +#endif + diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c new file mode 100644 index 00000000000..49a5b8482cc --- /dev/null +++ b/source/blender/editors/interface/interface_draw.c @@ -0,0 +1,2622 @@ +/** + * $Id: interface_draw.c 15733 2008-07-24 09:23:13Z aligorith $ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 ***** + */ + +#include +#include + +#include "DNA_color_types.h" +#include "DNA_listBase.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_texture_types.h" +#include "DNA_userdef_types.h" + +#include "BLI_arithb.h" + +#include "BKE_colortools.h" +#include "BKE_texture.h" +#include "BKE_utildefines.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "UI_interface.h" +#include "UI_text.h" + +#include "BMF_Api.h" +#ifdef INTERNATIONAL +#include "FTF_Api.h" +#endif + +#include "interface.h" + +#define UI_RB_ALPHA 16 +static int roundboxtype= 15; + +void uiSetRoundBox(int type) +{ + /* Not sure the roundbox function is the best place to change this + * if this is undone, its not that big a deal, only makes curves edges + * square for the */ + if (UI_GetThemeValue(TH_BUT_DRAWTYPE) == TH_MINIMAL) + roundboxtype= 0; + else + roundboxtype= type; + + /* flags to set which corners will become rounded: + + 1------2 + | | + 8------4 + */ + +} + +void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad) +{ + float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293}, + {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; + int a; + + /* mult */ + for(a=0; a<7; a++) { + vec[a][0]*= rad; vec[a][1]*= rad; + } + + glBegin(mode); + + /* start with corner right-bottom */ + if(roundboxtype & 4) { + glVertex2f( maxx-rad, miny); + for(a=0; a<7; a++) { + glVertex2f( maxx-rad+vec[a][0], miny+vec[a][1]); + } + glVertex2f( maxx, miny+rad); + } + else glVertex2f( maxx, miny); + + /* corner right-top */ + if(roundboxtype & 2) { + glVertex2f( maxx, maxy-rad); + for(a=0; a<7; a++) { + glVertex2f( maxx-vec[a][1], maxy-rad+vec[a][0]); + } + glVertex2f( maxx-rad, maxy); + } + else glVertex2f( maxx, maxy); + + /* corner left-top */ + if(roundboxtype & 1) { + glVertex2f( minx+rad, maxy); + for(a=0; a<7; a++) { + glVertex2f( minx+rad-vec[a][0], maxy-vec[a][1]); + } + glVertex2f( minx, maxy-rad); + } + else glVertex2f( minx, maxy); + + /* corner left-bottom */ + if(roundboxtype & 8) { + glVertex2f( minx, miny+rad); + for(a=0; a<7; a++) { + glVertex2f( minx+vec[a][1], miny+rad-vec[a][0]); + } + glVertex2f( minx+rad, miny); + } + else glVertex2f( minx, miny); + + glEnd(); +} + +/* ************** safe rasterpos for pixmap alignment with pixels ************* */ + +void ui_rasterpos_safe(float x, float y, float aspect) +{ + float vals[4], remainder; + int doit=0; + + glRasterPos2f(x, y); + glGetFloatv(GL_CURRENT_RASTER_POSITION, vals); + + remainder= vals[0] - floor(vals[0]); + if(remainder > 0.4 && remainder < 0.6) { + if(remainder < 0.5) x -= 0.1*aspect; + else x += 0.1*aspect; + doit= 1; + } + remainder= vals[1] - floor(vals[1]); + if(remainder > 0.4 && remainder < 0.6) { + if(remainder < 0.5) y -= 0.1*aspect; + else y += 0.1*aspect; + doit= 1; + } + + if(doit) glRasterPos2f(x, y); + + UI_RasterPos(x, y); + UI_SetScale(aspect); +} + +/* ************** generic embossed rect, for window sliders etc ************* */ + +void uiEmboss(float x1, float y1, float x2, float y2, int sel) +{ + + /* below */ + if(sel) glColor3ub(200,200,200); + else glColor3ub(50,50,50); + fdrawline(x1, y1, x2, y1); + + /* right */ + fdrawline(x2, y1, x2, y2); + + /* top */ + if(sel) glColor3ub(50,50,50); + else glColor3ub(200,200,200); + fdrawline(x1, y2, x2, y2); + + /* left */ + fdrawline(x1, y1, x1, y2); + +} + +/* ************** GENERIC ICON DRAW, NO THEME HERE ************* */ + +/* icons have been standardized... and this call draws in untransformed coordinates */ +#define ICON_HEIGHT 16.0f + +static void ui_draw_icon(uiBut *but, BIFIconID icon, int blend) +{ + /* XXX 2.50 need interface_icons.c */ +#if 0 + float xs=0, ys=0, aspect, height; + + /* this icon doesn't need draw... */ + if(icon==ICON_BLANK1) return; + + /* we need aspect from block, for menus... these buttons are scaled in uiPositionBlock() */ + aspect= but->block->aspect; + if(aspect != but->aspect) { + /* prevent scaling up icon in pupmenu */ + if (aspect < 1.0f) { + height= ICON_HEIGHT; + aspect = 1.0f; + + } + else + height= ICON_HEIGHT/aspect; + } + else + height= ICON_HEIGHT; + + if(but->flag & UI_ICON_LEFT) { + if (but->type==BUT_TOGDUAL) { + if (but->drawstr[0]) { + xs= but->x1-1.0; + } else { + xs= (but->x1+but->x2- height)/2.0; + } + } + else if (but->type==BUTM ) { + xs= but->x1+1.0; + } + else if ((but->type==ICONROW) || (but->type==ICONTEXTROW)) { + xs= but->x1+3.0; + } + else { + xs= but->x1+4.0; + } + ys= (but->y1+but->y2- height)/2.0; + } + if(but->flag & UI_ICON_RIGHT) { + xs= but->x2-17.0; + ys= (but->y1+but->y2- height)/2.0; + } + if (!((but->flag & UI_ICON_RIGHT) || (but->flag & UI_ICON_LEFT))) { + xs= (but->x1+but->x2- height)/2.0; + ys= (but->y1+but->y2- height)/2.0; + } + + glEnable(GL_BLEND); + + /* calculate blend color */ + if ELEM3(but->type, TOG, ROW, TOGN) { + if(but->flag & UI_SELECT); + else if(but->flag & UI_ACTIVE); + else blend= -60; + } + UI_icon_draw_aspect_blended(xs, ys, icon, aspect, blend); + + glDisable(GL_BLEND); +#endif +} + + +/* ************** DEFAULT THEME, SHADED BUTTONS ************* */ + + +#define M_WHITE UI_ThemeColorShade(colorid, 80) + +#define M_ACT_LIGHT UI_ThemeColorShade(colorid, 55) +#define M_LIGHT UI_ThemeColorShade(colorid, 45) +#define M_HILITE UI_ThemeColorShade(colorid, 25) +#define M_LMEDIUM UI_ThemeColorShade(colorid, 10) +#define M_MEDIUM UI_ThemeColor(colorid) +#define M_LGREY UI_ThemeColorShade(colorid, -20) +#define M_GREY UI_ThemeColorShade(colorid, -45) +#define M_DARK UI_ThemeColorShade(colorid, -80) + +#define M_NUMTEXT UI_ThemeColorShade(colorid, 25) +#define M_NUMTEXT_ACT_LIGHT UI_ThemeColorShade(colorid, 35) + +#define MM_WHITE UI_ThemeColorShade(TH_BUT_NEUTRAL, 120) + +/* Used for the subtle sunken effect around buttons. + * One option is to hardcode to white, with alpha, however it causes a + * weird 'building up' efect, so it's commented out for now. + */ + +/* +#define MM_WHITE_OP glColor4ub(255, 255, 255, 60) +#define MM_WHITE_TR glColor4ub(255, 255, 255, 0) + */ + +#define MM_WHITE_OP UI_ThemeColorShadeAlpha(TH_BACK, 55, -100) +#define MM_WHITE_TR UI_ThemeColorShadeAlpha(TH_BACK, 55, -255) + +#define MM_LIGHT UI_ThemeColorShade(TH_BUT_OUTLINE, 45) +#define MM_MEDIUM UI_ThemeColor(TH_BUT_OUTLINE) +#define MM_GREY UI_ThemeColorShade(TH_BUT_OUTLINE, -45) +#define MM_DARK UI_ThemeColorShade(TH_BUT_OUTLINE, -80) + +/* base shaded button */ +static void shaded_button(float x1, float y1, float x2, float y2, float asp, int colorid, int flag, int mid) +{ + /* 'mid' arg determines whether the button is in the middle of + * an alignment group or not. 0 = not middle, 1 = is in the middle. + * Done to allow cleaner drawing + */ + + /* *** SHADED BUTTON BASE *** */ + glShadeModel(GL_SMOOTH); + glBegin(GL_QUADS); + + if(flag & UI_SELECT) { + if(flag & UI_ACTIVE) M_MEDIUM; + else M_LGREY; + } else { + if(flag & UI_ACTIVE) M_LIGHT; + else M_HILITE; + } + + glVertex2f(x1,y1); + glVertex2f(x2,y1); + + if(flag & UI_SELECT) { + if(flag & UI_ACTIVE) M_LGREY; + else M_GREY; + } else { + if(flag & UI_ACTIVE) M_ACT_LIGHT; + else M_LIGHT; + } + + glVertex2f(x2,(y2-(y2-y1)/3)); + glVertex2f(x1,(y2-(y2-y1)/3)); + glEnd(); + + + glShadeModel(GL_FLAT); + glBegin(GL_QUADS); + + if(flag & UI_SELECT) { + if(flag & UI_ACTIVE) M_LGREY; + else M_GREY; + } else { + if(flag & UI_ACTIVE) M_ACT_LIGHT; + else M_LIGHT; + } + + glVertex2f(x1,(y2-(y2-y1)/3)); + glVertex2f(x2,(y2-(y2-y1)/3)); + glVertex2f(x2,y2); + glVertex2f(x1,y2); + + glEnd(); + /* *** END SHADED BUTTON BASE *** */ + + /* *** INNER OUTLINE *** */ + /* left */ + if(!(flag & UI_SELECT)) { + glShadeModel(GL_SMOOTH); + glBegin(GL_LINES); + M_MEDIUM; + glVertex2f(x1+1,y1+2); + M_WHITE; + glVertex2f(x1+1,y2); + glEnd(); + } + + /* right */ + if(!(flag & UI_SELECT)) { + glShadeModel(GL_SMOOTH); + glBegin(GL_LINES); + M_MEDIUM; + glVertex2f(x2-1,y1+2); + M_WHITE; + glVertex2f(x2-1,y2); + glEnd(); + } + + glShadeModel(GL_FLAT); + + /* top */ + if(flag & UI_SELECT) { + if(flag & UI_ACTIVE) M_LGREY; + else M_GREY; + } else { + if(flag & UI_ACTIVE) M_WHITE; + else M_WHITE; + } + + fdrawline(x1, (y2-1), x2, (y2-1)); + + /* bottom */ + if(flag & UI_SELECT) { + if(flag & UI_ACTIVE) M_MEDIUM; + else M_LGREY; + } else { + if(flag & UI_ACTIVE) M_LMEDIUM; + else M_MEDIUM; + } + fdrawline(x1, (y1+1), x2, (y1+1)); + /* *** END INNER OUTLINE *** */ + + /* *** OUTER OUTLINE *** */ + if (mid) { + // we draw full outline, its not AA, and it works better button mouse-over hilite + MM_DARK; + + // left right + fdrawline(x1, y1, x1, y2); + fdrawline(x2, y1, x2, y2); + + // top down + fdrawline(x1, y2, x2, y2); + fdrawline(x1, y1, x2, y1); + } else { + MM_DARK; + gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 1.5); + } + /* END OUTER OUTLINE */ +} + +/* base flat button */ +static void flat_button(float x1, float y1, float x2, float y2, float asp, int colorid, int flag, int mid) +{ + /* 'mid' arg determines whether the button is in the middle of + * an alignment group or not. 0 = not middle, 1 = is in the middle. + * Done to allow cleaner drawing + */ + + /* *** FLAT TEXT/NUM FIELD *** */ + glShadeModel(GL_FLAT); + if(flag & UI_SELECT) { + if(flag & UI_ACTIVE) M_LGREY; + else M_GREY; + } + else { + if(flag & UI_ACTIVE) M_NUMTEXT_ACT_LIGHT; + else M_NUMTEXT; + } + + glRectf(x1, y1, x2, y2); + /* *** END FLAT TEXT/NUM FIELD *** */ + + /* *** OUTER OUTLINE *** */ + if (mid) { + // we draw full outline, its not AA, and it works better button mouse-over hilite + MM_DARK; + + // left right + fdrawline(x1, y1, x1, y2); + fdrawline(x2, y1, x2, y2); + + // top down + fdrawline(x1, y2, x2, y2); + fdrawline(x1, y1, x2, y1); + } else { + MM_DARK; + gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 1.5); + } + /* END OUTER OUTLINE */ +} + +/* small side double arrow for iconrow */ +static void ui_default_iconrow_arrows(float x1, float y1, float x2, float y2) +{ + glEnable( GL_POLYGON_SMOOTH ); + glEnable( GL_BLEND ); + + glShadeModel(GL_FLAT); + glBegin(GL_TRIANGLES); + glVertex2f((short)x2-2,(short)(y2-(y2-y1)/2)+1); + glVertex2f((short)x2-6,(short)(y2-(y2-y1)/2)+1); + glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2)+4); + glEnd(); + + glBegin(GL_TRIANGLES); + glVertex2f((short)x2-2,(short)(y2-(y2-y1)/2) -1); + glVertex2f((short)x2-6,(short)(y2-(y2-y1)/2) -1); + glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2) -4); + glEnd(); + + glDisable( GL_BLEND ); + glDisable( GL_POLYGON_SMOOTH ); +} + +/* side double arrow for menu */ +static void ui_default_menu_arrows(float x1, float y1, float x2, float y2) +{ + glEnable( GL_POLYGON_SMOOTH ); + glEnable( GL_BLEND ); + + glShadeModel(GL_FLAT); + glBegin(GL_TRIANGLES); + glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2)+1); + glVertex2f((short)x2-12,(short)(y2-(y2-y1)/2)+1); + glVertex2f((short)x2-8,(short)(y2-(y2-y1)/2)+4); + glEnd(); + + glBegin(GL_TRIANGLES); + glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2) -1); + glVertex2f((short)x2-12,(short)(y2-(y2-y1)/2) -1); + glVertex2f((short)x2-8,(short)(y2-(y2-y1)/2) -4); + glEnd(); + + glDisable( GL_BLEND ); + glDisable( GL_POLYGON_SMOOTH ); +} + +/* left/right arrows for number fields */ +static void ui_default_num_arrows(float x1, float y1, float x2, float y2) +{ + if( x2-x1 > 25) { // 25 is a bit arbitrary, but small buttons cant have arrows + + glEnable( GL_POLYGON_SMOOTH ); + glEnable( GL_BLEND ); + + glShadeModel(GL_FLAT); + glBegin(GL_TRIANGLES); + + glVertex2f((short)x1+5,(short)(y2-(y2-y1)/2)); + glVertex2f((short)x1+10,(short)(y2-(y2-y1)/2)+4); + glVertex2f((short)x1+10,(short)(y2-(y2-y1)/2)-4); + glEnd(); + + /* right */ + glShadeModel(GL_FLAT); + glBegin(GL_TRIANGLES); + + glVertex2f((short)x2-5,(short)(y2-(y2-y1)/2)); + glVertex2f((short)x2-10,(short)(y2-(y2-y1)/2)-4); + glVertex2f((short)x2-10,(short)(y2-(y2-y1)/2)+4); + glEnd(); + + glDisable( GL_BLEND ); + glDisable( GL_POLYGON_SMOOTH ); + } +} + +/* changing black/white for TOG3 buts */ +static void ui_tog3_invert(float x1, float y1, float x2, float y2, int seltype) +{ + short alpha = 30; + + if (seltype == 0) { + glEnable(GL_BLEND); + + glColor4ub(0, 0, 0, alpha); + glRectf(x2-6, y1, x2, (y1+(y2-y1)/2)); + + glColor4ub(255, 255, 255, alpha); + glRectf(x2-6, (y1+(y2-y1)/2), x2, y2); + + glDisable(GL_BLEND); + } else { + glEnable(GL_BLEND); + + glColor4ub(255, 255, 255, alpha); + glRectf(x2-6, y1, x2, (y1+(y2-y1)/2)); + + glColor4ub(0, 0, 0, alpha); + glRectf(x2-6, (y1+(y2-y1)/2), x2, y2); + + glDisable(GL_BLEND); + } +} + +/* button/popup menu/iconrow drawing code */ +static void ui_default_button(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) +{ + int align= (flag & UI_BUT_ALIGN); + + if(align) { + + /* *** BOTTOM OUTER SUNKEN EFFECT *** */ + if (!((align == UI_BUT_ALIGN_DOWN) || + (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT)) || + (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT)))) { + glEnable(GL_BLEND); + MM_WHITE_OP; + fdrawline(x1, y1-1, x2, y1-1); + glDisable(GL_BLEND); + } + /* *** END BOTTOM OUTER SUNKEN EFFECT *** */ + + switch(align) { + case UI_BUT_ALIGN_TOP: + uiSetRoundBox(12); + + /* last arg in shaded_button() determines whether the button is in the middle of + * an alignment group or not. 0 = not middle, 1 = is in the middle. + * Done to allow cleaner drawing + */ + + shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + case UI_BUT_ALIGN_DOWN: + uiSetRoundBox(3); + shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + case UI_BUT_ALIGN_LEFT: + + /* RIGHT OUTER SUNKEN EFFECT */ + glEnable(GL_BLEND); + glShadeModel(GL_SMOOTH); + glBegin(GL_LINES); + MM_WHITE_OP; + glVertex2f(x2+1,y1); + MM_WHITE_TR; + glVertex2f(x2+1,y2); + glEnd(); + glDisable(GL_BLEND); + + uiSetRoundBox(6); + shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + case UI_BUT_ALIGN_RIGHT: + + /* LEFT OUTER SUNKEN EFFECT */ + glEnable(GL_BLEND); + glShadeModel(GL_SMOOTH); + glBegin(GL_LINES); + MM_WHITE_OP; + glVertex2f(x1-1,y1); + MM_WHITE_TR; + glVertex2f(x1-1,y2); + glEnd(); + glDisable(GL_BLEND); + + uiSetRoundBox(9); + shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + + case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT: + uiSetRoundBox(1); + shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT: + uiSetRoundBox(2); + shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT: + + /* LEFT OUTER SUNKEN EFFECT */ + glEnable(GL_BLEND); + glShadeModel(GL_SMOOTH); + glBegin(GL_LINES); + MM_WHITE_OP; + glVertex2f(x1-1,y1); + MM_WHITE_TR; + glVertex2f(x1-1,y2); + glEnd(); + glDisable(GL_BLEND); + + uiSetRoundBox(8); + shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT: + + /* RIGHT OUTER SUNKEN EFFECT */ + glEnable(GL_BLEND); + glShadeModel(GL_SMOOTH); + glBegin(GL_LINES); + MM_WHITE_OP; + glVertex2f(x2+1,y1); + MM_WHITE_TR; + glVertex2f(x2+1,y2); + glEnd(); + glDisable(GL_BLEND); + + uiSetRoundBox(4); + shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + + default: + shaded_button(x1, y1, x2, y2, asp, colorid, flag, 1); + break; + } + } + else { + glEnable(GL_BLEND); + glShadeModel(GL_SMOOTH); + + /* BOTTOM OUTER SUNKEN EFFECT */ + MM_WHITE_OP; + fdrawline(x1, y1-1, x2, y1-1); + + /* LEFT OUTER SUNKEN EFFECT */ + glBegin(GL_LINES); + MM_WHITE_OP; + glVertex2f(x1-1,y1); + MM_WHITE_TR; + glVertex2f(x1-1,y2); + glEnd(); + + /* RIGHT OUTER SUNKEN EFFECT */ + glBegin(GL_LINES); + MM_WHITE_OP; + glVertex2f(x2+1,y1); + MM_WHITE_TR; + glVertex2f(x2+1,y2); + glEnd(); + + glDisable(GL_BLEND); + + uiSetRoundBox(15); + shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0); + } + + /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */ + switch(type) { + case ICONROW: + case ICONTEXTROW: + /* DARKENED AREA */ + glEnable(GL_BLEND); + + glColor4ub(0, 0, 0, 30); + glRectf(x2-9, y1, x2, y2); + + glDisable(GL_BLEND); + /* END DARKENED AREA */ + + /* ICONROW DOUBLE-ARROW */ + M_DARK; + ui_default_iconrow_arrows(x1, y1, x2, y2); + /* END ICONROW DOUBLE-ARROW */ + break; + case MENU: + /* DARKENED AREA */ + glEnable(GL_BLEND); + + glColor4ub(0, 0, 0, 30); + glRectf(x2-18, y1, x2, y2); + + glDisable(GL_BLEND); + /* END DARKENED AREA */ + + /* MENU DOUBLE-ARROW */ + M_DARK; + ui_default_menu_arrows(x1, y1, x2, y2); + /* MENU DOUBLE-ARROW */ + break; + } +} + +/* number/text field drawing code */ +static void ui_default_flat(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) +{ + int align= (flag & UI_BUT_ALIGN); + + if(align) { + + /* *** BOTTOM OUTER SUNKEN EFFECT *** */ + if (!((align == UI_BUT_ALIGN_DOWN) || + (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT)) || + (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT)))) { + glEnable(GL_BLEND); + MM_WHITE_OP; + fdrawline(x1, y1-1, x2, y1-1); + glDisable(GL_BLEND); + } + /* *** END BOTTOM OUTER SUNKEN EFFECT *** */ + + switch(align) { + case UI_BUT_ALIGN_TOP: + uiSetRoundBox(12); + + /* last arg in shaded_button() determines whether the button is in the middle of + * an alignment group or not. 0 = not middle, 1 = is in the middle. + * Done to allow cleaner drawing + */ + + flat_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + case UI_BUT_ALIGN_DOWN: + uiSetRoundBox(3); + flat_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + case UI_BUT_ALIGN_LEFT: + + /* RIGHT OUTER SUNKEN EFFECT */ + glEnable(GL_BLEND); + glShadeModel(GL_SMOOTH); + glBegin(GL_LINES); + MM_WHITE_OP; + glVertex2f(x2+1,y1); + MM_WHITE_TR; + glVertex2f(x2+1,y2); + glEnd(); + glDisable(GL_BLEND); + + uiSetRoundBox(6); + flat_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + case UI_BUT_ALIGN_RIGHT: + + /* LEFT OUTER SUNKEN EFFECT */ + glEnable(GL_BLEND); + glShadeModel(GL_SMOOTH); + glBegin(GL_LINES); + MM_WHITE_OP; + glVertex2f(x1-1,y1); + MM_WHITE_TR; + glVertex2f(x1-1,y2); + glEnd(); + glDisable(GL_BLEND); + + uiSetRoundBox(9); + flat_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + + case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT: + uiSetRoundBox(1); + flat_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT: + uiSetRoundBox(2); + flat_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT: + + /* LEFT OUTER SUNKEN EFFECT */ + glEnable(GL_BLEND); + glShadeModel(GL_SMOOTH); + glBegin(GL_LINES); + MM_WHITE_OP; + glVertex2f(x1-1,y1); + MM_WHITE_TR; + glVertex2f(x1-1,y2); + glEnd(); + glDisable(GL_BLEND); + + uiSetRoundBox(8); + flat_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT: + + /* RIGHT OUTER SUNKEN EFFECT */ + glEnable(GL_BLEND); + glShadeModel(GL_SMOOTH); + glBegin(GL_LINES); + MM_WHITE_OP; + glVertex2f(x2+1,y1); + MM_WHITE_TR; + glVertex2f(x2+1,y2); + glEnd(); + glDisable(GL_BLEND); + + uiSetRoundBox(4); + flat_button(x1, y1, x2, y2, asp, colorid, flag, 0); + break; + + default: + flat_button(x1, y1, x2, y2, asp, colorid, flag, 1); + break; + } + } + else { + + glEnable(GL_BLEND); + glShadeModel(GL_SMOOTH); + + /* BOTTOM OUTER SUNKEN EFFECT */ + MM_WHITE_OP; + fdrawline(x1, y1-1, x2, y1-1); + + /* LEFT OUTER SUNKEN EFFECT */ + glBegin(GL_LINES); + MM_WHITE_OP; + glVertex2f(x1-1,y1); + MM_WHITE_TR; + glVertex2f(x1-1,y2); + glEnd(); + + /* RIGHT OUTER SUNKEN EFFECT */ + glBegin(GL_LINES); + MM_WHITE_OP; + glVertex2f(x2+1,y1); + MM_WHITE_TR; + glVertex2f(x2+1,y2); + glEnd(); + + glDisable(GL_BLEND); + + uiSetRoundBox(15); + flat_button(x1, y1, x2, y2, asp, colorid, flag, 0); + } + + /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */ + switch(type) { + case NUM: + case NUMABS: + /* SIDE ARROWS */ + /* left */ + if(flag & UI_SELECT) { + if(flag & UI_ACTIVE) M_DARK; + else M_DARK; + } else { + if(flag & UI_ACTIVE) M_GREY; + else M_LGREY; + } + + ui_default_num_arrows(x1, y1, x2, y2); + /* END SIDE ARROWS */ + } +} + +static void ui_default_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag) +{ + float ymid, yc; + + /* the slider background line */ + ymid= (y1+y2)/2.0; + //yc= 2.5*aspect; // height of center line + yc = 2.3; // height of center line + + if(flag & UI_SELECT) + UI_ThemeColorShade(TH_BUT_NUM, -5); + else { + if(flag & UI_ACTIVE) + UI_ThemeColorShade(TH_BUT_NUM, +35); + else + UI_ThemeColorShade(TH_BUT_NUM, +25); + } + + glRectf(x1, ymid-yc, x2, ymid+yc); + + /* top inner bevel */ + if(flag & UI_SELECT) UI_ThemeColorShade(TH_BUT_NUM, -40); + else UI_ThemeColorShade(TH_BUT_NUM, -5); + fdrawline(x1+1, ymid+yc, x2, ymid+yc); + + /* bottom inner bevel */ + if(flag & UI_SELECT) UI_ThemeColorShade(TH_BUT_NUM, +15); + else UI_ThemeColorShade(TH_BUT_NUM, +45); + fdrawline(x1+1, ymid-yc, x2, ymid-yc); + + + /* the movable slider */ + if(flag & UI_SELECT) UI_ThemeColorShade(TH_BUT_NUM, +80); + else UI_ThemeColorShade(TH_BUT_NUM, -45); + + glShadeModel(GL_SMOOTH); + glBegin(GL_QUADS); + + UI_ThemeColorShade(TH_BUT_NUM, -45); + + glVertex2f(x1, y1+2.5); + glVertex2f(x1+fac, y1+2.5); + + UI_ThemeColor(TH_BUT_NUM); + + glVertex2f(x1+fac, y2-2.5); + glVertex2f(x1, y2-2.5); + + glEnd(); + + + /* slider handle center */ + glShadeModel(GL_SMOOTH); + glBegin(GL_QUADS); + + UI_ThemeColor(TH_BUT_NUM); + glVertex2f(x1+fac-3, y1+2); + glVertex2f(x1+fac, y1+4); + UI_ThemeColorShade(TH_BUT_NUM, +80); + glVertex2f(x1+fac, y2-2); + glVertex2f(x1+fac-3, y2-2); + + glEnd(); + + /* slider handle left bevel */ + UI_ThemeColorShade(TH_BUT_NUM, +70); + fdrawline(x1+fac-3, y2-2, x1+fac-3, y1+2); + + /* slider handle right bevel */ + UI_ThemeColorShade(TH_BUT_NUM, -35); + fdrawline(x1+fac, y2-2, x1+fac, y1+2); + + glShadeModel(GL_FLAT); +} + +/* default theme callback */ +static void ui_draw_default(int type, int colorid, float aspect, float x1, float y1, float x2, float y2, int flag) +{ + + switch(type) { + case TEX: + case IDPOIN: + case NUM: + case NUMABS: + ui_default_flat(type, colorid, aspect, x1, y1, x2, y2, flag); + break; + case ICONROW: + case ICONTEXTROW: + case MENU: + default: + ui_default_button(type, colorid, aspect, x1, y1, x2, y2, flag); + } + +} + + +/* *************** OLDSKOOL THEME ***************** */ + +static void ui_draw_outlineX(float x1, float y1, float x2, float y2, float asp1) +{ + float vec[2]; + + glBegin(GL_LINE_LOOP); + vec[0]= x1+asp1; vec[1]= y1-asp1; + glVertex2fv(vec); + vec[0]= x2-asp1; + glVertex2fv(vec); + vec[0]= x2+asp1; vec[1]= y1+asp1; + glVertex2fv(vec); + vec[1]= y2-asp1; + glVertex2fv(vec); + vec[0]= x2-asp1; vec[1]= y2+asp1; + glVertex2fv(vec); + vec[0]= x1+asp1; + glVertex2fv(vec); + vec[0]= x1-asp1; vec[1]= y2-asp1; + glVertex2fv(vec); + vec[1]= y1+asp1; + glVertex2fv(vec); + glEnd(); + +} + + +static void ui_draw_oldskool(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) +{ + /* paper */ + if(flag & UI_SELECT) { + if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, -40); + else UI_ThemeColorShade(colorid, -30); + } + else { + if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, +30); + else UI_ThemeColorShade(colorid, +20); + } + + glRectf(x1+1, y1+1, x2-1, y2-1); + + x1+= asp; + x2-= asp; + y1+= asp; + y2-= asp; + + /* below */ + if(flag & UI_SELECT) UI_ThemeColorShade(colorid, 0); + else UI_ThemeColorShade(colorid, -30); + fdrawline(x1, y1, x2, y1); + + /* right */ + fdrawline(x2, y1, x2, y2); + + /* top */ + if(flag & UI_SELECT) UI_ThemeColorShade(colorid, -30); + else UI_ThemeColorShade(colorid, 0); + fdrawline(x1, y2, x2, y2); + + /* left */ + fdrawline(x1, y1, x1, y2); + + /* outline */ + glColor3ub(0,0,0); + ui_draw_outlineX(x1, y1, x2, y2, asp); + + + /* special type decorations */ + switch(type) { + case NUM: + case NUMABS: + if(flag & UI_SELECT) UI_ThemeColorShade(colorid, -60); + else UI_ThemeColorShade(colorid, -30); + ui_default_num_arrows(x1, y1, x2, y2); + break; + + case ICONROW: + case ICONTEXTROW: + if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, 0); + else UI_ThemeColorShade(colorid, -10); + glRectf(x2-9, y1+asp, x2-asp, y2-asp); + + UI_ThemeColorShade(colorid, -50); + ui_default_iconrow_arrows(x1, y1, x2, y2); + break; + + case MENU: + if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, 0); + else UI_ThemeColorShade(colorid, -10); + glRectf(x2-17, y1+asp, x2-asp, y2-asp); + + UI_ThemeColorShade(colorid, -50); + ui_default_menu_arrows(x1, y1, x2, y2); + break; + } + +} + +/* *************** BASIC ROUNDED THEME ***************** */ + +static void round_button(float x1, float y1, float x2, float y2, float asp, + int colorid, int round, int menudeco, int curshade) +{ + float rad; + char col[4]; + + rad= (y2-y1)/2.0; + if(rad>7.0) rad= 7.0; + + uiSetRoundBox(round); + gl_round_box(GL_POLYGON, x1, y1, x2, y2, rad); + + if(menudeco) { + uiSetRoundBox(round & ~9); + UI_ThemeColorShade(colorid, curshade-20); + gl_round_box(GL_POLYGON, x2-menudeco, y1, x2, y2, rad); + } + + /* fake AA */ + uiSetRoundBox(round); + glEnable( GL_BLEND ); + + UI_GetThemeColor3ubv(colorid, col); + + if(col[0]<100) col[0]= 0; else col[0]-= 100; + if(col[1]<100) col[1]= 0; else col[1]-= 100; + if(col[2]<100) col[2]= 0; else col[2]-= 100; + col[3]= 80; + glColor4ubv((GLubyte *)col); + gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, rad - asp); + gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, rad + asp); + col[3]= 180; + glColor4ubv((GLubyte *)col); + gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, rad); + + glDisable( GL_BLEND ); +} + +/* button in midst of alignment row */ +static void round_button_mid(float x1, float y1, float x2, float y2, float asp, + int colorid, int align, int menudeco, int curshade) +{ + glRectf(x1, y1, x2, y2); + + if(menudeco) { + UI_ThemeColorShade(colorid, curshade-20); + glRectf(x2-menudeco, y1, x2, y2); + } + + UI_ThemeColorBlendShade(colorid, TH_BACK, 0.5, -70); + // we draw full outline, its not AA, and it works better button mouse-over hilite + + // left right + fdrawline(x1, y1, x1, y2); + fdrawline(x2, y1, x2, y2); + + // top down + fdrawline(x1, y2, x2, y2); + fdrawline(x1, y1, x2, y1); +} + +static void ui_draw_round(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) +{ + int align= (flag & UI_BUT_ALIGN); + int curshade= 0, menudeco= 0; + + if(type==ICONROW || type==ICONTEXTROW) menudeco= 9; + else if((type==MENU || type==BLOCK) && x2-x1>24) menudeco= 16; + + /* paper */ + if(flag & UI_SELECT) { + if(flag & UI_ACTIVE) curshade= -40; + else curshade= -30; + } + else { + if(flag & UI_ACTIVE) curshade= 30; + else curshade= +20; + } + + UI_ThemeColorShade(colorid, curshade); + + if(align) { + switch(align) { + case UI_BUT_ALIGN_TOP: + round_button(x1, y1, x2, y2, asp, colorid, 12, menudeco, curshade); + break; + case UI_BUT_ALIGN_DOWN: + round_button(x1, y1, x2, y2, asp, colorid, 3, menudeco, curshade); + break; + case UI_BUT_ALIGN_LEFT: + round_button(x1, y1, x2, y2, asp, colorid, 6, menudeco, curshade); + break; + case UI_BUT_ALIGN_RIGHT: + round_button(x1, y1, x2, y2, asp, colorid, 9, menudeco, curshade); + break; + + case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT: + round_button(x1, y1, x2, y2, asp, colorid, 1, menudeco, curshade); + break; + case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT: + round_button(x1, y1, x2, y2, asp, colorid, 2, menudeco, curshade); + break; + case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT: + round_button(x1, y1, x2, y2, asp, colorid, 8, menudeco, curshade); + break; + case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT: + round_button(x1, y1, x2, y2, asp, colorid, 4, menudeco, curshade); + break; + + default: + round_button_mid(x1, y1, x2, y2, asp, colorid, align, menudeco, curshade); + break; + } + } + else { + round_button(x1, y1, x2, y2, asp, colorid, 15, menudeco, curshade); + } + + /* special type decorations */ + switch(type) { + case NUM: + case NUMABS: + UI_ThemeColorShade(colorid, curshade-60); + ui_default_num_arrows(x1, y1, x2, y2); + break; + + case ICONROW: + case ICONTEXTROW: + UI_ThemeColorShade(colorid, curshade-60); + ui_default_iconrow_arrows(x1, y1, x2, y2); + break; + + case MENU: + case BLOCK: + UI_ThemeColorShade(colorid, curshade-60); + ui_default_menu_arrows(x1, y1, x2, y2); + break; + } +} + +/* *************** MINIMAL THEME ***************** */ + +// theme can define an embosfunc and sliderfunc, text+icon drawing is standard, no theme. + + + +/* super minimal button as used in logic menu */ +static void ui_draw_minimal(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) +{ + /* too much space between buttons */ + + if (type==TEX || type==IDPOIN) { + x1+= asp; + x2-= (asp*2); + //y1+= asp; + y2-= asp; + } else { + /* Less space between buttons looks nicer */ + y2-= asp; + x2-= asp; + } + + /* paper */ + if(flag & UI_SELECT) { + if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, -40); + else UI_ThemeColorShade(colorid, -30); + } + else { + if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, +20); + else UI_ThemeColorShade(colorid, +10); + } + + glRectf(x1, y1, x2, y2); + + if (type==TEX || type==IDPOIN) { + UI_ThemeColorShade(colorid, -60); + + /* top */ + fdrawline(x1, y2, x2, y2); + /* left */ + fdrawline(x1, y1, x1, y2); + + + /* text underline, some */ + UI_ThemeColorShade(colorid, +50); + glEnable(GL_LINE_STIPPLE); + glLineStipple(1, 0x8888); + fdrawline(x1+(asp*2), y1+(asp*3), x2-(asp*2), y1+(asp*3)); + glDisable(GL_LINE_STIPPLE); + + + UI_ThemeColorShade(colorid, +60); + /* below */ + fdrawline(x1, y1, x2, y1); + /* right */ + fdrawline(x2, y1, x2, y2); + + } else { + if(flag & UI_SELECT) { + UI_ThemeColorShade(colorid, -60); + + /* top */ + fdrawline(x1, y2, x2, y2); + /* left */ + fdrawline(x1, y1, x1, y2); + UI_ThemeColorShade(colorid, +40); + + /* below */ + fdrawline(x1, y1, x2, y1); + /* right */ + fdrawline(x2, y1, x2, y2); + } + else { + UI_ThemeColorShade(colorid, +40); + + /* top */ + fdrawline(x1, y2, x2, y2); + /* left */ + fdrawline(x1, y1, x1, y2); + + UI_ThemeColorShade(colorid, -60); + /* below */ + fdrawline(x1, y1, x2, y1); + /* right */ + fdrawline(x2, y1, x2, y2); + } + } + + /* special type decorations */ + switch(type) { + case NUM: + case NUMABS: + if(flag & UI_SELECT) UI_ThemeColorShade(colorid, -60); + else UI_ThemeColorShade(colorid, -30); + ui_default_num_arrows(x1, y1, x2, y2); + break; + + case ICONROW: + case ICONTEXTROW: + if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, 0); + else UI_ThemeColorShade(colorid, -10); + glRectf(x2-9, y1+asp, x2-asp, y2-asp); + + UI_ThemeColorShade(colorid, -50); + ui_default_iconrow_arrows(x1, y1, x2, y2); + break; + + case MENU: + case BLOCK: + if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, 0); + else UI_ThemeColorShade(colorid, -10); + glRectf(x2-17, y1+asp, x2-asp, y2-asp); + + UI_ThemeColorShade(colorid, -50); + ui_default_menu_arrows(x1, y1, x2, y2); + break; + } + + +} + + +/* fac is the slider handle position between x1 and x2 */ +static void ui_draw_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag) +{ + float ymid, yc; + + /* the slider background line */ + ymid= (y1+y2)/2.0; + yc= 1.7*aspect; + + if(flag & UI_ACTIVE) + UI_ThemeColorShade(colorid, -50); + else + UI_ThemeColorShade(colorid, -40); + + /* left part */ + glRectf(x1, ymid-2.0*yc, x1+fac, ymid+2.0*yc); + /* right part */ + glRectf(x1+fac, ymid-yc, x2, ymid+yc); + + /* the movable slider */ + + UI_ThemeColorShade(colorid, +70); + glRectf(x1+fac-aspect, ymid-2.0*yc, x1+fac+aspect, ymid+2.0*yc); + +} + +/* ************** STANDARD MENU DRAWING FUNCTION ************* */ + + +static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha) +{ + glEnable(GL_BLEND); + glShadeModel(GL_SMOOTH); + + /* right quad */ + glBegin(GL_POLYGON); + glColor4ub(0, 0, 0, alpha); + glVertex2f(maxx, miny); + glVertex2f(maxx, maxy-shadsize); + glColor4ub(0, 0, 0, 0); + glVertex2f(maxx+shadsize, maxy-shadsize-shadsize); + glVertex2f(maxx+shadsize, miny); + glEnd(); + + /* corner shape */ + glBegin(GL_POLYGON); + glColor4ub(0, 0, 0, alpha); + glVertex2f(maxx, miny); + glColor4ub(0, 0, 0, 0); + glVertex2f(maxx+shadsize, miny); + glVertex2f(maxx+0.7*shadsize, miny-0.7*shadsize); + glVertex2f(maxx, miny-shadsize); + glEnd(); + + /* bottom quad */ + glBegin(GL_POLYGON); + glColor4ub(0, 0, 0, alpha); + glVertex2f(minx+shadsize, miny); + glVertex2f(maxx, miny); + glColor4ub(0, 0, 0, 0); + glVertex2f(maxx, miny-shadsize); + glVertex2f(minx+shadsize+shadsize, miny-shadsize); + glEnd(); + + glDisable(GL_BLEND); + glShadeModel(GL_FLAT); +} + +void uiDrawBoxShadow(unsigned char alpha, float minx, float miny, float maxx, float maxy) +{ + /* accumulated outline boxes to make shade not linear, is more pleasant */ + ui_shadowbox(minx, miny, maxx, maxy, 6.0, (30*alpha)>>8); + ui_shadowbox(minx, miny, maxx, maxy, 4.0, (70*alpha)>>8); + ui_shadowbox(minx, miny, maxx, maxy, 2.0, (100*alpha)>>8); + +} + +// background for pulldowns, pullups, and other drawing temporal menus.... +// has to be made themable still (now only color) + +void uiDrawMenuBox(float minx, float miny, float maxx, float maxy, short flag) +{ + char col[4]; + UI_GetThemeColor4ubv(TH_MENU_BACK, col); + + if( (flag & UI_BLOCK_NOSHADOW)==0) { + /* accumulated outline boxes to make shade not linear, is more pleasant */ + ui_shadowbox(minx, miny, maxx, maxy, 6.0, (30*col[3])>>8); + ui_shadowbox(minx, miny, maxx, maxy, 4.0, (70*col[3])>>8); + ui_shadowbox(minx, miny, maxx, maxy, 2.0, (100*col[3])>>8); + + glEnable(GL_BLEND); + glColor4ubv((GLubyte *)col); + glRectf(minx-1, miny, minx, maxy); // 1 pixel on left, to distinguish sublevel menus + } + glEnable(GL_BLEND); + glColor4ubv((GLubyte *)col); + glRectf(minx, miny, maxx, maxy); + glDisable(GL_BLEND); +} + + + +/* pulldown menu item */ +static void ui_draw_pulldown_item(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) +{ + char col[4]; + + UI_GetThemeColor4ubv(TH_MENU_BACK, col); + if(col[3]!=255) { + glEnable(GL_BLEND); + } + + if((flag & UI_ACTIVE) && type!=LABEL) { + UI_ThemeColor4(TH_MENU_HILITE); + glRectf(x1, y1, x2, y2); + + + } else { + UI_ThemeColor4(colorid); // is set at TH_MENU_ITEM when pulldown opened. + glRectf(x1, y1, x2, y2); + } + + glDisable(GL_BLEND); +} + +/* pulldown menu calling button */ +static void ui_draw_pulldown_round(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) +{ + + if(flag & UI_ACTIVE) { + UI_ThemeColor(TH_MENU_HILITE); + + uiSetRoundBox(15); + gl_round_box(GL_POLYGON, x1, y1+3, x2, y2-3, 7.0); + + glEnable( GL_LINE_SMOOTH ); + glEnable( GL_BLEND ); + gl_round_box(GL_LINE_LOOP, x1, y1+3, x2, y2-3, 7.0); + glDisable( GL_LINE_SMOOTH ); + glDisable( GL_BLEND ); + + } else { + UI_ThemeColor(colorid); // is set at TH_MENU_ITEM when pulldown opened. + glRectf(x1-1, y1+2, x2+1, y2-2); + } + +} + + +/* ************** TEXT AND ICON DRAWING FUNCTIONS ************* */ + + + +/* draws text and icons for buttons */ +static void ui_draw_text_icon(uiBut *but) +{ + float x; + int len; + char *cpoin; + short t, pos, ch; + short selsta_tmp, selend_tmp, selsta_draw, selwidth_draw; + + /* check for button text label */ + if (but->type == ICONTEXTROW) { + ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd), 0); + } + else { + + /* text button selection and cursor */ + if(but->editstr && but->pos != -1) { + + if ((but->selend - but->selsta) > 0) { + /* text button selection */ + selsta_tmp = but->selsta + strlen(but->str); + selend_tmp = but->selend + strlen(but->str); + + if(but->drawstr[0]!=0) { + ch= but->drawstr[selsta_tmp]; + but->drawstr[selsta_tmp]= 0; + + selsta_draw = but->aspect*UI_GetStringWidth(but->font, but->drawstr+but->ofs, ui_translate_buttons()) + 3; + + but->drawstr[selsta_tmp]= ch; + + + ch= but->drawstr[selend_tmp]; + but->drawstr[selend_tmp]= 0; + + selwidth_draw = but->aspect*UI_GetStringWidth(but->font, but->drawstr+but->ofs, ui_translate_buttons()) + 3; + + but->drawstr[selend_tmp]= ch; + + UI_ThemeColor(TH_BUT_TEXTFIELD_HI); + glRects(but->x1+selsta_draw+1, but->y1+2, but->x1+selwidth_draw+1, but->y2-2); + } + } else { + /* text cursor */ + pos= but->pos+strlen(but->str); + if(pos >= but->ofs) { + if(but->drawstr[0]!=0) { + ch= but->drawstr[pos]; + but->drawstr[pos]= 0; + + t= but->aspect*UI_GetStringWidth(but->font, but->drawstr+but->ofs, ui_translate_buttons()) + 3; + + but->drawstr[pos]= ch; + } + else t= 3; + + glColor3ub(255,0,0); + glRects(but->x1+t, but->y1+2, but->x1+t+2, but->y2-2); + } + } + } + + if(but->type==BUT_TOGDUAL) { + int dualset= 0; + if(but->pointype==SHO) + dualset= BTST( *(((short *)but->poin)+1), but->bitnr); + else if(but->pointype==INT) + dualset= BTST( *(((int *)but->poin)+1), but->bitnr); + + ui_draw_icon(but, ICON_DOT, dualset?0:-100); + } + + if(but->drawstr[0]!=0) { + int transopts; + int tog3= 0; + + // cut string in 2 parts + cpoin= strchr(but->drawstr, '|'); + if(cpoin) *cpoin= 0; + + /* If there's an icon too (made with uiDefIconTextBut) then draw the icon + and offset the text label to accomodate it */ + + /* XXX 2.50 need interface_icons.c */ +#if 0 + if ( (but->flag & UI_HAS_ICON) && (but->flag & UI_ICON_LEFT) ) { + ui_draw_icon(but, but->icon, 0); + + if(but->editstr || (but->flag & UI_TEXT_LEFT)) x= but->x1 + but->aspect*UI_icon_get_width(but->icon)+5.0; + else x= (but->x1+but->x2-but->strwidth+1)/2.0; + } + else +#endif + { + if(but->editstr || (but->flag & UI_TEXT_LEFT)) x= but->x1+4.0; + else x= (but->x1+but->x2-but->strwidth+1)/2.0; + } + + /* tog3 button exception; draws with glColor! */ + if(but->type==TOG3 && (but->flag & UI_SELECT)) { + + if( but->pointype==CHA ) { + if( BTST( *(but->poin+2), but->bitnr )) tog3= 1; + } + else if( but->pointype ==SHO ) { + short *sp= (short *)but->poin; + if( BTST( sp[1], but->bitnr )) tog3= 1; + } + + ui_tog3_invert(but->x1,but->y1,but->x2,but->y2, tog3); + if (tog3) glColor3ub(255, 255, 0); + } + + /* text color, with pulldown item exception */ + if(tog3); // color already set + else if(but->dt==UI_EMBOSSP) { + if((but->flag & (UI_SELECT|UI_ACTIVE)) && but->type!=LABEL) { // LABEL = title in pulldowns + UI_ThemeColor(TH_MENU_TEXT_HI); + } else { + UI_ThemeColor(TH_MENU_TEXT); + } + } + else { + if(but->flag & UI_SELECT) { + UI_ThemeColor(TH_BUT_TEXT_HI); + } else { + UI_ThemeColor(TH_BUT_TEXT); + } + } + + /* LABEL button exception */ + if(but->type==LABEL && but->min!=0.0) UI_ThemeColor(TH_BUT_TEXT_HI); + + ui_rasterpos_safe(x, (but->y1+but->y2- 9.0)/2.0, but->aspect); + if(but->type==IDPOIN) transopts= 0; // no translation, of course! + else transopts= ui_translate_buttons(); + + #ifdef INTERNATIONAL + if (but->type == FTPREVIEW) + FTF_DrawNewFontString (but->drawstr+but->ofs, FTF_INPUT_UTF8); + else + UI_DrawString(but->font, but->drawstr+but->ofs, transopts); + #else + UI_DrawString(but->font, but->drawstr+but->ofs, transopts); + #endif + + /* part text right aligned */ + if(cpoin) { + len= UI_GetStringWidth(but->font, cpoin+1, ui_translate_buttons()); + ui_rasterpos_safe( but->x2 - len*but->aspect-3, (but->y1+but->y2- 9.0)/2.0, but->aspect); + UI_DrawString(but->font, cpoin+1, ui_translate_buttons()); + *cpoin= '|'; + } + } + /* if there's no text label, then check to see if there's an icon only and draw it */ + else if( but->flag & UI_HAS_ICON ) { + ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd), 0); + } + } +} + +static void ui_draw_but_COL(uiBut *but) +{ + float *fp; + char colr, colg, colb; + + if( but->pointype==FLO ) { + fp= (float *)but->poin; + colr= floor(255.0*fp[0]+0.5); + colg= floor(255.0*fp[1]+0.5); + colb= floor(255.0*fp[2]+0.5); + } + else { + char *cp= (char *)but->poin; + colr= cp[0]; + colg= cp[1]; + colb= cp[2]; + } + + /* exception... hrms, but can't simply use the emboss callback for this now. */ + /* this button type needs review, and nice integration with rest of API here */ + /* XXX 2.50 bad U global access */ + if(but->embossfunc == ui_draw_round) { + char *cp= UI_ThemeGetColorPtr(U.themes.first, 0, TH_CUSTOM); + cp[0]= colr; cp[1]= colg; cp[2]= colb; + but->flag &= ~UI_SELECT; + but->embossfunc(but->type, TH_CUSTOM, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag); + } + else + { + + glColor3ub(colr, colg, colb); + glRectf((but->x1), (but->y1), (but->x2), (but->y2)); + glColor3ub(0, 0, 0); + fdrawbox((but->x1), (but->y1), (but->x2), (but->y2)); + } +} + +/* draws in resolution of 20x4 colors */ +static void ui_draw_but_HSVCUBE(uiBut *but) +{ + int a; + float h,s,v; + float dx, dy, sx1, sx2, sy, x, y; + float col0[4][3]; // left half, rect bottom to top + float col1[4][3]; // right half, rect bottom to top + + h= but->hsv[0]; + s= but->hsv[1]; + v= but->hsv[2]; + + /* draw series of gouraud rects */ + glShadeModel(GL_SMOOTH); + + if(but->a1==0) { // H and V vary + hsv_to_rgb(0.0, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(0.0, s, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]); + x= h; y= v; + } + else if(but->a1==1) { // H and S vary + hsv_to_rgb(0.0, 0.0, v, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(0.0, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]); + x= h; y= s; + } + else if(but->a1==2) { // S and V vary + hsv_to_rgb(h, 0.0, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(h, 1.0, 0.0, &col1[3][0], &col1[3][1], &col1[3][2]); + x= v; y= s; + } + else { // only hue slider + hsv_to_rgb(0.0, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]); + VECCOPY(col1[1], col1[0]); + VECCOPY(col1[2], col1[0]); + VECCOPY(col1[3], col1[0]); + x= h; y= 0.5; + } + + for(dx=0.0; dx<1.0; dx+= 0.05) { + // previous color + VECCOPY(col0[0], col1[0]); + VECCOPY(col0[1], col1[1]); + VECCOPY(col0[2], col1[2]); + VECCOPY(col0[3], col1[3]); + + // new color + if(but->a1==0) { // H and V vary + hsv_to_rgb(dx, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(dx, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(dx, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(dx, s, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]); + } + else if(but->a1==1) { // H and S vary + hsv_to_rgb(dx, 0.0, v, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(dx, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(dx, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(dx, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]); + } + else if(but->a1==2) { // S and V vary + hsv_to_rgb(h, 0.0, dx, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(h, 1.0, dx, &col1[3][0], &col1[3][1], &col1[3][2]); + } + else { // only H + hsv_to_rgb(dx, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]); + VECCOPY(col1[1], col1[0]); + VECCOPY(col1[2], col1[0]); + VECCOPY(col1[3], col1[0]); + } + + // rect + sx1= but->x1 + dx*(but->x2-but->x1); + sx2= but->x1 + (dx+0.05)*(but->x2-but->x1); + sy= but->y1; + dy= (but->y2-but->y1)/3.0; + + glBegin(GL_QUADS); + for(a=0; a<3; a++, sy+=dy) { + glColor3fv(col0[a]); + glVertex2f(sx1, sy); + + glColor3fv(col1[a]); + glVertex2f(sx2, sy); + + glColor3fv(col1[a+1]); + glVertex2f(sx2, sy+dy); + + glColor3fv(col0[a+1]); + glVertex2f(sx1, sy+dy); + } + glEnd(); + } + + glShadeModel(GL_FLAT); + + /* cursor */ + x= but->x1 + x*(but->x2-but->x1); + y= but->y1 + y*(but->y2-but->y1); + CLAMP(x, but->x1+3.0, but->x2-3.0); + CLAMP(y, but->y1+3.0, but->y2-3.0); + + fdrawXORcirc(x, y, 3.1); + + /* outline */ + glColor3ub(0, 0, 0); + fdrawbox((but->x1), (but->y1), (but->x2), (but->y2)); +} + +#ifdef INTERNATIONAL +static void ui_draw_but_CHARTAB(uiBut *but) +{ + /* XXX 2.50 bad global access */ +#if 0 + /* Some local variables */ + float sx, sy, ex, ey; + float width, height; + float butw, buth; + int x, y, cs; + wchar_t wstr[2]; + unsigned char ustr[16]; + PackedFile *pf; + int result = 0; + int charmax = G.charmax; + + /* font in use. There are TTF and non-TTF fonts */ + if(!strcmp(G.selfont->name, "")) + { + if(G.ui_international == TRUE) + { + charmax = 0xff; + } + else + { + charmax = 0xff; + } + } + + /* Category list exited without selecting the area */ + if(G.charmax == 0) + charmax = G.charmax = 0xffff; + + /* Calculate the size of the button */ + width = abs(but->x2 - but->x1); + height = abs(but->y2 - but->y1); + + butw = floor(width / 12); + buth = floor(height / 6); + + /* Initialize variables */ + sx = but->x1; + ex = but->x1 + butw; + sy = but->y1 + height - buth; + ey = but->y1 + height; + + cs = G.charstart; + + /* Set the font, in case it is not font */ + if(G.selfont && strcmp(G.selfont->name, "")) + { + char tmpStr[256]; + + // Is the font file packed, if so then use the packed file + if(G.selfont->packedfile) + { + pf = G.selfont->packedfile; + FTF_SetFont(pf->data, pf->size, 14.0); + } + else + { + int err; + + strcpy(tmpStr, G.selfont->name); + BLI_convertstringcode(tmpStr, G.sce); + err = FTF_SetFont((unsigned char *)tmpStr, 0, 14.0); + } + } + else + { + if(G.ui_international == TRUE) + { + FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, 14.0); + } + } + + /* Start drawing the button itself */ + glShadeModel(GL_SMOOTH); + + glColor3ub(200, 200, 200); + glRectf((but->x1), (but->y1), (but->x2), (but->y2)); + + glColor3ub(0, 0, 0); + for(y = 0; y < 6; y++) + { + // Do not draw more than the category allows + if(cs > charmax) break; + + for(x = 0; x < 12; x++) + { + // Do not draw more than the category allows + if(cs > charmax) break; + + // Draw one grid cell + glBegin(GL_LINE_LOOP); + glVertex2f(sx, sy); + glVertex2f(ex, sy); + glVertex2f(ex, ey); + glVertex2f(sx, ey); + glEnd(); + + // Draw character inside the cell + memset(wstr, 0, sizeof(wchar_t)*2); + memset(ustr, 0, 16); + + // Set the font to be either unicode or + wstr[0] = cs; + if(strcmp(G.selfont->name, "")) + { + wcs2utf8s((char *)ustr, (wchar_t *)wstr); + } + else + { + if(G.ui_international == TRUE) + { + wcs2utf8s((char *)ustr, (wchar_t *)wstr); + } + else + { + ustr[0] = cs; + ustr[1] = 0; + } + } + + if((G.selfont && strcmp(G.selfont->name, "")) || (G.selfont && !strcmp(G.selfont->name, "") && G.ui_international == TRUE)) + { + float wid; + float llx, lly, llz, urx, ury, urz; + float dx, dy; + float px, py; + + // Calculate the position + wid = FTF_GetStringWidth((char *) ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8); + FTF_GetBoundingBox((char *) ustr, &llx,&lly,&llz,&urx,&ury,&urz, FTF_USE_GETTEXT | FTF_INPUT_UTF8); + dx = urx-llx; + dy = ury-lly; + + // This isn't fully functional since the but->aspect isn't working like I suspected + px = sx + ((butw/but->aspect)-dx)/2; + py = sy + ((buth/but->aspect)-dy)/2; + + // Set the position and draw the character + ui_rasterpos_safe(px, py, but->aspect); + FTF_DrawString((char *) ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8); + } + else + { + ui_rasterpos_safe(sx + butw/2, sy + buth/2, but->aspect); + UI_DrawString(but->font, (char *) ustr, 0); + } + + // Calculate the next position and character + sx += butw; ex +=butw; + cs++; + } + /* Add the y position and reset x position */ + sy -= buth; + ey -= buth; + sx = but->x1; + ex = but->x1 + butw; + } + glShadeModel(GL_FLAT); + + /* Return Font Settings to original */ + if(U.fontsize && U.fontname[0]) + { + result = FTF_SetFont((unsigned char *)U.fontname, 0, U.fontsize); + } + else if (U.fontsize) + { + result = FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, U.fontsize); + } + + if (result == 0) + { + result = FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, 11); + } + + /* resets the font size */ + if(G.ui_international == TRUE) + { + uiSetCurFont(but->block, UI_HELV); + } +#endif +} + +#endif // INTERNATIONAL + +static void ui_draw_but_COLORBAND(uiBut *but) +{ + ColorBand *coba; + CBData *cbd; + float x1, y1, sizex, sizey; + float dx, v3[2], v1[2], v2[2], v1a[2], v2a[2]; + int a; + + coba= (ColorBand *)(but->editcoba? but->editcoba: but->poin); + if(coba==NULL) return; + + x1= but->x1; + y1= but->y1; + sizex= but->x2-x1; + sizey= but->y2-y1; + + /* first background, to show tranparency */ + dx= sizex/12.0; + v1[0]= x1; + for(a=0; a<12; a++) { + if(a & 1) glColor3f(0.3, 0.3, 0.3); else glColor3f(0.8, 0.8, 0.8); + glRectf(v1[0], y1, v1[0]+dx, y1+0.5*sizey); + if(a & 1) glColor3f(0.8, 0.8, 0.8); else glColor3f(0.3, 0.3, 0.3); + glRectf(v1[0], y1+0.5*sizey, v1[0]+dx, y1+sizey); + v1[0]+= dx; + } + + glShadeModel(GL_SMOOTH); + glEnable(GL_BLEND); + + cbd= coba->data; + + v1[0]= v2[0]= x1; + v1[1]= y1; + v2[1]= y1+sizey; + + glBegin(GL_QUAD_STRIP); + + glColor4fv( &cbd->r ); + glVertex2fv(v1); glVertex2fv(v2); + + for(a=0; atot; a++, cbd++) { + + v1[0]=v2[0]= x1+ cbd->pos*sizex; + + glColor4fv( &cbd->r ); + glVertex2fv(v1); glVertex2fv(v2); + } + + v1[0]=v2[0]= x1+ sizex; + glVertex2fv(v1); glVertex2fv(v2); + + glEnd(); + glShadeModel(GL_FLAT); + glDisable(GL_BLEND); + + /* outline */ + v1[0]= x1; v1[1]= y1; + + cpack(0x0); + glBegin(GL_LINE_LOOP); + glVertex2fv(v1); + v1[0]+= sizex; + glVertex2fv(v1); + v1[1]+= sizey; + glVertex2fv(v1); + v1[0]-= sizex; + glVertex2fv(v1); + glEnd(); + + + /* help lines */ + v1[0]= v2[0]=v3[0]= x1; + v1[1]= y1; + v1a[1]= y1+0.25*sizey; + v2[1]= y1+0.5*sizey; + v2a[1]= y1+0.75*sizey; + v3[1]= y1+sizey; + + + cbd= coba->data; + glBegin(GL_LINES); + for(a=0; atot; a++, cbd++) { + v1[0]=v2[0]=v3[0]=v1a[0]=v2a[0]= x1+ cbd->pos*sizex; + + if(a==coba->cur) { + glColor3ub(0, 0, 0); + glVertex2fv(v1); + glVertex2fv(v3); + glEnd(); + + setlinestyle(2); + glBegin(GL_LINES); + glColor3ub(255, 255, 255); + glVertex2fv(v1); + glVertex2fv(v3); + glEnd(); + setlinestyle(0); + glBegin(GL_LINES); + + /* glColor3ub(0, 0, 0); + glVertex2fv(v1); + glVertex2fv(v1a); + glColor3ub(255, 255, 255); + glVertex2fv(v1a); + glVertex2fv(v2); + glColor3ub(0, 0, 0); + glVertex2fv(v2); + glVertex2fv(v2a); + glColor3ub(255, 255, 255); + glVertex2fv(v2a); + glVertex2fv(v3); + */ + } + else { + glColor3ub(0, 0, 0); + glVertex2fv(v1); + glVertex2fv(v2); + + glColor3ub(255, 255, 255); + glVertex2fv(v2); + glVertex2fv(v3); + } + } + glEnd(); +} + +static void ui_draw_but_NORMAL(uiBut *but) +{ + static GLuint displist=0; + int a, old[8]; + GLfloat diff[4], diffn[4]={1.0f, 1.0f, 1.0f, 1.0f}; + float vec0[4]={0.0f, 0.0f, 0.0f, 0.0f}; + float dir[4], size; + + /* store stuff */ + glGetMaterialfv(GL_FRONT, GL_DIFFUSE, diff); + + /* backdrop */ + UI_ThemeColor(TH_BUT_NEUTRAL); + uiSetRoundBox(15); + gl_round_box(GL_POLYGON, but->x1, but->y1, but->x2, but->y2, 5.0f); + + /* sphere color */ + glMaterialfv(GL_FRONT, GL_DIFFUSE, diffn); + glCullFace(GL_BACK); glEnable(GL_CULL_FACE); + + /* disable blender light */ + for(a=0; a<8; a++) { + old[a]= glIsEnabled(GL_LIGHT0+a); + glDisable(GL_LIGHT0+a); + } + + /* own light */ + glEnable(GL_LIGHT7); + glEnable(GL_LIGHTING); + + VECCOPY(dir, (float *)but->poin); + dir[3]= 0.0f; /* glLight needs 4 args, 0.0 is sun */ + glLightfv(GL_LIGHT7, GL_POSITION, dir); + glLightfv(GL_LIGHT7, GL_DIFFUSE, diffn); + glLightfv(GL_LIGHT7, GL_SPECULAR, vec0); + glLightf(GL_LIGHT7, GL_CONSTANT_ATTENUATION, 1.0f); + glLightf(GL_LIGHT7, GL_LINEAR_ATTENUATION, 0.0f); + + /* transform to button */ + glPushMatrix(); + glTranslatef(but->x1 + 0.5f*(but->x2-but->x1), but->y1+ 0.5f*(but->y2-but->y1), 0.0f); + size= (but->x2-but->x1)/200.f; + glScalef(size, size, size); + + if(displist==0) { + GLUquadricObj *qobj; + + displist= glGenLists(1); + glNewList(displist, GL_COMPILE_AND_EXECUTE); + + qobj= gluNewQuadric(); + gluQuadricDrawStyle(qobj, GLU_FILL); + glShadeModel(GL_SMOOTH); + gluSphere( qobj, 100.0, 32, 24); + glShadeModel(GL_FLAT); + gluDeleteQuadric(qobj); + + glEndList(); + } + else glCallList(displist); + + /* restore */ + glPopMatrix(); + glDisable(GL_LIGHTING); + glDisable(GL_CULL_FACE); + glMaterialfv(GL_FRONT, GL_DIFFUSE, diff); + + glDisable(GL_LIGHT7); + + /* enable blender light */ + for(a=0; a<8; a++) { + if(old[a]) + glEnable(GL_LIGHT0+a); + } +} + +static void ui_draw_but_curve_grid(uiBut *but, float zoomx, float zoomy, float offsx, float offsy, float step) +{ + float dx, dy, fx, fy; + + glBegin(GL_LINES); + dx= step*zoomx; + fx= but->x1 + zoomx*(-offsx); + if(fx > but->x1) fx -= dx*( floor(fx-but->x1)); + while(fx < but->x2) { + glVertex2f(fx, but->y1); + glVertex2f(fx, but->y2); + fx+= dx; + } + + dy= step*zoomy; + fy= but->y1 + zoomy*(-offsy); + if(fy > but->y1) fy -= dy*( floor(fy-but->y1)); + while(fy < but->y2) { + glVertex2f(but->x1, fy); + glVertex2f(but->x2, fy); + fy+= dy; + } + glEnd(); + +} + +static void ui_draw_but_CURVE(uiBut *but) +{ + CurveMapping *cumap; + CurveMap *cuma; + CurveMapPoint *cmp; + float fx, fy, dx, dy, fac[2], zoomx, zoomy, offsx, offsy; + GLint scissor[4]; + int a; + + cumap= (CurveMapping *)(but->editcumap? but->editcumap: but->poin); + cuma= cumap->cm+cumap->cur; + + /* need scissor test, curve can draw outside of boundary */ + glGetIntegerv(GL_VIEWPORT, scissor); + fx= but->x1; fy= but->y1; + /* XXX 2.50 need context: ui_graphics_to_window(but->win, &fx, &fy); */ + dx= but->x2; dy= but->y2; + /* XXX 2.50 need context: ui_graphics_to_window(but->win, &dx, &dy); */ + //glScissor((int)floor(fx), (int)floor(fy), (int)ceil(dx-fx), (int)ceil(dy-fy)); + + /* calculate offset and zoom */ + zoomx= (but->x2-but->x1-2.0*but->aspect)/(cumap->curr.xmax - cumap->curr.xmin); + zoomy= (but->y2-but->y1-2.0*but->aspect)/(cumap->curr.ymax - cumap->curr.ymin); + offsx= cumap->curr.xmin-but->aspect/zoomx; + offsy= cumap->curr.ymin-but->aspect/zoomy; + + /* backdrop */ + if(cumap->flag & CUMA_DO_CLIP) { + UI_ThemeColorShade(TH_BUT_NEUTRAL, -20); + glRectf(but->x1, but->y1, but->x2, but->y2); + UI_ThemeColor(TH_BUT_NEUTRAL); + glRectf(but->x1 + zoomx*(cumap->clipr.xmin-offsx), + but->y1 + zoomy*(cumap->clipr.ymin-offsy), + but->x1 + zoomx*(cumap->clipr.xmax-offsx), + but->y1 + zoomy*(cumap->clipr.ymax-offsy)); + } + else { + UI_ThemeColor(TH_BUT_NEUTRAL); + glRectf(but->x1, but->y1, but->x2, but->y2); + } + + /* grid, every .25 step */ + UI_ThemeColorShade(TH_BUT_NEUTRAL, -16); + ui_draw_but_curve_grid(but, zoomx, zoomy, offsx, offsy, 0.25f); + /* grid, every 1.0 step */ + UI_ThemeColorShade(TH_BUT_NEUTRAL, -24); + ui_draw_but_curve_grid(but, zoomx, zoomy, offsx, offsy, 1.0f); + /* axes */ + UI_ThemeColorShade(TH_BUT_NEUTRAL, -50); + glBegin(GL_LINES); + glVertex2f(but->x1, but->y1 + zoomy*(-offsy)); + glVertex2f(but->x2, but->y1 + zoomy*(-offsy)); + glVertex2f(but->x1 + zoomx*(-offsx), but->y1); + glVertex2f(but->x1 + zoomx*(-offsx), but->y2); + glEnd(); + + /* cfra option */ + /* XXX 2.48 + if(cumap->flag & CUMA_DRAW_CFRA) { + glColor3ub(0x60, 0xc0, 0x40); + glBegin(GL_LINES); + glVertex2f(but->x1 + zoomx*(cumap->sample[0]-offsx), but->y1); + glVertex2f(but->x1 + zoomx*(cumap->sample[0]-offsx), but->y2); + glEnd(); + }*/ + /* sample option */ + /* XXX 2.48 + * if(cumap->flag & CUMA_DRAW_SAMPLE) { + if(cumap->cur==3) { + float lum= cumap->sample[0]*0.35f + cumap->sample[1]*0.45f + cumap->sample[2]*0.2f; + glColor3ub(240, 240, 240); + + glBegin(GL_LINES); + glVertex2f(but->x1 + zoomx*(lum-offsx), but->y1); + glVertex2f(but->x1 + zoomx*(lum-offsx), but->y2); + glEnd(); + } + else { + if(cumap->cur==0) + glColor3ub(240, 100, 100); + else if(cumap->cur==1) + glColor3ub(100, 240, 100); + else + glColor3ub(100, 100, 240); + + glBegin(GL_LINES); + glVertex2f(but->x1 + zoomx*(cumap->sample[cumap->cur]-offsx), but->y1); + glVertex2f(but->x1 + zoomx*(cumap->sample[cumap->cur]-offsx), but->y2); + glEnd(); + } + }*/ + + /* the curve */ + UI_ThemeColorBlend(TH_TEXT, TH_BUT_NEUTRAL, 0.35); + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glBegin(GL_LINE_STRIP); + + if(cuma->table==NULL) + curvemapping_changed(cumap, 0); /* 0 = no remove doubles */ + cmp= cuma->table; + + /* first point */ + if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0) + glVertex2f(but->x1, but->y1 + zoomy*(cmp[0].y-offsy)); + else { + fx= but->x1 + zoomx*(cmp[0].x-offsx + cuma->ext_in[0]); + fy= but->y1 + zoomy*(cmp[0].y-offsy + cuma->ext_in[1]); + glVertex2f(fx, fy); + } + for(a=0; a<=CM_TABLE; a++) { + fx= but->x1 + zoomx*(cmp[a].x-offsx); + fy= but->y1 + zoomy*(cmp[a].y-offsy); + glVertex2f(fx, fy); + } + /* last point */ + if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0) + glVertex2f(but->x2, but->y1 + zoomy*(cmp[CM_TABLE].y-offsy)); + else { + fx= but->x1 + zoomx*(cmp[CM_TABLE].x-offsx - cuma->ext_out[0]); + fy= but->y1 + zoomy*(cmp[CM_TABLE].y-offsy - cuma->ext_out[1]); + glVertex2f(fx, fy); + } + glEnd(); + glDisable(GL_LINE_SMOOTH); + glDisable(GL_BLEND); + + /* the points, use aspect to make them visible on edges */ + cmp= cuma->curve; + glPointSize(3.0f); + bglBegin(GL_POINTS); + for(a=0; atotpoint; a++) { + if(cmp[a].flag & SELECT) + UI_ThemeColor(TH_TEXT_HI); + else + UI_ThemeColor(TH_TEXT); + fac[0]= but->x1 + zoomx*(cmp[a].x-offsx); + fac[1]= but->y1 + zoomy*(cmp[a].y-offsy); + bglVertex2fv(fac); + } + bglEnd(); + glPointSize(1.0f); + + /* restore scissortest */ + glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); + + /* outline */ + UI_ThemeColor(TH_BUT_OUTLINE); + fdrawbox(but->x1, but->y1, but->x2, but->y2); +} + +static void ui_draw_roundbox(uiBut *but) +{ + glEnable(GL_BLEND); + + UI_ThemeColorShadeAlpha(but->themecol, but->a2, but->a2); + + uiSetRoundBox(but->a1); + gl_round_box(GL_POLYGON, but->x1, but->y1, but->x2, but->y2, but->min); + + glDisable(GL_BLEND); +} + + +/* nothing! */ +static void ui_draw_nothing(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) +{ +} + +/* minimal drawing for table items */ +static void ui_draw_table(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) +{ + int background= 1; + + /* paper */ + if(flag & UI_SELECT) { + if(flag & UI_ACTIVE) glColor4f(0, 0, 0, 0.2f); + else glColor4f(0, 0, 0, 0.1f); + } + else { + if(flag & UI_ACTIVE) glColor4f(1.0f, 1.0f, 1.0f, 0.2f); + else background= 0; + } + + if(background) { + glEnable(GL_BLEND); + glRectf(x1, y1, x2, y2); + glDisable(GL_BLEND); + } + + /* special type decorations */ + switch(type) { + case NUM: + case NUMABS: + if(flag & UI_SELECT) UI_ThemeColorShade(colorid, -120); + else UI_ThemeColorShade(colorid, -90); + ui_default_num_arrows(x1, y1, x2, y2); + break; + + case ICONROW: + case ICONTEXTROW: + if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, 0); + else UI_ThemeColorShade(colorid, -10); + glRectf(x2-9, y1+asp, x2-asp, y2-asp); + + UI_ThemeColorShade(colorid, -50); + ui_default_iconrow_arrows(x1, y1, x2, y2); + break; + + case MENU: + case BLOCK: + if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, 0); + else UI_ThemeColorShade(colorid, -10); + glRectf(x2-17, y1+asp, x2-asp, y2-asp); + + UI_ThemeColorShade(colorid, -50); + ui_default_menu_arrows(x1, y1, x2, y2); + break; + } +} + +/* ************** EXTERN, called from interface.c ************* */ +/* ************** MAIN CALLBACK FUNCTION ************* */ + +void ui_set_embossfunc(uiBut *but, int drawtype) +{ + // this aded for evaluating textcolor for example + but->dt= drawtype; + + // not really part of standard minimal themes, just make sure it is set + but->sliderfunc= ui_draw_slider; + + // standard builtin first: + if(but->type==LABEL || but->type==ROUNDBOX) but->embossfunc= ui_draw_nothing; + else if(but->type==PULLDOWN) but->embossfunc= ui_draw_pulldown_round; + else if(drawtype==UI_EMBOSSM) but->embossfunc= ui_draw_minimal; + else if(drawtype==UI_EMBOSSN) but->embossfunc= ui_draw_nothing; + else if(drawtype==UI_EMBOSSP) but->embossfunc= ui_draw_pulldown_item; + else if(drawtype==UI_EMBOSSR) but->embossfunc= ui_draw_round; + else if(drawtype==UI_EMBOSST) but->embossfunc= ui_draw_table; + else { + int theme= UI_GetThemeValue(TH_BUT_DRAWTYPE); + + switch(theme) { + + case TH_ROUNDED: + but->embossfunc= ui_draw_round; + break; + case TH_OLDSKOOL: + but->embossfunc= ui_draw_oldskool; + break; + case TH_MINIMAL: + but->embossfunc= ui_draw_minimal; + break; + case TH_SHADED: + default: + but->embossfunc= ui_draw_default; + but->sliderfunc= ui_default_slider; + break; + } + } + + // note: if you want aligning, adapt the call uiBlockEndAlign in interface.c +} + +void ui_draw_but(uiBut *but) +{ + double value; + float x1, x2, y1, y2, fac; + int type; + + if(but==NULL) return; + + /* XXX 2.50 no frontbuffer drawing allowed */ +#if 0 + /* signal for frontbuf flush buttons and menus, not when normal drawing */ + if(but->block->in_use) ui_block_set_flush(but->block, but); +#endif + + switch (but->type) { + + case NUMSLI: + case HSVSLI: + type= (but->editstr)? TEX: but->type; + but->embossfunc(type, but->themecol, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag); + ui_draw_text_icon(but); + + x1= (but->x1+but->x2)/2; + x2= but->x2 - 5.0*but->aspect; + y1= but->y1 + 2.0*but->aspect; + y2= but->y2 - 2.0*but->aspect; + + value= ui_get_but_val(but); + fac= (value-but->min)*(x2-x1)/(but->max - but->min); + + but->sliderfunc(but->themecol, fac, but->aspect, x1, y1, x2, y2, but->flag); + break; + + case SEPR: + // only background + break; + + case COL: + ui_draw_but_COL(but); // black box with color + break; + + case HSVCUBE: + ui_draw_but_HSVCUBE(but); // box for colorpicker, three types + break; + +#ifdef INTERNATIONAL + case CHARTAB: + value= ui_get_but_val(but); + ui_draw_but_CHARTAB(but); + break; +#endif + + case LINK: + case INLINK: + ui_draw_icon(but, but->icon, 0); + break; + + case ROUNDBOX: + ui_draw_roundbox(but); + break; + + case BUT_COLORBAND: + ui_draw_but_COLORBAND(but); + break; + case BUT_NORMAL: + ui_draw_but_NORMAL(but); + break; + case BUT_CURVE: + ui_draw_but_CURVE(but); + break; + + default: + type= (but->editstr)? TEX: but->type; + but->embossfunc(type, but->themecol, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag); + ui_draw_text_icon(but); + + } +} + +void ui_dropshadow(rctf *rct, float radius, float aspect, int select) +{ + float rad; + float a; + char alpha= 2; + + glEnable(GL_BLEND); + + if(radius > (rct->ymax-rct->ymin-10.0f)/2.0f) + rad= (rct->ymax-rct->ymin-10.0f)/2.0f; + else + rad= radius; + + if(select) a= 12.0f*aspect; else a= 12.0f*aspect; + for(; a>0.0f; a-=aspect) { + /* alpha ranges from 2 to 20 or so */ + glColor4ub(0, 0, 0, alpha); + alpha+= 2; + + gl_round_box(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax-10.0f + a, rad+a); + } + + /* outline emphasis */ + glEnable( GL_LINE_SMOOTH ); + glColor4ub(0, 0, 0, 100); + gl_round_box(GL_LINE_LOOP, rct->xmin-0.5f, rct->ymin-0.5f, rct->xmax+0.5f, rct->ymax+0.5f, radius); + glDisable( GL_LINE_SMOOTH ); + + glDisable(GL_BLEND); +} + diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c new file mode 100644 index 00000000000..074c05b050f --- /dev/null +++ b/source/blender/editors/interface/interface_ops.c @@ -0,0 +1,3425 @@ +/** + * $Id$ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_color_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_texture_types.h" +#include "DNA_userdef_types.h" +#include "DNA_windowmanager_types.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "PIL_time.h" + +#include "BKE_colortools.h" +#include "BKE_global.h" +#include "BKE_texture.h" +#include "BKE_utildefines.h" + +#include "UI_interface.h" +#include "UI_text.h" +#include "interface.h" + +#include "WM_api.h" +#include "WM_types.h" + +/***************** structs and defines ****************/ + +#define BUTTON_TOOLTIP_DELAY 500 +#define BUTTON_FLASH_DELAY 20 +#define BUTTON_AUTO_OPEN_THRESH 0.3 +#define BUTTON_MOUSE_TOWARDS_THRESH 1.0 + +typedef enum uiActivateButState { + BUTTON_STATE_INIT, + BUTTON_STATE_HIGHLIGHT, + BUTTON_STATE_WAIT_FLASH, + BUTTON_STATE_WAIT_RELEASE, + BUTTON_STATE_WAIT_KEY_EVENT, + BUTTON_STATE_NUM_EDITING, + BUTTON_STATE_TEXT_EDITING, + BUTTON_STATE_TEXT_SELECTING, + BUTTON_STATE_BLOCK_OPEN, + BUTTON_STATE_EXIT +} uiActivateButState; + +typedef struct uiActivateBut { + ARegion *region; + wmOperator *operator; + + int interactive; + + /* overall state */ + uiActivateButState state; + int cancel, retval; + int applied, appliedinteractive; + wmTimerHandle *flashtimer; + + /* edited value */ + char *str, *origstr; + double value, origvalue; + float vec[3], origvec[3]; + int togdual, togonly; + ColorBand *coba; + CurveMapping *cumap; + + /* tooltip */ + ARegion *tooltip; + wmTimerHandle *tooltiptimer; + wmTimerHandle *autoopentimer; + int tooltipdisabled; + + /* text selection/editing */ + int maxlen, selextend, selstartx; + + /* number editing / dragging */ + int draglastx, draglasty; + int dragstartx, dragstarty; + int dragchange, draglock, dragsel; + float dragf, dragfstart; + CBData *dragcbd; + + /* block open */ + uiMenuBlockHandle *blockhandle; + int blockretval; +} uiActivateBut; + +static void button_activate_state(bContext *C, uiBut *but, uiActivateButState state); + +/* ********************** button apply/revert ************************ */ + +static void ui_apply_but_func(uiBut *but) +{ + if (but->func) + but->func(but->func_arg1, but->func_arg2); + if(but->func3) + but->func3(but->func_arg1, but->func_arg2, but->func_arg3); +} + +static void ui_apply_but_BUT(uiBut *but, uiActivateBut *data) +{ + ui_apply_but_func(but); + + data->retval= but->retval; + data->applied= 1; +} + +static void ui_apply_but_BUTM(uiBut *but, uiActivateBut *data) +{ + ui_set_but_val(but, but->min); + ui_apply_but_func(but); + + data->retval= but->retval; + data->applied= 1; +} + +static void ui_apply_but_BLOCK(uiBut *but, uiActivateBut *data) +{ + if(but->type == COL) + ui_set_but_vectorf(but, data->vec); + else if(ELEM3(but->type, MENU, ICONROW, ICONTEXTROW)) + ui_set_but_val(but, data->value); + + ui_check_but(but); + ui_apply_but_func(but); + data->retval= but->retval; + data->applied= 1; +} + +static void ui_apply_but_TOG(uiBlock *block, uiBut *but, uiActivateBut *data) +{ + double value; + int w, lvalue, push; + + /* local hack... */ + if(but->type==BUT_TOGDUAL && data->togdual) { + if(but->pointype==SHO) + but->poin += 2; + else if(but->pointype==INT) + but->poin += 4; + } + + value= ui_get_but_val(but); + lvalue= (int)value; + + if(but->bit) { + w= BTST(lvalue, but->bitnr); + if(w) lvalue = BCLR(lvalue, but->bitnr); + else lvalue = BSET(lvalue, but->bitnr); + + if(but->type==TOGR) { + if(!data->togonly) { + lvalue= 1<<(but->bitnr); + + ui_set_but_val(but, (double)lvalue); + } + else { + if(lvalue==0) lvalue= 1<<(but->bitnr); + } + } + + ui_set_but_val(but, (double)lvalue); + if(but->type==ICONTOG || but->type==ICONTOGN) ui_check_but(but); + } + else { + + if(value==0.0) push= 1; + else push= 0; + + if(but->type==TOGN || but->type==ICONTOGN) push= !push; + ui_set_but_val(but, (double)push); + if(but->type==ICONTOG || but->type==ICONTOGN) ui_check_but(but); + } + + /* end local hack... */ + if(but->type==BUT_TOGDUAL && data->togdual) { + if(but->pointype==SHO) + but->poin -= 2; + else if(but->pointype==INT) + but->poin -= 4; + } + + ui_apply_but_func(but); + + data->retval= but->retval; + data->applied= 1; +} + +static void ui_apply_but_ROW(uiBlock *block, uiBut *but, uiActivateBut *data) +{ + ui_set_but_val(but, but->max); + ui_apply_but_func(but); + + data->retval= but->retval; + data->applied= 1; +} + +static void ui_apply_but_TEX(uiBut *but, uiActivateBut *data) +{ + if(!data->str) + return; + + ui_set_but_string(but, data->str); + ui_check_but(but); + + /* give butfunc the original text too */ + /* feature used for bone renaming, channels, etc */ + if(but->func_arg2==NULL) but->func_arg2= data->origstr; + ui_apply_but_func(but); + if(but->func_arg2==data->origstr) but->func_arg2= NULL; + + data->retval= but->retval; + data->applied= 1; +} + +static void ui_apply_but_NUM(uiBut *but, uiActivateBut *data) +{ + if(data->str) { + /* XXX 2.50 missing python api */ +#if 0 + if(BPY_button_eval(data->str, &data->value)) { + WM_report(C, WM_LOG_WARNING, "Invalid Python expression, check console"); + data->value = 0.0f; /* Zero out value on error */ + + if(data->str[0]) { + data->cancel= 1; /* invalidate return value if eval failed, except when string was null */ + return; + } + } +#else + data->value= atof(data->str); +#endif + + if(!ui_is_but_float(but)) data->value= (int)data->value; + if(but->type==NUMABS) data->value= fabs(data->value); + if(data->valuemin) data->value= but->min; + if(data->value>but->max) data->value= but->max; + } + + ui_set_but_val(but, data->value); + ui_check_but(but); + ui_apply_but_func(but); + + data->retval= but->retval; + data->applied= 1; +} + +static void ui_apply_but_LABEL(uiBut *but, uiActivateBut *data) +{ + ui_apply_but_func(but); + data->retval= but->retval; + data->applied= 1; +} + +static void ui_apply_but_TOG3(uiBut *but, uiActivateBut *data) +{ + if(but->pointype==SHO ) { + short *sp= (short *)but->poin; + + if( BTST(sp[1], but->bitnr)) { + sp[1]= BCLR(sp[1], but->bitnr); + sp[0]= BCLR(sp[0], but->bitnr); + } + else if( BTST(sp[0], but->bitnr)) { + sp[1]= BSET(sp[1], but->bitnr); + } else { + sp[0]= BSET(sp[0], but->bitnr); + } + } + else { + if( BTST(*(but->poin+2), but->bitnr)) { + *(but->poin+2)= BCLR(*(but->poin+2), but->bitnr); + *(but->poin)= BCLR(*(but->poin), but->bitnr); + } + else if( BTST(*(but->poin), but->bitnr)) { + *(but->poin+2)= BSET(*(but->poin+2), but->bitnr); + } else { + *(but->poin)= BSET(*(but->poin), but->bitnr); + } + } + + ui_check_but(but); + ui_apply_but_func(but); + data->retval= but->retval; + data->applied= 1; +} + +static void ui_apply_but_VEC(uiBut *but, uiActivateBut *data) +{ + ui_set_but_vectorf(but, data->vec); + ui_check_but(but); + ui_apply_but_func(but); + + data->retval= but->retval; + data->applied= 1; +} + +static void ui_apply_but_COLORBAND(uiBut *but, uiActivateBut *data) +{ + ui_apply_but_func(but); + data->retval= but->retval; + data->applied= 1; +} + +static void ui_apply_but_CURVE(uiBut *but, uiActivateBut *data) +{ + ui_apply_but_func(but); + data->retval= but->retval; + data->applied= 1; +} + +static void ui_apply_but_IDPOIN(uiBut *but, uiActivateBut *data) +{ + but->idpoin_func(data->str, but->idpoin_idpp); + ui_check_but(but); + ui_apply_but_func(but); + data->retval= but->retval; + data->applied= 1; +} + +#ifdef INTERNATIONAL +static void ui_apply_but_CHARTAB(uiBut *but, uiActivateBut *data) +{ + ui_apply_but_func(but); + data->retval= but->retval; + data->applied= 1; +} +#endif + +static void ui_apply_button(uiBlock *block, uiBut *but, uiActivateBut *data, int interactive) +{ + char *editstr; + double *editval; + float *editvec; + ColorBand *editcoba; + CurveMapping *editcumap; + + data->retval= 0; + + /* if we cancel and have not applied yet, there is nothing to do, + * otherwise we have to restore the original value again */ + if(data->cancel) { + if(!data->applied) + return; + + if(data->str) MEM_freeN(data->str); + data->str= data->origstr; + data->origstr= NULL; + data->value= data->origvalue; + data->origvalue= 0.0; + VECCOPY(data->vec, data->origvec); + data->origvec[0]= data->origvec[1]= data->origvec[2]= 0.0f; + } + else { + /* we avoid applying interactive edits a second time + * at the end with the appliedinteractive flag */ + if(interactive) + data->appliedinteractive= 1; + else if(data->appliedinteractive) + return; + } + + /* ensures we are writing actual values */ + editstr= but->editstr; + editval= but->editval; + editvec= but->editvec; + editcoba= but->editcoba; + editcumap= but->editcumap; + but->editstr= NULL; + but->editval= NULL; + but->editvec= NULL; + but->editcoba= NULL; + but->editcumap= NULL; + + /* handle different types */ + switch(but->type) { + case BUT: + ui_apply_but_BUT(but, data); + break; + case TEX: + ui_apply_but_TEX(but, data); + break; + case TOG: + case TOGR: + case ICONTOG: + case ICONTOGN: + case TOGN: + case BUT_TOGDUAL: + ui_apply_but_TOG(block, but, data); + break; + case ROW: + ui_apply_but_ROW(block, but, data); + break; + case SCROLL: + break; + case NUM: + case NUMABS: + ui_apply_but_NUM(but, data); + break; + case SLI: + case NUMSLI: + ui_apply_but_NUM(but, data); + break; + case HSVSLI: + break; + case ROUNDBOX: + case LABEL: + ui_apply_but_LABEL(but, data); + break; + case TOG3: + ui_apply_but_TOG3(but, data); + break; + case MENU: + case ICONROW: + case ICONTEXTROW: + case BLOCK: + case PULLDOWN: + case COL: + ui_apply_but_BLOCK(but, data); + break; + case BUTM: + ui_apply_but_BUTM(but, data); + break; + case BUT_NORMAL: + case HSVCUBE: + ui_apply_but_VEC(but, data); + break; + case BUT_COLORBAND: + ui_apply_but_COLORBAND(but, data); + break; + case BUT_CURVE: + ui_apply_but_CURVE(but, data); + break; + case IDPOIN: + ui_apply_but_IDPOIN(but, data); + break; +#ifdef INTERNATIONAL + case CHARTAB: + ui_apply_but_CHARTAB(but, data); + break; +#endif + case LINK: + case INLINK: + break; + } + + but->editstr= editstr; + but->editval= editval; + but->editvec= editvec; + but->editcoba= editcoba; + but->editcumap= editcumap; +} + +/* ******************* copy and paste ******************** */ + +/* c = copy, v = paste */ +static void ui_but_copy_paste(bContext *C, uiBut *but, uiActivateBut *data, char mode) +{ + static ColorBand but_copypaste_coba = {0}; + char buf[UI_MAX_DRAW_STR+1]= {0}; + double val; + + if(mode=='v' && but->lock) + return; + + if(mode=='v') { + /* extract first line from clipboard in case of multi-line copies */ + char *p = NULL; /* XXX 2.48 getClipboard(0); */ + if(p) { + int i = 0; + while (*p && *p!='\r' && *p!='\n' && itype, NUM, NUMABS, NUMSLI, HSVSLI) { + + if(but->poin==NULL && but->rnapoin.data==NULL); + else if(mode=='c') { + sprintf(buf, "%f", ui_get_but_val(but)); + /* XXX 2.48 putClipboard(buf, 0); */ + } + else { + if (sscanf(buf, " %lf ", &val) == 1) { + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + data->value= val; + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + } + } + + /* RGB triple */ + else if(but->type==COL) { + float rgb[3]; + + if(but->poin==NULL && but->rnapoin.data==NULL); + else if(mode=='c') { + + ui_get_but_vectorf(but, rgb); + sprintf(buf, "[%f, %f, %f]", rgb[0], rgb[1], rgb[2]); + /* XXX 2.48 putClipboard(buf, 0); */ + + } + else { + if (sscanf(buf, "[%f, %f, %f]", &rgb[0], &rgb[1], &rgb[2]) == 3) { + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + VECCOPY(data->vec, rgb); + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + } + } + + /* text/string and ID data */ + else if(ELEM(but->type, TEX, IDPOIN)) { + uiActivateBut *data= but->activate; + + if(but->poin==NULL && but->rnapoin.data==NULL); + else if(mode=='c') { + button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + BLI_strncpy(buf, data->str, UI_MAX_DRAW_STR); + /* XXX 2.48 putClipboard(data->str, 0); */ + data->cancel= 1; + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + else { + button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + BLI_strncpy(data->str, buf, data->maxlen); + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + } + /* colorband (not supported by system clipboard) */ + else if(but->type==BUT_COLORBAND) { + if(mode=='c') { + if(but->poin) + return; + + memcpy(&but_copypaste_coba, but->poin, sizeof(ColorBand)); + } + else { + if(but_copypaste_coba.tot==0) + return; + + if(!but->poin) + but->poin= MEM_callocN(sizeof(ColorBand), "colorband"); + + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + memcpy(data->coba, &but_copypaste_coba, sizeof(ColorBand) ); + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + } +} + +/* ************* in-button text selection/editing ************* */ + +/* return 1 if char ch is special character, otherwise return 0 */ +static short test_special_char(char ch) +{ + switch(ch) { + case '\\': + case '/': + case '~': + case '!': + case '@': + case '#': + case '$': + case '%': + case '^': + case '&': + case '*': + case '(': + case ')': + case '+': + case '=': + case '{': + case '}': + case '[': + case ']': + case ':': + case ';': + case '\'': + case '\"': + case '<': + case '>': + case ',': + case '.': + case '?': + case '_': + case '-': + case ' ': + return 1; + break; + default: + break; + } + return 0; +} + +static int ui_textedit_delete_selection(uiBut *but, uiActivateBut *data) +{ + char *str; + int x, changed; + + str= data->str; + changed= (but->selsta != but->selend); + + for(x=0; x< strlen(str); x++) { + if (but->selend + x <= strlen(str) ) { + str[but->selsta + x]= str[but->selend + x]; + } else { + str[but->selsta + x]= '\0'; + break; + } + } + + but->pos = but->selend = but->selsta; + + return changed; +} + +static void ui_textedit_set_cursor_pos(uiBut *but, uiActivateBut *data, short x) +{ + char *origstr; + + origstr= MEM_callocN(sizeof(char)*(data->maxlen+1), "ui_textedit origstr"); + + BLI_strncpy(origstr, but->drawstr, data->maxlen+1); + but->pos= strlen(origstr)-but->ofs; + + while((but->aspect*UI_GetStringWidth(but->font, origstr+but->ofs, 0) + but->x1) > x) { + if (but->pos <= 0) break; + but->pos--; + origstr[but->pos+but->ofs] = 0; + } + + but->pos -= strlen(but->str); + but->pos += but->ofs; + if(but->pos<0) but->pos= 0; + + MEM_freeN(origstr); +} + +static void ui_textedit_set_cursor_select(uiBut *but, uiActivateBut *data, short x) +{ + if (x > data->selstartx) data->selextend = EXTEND_RIGHT; + else if (x < data->selstartx) data->selextend = EXTEND_LEFT; + + ui_textedit_set_cursor_pos(but, data, x); + + if (data->selextend == EXTEND_RIGHT) but->selend = but->pos; + if (data->selextend == EXTEND_LEFT) but->selsta = but->pos; + + ui_check_but(but); +} + +static int ui_textedit_type_ascii(uiBut *but, uiActivateBut *data, char ascii) +{ + char *str; + int len, x, changed= 0; + + str= data->str; + len= strlen(str); + + if(len-(but->selend - but->selsta)+1 <= data->maxlen) { + /* type over the current selection */ + if ((but->selend - but->selsta) > 0) + changed= ui_textedit_delete_selection(but, data); + + len= strlen(str); + if(len < data->maxlen) { + for(x= data->maxlen; x>but->pos; x--) + str[x]= str[x-1]; + str[but->pos]= ascii; + str[len+1]= '\0'; + + but->pos++; + changed= 1; + } + } + + return 1; +} + +void ui_textedit_move(uiBut *but, uiActivateBut *data, int direction, int select, int jump) +{ + char *str; + int len; + + str= data->str; + len= strlen(str); + + if(direction) { /* right*/ + /* if there's a selection */ + if ((but->selend - but->selsta) > 0) { + /* extend the selection based on the first direction taken */ + if(select) { + if (!data->selextend) { + data->selextend = EXTEND_RIGHT; + } + if (data->selextend == EXTEND_RIGHT) { + but->selend++; + if (but->selend > len) but->selend = len; + } else if (data->selextend == EXTEND_LEFT) { + but->selsta++; + /* if the selection start has gone past the end, + * flip them so they're in sync again */ + if (but->selsta == but->selend) { + but->pos = but->selsta; + data->selextend = EXTEND_RIGHT; + } + } + } else { + but->selsta = but->pos = but->selend; + data->selextend = 0; + } + } else { + if(select) { + /* make a selection, starting from the cursor position */ + but->selsta = but->pos; + + but->pos++; + if(but->pos>strlen(str)) but->pos= strlen(str); + + but->selend = but->pos; + } else if(jump) { + /* jump betweenn special characters (/,\,_,-, etc.), + * look at function test_special_char() for complete + * list of special character, ctr -> */ + while(but->pos < len) { + but->pos++; + if(test_special_char(str[but->pos])) break; + } + } else { + but->pos++; + if(but->pos>strlen(str)) but->pos= strlen(str); + } + } + } + else { /* left */ + /* if there's a selection */ + if ((but->selend - but->selsta) > 0) { + /* extend the selection based on the first direction taken */ + if(select) { + if (!data->selextend) { + data->selextend = EXTEND_LEFT; + } + if (data->selextend == EXTEND_LEFT) { + but->selsta--; + if (but->selsta < 0) but->selsta = 0; + } else if (data->selextend == EXTEND_RIGHT) { + but->selend--; + /* if the selection start has gone past the end, + * flip them so they're in sync again */ + if (but->selsta == but->selend) { + but->pos = but->selsta; + data->selextend = EXTEND_LEFT; + } + } + } else { + but->pos = but->selend = but->selsta; + data->selextend = 0; + } + } else { + if(select) { + /* make a selection, starting from the cursor position */ + but->selend = but->pos; + + but->pos--; + if(but->pos<0) but->pos= 0; + + but->selsta = but->pos; + } else if(jump) { + /* jump betweenn special characters (/,\,_,-, etc.), + * look at function test_special_char() for complete + * list of special character, ctr -> */ + while(but->pos > 0){ + but->pos--; + if(test_special_char(str[but->pos])) break; + } + } else { + if(but->pos>0) but->pos--; + } + } + } +} + +void ui_textedit_move_end(uiBut *but, uiActivateBut *data, int direction, int select) +{ + char *str; + + str= data->str; + + if(direction) { /* right */ + if(select) { + but->selsta = but->pos; + but->selend = strlen(str); + data->selextend = EXTEND_RIGHT; + } else { + but->selsta = but->selend = but->pos= strlen(str); + } + } + else { /* left */ + if(select) { + but->selend = but->pos; + but->selsta = 0; + data->selextend = EXTEND_LEFT; + } else { + but->selsta = but->selend = but->pos= 0; + } + } +} + +static int ui_textedit_delete(uiBut *but, uiActivateBut *data, int direction, int all) +{ + char *str; + int len, x, changed= 0; + + str= data->str; + len= strlen(str); + + if(all) { + if(len) changed=1; + str[0]= 0; + but->pos= 0; + } + else if(direction) { /* delete */ + if ((but->selend - but->selsta) > 0) { + changed= ui_textedit_delete_selection(but, data); + } + else if(but->pos>=0 && but->pospos; xselend - but->selsta) > 0) { + ui_textedit_delete_selection(but, data); + } + else if(but->pos>0) { + for(x=but->pos; xpos--; + changed= 1; + } + } + } + + return changed; +} + +static int ui_textedit_autocomplete(uiBut *but, uiActivateBut *data) +{ + char *str; + int changed= 1; + + str= data->str; + but->autocomplete_func(str, but->autofunc_arg); + but->pos= strlen(str); + + return changed; +} + +static int ui_textedit_copypaste(uiBut *but, uiActivateBut *data, int paste, int copy, int cut) +{ + char buf[UI_MAX_DRAW_STR]={0}; + char *str, *p; + int len, x, y, i, changed= 0; + + str= data->str; + len= strlen(str); + + /* paste */ + if (paste) { + /* extract the first line from the clipboard */ + p = NULL; /* XXX 2.48 getClipboard(0); */ + + if(p && p[0]) { + while (*p && *p!='\r' && *p!='\n' && iselend - but->selsta) > 0) + ui_textedit_delete_selection(but, data); + + for (y=0; ymaxlen) { + for(x= data->maxlen; x>but->pos; x--) + str[x]= str[x-1]; + str[but->pos]= buf[y]; + but->pos++; + len++; + str[len]= '\0'; + } + } + + changed= 1; + } + } + /* cut & copy */ + else if (copy || cut) { + /* copy the contents to the copypaste buffer */ + for(x= but->selsta; x <= but->selend; x++) { + if (x==but->selend) + buf[x] = '\0'; + else + buf[(x - but->selsta)] = str[x]; + } + /* XXX 2.48 putClipboard(buf, 0); */ + + /* for cut only, delete the selection afterwards */ + if(cut) + if((but->selend - but->selsta) > 0) + changed= ui_textedit_delete_selection(but, data); + } + + return changed; +} + +static void ui_textedit_begin(uiBut *but, uiActivateBut *data) +{ + if(data->str) { + MEM_freeN(data->str); + data->str= NULL; + } + + /* retrieve string */ + if(but->type == TEX) { + data->maxlen= but->max; + data->str= MEM_callocN(sizeof(char)*(data->maxlen+1), "textedit str"); + + ui_get_but_string(but, data->str, data->maxlen+1); + } + else if(but->type == IDPOIN) { + ID *id; + + data->maxlen= 22; + data->str= MEM_callocN(sizeof(char)*(data->maxlen+1), "textedit str"); + + id= *but->idpoin_idpp; + if(id) BLI_strncpy(data->str, id->name+2, data->maxlen+1); + else data->str[0]= 0; + } + else { + double value; + + data->maxlen= UI_MAX_DRAW_STR; + data->str= MEM_callocN(sizeof(char)*(data->maxlen+1), "textedit str"); + + value= ui_get_but_val(but); + if(ui_is_but_float(but)) { + if(but->a2) { /* amount of digits defined */ + if(but->a2==1) sprintf(data->str, "%.1f", value); + else if(but->a2==2) sprintf(data->str, "%.2f", value); + else if(but->a2==3) sprintf(data->str, "%.3f", value); + else sprintf(data->str, "%.4f", value); + } + else sprintf(data->str, "%.3f", value); + } + else { + sprintf(data->str, "%d", (int)value); + } + } + + data->origstr= BLI_strdup(data->str); + data->selextend= 0; + data->selstartx= 0; + + /* set cursor pos to the end of the text */ + but->editstr= data->str; + but->pos= strlen(data->str); + but->selsta= 0; + but->selend= strlen(but->drawstr) - strlen(but->str); + + ui_check_but(but); +} + +static void ui_textedit_end(uiBut *but, uiActivateBut *data) +{ + if(but) { + but->editstr= 0; + but->pos= -1; + } +} + +static void ui_textedit_next_but(uiBlock *block, uiBut *actbut) +{ + uiBut *but; + + /* label and roundbox can overlap real buttons (backdrops...) */ + if(actbut->type==LABEL && actbut->type==ROUNDBOX) + return; + + for(but= actbut->next; but; but= but->next) { + if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) { + but->activateflag= UI_ACTIVATE_TEXT_EDITING; + return; + } + } + for(but= block->buttons.first; but!=actbut; but= but->next) { + if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) { + but->activateflag= UI_ACTIVATE_TEXT_EDITING; + return; + } + } +} + +static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut) +{ + uiBut *but; + + /* label and roundbox can overlap real buttons (backdrops...) */ + if(actbut->type==LABEL && actbut->type==ROUNDBOX) + return; + + for(but= actbut->prev; but; but= but->prev) { + if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) { + but->activateflag= UI_ACTIVATE_TEXT_EDITING; + return; + } + } + for(but= block->buttons.last; but!=actbut; but= but->prev) { + if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) { + but->activateflag= UI_ACTIVATE_TEXT_EDITING; + return; + } + } +} + +static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + int mx, my, changed= 0, handled= 0; + + switch(event->type) { + case RIGHTMOUSE: + case ESCKEY: + data->cancel= 1; + button_activate_state(C, but, BUTTON_STATE_EXIT); + handled= 1; + break; + case LEFTMOUSE: { + if(event->val) { + mx= event->x; + my= event->y; + ui_window_to_block(data->region, block, &mx, &my); + + if ((but->y1 <= my) && (my <= but->y2) && (but->x1 <= mx) && (mx <= but->x2)) { + ui_textedit_set_cursor_pos(but, data, mx); + but->selsta = but->selend = but->pos; + data->selstartx= mx; + + button_activate_state(C, but, BUTTON_STATE_TEXT_SELECTING); + handled= 1; + } + else { + button_activate_state(C, but, BUTTON_STATE_EXIT); + handled= 1; + } + } + break; + } + } + + if(event->val) { + switch (event->type) { + case VKEY: + case XKEY: + case CKEY: + if(event->ctrl || event->oskey) { + if(event->type == VKEY) + changed= ui_textedit_copypaste(but, data, 1, 0, 0); + else if(event->type == XKEY) + changed= ui_textedit_copypaste(but, data, 0, 1, 0); + else if(event->type == CKEY) + changed= ui_textedit_copypaste(but, data, 0, 0, 1); + + handled= 1; + } + break; + case RIGHTARROWKEY: + ui_textedit_move(but, data, 1, event->shift, event->ctrl); + handled= 1; + break; + case LEFTARROWKEY: + ui_textedit_move(but, data, 0, event->shift, event->ctrl); + handled= 1; + break; + case DOWNARROWKEY: + case ENDKEY: + ui_textedit_move_end(but, data, 1, event->shift); + handled= 1; + break; + case UPARROWKEY: + case HOMEKEY: + ui_textedit_move_end(but, data, 0, event->shift); + handled= 1; + break; + case PADENTER: + case RETKEY: + button_activate_state(C, but, BUTTON_STATE_EXIT); + handled= 1; + break; + case DELKEY: + changed= ui_textedit_delete(but, data, 1, 0); + handled= 1; + break; + + case BACKSPACEKEY: + changed= ui_textedit_delete(but, data, 0, event->shift); + handled= 1; + break; + + case TABKEY: + /* there is a key conflict here, we can't tab with autocomplete */ + if(but->autocomplete_func) { + changed= ui_textedit_autocomplete(but, data); + handled= 1; + } + /* the hotkey here is not well defined, was G.qual so we check all */ + else if(event->shift || event->ctrl || event->alt || event->oskey) { + ui_textedit_prev_but(block, but); + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + else { + ui_textedit_next_but(block, but); + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + handled= 1; + break; + } + + if(event->ascii && !handled) { + changed= ui_textedit_type_ascii(but, data, event->ascii); + handled= 1; + } + } + + if(changed) { + if(data->interactive) ui_apply_button(block, but, data, 1); + else ui_check_but(but); + } + + if(changed || handled) + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL); +} + +static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + int mx, my, handled= 0; + + switch(event->type) { + case MOUSEMOVE: { + mx= event->x; + my= event->y; + ui_window_to_block(data->region, block, &mx, &my); + + ui_textedit_set_cursor_select(but, data, mx); + handled= 1; + break; + } + case LEFTMOUSE: + if(event->val == 0) + button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + handled= 1; + break; + } + + if(handled) { + ui_check_but(but); + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL); + } +} + +/* ************* number editing for various types ************* */ + +static void ui_numedit_begin(uiBut *but, uiActivateBut *data) +{ + float butrange; + + if(but->type == BUT_CURVE) { + data->cumap= (CurveMapping*)but->poin; + but->editcumap= data->coba; + } + else if(but->type == BUT_COLORBAND) { + data->coba= (ColorBand*)but->poin; + but->editcoba= data->coba; + } + else if(ELEM(but->type, BUT_NORMAL, HSVCUBE)) { + ui_get_but_vectorf(but, data->origvec); + VECCOPY(data->vec, data->origvec); + but->editvec= data->vec; + } + else { + data->origvalue= ui_get_but_val(but); + data->value= data->origvalue; + but->editval= &data->value; + + butrange= (but->max - but->min); + data->dragfstart= (butrange == 0.0)? 0.0f: (data->value - but->min)/butrange; + data->dragf= data->dragfstart; + } + + data->dragchange= 0; + data->draglock= 1; +} + +static void ui_numedit_end(uiBut *but, uiActivateBut *data) +{ + but->editval= NULL; + but->editvec= NULL; + but->editcoba= NULL; + but->editcumap= NULL; + + data->dragstartx= 0; + data->draglastx= 0; + data->dragchange= 0; + data->dragcbd= NULL; + data->dragsel= 0; +} + +static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiActivateBut *data) +{ + if(data->interactive) ui_apply_button(block, but, data, 1); + else ui_check_but(but); + + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL); +} + +/* ****************** block opening for various types **************** */ + +static void ui_blockopen_begin(bContext *C, uiBut *but, uiActivateBut *data) +{ + uiBlockFuncFP func= NULL; + void *arg= NULL; + + switch(but->type) { + case BLOCK: + case PULLDOWN: + func= but->block_func; + arg= but->poin; + break; + case MENU: + data->origvalue= ui_get_but_val(but); + data->value= data->origvalue; + but->editval= &data->value; + + func= ui_block_func_MENU; + arg= but; + break; + case ICONROW: + func= ui_block_func_ICONROW; + arg= but; + break; + case ICONTEXTROW: + func= ui_block_func_ICONTEXTROW; + arg= but; + break; + case COL: + ui_get_but_vectorf(but, data->origvec); + VECCOPY(data->vec, data->origvec); + but->editvec= data->vec; + + func= ui_block_func_COL; + arg= but; + break; + } + + if(func) + data->blockhandle= ui_menu_block_create(C, data->region, but, func, arg); + + /* this makes adjacent blocks auto open from now on */ + if(but->block->auto_open==0) but->block->auto_open= 1; +} + +static void ui_blockopen_end(bContext *C, uiBut *but, uiActivateBut *data) +{ + if(but) { + but->editval= NULL; + but->editvec= NULL; + + but->block->auto_open_last= PIL_check_seconds_timer(); + } + + if(data->blockhandle) { + ui_menu_block_free(C, data->blockhandle); + data->blockhandle= NULL; + } +} + +/* ***************** events for different button types *************** */ + +static void ui_do_but_BUT(bContext *C, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(event->type == LEFTMOUSE && event->val) + button_activate_state(C, but, BUTTON_STATE_WAIT_RELEASE); + else if(ELEM(event->type, PADENTER, RETKEY) && event->val) + button_activate_state(C, but, BUTTON_STATE_WAIT_FLASH); + } + else if(data->state == BUTTON_STATE_WAIT_RELEASE) { + if(event->type == LEFTMOUSE && event->val==0) { + if(!(but->flag & UI_SELECT)) + data->cancel= 1; + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + } +} + +static void ui_do_but_KEYEVT(bContext *C, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val) + button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT); + } + else if(data->state == BUTTON_STATE_WAIT_KEY_EVENT) { + if(event->type == MOUSEMOVE) + return; + + /* XXX 2.50 missing function */ +#if 0 + if(event->val) { + if(!key_event_to_string(event)[0]) + data->cancel= 1; + else + ui_set_but_val(but, event->type); + + button_activate_state(C, but, BUTTON_STATE_EXIT); + } +#endif + } +} + +static void ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val) + button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + } + else if(data->state == BUTTON_STATE_TEXT_EDITING) + ui_do_but_textedit(C, block, but, data, event); + else if(data->state == BUTTON_STATE_TEXT_SELECTING) + ui_do_but_textedit_select(C, block, but, data, event); +} + +static void ui_do_but_TOG(bContext *C, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val) { + data->togdual= event->ctrl; + data->togonly= !event->shift; + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + } +} + +static void ui_do_but_EXIT(bContext *C, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + if(data->state == BUTTON_STATE_HIGHLIGHT) + if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val) + button_activate_state(C, but, BUTTON_STATE_EXIT); +} + +static int ui_numedit_but_NUM(uiBut *but, uiActivateBut *data, float fac, int snap, int mx) +{ + float deler, tempf; + int lvalue, temp, changed= 0; + + if(mx == data->draglastx) + return changed; + + /* drag-lock - prevent unwanted scroll adjustments */ + /* change value (now 3) to adjust threshold in pixels */ + if(data->draglock) { + if(abs(mx-data->dragstartx) <= 3) + return changed; + + data->draglock= 0; + data->dragstartx= mx; /* ignore mouse movement within drag-lock */ + } + + deler= 500; + if(!ui_is_but_float(but)) { + if((but->max-but->min)<100) deler= 200.0; + if((but->max-but->min)<25) deler= 50.0; + } + deler /= fac; + + if(ui_is_but_float(but) && but->max-but->min > 11) { + /* non linear change in mouse input- good for high precicsion */ + data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.002); + } else if (!ui_is_but_float(but) && but->max-but->min > 129) { /* only scale large int buttons */ + /* non linear change in mouse input- good for high precicsionm ints need less fine tuning */ + data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.004); + } else { + /*no scaling */ + data->dragf+= ((float)(mx-data->draglastx))/deler ; + } + + if(data->dragf>1.0) data->dragf= 1.0; + if(data->dragf<0.0) data->dragf= 0.0; + data->draglastx= mx; + tempf= ( but->min + data->dragf*(but->max-but->min)); + + if(!ui_is_but_float(but)) { + + temp= floor(tempf+.5); + + if(tempf==but->min || tempf==but->max); + else if(snap) { + if(snap == 2) temp= 100*(temp/100); + else temp= 10*(temp/10); + } + if( temp>=but->min && temp<=but->max) { + lvalue= (int)data->value; + + if(temp != lvalue ) { + data->dragchange= 1; + data->value= (double)temp; + changed= 1; + } + } + + } + else { + temp= 0; + if(snap) { + if(snap == 2) { + if(tempf==but->min || tempf==but->max); + else if(but->max-but->min < 2.10) tempf= 0.01*floor(100.0*tempf); + else if(but->max-but->min < 21.0) tempf= 0.1*floor(10.0*tempf); + else tempf= floor(tempf); + } + else { + if(tempf==but->min || tempf==but->max); + else if(but->max-but->min < 2.10) tempf= 0.1*floor(10*tempf); + else if(but->max-but->min < 21.0) tempf= floor(tempf); + else tempf= 10.0*floor(tempf/10.0); + } + } + + if( tempf>=but->min && tempf<=but->max) { + if(tempf != data->value) { + data->dragchange= 1; + data->value= tempf; + changed= 1; + } + } + } + + return changed; +} + +static void ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + int mx, my, click= 0; + + mx= event->x; + my= event->y; + ui_window_to_block(data->region, block, &mx, &my); + + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(event->val) { + if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->shift) { + button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + } + else if(event->type == LEFTMOUSE) { + data->dragstartx= mx; + data->draglastx= mx; + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + } + else if(ELEM(event->type, PADENTER, RETKEY) && event->val) + click= 1; + } + } + else if(data->state == BUTTON_STATE_NUM_EDITING) { + if(event->type == LEFTMOUSE && event->val==0) { + if(data->dragchange) + button_activate_state(C, but, BUTTON_STATE_EXIT); + else + click= 1; + } + else if(event->type == MOUSEMOVE) { + float fac; + int snap; + + fac= 1.0f; + if(event->shift) fac /= 10.0f; + if(event->alt) fac /= 20.0f; + + if(event->custom == EVT_TABLET) { + wmTabletData *wmtab= event->customdata; + + /* de-sensitise based on tablet pressure */ + if (ELEM(wmtab->Active, DEV_STYLUS, DEV_ERASER)) + fac *= wmtab->Pressure; + } + + snap= (event->ctrl)? (event->shift)? 2: 1: 0; + + if(ui_numedit_but_NUM(but, data, fac, snap, mx)) + ui_numedit_apply(C, block, but, data); + } + } + else if(data->state == BUTTON_STATE_TEXT_EDITING) + ui_do_but_textedit(C, block, but, data, event); + else if(data->state == BUTTON_STATE_TEXT_SELECTING) + ui_do_but_textedit_select(C, block, but, data, event); + + if(click) { + /* we can click on the side arrows to increment/decrement, + * or click inside to edit the value directly */ + float tempf; + int temp; + + if(!ui_is_but_float(but)) { + if(mx < (but->x1 + (but->x2 - but->x1)/3 - 3)) { + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + + temp= (int)data->value - 1; + if(temp>=but->min && temp<=but->max) + data->value= (double)temp; + else + data->cancel= 1; + + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + else if(mx > (but->x1 + (2*(but->x2 - but->x1)/3) + 3)) { + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + + temp= (int)data->value + 1; + if(temp>=but->min && temp<=but->max) + data->value= (double)temp; + else + data->cancel= 1; + + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + else + button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + } + else { + if(mx < (but->x1 + (but->x2 - but->x1)/3 - 3)) { + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + + tempf= data->value - 0.01*but->a1; + if (tempf < but->min) tempf = but->min; + data->value= tempf; + + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + else if(mx > but->x1 + (2*((but->x2 - but->x1)/3) + 3)) { + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + + tempf= data->value + 0.01*but->a1; + if (tempf < but->min) tempf = but->min; + data->value= tempf; + + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + else + button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + } + } +} + +static int ui_numedit_but_SLI(uiBut *but, uiActivateBut *data, int shift, int ctrl, int mx) +{ + float deler, f, tempf; + int temp, lvalue, changed= 0; + + if(but->type==NUMSLI) deler= ((but->x2-but->x1)/2 - 5.0*but->aspect); + else if(but->type==HSVSLI) deler= ((but->x2-but->x1)/2 - 5.0*but->aspect); + else deler= (but->x2-but->x1- 5.0*but->aspect); + + f= (float)(mx-data->dragstartx)/deler + data->dragfstart; + + if(shift) + f= (f-data->dragfstart)/10.0 + data->dragfstart; + + CLAMP(f, 0.0, 1.0); + tempf= but->min+f*(but->max-but->min); + temp= floor(tempf+.5); + + if(ctrl) { + if(tempf==but->min || tempf==but->max); + else if(ui_is_but_float(but)) { + + if(shift) { + if(tempf==but->min || tempf==but->max); + else if(but->max-but->min < 2.10) tempf= 0.01*floor(100.0*tempf); + else if(but->max-but->min < 21.0) tempf= 0.1*floor(10.0*tempf); + else tempf= floor(tempf); + } + else { + if(but->max-but->min < 2.10) tempf= 0.1*floor(10*tempf); + else if(but->max-but->min < 21.0) tempf= floor(tempf); + else tempf= 10.0*floor(tempf/10.0); + } + } + else { + temp= 10*(temp/10); + tempf= temp; + } + } + + if(!ui_is_but_float(but)) { + lvalue= floor(data->value+0.5); + + if(temp != lvalue) { + data->value= temp; + data->dragchange= 1; + changed= 1; + } + } + else { + if(tempf != data->value) { + data->value= tempf; + data->dragchange= 1; + changed= 1; + } + } + + return changed; +} + +static void ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + int mx, my, click= 0; + + mx= event->x; + my= event->y; + ui_window_to_block(data->region, block, &mx, &my); + + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val) { + /* start either dragging as slider, or editing as text */ + if(mx>= -6+(but->x1+but->x2)/2) { + if(event->type == LEFTMOUSE) { + data->dragstartx= mx; + data->draglastx= mx; + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + } + else + click= 1; + } + else + button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + } + } + else if(data->state == BUTTON_STATE_NUM_EDITING) { + if(event->type == LEFTMOUSE && event->val==0) { + if(data->dragchange) + button_activate_state(C, but, BUTTON_STATE_EXIT); + else + click= 1; + } + else if(event->type == MOUSEMOVE) { + if(ui_numedit_but_SLI(but, data, event->shift, event->ctrl, mx)) + ui_numedit_apply(C, block, but, data); + } + } + else if(data->state == BUTTON_STATE_TEXT_EDITING) + ui_do_but_textedit(C, block, but, data, event); + else if(data->state == BUTTON_STATE_TEXT_SELECTING) + ui_do_but_textedit_select(C, block, but, data, event); + + if(click) { + float f, h; + float tempf; + int temp; + + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + + tempf= data->value; + temp= (int)data->value; + + h= but->y2-but->y1; + + if(but->type==SLI) f= (float)(mx-but->x1)/(but->x2-but->x1-h); + else f= (float)(mx- (but->x1+but->x2)/2)/((but->x2-but->x1)/2 - h); + + f= but->min+f*(but->max-but->min); + + if(!ui_is_but_float(but)) { + if(f=but->min && temp<=but->max) + data->value= temp; + else + data->cancel= 1; + } + else { + if(f=but->min && tempf<=but->max) + data->value= tempf; + else + data->cancel= 1; + } + + button_activate_state(C, but, BUTTON_STATE_EXIT); + } +} + +static void ui_do_but_BLOCK(bContext *C, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val) + button_activate_state(C, but, BUTTON_STATE_BLOCK_OPEN); + } + else if(data->state == BUTTON_STATE_BLOCK_OPEN) { + if(event->type == MESSAGE) { + uiMenuBlockHandle *handle= event->customdata; + + if(handle == data->blockhandle) { + data->blockretval= handle->blockretval; + + if(handle->blockretval == UI_RETURN_OK) { + if(but->type == COL) + VECCOPY(data->vec, handle->retvec) + else if(ELEM3(but->type, MENU, ICONROW, ICONTEXTROW)) + data->value= handle->retvalue; + } + + if(handle->blockretval == UI_RETURN_OUT) + /* we close the block and proceed as if nothing happened */ + button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT); + else + /* ok/cancel, we exit and will send message in _exit */ + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + } + } +} + +static int ui_numedit_but_NORMAL(uiBut *but, uiActivateBut *data, int mx, int my) +{ + float dx, dy, rad, radsq, mrad, *fp; + int mdx, mdy, changed= 1; + + /* button is presumed square */ + /* if mouse moves outside of sphere, it does negative normal */ + + fp= data->origvec; + rad= (but->x2 - but->x1); + radsq= rad*rad; + + if(fp[2]>0.0f) { + mdx= (rad*fp[0]); + mdy= (rad*fp[1]); + } + else if(fp[2]> -1.0f) { + mrad= rad/sqrt(fp[0]*fp[0] + fp[1]*fp[1]); + + mdx= 2.0f*mrad*fp[0] - (rad*fp[0]); + mdy= 2.0f*mrad*fp[1] - (rad*fp[1]); + } + else mdx= mdy= 0; + + dx= (float)(mx+mdx-data->dragstartx); + dy= (float)(my+mdy-data->dragstarty); + + fp= data->vec; + mrad= dx*dx+dy*dy; + if(mrad < radsq) { /* inner circle */ + fp[0]= dx; + fp[1]= dy; + fp[2]= sqrt( radsq-dx*dx-dy*dy ); + } + else { /* outer circle */ + + mrad= rad/sqrt(mrad); // veclen + + dx*= (2.0f*mrad - 1.0f); + dy*= (2.0f*mrad - 1.0f); + + mrad= dx*dx+dy*dy; + if(mrad < radsq) { + fp[0]= dx; + fp[1]= dy; + fp[2]= -sqrt( radsq-dx*dx-dy*dy ); + } + } + Normalize(fp); + + data->draglastx= mx; + data->draglasty= my; + + return changed; +} + +static void ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + int mx, my; + + mx= event->x; + my= event->y; + ui_window_to_block(data->region, block, &mx, &my); + + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(event->type==LEFTMOUSE && event->val) { + data->dragstartx= mx; + data->dragstarty= my; + data->draglastx= mx; + data->draglasty= my; + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + + /* also do drag the first time */ + if(ui_numedit_but_NORMAL(but, data, mx, my)) + ui_numedit_apply(C, block, but, data); + } + } + else if(data->state == BUTTON_STATE_NUM_EDITING) { + if(event->type == MOUSEMOVE) { + if(mx!=data->draglastx || my!=data->draglasty) { + if(ui_numedit_but_NORMAL(but, data, mx, my)) + ui_numedit_apply(C, block, but, data); + } + } + else if(event->type==LEFTMOUSE && event->val==0) + button_activate_state(C, but, BUTTON_STATE_EXIT); + } +} + +static int ui_numedit_but_HSVCUBE(uiBut *but, uiActivateBut *data, int mx, int my) +{ + float x, y; + int changed= 1; + + /* relative position within box */ + x= ((float)mx-but->x1)/(but->x2-but->x1); + y= ((float)my-but->y1)/(but->y2-but->y1); + CLAMP(x, 0.0, 1.0); + CLAMP(y, 0.0, 1.0); + + if(but->a1==0) { + but->hsv[0]= x; + but->hsv[2]= y; + } + else if(but->a1==1) { + but->hsv[0]= x; + but->hsv[1]= y; + } + else if(but->a1==2) { + but->hsv[2]= x; + but->hsv[1]= y; + } + else + but->hsv[0]= x; + + ui_set_but_hsv(but); // converts to rgb + + // update button values and strings + ui_update_block_buts_hsv(but->block, but->hsv); + + data->draglastx= mx; + data->draglasty= my; + + return changed; +} + +static void ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + int mx, my; + + mx= event->x; + my= event->y; + ui_window_to_block(data->region, block, &mx, &my); + + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(event->type==LEFTMOUSE && event->val) { + data->dragstartx= mx; + data->dragstarty= my; + data->draglastx= mx; + data->draglasty= my; + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + + /* also do drag the first time */ + if(ui_numedit_but_HSVCUBE(but, data, mx, my)) + ui_numedit_apply(C, block, but, data); + } + } + else if(data->state == BUTTON_STATE_NUM_EDITING) { + if(event->type == MOUSEMOVE) { + if(mx!=data->draglastx || my!=data->draglasty) { + if(ui_numedit_but_HSVCUBE(but, data, mx, my)) + ui_numedit_apply(C, block, but, data); + } + } + else if(event->type==LEFTMOUSE && event->val==0) + button_activate_state(C, but, BUTTON_STATE_EXIT); + } +} + +static int verg_colorband(const void *a1, const void *a2) +{ + const CBData *x1=a1, *x2=a2; + + if( x1->pos > x2->pos ) return 1; + else if( x1->pos < x2->pos) return -1; + return 0; +} + +static void ui_colorband_update(ColorBand *coba) +{ + int a; + + if(coba->tot<2) return; + + for(a=0; atot; a++) coba->data[a].cur= a; + qsort(coba->data, coba->tot, sizeof(CBData), verg_colorband); + for(a=0; atot; a++) { + if(coba->data[a].cur==coba->cur) { + coba->cur= a; + break; + } + } +} + +static int ui_numedit_but_COLORBAND(uiBut *but, uiActivateBut *data, int mx) +{ + float dx; + int changed= 0; + + if(data->draglastx == mx) + return changed; + + dx= ((float)(mx - data->draglastx))/(but->x2-but->x1); + data->dragcbd->pos += dx; + CLAMP(data->dragcbd->pos, 0.0, 1.0); + + ui_colorband_update(data->coba); + data->dragcbd= data->coba->data + data->coba->cur; /* because qsort */ + + data->draglastx= mx; + changed= 1; + + return changed; +} + +static void ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + ColorBand *coba; + CBData *cbd; + int mx, my, a, xco, mindist= 12; + + mx= event->x; + my= event->y; + ui_window_to_block(data->region, block, &mx, &my); + + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(event->type==LEFTMOUSE && event->val) { + coba= (ColorBand*)but->poin; + + if(event->ctrl) { + /* insert new key on mouse location */ + if(coba->tot < MAXCOLORBAND-1) { + float pos= ((float)(mx - but->x1))/(but->x2-but->x1); + float col[4]; + + do_colorband(coba, pos, col); /* executes it */ + + coba->tot++; + coba->cur= coba->tot-1; + + coba->data[coba->cur].r= col[0]; + coba->data[coba->cur].g= col[1]; + coba->data[coba->cur].b= col[2]; + coba->data[coba->cur].a= col[3]; + coba->data[coba->cur].pos= pos; + + ui_colorband_update(coba); + } + + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + else { + data->dragstartx= mx; + data->dragstarty= my; + data->draglastx= mx; + data->draglasty= my; + + /* activate new key when mouse is close */ + for(a=0, cbd= coba->data; atot; a++, cbd++) { + xco= but->x1 + (cbd->pos*(but->x2-but->x1)); + xco= ABS(xco-mx); + if(a==coba->cur) xco+= 5; // selected one disadvantage + if(xcocur= a; + mindist= xco; + } + } + + data->dragcbd= coba->data + coba->cur; + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + } + } + } + else if(data->state == BUTTON_STATE_NUM_EDITING) { + if(event->type == MOUSEMOVE) { + if(mx!=data->draglastx || my!=data->draglasty) { + if(ui_numedit_but_COLORBAND(but, data, mx)) + ui_numedit_apply(C, block, but, data); + } + } + else if(event->type==LEFTMOUSE && event->val==0) + button_activate_state(C, but, BUTTON_STATE_EXIT); + } +} + +static int ui_numedit_but_CURVE(uiBut *but, uiActivateBut *data, int snap, int mx, int my) +{ + CurveMapping *cumap= data->cumap; + CurveMap *cuma= cumap->cm+cumap->cur; + CurveMapPoint *cmp= cuma->curve; + float fx, fy, zoomx, zoomy, offsx, offsy; + int a, changed= 0; + + zoomx= (but->x2-but->x1)/(cumap->curr.xmax-cumap->curr.xmin); + zoomy= (but->y2-but->y1)/(cumap->curr.ymax-cumap->curr.ymin); + offsx= cumap->curr.xmin; + offsy= cumap->curr.ymin; + + if(data->dragsel != -1) { + int moved_point= 0; /* for ctrl grid, can't use orig coords because of sorting */ + + fx= (mx-data->draglastx)/zoomx; + fy= (my-data->draglasty)/zoomy; + for(a=0; atotpoint; a++) { + if(cmp[a].flag & SELECT) { + float origx= cmp[a].x, origy= cmp[a].y; + cmp[a].x+= fx; + cmp[a].y+= fy; + if(snap) { + cmp[a].x= 0.125f*floor(0.5f + 8.0f*cmp[a].x); + cmp[a].y= 0.125f*floor(0.5f + 8.0f*cmp[a].y); + } + if(cmp[a].x!=origx || cmp[a].y!=origy) + moved_point= 1; + } + } + + curvemapping_changed(cumap, 0); /* no remove doubles */ + + if(moved_point) { + data->draglastx= mx; + data->draglasty= my; + changed= 1; + } + + data->dragchange= 1; /* mark for selection */ + } + else { + fx= (mx-data->draglastx)/zoomx; + fy= (my-data->draglasty)/zoomy; + + /* clamp for clip */ + if(cumap->flag & CUMA_DO_CLIP) { + if(cumap->curr.xmin-fx < cumap->clipr.xmin) + fx= cumap->curr.xmin - cumap->clipr.xmin; + else if(cumap->curr.xmax-fx > cumap->clipr.xmax) + fx= cumap->curr.xmax - cumap->clipr.xmax; + if(cumap->curr.ymin-fy < cumap->clipr.ymin) + fy= cumap->curr.ymin - cumap->clipr.ymin; + else if(cumap->curr.ymax-fy > cumap->clipr.ymax) + fy= cumap->curr.ymax - cumap->clipr.ymax; + } + + cumap->curr.xmin-=fx; + cumap->curr.ymin-=fy; + cumap->curr.xmax-=fx; + cumap->curr.ymax-=fy; + + data->draglastx= mx; + data->draglasty= my; + + changed= 1; + } + + return changed; +} + +static void ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + int mx, my, a, changed= 0; + + mx= event->x; + my= event->y; + ui_window_to_block(data->region, block, &mx, &my); + + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(event->type==LEFTMOUSE && event->val) { + CurveMapping *cumap= (CurveMapping*)but->poin; + CurveMap *cuma= cumap->cm+cumap->cur; + CurveMapPoint *cmp= cuma->curve; + float fx, fy, zoomx, zoomy, offsx, offsy; + float dist, mindist= 200.0f; // 14 pixels radius + int sel= -1; + + zoomx= (but->x2-but->x1)/(cumap->curr.xmax-cumap->curr.xmin); + zoomy= (but->y2-but->y1)/(cumap->curr.ymax-cumap->curr.ymin); + offsx= cumap->curr.xmin; + offsy= cumap->curr.ymin; + + if(event->ctrl) { + fx= ((float)my - but->x1)/zoomx + offsx; + fy= ((float)my - but->y1)/zoomy + offsy; + + curvemap_insert(cuma, fx, fy); + curvemapping_changed(cumap, 0); + changed= 1; + } + + /* check for selecting of a point */ + cmp= cuma->curve; /* ctrl adds point, new malloc */ + for(a=0; atotpoint; a++) { + fx= but->x1 + zoomx*(cmp[a].x-offsx); + fy= but->y1 + zoomy*(cmp[a].y-offsy); + dist= (fx-mx)*(fx-mx) + (fy-my)*(fy-my); + if(dist < mindist) { + sel= a; + mindist= dist; + } + } + + if (sel == -1) { + /* if the click didn't select anything, check if it's clicked on the + * curve itself, and if so, add a point */ + fx= ((float)mx - but->x1)/zoomx + offsx; + fy= ((float)my - but->y1)/zoomy + offsy; + + cmp= cuma->table; + + /* loop through the curve segment table and find what's near the mouse. + * 0.05 is kinda arbitrary, but seems to be what works nicely. */ + for(a=0; a<=CM_TABLE; a++) { + if ( ( fabs(fx - cmp[a].x) < (0.05) ) && ( fabs(fy - cmp[a].y) < (0.05) ) ) { + + curvemap_insert(cuma, fx, fy); + curvemapping_changed(cumap, 0); + + changed= 1; + + /* reset cmp back to the curve points again, rather than drawing segments */ + cmp= cuma->curve; + + /* find newly added point and make it 'sel' */ + for(a=0; atotpoint; a++) + if(cmp[a].x == fx) + sel = a; + + break; + } + } + } + + if(sel!= -1) { + /* ok, we move a point */ + /* deselect all if this one is deselect. except if we hold shift */ + if(event->shift==0 && (cmp[sel].flag & SELECT)==0) + for(a=0; atotpoint; a++) + cmp[a].flag &= ~SELECT; + cmp[sel].flag |= SELECT; + } + else { + /* move the view */ + data->cancel= 1; + } + + data->dragsel= sel; + + data->dragstartx= mx; + data->dragstarty= my; + data->draglastx= mx; + data->draglasty= my; + + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + } + } + else if(data->state == BUTTON_STATE_NUM_EDITING) { + if(event->type == MOUSEMOVE) { + if(mx!=data->draglastx || my!=data->draglasty) { + if(ui_numedit_but_CURVE(but, data, event->shift, mx, my)) + ui_numedit_apply(C, block, but, data); + } + } + else if(event->type==LEFTMOUSE && event->val==0) { + if(data->dragsel != -1) { + CurveMapping *cumap= data->cumap; + CurveMap *cuma= cumap->cm+cumap->cur; + CurveMapPoint *cmp= cuma->curve; + + if(!data->dragchange) { + /* deselect all, select one */ + if(event->shift==0) { + for(a=0; atotpoint; a++) + cmp[a].flag &= ~SELECT; + cmp[data->dragsel].flag |= SELECT; + } + } + else + curvemapping_changed(cumap, 1); /* remove doubles */ + } + + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + } +} + +#ifdef INTERNATIONAL +static void ui_do_but_CHARTAB(bContext *C, uiBlock *block, uiBut *but, uiActivateBut *data, wmEvent *event) +{ + /* XXX 2.50 bad global and state access */ +#if 0 + float sx, sy, ex, ey; + float width, height; + float butw, buth; + int mx, my, x, y, cs, che; + + mx= event->x; + my= event->y; + ui_window_to_block(data->region, block, &mx, &my); + + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val) { + /* Calculate the size of the button */ + width = abs(but->x2 - but->x1); + height = abs(but->y2 - but->y1); + + butw = floor(width / 12); + buth = floor(height / 6); + + /* Initialize variables */ + sx = but->x1; + ex = but->x1 + butw; + sy = but->y1 + height - buth; + ey = but->y1 + height; + + cs = G.charstart; + + /* And the character is */ + x = (int) ((mx / butw) - 0.5); + y = (int) (6 - ((my / buth) - 0.5)); + + che = cs + (y*12) + x; + + if(che > G.charmax) + che = 0; + + if(G.obedit) + { + do_textedit(0,0,che); + } + + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + else if(ELEM(event->type, WHEELUPMOUSE, PAGEUPKEY)) { + for(but= block->buttons.first; but; but= but->next) { + if(but->type == CHARTAB) { + G.charstart = G.charstart - (12*6); + if(G.charstart < 0) + G.charstart = 0; + if(G.charstart < G.charmin) + G.charstart = G.charmin; + ui_draw_but(but); + + //Really nasty... to update the num button from the same butblock + for(bt= block->buttons.first; bt; bt= bt->next) + { + if(ELEM(bt->type, NUM, NUMABS)) { + ui_check_but(bt); + ui_draw_but(bt); + } + } + retval=UI_CONT; + break; + } + } + break; + } + else if(ELEM(event->type, WHEELDOWNMOUSE, PAGEDOWNKEY)) { + for(but= block->buttons.first; but; but= but->next) + { + if(but->type == CHARTAB) + { + G.charstart = G.charstart + (12*6); + if(G.charstart > (0xffff - 12*6)) + G.charstart = 0xffff - (12*6); + if(G.charstart > G.charmax - 12*6) + G.charstart = G.charmax - 12*6; + ui_draw_but(but); + + for(bt= block->buttons.first; bt; bt= bt->next) + { + if(ELEM(bt->type, NUM, NUMABS)) { + ui_check_but(bt); + ui_draw_but(bt); + } + } + + but->flag |= UI_ACTIVE; + retval=UI_RETURN_OK; + break; + } + } + break; + } + } +#endif +} +#endif + +static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) +{ + uiActivateBut *data; + int handled; + + data= but->activate; + handled= 0; + + /* handle copy-paste */ + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(ELEM(event->type, CKEY, VKEY) && event->val && (event->ctrl || event->oskey)) { + ui_but_copy_paste(C, but, data, (event->type == CKEY)? 'c': 'v'); + return 1; + } + } + + /* these events are swallowed */ + if(ELEM5(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE, WHEELUPMOUSE, WHEELDOWNMOUSE)) + handled= 1; + else if(ELEM(event->type, PADENTER, RETKEY)) + handled= 1; + + /* verify if we can edit this button */ + if(but->lock) { + if(but->lockstr) { + WM_report(C, WM_LOG_WARNING, but->lockstr); + button_activate_state(C, but, BUTTON_STATE_EXIT); + return handled; + } + } + else if(but->pointype && but->poin==0) { + /* there's a pointer needed */ + WM_reportf(C, WM_LOG_WARNING, "DoButton pointer error: %s", but->str); + button_activate_state(C, but, BUTTON_STATE_EXIT); + return handled; + } + + switch(but->type) { + case BUT: + ui_do_but_BUT(C, but, data, event); + break; + case KEYEVT: + ui_do_but_KEYEVT(C, but, data, event); + break; + case TOG: + case TOGR: + case ICONTOG: + case ICONTOGN: + case TOGN: + case BUT_TOGDUAL: + ui_do_but_TOG(C, but, data, event); + break; +#if 0 + case SCROLL: + /* DrawBut(b, 1); */ + /* do_scrollbut(b); */ + /* DrawBut(b,0); */ + break; +#endif + case NUM: + case NUMABS: + ui_do_but_NUM(C, block, but, data, event); + break; + case SLI: + case NUMSLI: + case HSVSLI: + ui_do_but_SLI(C, block, but, data, event); + break; + case ROUNDBOX: + case LABEL: + case TOG3: + case ROW: + ui_do_but_EXIT(C, but, data, event); + break; + case TEX: + case IDPOIN: + ui_do_but_TEX(C, block, but, data, event); + break; + case MENU: + ui_do_but_BLOCK(C, but, data, event); + break; + case ICONROW: + ui_do_but_BLOCK(C, but, data, event); + break; + case ICONTEXTROW: + ui_do_but_BLOCK(C, but, data, event); + break; + case BLOCK: + case PULLDOWN: + ui_do_but_BLOCK(C, but, data, event); + break; + case BUTM: + ui_do_but_BUT(C, but, data, event); + break; + case COL: + if(but->a1 == -1) // signal to prevent calling up color picker + ui_do_but_EXIT(C, but, data, event); + else + ui_do_but_BLOCK(C, but, data, event); + break; + case BUT_NORMAL: + ui_do_but_NORMAL(C, block, but, data, event); + break; + case BUT_COLORBAND: + ui_do_but_COLORBAND(C, block, but, data, event); + break; + case BUT_CURVE: + ui_do_but_CURVE(C, block, but, data, event); + break; + case HSVCUBE: + ui_do_but_HSVCUBE(C, block, but, data, event); + break; +#ifdef INTERNATIONAL + case CHARTAB: + ui_do_but_CHARTAB(C, block, but, data, event); + break; +#endif + /* XXX 2.50 links not implemented yet */ +#if 0 + case LINK: + case INLINK: + retval= ui_do_but_LINK(block, but); + break; +#endif + } + + return handled; +} + +/* ************************ button utilities *********************** */ + +static int ui_but_contains_pt(uiBut *but, int mx, int my) +{ + return ((but->x1x2>=mx) && (but->y1y2>=my)); +} + +static uiBut *ui_but_find_activated(ARegion *ar, uiActivateBut *data, uiBlock **rblock) +{ + uiBlock *block; + uiBut *but; + + for(block=ar->uiblocks.first; block; block=block->next) { + for(but=block->buttons.first; but; but= but->next) { + if((but->activate == data && data) || (but->activate && data == NULL)) { + if(rblock) *rblock= block; + return but; + } + } + } + + if(rblock) *rblock= NULL; + return NULL; +} + +static uiBut *ui_but_find_signal(ARegion *ar, uiActivateBut *data, uiBlock **rblock) +{ + uiBlock *block; + uiBut *but; + + for(block=ar->uiblocks.first; block; block=block->next) { + for(but=block->buttons.first; but; but= but->next) { + if(but->activateflag) { + if(rblock) *rblock= block; + return but; + } + } + } + + if(rblock) *rblock= NULL; + return NULL; +} + +static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y, uiBlock **rblock) +{ + uiBlock *block, *blockover= NULL; + uiBut *but, *butover= NULL; + int mx, my; + + for(block=ar->uiblocks.first; block; block=block->next) { + mx= x; + my= y; + ui_window_to_block(ar, block, &mx, &my); + + for(but=block->buttons.first; but; but= but->next) { + /* give precedence to already activated buttons */ + if(ui_but_contains_pt(but, mx, my)) { + if(!butover || (!butover->activate && but->activate)) { + butover= but; + blockover= block; + } + } + } + } + + if(rblock) + *rblock= blockover; + + return butover; +} + +/*********************** button activate operator *************************** + * this operator runs from the moment the mouse is position over a button and + * handles all interaction with the button, from highlight to text editing, + * dragging, having a block open to leaving the button to activate another. */ + +static void button_disable_timers(bContext *C, uiActivateBut *data) +{ + if(data->tooltiptimer) { + WM_event_remove_window_timer(C->window, data->tooltiptimer); + data->tooltiptimer= NULL; + } + if(data->tooltip) { + ui_tooltip_free(C, data->tooltip); + data->tooltip= NULL; + } + data->tooltipdisabled= 1; + + if(data->autoopentimer) { + WM_event_remove_window_timer(C->window, data->autoopentimer); + data->autoopentimer= NULL; + } +} + +static void button_activate_state(bContext *C, uiBut *but, uiActivateButState state) +{ + uiActivateBut *data; + + data= but->activate; + if(data->state == state) + return; + + if(state == BUTTON_STATE_HIGHLIGHT) { + but->flag &= ~UI_SELECT; + + /* XXX 2.50 U missing from context */ + if(U.flag & USER_TOOLTIPS) + if(!data->tooltiptimer && !data->tooltipdisabled) + data->tooltiptimer= WM_event_add_window_timer(C->window, BUTTON_TOOLTIP_DELAY, ~0); + + /* automatic open pulldown block timer */ + if(but->type==BLOCK || but->type==MENU || but->type==PULLDOWN || but->type==ICONTEXTROW) { + if(!data->autoopentimer) { + int time; + + if(but->block->auto_open==2) time= 1; // test for toolbox + else if(but->block->flag & UI_BLOCK_LOOP || but->block->auto_open) time= 5*U.menuthreshold2; + else if(U.uiflag & USER_MENUOPENAUTO) time= 5*U.menuthreshold1; + else time= -1; + + if(time >= 0) + data->autoopentimer= WM_event_add_window_timer(C->window, time*20, ~0); + } + } + } + else { + but->flag |= UI_SELECT; + button_disable_timers(C, data); + } + + if(state == BUTTON_STATE_TEXT_EDITING && data->state != BUTTON_STATE_TEXT_SELECTING) + ui_textedit_begin(but, data); + else if(data->state == BUTTON_STATE_TEXT_EDITING && state != BUTTON_STATE_TEXT_SELECTING) + ui_textedit_end(but, data); + + if(state == BUTTON_STATE_NUM_EDITING) + ui_numedit_begin(but, data); + else if(data->state == BUTTON_STATE_NUM_EDITING) + ui_numedit_end(but, data); + + if(state == BUTTON_STATE_BLOCK_OPEN) { + ui_blockopen_begin(C, but, data); + /* note we move the handler to the region when the block is open, + * so we don't interfere with the events as long as it's open */ + WM_event_remove_modal_handler(&C->window->handlers, data->operator); + WM_event_add_modal_handler(&data->region->handlers, data->operator); + } + else if(data->state == BUTTON_STATE_BLOCK_OPEN) { + ui_blockopen_end(C, but, data); + WM_event_remove_modal_handler(&data->region->handlers, data->operator); + WM_event_add_modal_handler(&C->window->handlers, data->operator); + } + + if(state == BUTTON_STATE_WAIT_FLASH) { + data->flashtimer= WM_event_add_window_timer(C->window, BUTTON_FLASH_DELAY, ~0); + } + else if(data->flashtimer) { + WM_event_remove_window_timer(C->window, data->flashtimer); + data->flashtimer= NULL; + } + + data->state= state; + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL); +} + +static void button_activate_init(bContext *C, ARegion *ar, wmOperator *op, uiBut *but, uiBut *lastbut) +{ + uiActivateBut *data; + + /* setup struct */ + data= MEM_callocN(sizeof(uiActivateBut), "uiActivateBut"); + data->region= ar; + data->operator= op; + data->interactive= 0; + data->state = BUTTON_STATE_INIT; + op->customdata= data; + + /* activate button */ + but->flag |= UI_ACTIVE; + but->activate= data; + + if(but == lastbut) + data->tooltipdisabled= 1; + + /* we disable auto_open in the block after a threshold, because we still + * want to allow auto opening adjacent menus even if no button is activated + * inbetween going over to the other button, but only for a short while */ + if(!lastbut && but->block->auto_open) + if(but->block->auto_open_last+BUTTON_AUTO_OPEN_THRESH < PIL_check_seconds_timer()) + but->block->auto_open= 0; + + /* modal handler */ + WM_event_add_modal_handler(&C->window->handlers, op); + + button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT); + + if(but->activateflag == UI_ACTIVATE_OPEN) + button_activate_state(C, but, BUTTON_STATE_BLOCK_OPEN); + else if(but->activateflag == UI_ACTIVATE_TEXT_EDITING) + button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + else if(but->activateflag == UI_ACTIVATE_APPLY) + button_activate_state(C, but, BUTTON_STATE_WAIT_FLASH); + + but->activateflag= 0; +} + +static void button_activate_exit(bContext *C, uiActivateBut *data, wmOperator *op) +{ + uiBut *but; + uiBlock *block; + + /* verify if we still have a button, can be NULL! */ + but= ui_but_find_activated(data->region, data, &block); + + /* stop text editing */ + if(data->state == BUTTON_STATE_TEXT_EDITING || data->state == BUTTON_STATE_TEXT_SELECTING) { + data->cancel= 1; + ui_textedit_end(but, data); + } + + if(data->state == BUTTON_STATE_NUM_EDITING) + ui_numedit_end(but, data); + + if(data->state == BUTTON_STATE_BLOCK_OPEN) { + ui_blockopen_end(C, but, data); + WM_event_remove_modal_handler(&data->region->handlers, data->operator); + } + else + WM_event_remove_modal_handler(&C->window->handlers, op); + + if(but) { + /* if someone is expecting a message */ + if(but->block->handle && !(but->block->flag & UI_BLOCK_KEEP_OPEN) && !data->cancel) { + uiMenuBlockHandle *handle; + + handle= but->block->handle; + handle->butretval= data->retval; + if(data->blockretval) { + handle->blockretval= data->blockretval; + + /* if we got a cancel from a block menu, then also cancel this + * button, we set that here to instead of in do_BLOCK to make + * a distinction with cancel after lost highlight for example */ + if(data->blockretval == UI_RETURN_CANCEL) + data->cancel= 1; + } + else + handle->blockretval= UI_RETURN_OK; + + WM_event_add_message(C->wm, handle, 0); + } + + /* apply the button action or value */ + ui_apply_button(block, but, data, 0); + + /* clean up button */ + but->activate= NULL; + but->flag &= ~(UI_ACTIVE|UI_SELECT); + } + + /* redraw */ + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL); + + /* clean up */ + button_disable_timers(C, data); + + if(data->str) + MEM_freeN(data->str); + if(data->origstr) + MEM_freeN(data->origstr); + if(data->flashtimer) + WM_event_remove_window_timer(C->window, data->flashtimer); + + MEM_freeN(op->customdata); + op->customdata= NULL; +} + +static int button_activate_try_init(bContext *C, ARegion *ar, wmOperator *op, wmEvent *event, uiBut *lastbut) +{ + uiBut *but; + + /* try to activate a button */ + if(!ar) + return OPERATOR_PASS_THROUGH; + + if(ui_but_find_activated(ar, NULL, NULL)) + return OPERATOR_PASS_THROUGH; + + but= ui_but_find_signal(ar, NULL, NULL); + + if(!but) + but= ui_but_find_mouse_over(ar, event->x, event->y, NULL); + + if(lastbut && but && but!=lastbut) + return OPERATOR_PASS_THROUGH; + + if(but && !but->activate) { + button_activate_init(C, ar, op, but, lastbut); + return OPERATOR_RUNNING_MODAL; + } + + return OPERATOR_PASS_THROUGH; +} + +static int button_activate_try_exit(bContext *C, wmOperator *op, wmEvent *event) +{ + ARegion *ar; + uiActivateBut *data; + uiBut *but; + int state; + + data= op->customdata; + ar= data->region; + + but= ui_but_find_activated(data->region, data, NULL); + + /* exit the current button, but try to re-init as well */ + button_activate_exit(C, op->customdata, op); + state= button_activate_try_init(C, ar, op, event, but); + + return (state != OPERATOR_RUNNING_MODAL); +} + +static int button_activate_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + return button_activate_try_init(C, C->region, op, event, NULL); +} + +static int button_activate_cancel(bContext *C, wmOperator *op) +{ + uiActivateBut *data; + + data= op->customdata; + data->cancel= 1; + button_activate_exit(C, op->customdata, op); + + return OPERATOR_CANCELLED; +} + +static int button_activate_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + uiActivateBut *data; + uiBut *but; + uiBlock *block; + int handled= 0; + + data= op->customdata; + + /* check if the button dissappeared somehow */ + if(!(but= ui_but_find_activated(data->region, data, &block))) { + data->cancel= 1; + if(button_activate_try_exit(C, op, event)) + return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH; + else + return OPERATOR_RUNNING_MODAL|OPERATOR_PASS_THROUGH; + } + + if(data->state == BUTTON_STATE_HIGHLIGHT) { + switch(event->type) { + case MOUSEMOVE: + /* verify if we are still over the button, if not exit */ + but= ui_but_find_mouse_over(data->region, event->x, event->y, &block); + + if(!but || but->activate != data) { + data->cancel= 1; + if(button_activate_try_exit(C, op, event)) + return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH; + else + return OPERATOR_RUNNING_MODAL|OPERATOR_PASS_THROUGH; + } + break; + case TIMER: { + /* handle tooltip timer */ + if(event->customdata == data->tooltiptimer) { + if(!data->tooltip) { + data->tooltip= ui_tooltip_create(C, data->region, but); + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL); + } + + WM_event_remove_window_timer(C->window, data->tooltiptimer); + data->tooltiptimer= NULL; + } + else if(event->customdata == data->autoopentimer) { + button_activate_state(C, but, BUTTON_STATE_BLOCK_OPEN); + + WM_event_remove_window_timer(C->window, data->autoopentimer); + data->autoopentimer= NULL; + } + + break; + } + } + + handled= ui_do_button(C, block, but, event); + } + else if(data->state == BUTTON_STATE_WAIT_RELEASE) { + switch(event->type) { + case MOUSEMOVE: + /* deselect the button when moving the mouse away */ + but= ui_but_find_mouse_over(data->region, event->x, event->y, &block); + + if(but && but->activate == data) { + if(!(but->flag & UI_SELECT)) { + but->flag |= UI_SELECT; + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL); + } + } + else { + but= ui_but_find_activated(data->region, data, &block); + if(but->flag & UI_SELECT) { + but->flag &= ~UI_SELECT; + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL); + } + } + break; + } + + ui_do_button(C, block, but, event); + handled= 1; + } + else if(data->state == BUTTON_STATE_WAIT_FLASH) { + switch(event->type) { + case TIMER: { + if(event->customdata == data->flashtimer) + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + } + } + else if(data->state == BUTTON_STATE_BLOCK_OPEN) { + switch(event->type) { + case MOUSEMOVE: { + uiBut *bt= ui_but_find_mouse_over(data->region, event->x, event->y, &block); + + if(bt && bt->activate != data) { + data->cancel= 1; + if(button_activate_try_exit(C, op, event)) + return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH; + else + return OPERATOR_RUNNING_MODAL|OPERATOR_PASS_THROUGH; + } + break; + } + } + + ui_do_button(C, block, but, event); + handled= 0; + } + else { + ui_do_button(C, block, but, event); + handled= 1; + } + + if(data->state == BUTTON_STATE_EXIT) { + if(button_activate_try_exit(C, op, event)) + return OPERATOR_CANCELLED|(handled==0? OPERATOR_PASS_THROUGH: 0); + else + return OPERATOR_RUNNING_MODAL|(handled==0? OPERATOR_PASS_THROUGH: 0); + } + + if(handled) + return OPERATOR_RUNNING_MODAL; + else + return OPERATOR_RUNNING_MODAL|OPERATOR_PASS_THROUGH; +} + +static int button_activate_poll(bContext *C) +{ + if(C->region==NULL) return 0; + if(C->region->uiblocks.first==NULL) return 0; + return 1; +} + +void ED_UI_OT_button_activate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Button Highlight"; + ot->idname= "ED_UI_OT_button_activate"; + + /* api callbacks */ + ot->invoke= button_activate_invoke; + ot->cancel= button_activate_cancel; + ot->modal= button_activate_modal; + ot->poll= button_activate_poll; +} + +/* ******************** menu navigation helpers ************** */ + +static uiBut *ui_but_prev(uiBut *but) +{ + while(but->prev) { + but= but->prev; + if(but->type!=LABEL && but->type!=SEPR && but->type!=ROUNDBOX) return but; + } + return NULL; +} + +static uiBut *ui_but_next(uiBut *but) +{ + while(but->next) { + but= but->next; + if(but->type!=LABEL && but->type!=SEPR && but->type!=ROUNDBOX) return but; + } + return NULL; +} + +static uiBut *ui_but_first(uiBlock *block) +{ + uiBut *but; + + but= block->buttons.first; + while(but) { + if(but->type!=LABEL && but->type!=SEPR && but->type!=ROUNDBOX) return but; + but= but->next; + } + return NULL; +} + +static uiBut *ui_but_last(uiBlock *block) +{ + uiBut *but; + + but= block->buttons.last; + while(but) { + if(but->type!=LABEL && but->type!=SEPR && but->type!=ROUNDBOX) return but; + but= but->prev; + } + return NULL; +} + +/* ********************** menu navigate operator ***************************** + * this operator is invoked when the block/region is opened and cancelled when + * it closes, it blocks nearly all events. this operator will not close the + * actual block, instead this must be done by the button activate operator when + * it receives the result message */ + +typedef struct uiBlockHandle { + ARegion *region; + + int towardsx, towardsy; + double towardstime; + int dotowards; +} uiBlockHandle; + +static int menu_block_handle_cancel(bContext *C, wmOperator *op) +{ + if(op->customdata) { + MEM_freeN(op->customdata); + op->customdata= NULL; + WM_event_remove_modal_handler(&C->window->handlers, op); + } + + return OPERATOR_CANCELLED; +} + +static void menu_block_handle_return(bContext *C, wmOperator *op, uiBlock *block, int retval) +{ + uiMenuBlockHandle *handle; + + handle= block->handle; + handle->blockretval= retval; + handle->butretval= 0; + + WM_event_add_message(C->wm, handle, 0); + menu_block_handle_cancel(C, op); +} + +static int menu_block_handle_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + uiMenuBlockHandle *handle; + + handle= MEM_callocN(sizeof(uiBlockHandle), "uiBlockHandle"); + handle->region= C->region; + + op->customdata= handle; + WM_event_add_modal_handler(&C->window->handlers, op); + + return OPERATOR_RUNNING_MODAL|OPERATOR_PASS_THROUGH; +} + +static int menu_block_handle_block_open(uiBlock *block) +{ + uiBut *but; + uiActivateBut *data; + + for(but=block->buttons.first; but; but=but->next) { + data= but->activate; + + if(data && data->state == BUTTON_STATE_BLOCK_OPEN) + return 1; + } + + return 0; +} + +static void menu_block_handle_activate_button(bContext *C, wmEvent *event, ARegion *butregion, uiBut *but, int activateflag) +{ + wmOperatorType *ot; + + ot= WM_operatortype_find("ED_UI_OT_button_activate"); + + WM_operator_cancel(C, &butregion->modalops, ot); + but->activateflag= activateflag; + + SWAP(ARegion*, C->region, butregion); /* XXX 2.50 bad state manipulation? */ + WM_operator_invoke(C, ot, event); + SWAP(ARegion*, C->region, butregion); +} + +/* function used to prevent loosing the open menu when using nested pulldowns, + * when moving mouse towards the pulldown menu over other buttons that could + * steal the highlight from the current button, only checks: + * + * - while mouse moves in triangular area defined old mouse position and + * left/right side of new menu + * - only for 1 second + */ + +static void ui_mouse_motion_towards_init(uiBlockHandle *bhandle, int mx, int my) +{ + if(!bhandle->dotowards) { + bhandle->dotowards= 1; + bhandle->towardsx= mx; + bhandle->towardsy= my; + bhandle->towardstime= PIL_check_seconds_timer(); + } +} + +static int ui_mouse_motion_towards_check(uiBlock *block, uiBlockHandle *bhandle, int mx, int my) +{ + int fac, dx, dy, domx, domy; + + if(!bhandle->dotowards) return 0; + if((block->direction & UI_TOP) || (block->direction & UI_DOWN)) { + bhandle->dotowards= 0; + return bhandle->dotowards; + } + + /* calculate dominant direction */ + domx= (-bhandle->towardsx + (block->maxx+block->minx)/2); + domy= (-bhandle->towardsy + (block->maxy+block->miny)/2); + + /* we need some accuracy */ + if(abs(domx) < 4) { + bhandle->dotowards= 0; + return bhandle->dotowards; + } + + /* check direction */ + dx= mx - bhandle->towardsx; + dy= my - bhandle->towardsy; + + /* threshold */ + if(abs(dx)+abs(dy) > 4) { + /* menu to right */ + if(domx>0) { + fac= (mx - bhandle->towardsx)*( bhandle->towardsy - (int)(block->maxy+20)) + + (my - bhandle->towardsy)*(-bhandle->towardsx + (int)block->minx); + if(fac>0) bhandle->dotowards= 0; + + fac= (mx - bhandle->towardsx)*( bhandle->towardsy - (int)(block->miny-20)) + + (my - bhandle->towardsy)*(-bhandle->towardsx + (int)block->minx); + if(fac<0) bhandle->dotowards= 0; + } + else { + fac= (mx - bhandle->towardsx)*( bhandle->towardsy - (int)(block->maxy+20)) + + (my - bhandle->towardsy)*(-bhandle->towardsx + (int)block->maxx); + if(fac<0) bhandle->dotowards= 0; + + fac= (mx - bhandle->towardsx)*( bhandle->towardsy - (int)(block->miny-20)) + + (my - bhandle->towardsy)*(-bhandle->towardsx + (int)block->maxx); + if(fac>0) bhandle->dotowards= 0; + } + } + + /* 1 second timer */ + if(PIL_check_seconds_timer() - bhandle->towardstime > BUTTON_MOUSE_TOWARDS_THRESH) + bhandle->dotowards= 0; + + return bhandle->dotowards; +} + +static int menu_block_handle_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + ARegion *ar; + uiBlock *block; + uiBut *but, *bt; + uiBlockHandle *bhandle; + int inside, act, count, mx, my, handled; + + bhandle= op->customdata; + ar= bhandle->region; + block= ar->uiblocks.first; + + act= 0; + handled= 0; + + /* if we have another block opened, we shouldn't do anything + * until that block is closed again, otherwise we interfere */ + if(menu_block_handle_block_open(block)) + return OPERATOR_RUNNING_MODAL|OPERATOR_PASS_THROUGH; + + mx= event->x; + my= event->y; + ui_window_to_block(ar, block, &mx, &my); + + /* for ui_mouse_motion_towards_block */ + if(event->type == MOUSEMOVE) + ui_mouse_motion_towards_init(bhandle, mx, my); + + /* check if mouse is inside block */ + inside= 0; + if(block->minx <= mx && block->maxx >= mx) + if(block->miny <= my && block->maxy >= my) + inside= 1; + + switch(event->type) { + /* closing sublevels of pulldowns */ + case LEFTARROWKEY: + if(event->val && (block->flag & UI_BLOCK_LOOP)) + if(BLI_countlist(&block->saferct) > 0) + menu_block_handle_return(C, op, block, UI_RETURN_OUT); + + handled= 1; + break; + + /* opening sublevels of pulldowns */ + case RIGHTARROWKEY: + if(event->val && (block->flag & UI_BLOCK_LOOP)) { + but= ui_but_find_activated(ar, NULL, NULL); + + if(!but) { + /* no item active, we make first active */ + if(block->direction & UI_TOP) but= ui_but_last(block); + else but= ui_but_first(block); + } + + if(but && but->type==BLOCK) + menu_block_handle_activate_button(C, event, ar, but, UI_ACTIVATE_OPEN); + } + handled= 1; + break; + + case UPARROWKEY: + case DOWNARROWKEY: + case WHEELUPMOUSE: + case WHEELDOWNMOUSE: + /* arrowkeys: only handle for block_loop blocks */ + if(inside || (block->flag & UI_BLOCK_LOOP)) { + if(event->val) { + but= ui_but_find_activated(ar, NULL, NULL); + + if(but) { + if(ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) { + if(block->direction & UI_TOP) but= ui_but_next(but); + else but= ui_but_prev(but); + } + else { + if(block->direction & UI_TOP) but= ui_but_prev(but); + else but= ui_but_next(but); + } + + if(but) + menu_block_handle_activate_button(C, event, ar, but, UI_ACTIVATE); + } + + if(!but) { + if(ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) { + if(block->direction & UI_TOP) bt= ui_but_first(block); + else bt= ui_but_last(block); + } + else { + if(block->direction & UI_TOP) bt= ui_but_last(block); + else bt= ui_but_first(block); + } + + if(bt) + menu_block_handle_activate_button(C, event, ar, bt, UI_ACTIVATE); + } + } + } + handled= 1; + break; + + case ONEKEY: case PAD1: + act= 1; + case TWOKEY: case PAD2: + if(act==0) act= 2; + case THREEKEY: case PAD3: + if(act==0) act= 3; + case FOURKEY: case PAD4: + if(act==0) act= 4; + case FIVEKEY: case PAD5: + if(act==0) act= 5; + case SIXKEY: case PAD6: + if(act==0) act= 6; + case SEVENKEY: case PAD7: + if(act==0) act= 7; + case EIGHTKEY: case PAD8: + if(act==0) act= 8; + case NINEKEY: case PAD9: + if(act==0) act= 9; + case ZEROKEY: case PAD0: + if(act==0) act= 10; + + if(block->flag & UI_BLOCK_NUMSELECT) { + if(event->alt) act+= 10; + + count= 0; + for(but= block->buttons.first; but; but= but->next) { + int doit= 0; + + if(but->type!=LABEL && but->type!=SEPR) + count++; + + /* exception for menus like layer buts, with button aligning they're not drawn in order */ + if(but->type==TOGR) { + if(but->bitnr==act-1) + doit= 1; + } + else if(count==act) + doit=1; + + if(doit) { + menu_block_handle_activate_button(C, event, ar, but, UI_ACTIVATE_APPLY); + break; + } + } + } + handled= 1; + break; + } + + /* here we check return conditions for menus */ + if(block->flag & UI_BLOCK_LOOP) { + /* if we click outside the block, verify if we clicked on the + * button that opened us, otherwise we need to close */ + if(inside==0) { + uiSafetyRct *saferct= block->saferct.first; + + if(ELEM3(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) && event->val) { + if(saferct && !BLI_in_rctf(&saferct->parent, event->x, event->y)) { + menu_block_handle_return(C, op, block, UI_RETURN_OK); + return OPERATOR_RUNNING_MODAL; + } + } + } + + /* esc cancel this and all preceding menus */ + if(event->type==ESCKEY && event->val) { + menu_block_handle_return(C, op, block, UI_RETURN_CANCEL); + return OPERATOR_RUNNING_MODAL; + } + + if(ELEM(event->type, RETKEY, PADENTER) && event->val) { + /* enter will always close this block, but note that the event + * can still get pass through so the button is executed */ + menu_block_handle_return(C, op, block, UI_RETURN_OK); + handled= 1; + } + else { + ui_mouse_motion_towards_check(block, bhandle, mx, my); + + /* check mouse moving outside of the menu */ + if(inside==0 && (block->flag & UI_BLOCK_MOVEMOUSE_QUIT)) { + uiSafetyRct *saferct; + + /* check for all parent rects, enables arrowkeys to be used */ + for(saferct=block->saferct.first; saferct; saferct= saferct->next) { + /* for mouse move we only check our own rect, for other + * events we check all preceding block rects too to make + * arrow keys navigation work */ + if(event->type!=MOUSEMOVE || saferct==block->saferct.first) { + if(BLI_in_rctf(&saferct->parent, (float)event->x, (float)event->y)) + break; + if(BLI_in_rctf(&saferct->safety, (float)event->x, (float)event->y)) + break; + } + } + + /* strict check, and include the parent rect */ + if(!bhandle->dotowards && !saferct) { + menu_block_handle_return(C, op, block, UI_RETURN_OK); + return OPERATOR_RUNNING_MODAL|OPERATOR_PASS_THROUGH; + } + + if(bhandle->dotowards && event->type==MOUSEMOVE) + handled= 1; + } + } + } + + /* we pass on events only when the mouse pointer is inside, this ensures + * events only go to handlers inside this region, and no other region. + * that's an indirect way to get this behavior, maybe it should be done + * in a more explicit way somewhow. */ + if(inside && !handled) + return OPERATOR_RUNNING_MODAL|OPERATOR_PASS_THROUGH; + else + return OPERATOR_RUNNING_MODAL; +} + +static int menu_block_handle_poll(bContext *C) +{ + uiBlock *block; + + if(C->region==NULL) return 0; + block= C->region->uiblocks.first; + if(!block) return 0; + + return 1; +} + +void ED_UI_OT_menu_block_handle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Menu Block Handle"; + ot->idname= "ED_UI_OT_menu_block_handle"; + + /* api callbacks */ + ot->invoke= menu_block_handle_invoke; + ot->modal= menu_block_handle_modal; + ot->cancel= menu_block_handle_cancel; + ot->poll= menu_block_handle_poll; +} + +/* ************************** registration **********************************/ + +void ui_operatortypes(void) +{ + WM_operatortype_append(ED_UI_OT_button_activate); + WM_operatortype_append(ED_UI_OT_menu_block_handle); +} + +void UI_keymap(wmWindowManager *wm) +{ + ui_operatortypes(); + + WM_keymap_add_item(&wm->uikeymap, "ED_UI_OT_button_activate", MOUSEMOVE, 0, 0, 0); +} + diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c new file mode 100644 index 00000000000..5bbc5923c7d --- /dev/null +++ b/source/blender/editors/interface/interface_regions.c @@ -0,0 +1,1773 @@ + +#include +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_screen_types.h" +#include "DNA_windowmanager_types.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" + +#include "BKE_global.h" +#include "BKE_screen.h" +#include "BKE_utildefines.h" + +#include "WM_api.h" +#include "WM_types.h" +#include "wm_subwindow.h" +#include "wm_window.h" + +#include "BIF_gl.h" + +#include "UI_text.h" +#include "UI_interface.h" + +#include "ED_screen.h" + +#include "interface.h" + +#define MENU_BUTTON_HEIGHT 20 +#define B_NOP -1 +#define MENU_SHADOW_LEFT -1 +#define MENU_SHADOW_BOTTOM -10 +#define MENU_SHADOW_RIGHT 10 +#define MENU_SHADOW_TOP 1 + +/*********************** Menu Data Parsing ********************* */ + +typedef struct { + char *str; + int retval; + int icon; +} MenuEntry; + +typedef struct { + char *instr; + char *title; + int titleicon; + + MenuEntry *items; + int nitems, itemssize; +} MenuData; + +static MenuData *menudata_new(char *instr) +{ + MenuData *md= MEM_mallocN(sizeof(*md), "MenuData"); + + md->instr= instr; + md->title= NULL; + md->titleicon= 0; + md->items= NULL; + md->nitems= md->itemssize= 0; + + return md; +} + +static void menudata_set_title(MenuData *md, char *title, int titleicon) +{ + if (!md->title) + md->title= title; + if (!md->titleicon) + md->titleicon= titleicon; +} + +static void menudata_add_item(MenuData *md, char *str, int retval, int icon) +{ + if (md->nitems==md->itemssize) { + int nsize= md->itemssize?(md->itemssize<<1):1; + MenuEntry *oitems= md->items; + + md->items= MEM_mallocN(nsize*sizeof(*md->items), "md->items"); + if (oitems) { + memcpy(md->items, oitems, md->nitems*sizeof(*md->items)); + MEM_freeN(oitems); + } + + md->itemssize= nsize; + } + + md->items[md->nitems].str= str; + md->items[md->nitems].retval= retval; + md->items[md->nitems].icon= icon; + md->nitems++; +} + +void menudata_free(MenuData *md) +{ + MEM_freeN(md->instr); + if (md->items) + MEM_freeN(md->items); + MEM_freeN(md); +} + + /** + * Parse menu description strings, string is of the + * form "[sss%t|]{(sss[%xNN]|), (%l|)}", ssss%t indicates the + * menu title, sss or sss%xNN indicates an option, + * if %xNN is given then NN is the return value if + * that option is selected otherwise the return value + * is the index of the option (starting with 1). %l + * indicates a seperator. + * + * @param str String to be parsed. + * @retval new menudata structure, free with menudata_free() + */ +MenuData *decompose_menu_string(char *str) +{ + char *instr= BLI_strdup(str); + MenuData *md= menudata_new(instr); + char *nitem= NULL, *s= instr; + int nicon=0, nretval= 1, nitem_is_title= 0; + + while (1) { + char c= *s; + + if (c=='%') { + if (s[1]=='x') { + nretval= atoi(s+2); + + *s= '\0'; + s++; + } else if (s[1]=='t') { + nitem_is_title= 1; + + *s= '\0'; + s++; + } else if (s[1]=='l') { + nitem= "%l"; + s++; + } else if (s[1]=='i') { + nicon= atoi(s+2); + + *s= '\0'; + s++; + } + } else if (c=='|' || c=='\0') { + if (nitem) { + *s= '\0'; + + if (nitem_is_title) { + menudata_set_title(md, nitem, nicon); + nitem_is_title= 0; + } else { + /* prevent separator to get a value */ + if(nitem[0]=='%' && nitem[1]=='l') + menudata_add_item(md, nitem, -1, nicon); + else + menudata_add_item(md, nitem, nretval, nicon); + nretval= md->nitems+1; + } + + nitem= NULL; + nicon= 0; + } + + if (c=='\0') + break; + } else if (!nitem) + nitem= s; + + s++; + } + + return md; +} + +void ui_set_name_menu(uiBut *but, int value) +{ + MenuData *md; + int i; + + md= decompose_menu_string(but->str); + for (i=0; initems; i++) + if (md->items[i].retval==value) + strcpy(but->drawstr, md->items[i].str); + + menudata_free(md); +} + +/******************** Creating Temporary regions ******************/ + +ARegion *ui_add_temporary_region(bScreen *sc) +{ + ARegion *ar; + + ar= MEM_callocN(sizeof(ARegion), "area region"); + BLI_addtail(&sc->regionbase, ar); + + ar->regiontype= RGN_TYPE_TEMPORARY; + ar->alignment= RGN_ALIGN_FLOAT; + + return ar; +} + +void ui_remove_temporary_region(bContext *C, bScreen *sc, ARegion *ar) +{ + ED_region_exit(C, ar); + BKE_area_region_free(ar); + BLI_freelinkN(&sc->regionbase, ar); +} + +/************************* Creating Tooltips **********************/ + +typedef struct uiTooltipData { + rctf bbox; + struct BMF_Font *font; + char *tip; + float aspect; +} uiTooltipData; + +static void ui_tooltip_region_draw(const bContext *C, ARegion *ar) +{ + uiTooltipData *data; + int x1, y1, x2, y2; + + data= ar->regiondata; + + x1= ar->winrct.xmin; + y1= ar->winrct.ymin; + x2= ar->winrct.xmax; + y2= ar->winrct.ymax; + + /* draw drop shadow */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + glColor4ub(0, 0, 0, 20); + + gl_round_box(GL_POLYGON, 3, 3, x2-x1-3, y2-y1-2, 2.0); + gl_round_box(GL_POLYGON, 3, 2, x2-x1-2, y2-y1-2, 3.0); + + glColor4ub(0, 0, 0, 8); + + gl_round_box(GL_POLYGON, 3, 1, x2-x1-1, y2-y1-3, 4.0); + gl_round_box(GL_POLYGON, 3, 0, x2-x1-0, y2-y1-3, 5.0); + + glDisable(GL_BLEND); + + /* draw background */ + glColor3f(1.0f, 1.0f, 0.8666f); + glRectf(0, 4, x2-x1-4, y2-y1); + + /* draw text */ + glColor3ub(0,0,0); + + /* set the position for drawing text +4 in from the left edge, and leaving + * an equal gap between the top of the background box and the top of the + * string's bbox, and the bottom of the background box, and the bottom of + * the string's bbox */ + ui_rasterpos_safe(4, ((y2-data->bbox.ymax)+(y1+data->bbox.ymin))/2 - data->bbox.ymin - y1, data->aspect); + UI_SetScale(1.0); + + UI_DrawString(data->font, data->tip, ui_translate_tooltips()); +} + +static void ui_tooltip_region_free(ARegion *ar) +{ + uiTooltipData *data; + + data= ar->regiondata; + MEM_freeN(data->tip); + MEM_freeN(data); +} + +ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) +{ + static ARegionType type={NULL, NULL, NULL, NULL, NULL}; + ARegion *ar; + uiTooltipData *data; + int x1, x2, y1, y2, winx, winy; + + if(!but->tip || strlen(but->tip)==0) + return NULL; + + /* create area region */ + ar= ui_add_temporary_region(C->window->screen); + + type.draw= ui_tooltip_region_draw; + type.free= ui_tooltip_region_free; + ar->type= &type; + + /* create tooltip data */ + data= MEM_callocN(sizeof(uiTooltipData), "uiTooltipData"); + data->tip= BLI_strdup(but->tip); + data->font= but->font; + data->aspect= but->aspect; + UI_GetBoundingBox(data->font, data->tip, ui_translate_tooltips(), &data->bbox); + + ar->regiondata= data; + + /* compute position */ + x1= (but->x1+but->x2)/2; + x2= x1+but->aspect*((data->bbox.xmax-data->bbox.xmin) + 8); + y2= but->y1-10; + y1= y2-but->aspect*((data->bbox.ymax+(data->bbox.ymax-data->bbox.ymin))); + + y2 += 4; + x2 += 4; + + if(butregion) { + x1 += butregion->winrct.xmin; + x2 += butregion->winrct.xmin; + y1 += butregion->winrct.ymin; + y2 += butregion->winrct.ymin; + } + + wm_window_get_size(C->window, &winx, &winy); + + if(x2 > winx) { + x1 -= x2-winx; + x2= winx; + } + if(y1 < 0) { + y1 += 36; + y2 += 36; + } + + ar->winrct.xmin= x1; + ar->winrct.ymin= y1; + ar->winrct.xmax= x2; + ar->winrct.ymax= y2; + + /* notify change and redraw */ + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL); + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL); + + return ar; +} + +void ui_tooltip_free(bContext *C, ARegion *ar) +{ + ui_remove_temporary_region(C, C->window->screen, ar); + + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL); + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL); +} + +/************************* Creating Menu Blocks **********************/ + +/* position block relative to but, result is in window space */ +static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, uiBlock *block) +{ + uiBut *bt; + uiSafetyRct *saferct; + rctf butrct; + float aspect; + int xsize, ysize, xof=0, yof=0, center; + short dir1= 0, dir2=0; + + /* transform to window coordinates, using the source button region/block */ + butrct.xmin= but->x1; butrct.xmax= but->x2; + butrct.ymin= but->y1; butrct.ymax= but->y2; + + ui_block_to_window_fl(butregion, but->block, &butrct.xmin, &butrct.ymin); + ui_block_to_window_fl(butregion, but->block, &butrct.xmax, &butrct.ymax); + + /* calc block rect */ + if(block->minx == 0.0f && block->maxx == 0.0f) { + if(block->buttons.first) { + block->minx= block->miny= 10000; + block->maxx= block->maxy= -10000; + + bt= block->buttons.first; + while(bt) { + if(bt->x1 < block->minx) block->minx= bt->x1; + if(bt->y1 < block->miny) block->miny= bt->y1; + + if(bt->x2 > block->maxx) block->maxx= bt->x2; + if(bt->y2 > block->maxy) block->maxy= bt->y2; + + bt= bt->next; + } + } + else { + /* we're nice and allow empty blocks too */ + block->minx= block->miny= 0; + block->maxx= block->maxy= 20; + } + } + + aspect= (float)(block->maxx - block->minx + 4); + ui_block_to_window_fl(butregion, but->block, &block->minx, &block->miny); + ui_block_to_window_fl(butregion, but->block, &block->maxx, &block->maxy); + + //block->minx-= 2.0; block->miny-= 2.0; + //block->maxx+= 2.0; block->maxy+= 2.0; + + xsize= block->maxx - block->minx+4; // 4 for shadow + ysize= block->maxy - block->miny+4; + aspect/= (float)xsize; + + if(but) { + int left=0, right=0, top=0, down=0; + int winx, winy; + + wm_window_get_size(window, &winx, &winy); + + if(block->direction & UI_CENTER) center= ysize/2; + else center= 0; + + if( butrct.xmin-xsize > 0.0) left= 1; + if( butrct.xmax+xsize < winx) right= 1; + if( butrct.ymin-ysize+center > 0.0) down= 1; + if( butrct.ymax+ysize-center < winy) top= 1; + + dir1= block->direction & UI_DIRECTION; + + /* secundary directions */ + if(dir1 & (UI_TOP|UI_DOWN)) { + if(dir1 & UI_LEFT) dir2= UI_LEFT; + else if(dir1 & UI_RIGHT) dir2= UI_RIGHT; + dir1 &= (UI_TOP|UI_DOWN); + } + + if(dir2==0) if(dir1==UI_LEFT || dir1==UI_RIGHT) dir2= UI_DOWN; + if(dir2==0) if(dir1==UI_TOP || dir1==UI_DOWN) dir2= UI_LEFT; + + /* no space at all? dont change */ + if(left || right) { + if(dir1==UI_LEFT && left==0) dir1= UI_RIGHT; + if(dir1==UI_RIGHT && right==0) dir1= UI_LEFT; + /* this is aligning, not append! */ + if(dir2==UI_LEFT && right==0) dir2= UI_RIGHT; + if(dir2==UI_RIGHT && left==0) dir2= UI_LEFT; + } + if(down || top) { + if(dir1==UI_TOP && top==0) dir1= UI_DOWN; + if(dir1==UI_DOWN && down==0) dir1= UI_TOP; + if(dir2==UI_TOP && top==0) dir2= UI_DOWN; + if(dir2==UI_DOWN && down==0) dir2= UI_TOP; + } + + if(dir1==UI_LEFT) { + xof= butrct.xmin - block->maxx; + if(dir2==UI_TOP) yof= butrct.ymin - block->miny-center; + else yof= butrct.ymax - block->maxy+center; + } + else if(dir1==UI_RIGHT) { + xof= butrct.xmax - block->minx; + if(dir2==UI_TOP) yof= butrct.ymin - block->miny-center; + else yof= butrct.ymax - block->maxy+center; + } + else if(dir1==UI_TOP) { + yof= butrct.ymax - block->miny; + if(dir2==UI_RIGHT) xof= butrct.xmax - block->maxx; + else xof= butrct.xmin - block->minx; + // changed direction? + if((dir1 & block->direction)==0) { + if(block->direction & UI_SHIFT_FLIPPED) + xof+= dir2==UI_LEFT?25:-25; + uiBlockFlipOrder(block); + } + } + else if(dir1==UI_DOWN) { + yof= butrct.ymin - block->maxy; + if(dir2==UI_RIGHT) xof= butrct.xmax - block->maxx; + else xof= butrct.xmin - block->minx; + // changed direction? + if((dir1 & block->direction)==0) { + if(block->direction & UI_SHIFT_FLIPPED) + xof+= dir2==UI_LEFT?25:-25; + uiBlockFlipOrder(block); + } + } + + /* and now we handle the exception; no space below or to top */ + if(top==0 && down==0) { + if(dir1==UI_LEFT || dir1==UI_RIGHT) { + // align with bottom of screen + yof= ysize; + } + } + + /* or no space left or right */ + if(left==0 && right==0) { + if(dir1==UI_TOP || dir1==UI_DOWN) { + // align with left size of screen + xof= -block->minx+5; + } + } + + // apply requested offset in the block + xof += block->xofs/block->aspect; + yof += block->yofs/block->aspect; + } + + /* apply */ + + for(bt= block->buttons.first; bt; bt= bt->next) { + ui_block_to_window_fl(butregion, but->block, &bt->x1, &bt->y1); + ui_block_to_window_fl(butregion, but->block, &bt->x2, &bt->y2); + + bt->x1 += xof; + bt->x2 += xof; + bt->y1 += yof; + bt->y2 += yof; + + bt->aspect= 1.0; + // ui_check_but recalculates drawstring size in pixels + ui_check_but(bt); + } + + block->minx += xof; + block->miny += yof; + block->maxx += xof; + block->maxy += yof; + + /* safety calculus */ + if(but) { + float midx= (butrct.xmin+butrct.xmax)/2.0; + float midy= (butrct.ymin+butrct.ymax)/2.0; + + /* when you are outside parent button, safety there should be smaller */ + + // parent button to left + if( midx < block->minx ) block->safety.xmin= block->minx-3; + else block->safety.xmin= block->minx-40; + // parent button to right + if( midx > block->maxx ) block->safety.xmax= block->maxx+3; + else block->safety.xmax= block->maxx+40; + + // parent button on bottom + if( midy < block->miny ) block->safety.ymin= block->miny-3; + else block->safety.ymin= block->miny-40; + // parent button on top + if( midy > block->maxy ) block->safety.ymax= block->maxy+3; + else block->safety.ymax= block->maxy+40; + + // exception for switched pulldowns... + if(dir1 && (dir1 & block->direction)==0) { + if(dir2==UI_RIGHT) block->safety.xmax= block->maxx+3; + if(dir2==UI_LEFT) block->safety.xmin= block->minx-3; + } + block->direction= dir1; + } + else { + block->safety.xmin= block->minx-40; + block->safety.ymin= block->miny-40; + block->safety.xmax= block->maxx+40; + block->safety.ymax= block->maxy+40; + } + + /* keep a list of these, needed for pulldown menus */ + saferct= MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct"); + saferct->parent= butrct; + saferct->safety= block->safety; + BLI_freelistN(&block->saferct); + if(but) + BLI_duplicatelist(&block->saferct, &but->block->saferct); + BLI_addhead(&block->saferct, saferct); +} + +static void ui_block_region_draw(const bContext *C, ARegion *ar) +{ + uiBlock *block; + + for(block=ar->uiblocks.first; block; block=block->next) { + wm_subwindow_getmatrix(C->window, ar->swinid, block->winmat); + uiDrawBlock(block); + } +} + +static void ui_block_region_free(ARegion *ar) +{ + uiFreeBlocks(&ar->uiblocks); +} + +uiMenuBlockHandle *ui_menu_block_create(bContext *C, ARegion *butregion, uiBut *but, uiBlockFuncFP block_func, void *arg) +{ + static ARegionType type={NULL, NULL, NULL, NULL, NULL}; + ARegion *ar; + uiBlock *block; + uiBut *bt; + uiMenuBlockHandle *handle; + uiSafetyRct *saferct; + + /* create handle */ + handle= MEM_callocN(sizeof(uiMenuBlockHandle), "uiMenuBlockHandle"); + + /* create area region */ + ar= ui_add_temporary_region(C->window->screen); + + type.draw= ui_block_region_draw; + type.free= ui_block_region_free; + ar->type= &type; + + WM_event_add_keymap_handler(&ar->handlers, &C->wm->uikeymap); + + handle->region= ar; + ar->regiondata= handle; + + /* create ui block */ + block= block_func(C->window, handle, arg); + block->handle= handle; + + /* if this is being created from a button */ + if(but) { + if(ELEM(but->type, BLOCK, PULLDOWN)) + block->xofs = -2; /* for proper alignment */ + + /* only used for automatic toolbox, so can set the shift flag */ + if(but->flag & UI_MAKE_TOP) { + block->direction= UI_TOP|UI_SHIFT_FLIPPED; + uiBlockFlipOrder(block); + } + if(but->flag & UI_MAKE_DOWN) block->direction= UI_DOWN|UI_SHIFT_FLIPPED; + if(but->flag & UI_MAKE_LEFT) block->direction |= UI_LEFT; + if(but->flag & UI_MAKE_RIGHT) block->direction |= UI_RIGHT; + + ui_block_position(C->window, butregion, but, block); + } + else { + /* keep a list of these, needed for pulldown menus */ + saferct= MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct"); + saferct->safety= block->safety; + BLI_addhead(&block->saferct, saferct); + } + + /* the block and buttons were positioned in window space as in 2.4x, now + * these menu blocks are regions so we bring it back to region space. + * additionally we add some padding for the menu shadow */ + ar->winrct.xmin= block->minx + MENU_SHADOW_LEFT; + ar->winrct.xmax= block->maxx + MENU_SHADOW_RIGHT; + ar->winrct.ymin= block->miny + MENU_SHADOW_BOTTOM; + ar->winrct.ymax= block->maxy + MENU_SHADOW_TOP; + + block->minx -= ar->winrct.xmin; + block->maxx -= ar->winrct.xmin; + block->miny -= ar->winrct.ymin; + block->maxy -= ar->winrct.ymin; + + for(bt= block->buttons.first; bt; bt= bt->next) { + bt->x1 -= ar->winrct.xmin; + bt->x2 -= ar->winrct.xmin; + bt->y1 -= ar->winrct.ymin; + bt->y2 -= ar->winrct.ymin; + } + + block->flag |= UI_BLOCK_LOOP|UI_BLOCK_MOVEMOUSE_QUIT; + + /* notify change and redraw */ + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL); + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL); + + SWAP(ARegion*, C->region, ar); /* XXX 2.50 bad context swapping */ + WM_operator_invoke(C, WM_operatortype_find("ED_UI_OT_menu_block_handle"), NULL); + SWAP(ARegion*, C->region, ar); + + return handle; +} + +void ui_menu_block_free(bContext *C, uiMenuBlockHandle *handle) +{ + ui_remove_temporary_region(C, C->window->screen, handle->region); + MEM_freeN(handle); + + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL); + WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL); +} + +/***************************** Menu Button ***************************/ + +uiBlock *ui_block_func_MENU(wmWindow *window, uiMenuBlockHandle *handle, void *arg_but) +{ + uiBut *but= arg_but; + uiBlock *block; + uiBut *bt; + MenuData *md; + ListBase lb; + float aspect; + int width, height, boxh, columns, rows, startx, starty, x1, y1, xmax, a; + + /* create the block */ + block= uiBeginBlock(window, handle->region, "menu", UI_EMBOSSP, UI_HELV); + block->dt= UI_EMBOSSP; + block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT; + block->themecol= TH_MENU_ITEM; + + /* compute menu data */ + md= decompose_menu_string(but->str); + + /* columns and row calculation */ + columns= (md->nitems+20)/20; + if(columns<1) + columns= 1; + if(columns>8) + columns= (md->nitems+25)/25; + + rows= md->nitems/columns; + if(rows<1) + rows= 1; + while(rows*columnsnitems) + rows++; + + /* prevent scaling up of pupmenu */ + aspect= but->aspect; + if(aspect < 1.0f) + aspect = 1.0f; + + /* size and location */ + if(md->title) + width= 1.5*aspect*strlen(md->title)+UI_GetStringWidth(block->curfont, md->title, ui_translate_menus()); + else + width= 0; + + for(a=0; anitems; a++) { + xmax= aspect*UI_GetStringWidth(block->curfont, md->items[a].str, ui_translate_menus()); + if(md->items[a].icon) + xmax += 20*aspect; + if(xmax>width) + width= xmax; + } + + width+= 10; + if(width < (but->x2 - but->x1)) + width = (but->x2 - but->x1); + if(width<50) + width=50; + + boxh= MENU_BUTTON_HEIGHT; + + height= rows*boxh; + if(md->title) + height+= boxh; + + /* here we go! */ + startx= but->x1; + starty= but->y1; + + if(md->title) { + uiBut *bt; + uiSetCurFont(block, block->font+1); + if (md->titleicon) { + bt= uiDefIconTextBut(block, LABEL, 0, md->titleicon, md->title, startx, (short)(starty+rows*boxh), (short)width, (short)boxh, NULL, 0.0, 0.0, 0, 0, ""); + } else { + bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+rows*boxh), (short)width, (short)boxh, NULL, 0.0, 0.0, 0, 0, ""); + bt->flag= UI_TEXT_LEFT; + } + uiSetCurFont(block, block->font); + } + + for(a=0; anitems; a++) { + + x1= startx + width*((int)(md->nitems-a-1)/rows); + y1= starty - boxh*(rows - ((md->nitems - a - 1)%rows)) + (rows*boxh); + + if (strcmp(md->items[md->nitems-a-1].str, "%l")==0) { + bt= uiDefBut(block, SEPR, B_NOP, "", x1, y1,(short)(width-(rows>1)), (short)(boxh-1), NULL, 0.0, 0.0, 0, 0, ""); + } + else if(md->items[md->nitems-a-1].icon) { + bt= uiDefIconTextButF(block, BUTM|FLO, B_NOP, md->items[md->nitems-a-1].icon ,md->items[md->nitems-a-1].str, x1, y1,(short)(width-(rows>1)), (short)(boxh-1), &handle->retvalue, (float) md->items[md->nitems-a-1].retval, 0.0, 0, 0, ""); + } + else { + bt= uiDefButF(block, BUTM|FLO, B_NOP, md->items[md->nitems-a-1].str, x1, y1,(short)(width-(rows>1)), (short)(boxh-1), &handle->retvalue, (float) md->items[md->nitems-a-1].retval, 0.0, 0, 0, ""); + } + } + + menudata_free(md); + + /* the code up here has flipped locations, because of change of preferred order */ + /* thats why we have to switch list order too, to make arrowkeys work */ + + lb.first= lb.last= NULL; + bt= block->buttons.first; + while(bt) { + uiBut *next= bt->next; + BLI_remlink(&block->buttons, bt); + BLI_addhead(&lb, bt); + bt= next; + } + block->buttons= lb; + + block->direction= UI_TOP; + uiEndBlock(block); + + return block; +} + +uiBlock *ui_block_func_ICONROW(wmWindow *window, uiMenuBlockHandle *handle, void *arg_but) +{ + uiBut *but= arg_but; + uiBlock *block; + int a; + + block= uiBeginBlock(window, handle->region, "menu", UI_EMBOSSP, UI_HELV); + block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT; + block->themecol= TH_MENU_ITEM; + + for(a=(int)but->min; a<=(int)but->max; a++) { + uiDefIconButF(block, BUTM|FLO, B_NOP, but->icon+(a-but->min), 0, (short)(18*a), (short)(but->x2-but->x1-4), 18, &handle->retvalue, (float)a, 0.0, 0, 0, ""); + } + + block->direction= UI_TOP; + + uiEndBlock(block); + + return block; +} + +uiBlock *ui_block_func_ICONTEXTROW(wmWindow *window, uiMenuBlockHandle *handle, void *arg_but) +{ + uiBut *but= arg_but; + uiBlock *block; + MenuData *md; + int width, xmax, ypos, a; + + block= uiBeginBlock(window, handle->region, "menu", UI_EMBOSSP, UI_HELV); + block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT; + block->themecol= TH_MENU_ITEM; + + md= decompose_menu_string(but->str); + + /* size and location */ + /* expand menu width to fit labels */ + if(md->title) + width= 2*strlen(md->title)+UI_GetStringWidth(block->curfont, md->title, ui_translate_menus()); + else + width= 0; + + for(a=0; anitems; a++) { + xmax= UI_GetStringWidth(block->curfont, md->items[a].str, ui_translate_menus()); + if(xmax>width) width= xmax; + } + + width+= 30; + if (width<50) width=50; + + ypos = 1; + + /* loop through the menu options and draw them out with icons & text labels */ + for(a=0; anitems; a++) { + + /* add a space if there's a separator (%l) */ + if (strcmp(md->items[a].str, "%l")==0) { + ypos +=3; + } + else { + uiDefIconTextButF(block, BUTM|FLO, B_NOP, (short)((but->icon)+(md->items[a].retval-but->min)), md->items[a].str, 0, ypos,(short)width, 19, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, ""); + ypos += 20; + } + } + + if(md->title) { + uiBut *bt; + uiSetCurFont(block, block->font+1); + bt= uiDefBut(block, LABEL, 0, md->title, 0, ypos, (short)width, 19, NULL, 0.0, 0.0, 0, 0, ""); + uiSetCurFont(block, block->font); + bt->flag= UI_TEXT_LEFT; + } + + menudata_free(md); + + block->direction= UI_TOP; + + uiBoundsBlock(block, 3); + uiEndBlock(block); + + return block; +} + +static void ui_warp_pointer(short x, short y) +{ + /* XXX 2.50 which function to use for this? */ +#if 0 + /* OSX has very poor mousewarp support, it sends events; + this causes a menu being pressed immediately ... */ + #ifndef __APPLE__ + warp_pointer(x, y); + #endif +#endif +} + +/********************* Color Button ****************/ + +/* picker sizes S hsize, F full size, D spacer, B button/pallette height */ +#define SPICK 110.0 +#define FPICK 180.0 +#define DPICK 6.0 +#define BPICK 24.0 + +#define UI_PALETTE_TOT 16 +/* note; in tot+1 the old color is stored */ +static float palette[UI_PALETTE_TOT+1][3]= { +{0.93, 0.83, 0.81}, {0.88, 0.89, 0.73}, {0.69, 0.81, 0.57}, {0.51, 0.76, 0.64}, +{0.37, 0.56, 0.61}, {0.33, 0.29, 0.55}, {0.46, 0.21, 0.51}, {0.40, 0.12, 0.18}, +{1.0, 1.0, 1.0}, {0.85, 0.85, 0.85}, {0.7, 0.7, 0.7}, {0.56, 0.56, 0.56}, +{0.42, 0.42, 0.42}, {0.28, 0.28, 0.28}, {0.14, 0.14, 0.14}, {0.0, 0.0, 0.0} +}; + +/* for picker, while editing hsv */ +void ui_set_but_hsv(uiBut *but) +{ + float col[3]; + + hsv_to_rgb(but->hsv[0], but->hsv[1], but->hsv[2], col, col+1, col+2); + ui_set_but_vectorf(but, col); +} + +static void update_picker_hex(uiBlock *block, float *rgb) +{ + uiBut *bt; + char col[16]; + + sprintf(col, "%02X%02X%02X", (unsigned int)(rgb[0]*255.0), (unsigned int)(rgb[1]*255.0), (unsigned int)(rgb[2]*255.0)); + + // this updates button strings, is hackish... but button pointers are on stack of caller function + + for(bt= block->buttons.first; bt; bt= bt->next) { + if(strcmp(bt->str, "Hex: ")==0) { + strcpy(bt->poin, col); + ui_check_but(bt); + break; + } + } +} + +void ui_update_block_buts_hsv(uiBlock *block, float *hsv) +{ + uiBut *bt; + float r, g, b; + float rgb[3]; + + // this updates button strings, is hackish... but button pointers are on stack of caller function + hsv_to_rgb(hsv[0], hsv[1], hsv[2], &r, &g, &b); + + rgb[0] = r; rgb[1] = g; rgb[2] = b; + update_picker_hex(block, rgb); + + for(bt= block->buttons.first; bt; bt= bt->next) { + if(bt->type==HSVCUBE) { + VECCOPY(bt->hsv, hsv); + ui_set_but_hsv(bt); + } + else if(bt->str[1]==' ') { + if(bt->str[0]=='R') { + ui_set_but_val(bt, r); + } + else if(bt->str[0]=='G') { + ui_set_but_val(bt, g); + } + else if(bt->str[0]=='B') { + ui_set_but_val(bt, b); + } + else if(bt->str[0]=='H') { + ui_set_but_val(bt, hsv[0]); + } + else if(bt->str[0]=='S') { + ui_set_but_val(bt, hsv[1]); + } + else if(bt->str[0]=='V') { + ui_set_but_val(bt, hsv[2]); + } + } + } +} + +static void ui_update_block_buts_hex(uiBlock *block, char *hexcol) +{ + uiBut *bt; + float r=0, g=0, b=0; + float h, s, v; + + + // this updates button strings, is hackish... but button pointers are on stack of caller function + hex_to_rgb(hexcol, &r, &g, &b); + rgb_to_hsv(r, g, b, &h, &s, &v); + + for(bt= block->buttons.first; bt; bt= bt->next) { + if(bt->type==HSVCUBE) { + bt->hsv[0] = h; + bt->hsv[1] = s; + bt->hsv[2] = v; + ui_set_but_hsv(bt); + } + else if(bt->str[1]==' ') { + if(bt->str[0]=='R') { + ui_set_but_val(bt, r); + } + else if(bt->str[0]=='G') { + ui_set_but_val(bt, g); + } + else if(bt->str[0]=='B') { + ui_set_but_val(bt, b); + } + else if(bt->str[0]=='H') { + ui_set_but_val(bt, h); + } + else if(bt->str[0]=='S') { + ui_set_but_val(bt, s); + } + else if(bt->str[0]=='V') { + ui_set_but_val(bt, v); + } + } + } +} + +/* bt1 is palette but, col1 is original color */ +/* callback to copy from/to palette */ +static void do_palette_cb(void *bt1, void *col1) +{ + uiBut *but1= (uiBut *)bt1; + float *col= (float *)col1; + float *fp, hsv[3]; + + fp= (float *)but1->poin; + + /* XXX 2.50 bad access, how to solve? + * + if( (get_qual() & LR_CTRLKEY) ) { + VECCOPY(fp, col); + } + else*/ { + VECCOPY(col, fp); + } + + rgb_to_hsv(col[0], col[1], col[2], hsv, hsv+1, hsv+2); + ui_update_block_buts_hsv(but1->block, hsv); + update_picker_hex(but1->block, col); +} + +/* bt1 is num but, hsv1 is pointer to original color in hsv space*/ +/* callback to handle changes in num-buts in picker */ +static void do_palette1_cb(void *bt1, void *hsv1) +{ + uiBut *but1= (uiBut *)bt1; + float *hsv= (float *)hsv1; + float *fp= NULL; + + if(but1->str[1]==' ') { + if(but1->str[0]=='R') fp= (float *)but1->poin; + else if(but1->str[0]=='G') fp= ((float *)but1->poin)-1; + else if(but1->str[0]=='B') fp= ((float *)but1->poin)-2; + } + if(fp) { + rgb_to_hsv(fp[0], fp[1], fp[2], hsv, hsv+1, hsv+2); + } + ui_update_block_buts_hsv(but1->block, hsv); +} + +/* bt1 is num but, col1 is pointer to original color */ +/* callback to handle changes in num-buts in picker */ +static void do_palette2_cb(void *bt1, void *col1) +{ + uiBut *but1= (uiBut *)bt1; + float *rgb= (float *)col1; + float *fp= NULL; + + if(but1->str[1]==' ') { + if(but1->str[0]=='H') fp= (float *)but1->poin; + else if(but1->str[0]=='S') fp= ((float *)but1->poin)-1; + else if(but1->str[0]=='V') fp= ((float *)but1->poin)-2; + } + if(fp) { + hsv_to_rgb(fp[0], fp[1], fp[2], rgb, rgb+1, rgb+2); + } + ui_update_block_buts_hsv(but1->block, fp); +} + +static void do_palette_hex_cb(void *bt1, void *hexcl) +{ + uiBut *but1= (uiBut *)bt1; + char *hexcol= (char *)hexcl; + + ui_update_block_buts_hex(but1->block, hexcol); +} + +/* used for both 3d view and image window */ +static void do_palette_sample_cb(void *bt1, void *col1) /* frontbuf */ +{ + /* XXX 2.50 this should become an operator? */ +#if 0 + uiBut *but1= (uiBut *)bt1; + uiBut *but; + float tempcol[4]; + int x=0, y=0; + short mval[2]; + float hsv[3]; + short capturing; + int oldcursor; + Window *win; + unsigned short dev; + + oldcursor=get_cursor(); + win=winlay_get_active_window(); + + while (get_mbut() & L_MOUSE) UI_wait_for_statechange(); + + SetBlenderCursor(BC_EYEDROPPER_CURSOR); + + /* loop and wait for a mouse click */ + capturing = TRUE; + while(capturing) { + char ascii; + short val; + + dev = extern_qread_ext(&val, &ascii); + + if(dev==INPUTCHANGE) break; + if(get_mbut() & R_MOUSE) break; + else if(get_mbut() & L_MOUSE) { + uiGetMouse(mywinget(), mval); + x= mval[0]; y= mval[1]; + + capturing = FALSE; + break; + } + else if(dev==ESCKEY) break; + } + window_set_cursor(win, oldcursor); + + if(capturing) return; + + if(x<0 || y<0) return; + + /* if we've got a glick, use OpenGL to sample the color under the mouse pointer */ + glReadBuffer(GL_FRONT); + glReadPixels(x, y, 1, 1, GL_RGBA, GL_FLOAT, tempcol); + glReadBuffer(GL_BACK); + + /* and send that color back to the picker */ + rgb_to_hsv(tempcol[0], tempcol[1], tempcol[2], hsv, hsv+1, hsv+2); + ui_update_block_buts_hsv(but1->block, hsv); + update_picker_hex(but1->block, tempcol); + + for (but= but1->block->buttons.first; but; but= but->next) { + ui_check_but(but); + ui_draw_but(but); + } + + but= but1->block->buttons.first; + ui_block_flush_back(but->block); +#endif +} + +/* color picker, Gimp version. mode: 'f' = floating panel, 'p' = popup */ +/* col = read/write to, hsv/old/hexcol = memory for temporal use */ +void uiBlockPickerButtons(uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval) +{ + uiBut *bt; + float h, offs; + int a; + + VECCOPY(old, col); // old color stored there, for palette_cb to work + + // the cube intersection + bt= uiDefButF(block, HSVCUBE, retval, "", 0,DPICK+BPICK,FPICK,FPICK, col, 0.0, 0.0, 2, 0, ""); + uiButSetFlag(bt, UI_NO_HILITE); + + bt= uiDefButF(block, HSVCUBE, retval, "", 0,0,FPICK,BPICK, col, 0.0, 0.0, 3, 0, ""); + uiButSetFlag(bt, UI_NO_HILITE); + + // palette + + uiBlockSetEmboss(block, UI_EMBOSSP); + + bt=uiDefButF(block, COL, retval, "", FPICK+DPICK, 0, BPICK,BPICK, old, 0.0, 0.0, -1, 0, "Old color, click to restore"); + uiButSetFunc(bt, do_palette_cb, bt, col); + uiDefButF(block, COL, retval, "", FPICK+DPICK, BPICK+DPICK, BPICK,60-BPICK-DPICK, col, 0.0, 0.0, -1, 0, "Active color"); + + h= (DPICK+BPICK+FPICK-64)/(UI_PALETTE_TOT/2.0); + uiBlockBeginAlign(block); + for(a= -1+UI_PALETTE_TOT/2; a>=0; a--) { + bt= uiDefButF(block, COL, retval, "", FPICK+DPICK, 65.0+(float)a*h, BPICK/2, h, palette[a+UI_PALETTE_TOT/2], 0.0, 0.0, -1, 0, "Click to choose, hold CTRL to store in palette"); + uiButSetFunc(bt, do_palette_cb, bt, col); + bt= uiDefButF(block, COL, retval, "", FPICK+DPICK+BPICK/2, 65.0+(float)a*h, BPICK/2, h, palette[a], 0.0, 0.0, -1, 0, "Click to choose, hold CTRL to store in palette"); + uiButSetFunc(bt, do_palette_cb, bt, col); + } + uiBlockEndAlign(block); + + uiBlockSetEmboss(block, UI_EMBOSS); + + // buttons + rgb_to_hsv(col[0], col[1], col[2], hsv, hsv+1, hsv+2); + sprintf(hexcol, "%02X%02X%02X", (unsigned int)(col[0]*255.0), (unsigned int)(col[1]*255.0), (unsigned int)(col[2]*255.0)); + + offs= FPICK+2*DPICK+BPICK; + + /* note; made this a TOG now, with NULL pointer. Is because BUT now gets handled with a afterfunc */ + bt= uiDefIconTextBut(block, TOG, UI_RETURN_OK, ICON_EYEDROPPER, "Sample", offs+55, 170, 85, 20, NULL, 0, 0, 0, 0, "Sample the color underneath the following mouse click (ESC or RMB to cancel)"); + uiButSetFunc(bt, do_palette_sample_cb, bt, col); + uiButSetFlag(bt, UI_TEXT_LEFT); + + bt= uiDefBut(block, TEX, retval, "Hex: ", offs, 140, 140, 20, hexcol, 0, 8, 0, 0, "Hex triplet for color (#RRGGBB)"); + uiButSetFunc(bt, do_palette_hex_cb, bt, hexcol); + + uiBlockBeginAlign(block); + bt= uiDefButF(block, NUMSLI, retval, "R ", offs, 110, 140,20, col, 0.0, 1.0, 10, 3, ""); + uiButSetFunc(bt, do_palette1_cb, bt, hsv); + bt= uiDefButF(block, NUMSLI, retval, "G ", offs, 90, 140,20, col+1, 0.0, 1.0, 10, 3, ""); + uiButSetFunc(bt, do_palette1_cb, bt, hsv); + bt= uiDefButF(block, NUMSLI, retval, "B ", offs, 70, 140,20, col+2, 0.0, 1.0, 10, 3, ""); + uiButSetFunc(bt, do_palette1_cb, bt, hsv); + + uiBlockBeginAlign(block); + bt= uiDefButF(block, NUMSLI, retval, "H ", offs, 40, 140,20, hsv, 0.0, 1.0, 10, 3, ""); + uiButSetFunc(bt, do_palette2_cb, bt, col); + bt= uiDefButF(block, NUMSLI, retval, "S ", offs, 20, 140,20, hsv+1, 0.0, 1.0, 10, 3, ""); + uiButSetFunc(bt, do_palette2_cb, bt, col); + bt= uiDefButF(block, NUMSLI, retval, "V ", offs, 0, 140,20, hsv+2, 0.0, 1.0, 10, 3, ""); + uiButSetFunc(bt, do_palette2_cb, bt, col); + uiBlockEndAlign(block); +} + +uiBlock *ui_block_func_COL(wmWindow *window, uiMenuBlockHandle *handle, void *arg_but) +{ + uiBut *but= arg_but; + uiBlock *block; + static float hsvcol[3], oldcol[3]; + static char hexcol[128]; + + block= uiBeginBlock(window, handle->region, "colorpicker", UI_EMBOSS, UI_HELV); + block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_KEEP_OPEN; + block->themecol= TH_BUT_NUM; + + VECCOPY(handle->retvec, but->editvec); + uiBlockPickerButtons(block, handle->retvec, hsvcol, oldcol, hexcol, 'p', 0); + + /* and lets go */ + block->direction= UI_TOP; + uiBoundsBlock(block, 3); + + return block; +} + +/* ******************** PUPmenu ****************** */ + +static int pupmenu_set= 0; + +void pupmenu_set_active(int val) +{ + pupmenu_set= val; +} + +/* value== -1 read, otherwise set */ +static int pupmenu_memory(char *str, int value) +{ + static char mem[256], first=1; + int val=0, nr=0; + + if(first) { + memset(mem, 0, 256); + first= 0; + } + while(str[nr]) { + val+= str[nr]; + nr++; + } + + if(value >= 0) mem[ val & 255 ]= value; + else return mem[ val & 255 ]; + + return 0; +} + +#define PUP_LABELH 6 + +typedef struct uiPupMenuInfo { + char *instr; + int mx, my; + int startx, starty; + int maxrow; +} uiPupMenuInfo; + +uiBlock *ui_block_func_PUPMENU(wmWindow *window, uiMenuBlockHandle *handle, void *arg_info) +{ + uiBlock *block; + uiPupMenuInfo *info; + int columns, rows, mousemove[2]= {0, 0}, mousewarp= 0; + int width, height, xmax, ymax, maxrow; + int a, startx, starty, endx, endy, x1, y1; + int lastselected; + MenuData *md; + + info= arg_info; + maxrow= info->maxrow; + height= 0; + + /* block stuff first, need to know the font */ + block= uiBeginBlock(window, handle->region, "menu", UI_EMBOSSP, UI_HELV); + uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_NUMSELECT); + block->themecol= TH_MENU_ITEM; + + md= decompose_menu_string(info->instr); + + rows= md->nitems; + columns= 1; + + /* size and location, title slightly bigger for bold */ + if(md->title) { + width= 2*strlen(md->title)+UI_GetStringWidth(uiBlockGetCurFont(block), md->title, ui_translate_buttons()); + width /= columns; + } + else width= 0; + + for(a=0; anitems; a++) { + xmax= UI_GetStringWidth(uiBlockGetCurFont(block), md->items[a].str, ui_translate_buttons()); + if(xmax>width) width= xmax; + + if(strcmp(md->items[a].str, "%l")==0) height+= PUP_LABELH; + else height+= MENU_BUTTON_HEIGHT; + } + + width+= 10; + if (width<50) width=50; + + wm_window_get_size(window, &xmax, &ymax); + + /* set first item */ + lastselected= 0; + if(pupmenu_set) { + lastselected= pupmenu_set-1; + pupmenu_set= 0; + } + else if(md->nitems>1) { + lastselected= pupmenu_memory(info->instr, -1); + } + + startx= info->mx-(0.8*(width)); + starty= info->my-height+MENU_BUTTON_HEIGHT/2; + if(lastselected>=0 && lastselectednitems) { + for(a=0; anitems; a++) { + if(a==lastselected) break; + if( strcmp(md->items[a].str, "%l")==0) starty+= PUP_LABELH; + else starty+=MENU_BUTTON_HEIGHT; + } + + //starty= info->my-height+MENU_BUTTON_HEIGHT/2+lastselected*MENU_BUTTON_HEIGHT; + } + + if(startx<10) { + startx= 10; + } + if(starty<10) { + mousemove[1]= 10-starty; + starty= 10; + } + + endx= startx+width*columns; + endy= starty+height; + + if(endx>xmax) { + endx= xmax-10; + startx= endx-width*columns; + } + if(endy>ymax-20) { + mousemove[1]= ymax-endy-20; + endy= ymax-20; + starty= endy-height; + } + + if(mousemove[0] || mousemove[1]) { + ui_warp_pointer(info->mx+mousemove[0], info->my+mousemove[1]); + mousemove[0]= info->mx; + mousemove[1]= info->my; + mousewarp= 1; + } + + /* here we go! */ + if(md->title) { + uiBut *bt; + char titlestr[256]; + uiSetCurFont(block, UI_HELVB); + + if(md->titleicon) { + width+= 20; + sprintf(titlestr, " %s", md->title); + uiDefIconTextBut(block, LABEL, 0, md->titleicon, titlestr, startx, (short)(starty+height), width, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, ""); + } + else { + bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+height), columns*width, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, ""); + bt->flag= UI_TEXT_LEFT; + } + uiSetCurFont(block, UI_HELV); + } + + x1= startx + width*((int)a/rows); + y1= starty + height - MENU_BUTTON_HEIGHT; + + for(a=0; anitems; a++) { + char *name= md->items[a].str; + int icon = md->items[a].icon; + + if(strcmp(name, "%l")==0) { + uiDefBut(block, SEPR, B_NOP, "", x1, y1, width, PUP_LABELH, NULL, 0, 0.0, 0, 0, ""); + y1 -= PUP_LABELH; + } + else if (icon) { + uiDefIconButF(block, BUTM, B_NOP, icon, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, ""); + y1 -= MENU_BUTTON_HEIGHT; + } + else { + uiDefButF(block, BUTM, B_NOP, name, x1, y1, width, MENU_BUTTON_HEIGHT-1, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, ""); + y1 -= MENU_BUTTON_HEIGHT; + } + } + + uiBoundsBlock(block, 1); + uiEndBlock(block); + + menudata_free(md); + + /* XXX 2.5 need to store last selected */ +#if 0 + /* calculate last selected */ + if(event & ui_return_ok) { + lastselected= 0; + for(a=0; anitems; a++) { + if(val==md->items[a].retval) lastselected= a; + } + + pupmenu_memory(info->instr, lastselected); + } +#endif + + /* XXX 2.5 need to warp back */ +#if 0 + if(mousemove[1] && (event & ui_return_out)==0) + ui_warp_pointer(mousemove[0], mousemove[1]); + return val; +#endif + + return block; +} + +uiBlock *ui_block_func_PUPMENUCOL(wmWindow *window, uiMenuBlockHandle *handle, void *arg_info) +{ + uiBlock *block; + uiPupMenuInfo *info; + int columns, rows, mousemove[2]= {0, 0}, mousewarp; + int width, height, xmax, ymax, maxrow; + int a, startx, starty, endx, endy, x1, y1; + float fvalue; + MenuData *md; + + info= arg_info; + maxrow= info->maxrow; + height= 0; + + /* block stuff first, need to know the font */ + block= uiBeginBlock(window, handle->region, "menu", UI_EMBOSSP, UI_HELV); + uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_NUMSELECT); + block->themecol= TH_MENU_ITEM; + + md= decompose_menu_string(info->instr); + + /* columns and row calculation */ + columns= (md->nitems+maxrow)/maxrow; + if (columns<1) columns= 1; + + if(columns > 8) { + maxrow += 5; + columns= (md->nitems+maxrow)/maxrow; + } + + rows= (int) md->nitems/columns; + if (rows<1) rows= 1; + + while (rows*columns<(md->nitems+columns) ) rows++; + + /* size and location, title slightly bigger for bold */ + if(md->title) { + width= 2*strlen(md->title)+UI_GetStringWidth(uiBlockGetCurFont(block), md->title, ui_translate_buttons()); + width /= columns; + } + else width= 0; + + for(a=0; anitems; a++) { + xmax= UI_GetStringWidth(uiBlockGetCurFont(block), md->items[a].str, ui_translate_buttons()); + if(xmax>width) width= xmax; + } + + width+= 10; + if (width<50) width=50; + + height= rows*MENU_BUTTON_HEIGHT; + if (md->title) height+= MENU_BUTTON_HEIGHT; + + wm_window_get_size(window, &xmax, &ymax); + + /* find active item */ + fvalue= handle->retvalue; + for(a=0; anitems; a++) { + if( md->items[a].retval== (int)fvalue ) break; + } + + /* no active item? */ + if(a==md->nitems) { + if(md->title) a= -1; + else a= 0; + } + + if(a>0) + startx = info->mx-width/2 - ((int)(a)/rows)*width; + else + startx= info->mx-width/2; + starty = info->my-height + MENU_BUTTON_HEIGHT/2 + ((a)%rows)*MENU_BUTTON_HEIGHT; + + if (md->title) starty+= MENU_BUTTON_HEIGHT; + + if(startx<10) { + mousemove[0]= 10-startx; + startx= 10; + } + if(starty<10) { + mousemove[1]= 10-starty; + starty= 10; + } + + endx= startx+width*columns; + endy= starty+height; + + if(endx>xmax) { + mousemove[0]= xmax-endx-10; + endx= xmax-10; + startx= endx-width*columns; + } + if(endy>ymax) { + mousemove[1]= ymax-endy-10; + endy= ymax-10; + starty= endy-height; + } + + if(mousemove[0] || mousemove[1]) { + ui_warp_pointer(info->mx+mousemove[0], info->my+mousemove[1]); + mousemove[0]= info->mx; + mousemove[1]= info->my; + mousewarp= 1; + } + + /* here we go! */ + if(md->title) { + uiBut *bt; + uiSetCurFont(block, UI_HELVB); + + if(md->titleicon) { + } + else { + bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+rows*MENU_BUTTON_HEIGHT), columns*width, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, ""); + bt->flag= UI_TEXT_LEFT; + } + uiSetCurFont(block, UI_HELV); + } + + for(a=0; anitems; a++) { + char *name= md->items[a].str; + int icon = md->items[a].icon; + + x1= startx + width*((int)a/rows); + y1= starty - MENU_BUTTON_HEIGHT*(a%rows) + (rows-1)*MENU_BUTTON_HEIGHT; + + if(strcmp(name, "%l")==0) { + uiDefBut(block, SEPR, B_NOP, "", x1, y1, width, PUP_LABELH, NULL, 0, 0.0, 0, 0, ""); + y1 -= PUP_LABELH; + } + else if (icon) { + uiDefIconButF(block, BUTM, B_NOP, icon, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, ""); + y1 -= MENU_BUTTON_HEIGHT; + } + else { + uiDefButF(block, BUTM, B_NOP, name, x1, y1, width, MENU_BUTTON_HEIGHT-1, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, ""); + y1 -= MENU_BUTTON_HEIGHT; + } + } + + uiBoundsBlock(block, 1); + uiEndBlock(block); + +#if 0 + event= uiDoBlocks(&listb, 0, 1); +#endif + + menudata_free(md); + + /* XXX 2.5 need to warp back */ +#if 0 + if((event & UI_RETURN_OUT)==0) + ui_warp_pointer(mousemove[0], mousemove[1]); +#endif + + return block; +} + +uiMenuBlockHandle *pupmenu_col(bContext *C, char *instr, int mx, int my, int maxrow) +{ + uiPupMenuInfo info; + + memset(&info, 0, sizeof(info)); + info.instr= instr; + info.mx= mx; + info.my= my; + info.maxrow= maxrow; + + return ui_menu_block_create(C, NULL, NULL, ui_block_func_PUPMENUCOL, &info); +} + +uiMenuBlockHandle *pupmenu(bContext *C, char *instr, int mx, int my) +{ + uiPupMenuInfo info; + + memset(&info, 0, sizeof(info)); + info.instr= instr; + info.mx= mx; + info.my= my; + + return ui_menu_block_create(C, NULL, NULL, ui_block_func_PUPMENU, &info); +} + + +void pupmenu_free(bContext *C, uiMenuBlockHandle *handle) +{ + ui_menu_block_free(C, handle); +} + +/*************** Temporary Buttons Tests **********************/ + +static uiBlock *test_submenu(wmWindow *window, uiMenuBlockHandle *handle, void *arg) +{ + ARegion *ar= handle->region; + uiBlock *block; + short yco= 0, menuwidth=120; + + block= uiBeginBlock(window, ar, "test_viewmenu", UI_EMBOSSP, UI_HELV); + //uiBlockSetButmFunc(block, do_test_viewmenu, NULL); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Play Back Animation", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Seconds|T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, + "Only Selected Data Keys|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump To Next Marker|PageUp", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump To Prev Marker|PageDown", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump To Next Key|Ctrl PageUp", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump To Prev Key|Ctrl PageDown", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Center View|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View All|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, + "Lock Time to Other Windows|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, ""); + + uiBlockSetDirection(block, UI_RIGHT); + + uiTextBoundsBlock(block, 50); + uiEndBlock(block); + + return block; +} + +static uiBlock *test_viewmenu(wmWindow *window, uiMenuBlockHandle *handle, void *arg_area) +{ + ScrArea *area= arg_area; + ARegion *ar= handle->region; + uiBlock *block; + short yco= 0, menuwidth=120; + + block= uiBeginBlock(window, ar, "test_viewmenu", UI_EMBOSSP, UI_HELV); + //uiBlockSetButmFunc(block, do_test_viewmenu, NULL); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Play Back Animation", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Seconds|T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, + "Only Selected Data Keys|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump To Next Marker|PageUp", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump To Prev Marker|PageDown", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump To Next Key|Ctrl PageUp", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump To Prev Key|Ctrl PageDown", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Center View|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View All|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, + "Lock Time to Other Windows|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBlockBut(block, test_submenu, NULL, ICON_RIGHTARROW_THIN, "Sub Menu", 0, yco-=20, 120, 19, ""); + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + if(area->headertype==HEADERTOP) { + uiBlockSetDirection(block, UI_DOWN); + } + else { + uiBlockSetDirection(block, UI_TOP); + uiBlockFlipOrder(block); + } + + uiTextBoundsBlock(block, 50); + uiEndBlock(block); + + return block; +} + +void uiTestRegion(const bContext *C) +{ + uiBlock *block; + static float testcol[3]; + static char testtext[64]; + static float testnumf=5.0f; + static short testchoice= 0, testtog= 0; +#if 0 + static CurveMapping *cumap= NULL; + static ColorBand *coba= NULL; +#endif + + block= uiBeginBlock(C->window, C->region, "header buttons", UI_EMBOSS, UI_HELV); + + uiDefPulldownBut(block, test_viewmenu, C->area, "View", + 13, 1, 50, 24, ""); + + uiDefBut(block, BUT, 31415, "Type BUT", + 13+50+5, 3, 80, 20, NULL, 0, 0, 0, 0, "A tooltip."); + uiDefButS(block, MENU, 31416, "Gather Method%t|Raytrace %x0|Approximate %x1", + 13+50+5+80+5, 3, 100, 20, &testchoice, 0, 0, 0, 0, "Method for occlusion gathering"); + uiDefButBitS(block, TOG, 1, 31417, "Pixel Cache", + 13+50+5+80+5+100+5, 3, 80, 20, &testtog, 0, 0, 0, 0, "Cache AO results in pixels and interpolate over neighbouring pixels for speedup."); + + uiDefBut(block, TEX, 31418, "Text: ", + 13+50+5+80+5+100+5+80+5, 3, 200, 20, testtext, 0, sizeof(testtext), 0, 0, "User defined text"); + + uiDefButF(block, NUMSLI, 31419, "Slider: ", + 13+50+5+80+5+100+5+80+5+200+5, 3, 150, 20, &testnumf, 0.0, 10.0, 0, 0, "Some tooltip."); + uiDefButF(block, NUM, 31419, "N: ", + 13+50+5+80+5+100+5+80+5+200+5+150+5, 3, 100, 20, &testnumf, 0.0, 10.0, 0, 0, "Some tooltip."); + + uiDefButF(block, COL, 3142, "", + 13+50+5+80+5+100+5+80+5+200+5+150+5+100+5, 3, 100, 20, testcol, 0, 0, 0, 0 /*B_BANDCOL*/, ""); + +#if 0 + if(!cumap) { + cumap= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); + cumap->flag &= ~CUMA_DO_CLIP; + } + if(!coba) + coba= add_colorband(0); + + uiDefBut(block, BUT_CURVE, 3143, "", + 13+400, 33, 100, 100, cumap, 0.0f, 1.0f, 0, 0, ""); + uiDefBut(block, BUT_COLORBAND, 3143, "", + 13+400+100+10, 33, 150, 30, coba, 0.0f, 1.0f, 0, 0, ""); +#endif + + uiEndBlock(block); + uiDrawBlock(block); +} + diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 4bbf2a64b53..bfb2d39fbb5 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -51,8 +51,9 @@ #include "BKE_utildefines.h" #include "BIF_gl.h" -#include "BIF_resources.h" -#include "BIF_interface_icons.h" + +#include "UI_resources.h" +//#include "UI_icons.h" #include "BLI_blenlib.h" @@ -63,14 +64,14 @@ static bTheme *theme_active=NULL; static int theme_spacetype= SPACE_VIEW3D; -void BIF_resources_init(void) +void ui_resources_init(void) { - BIF_icons_init(BIFICONID_LAST+1); + // XXX 2.50 missing UI_icons_init(BIFICONID_LAST+1); } -void BIF_resources_free(void) +void ui_resources_free(void) { - BIF_icons_free(); + // XXX 2.50 missing UI_icons_free(); } @@ -78,7 +79,7 @@ void BIF_resources_free(void) /* THEMES */ /* ******************************************************** */ -char *BIF_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) +char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) { ThemeSpace *ts= NULL; static char error[4]={240, 0, 240, 255}; @@ -328,7 +329,7 @@ char *BIF_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) Note: when you add new colors, created & saved themes need initialized in usiblender.c, search for "versionfile" */ -void BIF_InitTheme(void) +void ui_theme_init_userdef(void) { bTheme *btheme= U.themes.first; @@ -343,7 +344,7 @@ void BIF_InitTheme(void) strcpy(btheme->name, "Default"); } - BIF_SetTheme(NULL); // make sure the global used in this file is set + UI_SetTheme(NULL); // make sure the global used in this file is set /* UI buttons (todo) */ SETCOL(btheme->tui.outline, 0xA0,0xA0,0xA0, 255); @@ -542,7 +543,7 @@ void BIF_InitTheme(void) } -char *BIF_ThemeColorsPup(int spacetype) +char *UI_ThemeColorsPup(int spacetype) { char *cp= MEM_callocN(32*32, "theme pup"); char *str = cp; @@ -713,7 +714,7 @@ char *BIF_ThemeColorsPup(int spacetype) return cp; } -void BIF_SetTheme(ScrArea *sa) +void UI_SetTheme(ScrArea *sa) { if(sa==NULL) { // called for safety, when delete themes theme_active= U.themes.first; @@ -728,32 +729,32 @@ void BIF_SetTheme(ScrArea *sa) } // for space windows only -void BIF_ThemeColor(int colorid) +void UI_ThemeColor(int colorid) { char *cp; - cp= BIF_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); glColor3ub(cp[0], cp[1], cp[2]); } // plus alpha -void BIF_ThemeColor4(int colorid) +void UI_ThemeColor4(int colorid) { char *cp; - cp= BIF_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); glColor4ub(cp[0], cp[1], cp[2], cp[3]); } // set the color with offset for shades -void BIF_ThemeColorShade(int colorid, int offset) +void UI_ThemeColorShade(int colorid, int offset) { int r, g, b; char *cp; - cp= BIF_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); r= offset + (int) cp[0]; CLAMP(r, 0, 255); g= offset + (int) cp[1]; @@ -763,12 +764,12 @@ void BIF_ThemeColorShade(int colorid, int offset) //glColor3ub(r, g, b); glColor4ub(r, g, b, cp[3]); } -void BIF_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset) +void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset) { int r, g, b, a; char *cp; - cp= BIF_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); r= coloffset + (int) cp[0]; CLAMP(r, 0, 255); g= coloffset + (int) cp[1]; @@ -781,13 +782,13 @@ void BIF_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset) } // blend between to theme colors, and set it -void BIF_ThemeColorBlend(int colorid1, int colorid2, float fac) +void UI_ThemeColorBlend(int colorid1, int colorid2, float fac) { int r, g, b; char *cp1, *cp2; - cp1= BIF_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1); - cp2= BIF_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2); + cp1= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1); + cp2= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2); if(fac<0.0) fac=0.0; else if(fac>1.0) fac= 1.0; r= floor((1.0-fac)*cp1[0] + fac*cp2[0]); @@ -798,13 +799,13 @@ void BIF_ThemeColorBlend(int colorid1, int colorid2, float fac) } // blend between to theme colors, shade it, and set it -void BIF_ThemeColorBlendShade(int colorid1, int colorid2, float fac, int offset) +void UI_ThemeColorBlendShade(int colorid1, int colorid2, float fac, int offset) { int r, g, b; char *cp1, *cp2; - cp1= BIF_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1); - cp2= BIF_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2); + cp1= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1); + cp2= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2); if(fac<0.0) fac=0.0; else if(fac>1.0) fac= 1.0; r= offset+floor((1.0-fac)*cp1[0] + fac*cp2[0]); @@ -819,65 +820,65 @@ void BIF_ThemeColorBlendShade(int colorid1, int colorid2, float fac, int offset) } // get individual values, not scaled -float BIF_GetThemeValuef(int colorid) +float UI_GetThemeValuef(int colorid) { char *cp; - cp= BIF_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); return ((float)cp[0]); } // get individual values, not scaled -int BIF_GetThemeValue(int colorid) +int UI_GetThemeValue(int colorid) { char *cp; - cp= BIF_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); return ((int) cp[0]); } // get the color, range 0.0-1.0 -void BIF_GetThemeColor3fv(int colorid, float *col) +void UI_GetThemeColor3fv(int colorid, float *col) { char *cp; - cp= BIF_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); col[0]= ((float)cp[0])/255.0; col[1]= ((float)cp[1])/255.0; col[2]= ((float)cp[2])/255.0; } // get the color, in char pointer -void BIF_GetThemeColor3ubv(int colorid, char *col) +void UI_GetThemeColor3ubv(int colorid, char *col) { char *cp; - cp= BIF_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); col[0]= cp[0]; col[1]= cp[1]; col[2]= cp[2]; } // get the color, in char pointer -void BIF_GetThemeColor4ubv(int colorid, char *col) +void UI_GetThemeColor4ubv(int colorid, char *col) { char *cp; - cp= BIF_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); col[0]= cp[0]; col[1]= cp[1]; col[2]= cp[2]; col[3]= cp[3]; } -void BIF_GetThemeColorType4ubv(int colorid, int spacetype, char *col) +void UI_GetThemeColorType4ubv(int colorid, int spacetype, char *col) { char *cp; - cp= BIF_ThemeGetColorPtr(theme_active, spacetype, colorid); + cp= UI_ThemeGetColorPtr(theme_active, spacetype, colorid); col[0]= cp[0]; col[1]= cp[1]; col[2]= cp[2]; @@ -885,7 +886,7 @@ void BIF_GetThemeColorType4ubv(int colorid, int spacetype, char *col) } // blends and shades between two char color pointers -void BIF_ColorPtrBlendShade3ubv(char *cp1, char *cp2, float fac, int offset) +void UI_ColorPtrBlendShade3ubv(char *cp1, char *cp2, float fac, int offset) { int r, g, b; @@ -902,7 +903,7 @@ void BIF_ColorPtrBlendShade3ubv(char *cp1, char *cp2, float fac, int offset) } // get a 3 byte color, blended and shaded between two other char color pointers -void BIF_GetColorPtrBlendShade3ubv(char *cp1, char *cp2, char *col, float fac, int offset) +void UI_GetColorPtrBlendShade3ubv(char *cp1, char *cp2, char *col, float fac, int offset) { int r, g, b; @@ -919,3 +920,4 @@ void BIF_GetColorPtrBlendShade3ubv(char *cp1, char *cp2, char *col, float fac, i col[1] = g; col[2] = b; } + diff --git a/source/blender/editors/interface/text.c b/source/blender/editors/interface/text.c new file mode 100644 index 00000000000..edca092f42b --- /dev/null +++ b/source/blender/editors/interface/text.c @@ -0,0 +1,442 @@ +/** + * $Id$ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is written by Rob Haarsma (phase) + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/* XXX 2.50 this file must be cleanup still, using globals etc. */ + +#include +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" +#include "DNA_userdef_types.h" +#include "DNA_vec_types.h" + +#include "BKE_global.h" /* G */ +#include "BKE_utildefines.h" + +#include "BLI_blenlib.h" +#include "BLI_linklist.h" /* linknode */ + +#include "BIF_gl.h" +#include "UI_text.h" + +#include "ED_datafiles.h" + +#include "BMF_Api.h" + +#ifdef WITH_ICONV +#include "iconv.h" + +void string_to_utf8(char *original, char *utf_8, char *code) +{ + size_t inbytesleft=strlen(original); + size_t outbytesleft=512; + size_t rv=0; + iconv_t cd; + + cd=iconv_open("UTF-8", code); + + if (cd == (iconv_t)(-1)) { + printf("iconv_open Error"); + *utf_8='\0'; + return ; + } + rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft); + if (rv == (size_t) -1) { + printf("iconv Error\n"); + return ; + } + *utf_8 = '\0'; + iconv_close(cd); +} +#endif // WITH_ICONV + +#ifdef INTERNATIONAL +#include "FTF_Api.h" + +static struct LANGMenuEntry *langmenu= 0; +static int tot_lang = 0; + +#endif // INTERNATIONAL + +void UI_RasterPos(float x, float y) +{ +#ifdef INTERNATIONAL + FTF_SetPosition(x, y); +#endif // INTERNATIONAL +} + +void UI_SetScale(float aspect) +{ +#ifdef INTERNATIONAL + FTF_SetScale(aspect); +#endif // INTERNATIONAL +} + +void ui_text_init_userdef(void) +{ +#ifdef INTERNATIONAL + if(U.transopts & USER_DOTRANSLATE) + start_interface_font(); + else + G.ui_international= FALSE; +#else // INTERNATIONAL + G.ui_international= FALSE; +#endif +} + +int UI_DrawString(BMF_Font* font, char *str, int translate) +{ +#ifdef INTERNATIONAL + if(G.ui_international == TRUE) { + if(translate) + { +#ifdef WITH_ICONV + if(translate & CONVERT_TO_UTF8) { + char utf_8[512]; + + struct LANGMenuEntry *lme; + lme = find_language(U.language); + + if (lme !=NULL) { + if (!strcmp(lme->code, "ja_JP")) + string_to_utf8(str, utf_8, "Shift_JIS"); /* Japanese */ + else if (!strcmp(lme->code, "zh_CN")) + string_to_utf8(str, utf_8, "GB2312"); /* Chinese */ + } + + return FTF_DrawString(utf_8, FTF_INPUT_UTF8); + } + else +#endif // WITH_ICONV + return FTF_DrawString(str, FTF_USE_GETTEXT | FTF_INPUT_UTF8); + } + else + return FTF_DrawString(str, FTF_NO_TRANSCONV | FTF_INPUT_UTF8); + } else { + return BMF_DrawString(font, str); + } +#else // INTERNATIONAL + return BMF_DrawString(font, str); +#endif +} + +float UI_GetStringWidth(BMF_Font* font, char *str, int translate) +{ + float rt; + +#ifdef INTERNATIONAL + if(G.ui_international == TRUE) + if(translate && (U.transopts & USER_TR_BUTTONS)) + rt= FTF_GetStringWidth(str, FTF_USE_GETTEXT | FTF_INPUT_UTF8); + else + rt= FTF_GetStringWidth(str, FTF_NO_TRANSCONV | FTF_INPUT_UTF8); + else + rt= BMF_GetStringWidth(font, str); +#else + rt= BMF_GetStringWidth(font, str); +#endif + + return rt; +} + +void UI_GetBoundingBox(struct BMF_Font* font, char* str, int translate, rctf *bbox) +{ +#ifdef INTERNATIONAL + float dummy; + if(G.ui_international == TRUE) + if(translate && (U.transopts & USER_TR_BUTTONS)) + FTF_GetBoundingBox(str, &bbox->xmin, &bbox->ymin, &dummy, &bbox->xmax, &bbox->ymax, &dummy, FTF_USE_GETTEXT | FTF_INPUT_UTF8); + else + FTF_GetBoundingBox(str, &bbox->xmin, &bbox->ymin, &dummy, &bbox->xmax, &bbox->ymax, &dummy, FTF_NO_TRANSCONV | FTF_INPUT_UTF8); + else + BMF_GetStringBoundingBox(font, str, &bbox->xmin, &bbox->ymin, &bbox->xmax, &bbox->ymax); +#else + BMF_GetStringBoundingBox(font, str, &bbox->xmin, &bbox->ymin, &bbox->xmax, &bbox->ymax); +#endif +} + +#ifdef INTERNATIONAL + +char *fontsize_pup(void) +{ + static char string[1024]; + char formatstring[1024]; + + strcpy(formatstring, "Choose Font Size: %%t|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d"); + + sprintf(string, formatstring, + "Font Size: 8", 8, + "Font Size: 9", 9, + "Font Size: 10", 10, + "Font Size: 11", 11, + "Font Size: 12", 12, + "Font Size: 13", 13, + "Font Size: 14", 14, + "Font Size: 15", 15, + "Font Size: 16", 16 + ); + + return (string); +} + + +char *language_pup(void) +{ + struct LANGMenuEntry *lme = langmenu; + static char string[1024]; + static char tmp[1024]; + + if(tot_lang == 0) + sprintf(string, "Choose Language: %%t|Language: English %%x0"); + else { + sprintf(string, "Choose Language: %%t"); + while(lme) { + sprintf(tmp, "|Language: %s %%x%d", lme->language, lme->id); + strcat(string, tmp); + lme= lme->next; + } + } + + return string; +} + +struct LANGMenuEntry *find_language(short langid) +{ + struct LANGMenuEntry *lme = langmenu; + + while(lme) { + if(lme->id == langid) + return lme; + + lme=lme->next; + } + return NULL; +} + + +void lang_setlanguage(void) +{ + struct LANGMenuEntry *lme; + + lme = find_language(U.language); + if(lme) FTF_SetLanguage(lme->code); + else FTF_SetLanguage("en_US"); +} + +/* called from fileselector */ +void set_interface_font(char *str) +{ + + /* this test needed because fileselect callback can happen after disable AA fonts */ + if(U.transopts & USER_DOTRANSLATE) { + if(FTF_SetFont((unsigned char*)str, 0, U.fontsize)) { + lang_setlanguage(); + + if(strlen(str) < FILE_MAXDIR) strcpy(U.fontname, str); + G.ui_international = TRUE; + } + else { + U.fontname[0]= 0; + FTF_SetFont((unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size, U.fontsize); + G.ui_international = TRUE; // this case will switch to standard font + /* XXX 2.50 bad call okee("Invalid font selection - reverting to built-in font."); */ + } + /* XXX 2.50 bad call allqueue(REDRAWALL, 0); */ + } +} + +void start_interface_font(void) +{ + int result = 0; + + if(U.transopts & USER_USETEXTUREFONT) + FTF_SetMode(FTF_TEXTUREFONT); + else + FTF_SetMode(FTF_PIXMAPFONT); + + if(U.fontsize && U.fontname[0] ) { // we have saved user settings + fontpath + + // try loading font from U.fontname = full path to font in usersettings + result = FTF_SetFont((unsigned char*)U.fontname, 0, U.fontsize); + } + else if(U.fontsize) { // user settings, default + result = FTF_SetFont((unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size, U.fontsize); + } + + if(result==0) { // use default + U.language= 0; + U.fontsize= 11; + U.encoding= 0; + U.fontname[0]= 0; + result = FTF_SetFont((unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size, U.fontsize); + } + + if(result) { + lang_setlanguage(); + + G.ui_international = TRUE; + } + else { + printf("no font found for international support\n"); + G.ui_international = FALSE; + U.transopts &= ~USER_DOTRANSLATE; + U.fontsize = 0; + } + + /* XXX 2.50 bad call allqueue(REDRAWALL, 0); */ +} + +static char *first_dpointchar(char *string) +{ + char *dpointchar; + + dpointchar= strchr(string, ':'); + + return dpointchar; +} + + +static void splitlangline(char *line, struct LANGMenuEntry *lme) +{ + char *dpointchar= first_dpointchar(line); + + if (dpointchar) { + lme->code= BLI_strdup(dpointchar+1); + *(dpointchar)=0; + lme->language= BLI_strdup(line); + } else { + /* XXX 2.50 bad call error("Invalid language file"); */ + } +} + + +static void puplang_insert_entry(char *line) +{ + struct LANGMenuEntry *lme, *prev; + int sorted = 0; + + prev= NULL; + lme= langmenu; + + for (; lme; prev= lme, lme= lme->next) { + if (lme->line) { + if (BLI_streq(line, lme->line)) { + return; + } else if (sorted && strcmp(line, lme->line)<0) { + break; + } + } + } + + lme= MEM_mallocN(sizeof(*lme), "lme"); + lme->line = BLI_strdup(line); + splitlangline(line, lme); + lme->id = tot_lang; + tot_lang++; + + if (prev) { + lme->next= prev->next; + prev->next= lme; + } else { + lme->next= langmenu; + langmenu= lme; + } +} + + +int read_languagefile(void) +{ + char name[FILE_MAXDIR+FILE_MAXFILE]; + LinkNode *l, *lines; + + /* .Blanguages, http://www.blender3d.org/cms/Installation_Policy.352.0.html*/ +#if defined (__APPLE__) || (WIN32) + BLI_make_file_string("/", name, BLI_gethome(), ".Blanguages"); +#else + BLI_make_file_string("/", name, BLI_gethome(), ".blender/.Blanguages"); +#endif + + lines= BLI_read_file_as_lines(name); + + if(lines == NULL) { + /* If not found in home, try current dir + * (Resources folder of app bundle on OS X) */ +#if defined (__APPLE__) + char *bundlePath = BLI_getbundle(); + strcpy(name, bundlePath); + strcat(name, "/Contents/Resources/.Blanguages"); +#else + /* Check the CWD. Takes care of the case where users + * unpack blender tarball; cd blender-dir; ./blender */ + strcpy(name, ".blender/.Blanguages"); +#endif + lines= BLI_read_file_as_lines(name); + + if(lines == NULL) { + /* If not found in .blender, try current dir */ + strcpy(name, ".Blanguages"); + lines= BLI_read_file_as_lines(name); + if(lines == NULL) { + if(G.f & G_DEBUG) printf("File .Blanguages not found\n"); + return 0; + } + } + } + + for (l= lines; l; l= l->next) { + char *line= l->link; + + if (!BLI_streq(line, "")) { + puplang_insert_entry(line); + } + } + + BLI_free_file_lines(lines); + + return 1; +} + + +void free_languagemenu(void) +{ + struct LANGMenuEntry *lme= langmenu; + + while (lme) { + struct LANGMenuEntry *n= lme->next; + + if (lme->line) MEM_freeN(lme->line); + if (lme->language) MEM_freeN(lme->language); + if (lme->code) MEM_freeN(lme->code); + MEM_freeN(lme); + + lme= n; + } +} + +#endif /* INTERNATIONAL */ + diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index 564dd57cc62..075c89c9b47 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -13,8 +13,9 @@ #include "WM_api.h" #include "BIF_gl.h" -#include "BIF_resources.h" -#include "BIF_view2d.h" + +#include "UI_resources.h" +#include "UI_view2d.h" /* minimum pixels per gridstep */ #define IPOSTEP 35 @@ -24,13 +25,67 @@ struct View2DGrid { int machtx, machty; }; -/* OpenGL setup */ +/* Setup */ -void BIF_view2d_ortho(const bContext *C, View2D *v2d) +void UI_view2d_ortho(const bContext *C, View2D *v2d) { wmOrtho2(C->window, v2d->cur.xmin, v2d->cur.xmax, v2d->cur.ymin, v2d->cur.ymax); } +void UI_view2d_update_size(View2D *v2d, int winx, int winy) +{ + v2d->mask.xmin= v2d->mask.ymin= 0; + v2d->mask.xmax= winx; + v2d->mask.ymax= winy; + +#if 0 + if(sa->spacetype==SPACE_ACTION) { + if(sa->winx > ACTWIDTH+50) { + v2d->mask.xmin+= ACTWIDTH; + v2d->hor.xmin+=ACTWIDTH; + } + } + else if(sa->spacetype==SPACE_NLA){ + if(sa->winx > NLAWIDTH+50) { + v2d->mask.xmin+= NLAWIDTH; + v2d->hor.xmin+=NLAWIDTH; + } + } + else if(sa->spacetype==SPACE_IPO) { + int ipobutx = calc_ipobuttonswidth(sa); + + v2d->mask.xmax-= ipobutx; + + if(v2d->mask.xmaxmask.xmax= winx; + } +#endif + + if(v2d->scroll) { + if(v2d->scroll & L_SCROLL) { + v2d->vert= v2d->mask; + v2d->vert.xmax= SCROLLB; + v2d->mask.xmin= SCROLLB; + } + else if(v2d->scroll & R_SCROLL) { + v2d->vert= v2d->mask; + v2d->vert.xmin= v2d->vert.xmax-SCROLLB; + v2d->mask.xmax= v2d->vert.xmin; + } + + if((v2d->scroll & B_SCROLL) || (v2d->scroll & B_SCROLLO)) { + v2d->hor= v2d->mask; + v2d->hor.ymax= SCROLLH; + v2d->mask.ymin= SCROLLH; + } + else if(v2d->scroll & T_SCROLL) { + v2d->hor= v2d->mask; + v2d->hor.ymin= v2d->hor.ymax-SCROLLH; + v2d->mask.ymax= v2d->hor.ymin; + } + } +} + /* Grid */ static void step_to_grid(float *step, int *macht, int unit) @@ -71,7 +126,7 @@ static void step_to_grid(float *step, int *macht, int unit) } } -View2DGrid *BIF_view2d_calc_grid(const bContext *C, View2D *v2d, int unit, int clamp, int winx, int winy) +View2DGrid *UI_view2d_calc_grid(const bContext *C, View2D *v2d, int unit, int clamp, int winx, int winy) { View2DGrid *grid; float space, pixels, seconddiv; @@ -123,7 +178,7 @@ View2DGrid *BIF_view2d_calc_grid(const bContext *C, View2D *v2d, int unit, int c return grid; } -void BIF_view2d_draw_grid(const bContext *C, View2D *v2d, View2DGrid *grid, int flag) +void UI_view2d_draw_grid(const bContext *C, View2D *v2d, View2DGrid *grid, int flag) { float vec1[2], vec2[2]; int a, step; @@ -136,7 +191,7 @@ void BIF_view2d_draw_grid(const bContext *C, View2D *v2d, View2DGrid *grid, int step= (v2d->mask.xmax - v2d->mask.xmin+1)/IPOSTEP; - BIF_ThemeColor(TH_GRID); + UI_ThemeColor(TH_GRID); for(a=0; adx; - BIF_ThemeColorShade(TH_GRID, 16); + UI_ThemeColorShade(TH_GRID, 16); step++; for(a=0; a<=step; a++) { @@ -166,7 +221,7 @@ void BIF_view2d_draw_grid(const bContext *C, View2D *v2d, View2DGrid *grid, int step= (C->area->winy+1)/IPOSTEP; - BIF_ThemeColor(TH_GRID); + UI_ThemeColor(TH_GRID); for(a=0; a<=step; a++) { glBegin(GL_LINE_STRIP); glVertex2fv(vec1); glVertex2fv(vec2); @@ -177,7 +232,7 @@ void BIF_view2d_draw_grid(const bContext *C, View2D *v2d, View2DGrid *grid, int step++; } - BIF_ThemeColorShade(TH_GRID, -50); + UI_ThemeColorShade(TH_GRID, -50); if(flag & V2D_HORIZONTAL_AXIS) { /* horizontal axis */ @@ -203,14 +258,14 @@ void BIF_view2d_draw_grid(const bContext *C, View2D *v2d, View2DGrid *grid, int } } -void BIF_view2d_free_grid(View2DGrid *grid) +void UI_view2d_free_grid(View2DGrid *grid) { MEM_freeN(grid); } /* Coordinate conversion */ -void BIF_view2d_region_to_view(View2D *v2d, short x, short y, float *viewx, float *viewy) +void UI_view2d_region_to_view(View2D *v2d, short x, short y, float *viewx, float *viewy) { float div, ofs; @@ -229,7 +284,7 @@ void BIF_view2d_region_to_view(View2D *v2d, short x, short y, float *viewx, floa } } -void BIF_view2d_view_to_region(View2D *v2d, float x, float y, short *regionx, short *regiony) +void UI_view2d_view_to_region(View2D *v2d, float x, float y, short *regionx, short *regiony) { *regionx= V2D_IS_CLIPPED; *regiony= V2D_IS_CLIPPED; @@ -247,7 +302,7 @@ void BIF_view2d_view_to_region(View2D *v2d, float x, float y, short *regionx, sh } } -void BIF_view2d_to_region_no_clip(View2D *v2d, float x, float y, short *regionx, short *regiony) +void UI_view2d_to_region_no_clip(View2D *v2d, float x, float y, short *regionx, short *regiony) { x= (x - v2d->cur.xmin)/(v2d->cur.xmax-v2d->cur.xmin); y= (x - v2d->cur.ymin)/(v2d->cur.ymax-v2d->cur.ymin); @@ -268,3 +323,4 @@ void BIF_view2d_to_region_no_clip(View2D *v2d, float x, float y, short *regionx, } } + diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 6d77dc4eee9..bb7bb689289 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -47,10 +47,11 @@ #include "WM_types.h" #include "wm_subwindow.h" -#include "BIF_resources.h" #include "BIF_gl.h" #include "BIF_glutil.h" +#include "UI_resources.h" + #include "BPY_extern.h" #include "screen_intern.h" @@ -112,9 +113,9 @@ void ED_region_do_draw(bContext *C, ARegion *ar) wm_subwindow_set(C->window, ar->swinid); if(ar->swinid && at->draw) { - BIF_SetTheme(C->area); + UI_SetTheme(C->area); at->draw(C, ar); - BIF_SetTheme(NULL); + UI_SetTheme(NULL); } else { float fac= 0.1*ar->swinid; diff --git a/source/blender/editors/screen/spacetypes.c b/source/blender/editors/screen/spacetypes.c index 0292df8bc24..64c8c920c64 100644 --- a/source/blender/editors/screen/spacetypes.c +++ b/source/blender/editors/screen/spacetypes.c @@ -30,6 +30,8 @@ #include "BKE_global.h" #include "BKE_screen.h" +#include "UI_interface.h" + #include "BIF_gl.h" #include "WM_api.h" @@ -68,6 +70,7 @@ void ED_spacetypes_keymap(wmWindowManager *wm) SpaceType *type; ED_keymap_screen(wm); + UI_keymap(wm); spacetypes = BKE_spacetypes_list(); for(type=spacetypes->first; type; type=type->next) diff --git a/source/blender/editors/screen/stubs.c b/source/blender/editors/screen/stubs.c index 1b38173fbbd..b0b21881b07 100644 --- a/source/blender/editors/screen/stubs.c +++ b/source/blender/editors/screen/stubs.c @@ -33,7 +33,6 @@ void blender_test_break() {} void error() {} void set_timecursor() {} void waitcursor() {} -void pupmenu() {} void mainqenter() {} void saveover() {} void BIF_icons_free() {} diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 02a07044a8a..9dbbf668c27 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -29,7 +29,6 @@ #include #include -#include "DNA_object_types.h" #include "DNA_space_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -37,10 +36,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" -#include "BLI_arithb.h" -#include "BLI_rand.h" - #include "BKE_global.h" #include "BKE_screen.h" @@ -51,8 +46,10 @@ #include "BIF_gl.h" #include "BIF_glutil.h" -#include "BIF_resources.h" -#include "BIF_view2d.h" + +#include "UI_interface.h" +#include "UI_resources.h" +#include "UI_view2d.h" #include "time_intern.h" @@ -64,14 +61,13 @@ static void time_draw_cfra_time(const bContext *C, SpaceTime *stime) Scene *scene= C->scene; float vec[2]; - vec[0]= scene->r.cfra; - vec[0]*= scene->r.framelen; + vec[0]= scene->r.cfra*scene->r.framelen; - vec[1]= stime->v2d.cur.ymin; - BIF_ThemeColor(TH_CFRAME); // no theme, should be global color once... + UI_ThemeColor(TH_CFRAME); // no theme, should be global color once... glLineWidth(3.0); glBegin(GL_LINES); + vec[1]= stime->v2d.cur.ymin; glVertex2fv(vec); vec[1]= stime->v2d.cur.ymax; glVertex2fv(vec); @@ -84,7 +80,7 @@ static void time_draw_sfra_efra(const bContext *C, SpaceTime *stime) { /* draw darkened area outside of active timeline * frame range used is preview range or scene range */ - BIF_ThemeColorShade(TH_BACK, -25); + UI_ThemeColorShade(TH_BACK, -25); if (PSFRA < PEFRA) { glRectf(stime->v2d.cur.xmin, stime->v2d.cur.ymin, PSFRA, stime->v2d.cur.ymax); @@ -94,7 +90,7 @@ static void time_draw_sfra_efra(const bContext *C, SpaceTime *stime) glRectf(stime->v2d.cur.xmin, stime->v2d.cur.ymin, stime->v2d.cur.xmax, stime->v2d.cur.ymax); } - BIF_ThemeColorShade(TH_BACK, -60); + UI_ThemeColorShade(TH_BACK, -60); /* thin lines where the actual frames are */ fdrawline(PSFRA, stime->v2d.cur.ymin, PSFRA, stime->v2d.cur.ymax); fdrawline(PEFRA, stime->v2d.cur.ymin, PEFRA, stime->v2d.cur.ymax); @@ -121,21 +117,23 @@ static void time_main_area_draw(const bContext *C, ARegion *ar) winx= ar->winrct.xmax-ar->winrct.xmin; winy= ar->winrct.ymax-ar->winrct.ymin; + UI_view2d_update_size(&stime->v2d, winx, winy); + /* clear and setup matrix */ - BIF_GetThemeColor3fv(TH_BACK, col); + UI_GetThemeColor3fv(TH_BACK, col); glClearColor(col[0], col[1], col[2], 0.0); glClear(GL_COLOR_BUFFER_BIT); - BIF_view2d_ortho(C, &stime->v2d); + UI_view2d_ortho(C, &stime->v2d); /* start and end frame */ time_draw_sfra_efra(C, stime); /* grid */ unit= (stime->flag & TIME_DRAWFRAMES)? V2D_UNIT_FRAMES: V2D_UNIT_SECONDS; - grid= BIF_view2d_calc_grid(C, &stime->v2d, unit, V2D_GRID_CLAMP, winx, winy); - BIF_view2d_draw_grid(C, &stime->v2d, grid, V2D_VERTICAL_LINES|V2D_VERTICAL_AXIS); - BIF_view2d_free_grid(grid); + grid= UI_view2d_calc_grid(C, &stime->v2d, unit, V2D_GRID_CLAMP, winx, winy); + UI_view2d_draw_grid(C, &stime->v2d, grid, V2D_VERTICAL_LINES|V2D_VERTICAL_AXIS); + UI_view2d_free_grid(grid); /* current frame */ time_draw_cfra_time(C, stime); @@ -146,6 +144,25 @@ static void time_main_area_listener(ARegion *ar, wmNotifier *wmn) /* draw entirely, windowsize changes should be handled here */ } +/* ************************ header time area region *********************** */ + +static void time_header_area_draw(const bContext *C, ARegion *ar) +{ + float col[3]; + + /* clear */ + UI_GetThemeColor3fv(TH_HEADER, col); + glClearColor(col[0], col[1], col[2], 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + uiTestRegion(C); +} + +static void time_header_area_free(ARegion *ar) +{ + uiFreeBlocks(&ar->uiblocks); +} + /* ******************** default callbacks for time space ***************** */ static SpaceLink *time_new(void) @@ -219,6 +236,15 @@ static void time_init(wmWindowManager *wm, ScrArea *sa) WM_event_remove_keymap_handler(&ar->handlers, &wm->timekeymap); WM_event_add_keymap_handler(&ar->handlers, &wm->timekeymap); } + else if(ar->regiontype == RGN_TYPE_HEADER) { + static ARegionType headerart={NULL, NULL, NULL, NULL, NULL}; + + headerart.draw= time_header_area_draw; + headerart.free= time_header_area_free; + + ar->type= &headerart; + WM_event_add_keymap_handler(&ar->handlers, &wm->uikeymap); + } else { static ARegionType art={NULL, NULL, NULL, NULL, NULL}; diff --git a/source/blender/editors/space_time/time_ops.c b/source/blender/editors/space_time/time_ops.c index a02c5eb6844..bc9cb3fa762 100644 --- a/source/blender/editors/space_time/time_ops.c +++ b/source/blender/editors/space_time/time_ops.c @@ -39,7 +39,8 @@ #include "BKE_global.h" -#include "BIF_view2d.h" +#include "UI_interface.h" +#include "UI_view2d.h" #include "WM_api.h" #include "WM_types.h" @@ -110,10 +111,9 @@ static int frame_from_event(bContext *C, wmEvent *event) int x, y; float viewx; - /* XXX region->winrect isn't updated on window changes */ x= event->x - region->winrct.xmin; y= event->y - region->winrct.ymin; - BIF_view2d_region_to_view(&stime->v2d, x, y, &viewx, NULL); + UI_view2d_region_to_view(&stime->v2d, x, y, &viewx, NULL); return (int)(viewx+0.5f); } @@ -157,7 +157,6 @@ static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -/* Operator for joining two areas (space types) */ void ED_TIME_OT_change_frame(wmOperatorType *ot) { /* identifiers */ diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index bb5bf6d19b3..aa2b0938775 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -67,6 +67,7 @@ typedef struct wmWindowManager { /* custom keymaps */ ListBase windowkeymap; ListBase screenkeymap; + ListBase uikeymap; ListBase timekeymap; diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 87a3ce790f9..a162670b226 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -149,6 +149,7 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm) } BLI_freelistN(&wm->timekeymap); + BLI_freelistN(&wm->uikeymap); BLI_freelistN(&wm->windowkeymap); BLI_freelistN(&wm->screenkeymap); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index ec2e750eb2c..425c1f1acc5 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -74,9 +74,10 @@ #include "BLO_readfile.h" #include "BLO_writefile.h" -// XXX #include "BPY_extern.h" +#include "ED_datafiles.h" +#include "UI_interface.h" -//XXX #include "datatoc.h" +// XXX #include "BPY_extern.h" #include "WM_api.h" #include "WM_types.h" @@ -90,8 +91,8 @@ /* patching UserDef struct and Themes */ static void init_userdef_themes(void) { - -// XXX BIF_InitTheme(); // sets default again + // sets themes, fonts, .. from userdef + UI_init_userdef(); // countall(); @@ -556,8 +557,6 @@ int WM_read_homefile(bContext *C, int from_memory) if (!from_memory && BLI_exists(tstr)) { success = BKE_read_file(C, tstr, NULL); } else { - extern int datatoc_B_blend_size; - extern char datatoc_B_blend[]; success = BKE_read_file_from_memory(C, datatoc_B_blend, datatoc_B_blend_size, NULL); /* outliner patch for 2.42 .b.blend */ outliner_242_patch(); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index ffc535c1d46..67670383060 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -68,6 +68,8 @@ #include "SYS_System.h" +#include "UI_interface.h" + #include "WM_api.h" #include "WM_types.h" #include "wm.h" @@ -78,16 +80,7 @@ static void initbuttons(void) { -// uiDefFont(UI_HELVB, -// BMF_GetFont(BMF_kHelveticaBold14), -// BMF_GetFont(BMF_kHelveticaBold12), -// BMF_GetFont(BMF_kHelveticaBold10), -// BMF_GetFont(BMF_kHelveticaBold8)); -// uiDefFont(UI_HELV, -// BMF_GetFont(BMF_kHelvetica12), -// BMF_GetFont(BMF_kHelvetica12), -// BMF_GetFont(BMF_kHelvetica10), -// BMF_GetFont(BMF_kHelveticaBold8)); + UI_init(); // glClearColor(.7f, .7f, .6f, 0.0); @@ -133,10 +126,7 @@ void WM_init(bContext *C) // XXX BIF_preview_init_dbase(); - -// XXX BIF_resources_init(); /* after homefile, to dynamically load an icon file based on theme settings */ - -// XXX BIF_filelist_init_icons(); +// XXX UI_filelist_init_icons(); // init_gl_stuff(); /* drawview.c, after homefile */ read_Blog(); @@ -228,9 +218,7 @@ void WM_exit(bContext *C) #endif if (!G.background) { -// XXX BIF_resources_free(); - -// XXX BIF_filelist_free_icons(); +// XXX UI_filelist_free_icons(); } #ifdef INTERNATIONAL @@ -246,6 +234,7 @@ void WM_exit(bContext *C) BKE_undo_save_quit(); // saves quit.blend if global undo is on BKE_reset_undo(); + UI_exit(); BLI_freelistN(&U.themes); // XXX BIF_preview_free_dbase();