使用C#对Godot属性进行改写(其实是覆盖)
背景
我还真没想到C#这个鬼东西还能这么用……
起初是想通过某种办法改写一下Label的text属性的赋值机制来改写一个自己的Label运作方式,之前想尽办法用GDScript改写set_text(实际情况是GDScript下根本不提供这个函数)和_set(这玩意改完了不对赋值操作起作用,感觉更像是给反射用的)然而并没有什么卵用……虽然说直接调用那些函数的方式还是可以使用的,但是写法上我还是喜欢用直接赋值的来得简洁。
但总之我希望修改对于text属性赋值时的运作方式,我甚至去想写NativeScript直接把Label重写一下,不过NativeScript在官方文档里的一顿操作猛如虎我愣是没看懂,Native这块我先放着,哪天用得上哪天再研究。(但我估计重写还是能办到的)
好在我下的Godot版本是mono版(虽然官方到了3.3rc6的文档里都说C#绑定得不太完善,不过考虑到随时有可能出现需要C#的情形以及mono版也不耽误写GDScript的情况下我就下的mono版,Steam上没有mono版也就罢了),所以我又重新考虑C#是否可以解决这个问题。
改造方法
就以改写Label.text的运作方式为例……
Godot源码是C++的,GDScript里面怎么做的封装我不太清楚,但总之只剩下了text属性变量,因为GDScript并不允许对属性重定义,所以不能用setget来指定setter和getter函数(因为文档规定setget只能在var声明句中使用,但GDScript的语法又不让重声明,至少不能再次声明同名的属性)。
不过在C++的源码中,Godot实际上是有set_text和get_text的,而且这两个函数被表述为public,所以就很迷……
// setter
void Label::set_text(const String &p_string) {
if (text == p_string) {
return;
}
text = p_string;
xl_text = tr(p_string);
dirty = true;
if (percent_visible < 1) {
visible_chars = get_total_character_count() * percent_visible;
}
update();
}
// getter
String Label::get_text() const {
return text;
}
至于为什么在GDScript里没了,可能是跟某种绑定机制有关,不过这个改天再看看。
不过用C#脚本的话,情况就不一样了,因为在C#里对应的Label.Text就是C#概念下的Property,而且由于C++源码里是public(事实上也必须是,因为这东西可改),所以Label里的绑定多半写的也肯定是:
public class Label : Control
{
//...
public string Text { get{/*...*/} set{/*...*/} }
//...
}
本来我想用override把原来版本的Text属性直接推翻重写,不过因为Label.Text并非virtual所以我不能推翻,只能强制隐藏……
public class MyLabel : Label
{
public new String Text
{
get {/*...*/}
set {/*...*/}
}
//...
}
不过另外一个问题来了,getter和setter怎么重写的问题……
本来傻fufu的想直接对新的Text做手脚结果运行的时候Godot调试器直接卡崩溃了……
报错告诉我内存空间爆了,那估计是被当成无尽递归闹得,于是我就改成了给父类捆绑的方式……
public class MyLabel : Label
{
public new String Text
{
get => base.Text;
set
{
// ...
base.Text = value;
// ...
}
}
//...
}
成功了,当我操作Text的时候,我可以在此基础上改写这些性质。
当然了,这种做法有局限:
- 涉及底层API的操作很难复现,所以除非保留对base属性的赋值句
base.XXX=value;,因为base属性也是相当于一个名字带两个函数,直接执行这个语句会连同原有的操作也做一遍,但是有些底层属性对继承类是private的,继承类看不到。 - 如果彻底不想使用原有的运作机制的话,那可能还需要引入字段来解决这个问题。(但是实际上这跟独立重开一个属性没差,只是不用换名字了而已)
- 结合上述两点,这种方法可能无法保留局部的原有机制,也就是说要么全用要么全不用,你只能在原有的基础上叠加,如果真的想达到真正意义上的重写可能还得下到底层去……
使用C#对Godot属性进行改写(其实是覆盖)的更多相关文章
- java-成员变量的属性与成员函数的覆盖
java中在多态的实现是通过类的继承或者接口的实现来完成的. 在类继承或者接口实现过程中就会涉及到成员属性以及成员函数的重写,需要注意的是,成员函数的重写是直接覆盖父类的(继承中),但是成员变量重写是 ...
- 将CSS CLIP属性应用在:扩展覆盖效果
我们想要展示如何利用CSS3 clip属性制作一种简单而整洁的扩展效果,当点击一个box元素时实现平稳过渡.这个想法是为了实现某种叠加效果,好像它实际上在各个元素的下面.点击其中一个元素将创建一个切断 ...
- android:scrollbarStyle属性及滚动条和分割线覆盖问题
android:scrollbarStyle可以定义滚动条的样式和位置,可选值有insideOverlay.insideInset.outsideOverlay.outsideInset四种. 其中i ...
- ECMAScript 5中的数据属性和访问器属性
简介 ECMAScript 定义的对象中有两种特殊的属性, 这两种特殊的属性在你定义对象属性时就会赋予, 我们在必要时可以改写这两种特殊的属性让其属性的访问更加的合理化, 这两种特殊的属性称呼及作用如 ...
- WPF快速入门系列(2)——深入解析依赖属性
一.引言 感觉最近都颓废了,好久没有学习写博文了,出于负罪感,今天强烈逼迫自己开始更新WPF系列.尽管最近看到一篇WPF技术是否老矣的文章,但是还是不能阻止我系统学习WPF.今天继续分享WPF中一个最 ...
- Object-C属性(Properties)
前面我们写了caption和photographer的访问方法,你可能也注意到了,那些代码很简单,应该可以写成具有更普遍意义的形式. 属性是Object-C的一个特性,它允许我们自动生成访问器,同时还 ...
- Vue.js 学习笔记 第3章 计算属性
本篇目录: 3.1 什么是计算属性 3.2 计算属性用法 3.3 计算属性缓存 模板内容的表达式常用语简单的运算,当其过长或逻辑复杂时,会难以维护,本章的计算属性就是用于解决该问题的. 3.1 什么是 ...
- Vue(二) 计算属性
模板内的表达式常用于简单的运算,当过长或逻辑复杂时,难以维护,计算属性就是解决该问题的 什么是计算属性 表达式如果过长,或逻辑更为复杂,就会变得臃肿甚至难以维护,比如: <div> {{ ...
- 奇怪的组数length属性
Java中的数组其实也是一个对象,但是确实是一个特殊的对象,实在是太特殊了,继承自Object, 多出一个属性length,改写了clone方法. 我debug了数组对象的运行时的Class对象, ...
- Vue 2.0学习(四)计算属性
{{}}模板内的表达式常用于简单的运算,当运算过长或逻辑复杂时,会难以维护. <div> {{ text.split(',').reverse().join('') }} </div ...
随机推荐
- 试了下Cursor,感觉程序员工种危险了
大家好,我是汤师爷~ 今年8月份,AI 编程工具 Cursor 在开发者社区彻底火了.在 Twitter 平台上,Cloudflare 副总裁分享了一段视频,展示了一个令人震惊的案例.他年仅 8 岁的 ...
- QPixmap 线程 奔溃
使用QImage替代QPixmap. ·QImage与Qpixmap的区别 1.QPixmap主要是用于绘图,针对屏幕显示而最佳化设计,QImage主要是为图像I/O.图片访问和像素修改而设计的 2. ...
- 协议Fuzz技术
文章一开始发表在微信公众号 https://mp.weixin.qq.com/s?__biz=MzUyNzc4Mzk3MQ==&mid=2247486230&idx=1&sn= ...
- 为什么SQL正在击败NoSQL,这对未来的数据意味着什么(转载)
为什么SQL正在击败NoSQL,这对未来的数据意味着什么 : http://geek.csdn.net/news/detail/238939 译者注:经过多年的沉寂之后,今天的SQL正在复出.缘由如何 ...
- Qt音视频开发24-视频显示QOpenGLWidget方式(占用GPU)
一.前言 采用painter的方式绘制解码后的图片,方式简单易懂,巨大缺点就是占CPU,一个两个通道还好,基本上CPU很低,但是到了16个64个通道的时候,会发现CPU也是很吃紧(当然强劲的电脑配置另 ...
- Qt音视频开发38-USB摄像头解码linux方案
一.前言 做嵌入式linux上的开发很多年了,扳手指头算算,也起码9年了,陆陆续续做过很过诸如需要读取外接的USB摄像头或者CMOS摄像机的程序,实时采集视频,将图像传到前端,或者对图像进行人脸分析处 ...
- Eclipse IDE最常用的快捷键
0.运行:Ctrl+F111.启动调试:F112.终止调试:Ctrl+F23.插入断点:Ctrl+Shift+B或双击行前4.单步跳入:F55.单步跳过:F66.跳出方法:F77.直接跳转到下一个断点 ...
- asp.net core中,使用CancellationToken在用户终止请求时取消所有异步操作+ abp中的设计
如果一个Controller.Action里的处理非常耗时,比如读数据库.文件操作.调用第三方接口等此时用户随时可能关闭浏览器.F5刷新网页等操作.但是服务端的耗时代码任然在执行,这太浪费了,既然用户 ...
- 第一章 Java集合框架
----------------------------------------------------------------------------- Java集合框架(一)-ArrayList ...
- SpringBoot实现人脸识别功能
一.人脸注册 step1:人像采集.在注册页面上用html中video组件和js调用笔记本摄像头,并抓取人像图片.没有摄像头的笔记本.台式机的童鞋告辞吧,走好不送... step2:人像上传至项目文件 ...