Maxscript 使用依赖注入的模式来设计材质转换工具概要

需求

在常规的转换工具编写中,我们需要编写材质的转换代码,编写后需要进行注册到类型判断中
比如,把标准材质转换到vray材质,我们可能会这样写

fn convertStandardToVrayMtl oldMat =
(
      newMat = VrayMtl()
      return newMat
)
--使用时进行类型判断,这里我管他叫注册
if classof xx == Standard do 
      obj.mat = convertStandardToVrayMtl xx

如果添加了新的转换函数,我们又需要加入到类型的注册中,很多设计模式也是这样,编写函数 --> 注册类型 --> 使用函数
但由于材质类型众多,代码量会变得很长,多一步注册或者忘记注册是烦人的事情
于是乎,在其他语言中常见的控制反转模式,拿到这里来应该非常好用,而且转换函数的模式非常固定,传入旧实例,返回新实例,非常适合做模板式的代码编写

容器处理

mxs的结构类型中,可以使用 getPropNames 来获得一个结构体的成员名字,以此来实现其他语言的"反射"特性

struct foo
(
	age,
	showMyAge = fn _ myName = (print (myName + " - " + this.age as string)),
	fn eat =
	(
		print 1
	)
)
newFoo = foo()

--获取所有方法以及属性名字
getPropNames newFoo --返回 #(#age, #test, #showMyAge)

--通过名字找到方法
eatFn = getProperty newFoo #eat
--调用方法
eatFn()

--重写方法,因为showMyAge作为一个<data>,而非一个函数,所以他的内容可以被赋予任何内容
--如果你需要调用实例内的成员,这里的this作为一个很丑陋的形参
newFoo.showMyAge = (fn _ myName this = (
	this.age = 50
	print (myName + " -- " + this.age as string)
))
--调用方法
newFoo.showMyAge "tom" newFoo 

--还有一个需求,mxs里面没有继承,我们无法为原有结构添加新的处理函数,比如新版更新了有了新的材质类型
--可以定义一个扩展数组成员,为未来新添加的处理函数预留位置

转换函数

有了上面的容器处理方法,就可以编写转换函数了,为了便于容器处理时使用 getPropNames 的方式找到处理的函数,这里对函数的名字进行强制规定
使用ConvertFromMat前缀开头,下划线分割,结尾接具体的材质类型,参数为旧材质,返回类型为新材质
在处理容器中直接分割函数名字可以非常轻松的拿到:需要转换的材质类型,从而实现自动化处理,无需手动注册,我们仅仅需要专注转换函数的编写,其他由框架自动处理
比如:

--将标准材质转为Vray材质
fn ConvertFromMat_Standardmaterial oldMat = 
(
      ...
      return newMat
)
--为了方便整体的替换,所有输入得参数变量名全部改为old ,输出变量名为r

其他

为了兼容汉化属性

我还专门搞了个工具来进行痛苦的替换,越陷越坑发现这个是大工程

原文地址:https://www.cnblogs.com/trykle/p/13734644.html