creator 里 director 流程

cc.Director

cc.Director 继承自 EventTarget(前面分析过),
所以 cc.Director 也有 分发事件, 监听事件,发布事件的能力.

其包含的几个关键属性:

	// Scheduler for user registration update
    this._scheduler = null;    
    // Scheduler for life-cycle methods in component
    this._compScheduler = null;
    // Node activator
    this._nodeActivator = null;
    // Action manager
    this._actionManager = null;

解释一下里面几个东西的作用.
a. this._scheduler 一个全局的调度器. _actionManager,_collisionManager,_physicsManager 都直接注册这这上面.
我们一般不需要用这个.

b. this._compScheduler 和 this._nodeActivator
这两个东西其实互相一起作用的. 在加载完scene后,或者切换scene,要进行显示之前,
会调用 scene 的 _activate方法. 在director::runSceneImmediate 这方法里面:

scene._activate();

这个 _activate 方法,就会通过 director的 _nodeActivator 这东西的 activateNode 方法进行激活:
NodeActivator::_activateNodeRecursively

	this._activateNodeRecursively(node, task.preload, task.onLoad, task.onEnable);

这里面node就是加载的scene, 先激活scene上的 component(NodeActivator::activateComp).
然后再对 scene 上的子节点进行递归调用 _activateNodeRecursively.

在激活node的时候(NodeActivator::activateComp方法),

 cc.director._compScheduler.enableComp(comp, onEnableInvoker);

在 ComponentScheduler::enableComp 里,又会调用 ComponentScheduler::_onEnabled(comp)这方法,
如果当前正在更新,就放到 scheduleInNextFrame 这个数组中,下一帧来处理,
否则就 ComponentScheduler::_scheduleImmediate 调用这方法,

	_scheduleImmediate (comp) {
        if (comp.start && !(comp._objFlags & IsStartCalled)) {
            this.startInvoker.add(comp);
        }
        if (comp.update) {
            this.updateInvoker.add(comp);
        }
        if (comp.lateUpdate) {
            this.lateUpdateInvoker.add(comp);
        }
    },

director的 this._compScheduler 这家伙,里面包含:
ComponentScheduler::ctor()

	function ctor () {
    // invokers
    this.startInvoker = new OneOffInvoker(createInvokeImpl(
        CC_EDITOR ? callStartInTryCatch : callStart));
    this.updateInvoker = new ReusableInvoker(createInvokeImpl(
        CC_EDITOR ? callUpdateInTryCatch : callUpdate, true));
    this.lateUpdateInvoker = new ReusableInvoker(createInvokeImpl(
        CC_EDITOR ? callLateUpdateInTryCatch : callLateUpdate, true));

    // components deferred to next frame
    this.scheduleInNextFrame = [];

    // during a loop
    this._updating = false;
}

在 _scheduleImmediate 方法中,就将scene中所有节点的组件,
按照从scene开始 递归下来 全部加入到 这几个 invoker里面了.
然后,就会在 director::mainLoop 方法里,去更新了.

引擎初始化后,会调用 自身的 init 方法,完成初始化:

  1. 创建调度器.
this._scheduler = new Scheduler();
  1. 创建 ActionManager, 并且启动.
	if (cc.ActionManager) {
		this._actionManager = new cc.ActionManager();
		this._scheduler.scheduleUpdate(this._actionManager, Scheduler.PRIORITY_SYSTEM, false);    
	} else {
		this._actionManager = null;
	}
  1. 创建 组件调度器和 NodeActivator(管理节点的激活)
	this._compScheduler = new ComponentScheduler();
	this._nodeActivator = new NodeActivator();
  1. 创建 动画管理器,并且启动.
	if (cc.AnimationManager) {
		this._animationManager = new cc.AnimationManager();
		this._scheduler.scheduleUpdate(this._animationManager, Scheduler.PRIORITY_SYSTEM, false);
	}
	else {
		this._animationManager = null;
	}
  1. 创建碰撞管理器,并且启动.
	// collision manager
	if (cc.CollisionManager) {
		this._collisionManager = new cc.CollisionManager();
		this._scheduler.scheduleUpdate(this._collisionManager, Scheduler.PRIORITY_SYSTEM, false);
	}
	else {
		this._collisionManager = null;
	}
  1. 创建物理引擎管理器,并且启动.
	// physics manager
	if (cc.PhysicsManager) {
		this._physicsManager = new cc.PhysicsManager();
		this._scheduler.scheduleUpdate(this._physicsManager, Scheduler.PRIORITY_SYSTEM, false);
	}
	else {
		this._physicsManager = null;
	}
  1. 创建控件管理器
	// WidgetManager
	if (cc._widgetManager) {
		cc._widgetManager.init(this);
	}

mainLoop 方法

  1. 先计算 dt
