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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/src/interface.c')
-rw-r--r--source/blender/src/interface.c6699
1 files changed, 0 insertions, 6699 deletions
diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c
deleted file mode 100644
index a17e488ef13..00000000000
--- a/source/blender/src/interface.c
+++ /dev/null
@@ -1,6699 +0,0 @@
-/**
- * $Id$
- *
- * ***** 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 *****
- */
-
-/*
- a full doc with API notes can be found in bf-blender/blender/doc/interface_API.txt
-
- */
-
-
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef WIN32
-#include <unistd.h>
-#else
-#include <io.h>
-#endif
-
-#include "MEM_guardedalloc.h"
-
-#include "PIL_time.h"
-
-#include "BMF_Api.h"
-#include "BIF_language.h"
-#ifdef INTERNATIONAL
-#include "FTF_Api.h"
-#endif // INTERNATIONAL
-
-#include "BLI_blenlib.h"
-#include "BLI_arithb.h"
-
-#include "DNA_color_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-#include "DNA_userdef_types.h"
-#include "DNA_vec_types.h"
-#include "DNA_object_types.h"
-#include "DNA_texture_types.h"
-#include "DNA_vfont_types.h"
-
-#include "BKE_blender.h"
-#include "BKE_colortools.h"
-#include "BKE_global.h"
-#include "BKE_library.h"
-#include "BKE_texture.h"
-#include "BKE_utildefines.h"
-
-#include "BIF_cursors.h"
-#include "BIF_gl.h"
-#include "BIF_graphics.h"
-#include "BIF_keyval.h"
-#include "BIF_mainqueue.h"
-#include "BIF_resources.h"
-#include "BIF_screen.h"
-#include "BIF_toolbox.h"
-#include "BIF_mywindow.h"
-#include "BIF_space.h"
-#include "BIF_glutil.h"
-#include "BIF_editfont.h"
-#include "BIF_interface.h"
-#include "BIF_interface_icons.h"
-#include "BIF_butspace.h"
-#include "BIF_previewrender.h"
-
-#include "BSE_view.h"
-
-#include "BPY_extern.h" /* for BPY_button_eval */
-
-#include "GHOST_Types.h" /* for tablet data */
-
-#include "mydevice.h"
-#include "interface.h"
-#include "blendef.h"
-#include "winlay.h"
-
-#define INSIDE_BLOCK 1
-#define INSIDE_PANEL_HEADER 2
-#define INSIDE_PANEL_SCALE 3
-
-/* naming conventions:
- *
- * uiBlahBlah() external function
- * ui_blah_blah() internal function
- */
-
-/***/
-/* ************ GLOBALS ************* */
-
-float UIwinmat[4][4];
-static int UIlock= 0, UIafterval;
-static char *UIlockstr=NULL;
-
-static void (*UIafterfunc_butm)(void *arg, int event);
-static void (*UIafterfunc_but)(void *arg1, void *arg2);
-static void *UIafterfunc_arg1, *UIafterfunc_arg2;
-
-static uiFont UIfont[UI_ARRAY]; // no init needed
-uiBut *UIbuttip;
-
-static char but_copypaste_str[256]="";
-static double but_copypaste_val=0.0;
-static float but_copypaste_rgb[3];
-static ColorBand but_copypaste_coba;
-
-/* ************* PROTOTYPES ***************** */
-
-static void ui_set_but_val(uiBut *but, double value);
-static void ui_do_but_tip(uiBut *buttip);
-
-/* ****************************** */
-
-static int uibut_contains_pt(uiBut *but, short *pt)
-{
- return ((but->x1<pt[0] && but->x2>=pt[0]) &&
- (but->y1<pt[1] && but->y2>=pt[1]));
-}
-
-static void uibut_do_func(uiBut *but)
-{
- if (but->func) {
- but->func(but->func_arg1, but->func_arg2);
- }
-}
-
-/* ************* window matrix ************** */
-
-
-void ui_graphics_to_window(int win, float *x, float *y) /* for rectwrite */
-{
- float gx, gy;
- int sx, sy;
- int getsizex, getsizey;
-
- bwin_getsize(win, &getsizex, &getsizey);
- bwin_getsuborigin(win, &sx, &sy);
-
- gx= *x;
- gy= *y;
- *x= ((float)sx) + ((float)getsizex)*(0.5+ 0.5*(gx*UIwinmat[0][0]+ gy*UIwinmat[1][0]+ UIwinmat[3][0]));
- *y= ((float)sy) + ((float)getsizey)*(0.5+ 0.5*(gx*UIwinmat[0][1]+ gy*UIwinmat[1][1]+ UIwinmat[3][1]));
-}
-
-void ui_graphics_to_window_rct(int win, rctf *graph, rcti *winr)
-{
- float gx, gy;
- int sx, sy;
- int getsizex, getsizey;
-
- bwin_getsize(win, &getsizex, &getsizey);
- bwin_getsuborigin(win, &sx, &sy);
-
- gx= graph->xmin;
- gy= graph->ymin;
- winr->xmin= (int)((float)sx) + ((float)getsizex)*(0.5+ 0.5*(gx*UIwinmat[0][0]+ gy*UIwinmat[1][0]+ UIwinmat[3][0]));
- winr->ymin= (int)((float)sy) + ((float)getsizey)*(0.5+ 0.5*(gx*UIwinmat[0][1]+ gy*UIwinmat[1][1]+ UIwinmat[3][1]));
- gx= graph->xmax;
- gy= graph->ymax;
- winr->xmax= (int)((float)sx) + ((float)getsizex)*(0.5+ 0.5*(gx*UIwinmat[0][0]+ gy*UIwinmat[1][0]+ UIwinmat[3][0]));
- winr->ymax= (int)((float)sy) + ((float)getsizey)*(0.5+ 0.5*(gx*UIwinmat[0][1]+ gy*UIwinmat[1][1]+ UIwinmat[3][1]));
-}
-
-
-void ui_window_to_graphics(int win, float *x, float *y) /* for mouse cursor */
-{
- float a, b, c, d, e, f, px, py;
- int getsizex, getsizey;
-
- bwin_getsize(win, &getsizex, &getsizey);
-
- a= .5*((float)getsizex)*UIwinmat[0][0];
- b= .5*((float)getsizex)*UIwinmat[1][0];
- c= .5*((float)getsizex)*(1.0+UIwinmat[3][0]);
-
- d= .5*((float)getsizey)*UIwinmat[0][1];
- e= .5*((float)getsizey)*UIwinmat[1][1];
- f= .5*((float)getsizey)*(1.0+UIwinmat[3][1]);
-
- px= *x;
- py= *y;
-
- *y= (a*(py-f) + d*(c-px))/(a*e-d*b);
- *x= (px- b*(*y)- c)/a;
-
-}
-
-
-/* ************* SAVE UNDER ************ */
-
-/* new method:
-
-OverDraw *ui_begin_overdraw(int minx, int miny, int maxx, int maxy);
-- enforces mainwindow to become active
-- grabs copy from frontbuffer, pastes in back
-
-void ui_flush_overdraw(OverDraw *od);
-- copies backbuffer to front
-
-void ui_refresh_overdraw(Overdraw *od);
-- pastes in back copy of frontbuffer again for fresh drawing
-
-void ui_end_overdraw(OverDraw *od);
-- puts back on frontbuffer saved image
-- frees copy
-- sets back active blender area
-- signals backbuffer to be corrupt (sel buffer!)
-
-*/
-
-/* frontbuffer updates now glCopyPixels too, with block->flush rect */
-
-/* new idea for frontbuffer updates:
-
-- hilites: with blended poly?
-
-- full updates... thats harder, but:
- - copy original
- - before draw, always paste to backbuf
- - flush
- - always end with redraw event for full update
-
-*/
-
-static void myglCopyPixels(int a, int b, int c, int d, int e)
-{
- if(G.rt==2) {
- unsigned int *buf= MEM_mallocN(4*c*d, "temp glcopypixels");
- glReadPixels(a, b, c, d, GL_RGBA, GL_UNSIGNED_BYTE, buf);
- glDrawPixels(c, d, GL_RGBA, GL_UNSIGNED_BYTE, buf);
- MEM_freeN(buf);
- }
- else glCopyPixels(a, b, c, d, e);
-}
-
-typedef struct {
- short x, y, sx, sy, oldwin;
- unsigned int *rect;
-} uiOverDraw;
-
-
-static uiOverDraw *ui_begin_overdraw(int minx, int miny, int maxx, int maxy)
-{
- uiOverDraw *od=NULL;
-
- // dirty patch removed for sun and sgi to mywindow.c commented out
-
- /* clip with actual window size */
- if(minx < 0) minx= 0;
- if(miny < 0) miny= 0;
- if(maxx >= G.curscreen->sizex) maxx= G.curscreen->sizex-1;
- if(maxy >= G.curscreen->sizey) maxy= G.curscreen->sizey-1;
-
- if(minx<maxx && miny<maxy) {
- od= MEM_callocN(sizeof(uiOverDraw), "overdraw");
-
- od->x= minx;
- od->y= miny;
- od->sx= maxx-minx;
- od->sy= maxy-miny;
- od->rect= MEM_mallocN(od->sx*od->sy*4, "temp_frontbuffer_image");
-
- od->oldwin= mywinget();
- mywinset(G.curscreen->mainwin);
- /* grab front */
- glReadBuffer(GL_FRONT);
- glReadPixels(od->x, od->y, od->sx, od->sy, GL_RGBA, GL_UNSIGNED_BYTE, od->rect);
- glReadBuffer(GL_BACK);
- /* paste in back */
- glDisable(GL_DITHER);
- glRasterPos2f(od->x, od->y);
- glDrawPixels(od->sx, od->sy, GL_RGBA, GL_UNSIGNED_BYTE, od->rect);
- glEnable(GL_DITHER);
- }
-
- return od;
-}
-
-static void ui_flush_overdraw(uiOverDraw *od)
-{
-
- if(od==NULL) return;
- glDisable(GL_DITHER);
- glReadBuffer(GL_BACK);
- glDrawBuffer(GL_FRONT);
- glRasterPos2s(od->x, od->y);
- myglCopyPixels(od->x, od->y, od->sx, od->sy, GL_COLOR);
- glEnable(GL_DITHER);
- bglFlush();
- glDrawBuffer(GL_BACK);
-}
-
-/* special flush version to enable transparent menus */
-static void ui_block_flush_overdraw(uiBlock *block)
-{
-
- if(block->flag & UI_BLOCK_LOOP) {
- char col[4];
-
- BIF_GetThemeColor4ubv(TH_MENU_BACK, col);
- if(col[3]!=255) {
- uiBut *bt;
- uiOverDraw *od= block->overdraw;
-
- /* completely draw all! */
- glRasterPos2s(od->x, od->y);
- glDrawPixels(od->sx, od->sy, GL_RGBA, GL_UNSIGNED_BYTE, od->rect);
-
- uiDrawMenuBox(block->minx, block->miny, block->maxx, block->maxy, block->flag);
- for (bt= block->buttons.first; bt; bt= bt->next) {
- ui_draw_but(bt);
- }
- }
- }
-
- ui_flush_overdraw(block->overdraw);
-}
-
-static void ui_end_overdraw(uiOverDraw *od)
-{
- if(od==NULL) return;
-
- glDisable(GL_DITHER);
-
- // clear in back
- glRasterPos2s(od->x, od->y);
- glDrawPixels(od->sx, od->sy, GL_RGBA, GL_UNSIGNED_BYTE, od->rect);
-
- // clear in front
- glDrawBuffer(GL_FRONT);
- glRasterPos2s(od->x, od->y);
- glDrawPixels(od->sx, od->sy, GL_RGBA, GL_UNSIGNED_BYTE, od->rect);
-
- bglFlush();
- glDrawBuffer(GL_BACK);
- glEnable(GL_DITHER);
-
- if(od->oldwin) mywinset(od->oldwin);
-
- MEM_freeN(od->rect);
- MEM_freeN(od);
-
- markdirty_all_back(); // sets flags only
-}
-
-/* ****************** live updates for hilites and button presses *********** */
-
-void ui_block_flush_back(uiBlock *block)
-{
- int minx, miny, sizex, sizey;
-
- /* note; this routine also has to work for block loop */
- if(block->needflush==0) return;
-
- /* exception, when we cannot use backbuffer for draw... */
- if(block->flag & UI_BLOCK_FRONTBUFFER) {
- bglFlush();
- glDrawBuffer(GL_BACK);
- block->needflush= 0;
- return;
- }
-
- /* copy pixels works on window coords, so we move to window space */
-
- ui_graphics_to_window(block->win, &block->flush.xmin, &block->flush.ymin);
- ui_graphics_to_window(block->win, &block->flush.xmax, &block->flush.ymax);
- minx= floor(block->flush.xmin);
- miny= floor(block->flush.ymin);
- sizex= ceil(block->flush.xmax-block->flush.xmin);
- sizey= ceil(block->flush.ymax-block->flush.ymin);
-
- if(sizex>0 && sizey>0) {
- glPushMatrix();
- mywinset(G.curscreen->mainwin);
-
- glDisable(GL_DITHER);
- glReadBuffer(GL_BACK);
- glDrawBuffer(GL_FRONT);
- glRasterPos2i(minx, miny);
-#ifdef __sun__
- myglCopyPixels(minx, miny+1, sizex, sizey, GL_COLOR);
-#else
- myglCopyPixels(minx, miny, sizex, sizey, GL_COLOR);
-#endif
- glEnable(GL_DITHER);
- bglFlush();
- glDrawBuffer(GL_BACK);
-
- mywinset(block->win);
- glPopMatrix();
-
- markdirty_win_back(block->win);
- }
-
- block->needflush= 0;
-}
-
-/* merge info for live updates in frontbuf */
-void ui_block_set_flush(uiBlock *block, uiBut *but)
-{
- /* clear signal */
- if(but==NULL) {
- block->needflush= 0;
-
- block->flush.xmin= 0.0;
- block->flush.xmax= 0.0;
- }
- else {
- /* exception, when we cannot use backbuffer for draw... */
- if(block->flag & UI_BLOCK_FRONTBUFFER) {
- glDrawBuffer(GL_FRONT);
- }
- else if(block->needflush==0) {
- /* first rect */
- block->flush.xmin= but->x1;
- block->flush.xmax= but->x2;
- block->flush.ymin= but->y1;
- block->flush.ymax= but->y2;
-
- }
- else {
- /* union of rects */
- if(block->flush.xmin > but->x1) block->flush.xmin= but->x1;
- if(block->flush.xmax < but->x2) block->flush.xmax= but->x2;
- if(block->flush.ymin > but->y1) block->flush.ymin= but->y1;
- if(block->flush.ymax < but->y2) block->flush.ymax= but->y2;
- }
-
- block->needflush= 1;
-
- }
-}
-
-/* ******************* copy and paste ******************** */
-
-/* c = copy, v = paste */
-/* return 1 when something changed */
-static int ui_but_copy_paste(uiBut *but, char mode)
-{
- void *poin;
-
- if(mode=='v' && but->lock) return 0;
- poin= but->poin;
-
- if ELEM3(but->type, NUM, NUMSLI, HSVSLI) {
-
- if(poin==NULL);
- else if(mode=='c') {
- but_copypaste_val= ui_get_but_val(but);
- }
- else {
- ui_set_but_val(but, but_copypaste_val);
- uibut_do_func(but);
- ui_check_but(but);
- return 1;
- }
- }
- else if(but->type==COL) {
-
- if(poin==NULL);
- else if(mode=='c') {
- if(but->pointype==FLO) {
- float *fp= (float *) poin;
- but_copypaste_rgb[0]= fp[0];
- but_copypaste_rgb[1]= fp[1];
- but_copypaste_rgb[2]= fp[2];
- }
- else if (but->pointype==CHA) {
- char *cp= (char *) poin;
- but_copypaste_rgb[0]= (float)(cp[0]/255.0);
- but_copypaste_rgb[1]= (float)(cp[1]/255.0);
- but_copypaste_rgb[2]= (float)(cp[2]/255.0);
- }
-
- }
- else {
- if(but->pointype==FLO) {
- float *fp= (float *) poin;
- fp[0] = but_copypaste_rgb[0];
- fp[1] = but_copypaste_rgb[1];
- fp[2] = but_copypaste_rgb[2];
- return 1;
- }
- else if (but->pointype==CHA) {
- char *cp= (char *) poin;
- cp[0] = (char)(but_copypaste_rgb[0]*255.0);
- cp[1] = (char)(but_copypaste_rgb[1]*255.0);
- cp[2] = (char)(but_copypaste_rgb[2]*255.0);
-
- return 1;
- }
-
- }
- }
- else if(but->type==TEX) {
- if(poin==NULL);
- else if(mode=='c') {
- strncpy(but_copypaste_str, but->poin, but->max);
- }
- else {
- char backstr[UI_MAX_DRAW_STR];
- /* give butfunc the original text too */
- /* feature used for bone renaming, channels, etc */
- if(but->func_arg2==NULL) {
- strncpy(backstr, but->drawstr, UI_MAX_DRAW_STR);
- but->func_arg2= backstr;
- }
- strncpy(but->poin, but_copypaste_str, but->max);
- uibut_do_func(but);
- ui_check_but(but);
- return 1;
- }
- }
- else if(but->type==IDPOIN) {
- if(mode=='c') {
- ID *id= *but->idpoin_idpp;
- if(id) strncpy(but_copypaste_str, id->name+2, 22);
- }
- else {
- but->idpoin_func(but_copypaste_str, but->idpoin_idpp);
- ui_check_but(but);
- return 1;
- }
- }
- else if(but->type==BUT_COLORBAND) {
- if(mode=='c') {
- if (!but->poin) {
- return 0;
- }
- memcpy( &but_copypaste_coba, but->poin, sizeof(ColorBand) );
- } else {
- if (but_copypaste_coba.tot==0) {
- return 0;
- }
- if (!but->poin) {
- but->poin= MEM_callocN( sizeof(ColorBand), "colorband");
- }
- memcpy( but->poin, &but_copypaste_coba, sizeof(ColorBand) );
- return 1;
- }
- }
-
- return 0;
-}
-
-/* ******************* 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= (U.transopts & USER_TR_BUTTONS);
- if(bt->type==TEX || bt->type==IDPOIN) transopts= 0;
- j= BIF_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->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;
-}
-
-static void ui_positionblock(uiBlock *block, uiBut *but)
-{
- /* position block relative to but */
- uiBut *bt;
- rctf butrct;
- float aspect;
- int xsize, ysize, xof=0, yof=0, center;
- short dir1= 0, dir2=0;
-
- /* first transform to screen coords, assuming matrix is stil OK */
- /* the UIwinmat is in panelspace */
-
- butrct.xmin= but->x1; butrct.xmax= but->x2;
- butrct.ymin= but->y1; butrct.ymax= but->y2;
-
- ui_graphics_to_window(block->win, &butrct.xmin, &butrct.ymin);
- ui_graphics_to_window(block->win, &butrct.xmax, &butrct.ymax);
- block->parentrct= butrct; // will use that for pulldowns later
-
- /* calc block rect */
- 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_graphics_to_window(block->win, &block->minx, &block->miny);
- ui_graphics_to_window(block->win, &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) {
- short left=0, right=0, top=0, down=0;
-
- if(block->direction & UI_CENTER) center= ysize/2;
- else center= 0;
-
- if( butrct.xmin-xsize > 0.0) left= 1;
- if( butrct.xmax+xsize < G.curscreen->sizex) right= 1;
- if( butrct.ymin-ysize+center > 0.0) down= 1;
- if( butrct.ymax+ysize-center < G.curscreen->sizey) 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_graphics_to_window(block->win, &bt->x1, &bt->y1);
- ui_graphics_to_window(block->win, &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= (block->parentrct.xmin+block->parentrct.xmax)/2.0;
- float midy= (block->parentrct.ymin+block->parentrct.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;
- }
-
-}
-
-
-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; i<rows; i++) totmaxh+= maxh[i];
-
- /* apply widths/heights */
- starty= block->maxy;
- 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) BIF_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 DRAWING FUNCTION ************* */
-
-
-void uiDrawBlock(uiBlock *block)
-{
- uiBut *but;
- short testmouse=0, mouse[2];
-
- /* we set this only once */
- glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
-
- /* 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);
-
- /* we set active flag on a redraw again */
- if((block->flag & UI_BLOCK_LOOP)==0) {
- testmouse= 1;
- Mat4CpyMat4(UIwinmat, block->winmat);
- }
-
- uiPanelPush(block); // panel matrix
-
- if(block->flag & UI_BLOCK_LOOP) {
- uiDrawMenuBox(block->minx, block->miny, block->maxx, block->maxy, block->flag);
- }
- else {
- if(block->panel) ui_draw_panel(block);
- }
-
- if(block->drawextra) block->drawextra(curarea, block);
-
- if(testmouse) /* do it after panel push, otherwise coords are wrong */
- uiGetMouse(block->win, mouse);
-
- for (but= block->buttons.first; but; but= but->next) {
-
- if(testmouse && uibut_contains_pt(but, mouse))
- but->flag |= UI_ACTIVE;
-
- ui_draw_but(but);
- }
-
- ui_draw_links(block);
-
- uiPanelPop(block); // matrix restored
-}
-
-/* ************* MENUBUTS *********** */
-
-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++;
-}
-
-static 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()
- */
-static 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;
-}
-
-static void ui_set_name_menu(uiBut *but, int value)
-{
- MenuData *md;
- int i;
-
- md= decompose_menu_string(but->str);
- for (i=0; i<md->nitems; i++)
- if (md->items[i].retval==value)
- strcpy(but->drawstr, md->items[i].str);
-
- menudata_free(md);
-}
-
-static void ui_warp_pointer(short x, short y)
-{
- /* OSX has very poor mousewarp support, it sends events;
- this causes a menu being pressed immediately ... */
- #ifndef __APPLE__
- warp_pointer(x, y);
- #endif
-}
-
-#define TBOXH 20
-static int ui_do_but_MENU(uiBut *but)
-{
- uiBlock *block;
- uiBut *bt;
- ListBase listb={NULL, NULL}, lb;
- double fvalue;
- int width, height=0, a, xmax, starty;
- short startx;
- int columns=1, rows=0, boxh, event;
- short x1, y1, active= -1;
- short mval[2];
- MenuData *md;
-
- but->flag |= UI_SELECT;
- ui_draw_but(but);
- ui_block_flush_back(but->block); // flush because this button creates own blocks loop
-
- block= uiNewBlock(&listb, "menu", UI_EMBOSSP, UI_HELV, but->win);
- block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT;
- block->themecol= TH_MENU_ITEM;
-
- 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= (int) md->nitems/columns;
- if (rows<1) rows= 1;
-
- while (rows*columns<md->nitems) rows++;
-
- /* prevent scaling up of pupmenu */
- if (but->aspect < 1.0f) but->aspect = 1.0f;
-
- /* size and location */
- if(md->title)
- width= 1.5*but->aspect*strlen(md->title)+BIF_GetStringWidth(block->curfont, md->title, (U.transopts & USER_TR_MENUS));
- else
- width= 0;
-
- for(a=0; a<md->nitems; a++) {
- xmax= but->aspect*BIF_GetStringWidth(block->curfont, md->items[a].str, (U.transopts & USER_TR_MENUS));
- if ( md->items[a].icon) xmax += 20*but->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= TBOXH;
-
- height= rows*boxh;
- if (md->title) height+= boxh;
-
- getmouseco_sc(mval);
-
- /* find active item */
- fvalue= ui_get_but_val(but);
- for(active=0; active<md->nitems; active++) {
- if( md->items[active].retval== (int)fvalue ) break;
- }
- /* no active item? */
- if(active==md->nitems) {
- if(md->title) active= -1;
- else active= 0;
- }
-
- /* for now disabled... works confusing because you think it's a title or so.... */
- active= -1;
-
- /* here we go! */
- startx= but->x1;
- starty= but->y1;
-
- if(md->title) {
- uiBut *bt;
- uiSetCurFont(block, block->font+1);
- if (md->titleicon) {
- 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; a<md->nitems; a++) {
-
- x1= but->x1 + width*((int)(md->nitems-a-1)/rows);
- y1= but->y1 - boxh*(rows - ((md->nitems - a - 1)%rows)) + (rows*boxh);
-
- if (strcmp(md->items[md->nitems-a-1].str, "%l")==0) {
- 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) {
- uiBut *bt= uiDefIconTextBut(block, BUTM|but->pointype, but->retval, md->items[md->nitems-a-1].icon ,md->items[md->nitems-a-1].str, x1, y1,(short)(width-(rows>1)), (short)(boxh-1), but->poin, (float) md->items[md->nitems-a-1].retval, 0.0, 0, 0, "");
- if(active==a) bt->flag |= UI_ACTIVE;
- }
- else {
- uiBut *bt= uiDefBut(block, BUTM|but->pointype, but->retval, md->items[md->nitems-a-1].str, x1, y1,(short)(width-(rows>1)), (short)(boxh-1), but->poin, (float) md->items[md->nitems-a-1].retval, 0.0, 0, 0, "");
- if(active==a) bt->flag |= UI_ACTIVE;
- }
- }
-
- /* 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;
-
- /* and lets go */
- block->direction= UI_TOP;
- ui_positionblock(block, but);
-
- /* blocks can come (and get scaled) from a normal window, now we go to screenspace */
- block->win= G.curscreen->mainwin;
- for(bt= block->buttons.first; bt; bt= bt->next) bt->win= block->win;
- bwin_getsinglematrix(block->win, block->winmat);
-
- event= uiDoBlocks(&listb, 0, 1);
-
- menudata_free(md);
-
- but->flag &= ~UI_SELECT;
- ui_check_but(but);
- /* no draw of button now, for floating panels the matrix now is invalid...
- the button still is active, and will be redrawn in main loop to de-activate it */
- /* but, if no hilites, we send redraw to queue */
- if(but->flag & UI_NO_HILITE)
- addqueue(but->block->winq, REDRAW, 1);
-
- uibut_do_func(but);
-
- /* return no existing event, because the menu sends events instead */
- return -1;
-}
-
-/* ********************** NEXT/PREV for arrowkeys etc ************** */
-
-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;
-}
-
-
-/* ************* IN-BUTTON TEXT SELECTION/EDITING ************* */
-
-static short ui_delete_selection_edittext(uiBut *but)
-{
- int x;
- short deletedwidth=0;
- char *str;
-
- str= (char *)but->poin;
-
- deletedwidth = (but->selend - but->selsta);
-
- 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 deletedwidth;
-}
-
-static void ui_set_cursor_pos_edittext(uiBut *but, short sx)
-{
- char backstr[UI_MAX_DRAW_STR];
-
- BLI_strncpy(backstr, but->drawstr, UI_MAX_DRAW_STR);
- but->pos= strlen(backstr)-but->ofs;
-
- while((but->aspect*BIF_GetStringWidth(but->font, backstr+but->ofs, 0) + but->x1) > sx) {
- if (but->pos <= 0) break;
- but->pos--;
- backstr[but->pos+but->ofs] = 0;
- }
-
- but->pos -= strlen(but->str);
- but->pos += but->ofs;
- if(but->pos<0) but->pos= 0;
-}
-
-
-/* ************* EVENTS ************* */
-
-void uiGetMouse(int win, short *adr)
-{
- int x, y;
- float xwin, ywin;
-
- getmouseco_sc(adr);
- if (win == G.curscreen->mainwin) return;
-
- bwin_getsuborigin(win, &x, &y);
-
- adr[0]-= x;
- adr[1]-= y;
-
- xwin= adr[0];
- ywin= adr[1];
-
- ui_window_to_graphics(win, &xwin, &ywin);
-
- adr[0]= (short)(xwin+0.5);
- adr[1]= (short)(ywin+0.5);
-}
-
-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= 0;
- 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;
-}
-
-static int ui_do_but_BUT(uiBut *but)
-{
- int activated;
-
- do {
- int oflag= but->flag;
- short mval[2];
-
- uiGetMouse(mywinget(), mval);
-
- if (uibut_contains_pt(but, mval))
- but->flag |= UI_SELECT;
- else
- but->flag &= ~UI_SELECT;
-
- if (but->flag != oflag) {
- ui_draw_but(but);
- ui_block_flush_back(but->block);
- }
-
- PIL_sleep_ms(10);
- } while (get_mbut() & L_MOUSE);
-
- activated= (but->flag & UI_SELECT);
-
- if(activated) {
- UIafterfunc_but= but->func;
- UIafterfunc_arg1= but->func_arg1;
- UIafterfunc_arg2= but->func_arg2;
- /* no more uibut_do_func(but); this button calls fileselecting windows */
- }
-
- but->flag &= ~UI_SELECT;
- ui_draw_but(but);
-
- return activated?but->retval:0;
-}
-
-static int ui_do_but_KEYEVT(uiBut *but)
-{
- unsigned short event= 0;
- short val;
-
- /* flag for ui_check_but */
- ui_set_but_val(but, -1);
- ui_check_but(but);
- ui_draw_but(but);
- ui_block_flush_back(but->block);
-
- do {
- event= extern_qread(&val);
- } while (!event || !val || ELEM(event, MOUSEX, MOUSEY));
-
- if (!key_event_to_string(event)[0]) event= 0;
-
- ui_set_but_val(but, (double) event);
- ui_check_but(but);
- ui_draw_but(but);
-
- return (event!=0);
-}
-
-static int ui_do_but_TOG(uiBlock *block, uiBut *but, int qual)
-{
- uiBut *bt;
- double value;
- int w, lvalue, push;
-
- /* local hack... */
- if(but->type==BUT_TOGDUAL && qual==LR_CTRLKEY) {
- 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( (get_qual() & LR_SHIFTKEY)==0 ) {
- lvalue= 1<<(but->bitnr);
-
- ui_set_but_val(but, (double)lvalue);
-
- bt= block->buttons.first;
- while(bt) {
- if( bt!=but && bt->poin==but->poin ) {
- ui_is_but_sel(bt);
- ui_draw_but(bt);
- }
- bt= bt->next;
- }
- }
- 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);
- // no frontbuffer draw for this one
- if(but->type==BUT_TOGDUAL);
- else if((but->flag & UI_NO_HILITE)==0) ui_draw_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);
- // no frontbuffer draw for this one
- if((but->flag & UI_NO_HILITE)==0) ui_draw_but(but);
- }
-
- /* end local hack... */
- if(but->type==BUT_TOGDUAL && qual==LR_CTRLKEY) {
- if(but->pointype==SHO)
- but->poin -= 2;
- else if(but->pointype==INT)
- but->poin -= 4;
- }
-
- /* no while loop...this button is used for viewmove */
-
- uibut_do_func(but);
-
- return but->retval;
-}
-
-static int ui_do_but_ROW(uiBlock *block, uiBut *but)
-{
- uiBut *bt;
-
- ui_set_but_val(but, but->max);
- ui_draw_but(but);
-
- bt= block->buttons.first;
- while(bt) {
- if( bt!=but && bt->type==ROW ) {
- if(bt->min==but->min) {
- ui_is_but_sel(bt);
- ui_draw_but(bt);
- }
- }
- bt= bt->next;
- }
- return but->retval;
-}
-
-/* return 1 if char ch is special character otherwise
- * it returns 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_do_but_TEX(uiBut *but)
-{
- unsigned short dev;
- short x, y, mval[2], len=0, dodraw, selextend=0;
- char *str, backstr[UI_MAX_DRAW_STR];
- short capturing, sx, sy, prevx;
-
- str= (char *)but->poin;
-
- but->flag |= UI_SELECT;
-
- uiGetMouse(mywinget(), mval);
-
- /* set cursor pos to the end of the text */
- but->pos = strlen(str);
- but->selsta = 0;
- but->selend = strlen(but->drawstr) - strlen(but->str);
-
- /* backup */
- BLI_strncpy(backstr, but->poin, UI_MAX_DRAW_STR);
-
- ui_draw_but(but);
- ui_block_flush_back(but->block);
-
- while (get_mbut() & L_MOUSE) BIF_wait_for_statechange();
- len= strlen(str);
-
- but->min= 0.0;
-
- capturing = TRUE;
- while(capturing) {
- char ascii;
- short val;
-
- dodraw= 0;
- dev = extern_qread_ext(&val, &ascii);
-
- if(dev==INPUTCHANGE) break;
- else if(get_mbut() & R_MOUSE) break;
- else if(get_mbut() & L_MOUSE) {
- uiGetMouse(mywinget(), mval);
- sx = mval[0]; sy = mval[1];
-
- if ((but->y1 <= sy) && (sy <= but->y2) && (but->x1 <= sx) && (sx <= but->x2)) {
- ui_set_cursor_pos_edittext(but, mval[0]);
-
- but->selsta = but->selend = but->pos;
-
- /* drag text select */
- prevx= mval[0];
- while (get_mbut() & L_MOUSE) {
- uiGetMouse(mywinget(), mval);
-
- if(prevx!=mval[0]) {
-
- if (mval[0] > sx) selextend = EXTEND_RIGHT;
- else if (mval[0] < sx) selextend = EXTEND_LEFT;
-
- ui_set_cursor_pos_edittext(but, mval[0]);
-
- if (selextend == EXTEND_RIGHT) but->selend = but->pos;
- if (selextend == EXTEND_LEFT) but->selsta = but->pos;
-
- ui_check_but(but);
- ui_draw_but(but);
- ui_block_flush_back(but->block);
- }
- PIL_sleep_ms(10);
- }
- dodraw= 1;
- } else break;
- }
- else if(dev==ESCKEY) break;
- else if(dev==MOUSEX) val= 0;
- else if(dev==MOUSEY) val= 0;
-
- /* cut, copy, paste selected text */
- /* mainqread discards ascii values < 32, so can't do this cleanly within the if(ascii) block*/
- else if ( (val) &&
- ((G.qual & LR_COMMANDKEY) || (G.qual & LR_CTRLKEY)) &&
- ((dev==XKEY) || (dev==CKEY) || (dev==VKEY)) ) {
-
-
- /* paste */
- if (dev==VKEY) {
- /* paste over the current selection */
- if ((but->selend - but->selsta) > 0) {
- len -= ui_delete_selection_edittext(but);
- }
-
- for (y=0; y<strlen(but_copypaste_str); y++)
- {
- /* add contents of buffer */
- if(len < but->max) {
- for(x= but->max; x>but->pos; x--)
- str[x]= str[x-1];
- str[but->pos]= but_copypaste_str[y];
- but->pos++;
- len++;
- str[len]= '\0';
- }
- }
- if (strlen(but_copypaste_str) > 0) dodraw= 1;
- }
- /* cut & copy */
- else if ( (dev==XKEY) || (dev==CKEY) ) {
- /* copy the contents to the copypaste buffer */
- for(x= but->selsta; x <= but->selend; x++) {
- if (x==but->selend)
- but_copypaste_str[x] = '\0';
- else
- but_copypaste_str[(x - but->selsta)] = str[x];
- }
-
- /* for cut only, delete the selection afterwards */
- if (dev==XKEY) {
- if ((but->selend - but->selsta) > 0) {
- len -= ui_delete_selection_edittext(but);
-
- if (len < 0) len = 0;
- dodraw=1;
- }
- }
- }
- }
- else if((ascii)){
-
- if(len-(but->selend - but->selsta)+1 <= but->max) {
-
- /* type over the current selection */
- if ((but->selend - but->selsta) > 0) {
- len -= ui_delete_selection_edittext(but);
- }
-
- if(len < but->max) {
- for(x= but->max; x>but->pos; x--)
- str[x]= str[x-1];
- str[but->pos]= ascii;
- but->pos++;
- len++;
- str[len]= '\0';
- dodraw= 1;
- }
- }
- }
- else if(val) {
-
- switch (dev) {
-
- case RIGHTARROWKEY:
- /* if there's a selection */
- if ((but->selend - but->selsta) > 0) {
- /* extend the selection based on the first direction taken */
- if(G.qual & LR_SHIFTKEY) {
- if (!selextend) {
- selextend = EXTEND_RIGHT;
- }
- if (selextend == EXTEND_RIGHT) {
- but->selend++;
- if (but->selend > len) but->selend = len;
- } else if (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;
- selextend = EXTEND_RIGHT;
- }
- }
- } else {
- but->selsta = but->pos = but->selend;
- selextend = 0;
- }
- } else {
- if(G.qual & LR_SHIFTKEY) {
- /* 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(G.qual & LR_CTRLKEY) {
- /* 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);
- }
- }
- dodraw= 1;
- break;
-
- case LEFTARROWKEY:
- /* if there's a selection */
- if ((but->selend - but->selsta) > 0) {
- /* extend the selection based on the first direction taken */
- if(G.qual & LR_SHIFTKEY) {
- if (!selextend) {
- selextend = EXTEND_LEFT;
- }
- if (selextend == EXTEND_LEFT) {
- but->selsta--;
- if (but->selsta < 0) but->selsta = 0;
- } else if (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;
- selextend = EXTEND_LEFT;
- }
- }
- } else {
- but->pos = but->selend = but->selsta;
- selextend = 0;
- }
- } else {
- if(G.qual & LR_SHIFTKEY) {
- /* 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(G.qual & LR_CTRLKEY) {
- /* 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--;
- }
- }
- dodraw= 1;
- break;
-
- case DOWNARROWKEY:
- case ENDKEY:
- if(G.qual & LR_SHIFTKEY) {
- but->selsta = but->pos;
- but->selend = strlen(str);
- selextend = EXTEND_RIGHT;
- } else {
- but->selsta = but->selend = but->pos= strlen(str);
- }
- dodraw= 1;
- break;
-
- case UPARROWKEY:
- case HOMEKEY:
- if(G.qual & LR_SHIFTKEY) {
- but->selend = but->pos;
- but->selsta = 0;
- selextend = EXTEND_LEFT;
- } else {
- but->selsta = but->selend = but->pos= 0;
- }
- dodraw= 1;
- break;
-
- case PADENTER:
- case RETKEY:
- capturing = FALSE;
- break;
-
- case DELKEY:
- if ((but->selend - but->selsta) > 0) {
- len -= ui_delete_selection_edittext(but);
-
- if (len < 0) len = 0;
- dodraw=1;
- }
- else if(but->pos>=0 && but->pos<strlen(str)) {
- for(x=but->pos; x<=strlen(str); x++)
- str[x]= str[x+1];
- str[--len]='\0';
- dodraw= 1;
- }
- break;
-
- case BACKSPACEKEY:
- if(len!=0) {
- if ((but->selend - but->selsta) > 0) {
- len -= ui_delete_selection_edittext(but);
-
- if (len < 0) len = 0;
- dodraw=1;
- }
- else if(get_qual() & LR_SHIFTKEY) {
- str[0]= 0;
- but->pos= 0;
- len= 0;
- dodraw= 1;
- }
- else if(but->pos>0) {
- for(x=but->pos; x<=strlen(str); x++)
- str[x-1]= str[x];
- but->pos--;
- str[--len]='\0';
- dodraw= 1;
- }
- }
- break;
-
- case TABKEY:
- if(but->autocomplete_func) {
- but->autocomplete_func(str, but->autofunc_arg);
- but->pos= strlen(str);
- len= but->pos;
- dodraw= 1;
- }
- else capturing= FALSE;
-
- break;
- }
- }
-
-
- if(dodraw) {
- ui_check_but(but);
- ui_draw_but(but);
- ui_block_flush_back(but->block);
- }
- }
-
- if(dev==ESCKEY) strcpy(but->poin, backstr);
- but->pos= -1;
- but->flag &= ~UI_SELECT;
-
- if(dev!=ESCKEY) {
- /* give butfunc the original text too */
- /* feature used for bone renaming, channels, etc */
- if(but->func_arg2==NULL) but->func_arg2= backstr;
- uibut_do_func(but);
- }
-
- ui_check_but(but);
- ui_draw_but(but);
-
- if(dev==TABKEY) addqueue(but->win, G.qual?BUT_PREV:BUT_NEXT, 1);
-
- if(dev!=ESCKEY) return but->retval;
- else return B_NOP; // prevent event to be passed on
-}
-
-
-static int ui_act_as_text_but(uiBut *but)
-{
- void *but_func;
- double value;
- float min, max;
- int temp, retval, textleft;
- char str[UI_MAX_DRAW_STR], *point;
-
- /* this function is abused for tab-cycling */
- if(but->type==TEX)
- return ui_do_but_TEX(but);
-
- value= ui_get_but_val(but);
- if( but->pointype==FLO ) {
- if(but->a2) { /* amount of digits defined */
- if(but->a2==1) sprintf(str, "%.1f", value);
- else if(but->a2==2) sprintf(str, "%.2f", value);
- else if(but->a2==3) sprintf(str, "%.3f", value);
- else sprintf(str, "%.4f", value);
- }
- else sprintf(str, "%.3f", value);
- }
- else {
- sprintf(str, "%d", (int)value);
- }
- /* store values before calling as text button */
- point= but->poin;
- but->poin= str;
- but_func= but->func;
- but->func= NULL;
- min= but->min;
- max= but->max;
- but->min= 0.0;
- but->max= UI_MAX_DRAW_STR - 1; /* for py strings evaluation */
- temp= but->type;
- but->type= TEX;
- textleft= but->flag & UI_TEXT_LEFT;
- but->flag |= UI_TEXT_LEFT;
- ui_check_but(but);
-
- retval= ui_do_but_TEX(but);
-
- /* restore values */
- but->type= temp;
- but->poin= point;
- but->func= but_func;
- but->min= min;
- but->max= max;
- if(textleft==0) but->flag &= ~UI_TEXT_LEFT;
-
- if(BPY_button_eval(str, &value)) {
- /* Uncomment this if you want to see an error message (and annoy users) */
- /* error("Invalid Python expression, check console");*/
- value = 0.0f; /* Zero out value on error */
-
- if(str[0])
- retval = 0; /* invalidate return value if eval failed, except when string was null */
- }
-
- if(but->pointype!=FLO) value= (int)value;
-
- if(value<min) value= min;
- if(value>max) value= max;
-
- ui_set_but_val(but, value);
- ui_check_but(but);
- ui_draw_but(but);
-
- return retval;
-}
-
-static int ui_do_but_NUM(uiBut *but)
-{
- double value;
- float deler, fstart, f, tempf, pressure;
- int lvalue, temp, orig_x; /* , firsttime=1; */
- short retval=0, qual, sx, mval[2], pos=0;
-
- but->flag |= UI_SELECT;
- ui_draw_but(but);
- ui_block_flush_back(but->block);
-
- uiGetMouse(mywinget(), mval);
- value= ui_get_but_val(but);
-
- sx= mval[0];
- orig_x = sx; /* Store so we can scale the rate of change by the dist the mouse is from its original xlocation */
- fstart= (value - but->min)/(but->max-but->min);
- f= fstart;
-
- temp= (int)value;
- tempf= value;
-
- if(get_qual() & LR_SHIFTKEY) { /* make it textbut */
- if( ui_act_as_text_but(but) ) retval= but->retval;
- }
- else {
- retval= but->retval;
- /* firsttime: this button can be approached with enter as well */
-
- /* drag-lock - prevent unwanted scroll adjustments */
- /* change last value (now 3) to adjust threshold in pixels */
- while (get_mbut() & L_MOUSE & ( abs(mval[0]-sx) <= 3) ) {
- uiGetMouse(mywinget(), mval);
- }
- sx = mval[0]; /* ignore mouse movement within drag-lock */
-
- while (get_mbut() & L_MOUSE) {
- qual= get_qual();
- pressure = get_pressure();
-
- uiGetMouse(mywinget(), mval);
-
- deler= 500;
- if( but->pointype!=FLO ) {
-
- if( (but->max-but->min)<100 ) deler= 200.0;
- if( (but->max-but->min)<25 ) deler= 50.0;
- }
-
- if(qual & LR_SHIFTKEY) deler*= 10.0;
- if(qual & LR_ALTKEY) deler*= 20.0;
-
- /* de-sensitise based on tablet pressure */
- if (ELEM(get_activedevice(), DEV_STYLUS, DEV_ERASER)) deler /= pressure;
-
- if(mval[0] != sx) {
- if( but->pointype==FLO && but->max-but->min > 11) {
- /* non linear change in mouse input- good for high precicsion */
- f+= (((float)(mval[0]-sx))/deler) * (fabs(orig_x-mval[0])*0.002);
- } else if ( but->pointype!=FLO && 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 */
- f+= (((float)(mval[0]-sx))/deler) * (fabs(orig_x-mval[0])*0.004);
- } else {
- /*no scaling */
- f+= ((float)(mval[0]-sx))/deler ;
- }
-
- if(f>1.0) f= 1.0;
- if(f<0.0) f= 0.0;
- sx= mval[0];
- tempf= ( but->min + f*(but->max-but->min));
-
- if( but->pointype!=FLO ) {
-
- temp= floor(tempf+.5);
-
- if(tempf==but->min || tempf==but->max);
- else if(qual & LR_CTRLKEY) {
- if(qual & LR_SHIFTKEY) temp= 100*(temp/100);
- else temp= 10*(temp/10);
- }
- if( temp>=but->min && temp<=but->max) {
-
- value= ui_get_but_val(but);
- lvalue= (int)value;
-
- if(temp != lvalue ) {
- pos= 1;
- ui_set_but_val(but, (double)temp);
- ui_check_but(but);
- ui_draw_but(but);
- ui_block_flush_back(but->block);
-
- uibut_do_func(but);
- }
- }
-
- }
- else {
- temp= 0;
- if(qual & LR_CTRLKEY) {
- if(qual & LR_SHIFTKEY) {
- 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) {
- value= ui_get_but_val(but);
-
- if(tempf != value ) {
- pos= 1;
- ui_set_but_val(but, tempf);
- ui_check_but(but);
- ui_draw_but(but);
- ui_block_flush_back(but->block);
- }
- }
-
- }
- }
- BIF_wait_for_statechange();
- }
-
- /* click on the side arrows to increment/decrement, click inside
- * to edit the value directly */
- if(pos==0) { /* plus 1 or minus 1 */
- if( but->pointype!=FLO ) {
-
- if(sx < (but->x1 + (but->x2 - but->x1)/3 - 3)) {
- temp--;
- if( temp>=but->min && temp<=but->max) ui_set_but_val(but, (double)temp);
- }
- else if(sx > (but->x1 + (2*(but->x2 - but->x1)/3) + 3)) {
- temp++;
- if( temp>=but->min && temp<=but->max) ui_set_but_val(but, (double)temp);
- }
- else {
- if( ui_act_as_text_but(but) ); else retval= 0;
- }
- }
- else {
-
- if(sx < (but->x1 + (but->x2 - but->x1)/3 - 3)) {
- tempf-= 0.01*but->a1;
- if (tempf < but->min) tempf = but->min;
- ui_set_but_val(but, tempf);
- }
- else if(sx > but->x1 + (2*((but->x2 - but->x1)/3) + 3)) {
- tempf+= 0.01*but->a1;
- if (tempf < but->min) tempf = but->min;
- ui_set_but_val(but, tempf);
- }
- else {
- if( ui_act_as_text_but(but) ); else retval= 0;
- }
- }
- }
- }
-
- but->flag &= ~UI_SELECT;
- ui_check_but(but);
- ui_draw_but(but);
- ui_block_flush_back(but->block);
-
- uibut_do_func(but);
-
- return retval;
-}
-
-static int ui_do_but_TOG3(uiBut *but)
-{
-
- 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_is_but_sel(but);
- ui_draw_but(but);
-
- return but->retval;
-}
-
-static int ui_do_but_ICONROW(uiBut *but)
-{
- ListBase listb= {NULL, NULL};
- uiBlock *block;
- int a;
-
- but->flag |= UI_SELECT;
- ui_draw_but(but);
- ui_block_flush_back(but->block); // flush because this button creates own blocks loop
-
- /* here we go! */
- block= uiNewBlock(&listb, "menu", UI_EMBOSSP, UI_HELV, but->win);
- 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++) {
- uiDefIconBut(block, BUTM|but->pointype, but->retval, but->icon+(a-but->min), 0, (short)(18*a), (short)(but->x2-but->x1-4), 18, but->poin, (float)a, 0.0, 0, 0, "");
- }
- block->direction= UI_TOP;
- ui_positionblock(block, but);
-
- /* the block is made with but-win, but is handled in mainwin space...
- this is needs better implementation */
- block->win= G.curscreen->mainwin;
-
- uiDoBlocks(&listb, 0, 1);
-
- but->flag &= ~UI_SELECT;
- ui_check_but(but);
- ui_draw_but(but);
-
- return but->retval;
-}
-
-static int ui_do_but_ICONTEXTROW(uiBut *but)
-{
- uiBlock *block;
- ListBase listb={NULL, NULL};
- int width, a, xmax, ypos;
- MenuData *md;
-
- but->flag |= UI_SELECT;
- ui_draw_but(but);
- ui_block_flush_back(but->block); // flush because this button creates own blocks loop
-
- block= uiNewBlock(&listb, "menu", UI_EMBOSSP, UI_HELV, but->win);
- 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)+BIF_GetStringWidth(block->curfont, md->title, (U.transopts & USER_TR_MENUS));
- else
- width= 0;
-
- for(a=0; a<md->nitems; a++) {
- xmax= BIF_GetStringWidth(block->curfont, md->items[a].str, (U.transopts & USER_TR_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; a<md->nitems; a++) {
-
- /* add a space if there's a separator (%l) */
- if (strcmp(md->items[a].str, "%l")==0) {
- ypos +=3;
- }
- else {
- uiDefIconTextBut(block, BUTM|but->pointype, but->retval, (short)((but->icon)+(md->items[a].retval-but->min)), md->items[a].str, 0, ypos,(short)width, 19, but->poin, (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;
- }
-
- block->direction= UI_TOP;
- ui_positionblock(block, but);
-
- /* the block is made with but-win, but is handled in mainwin space...
- this is needs better implementation */
- block->win= G.curscreen->mainwin;
-
- uiBoundsBlock(block, 3);
-
- uiDoBlocks(&listb, 0, 1);
-
- menudata_free(md);
-
- but->flag &= ~UI_SELECT;
- ui_check_but(but);
- ui_draw_but(but);
-
- uibut_do_func(but);
-
- return but->retval;
-
-}
-
-static int ui_do_but_IDPOIN(uiBut *but)
-{
- char str[UI_MAX_DRAW_STR];
- ID *id;
-
- id= *but->idpoin_idpp;
- if(id) strcpy(str, id->name+2);
- else str[0]= 0;
-
- but->type= TEX;
- but->poin= str;
- but->min= 0.0;
- but->max= 22.0;
- ui_check_but(but);
- ui_do_but_TEX(but);
- but->poin= NULL;
- but->type= IDPOIN;
-
- but->idpoin_func(str, but->idpoin_idpp);
- ui_check_but(but);
- ui_draw_but(but);
-
- return but->retval;
-}
-
-static int ui_do_but_SLI(uiBut *but)
-{
- float f, fstart, tempf = 0.0, deler, value;
- int sx, h, temp, pos=0, lvalue, redraw;
- short mval[2], qual;
-
- value= ui_get_but_val(but);
- uiGetMouse(mywinget(), mval);
-
- sx= mval[0];
- h= but->y2-but->y1;
- fstart= but->max-but->min;
- fstart= (value - but->min)/fstart;
- temp= 32767;
-
- 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);
-
-
- while (get_mbut() & L_MOUSE) {
-
- qual= get_qual();
- uiGetMouse(mywinget(), mval);
-
- f= (float)(mval[0]-sx)/deler +fstart;
-
- if (qual & LR_SHIFTKEY) {
- f= (f-fstart)/10.0 + fstart;
- }
-
- CLAMP(f, 0.0, 1.0);
- tempf= but->min+f*(but->max-but->min);
- temp= floor(tempf+.5);
-
- if(qual & LR_CTRLKEY) {
- if(tempf==but->min || tempf==but->max);
- else if( but->pointype==FLO ) {
-
- if(qual & LR_SHIFTKEY) {
- 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;
- }
- }
-
- value= ui_get_but_val(but);
- lvalue= floor(value+0.5);
-
- if( but->pointype!=FLO )
- redraw= (temp != lvalue);
- else
- redraw= (tempf != value);
-
- if (redraw) {
- pos= 1;
- ui_set_but_val(but, tempf);
- ui_check_but(but);
- ui_draw_but(but);
- ui_block_flush_back(but->block);
-
- if(but->a1) { /* color number */
- uiBut *bt= but->prev;
- while(bt) {
- if(bt->a2 == but->a1) ui_draw_but(bt);
- bt= bt->prev;
- }
- bt= but->next;
- while(bt) {
- if(bt->a2 == but->a1) ui_draw_but(bt);
- bt= bt->next;
- }
- }
- /* save current window matrix (global UIwinmat)
- because button callback function MIGHT change it
- - which has until now occured through the Python API
- */
- /* This is really not possible atm... nothing in Blender
- supports such functionality even now. Calling function
- callbacks while using a button screws up the UI (ton)
- */
- /* Mat4CpyMat4(curmatrix, UIwinmat);
- uibut_do_func(but);
- Mat4CpyMat4(UIwinmat, curmatrix); */
- }
- else BIF_wait_for_statechange();
- }
-
-
- if(temp!=32767 && pos==0) { /* plus 1 or minus 1 */
-
- if( but->type==SLI) f= (float)(mval[0]-but->x1)/(but->x2-but->x1-h);
- else f= (float)(mval[0]- (but->x1+but->x2)/2)/( (but->x2-but->x1)/2 - h);
-
- f= but->min+f*(but->max-but->min);
-
- if( but->pointype!=FLO ) {
-
- if(f<temp) temp--;
- else temp++;
- if( temp>=but->min && temp<=but->max)
- ui_set_but_val(but, (float)temp);
-
- }
- else {
-
- if(f<tempf) tempf-=.01;
- else tempf+=.01;
- if( tempf>=but->min && tempf<=but->max)
- ui_set_but_val(but, tempf);
-
- }
- }
- ui_check_but(but);
- ui_draw_but(but);
- uibut_do_func(but);
- ui_block_flush_back(but->block);
-
- return but->retval;
-}
-
-static int ui_do_but_NUMSLI(uiBut *but)
-{
- short mval[2];
-
- /* first define if it's a slider or textbut */
- uiGetMouse(mywinget(), mval);
-
- if(mval[0]>= -6+(but->x1+but->x2)/2 ) { /* slider */
- but->flag |= UI_SELECT;
- ui_draw_but(but);
- ui_do_but_SLI(but);
- but->flag &= ~UI_SELECT;
- }
- else {
- ui_act_as_text_but(but);
- uibut_do_func(but); // this is done in ui_do_but_SLI() not in ui_act_as_text_but()
- }
-
- while(get_mbut() & L_MOUSE) BIF_wait_for_statechange();
-
- ui_draw_but(but);
-
- /* hsv patch */
- if(but->type==HSVSLI) {
-
- if(but->str[0]=='H') {
- ui_draw_but(but->next);
- ui_draw_but(but->next->next);
- }
- else if(but->str[0]=='S') {
- ui_draw_but(but->next);
- ui_draw_but(but->prev);
- }
- else if(but->str[0]=='V') {
- ui_draw_but(but->prev);
- ui_draw_but(but->prev->prev);
- }
- }
-
- return but->retval;
-}
-
-/* event denotes if we make first item active or not */
-static uiBlock *ui_do_but_BLOCK(uiBut *but, int event)
-{
- uiBlock *block;
- uiBut *bt;
-
- but->flag |= UI_SELECT;
- ui_draw_but(but);
-
- block= but->block_func(but->poin);
- block->parent= but->block; /* allows checking for nested pulldowns */
-
- 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_positionblock(block, but);
- block->flag |= UI_BLOCK_LOOP;
-
- /* blocks can come (and get scaled) from a normal window, now we go to screenspace */
- block->win= G.curscreen->mainwin;
- for(bt= block->buttons.first; bt; bt= bt->next) bt->win= block->win;
- bwin_getsinglematrix(block->win, block->winmat);
-
- /* postpone draw, this will cause a new window matrix, first finish all other buttons */
- block->flag |= UI_BLOCK_REDRAW;
-
- if(event!=MOUSEX && event!=MOUSEY && event!=LEFTMOUSE && but->type==BLOCK) {
- bt= ui_but_first(block);
- if(bt) bt->flag |= UI_ACTIVE;
- }
-
- but->flag &= ~UI_SELECT;
- uibut_do_func(but);
-
- if(but->retval)
- addqueue(curarea->win, UI_BUT_EVENT, (short)but->retval);
-
- return block;
-}
-
-static int ui_do_but_BUTM(uiBut *but)
-{
-
- ui_set_but_val(but, but->min);
- UIafterfunc_butm= but->butm_func;
- UIafterfunc_arg1= but->butm_func_arg;
- UIafterval= but->a2;
-
- return but->retval;
-}
-
-static int ui_do_but_LABEL(uiBut *but)
-{
- uibut_do_func(but);
- return but->retval;
-}
-
-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;
-}
-
-
-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 BIF_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;
-}
-
-/* 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 */
-static 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;
- }
- }
-}
-
-static void update_picker_buts_hsv(uiBlock *block, float *hsv, char *poin)
-{
- 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 update_picker_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;
- uiBut *but;
- float *col= (float *)col1;
- float *fp, hsv[3];
-
- fp= (float *)but1->poin;
-
- 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);
- update_picker_buts_hsv(but1->block, hsv, but1->poin);
- update_picker_hex(but1->block, col);
-
- 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);
-}
-
-/* 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;
- uiBut *but;
- 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);
- }
- update_picker_buts_hsv(but1->block, hsv, but1->poin);
-
- 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);
-
-}
-
-/* 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;
- uiBut *but;
- 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);
- }
- update_picker_buts_hsv(but1->block, fp, but1->poin);
-
- 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);
-
-}
-
-static void do_palette_hex_cb(void *bt1, void *hexcl)
-{
- uiBut *but1= (uiBut *)bt1;
- uiBut *but;
- char *hexcol= (char *)hexcl;
-
- update_picker_buts_hex(but1->block, hexcol);
-
- 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);
-}
-
-
-/* used for both 3d view and image window */
-static void do_palette_sample_cb(void *bt1, void *col1) /* frontbuf */
-{
- 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) BIF_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);
- update_picker_buts_hsv(but1->block, hsv, but1->poin);
- 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);
-}
-
-
-/* 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);
-}
-
-static int ui_do_but_COL(uiBut *but)
-{
- uiBlock *block;
- uiBut *bt;
- ListBase listb={NULL, NULL};
- float hsv[3], old[3], *poin= NULL, colstore[3];
- static char hexcol[128];
- short event;
-
- // signal to prevent calling up color picker
- if(but->a1 == -1) {
- uibut_do_func(but);
- return but->retval;
- }
-
- // enable char button too, use temporal colstore for color
- if(but->pointype!=FLO) {
- if(but->pointype==CHA) {
- ui_get_but_vectorf(but, colstore);
- poin= colstore;
- }
- else return but->retval;
- }
- else poin= (float *)but->poin;
-
- block= uiNewBlock(&listb, "colorpicker", UI_EMBOSS, UI_HELV, but->win);
- block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW;
- block->themecol= TH_BUT_NUM;
-
- uiBlockPickerButtons(block, poin, hsv, old, hexcol, 'p', 0);
-
- /* and lets go */
- block->direction= UI_TOP;
- ui_positionblock(block, but);
- uiBoundsBlock(block, 3);
-
- /* blocks can come from a normal window, but we go to screenspace */
- block->win= G.curscreen->mainwin;
- for(bt= block->buttons.first; bt; bt= bt->next) bt->win= block->win;
- bwin_getsinglematrix(block->win, block->winmat);
-
- event= uiDoBlocks(&listb, 0, 1);
-
- if(but->pointype==CHA) ui_set_but_vectorf(but, colstore);
-
- uibut_do_func(but);
- return but->retval;
-
-}
-
-static int ui_do_but_HSVCUBE(uiBut *but)
-{
- uiBut *bt;
- float x, y;
- short mval[2], mvalo[2];
-
- mvalo[0]= mvalo[1]= -32000;
-
- /* we work on persistant hsv, to prevent it being converted back and forth all the time */
-
- while (get_mbut() & L_MOUSE) {
-
- uiGetMouse(mywinget(), mval);
-
- if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
- mvalo[0]= mval[0];
- mvalo[1]= mval[1];
-
- /* relative position within box */
- x= ((float)mval[0]-but->x1)/(but->x2-but->x1);
- y= ((float)mval[1]-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;
- // hsv_to_rgb(x, s, y, col, col+1, col+2);
- }
- else if(but->a1==1) {
- but->hsv[0]= x;
- but->hsv[1]= y;
- // hsv_to_rgb(x, y, v, col, col+1, col+2);
- }
- else if(but->a1==2) {
- but->hsv[2]= x;
- but->hsv[1]= y;
- // hsv_to_rgb(h, y, x, col, col+1, col+2);
- }
- else {
- but->hsv[0]= x;
- // hsv_to_rgb(x, s, v, col, col+1, col+2);
- }
-
- ui_set_but_hsv(but); // converts to rgb
-
- // update button values and strings
- update_picker_buts_hsv(but->block, but->hsv, but->poin);
-// update_picker_buts_hex(but->block, but->hsv);
-
- /* we redraw the entire block */
- for (bt= but->block->buttons.first; bt; bt= bt->next) {
- if(but->poin == bt->poin) VECCOPY(bt->hsv, but->hsv);
- ui_draw_but(bt);
- }
- ui_block_flush_back(but->block);
- }
- else BIF_wait_for_statechange();
- }
-
- return but->retval;
-}
-
-#ifdef INTERNATIONAL
-
-static int ui_do_but_CHARTAB(uiBut *but)
-{
- /* Variables */
- short mval[2];
- float sx, sy, ex, ey;
- float width, height;
- float butw, buth;
- int x, y, cs, che;
-
- /* Check the position */
- uiGetMouse(mywinget(), mval);
-
- /* 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) ((mval[0] / butw) - 0.5);
- y = (int) (6 - ((mval[1] / buth) - 0.5));
-
- che = cs + (y*12) + x;
-
- if(che > G.charmax)
- che = 0;
-
- if(G.obedit)
- {
- do_textedit(0,0,che);
- }
-
- return but->retval;
-}
-
-#endif
-
-static int vergcband(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 do_colorband_evt(ColorBand *coba)
-{
- int a;
-
- if(coba==NULL) return;
-
- if(coba->tot<2) return;
-
- for(a=0; a<coba->tot; a++) coba->data[a].cur= a;
- qsort(coba->data, coba->tot, sizeof(CBData), vergcband);
- for(a=0; a<coba->tot; a++) {
- if(coba->data[a].cur==coba->cur) {
- if(coba->cur!=a) addqueue(curarea->win, REDRAW, 0); /* button cur */
- coba->cur= a;
- break;
- }
- }
-}
-
-static int ui_do_but_COLORBAND(uiBut *but)
-{
- ColorBand *coba= (ColorBand *)but->poin;
- CBData *cbd;
- float dx, width= but->x2-but->x1;
- int a;
- int mindist= 12, xco;
- short mval[2], mvalo[2];
-
- uiGetMouse(mywinget(), mvalo);
-
- if(G.qual & LR_CTRLKEY) {
- /* insert new key on mouse location */
- if(coba->tot < MAXCOLORBAND-1) {
- float pos= ((float)(mvalo[0] - but->x1))/width;
- 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;
-
- do_colorband_evt(coba);
- }
- }
- else {
-
- /* first, activate new key when mouse is close */
- for(a=0, cbd= coba->data; a<coba->tot; a++, cbd++) {
- xco= but->x1 + (cbd->pos*width);
- xco= ABS(xco-mvalo[0]);
- if(a==coba->cur) xco+= 5; // selected one disadvantage
- if(xco<mindist) {
- coba->cur= a;
- mindist= xco;
- }
- }
-
- cbd= coba->data + coba->cur;
-
- while(get_mbut() & L_MOUSE) {
- uiGetMouse(mywinget(), mval);
- if(mval[0]!=mvalo[0]) {
- dx= mval[0]-mvalo[0];
- dx/= width;
- cbd->pos+= dx;
- CLAMP(cbd->pos, 0.0, 1.0);
-
- ui_draw_but(but);
- ui_block_flush_back(but->block);
-
- do_colorband_evt(coba);
- cbd= coba->data + coba->cur; /* because qsort */
-
- mvalo[0]= mval[0];
- }
- BIF_wait_for_statechange();
- }
- }
-
- return but->retval;
-}
-
-/* button is presumed square */
-/* if mouse moves outside of sphere, it does negative normal */
-static int ui_do_but_NORMAL(uiBut *but)
-{
- float dx, dy, rad, radsq, mrad, *fp= (float *)but->poin;
- int firsttime=1;
- short mval[2], mvalo[2], mvals[2], mvaldx, mvaldy;
-
- rad= (but->x2 - but->x1);
- radsq= rad*rad;
-
- if(fp[2]>0.0f) {
- mvaldx= (rad*fp[0]);
- mvaldy= (rad*fp[1]);
- }
- else if(fp[2]> -1.0f) {
- mrad= rad/sqrt(fp[0]*fp[0] + fp[1]*fp[1]);
-
- mvaldx= 2.0f*mrad*fp[0] - (rad*fp[0]);
- mvaldy= 2.0f*mrad*fp[1] - (rad*fp[1]);
- }
- else mvaldx= mvaldy= 0;
-
- uiGetMouse(mywinget(), mvalo);
- mvals[0]= mvalo[0];
- mvals[1]= mvalo[1];
-
- while(get_mbut() & L_MOUSE) {
-
- uiGetMouse(mywinget(), mval);
-
- if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || firsttime) {
- firsttime= 0;
-
- dx= (float)(mval[0]+mvaldx-mvals[0]);
- dy= (float)(mval[1]+mvaldy-mvals[1]);
-
- 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);
-
- ui_draw_but(but);
- ui_block_flush_back(but->block);
-
- mvalo[0]= mval[0];
- mvalo[1]= mval[1];
- }
- BIF_wait_for_statechange();
- }
-
- return but->retval;
-}
-
-static int ui_do_but_CURVE(uiBut *but)
-{
- 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 a, sel= -1, retval= but->retval;
- short mval[2], mvalo[2];
-
- uiGetMouse(mywinget(), mval);
-
- /* calculate offset and zoom */
- 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(G.qual & LR_CTRLKEY) {
-
- fx= ((float)mval[0] - but->x1)/zoomx + offsx;
- fy= ((float)mval[1] - but->y1)/zoomy + offsy;
-
- curvemap_insert(cuma, fx, fy);
- curvemapping_changed(cumap, 0);
-
- ui_draw_but(but);
- ui_block_flush_back(but->block);
- }
-
-
- /* check for selecting of a point */
- cmp= cuma->curve; /* ctrl adds point, new malloc */
- for(a=0; a<cuma->totpoint; a++) {
- fx= but->x1 + zoomx*(cmp[a].x-offsx);
- fy= but->y1 + zoomy*(cmp[a].y-offsy);
- dist= (fx-mval[0])*(fx-mval[0]) + (fy-mval[1])*(fy-mval[1]);
- 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)mval[0] - but->x1)/zoomx + offsx;
- fy= ((float)mval[1] - 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);
-
- ui_draw_but(but);
- ui_block_flush_back(but->block);
-
- /* 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; a<cuma->totpoint; a++) {
- if (cmp[a].x == fx) sel = a;
- }
-
- break;
- }
- }
- }
-
- /* ok, we move a point */
- if(sel!= -1) {
- int moved_point;
- int moved_mouse= 0;
-
- /* deselect all if this one is deselect. except if we hold shift */
- if((G.qual & LR_SHIFTKEY)==0 && (cmp[sel].flag & SELECT)==0)
- for(a=0; a<cuma->totpoint; a++)
- cmp[a].flag &= ~SELECT;
- cmp[sel].flag |= SELECT;
-
- /* draw to show select updates */
- ui_draw_but(but);
- ui_block_flush_back(but->block);
-
- /* while move mouse, do move points around */
- while(get_mbut() & L_MOUSE) {
-
- uiGetMouse(mywinget(), mvalo);
-
- if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
- moved_mouse= 1; /* for selection */
- moved_point= 0; /* for ctrl grid, can't use orig coords because of sorting */
-
- fx= (mvalo[0]-mval[0])/zoomx;
- fy= (mvalo[1]-mval[1])/zoomy;
- for(a=0; a<cuma->totpoint; a++) {
- if(cmp[a].flag & SELECT) {
- float origx= cmp[a].x, origy= cmp[a].y;
- cmp[a].x+= fx;
- cmp[a].y+= fy;
- if( (get_qual() & LR_SHIFTKEY) ) {
- 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 */
-
- ui_draw_but(but);
- ui_block_flush_back(but->block);
-
- if(moved_point) {
- mval[0]= mvalo[0];
- mval[1]= mvalo[1];
- }
- }
- BIF_wait_for_statechange();
- }
-
- if(moved_mouse==0) {
- /* deselect all, select one */
- if((G.qual & LR_SHIFTKEY)==0) {
- for(a=0; a<cuma->totpoint; a++)
- cmp[a].flag &= ~SELECT;
- cmp[sel].flag |= SELECT;
- }
- }
- else
- curvemapping_changed(cumap, 1); /* remove doubles */
-
- ui_draw_but(but);
- ui_block_flush_back(but->block);
- }
- else {
- /* we move the view */
- retval= B_NOP;
-
- while(get_mbut() & L_MOUSE) {
-
- uiGetMouse(mywinget(), mvalo);
-
- if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
- fx= (mvalo[0]-mval[0])/zoomx;
- fy= (mvalo[1]-mval[1])/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;
-
- ui_draw_but(but);
- ui_block_flush_back(but->block);
-
- mval[0]= mvalo[0];
- mval[1]= mvalo[1];
- }
- }
- BIF_wait_for_statechange();
- }
-
- return retval;
-}
-
-/* ************************************************ */
-
-void uiSetButLock(int val, char *lockstr)
-{
- UIlock |= val;
- if (val) UIlockstr= lockstr;
-}
-
-void uiClearButLock()
-{
- UIlock= 0;
- UIlockstr= NULL;
-}
-
-/* *************************************************************** */
-
-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);
-}
-
-
-/* is called when LEFTMOUSE is pressed or released
- * return: butval or zero
- */
-static int ui_do_button(uiBlock *block, uiBut *but, uiEvent *uevent)
-{
- int retval= 0;
-
- if(but->lock) {
- if (but->lockstr) {
- error("%s", but->lockstr);
- return 0;
- }
- }
- else {
- if( but->pointype ) { /* there's a pointer needed */
- if(but->poin==0 ) {
- printf("DoButton pointer error: %s\n",but->str);
- return 0;
- }
- }
- }
-
- if(G.rt==1 && (uevent->qual & LR_CTRLKEY)) {
- edit_but(block, but, uevent);
- return 0;
- }
-
- block->flag |= UI_BLOCK_BUSY;
-
- switch(but->type) {
- case BUT:
- if(uevent->val) retval= ui_do_but_BUT(but);
- break;
-
- case KEYEVT:
- if(uevent->val) retval= ui_do_but_KEYEVT(but);
- break;
-
- case TOG:
- case TOGR:
- case ICONTOG:
- case ICONTOGN:
- case TOGN:
- case BUT_TOGDUAL:
- if(uevent->val) {
- retval= ui_do_but_TOG(block, but, uevent->qual);
- }
- break;
-
- case ROW:
- if(uevent->val) retval= ui_do_but_ROW(block, but);
- break;
-
- case SCROLL:
- /* DrawBut(b, 1); */
- /* do_scrollbut(b); */
- /* DrawBut(b,0); */
- break;
-
- case NUM:
- if(uevent->val) retval= ui_do_but_NUM(but);
- break;
-
- case SLI:
- case NUMSLI:
- case HSVSLI:
- if(uevent->val) retval= ui_do_but_NUMSLI(but);
- break;
-
- case ROUNDBOX:
- case LABEL:
- if(uevent->val) retval= ui_do_but_LABEL(but);
- break;
-
- case TOG3:
- if(uevent->val) retval= ui_do_but_TOG3(but);
- break;
-
- case TEX:
- if(uevent->val) retval= ui_do_but_TEX(but);
- break;
-
- case MENU:
- if(uevent->val) retval= ui_do_but_MENU(but);
- break;
-
- case ICONROW:
- if(uevent->val) retval= ui_do_but_ICONROW(but);
- break;
-
- case ICONTEXTROW:
- if(uevent->val) retval= ui_do_but_ICONTEXTROW(but);
- break;
-
- case IDPOIN:
- if(uevent->val) retval= ui_do_but_IDPOIN(but);
- break;
-
- case BLOCK:
- case PULLDOWN:
- if(uevent->val) {
- ui_do_but_BLOCK(but, uevent->event);
- retval= 0;
- if(block->auto_open==0) block->auto_open= 1;
- }
- break;
-
- case BUTM:
- retval= ui_do_but_BUTM(but);
- break;
-
- case LINK:
- case INLINK:
- retval= ui_do_but_LINK(block, but);
- break;
-
- case COL:
- if(uevent->val) retval= ui_do_but_COL(but);
- break;
-
- case HSVCUBE:
- retval= ui_do_but_HSVCUBE(but);
- break;
- case BUT_COLORBAND:
- retval= ui_do_but_COLORBAND(but);
- break;
- case BUT_NORMAL:
- retval= ui_do_but_NORMAL(but);
- break;
- case BUT_CURVE:
- retval= ui_do_but_CURVE(but);
- break;
-
-#ifdef INTERNATIONAL
- case CHARTAB:
- retval= ui_do_but_CHARTAB(but);
- break;
-#endif
- }
-
- block->flag &= ~UI_BLOCK_BUSY;
-
- return retval;
-}
-
-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);
- }
-}
-
-
-/* only to be used to prevent an 'outside' event when using nested pulldowns */
-/* only one checks:
- - while mouse moves in triangular area defined old mouse position and left/right side of new menu
- - only for 1 second
-
- return 0: check outside
-*/
-static int ui_mouse_motion_towards_block(uiBlock *block, uiEvent *uevent)
-{
- short mvalo[2], dx, dy, domx, domy;
- int counter=0;
-
- if((block->direction & UI_TOP) || (block->direction & UI_DOWN)) return 0;
- if(uevent->event!= MOUSEX && uevent->event!= MOUSEY) return 0;
-
- /* calculate dominant direction */
- domx= ( -uevent->mval[0] + (block->maxx+block->minx)/2 );
- domy= ( -uevent->mval[1] + (block->maxy+block->miny)/2 );
- /* we need some accuracy */
- if( abs(domx)<4 ) return 0;
-
- uiGetMouse(mywinget(), mvalo);
-
- while(TRUE) {
- uiGetMouse(mywinget(), uevent->mval);
-
- /* check inside, if so return */
- if( block->minx <= uevent->mval[0] && block->maxx >= uevent->mval[0] ) {
- if( block->miny <= uevent->mval[1] && block->maxy >= uevent->mval[1] ) {
- return 1;
- }
- }
-
- /* check direction */
- dx= uevent->mval[0] - mvalo[0];
- dy= uevent->mval[1] - mvalo[1];
-
- if( abs(dx)+abs(dy)>4 ) { // threshold
- /* menu to right */
- if(domx>0) {
- int fac= (uevent->mval[0] - mvalo[0])*(mvalo[1] - (short)(block->maxy +20)) + (uevent->mval[1] - mvalo[1])*(-mvalo[0] + (short)block->minx);
- if( (fac>0)) {
- // printf("Left outside 1, Fac %d\n", fac);
- return 0;
- }
-
- fac= (uevent->mval[0] - mvalo[0])*(mvalo[1] - (short)(block->miny-20)) + (uevent->mval[1] - mvalo[1])*(-mvalo[0] + (short)block->minx);
- if( (fac<0)) {
- //printf("Left outside 2, Fac %d\n", fac);
- return 0;
- }
- }
- else {
- int fac= (uevent->mval[0] - mvalo[0])*(mvalo[1] - (short)(block->maxy+20)) + (uevent->mval[1] - mvalo[1])*(-mvalo[0] + (short)block->maxx);
- if( (fac<0)) {
- // printf("Left outside 1, Fac %d\n", fac);
- return 0;
- }
-
- fac= (uevent->mval[0] - mvalo[0])*(mvalo[1] - (short)(block->miny-20)) + (uevent->mval[1] - mvalo[1])*(-mvalo[0] + (short)block->maxx);
- if( (fac>0)) {
- // printf("Left outside 2, Fac %d\n", fac);
- return 0;
- }
- }
- }
-
- /* idle for this poor code */
- PIL_sleep_ms(10);
- counter++;
- if(counter > 100) {
- //printf("left because of timer (1 sec)\n");
- return 0;
- }
- }
-
- return 0;
-}
-
-
-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
-}
-
-static void ui_but_next_edittext(uiBlock *block)
-{
- uiBut *but, *actbut;
-
- for(actbut= block->buttons.first; actbut; actbut= actbut->next) {
- /* label and roundbox can overlap real buttons (backdrops...) */
- if(actbut->type!=LABEL && actbut->type!=ROUNDBOX)
- if(actbut->flag & UI_ACTIVE) break;
- }
- if(actbut) {
- /* ensure all buttons are cleared, label/roundbox overlap */
- for(but= block->buttons.first; but; but= but->next)
- but->flag &= ~(UI_ACTIVE|UI_SELECT);
-
- for(but= actbut->next; but; but= but->next) {
- if(ELEM4(but->type, TEX, NUM, NUMSLI, HSVSLI)) {
- but->flag |= UI_ACTIVE;
- return;
- }
- }
- for(but= block->buttons.first; but!=actbut; but= but->next) {
- if(ELEM4(but->type, TEX, NUM, NUMSLI, HSVSLI)) {
- but->flag |= UI_ACTIVE;
- return;
- }
- }
- }
-}
-
-static void ui_but_prev_edittext(uiBlock *block)
-{
- uiBut *but, *actbut;
-
- for(actbut= block->buttons.first; actbut; actbut= actbut->next) {
- /* label and roundbox can overlap real buttons (backdrops...) */
- if(actbut->type!=LABEL && actbut->type!=ROUNDBOX)
- if(actbut->flag & UI_ACTIVE) break;
- }
- if(actbut) {
- /* ensure all buttons are cleared, label/roundbox overlap */
- for(but= block->buttons.first; but; but= but->next)
- but->flag &= ~(UI_ACTIVE|UI_SELECT);
-
- for(but= actbut->prev; but; but= but->prev) {
- if(ELEM4(but->type, TEX, NUM, NUMSLI, HSVSLI)) {
- but->flag |= UI_ACTIVE;
- return;
- }
- }
- for(but= block->buttons.last; but!=actbut; but= but->prev) {
- if(ELEM4(but->type, TEX, NUM, NUMSLI, HSVSLI)) {
- but->flag |= UI_ACTIVE;
- return;
- }
- }
- }
-}
-
-/* ******************************************************* */
-
-/* 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;
-}
-/* ******************************************************* */
-
-/* return:
- * UI_NOTHING pass event to other ui's
- * UI_CONT don't pass event to other ui's
- * UI_RETURN something happened, return, swallow event
- */
-static int ui_do_block(uiBlock *block, uiEvent *uevent, int movemouse_quit)
-{
- uiBut *but, *bt;
- int butevent, event, retval=UI_NOTHING, count, act=0;
- int inside= 0, active=0;
-
- if(block->win != mywinget()) return UI_NOTHING;
-
- /* filter some unwanted events */
- /* btw: we allow event==0 for first time in menus, draws the hilited item */
- if(uevent==0 || uevent->event==LEFTSHIFTKEY || uevent->event==RIGHTSHIFTKEY) return UI_NOTHING;
- if(uevent->event==UI_BUT_EVENT) return UI_NOTHING;
-
- if(block->flag & UI_BLOCK_ENTER_OK) {
- if((uevent->event==RETKEY || uevent->event==PADENTER) && uevent->val) {
- // printf("qual: %d %d %d\n", uevent->qual, get_qual(), G.qual);
- if ((G.qual & LR_SHIFTKEY) == 0) {
- return UI_RETURN_OK;
- }
- }
- }
-
- ui_set_ftf_font(block->aspect); // sets just a pointer in ftf lib... the button dont have ftf handles
- ui_set_screendump_bbox(block);
-
- // added this for panels in windows with buttons...
- // maybe speed optimize should require test
- if((block->flag & UI_BLOCK_LOOP)==0) {
- glMatrixMode(GL_PROJECTION);
- bwin_load_winmatrix(block->win, block->winmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- }
-
- Mat4CpyMat4(UIwinmat, block->winmat);
- uiPanelPush(block); // push matrix; no return without pop!
-
- uiGetMouse(mywinget(), uevent->mval); /* transformed mouseco */
-
- /* check boundbox and panel events */
- if( block->minx <= uevent->mval[0] && block->maxx >= uevent->mval[0] ) {
-
- // inside block
- if( block->miny <= uevent->mval[1] && block->maxy >= uevent->mval[1] ) inside= INSIDE_BLOCK;
-
- if(block->panel && block->panel->paneltab==NULL) {
-
- /* clicked at panel header? */
- if( block->panel->flag & PNL_CLOSEDX) {
- if(block->minx <= uevent->mval[0] && block->minx+PNL_HEADER >= uevent->mval[0])
- inside= INSIDE_PANEL_HEADER;
- }
- else if( (block->maxy <= uevent->mval[1]) && (block->maxy+PNL_HEADER >= uevent->mval[1]) ) {
- inside= INSIDE_PANEL_HEADER;
- }
- else if( block->panel->control & UI_PNL_SCALE) {
- if( (block->maxx-PNL_HEADER <= uevent->mval[0]))
- if( (block->miny+PNL_HEADER >= uevent->mval[1]) && inside )
- inside= INSIDE_PANEL_SCALE;
- }
-
- if (inside) { // this stuff should move to do_panel
-
- if(uevent->event==LEFTMOUSE) {
- if(ELEM(inside, INSIDE_PANEL_HEADER, INSIDE_PANEL_SCALE)) {
- uiPanelPop(block); // pop matrix; no return without pop!
- if(inside==INSIDE_PANEL_HEADER)
- ui_do_panel(block, uevent);
- else
- ui_scale_panel(block);
- return UI_EXIT_LOOP; // exit loops because of moving panels
- }
- }
- else if(uevent->event==ESCKEY) {
- if(block->handler) {
- rem_blockhandler(curarea, block->handler);
- addqueue(curarea->win, REDRAW, 1);
- }
- }
- else if(uevent->event==PADPLUSKEY || uevent->event==PADMINUS) {
- int zoom=0;
-
- /* if panel is closed, only zoom if mouse is over the header */
- if ((block->panel->flag & PNL_CLOSEDX) || (block->panel->flag & PNL_CLOSEDY)) {
- if (inside == INSIDE_PANEL_HEADER)
- zoom=1;
- } else if (inside >= INSIDE_BLOCK)
- zoom=1;
-
- if(zoom) {
- SpaceLink *sl= curarea->spacedata.first;
- if(curarea->spacetype!=SPACE_BUTS) {
- if(!(block->panel->control & UI_PNL_SCALE)) {
- if(uevent->event==PADPLUSKEY) sl->blockscale+= 0.1;
- else sl->blockscale-= 0.1;
- CLAMP(sl->blockscale, 0.6, 1.0);
- addqueue(block->winq, REDRAW, 1);
- retval= UI_RETURN_OK;
- }
- }
- }
-
- }
- }
- }
- }
-
- /* inside menus, scrollwheel acts as arrow */
- if(block->flag & UI_BLOCK_LOOP) {
- if(uevent->event==WHEELUPMOUSE) uevent->event= UPARROWKEY;
- if(uevent->event==WHEELDOWNMOUSE) uevent->event= DOWNARROWKEY;
- }
-
- switch(uevent->event) {
- case LEFTARROWKEY: /* closing sublevels of pulldowns */
- if(uevent->val && (block->flag & UI_BLOCK_LOOP) && block->parent) {
- return UI_RETURN_OUT;
- }
- break;
-
- case RIGHTARROWKEY: /* opening sublevels of pulldowns */
- if(uevent->val && (block->flag & UI_BLOCK_LOOP)) {
- for(but= block->buttons.first; but; but= but->next) {
- if(but->flag & UI_ACTIVE) {
- if(but->type==BLOCK) {
- but->flag &= ~UI_MOUSE_OVER;
- uevent->event= BUT_ACTIVATE;
- }
- break;
- }
- }
- if(but==NULL) { /* 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->flag |= UI_ACTIVE;
- ui_draw_but(but);
- }
- }
- }
- break;
-
- case PAD8: case PAD2:
- case UPARROWKEY:
- case DOWNARROWKEY:
- if(inside || (block->flag & UI_BLOCK_LOOP)) {
- /* arrowkeys: only handle for block_loop blocks */
- event= 0;
- if(block->flag & UI_BLOCK_LOOP) {
- event= uevent->event;
- if(event==PAD8) event= UPARROWKEY;
- if(event==PAD2) event= DOWNARROWKEY;
- }
- else {
- if(uevent->event==PAD8) event= UPARROWKEY;
- if(uevent->event==PAD2) event= DOWNARROWKEY;
- }
- if(event && uevent->val) {
-
- for(but= block->buttons.first; but; but= but->next) {
- but->flag &= ~UI_MOUSE_OVER;
-
- if(but->flag & UI_ACTIVE) {
- but->flag &= ~UI_ACTIVE;
- ui_draw_but(but);
-
- if(event==UPARROWKEY) {
- if(block->direction & UI_TOP) bt= ui_but_next(but);
- else bt= ui_but_prev(but);
- }
- else {
- if(block->direction & UI_TOP) bt= ui_but_prev(but);
- else bt= ui_but_next(but);
- }
-
- if(bt) {
- bt->flag |= UI_ACTIVE;
- ui_draw_but(bt);
- break;
- }
- }
- }
-
- /* nothing done */
- if(but==NULL) {
-
- if(event==UPARROWKEY) {
- if(block->direction & UI_TOP) but= ui_but_first(block);
- else but= ui_but_last(block);
- }
- else {
- if(block->direction & UI_TOP) but= ui_but_last(block);
- else but= ui_but_first(block);
- }
- if(but) {
- but->flag |= UI_ACTIVE;
- ui_draw_but(but);
- }
- }
- retval= UI_CONT;
- }
- }
- break;
-
- case ONEKEY: act= 1;
- case TWOKEY: if(act==0) act= 2;
- case THREEKEY: if(act==0) act= 3;
- case FOURKEY: if(act==0) act= 4;
- case FIVEKEY: if(act==0) act= 5;
- case SIXKEY: if(act==0) act= 6;
- case SEVENKEY: if(act==0) act= 7;
- case EIGHTKEY: if(act==0) act= 8;
- case NINEKEY: if(act==0) act= 9;
- case ZEROKEY: if(act==0) act= 10;
-
- if( block->flag & UI_BLOCK_NUMSELECT ) {
-
- if(get_qual() & LR_ALTKEY) 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) {
- but->flag |= UI_ACTIVE;
- if(uevent->val==1) ui_draw_but(but);
- else if(block->flag & UI_BLOCK_RET_1) { /* to make UI_BLOCK_RET_1 working */
- uevent->event= RETKEY;
- uevent->val= 1;
- //addqueue(block->winq, RIGHTARROWKEY, 1); (why! (ton))
- }
- else {
- uevent->event= LEFTMOUSE; /* to make sure the button is handled further on */
- uevent->val= 1;
- }
- }
- else if(but->flag & UI_ACTIVE) {
- but->flag &= ~UI_ACTIVE;
- ui_draw_but(but);
- }
- }
- }
- break;
- case BUT_NEXT:
- ui_but_next_edittext(block);
- break;
- case BUT_PREV:
- ui_but_prev_edittext(block);
- break;
- case BUT_ACTIVATE:
- for(but= block->buttons.first; but; but= but->next) {
- if(but->retval==uevent->val) but->flag |= UI_ACTIVE;
- }
- break;
- case VKEY:
- case CKEY:
- if(uevent->val && (uevent->qual & (LR_CTRLKEY|LR_COMMANDKEY))) {
- for(but= block->buttons.first; but; but= but->next) {
- if(but->type!=LABEL && but->type!=ROUNDBOX) {
- if(but->flag & UI_ACTIVE) {
- int doit=0;
-
- if(uevent->event==VKEY) doit= ui_but_copy_paste(but, 'v');
- else ui_but_copy_paste(but, 'c');
-
- if(doit) {
- ui_draw_but(but);
-
- if(but->retval) addqueue(block->winq, UI_BUT_EVENT, (short)but->retval);
- if((but->type==NUMSLI && but->a1) || (but->type==COL)) addqueue(block->winq, REDRAW, 1); // col button update
-
- BIF_undo_push(but->str);
- }
- // but we do return, to prevent passing event through other queues */
- if( (block->flag & UI_BLOCK_LOOP) && but->type==BLOCK);
- else if(but->retval) retval= UI_RETURN_OK;
- break;
- }
- }
- }
- }
- break;
-
-
-#ifdef INTERNATIONAL
- //HACK to let the chartab button react to the mousewheel and PGUP/PGDN keys
- case WHEELUPMOUSE:
- case PAGEUPKEY:
- for(but= block->buttons.first; but; but= but->next)
- {
- if(but->type == CHARTAB && (but->flag & UI_MOUSE_OVER))
- {
- 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(bt->type == NUM) {
- ui_check_but(bt);
- ui_draw_but(bt);
- }
- }
- retval=UI_CONT;
- break;
- }
- }
- break;
-
- case WHEELDOWNMOUSE:
- case PAGEDOWNKEY:
- for(but= block->buttons.first; but; but= but->next)
- {
- if(but->type == CHARTAB && (but->flag & UI_MOUSE_OVER))
- {
- 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(bt->type == NUM) {
- ui_check_but(bt);
- ui_draw_but(bt);
- }
- }
-
- but->flag |= UI_ACTIVE;
- retval=UI_RETURN_OK;
- break;
- }
- }
- break;
-#endif
-
- case PADENTER:
- case RETKEY: // prevent treating this as mousemove. for example when you enter at popup
- if(block->flag & UI_BLOCK_LOOP) break;
-
- default:
-
- for(but= block->buttons.first; but; but= but->next) {
-
- // active flag clear, it can have been set with number keys or arrows, prevents next loop from wrong selection on click
- if(uevent->event==LEFTMOUSE) but->flag &= ~UI_ACTIVE;
-
- but->flag &= ~UI_MOUSE_OVER;
-
- /* check boundbox */
- if (uibut_contains_pt(but, uevent->mval)) {
- but->flag |= UI_MOUSE_OVER;
- UIbuttip= but;
- }
- /* hilite case 1 */
- if(but->flag & UI_MOUSE_OVER) {
- if( (but->flag & UI_ACTIVE)==0) {
- but->flag |= UI_ACTIVE;
- if(but->type != LABEL && (but->flag & UI_NO_HILITE)==0) ui_draw_but(but);
- }
- }
- /* hilite case 2 */
- if(but->flag & UI_ACTIVE) {
- if( (but->flag & UI_MOUSE_OVER)==0) {
- /* we dont clear active flag until mouse move, for Menu buttons to remain showing active item when opened */
- if (uevent->event==MOUSEY) {
- but->flag &= ~UI_ACTIVE;
- if(but->type != LABEL && (but->flag & UI_NO_HILITE)==0) ui_draw_but(but);
- }
- }
- else if(but->type==BLOCK || but->type==MENU || but->type==PULLDOWN || but->type==ICONTEXTROW) { // automatic opens block button (pulldown)
- int time;
- if(uevent->event!=LEFTMOUSE ) {
- if(block->auto_open==2) time= 1; // test for toolbox
- else if(block->auto_open) time= 5*U.menuthreshold2;
- else if(U.uiflag & USER_MENUOPENAUTO) time= 5*U.menuthreshold1;
- else time= -1;
-
- for (; time>0; time--) {
- if (qtest()) break;
- else PIL_sleep_ms(20);
- }
-
- if(time==0) {
- uevent->val= 1; // otherwise buttons dont react
- ui_do_button(block, but, uevent);
- }
- }
- }
- if(but->flag & UI_ACTIVE) active= 1;
- }
- }
-
- /* if there are no active buttons... otherwise clear lines */
- if(active) ui_do_active_linklines(block, 0);
- else ui_do_active_linklines(block, uevent->mval);
-
- }
-
- /* middlemouse exception, not for regular blocks */
- if( (block->flag & UI_BLOCK_LOOP) && uevent->event==MIDDLEMOUSE) uevent->event= LEFTMOUSE;
-
- /* the final dobutton */
- for(but= block->buttons.first; but; but= but->next) {
- if(but->flag & UI_ACTIVE) {
-
- /* UI_BLOCK_RET_1: not return when val==0 */
-
- if(uevent->val || (block->flag & UI_BLOCK_RET_1)==0) {
- if ELEM6(uevent->event, LEFTMOUSE, PADENTER, RETKEY, BUT_ACTIVATE, BUT_NEXT, BUT_PREV) {
- /* when mouse outside, don't do button */
- if(inside || uevent->event!=LEFTMOUSE) {
-
- if ELEM(uevent->event, BUT_NEXT, BUT_PREV) {
- butevent= ui_act_as_text_but(but);
- uibut_do_func(but);
- }
- else
- butevent= ui_do_button(block, but, uevent);
-
- /* add undo pushes if... */
- if( !(block->flag & UI_BLOCK_LOOP)) {
- if(!G.obedit) {
- if ELEM5(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX);
- else {
- /* define which string to use for undo */
- if ELEM(but->type, LINK, INLINK) screen_delayed_undo_push("Add button link");
- else if ELEM(but->type, MENU, ICONTEXTROW) screen_delayed_undo_push(but->drawstr);
- else if(but->drawstr[0]) screen_delayed_undo_push(but->drawstr);
- else screen_delayed_undo_push(but->tip);
- }
- }
- }
-
- if(butevent) addqueue(block->winq, UI_BUT_EVENT, (short)butevent);
-
- /* i doubt about the next line! */
- /* if(but->func) mywinset(block->win); */
-
- if( (block->flag & UI_BLOCK_LOOP) && but->type==BLOCK);
- else
- if (butevent) retval= UI_RETURN_OK;
- }
- }
- }
- }
- }
-
- /* flush to frontbuffer */
- if((block->flag & UI_BLOCK_LOOP)==0) { // no loop, might need total flush in uidoblocks()
- ui_block_flush_back(block);
- }
-
- uiPanelPop(block); // pop matrix; no return without pop!
-
-
- /* the linkines... why not make buttons from it? Speed? Memory? */
- if(uevent->val && (uevent->event==XKEY || uevent->event==DELKEY))
- ui_delete_active_linkline(block);
-
- /* here we check return conditions for menus */
- if(block->flag & UI_BLOCK_LOOP) {
-
- if(inside==0 && uevent->val==1) {
- if ELEM3(uevent->event, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) {
- if(BLI_in_rctf(&block->parentrct, (float)uevent->mval[0], (float)uevent->mval[1]));
- else return UI_RETURN_OUT;
- }
- }
-
- if(uevent->event==ESCKEY && uevent->val==1) return UI_RETURN_CANCEL;
-
- if((uevent->event==RETKEY || uevent->event==PADENTER) && uevent->val==1) return UI_RETURN_OK;
-
- /* check outside */
- if(inside==0 && movemouse_quit) {
- uiBlock *tblock= NULL;
-
- /* check for all parent rects, enables arrowkeys to be used */
- if(uevent->event!=MOUSEX && uevent->event!=MOUSEY) {
- for(tblock=block->parent; tblock; tblock= tblock->parent) {
- if( BLI_in_rctf(&tblock->parentrct, (float)uevent->mval[0], (float)uevent->mval[1]))
- break;
- else if( BLI_in_rctf(&tblock->safety, (float)uevent->mval[0], (float)uevent->mval[1]))
- break;
- }
- }
- /* strict check, and include the parent rect */
- if(tblock);
- else if( BLI_in_rctf(&block->parentrct, (float)uevent->mval[0], (float)uevent->mval[1]));
- else if( ui_mouse_motion_towards_block(block, uevent));
- else if( BLI_in_rctf(&block->safety, (float)uevent->mval[0], (float)uevent->mval[1]));
- else return UI_RETURN_OUT;
- }
- }
-
- return retval;
-}
-
-static uiOverDraw *ui_draw_but_tip(uiBut *but)
-{
- uiOverDraw *od;
- float x1, x2, y1, y2;
- rctf tip_bbox;
-
- BIF_GetBoundingBox(but->font, but->tip, (U.transopts & USER_TR_TOOLTIPS), &tip_bbox);
-
- x1= (but->x1+but->x2)/2;
- x2= x1+but->aspect*((tip_bbox.xmax-tip_bbox.xmin) + 8);
- y2= but->y1-10;
- y1= y2-but->aspect*((tip_bbox.ymax+(tip_bbox.ymax-tip_bbox.ymin)));
-
-
- /* for pulldown menus it doesnt work */
- if(mywinget()==G.curscreen->mainwin);
- else {
- ui_graphics_to_window(mywinget(), &x1, &y1);
- ui_graphics_to_window(mywinget(), &x2, &y2);
- }
-
- if(x2 > G.curscreen->sizex) {
- x1 -= x2-G.curscreen->sizex;
- x2= G.curscreen->sizex;
- }
- if(y1 < 0) {
- y1 += 36;
- y2 += 36;
- }
-
- od= ui_begin_overdraw((int)(x1-1), (int)(y1-2), (int)(x2+4), (int)(y2+4));
-
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
-
- glColor4ub(0, 0, 0, 20);
-
- gl_round_box(GL_POLYGON, x1+3, y1-1, x2+1, y2-2, 2.0);
- gl_round_box(GL_POLYGON, x1+3, y1-2, x2+2, y2-2, 3.0);
-
- glColor4ub(0, 0, 0, 8);
-
- gl_round_box(GL_POLYGON, x1+3, y1-3, x2+3, y2-3, 4.0);
- gl_round_box(GL_POLYGON, x1+3, y1-4, x2+4, y2-3, 5.0);
-
- glDisable(GL_BLEND);
-
- glColor3ub(0xFF, 0xFF, 0xDD);
- glRectf(x1, y1, x2, y2);
-
- 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 tip_bbox, and the bottom of the background box, and the bottom of the string's tip_bbox
- */
- ui_rasterpos_safe(x1+4, ((y2-tip_bbox.ymax)+(y1+tip_bbox.ymin))/2 - tip_bbox.ymin, but->aspect);
- BIF_SetScale(1.0);
-
- BIF_DrawString(but->font, but->tip, (U.transopts & USER_TR_TOOLTIPS));
-
- ui_flush_overdraw(od); /* to show it in the frontbuffer */
- return od;
-}
-
-/* inside this function no global UIbuttip... qread is not safe */
-static void ui_do_but_tip(uiBut *buttip)
-{
- uiOverDraw *od;
- int time;
-
- if (buttip && buttip->tip && buttip->tip[0]) {
- /* Pause for a moment to see if we
- * should really display the tip
- * or if the user will keep moving
- * the pointer.
- */
- for (time= 0; time<25; time++) {
- if (anyqtest())
- return;
- else
- PIL_sleep_ms(20);
- }
-
- /* Display the tip, and keep it displayed
- * as long as the mouse remains on top
- * of the button that owns it.
- */
- Mat4CpyMat4(UIwinmat, buttip->block->winmat); // get rid of uiwinmat once...
- uiPanelPush(buttip->block); // panel matrix
- od= ui_draw_but_tip(buttip);
-
- if(od) {
- while (1) {
- char ascii;
- short val;
- unsigned short evt= extern_qread_ext(&val, &ascii);
-
- if (evt==MOUSEX || evt==MOUSEY) {
- short mouse[2];
- uiGetMouse(od->oldwin, mouse);
-
- if (!uibut_contains_pt(buttip, mouse))
- break;
- } else {
- mainqpushback(evt, val, ascii);
- break;
- }
- }
-
- ui_end_overdraw(od);
- }
-
- uiPanelPop(buttip->block); // panel matrix
- /* still the evil global.... */
- UIbuttip= NULL;
- }
-}
-
-/* returns UI_NOTHING, if nothing happened */
-int uiDoBlocks(ListBase *lb, int event, int movemouse_quit)
-{
- /* return when: firstblock != BLOCK_LOOP
- *
- * 'cont' is used to make sure you can press another button while a looping menu
- * is active. otherwise you have to press twice...
- */
-
- uiBlock *block, *first;
- uiEvent uevent;
- int retval= UI_NOTHING, cont= 1;
-
- if(lb->first==0) return UI_NOTHING;
-
- /* for every pixel both x and y events are generated, overloads the system! */
- if(event==MOUSEX) return UI_NOTHING;
-
- UIbuttip= NULL;
- UIafterfunc_butm= NULL; /* to prevent infinite loops, this shouldnt be a global! */
- UIafterfunc_but= NULL; /* to prevent infinite loops, this shouldnt be a global! */
- UIafterfunc_arg1= UIafterfunc_arg2= NULL;
-
- uevent.qual= G.qual;
- uevent.event= event;
- uevent.val= 1;
-
- /* this is a caching mechanism, to prevent too many calls to glFrontBuffer and glFlush, which slows down interface */
- block= lb->first;
- while(block) {
- ui_block_set_flush(block, NULL); // clears all flushing info
- block= block->next;
- }
-
- /* main loop, needed when you click outside a looping block (menu) then it uses that
- event to immediately evaluate the other uiBlocks again. */
- while(cont) {
-
- /* first loop, for the normal blocks */
- block= lb->first;
- while(block) {
-
- /* for pupmenus, the bgnpupdraw sets (and later restores) the active
- window. Then mousecoords get transformed OK.
- It looks double... but a call to ui_do_block otherwise doesnt get handled properly
- */
- if(block->flag & UI_BLOCK_REDRAW) {
- if( block->flag & UI_BLOCK_LOOP) {
- block->overdraw= ui_begin_overdraw((int)block->minx-1, (int)block->miny-10, (int)block->maxx+10, (int)block->maxy+1);
- }
- block->in_use= 1; // is always a menu
- uiDrawBlock(block);
- block->flag &= ~UI_BLOCK_REDRAW;
- }
-
- block->in_use= 1; // bit awkward, but now we can detect if frontbuf flush should be set
- retval |= ui_do_block(block, &uevent, movemouse_quit); /* we 'or' because 2nd loop can return to here, and we we want 'out' to return */
- block->in_use= 0;
- if(retval & UI_EXIT_LOOP) break;
-
- /* now a new block could be created for menus, this is
- inserted in the beginning of a list */
-
- /* is there a flush cached? */
- if(block->needflush) {
- ui_block_flush_overdraw(block);
- block->needflush= 0;
- }
-
- /* to make sure the matrix of the panel works for menus too */
- if(retval==UI_CONT || (retval & UI_RETURN)) break;
- first= lb->first; if(first->flag & UI_BLOCK_LOOP) break;
-
- block= block->next;
- }
-
- /* second loop, for menus (looping blocks). works for sub->menus too */
- block= lb->first;
- if(block==NULL || (block->flag & UI_BLOCK_LOOP)==0) cont= 0;
-
- while( (block= lb->first) && (block->flag & UI_BLOCK_LOOP)) {
- if(block->auto_open==0) block->auto_open= 1;
-
- /* this here, for menu buts */
- if(block->flag & UI_BLOCK_REDRAW) {
-
- if( block->flag & UI_BLOCK_LOOP) {
- block->overdraw= ui_begin_overdraw((int)block->minx-1, (int)block->miny-6, (int)block->maxx+6, (int)block->maxy+1);
- }
- uiDrawBlock(block);
- block->flag &= ~UI_BLOCK_REDRAW;
- ui_flush_overdraw(block->overdraw);
- block->needflush= 0;
- }
-
- uevent.event= extern_qread(&uevent.val);
- uevent.qual= G.qual;
-
- if(uevent.event) {
- block->in_use= 1; // bit awkward, but now we can detect if frontbuf flush should be set
- retval= ui_do_block(block, &uevent, movemouse_quit);
- block->in_use= 0;
-
- if(block->needflush) { // flush (old menu) now, maybe new menu was opened
- ui_block_flush_overdraw(block);
- block->needflush= 0;
- }
-
- if(retval & UI_RETURN) {
- ui_end_overdraw(block->overdraw);
- BLI_remlink(lb, block);
- uiFreeBlock(block);
- }
- if(retval & (UI_RETURN_OK|UI_RETURN_CANCEL)) {
- /* free other menus */
- while( (block= lb->first) && (block->flag & UI_BLOCK_LOOP)) {
- ui_end_overdraw(block->overdraw);
- BLI_remlink(lb, block);
- uiFreeBlock(block);
- }
- }
- }
-
- /* tooltip */
- if(retval==UI_NOTHING && (uevent.event==MOUSEX || uevent.event==MOUSEY)) {
- if(U.flag & USER_TOOLTIPS) ui_do_but_tip(UIbuttip);
- }
- }
-
- /* else it does the first part of this loop again, maybe another menu needs to be opened */
- if(retval==UI_CONT || (retval & UI_RETURN_OK)) cont= 0;
- }
-
- /* clears screendump boundbox, call before afterfunc! */
- ui_set_screendump_bbox(NULL);
-
- /* afterfunc is used for fileloading too, so after this call, the blocks pointers are invalid */
- if(retval & UI_RETURN_OK) {
- if(UIafterfunc_butm) {
- mywinset(curarea->win);
- UIafterfunc_butm(UIafterfunc_arg1, UIafterval);
- UIafterfunc_butm= NULL;
- }
- if(UIafterfunc_but) {
- mywinset(curarea->win);
- UIafterfunc_but(UIafterfunc_arg1, UIafterfunc_arg2);
- UIafterfunc_but= NULL;
- }
- }
-
- /* tooltip */
- if(retval==UI_NOTHING && (uevent.event==MOUSEX || uevent.event==MOUSEY)) {
- if(U.flag & USER_TOOLTIPS) ui_do_but_tip(UIbuttip);
- }
-
- return retval;
-}
-
-/* ************** DATA *************** */
-
-/* for buttons pointing to color for example */
-void ui_get_but_vectorf(uiBut *but, float *vec)
-{
- void *poin;
-
- poin= but->poin;
-
- if( but->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( but->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;
-
- poin= but->poin;
-
- if( 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);
- }
-}
-
-double ui_get_but_val(uiBut *but)
-{
- void *poin;
- double value = 0.0;
-
- if(but->poin==NULL) return 0.0;
- poin= but->poin;
-
- if(but->type== HSVSLI) {
- float h, s, v, *fp= (float *) 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 *)poin;
- }
- else if( but->pointype == SHO ) {
- value= *(short *)poin;
- }
- else if( but->pointype == INT ) {
- value= *(int *)poin;
- }
- else if( but->pointype == FLO ) {
- value= *(float *)poin;
- }
-
- return value;
-}
-
-static void ui_set_but_val(uiBut *but, double value)
-{
- void *poin;
-
- if(but->pointype==0) return;
- poin= but->poin;
-
- /* value is a hsv value: convert to rgb */
- if( but->type==HSVSLI ) {
- float h, s, v, *fp= (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 if( but->pointype==CHA )
- *((char *)poin)= (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);
- *((short *)poin)= (short) gcckludge;
- }
- else if( but->pointype==INT )
- *((int *)poin)= (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 */
- *((float *)poin)= fval;
- }
-
- /* update select flag */
- ui_is_but_sel(but);
-
-}
-
-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;
-}
-
-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;
-
- if(block->flag & UI_BLOCK_BUSY) printf("attempt to free busy buttonblock: %p\n", block);
-
- while( (but= block->buttons.first) ) {
- BLI_remlink(&block->buttons, but);
- ui_free_but(but);
- }
-
- if(block->panel) block->panel->active= 0;
-
-
- MEM_freeN(block);
- UIbuttip= NULL;
-}
-
-void uiFreeBlocks(ListBase *lb)
-{
- uiBlock *block;
-
- while( (block= lb->first) ) {
- BLI_remlink(lb, block);
- uiFreeBlock(block);
- }
-}
-
-void uiFreeBlocksWin(ListBase *lb, int win)
-{
- uiBlock *block, *blockn;
-
- block= lb->first;
- while(block) {
- blockn= block->next;
- if(block->win==win) {
- BLI_remlink(lb, block);
- uiFreeBlock(block);
- }
- block= blockn;
- }
-}
-
-uiBlock *uiNewBlock(ListBase *lb, char *name, short dt, short font, short win)
-{
- uiBlock *block;
-
- /* each listbase only has one block with this name */
- if(lb) {
- for (block= lb->first; block; block= block->next)
- if (BLI_streq(block->name, name))
- break;
- if (block) {
- BLI_remlink(lb, block);
- uiFreeBlock(block);
- }
- }
-
- block= MEM_callocN(sizeof(uiBlock), "uiBlock");
- if(lb) BLI_addhead(lb, block); /* at the beginning of the list! for dynamical menus/blocks */
-
- strcpy(block->name, name);
- /* 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();
- block->dt= dt;
- block->themecol= TH_AUTO;
-
- /* aspect */
- bwin_getsinglematrix(win, block->winmat);
-
- if (win==G.curscreen->mainwin) {
- block->aspect= 1.0;
- block->auto_open= 2;
- } else {
- int getsizex, getsizey;
-
- bwin_getsize(win, &getsizex, &getsizey);
- block->aspect= 2.0/( (getsizex)*block->winmat[0][0]);
- }
-
- uiSetCurFont(block, font);
-
- UIbuttip= NULL;
- UIlock= 0;
-
- return block;
-}
-
-uiBlock *uiGetBlock(char *name, ScrArea *sa)
-{
- uiBlock *block= sa->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= (U.transopts & USER_TR_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) value= but->min;
- if(value > but->max) value= but->max;
- ui_set_but_val(but, value);
- 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:
-
- value= ui_get_but_val(but);
-
- if( but->pointype==FLO ) {
- 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( but->pointype==FLO && but->poin) {
- 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:
- strcpy(but->drawstr, but->str);
- strcat(but->drawstr, but->poin);
- break;
-
- case KEYEVT:
- strcpy(but->drawstr, but->str);
- if (but->flag & UI_SELECT) {
- strcat(but->drawstr, "Press a key");
- } else {
- 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(but->drawstr[0]) {
- but->strwidth= but->aspect*BIF_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 ELEM(but->type, NUM, TEX) { // only these cut off left
- but->ofs++;
- but->strwidth= but->aspect*BIF_GetStringWidth(but->font, but->drawstr+but->ofs, transopts);
-
- /* textbut exception */
- if(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*BIF_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 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;
- 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= BIF_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 */
- BIF_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= UIlock;
- but->lockstr= UIlockstr;
-
- 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(but->type==NUM) { /* add a space to name */
- slen= strlen(but->str);
- if(slen>0 && slen<UI_MAX_NAME_STR-2) {
- if(but->str[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<<findBitIndex(x))==x for powers of two.
- */
-static int findBitIndex(unsigned int x) {
- if (!x || (x&(x-1))!=0) { /* x&(x-1) strips lowest bit */
- return -1;
- } else {
- int idx= 0;
-
- if (x&0xFFFF0000) idx+=16, x>>=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; a<autocpl->maxlen-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; a<autocpl->maxlen-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)
-{
- int blocktype= (long)arg_v;
- ListBase *listb= 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);
-}
-
-/* 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->miny<min)
- min= block->miny;
-
- 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;
-}
-
-
-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 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, (void *)(long)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);
-}
-
-/* ******************** 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
-short pupmenu(char *instr)
-{
- uiBlock *block;
- ListBase listb= {NULL, NULL};
- int event;
- short lastselected, width, height=0, mousexmove = 0, mouseymove, xmax, ymax, mval[2], val= -1;
- short a, startx, starty, endx, endy, boxh=TBOXH, x1, y1;
- MenuData *md;
-
- /* block stuff first, need to know the font */
- block= uiNewBlock(&listb, "menu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
- uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_NUMSELECT);
- block->themecol= TH_MENU_ITEM;
-
- md= decompose_menu_string(instr);
-
- /* size and location, title slightly bigger for bold */
- if(md->title) width= 2*strlen(md->title)+BIF_GetStringWidth(uiBlockGetCurFont(block), md->title, (U.transopts & USER_TR_BUTTONS));
- else width= 0;
- for(a=0; a<md->nitems; a++) {
- char *name= md->items[a].str;
-
- xmax= BIF_GetStringWidth(uiBlockGetCurFont(block), md->items[a].str, (U.transopts & USER_TR_BUTTONS));
- if(xmax>width) width= xmax;
-
- if( strcmp(name, "%l")==0) height+= PUP_LABELH;
- else height+= boxh;
- }
-
- width+= 10;
-
- xmax = G.curscreen->sizex;
- ymax = G.curscreen->sizey;
-
- getmouseco_sc(mval);
-
- /* set first item */
- lastselected= 0;
- if(pupmenu_set) {
- lastselected= pupmenu_set-1;
- pupmenu_set= 0;
- }
- else if(md->nitems>1) {
- lastselected= pupmenu_memory(instr, -1);
- }
-
- startx= mval[0]-(0.8*(width));
- starty= mval[1]-height+boxh/2;
- if(lastselected>=0 && lastselected<md->nitems) {
- for(a=0; a<md->nitems; a++) {
- if(a==lastselected) break;
- if( strcmp(md->items[a].str, "%l")==0) starty+= PUP_LABELH;
- else starty+=boxh;
- }
-
- //starty= mval[1]-height+boxh/2+lastselected*boxh;
- }
-
- mouseymove= 0;
-
- if(startx<10) startx= 10;
- if(starty<10) {
- mouseymove= 10-starty;
- starty= 10;
- }
-
- endx= startx+width;
- endy= starty+height;
- if(endx>xmax) {
- endx= xmax-10;
- startx= endx-width;
- }
- if(endy>ymax-20) {
- mouseymove= ymax-endy-20;
- endy= ymax-20;
- starty= endy-height;
-
- }
-
- if(mouseymove) {
- ui_warp_pointer(mval[0], mouseymove+mval[1]);
- mousexmove= mval[0];
- mouseymove= mval[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, boxh, NULL, 0.0, 0.0, 0, 0, "");
- } else {
- bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+height), width, boxh, NULL, 0.0, 0.0, 0, 0, "");
- bt->flag= UI_TEXT_LEFT;
- }
- uiSetCurFont(block, UI_HELV);
- }
-
- y1= starty + height - boxh;
- x1= startx;
-
- for(a=0; a<md->nitems; a++) {
- char *name= md->items[a].str;
-
- 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 {
- uiDefButS(block, BUTM, B_NOP, name, x1, y1, width, boxh-1, &val, (float) md->items[a].retval, 0.0, 0, 0, "");
- y1 -= boxh;
- }
- }
-
- uiBoundsBlock(block, 1);
-
- event= uiDoBlocks(&listb, 0, 1);
-
- /* calculate last selected */
- if(event & UI_RETURN_OK) {
- lastselected= 0;
- for(a=0; a<md->nitems; a++) {
- if(val==md->items[a].retval) lastselected= a;
- }
-
- pupmenu_memory(instr, lastselected);
- }
- menudata_free(md);
-
- if(mouseymove && (event & UI_RETURN_OUT)==0) ui_warp_pointer(mousexmove, mouseymove);
- return val;
-}
-
-short pupmenu_col(char *instr, int maxrow)
-{
- uiBlock *block;
- ListBase listb= {NULL, NULL};
- int columns, rows;
- short mousemove[2], mval[2], event;
- int width, height, xmax, ymax, val= -1;
- int a, startx, starty, endx, endy, boxh=TBOXH, x1, y1;
- MenuData *md;
-
- block= uiNewBlock(&listb, "menu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
- uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_NUMSELECT);
- block->themecol= TH_MENU_ITEM;
-
- md= decompose_menu_string(instr);
-
- /* collumns 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 */
- if(md->title) {
- width= 2*strlen(md->title)+BIF_GetStringWidth(uiBlockGetCurFont(block), md->title, (U.transopts & USER_TR_BUTTONS));
- width /= columns;
- }
- else width= 0;
-
- for(a=0; a<md->nitems; a++) {
- xmax= BIF_GetStringWidth(uiBlockGetCurFont(block), md->items[a].str, (U.transopts & USER_TR_BUTTONS));
- if(xmax>width) width= xmax;
- }
-
- width+= 10;
- if (width<50) width=50;
-
- boxh= TBOXH;
-
- height= rows*boxh;
- if (md->title) height+= boxh;
-
- xmax = G.curscreen->sizex;
- ymax = G.curscreen->sizey;
-
- getmouseco_sc(mval);
-
- /* find active item */
-#if 0
- fvalue= ui_get_but_val(but);
- for(a=0; a<md->nitems; a++) {
- if( md->items[a].retval== (int)fvalue ) break;
- }
-#endif
- /* no active item? */
- if(a==md->nitems) {
- if(md->title) a= -1;
- else a= 0;
- }
-
- if(a>0)
- startx = mval[0]-width/2 - ((int)(a)/rows)*width;
- else
- startx= mval[0]-width/2;
- starty = mval[1]-height + boxh/2 + ((a)%rows)*boxh;
-
- if (md->title) starty+= boxh;
-
- mousemove[0]= mousemove[1]= 0;
-
- 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;
- }
-
- ui_warp_pointer(mval[0]+mousemove[0], mval[1]+mousemove[1]);
-
- mousemove[0]= mval[0];
- mousemove[1]= mval[1];
-
- /* here we go! */
-
- if(md->title) {
- uiBut *bt;
- uiSetCurFont(block, UI_HELVB);
- bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+rows*boxh), columns*(short)width, (short)boxh, NULL, 0.0, 0.0, 0, 0, "");
- uiSetCurFont(block, UI_HELV);
- bt->flag= UI_TEXT_LEFT;
- }
-
- for(a=0; a<md->nitems; a++) {
- char *name= md->items[a].str;
-
- int icon = md->items[a].icon;
-
- x1= startx + width*((int)a/rows);
- y1= starty - boxh*(a%rows) + (rows-1)*boxh;
-
- 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) {
- uiDefIconButI(block, BUTM, B_NOP, icon, x1, y1, width+16, boxh-1, &val, (float) md->items[a].retval, 0.0, 0, 0, "");
- y1 -= boxh;
- }
- else {
- uiDefButI(block, BUTM, B_NOP, name, x1, y1, width, boxh-1, &val, (float) md->items[a].retval, 0.0, 0, 0, "");
- y1 -= boxh;
- }
- //uiDefButI(block, BUTM, B_NOP, md->items[a].str, x1, y1, (short)(width-(rows>1)), (short)(boxh-1), &val, (float)md->items[a].retval, 0.0, 0, 0, "");
- }
-
- uiBoundsBlock(block, 1);
-
- event= uiDoBlocks(&listb, 0, 1);
-
- menudata_free(md);
-
- if((event & UI_RETURN_OUT)==0) ui_warp_pointer(mousemove[0], mousemove[1]);
-
- return val;
-}
-