一个头皮发麻的 eel 按钮模拟

最近尝试用 eel 写 reaper 脚本,模拟一个button组件,基本可以实现:

  • 按钮边框,可控的 颜色 和 框线大小 (bd_size) ,
    通过 gfx_rect() 绘制两层大小不一的矩形实现
  • 文字自动居中,按钮自动调整大小,可控的内边距、文字颜色,
    通过 gfx_measurestr() 获取字符串宽度,计算调整文本位置,和按钮矩形宽高。
  • 鼠标位置判断,是否处于 button 范围内,以及鼠标是否按下,
    通过全局变量 mouse_cap 获取鼠标位 置,在主循环记录一次到 mouse_state 变量,
    在 button 函数判断鼠标位置、鼠标按下的键位。
  • button 本身的鼠标状态需要记录和判断,暂时还没有实现,所以鼠标一直按住,
    会一直重复运行判断内的代码,比如会反复执行 onclick 事件(假设有)。

不过 eel 的语言特性,感觉写一个UI框架是比较复杂的,加上 gfx 这种绘制方式比较底层,
之后估计会用其他UI方案,纯当经验分享了,下面是截图和代码。

GIF 2023-02-21 22-37-12

// 同时设置绘制起始点、颜色
function set_pos_and_color(x,y,r,g,b)
(
  gfx_x = x; gfx_y = y;
  gfx_r = r; gfx_g = g; gfx_b = b;
);

// 封装矩形绘制方法,模仿按钮
function draw_rect(x,y,text,w,h,bd_r,bd_g,bd_b,bd_size,bg_r,bg_g,bg_b,lbl_x,lbl_y,lbl_r,lbl_g,lbl_b,)
(
  // 绘制底层 border
  set_pos_and_color(x,y,bd_r,bd_g,bd_b);
  gfx_rect(x,y,w,h);
  // 绘制内层
  set_pos_and_color(x+bd_size,y+bd_size,bg_r,bg_g,bg_b);
  gfx_rect(x+bd_size,y+bd_size,w-bd_size*2,h-bd_size*2);
  // 绘制文本
  set_pos_and_color(lbl_x,lbl_y,lbl_r,lbl_g,lbl_b);
  gfx_drawstr(text);
);

// 按钮
function button(x,y,text)
(
  this.x = x;
  this.y = y;
  this.text = text;
  this.w = 0;
  this.h = 0;

  // 判断字符长度,自适应修改 w, h
  gfx_measurestr(text,this.text_w,this.text_h);
  this.text_w > this.w ? this.w = this.text_w + 40;
  this.text_h > this.h ? this.h = this.text_h + 20;

  // 计算文本位置,放到矩形中心
  this.text_x = (this.x + this.w * 0.5) - (this.text_w * 0.5);
  this.text_y = (this.y + this.h * 0.5)-(gfx_texth * 0.5);

  this.x1 = this.x + this.w;
  this.y1 = this.y + this.h;
  this.bd_r = 0;
  this.bd_g = 0.5;
  this.bd_b = 0.5;
  this.bd_size = 3;
  this.bg_r = 0.9;
  this.bg_g = 0.9;
  this.bg_b = 0.9;
  this.text_r = 0;
  this.text_g = 0;
  this.text_b = 0;

  
  this.mouse_state = 0;
  

  draw_rect(
    this.x,
    this.y,
    this.text,
    this.w,
    this.h,
    this.bd_r,
    this.bd_g,
    this.bd_b,
    this.bd_size,
    this.bg_r,
    this.bg_g,
    this.bg_b,
    this.text_x,
    this.text_y,
    this.text_r,
    this.text_g,
    this.text_b
  );


  // 鼠标事件判断
  (mouse_x > this.x && mouse_x < this.x1 && mouse_y > this.y && mouse_y < this.y1) ? (
    // 改变内层颜色
    this.bg_r = 0.8;
    this.bg_g = 0.7;
    this.bg_b = 0.9;
    draw_rect(
      this.x,
      this.y,
      this.text,
      this.w,
      this.h,
      this.bd_r,
      this.bd_g,
      this.bd_b,
      this.bd_size,
      this.bg_r,
      this.bg_g,
      this.bg_b,
      this.text_x,
      this.text_y,
      this.text_r,
      this.text_g,
      this.text_b
    );

    // 判断是否点击
    mouse_cap == 1 && mouse_cap != this.mouse_state ? (
      this.mouse_state = mouse_cap;
      this.bg_r = 0.5;
      this.bg_g = 0.5;
      this.bg_b = 0.9;
      draw_rect(
        this.x,
        this.y,
        this.text,
        this.w,
        this.h,
        this.bd_r,
        this.bd_g,
        this.bd_b,
        this.bd_size,
        this.bg_r,
        this.bg_g,
        this.bg_b,
        this.text_x,
        this.text_y,
        this.text_r,
        this.text_g,
        this.text_b
      );
    );
  );


);

function draw_status()
(
  this.x = 10;
  this.y = gfx_h - gfx_texth -10;

  set_pos_and_color(this.x, this.y, 1, 1, 1);
  gfx_printf("pos: (%d, %d), mouse_cap: %d", mouse_x, mouse_y, mouse_cap);
);


// 绘制函数
function draw()
(
  button(100,100,"A");
  button(100,150,"AA");
  button(100,200,"AAA");
  button(100,250,"abcdefghijk");
  button(100,300,"哈");
  button(100,350,"哈哈");
  button(100,400,"哈哈哈");

  draw_status();
);

// 主函数loop
function main()
(
  set_pos_and_color(0,0,1,1,1); 

  mouse_cap == 0 ? mouse_state = 0 : mouse_state = 1;

  // 绘制图形
  draw();

  // 更新画面,循环绘制
  gfx_update();
  gfx_getchar() >= 0 ? defer("main();");
);

// 初始化窗口
function init()
(
  font_name = "Arial";
  font_size = 20;
  
  gfx_setfont(1, font_name, font_size);
  gfx_init("EEL Test",400,600,0,300,300);
);

init();
main();

只能说硬核,真硬核!本来eel写脚本已经困难,用他手撸gui相当于拿指甲刀修火箭了。其实除了与音频采样相关的脚本他能加快速度以外,别的方面eel真的是性价比很低的选择。最近写完一个的我表示真的怕了

确实麻烦,目前reaimgui特别好用,可惜还不支持中文。

嗯,要用也就是临时绘制几个,然后位置和方法写死那种。适合做轻量化的、和音频相关计算类脚本,就像noiz说的。

eel 还是继续,但是不想碰 UI了,哈哈哈


我觉得eel Gui的天花板应该是Tukan大神了吧,他做出来的Gui跟常规的插件也没啥区别了,当然他是用了图片控件,而且每个Gui上都非得加上那个可笑的Logo,嘻嘻 :stuck_out_tongue_winking_eye:

笑死
我非常讨厌这个logo

哈哈,这个UI有味道了