2021SC@SDUSC
目录
3.after(name, action, context opt)
4.before(name, action, context opt)
7.getNodeByName(name) → {clay.compositor.CompositorNode}
8.has(name, action) → {boolean}
10.on(name, action, context opt)
11.once(name, action, context opt)
13.success(action, context opt)
clay.compositor. Graph类可以构造一个图,并为图添加节点
clay.compositor. Graph类有构造一个图,为图添加节点,设置触发事件,移除触发事件获取节点,移除节点,更新链接等功能
该函数是Graph的构造函数,继承自clay.core.Base,能够构造一个Graph对象。
无参数。
其源代码为:
var Graph = Base.extend(function () {
return /** @lends clay.compositor.Graph# */ {
/**
* @type {Array.<clay.compositor.CompositorNode>}
*/
nodes: []
};
}
从源代码中可以看出,Graph类有1个成员变量nodes,类型为数组Array<clay.compositor.CompositorNode>,表示图的节点;同时,Graph继承了Base的number成员变量。
该函数的作用是为图添加一个节点。
参数为node,类型为clay.compositor.CompositorNode,表示为图添加的节点。
其源代码为:
addNode: function (node) {
if (this.nodes.indexOf(node) >= 0) {
return;
}
this.nodes.push(node);
this._dirty = true;
}
从源代码中可以看出,该函数首先判断本对象的nodes数组中是否存在形式参数node,如果存在则返回,如果不存在则加入node对象,并设置本对象的_dirty为true,表示已经修改过。
该函数的作用是设置事件触发后的动作,继承自Base。
参数为name,类型为string,表示事件触发后的动作的名称,action,类型为function,表示事件触发后的动作的函数,context,类型为object,表示事件触发后的动作的内容。
其源代码为:
after: function(name, action, context) {
if (!name || !action) {
return;
}
name = 'after' + name;
return this.on(name, action, context);
}
从源代码中可以看出,该函数首先判断name和action是否存在,若其中一个不存在,则直接返回,若存在,则在name前加入字符串‘after’,并调用本对象的on(name, action, context)方法,从而实现事件触发后的动作
该函数的作用是设置事件触发前的动作,继承自Base。
参数为name,类型为string,表示事件触发前的动作的名称,action,类型为function,表示事件触发前的动作的函数,context,类型为object,表示事件触发前的动作的内容。
其源代码为:
before: function(name, action, context) {
if (!name || !action) {
return;
}
name = 'before' + name;
return this.on(name, action, context);
}
从源代码中可以看出,该函数首先判断name和action是否存在,若其中一个不存在,则直接返回,若存在,则在name前加入字符串‘before’,并调用本对象的on(name, action, context)方法,从而实现事件触发前的动作。
该函数的作用是标记Graph对象已经被修改过。
无参数。
其源代码为:
dirty: function () {
this._dirty = true;
}
该函数将本对象的成员变量_dirty设置为true,标记Graph对象已经修改过。
该函数的作用是设置事件发生错误触发的动作,继承自Base。
action,类型为function,表示事件发生错误触发的函数,context,类型为object,表示事件发生错误触发的内容。
其源代码如下:
error: function(action, context) {
return this.once('error', action, context);
}
从源代码中可以看出,该函数直接调用本对象的once方法,name为‘error’,另外两个参数为方法的形参,从而实现错误的处理。
该函数的作用是通过name名称获取Node节点。
无参数。
其源代码为:
getNodeByName: function (name) {
for (var i = 0; i < this.nodes.length; i++) {
if (this.nodes[i].name === name) {
return this.nodes[i];
}
}
}
从源代码中可以看出,该函数对本对象的nodes数组进行遍历,寻找数组中名称为name的对象,并返回该对象,从而实现通过名称找到相应的节点。
该函数的作用是判断是否注册事件驱动程序,继承自Base。
参数为name,类型为string,表示事件的名称,action,类型为function,表示事件执行的方法。
其源代码如下:
has: function(name, action) {
var handlers = this.__handlers__;
if (! handlers ||
! handlers[name]) {
return false;
}
var hdls = handlers[name];
for (var i = 0; i < hdls.length; i++) {
if (hdls[i].action === action) {
return true;
}
}
}
从源代码可以看出,首先将本对象的__handlers__成员变量赋值给新建的对象handlers,判断handlers是否存在和handlers中是否存在name的对象,若其中一个条件不满足,则返回false。接着,将handlers中名为name的对象赋给新变量hdls,对hdls进行遍历,若hdls中某一对象的action与形参的action相同,则返回true,从而判断name对象是否有action方法,进而判断是否注册事件驱动程序。
该函数的作用是移除事件监听器,继承自Base。
参数有action,类型为function,表示所移除事件监听器的动作方法,context,类型为object,表示所移除事件监听器的内容。
其源代码如下:
off: function(name, action) {
var handlers = this.__handlers__ || (this.__handlers__={});
if (!action) {
handlers[name] = [];
return;
}
if (handlers[name]) {
var hdls = handlers[name];
var retains = [];
for (var i = 0; i < hdls.length; i++) {
if (action && hdls[i].action !== action) {
retains.push(hdls[i]);
}
}
handlers[name] = retains;
}
return this;
}
从源代码中可以看出,off方法接收了name和action这两个形式参数,name表示事件监听器的name,action表示事件监听器的action。首先,若本对象的__handlers__成员变量若不为空,则将其赋值给新创建的局部变量handlers,否则将handlers设置为空字典。
判断action形参,若action为空,则设置handlers中键为name的值为空数组,并返回。判断handlers,若其键为name的值不为空,即action不为空,则创建局部变量hdls,并将handlers[name]赋值给它。继续创建名为retains的空数组。对hdls进行遍历,若action不为空并且hdls中不存在与action一致的action值,则将hdls中符合该特性的action放入retains数组中,并将retains数组重新赋给handlers中键为name的值,通过这一方法,即可删除本对象中的action方法,从而移除事件监听器。最后返回本对象即可。
该函数能够注册事件处理程序,继承自Base。
参数有name,类型为string,表示事件处理程序的名称,action,类型为function,表示事件处理程序的动作方法,context,类型为object,表示事件处理程序的内容。
其源代码如下:
on: function(name, action, context) {
if (!name || !action) {
return;
}
var handlers = this.__handlers__ || (this.__handlers__={});
if (!handlers[name]) {
handlers[name] = [];
}
else {
if (this.has(name, action)) {
return;
}
}
var handler = new Handler(action, context || this);
handlers[name].push(handler);
return this;
}
从源代码中可以看出,接收的形参有三个,分别为name,action,context,分别表示事件处理程序的名称,动作方法,内容。首先,该函数判断时间处理程序的名称和动作方法是否为空,若其中一个为空,则返回。
接着,若本对象的__handlers__成员变量若不为空,则将其赋值给新创建的局部变量handlers,否则将handlers设置为空字典。
然后,判断handlers键为name的值是否为空,如果为空则将其初始化为空数组,否则,调用has函数,判断相应name和action的事件处理程序是否已经存在,若存在则返回。
最后,采用形参action和context创建一个Handler对象,并赋值给新建的handler局部变量,若context为空,则将本对象作为context。将handler加入到handlers中键为name的数组中即可,从而完成时间处理程序的注册。最后返回本对象。
该函数的作用是注册一个事件,该事件仅执行一次便移除,继承自Base。
参数有name,类型为string,表示事件的名称,action,类型为function,表示事件的动作方法,context,类型为object,表示事件的内容。
其源代码如下:
once: function(name, action, context) {
if (!name || !action) {
return;
}
var self = this;
function wrapper() {
self.off(name, wrapper);
action.apply(this, arguments);
}
return this.on(name, wrapper, context);
}
从源代码中可以看出,接收的形参有三个,分别为name,action,context,分别表示事件处理程序的名称,动作方法,内容。首先,该函数判断时间处理程序的名称和动作方法是否为空,若其中一个为空,则返回。
接着,创建一个局部变量self,并将本对象赋值给self。执行一个函数wrapper,对self变量调用off方法,移除wrapper事件监听器,接着,通过接收的参数,调用action的apply方法,执行action,从而实现执行该action方法,但执行后即移除该事件,从而实现仅执行一次该方法的作用。最后返回本对象的on函数的返回值,参数为name,wrapper和context。
该函数的作用是移除Graph中指定的Node节点。
参数为node,类型为clay.compositor.CompositorNode或string,表示要移除的节点或节点的名称。
其源代码为:
removeNode: function (node) {
if (typeof node === 'string') {
node = this.getNodeByName(node);
}
var idx = this.nodes.indexOf(node);
if (idx >= 0) {
this.nodes.splice(idx, 1);
this._dirty = true;
}
}
从源代码中可以看出,首先判断node的类型,如果类型为string,则调用getNodeByName方法,获取nodes数组中指定的node,如果为Node类型,则直接获取该Node。接着,调用nodes数组的indexof方法,获取node的索引,如果索引存在,则根据索引去除该节点,并设置_dirty为true,表示已修改。
该函数的作用是注册success事件处理程序,继承自Base。
参数为action,类型为function,表示success事件处理程序的动作方法发,context,类型为object,表示success事件处理程序的内容。
其源代码如下:
success: function(action, context) {
return this.once('success', action, context);
}
从源代码可以看出,该函数调用本对象的once方法,once方法能够注册时间处理程序。传入的参数有name,action和context,name固定为'success',最终实现success事件处理程序的注册。
该函数的作用是触发事件,继承自Base。
参数有name,类型为string,表示触发事件的名称,继承自Base。
其源代码如下:
trigger: function(name) {
if (!this.hasOwnProperty('__handlers__')) {
return;
}
if (!this.__handlers__.hasOwnProperty(name)) {
return;
}
var hdls = this.__handlers__[name];
var l = hdls.length, i = -1, args = arguments;
// Optimize advise from backbone
switch (args.length) {
case 1:
while (++i < l) {
hdls[i].action.call(hdls[i].context);
}
return;
case 2:
while (++i < l) {
hdls[i].action.call(hdls[i].context, args[1]);
}
return;
case 3:
while (++i < l) {
hdls[i].action.call(hdls[i].context, args[1], args[2]);
}
return;
case 4:
while (++i < l) {
hdls[i].action.call(hdls[i].context, args[1], args[2], args[3]);
}
return;
case 5:
while (++i < l) {
hdls[i].action.call(hdls[i].context, args[1], args[2], args[3], args[4]);
}
return;
default:
while (++i < l) {
hdls[i].action.apply(hdls[i].context, Array.prototype.slice.call(args, 1));
}
return;
}
}
从源代码可以看出,首先判断本对象是否有成员变量__handlers__,若无则返回,若有,则判断__handlers__中是否有键为name的值,若其值为空,则返回。
若以上两个条件均满足,则创建一个局部变量hdls,将本对象中__handlers__中键为name的值赋给它。获取hdls的长度赋给局部变量l,创建i为-1,args为参数arguments。
判断args参数的长度,若为1,则调用hdls中第一个对象的action方法,参数为hdls第一个对象的内容;若为2,则调用hdls中第一个对象的action方法,参数为hdls第一个对象的内容和args[1];若为3,则调用hdls中第一个对象的action方法,参数为hdls第一个对象的内容和args[1],args[2];若为4,则调用hdls中第一个对象的action方法,参数为hdls第一个对象的内容和args[1],args[2],args[3];若为5,则调用hdls中第一个对象的action方法,参数为hdls第一个对象的内容和args[1],args[2],args[3],args[4];否则,调用hdls中第一个对象的action方法,参数为hdls第一个对象的内容和所有的args参数。可见,该函数能够调用hdls中的方法,即__handlers__的方法,并以context和arguments参数来运行,从而实现事件的出发。
该函数的作用是更新图的链接。
无参数。
其源代码为:
update: function () {
for (var i = 0; i < this.nodes.length; i++) {
this.nodes[i].clear();
}
// Traverse all the nodes and build the graph
for (var i = 0; i < this.nodes.length; i++) {
var node = this.nodes[i];
if (!node.inputs) {
continue;
}
for (var inputName in node.inputs) {
if (!node.inputs[inputName]) {
continue;
}
if (node.pass && !node.pass.material.isUniformEnabled(inputName)) {
console.warn('Pin ' + node.name + '.' + inputName + ' not used.');
continue;
}
var fromPinInfo = node.inputs[inputName];
var fromPin = this.findPin(fromPinInfo);
if (fromPin) {
node.link(inputName, fromPin.node, fromPin.pin);
}
else {
if (typeof fromPinInfo === 'string') {
console.warn('Node ' + fromPinInfo + ' not exist');
}
else {
console.warn('Pin of ' + fromPinInfo.node + '.' + fromPinInfo.pin + ' not exist');
}
}
}
}
}
从源代码中可以看出,首先对nodes数组进行遍历,并对每一个节点对象调用clear方法进行清除。接着,继续对nodes数组进行遍历,获取每一个node节点,如果node节点的inputs对象为空,则跳过该节点,否则对node节点的inputs数组中的对象进行遍历,如果inputs中的对象为空,则跳过,否则判断node的pass是否存在和pass的材料是否没有inputName,如果是,则未使用,打印相应的消息提醒并跳过。接着获取刚才inputs中的节点赋值给fromPinInfo,调用findPin方法找到fromPinInfo中的Pin赋值给fromPin,如果fromPin存在,调用node的link方法对其进行更新链接,如果Pin不存在,则判断fromPinInfo是否为string类型,是的话则打印fromPinInfo不存在Node,否则打印fromPinInfo的node中无Pin,表示未更新。从而实现图的更新