this.calculateDeltaTime();
  1. 更新. 主要是组件的更新
	// Update
	if (!this._paused) {
		this.emit(cc.Director.EVENT_BEFORE_UPDATE);
		// Call start for new added components
		this._compScheduler.startPhase();
		// Update for components
		this._compScheduler.updatePhase(this._deltaTime);
		// Engine update with scheduler
		this._scheduler.update(this._deltaTime);
		// Late update for components
		this._compScheduler.lateUpdatePhase(this._deltaTime);
		// User can use this event to do things after update
		this.emit(cc.Director.EVENT_AFTER_UPDATE);
		// Destroy entities that have been removed recently
		Obj._deferredDestroy();
	}

所有节点的 component 都在 _compScheduler 这里面,
startPhase 里面调用一些 onload start 这些一次性方法(只调用一次).
updatePhase 就调用组件中的 update 方法.
this._scheduler.update(this._deltaTime); 就只执行注册的 actionManager collisionManager physicsManager 这些更新.
lateUpdatePhase 调用 lateUpdate 方法.

发射 EVENT_AFTER_UPDATE 事件, 这时,WidgetManager 就会计算 widget 这些东西.
见 WidgetManager::refreshScene 方法.

  1. 渲染
renderer.render(this._scene);

注意: 这里面的 renderer. 是cc.renderer, 不是 renderEngine里面的那个 renderer.
这个 renderer 创建webgl环境,使用 ForwardRenderer 去做渲染.
renderEngine里面那个renderer,就只是包含渲染使用的工具.

当前renderer 在 cocos2d/core/renderer/index.js 里面,
在 initWebGL 方法里,
创建了用于渲染需要的东西:

this.device = new renderEngine.Device(canvas, opts);
this.scene = new renderEngine.Scene();
this._walker = new RenderComponentWalker(this.device, this.scene);
this._forward = new renderEngine.ForwardRenderer(this.device, builtins);

看 renderer.render 方法:

// walk entity component scene to generate models
this._walker.visit(ecScene);
// Render models in renderer scene
this._forward.render(this.scene);

调用了 walker:visit 这个方法,这个方法中最重要的是:

RenderFlow.render(scene);
function render (scene) {
    if (scene._renderFlag & WORLD_TRANSFORM) {
        _walker.worldMatDirty ++;
        scene._calculWorldMatrix();
        scene._renderFlag &= ~WORLD_TRANSFORM;

        flows[scene._renderFlag]._func(scene);

        _walker.worldMatDirty --;
    }
    else {
        flows[scene._renderFlag]._func(scene);
    }
}

flows[scene._renderFlag]._func(scene); 主要是这一句.
这一句会从 scene开始,按照:

const DONOTHING = 0;
const LOCAL_TRANSFORM = 1 << 0;
const WORLD_TRANSFORM = 1 << 1;
const TRANSFORM = LOCAL_TRANSFORM | WORLD_TRANSFORM;
const UPDATE_RENDER_DATA = 1 << 2;
const OPACITY = 1 << 3;
const COLOR = 1 << 4;
const RENDER = 1 << 5;
const CUSTOM_IA_RENDER = 1 << 6;
const CHILDREN = 1 << 7;
const POST_UPDATE_RENDER_DATA = 1 << 8;
const POST_RENDER = 1 << 9;

这里面的顺序,依次检查scene的 _renderFlag.
只要设置了,就调用相应的回调函数, 回调函数全部在 render-flow.js 里面.
当调用到 _children 这个回调的时候, 黑魔法来了.

会对scene的子节点又进行一次从上到下的检查. 直到场景树上所有的node全部更新完毕.
其实最核心更新的 就是 node 的模型矩阵,颜色,opacity.

在render-flow 中回调 _render 的时候,
会检查使用的材质,如果当前的和调用的 component 的材质不一样,
则需要将前面的 _flush一次, 会使用 model 来暂存.

接着调用:

 this._forward.render(this.scene);

2d中使用 main camera,去渲染 render_scene.
这个render_scene是 walk里面创建的scene,不是 director._scene.

然后就会调用到 Base::_render 这个方法,
此方法里面设置好渲染环境,
从models中把数据拿出来,
然后 在render stages里面,回调 forwardrenderer 里面 注册的 _transparentStage方法.

// render stages
  for (var i$2 = 0; i$2 < _stageInfos.length; ++i$2) {
    var info = _stageInfos.data[i$2];
    var fn = this$1._stage2fn[info.stage];

    fn(view, info.items);
  }

就是 fn(view, info.items); 调用下面的函数:

 ForwardRenderer.prototype._transparentStage = function _transparentStage (view, items) {
    var this$1 = this;

    // update uniforms
    this._device.setUniform('view', mat4.array(_a16_view, view._matView));
    this._device.setUniform('proj', mat4.array(_a16_proj, view._matProj));
    this._device.setUniform('viewProj', mat4.array(_a16_viewProj, view._matViewProj));

    // draw it
    for (var i = 0; i < items.length; ++i) {
      var item = items.data[i];
      this$1._draw(item);
    }
  };

然后有调用到: Base.prototype._draw,再在 Base::_draw里面
调用 device.draw(ia._start, count); 进行最终的绘制.

posted @ 2019-02-28 17:26  Dai Hanlong  阅读(829)  评论(0编辑  收藏  举报