BlenderDev/hotkey

Wikipedia,自由的百科全书

是否开启国际化支持是由一个名叫International Fonts的按钮实现的。 所以我们只要现在源代码中确定这个按钮的位置。 搜索"International Fonts", 发现它在space.c中。

space.c uiDefButBitS(block, TOG, USER_DOTRANSLATE, B_DOLANGUIFONT, "International Fonts",

  xpos,y2,mpref,buth,
  &(U.transopts), 0, 0, 0, 0, "Activate international interface");

可能你需要去了解一下uiDefButBitS的实现(interface.c中), 了解它对你洞悉Blender的UI机制有很大帮助, 之后可能深入到SDNA。这些是你的事情了, 我说我的。

如果你查找USER_DOTRANSLATE的定义会发现在DNA_userdef_types.h中有:

  1. define USER_DOTRANSLATE 32

为什么uiDefButBitS这一行又给出了&(U.transopts), 一个地址? 其实, uiDefButBitS绕来绕去, 就是想将按钮和U.transopts的某一位(二进制)联系在一起, 而这位是0还是1控制了是否开启国际化支持。 U.transopts控制了国际化支持的参数, 你应该看出来了, transopts是tranlation options的缩写。 我们只要改变相应位值就可以开启或关闭国际化支持。

究竟是哪位呢, 你可以看程序马上猜到是第5位, 00100000中是1的那一位。为了检验这个假设我帮你写了一段程序:

  1. define USER_DOTRANSLATE 32

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;
  }

}

void main() {

  printf("%x", findBitIndex(USER_TR_TOOLTIPS));

}

想办法定义一个快捷键, 灵感从何而来?答案:Quit Blender。我们知道, Ctrl+Q可以退出Blender。代码在哪里呢?搜索"Quit Blender"后发现它藏在editscreen.c中。 控制它就可以实现添加一个快捷键, 我们暂时定成Ctrl+I。

在 else if (event==QKEY) {

  if((G.obedit && G.obedit->type==OB_FONT && g_activearea->spacetype==SPACE_VIEW3D)||g_activearea->spacetype==SPACE_TEXT||g_activearea->spacetype==SPACE_SCRIPT);
  else {
     if(val && (G.qual & LR_CTRLKEY)) {
        if(okee("Quit Blender")) exit_usiblender();
     }
     towin= 0;
  }

} 后面加上

  1. ifdef INTERNATIONAL

else if (event==IKEY && (val && (G.qual & LR_CTRLKEY))) {

  U.transopts^=1<<findBitIndex(USER_DOTRANSLATE);
  if(U.transopts & USER_DOTRANSLATE)
     start_interface_font();
  else
     G.ui_international = FALSE;
  allqueue(REDRAWALL, 0);

}

  1. endif

解释一下, 1. IKEY就是I, event==IKEY检查是否按住了I。 LR_CTRLKEY自然就是左Ctrl, val && (G.qual & LR_CTRLKEY)检查是否按住了左Ctrl。 2. U.transopts^=1<<findBitIndex(USER_DOTRANSLATE);这句就是让U.transopts第5位求反。^是异或操作符, 嗯, 老师教过你异或也是可以求反的吧。如果他(or她)没教过, 好好诅咒他(or她)吧。 3. 由于你调用了findBitIndex, 它在interface.c中定义 static int findBitIndex(unsigned int x){...} 所以你要去改成int findBitIndex(unsigned int x){...} 也许你还要extern声明一下(在editscreen.c中, 包括对start_interface_fontd的声明), 不过不声明也不会得到什么错误, 只会warning一下。觉得很可怜。所以, 为了你良好的习惯, just do it。 extern int findBitIndex(unsigned int x); extern void start_interface_font(void); 4. 至于

  if(U.transopts & USER_DOTRANSLATE)
     start_interface_font();
  else
     G.ui_international = FALSE;
  allqueue(REDRAWALL, 0);

你去查找B_DOLANGUIFONT便可知道, 这段代码其实就是你按下International Fonts按钮后要执行的。所以, 直接copy来用。

总结一下, 整个过程一是你要改U.transopts, 顺便改G.ui_international,刷新屏幕(REDRAWALL);二是你要定义个快捷键完成这些操作。 最后, 希望我说的你都了解了。


附: 了解uiDefButBitS的实现过程需要查看interface.c中的下面代码: 这些代码环环相扣, 其实就是实现了C++中的思想, 或者我们也可以把它们看成高级API和低级API。

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);

}

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);
  }

}

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;
  }

}

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;

}

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;

}

Personal tools