コード例 #1
0
ファイル: Engine.cpp プロジェクト: beyourself/LordPsyanBots
bool Engine::MultiplyAndPush(NextAction** actions, float forceRelevance, bool skipPrerequisites, Event event, const char* pushType)
{
    bool pushed = false;
    if (actions)
    {
        for (int j=0; j<10; j++) // TODO: remove 10
        {
            NextAction* nextAction = actions[j];
            if (nextAction)
            {
                ActionNode* action = CreateActionNode(nextAction->getName());
                InitializeAction(action);

                float k = nextAction->getRelevance();
                if (forceRelevance > 0.0f)
                {
                    k = forceRelevance;
                }

                if (k > 0)
                {
                    LogAction("PUSH:%s - %f (%s)", action->getName().c_str(), k, pushType);
                    queue.Push(new ActionBasket(action, k, skipPrerequisites, event));
                    pushed = true;
                }

                delete nextAction;
            }
            else
                break;
        }
        delete actions;
    }
    return pushed;
}
コード例 #2
0
ファイル: CCActionObject.cpp プロジェクト: CryQ/coclua
void ActionObject::simulationActionUpdate(float dt)
{
	if (_loop)
	{
		bool isEnd = true;
		int nodeNum = _actionNodeList->count();

		for ( int i = 0; i < nodeNum; i++ )
		{
			ActionNode* actionNode = (ActionNode*)_actionNodeList->getObjectAtIndex(i);

			if (actionNode->isActionDoneOnce() == false)
			{
				isEnd = false;
				break;
			}
		}

		if (isEnd)
		{
			this->play();
		}

		//CCLOG("ActionObject Update");
	}
}
コード例 #3
0
BeliefNode *BeliefNode::getChild(Action const &action, Observation const &obs) const {
    ActionNode *node = actionMap_->getActionNode(action);
    if (node == nullptr) {
        return nullptr;
    }
    return node->getChild(obs);
}
コード例 #4
0
ファイル: ActionQueue.cpp プロジェクト: richardszeto/Checkers
    ActionQueue& ActionQueue::operator =(const ActionQueue &rightSide)
    {
        clear();

    	ActionNode *otherNode;

    	front = NULL;

    	back = NULL;

    	otherNode = rightSide.front;

    	if(otherNode != NULL)
    	{
    		front = new ActionNode(otherNode->getData());

    		back = front;

    		otherNode = otherNode->getLink();
    	}

    	while(otherNode != NULL)
    	{
    		back->setLink(new ActionNode(otherNode->getData()));

    		back = back->getLink();

    		otherNode = otherNode->getLink();
    	}

    	length = rightSide.length;

    	return *this;
    }
コード例 #5
0
ファイル: ActionQueue.cpp プロジェクト: richardszeto/Checkers
    ActionQueue::ActionQueue(const ActionQueue &queueObject)
    {
    	ActionNode *otherNode;

    	front = NULL;

    	back = NULL;

    	otherNode = queueObject.front;

    	if(otherNode != NULL)
    	{
    		front = new ActionNode(otherNode->getData());

    		back = front;

    		otherNode = otherNode->getLink();
    	}

    	while(otherNode != NULL)
    	{
    		back->setLink(new ActionNode(otherNode->getData()));

    		back = back->getLink();

    		otherNode = otherNode->getLink();
    	}

    	length = queueObject.length;
    }
コード例 #6
0
void ActionObject::simulationActionUpdate(float dt)
{
	bool isEnd = true;
	int nodeNum = m_ActionNodeList->count();

	for ( int i = 0; i < nodeNum; i++ )
	{
		ActionNode* actionNode = (ActionNode*)m_ActionNodeList->objectAtIndex(i);

		if (actionNode->isActionDoneOnce() == false)
		{
			isEnd = false;
			break;
		}
	}

	if (isEnd)
	{
		if (m_CallBack != NULL)
		{
			m_CallBack->execute();
		}
		if (m_loop)
		{
			this->play();
		}
	}
}
コード例 #7
0
void ActionObject::setUnitTime(float fTime)
{
	m_fUnitTime = fTime;
	int frameNum = m_ActionNodeList->count();
	for ( int i = 0; i < frameNum; i++ )
	{
		ActionNode* actionNode = (ActionNode*)m_ActionNodeList->objectAtIndex(i);
		actionNode->setUnitTime(m_fUnitTime);
	}
}
コード例 #8
0
ファイル: CCActionObject.cpp プロジェクト: CryQ/coclua
void ActionObject::setUnitTime(float fTime)
{
	_fUnitTime = fTime;
	int nodeNum = _actionNodeList->count();
	for ( int i = 0; i < nodeNum; i++ )
	{
		ActionNode* actionNode = (ActionNode*)_actionNodeList->getObjectAtIndex(i);
		actionNode->setUnitTime(_fUnitTime);
	}
}
コード例 #9
0
ファイル: Object.cpp プロジェクト: killing333/Colors
void Object::initActions(){
    StoredDataHandler *storedDataHandler = StoredDataHandler::sharedInstance();
    
    // Store the SpriteIndexNodes related to this object
    spriteIndexNodes = storedDataHandler->getSpriteIndexHashes(identifier, objectType, spriteBatchHandler, Object_Z_Order);
    spriteIndexNodes->retain();
    
    // Get the actions of this object
    CCArray *actions = storedDataHandler->getActionHashes(identifier, objectType);
    actionsHashes = CCDictionary::create();
    actionsHashes->retain();
    
    // Init sprite frame for all action
    {
        for (int i = 0; i < actions->count(); i++) {
            ActionNode *node = (ActionNode *)actions->objectAtIndex(i);
            CCArray *frames = node->spriteIndexes;

            // The assumption is all the sprite frames in a action belong to the same texture
            SpriteIndexNode *spriteIndexNode = this->getSpriteIndexNodeBySpriteIndex(node->getFirstSpriteIndex());
            
            // Create sprite frame objects
            CCArray *spriteFrame = CCArray::create();
            for (int j = 0; j < frames->count(); j++) {
                CCString *spriteIndexStr = (CCString *)frames->objectAtIndex(j);
                int spriteIndex = spriteIndexStr->intValue();
                spriteFrame->addObject(spriteIndexNode->getSpriteFrameByIndex(spriteIndex));
            }
            node->setFirstSpriteFrame((CCSpriteFrame*)spriteFrame->objectAtIndex(0));
            
            // Create animation object
            CCAnimation *animation = CCAnimation::createWithSpriteFrames(spriteFrame, node->delay);
            CCFiniteTimeAction *action = NULL;
            if (node->isRecursive) {
                action = CCRepeatForever::create(CCAnimate::create(animation));
            } else {
                action = CCAnimate::create(animation);
            }
            node->setAnimation(action);
            
            // Get AIActions in this action 
            CCArray *AIActions = storedDataHandler->getAIActionsInAction(identifier, node->name, objectType);
            
            CCArray *actionArray = CCArray::create(node, spriteIndexNode->getSpriteBatchNode(), AIActions, NULL);
            
            // Add (CCAction, CCSpriteBatchNode) into the action hash
            actionsHashes->setObject(actionArray, node->name);
        }
    }

    this->performIdleAnimation();
}
コード例 #10
0
ファイル: CCActionObject.cpp プロジェクト: CryQ/coclua
void ActionObject::stop()
{
	int frameNum = _actionNodeList->count();

	for ( int i = 0; i < frameNum; i++ )
	{
		ActionNode* actionNode = (ActionNode*)_actionNodeList->getObjectAtIndex(i);
		actionNode->stopAction();
	}

	_pScheduler->unscheduleSelector(schedule_selector(ActionObject::simulationActionUpdate), this);
	_bPause = false;
}
コード例 #11
0
ファイル: CCActionObject.cpp プロジェクト: CryQ/coclua
void ActionObject::updateToFrameByTime(float fTime)
{
	_currentTime = fTime;

	int nodeNum = _actionNodeList->count();

	for ( int i = 0; i < nodeNum; i++ )
	{
		ActionNode* actionNode = (ActionNode*)_actionNodeList->getObjectAtIndex(i);

		actionNode->updateActionToTimeLine(fTime);
	}
}
コード例 #12
0
ファイル: CCActionObject.cpp プロジェクト: CryQ/coclua
void ActionObject::play()
{
    stop();
	this->updateToFrameByTime(0.0f);
	int frameNum = _actionNodeList->count();
	for ( int i = 0; i < frameNum; i++ )
	{
		ActionNode* actionNode = (ActionNode*)_actionNodeList->getObjectAtIndex(i);
		actionNode->playAction();
	}
	if (_loop)
	{
		_pScheduler->scheduleSelector(schedule_selector(ActionObject::simulationActionUpdate), this, 0.0f , kRepeatForever, 0.0f, false);
	}
}
コード例 #13
0
ファイル: CCActionObject.cpp プロジェクト: CryQ/coclua
void ActionObject::initWithDictionary(JsonDictionary *dic,Object* root)
{
    setName(DICTOOL->getStringValue_json(dic, "name"));
    setLoop(DICTOOL->getBooleanValue_json(dic, "loop"));
	setUnitTime(DICTOOL->getFloatValue_json(dic, "unittime"));
    int actionNodeCount = DICTOOL->getArrayCount_json(dic, "actionnodelist");
    for (int i=0; i<actionNodeCount; i++) {
        ActionNode* actionNode = new ActionNode();
		actionNode->autorelease();
        JsonDictionary* actionNodeDic = DICTOOL->getDictionaryFromArray_json(dic, "actionnodelist", i);
        actionNode->initWithDictionary(actionNodeDic,root);
		actionNode->setUnitTime(getUnitTime());
        _actionNodeList->addObject(actionNode);
		CC_SAFE_DELETE(actionNodeDic);
    }
}
コード例 #14
0
/* -------------------- Core tree-related methods  ---------------------- */
BeliefNode *BeliefNode::createOrGetChild(Action const &action,
        Observation const &obs) {
    ActionNode *actionNode = actionMap_->getActionNode(action);
    if (actionNode == nullptr) {
        actionNode = actionMap_->createActionNode(action);
        actionNode->setMapping(solver_->getObservationPool()->createObservationMapping(actionNode));
    }
    BeliefNode *childNode;
    bool isNew;
    std::tie(childNode, isNew) = actionNode->createOrGetChild(solver_, obs);
    if (isNew) {
        // If we've created a new node, we also need to create some of its key elements.
        if (data_ != nullptr) {
            childNode->setHistoricalData(data_->createChild(action, obs));
        }
        childNode->setMapping(solver_->getActionPool()->createActionMapping(childNode));
        solver_->getEstimationStrategy()->setValueEstimator(solver_, childNode);
    }
    return childNode;
}
コード例 #15
0
ファイル: Object.cpp プロジェクト: killing333/Colors
void Object::performAnimation(string name, SEL_CallFunc func){
    if (this->getCurrentObjectState() == ObjectStateDead && name.compare("Dead") != 0) {
        return;
    }
    
    CCSpriteBatchNode *currentSpriteBatchNode = m_pobBatchNode;
    CCSpriteBatchNode *newSpriteBatchNode = NULL;

    // Get the action pair by key name
    CCArray *actionPair = (CCArray *)actionsHashes->objectForKey(name);
    // If the action pair does not exist, return early
    if (!actionPair) {
        return;
    }
    newSpriteBatchNode = (CCSpriteBatchNode *)actionPair->objectAtIndex(1);
    ActionNode *actionNode = (ActionNode *)actionPair->objectAtIndex(0);
    
    this->stopActionByTag(ACTION_ANIMATION_TAG);
    
    // If required spriteBatchNode is different from current, replace it
    if (currentSpriteBatchNode != newSpriteBatchNode) {
        this->removeFromParentAndCleanup(false);
        this->setTexture(actionNode->getFirstSpriteFrame()->getTexture());
        this->setTextureRect(actionNode->getFirstSpriteFrame()->getRect());
        newSpriteBatchNode->addChild(this);
    }

    if (func != NULL) {
        CCAssert(dynamic_cast<CCRepeatForever*>(actionNode->getAnimation()) == NULL, "Not able to call function for CCRepeatForever action.");
        
        // Create animation followed by a function call
        CCSequence *seq = CCSequence::createWithTwoActions(actionNode->getAnimation(), CCCallFunc::create(this, func));
        seq->setTag(ACTION_ANIMATION_TAG);
        this->runAction(seq);
    } else {
        // Run the action
        actionNode->getAnimation()->setTag(ACTION_ANIMATION_TAG);
        this->runAction(actionNode->getAnimation());
    }
    
    // Run AI in this action
    {
        if (actionPair->count() > 2) {
            CCArray *AIActions = (CCArray *)actionPair->objectAtIndex(2);
            CCLOG("%s is running AI, total AIAction count: %d", identifier.c_str(), AIActions->count());
            for (int i = 0; i < AIActions->count(); i++) {
                CCAction *action = (CCAction*)AIActions->objectAtIndex(i);
                this->runAction(action);
            }
        }
    }
}
コード例 #16
0
	ActionChoiceWindow::ActionNode* 
        ActionChoiceWindow::ActionNode::createActionTree(const ActionVector& actions, ActionGroup* rootGroup)
	{
		ActionNode* root = new ActionNode(false);
		root->setGroup(rootGroup);

		set<ActionGroup*> groups;
		ActionVector rest;
        
		for (ActionVector::const_iterator iter = actions.begin(); iter != actions.end(); iter++)
		{
			Action* action = *iter;

			ActionGroup* group = action->getGroup();
			if (group == NULL || group == rootGroup )
				rest.push_back(action);
			else if (groups.find(group) == groups.end())
				groups.insert(group);
		}

		if (actions.size() / 1.2 <= rest.size() + groups.size())
		{
			groups.clear();
			rest = actions;
		}

		for (set<ActionGroup*>::iterator groupIter = groups.begin();
			 groupIter != groups.end(); groupIter++)
		{
			ActionVector actionsThisGroup;
			ActionGroup* thisGroup = *groupIter;

			for (ActionVector::const_iterator actionIter = actions.begin(); 
				 actionIter != actions.end(); actionIter++)
			{
				Action* action = *actionIter;
				if (action->getGroup() == thisGroup)
					actionsThisGroup.push_back(action);
			}

			if (actionsThisGroup.size() > 0)
			{
				ActionNode* actionNodeGroup = createActionTree(actionsThisGroup, thisGroup);
				root->addChild(actionNodeGroup);
			}
		}

		for (ActionVector::iterator iter = rest.begin(); iter != rest.end(); iter++)
		{
			ActionNode* node = new ActionNode(true);
			node->setAction(*iter);
			root->addChild(node);
		}

		return root;
	}
コード例 #17
0
	ActionChoiceWindow::NodeSet ActionChoiceWindow::ActionNode::getAllNodesNotBelow(
		ActionNode* treeRoot, ActionChoiceWindow::ActionNode* targetNode)
	{
		NodeSet allNodes;
		getAllNodes(treeRoot, allNodes);
		
		NodeSet nodes;
		for (NodeSet::iterator iter = allNodes.begin(); iter != allNodes.end(); iter++)
		{
			bool leaveOut = false;
			
			if ((*iter)->getParent() == treeRoot ||
				*iter == targetNode ||
				(*iter)->getButton() == NULL)
			{
				leaveOut = true;
				continue;
			}
				
			ActionNode* node = *iter;
			while(node->getParent() != NULL)
			{
				node = node->getParent();
				if (node == targetNode)
				{
					leaveOut = true;
					continue;
				}
			}

			if (!leaveOut)
				nodes.insert(*iter);
		}
		
		return nodes;
	}
コード例 #18
0
void ActionObject::initWithBinary(CocoLoader *cocoLoader,
                                  stExpCocoNode *cocoNode,
                                  cocos2d::Ref *root)
{
    stExpCocoNode *stChildNode = cocoNode->GetChildArray(cocoLoader);
    stExpCocoNode *actionNodeList = nullptr;
    int count = cocoNode->GetChildNum();
    for (int i = 0; i < count; ++i) {
        std::string key = stChildNode[i].GetName(cocoLoader);
        std::string value = stChildNode[i].GetValue(cocoLoader);
        if (key == "name") {
            setName(value.c_str());
        }else if (key == "loop"){
            setLoop(valueToBool(value));
        }else if(key == "unittime"){
            setUnitTime(valueToFloat(value));
        }else if (key == "actionnodelist"){
            actionNodeList = &stChildNode[i];
        }
    }
    
    if(nullptr != actionNodeList)
    {
        int actionNodeCount = actionNodeList->GetChildNum();
        stExpCocoNode *actionNodeArray = actionNodeList->GetChildArray(cocoLoader);
        int maxLength = 0;
        for (int i=0; i<actionNodeCount; i++) {
            ActionNode* actionNode = new ActionNode();
            actionNode->autorelease();
            
            actionNode->initWithBinary(cocoLoader, &actionNodeArray[i] , root);
            
            actionNode->setUnitTime(getUnitTime());
            
            _actionNodeList.pushBack(actionNode);
            
            int length = actionNode->getLastFrameIndex() - actionNode->getFirstFrameIndex();
            if(length > maxLength)
                maxLength = length;
        }
        
        
        _fTotalTime = maxLength* _fUnitTime;
    }
}
コード例 #19
0
void ActionObject::initWithDictionary(const rapidjson::Value& dic, Ref* root)
{
    setName(DICTOOL->getStringValue_json(dic, "name"));
    setLoop(DICTOOL->getBooleanValue_json(dic, "loop"));
    setUnitTime(DICTOOL->getFloatValue_json(dic, "unittime"));
    int actionNodeCount = DICTOOL->getArrayCount_json(dic, "actionnodelist");
    int maxLength = 0;
    for (int i=0; i<actionNodeCount; i++) {
        ActionNode* actionNode = new ActionNode();
        actionNode->autorelease();
        const rapidjson::Value& actionNodeDic = DICTOOL->getDictionaryFromArray_json(dic, "actionnodelist", i);
        actionNode->initWithDictionary(actionNodeDic,root);
        actionNode->setUnitTime(getUnitTime());
        _actionNodeList.pushBack(actionNode);
        
        int length = actionNode->getLastFrameIndex() - actionNode->getFirstFrameIndex();
        if(length > maxLength)
            maxLength = length;
    }
    _fTotalTime = maxLength*_fUnitTime;
}
コード例 #20
0
ファイル: Engine.cpp プロジェクト: beyourself/LordPsyanBots
bool Engine::DoNextAction(Unit* unit, int depth)
{
    LogAction("--- AI Tick ---");
    if (sPlayerbotAIConfig.logValuesPerTick)
        LogValues();

    bool actionExecuted = false;
    ActionBasket* basket = NULL;

    time_t currentTime = time(0);
    aiObjectContext->Update();
    ProcessTriggers();

    int iterations = 0;
    int iterationsPerTick = queue.Size() * sPlayerbotAIConfig.iterationsPerTick;
    do {
        basket = queue.Peek();
        if (basket) {
            if (++iterations > iterationsPerTick)
                break;

            float relevance = basket->getRelevance(); // just for reference
            bool skipPrerequisites = basket->isSkipPrerequisites();
            Event event = basket->getEvent();
            // NOTE: queue.Pop() deletes basket
            ActionNode* actionNode = queue.Pop();
            Action* action = InitializeAction(actionNode);

            if (!action)
            {
                LogAction("A:%s - UNKNOWN", actionNode->getName().c_str());
            }
            else if (action->isUseful())
            {
                for (list<Multiplier*>::iterator i = multipliers.begin(); i!= multipliers.end(); i++)
                {
                    Multiplier* multiplier = *i;
                    relevance *= multiplier->GetValue(action);
                    if (!relevance)
                    {
                        LogAction("Multiplier %s made action %s useless", multiplier->getName().c_str(), action->getName().c_str());
                        break;
                    }
                }

                if (action->isPossible() && relevance)
                {
                    if (!skipPrerequisites)
                    {
                        LogAction("A:%s - PREREQ", action->getName().c_str());
                        if (MultiplyAndPush(actionNode->getPrerequisites(), relevance + 0.02, false, event, "prereq"))
                        {
                            PushAgain(actionNode, relevance + 0.01, event);
                            continue;
                        }
                    }

                    actionExecuted = ListenAndExecute(action, event);

                    if (actionExecuted)
                    {
                        LogAction("A:%s - OK", action->getName().c_str());
                        MultiplyAndPush(actionNode->getContinuers(), 0, false, event, "cont");
                        lastRelevance = relevance;
                        delete actionNode;
                        break;
                    }
                    else
                    {
                        LogAction("A:%s - FAILED", action->getName().c_str());
                        MultiplyAndPush(actionNode->getAlternatives(), relevance + 0.03, false, event, "alt");
                    }
                }
                else
                {
                    LogAction("A:%s - IMPOSSIBLE", action->getName().c_str());
                    MultiplyAndPush(actionNode->getAlternatives(), relevance + 0.03, false, event, "alt");
                }
            }
            else
            {
                lastRelevance = relevance;
                LogAction("A:%s - USELESS", action->getName().c_str());
            }
            delete actionNode;
        }
    }
    while (basket);

    if (!basket)
    {
        lastRelevance = 0.0f;
        PushDefaultActions();
        if (queue.Peek() && depth < 2)
            return DoNextAction(unit, depth + 1);
    }

    if (time(0) - currentTime > 1) {
        LogAction("too long execution");
    }

    if (!actionExecuted)
        LogAction("no actions executed");

    return actionExecuted;
}
コード例 #21
0
ファイル: SlGeneratorInstance.cpp プロジェクト: quyse/inanity
void SlGeneratorInstance::RegisterNode(Node* node)
{
	// if registration of node already began
	if(registeredNodes.find(node) != registeredNodes.end())
	{
		// if node is not registered yet
		if(nodeInitIndices.find(node) == nodeInitIndices.end())
			// than it's a loop
			THROW("Node cyclic dependency");
		// else it's ok, it's just another use of node
		return;
	}
	// register node
	registeredNodes.insert(node);

	switch(node->GetType())
	{
	case Node::typeFloatConst:
	case Node::typeIntConst:
		break;
	case Node::typeAttribute:
		{
			if(shaderType != ShaderTypes::vertex)
				THROW("Only vertex shader can have attribute nodes");

			attributes.push_back(fast_cast<AttributeNode*>(node));
		}
		break;
	case Node::typeUniform:
		{
			UniformNode* uniformNode = fast_cast<UniformNode*>(node);
			uniforms.push_back(std::make_pair(uniformNode->GetGroup(), uniformNode));
		}
		break;
	case Node::typeSampler:
		samplers.push_back(fast_cast<SamplerNode*>(node));
		break;
	case Node::typeReadUniform:
		RegisterNode(fast_cast<ReadUniformNode*>(node)->GetUniformNode());
		break;
	case Node::typeIndexUniformArray:
		{
			IndexUniformArrayNode* indexUniformArrayNode = fast_cast<IndexUniformArrayNode*>(node);
			RegisterNode(indexUniformArrayNode->GetUniformNode());
			RegisterNode(indexUniformArrayNode->GetIndexNode());
		}
		break;
	case Node::typeTransformed:
		transformedNodes.push_back(fast_cast<TransformedNode*>(node));
		break;
	case Node::typeInterpolate:
		{
			InterpolateNode* interpolateNode = fast_cast<InterpolateNode*>(node);
			interpolateNodes.push_back(interpolateNode);
			RegisterNode(interpolateNode->GetNode());
		}
		break;
	case Node::typeSequence:
		{
			SequenceNode* sequenceNode = fast_cast<SequenceNode*>(node);
			RegisterNode(sequenceNode->GetA());
			RegisterNode(sequenceNode->GetB());
		}
		break;
	case Node::typeSwizzle:
		RegisterNode(fast_cast<SwizzleNode*>(node)->GetA());
		break;
	case Node::typeOperation:
		{
			OperationNode* operationNode = fast_cast<OperationNode*>(node);
			int argumentsCount = operationNode->GetArgumentsCount();
			for(int i = 0; i < argumentsCount; ++i)
				RegisterNode(operationNode->GetArgument(i));
		}
		break;
	case Node::typeAction:
		{
			ActionNode* actionNode = fast_cast<ActionNode*>(node);
			int argumentsCount = actionNode->GetArgumentsCount();
			for(int i = 0; i < argumentsCount; ++i)
				RegisterNode(actionNode->GetArgument(i));
		}
		break;
	case Node::typeSample:
		{
			SampleNode* sampleNode = fast_cast<SampleNode*>(node);

			RegisterNode(sampleNode->GetSamplerNode());
			RegisterNode(sampleNode->GetCoordsNode());

			ValueNode* lodNode = sampleNode->GetLodNode();
			if(lodNode)
				RegisterNode(lodNode);

			ValueNode* biasNode = sampleNode->GetBiasNode();
			if(biasNode)
				RegisterNode(biasNode);

			ValueNode* gradXNode = sampleNode->GetGradXNode();
			if(gradXNode)
				RegisterNode(gradXNode);
			ValueNode* gradYNode = sampleNode->GetGradYNode();
			if(gradYNode)
				RegisterNode(gradYNode);

			ValueNode* offsetNode = sampleNode->GetOffsetNode();
			if(offsetNode)
				RegisterNode(offsetNode);
		}
		break;
	case Node::typeFragment:
		{
			if(shaderType != ShaderTypes::pixel)
				THROW("Only pixel shader can do fragment output");
			FragmentNode* fragmentNode = fast_cast<FragmentNode*>(node);

			// register maximum number of fragment outputs
			fragmentTargetsCount = std::max(fragmentTargetsCount, fragmentNode->GetTarget() + 1);
			RegisterNode(fragmentNode->GetNode());
		}
		break;
	case Node::typeDualFragment:
		{
			if(shaderType != ShaderTypes::pixel)
				THROW("Only pixel shader can do dual fragment output");
			DualFragmentNode* dualFragmentNode = fast_cast<DualFragmentNode*>(node);

			dualFragmentTarget = true;

			// register maximum number of fragment outputs
			fragmentTargetsCount = std::max(fragmentTargetsCount, 2);
			RegisterNode(dualFragmentNode->GetNode0());
			RegisterNode(dualFragmentNode->GetNode1());
		}
		break;
	case Node::typeCast:
		RegisterNode(fast_cast<CastNode*>(node)->GetA());
		break;
	default:
		THROW("Unknown node type");
	}

	// add initialization of node
	THROW_ASSERT(nodeInitIndices.find(node) == nodeInitIndices.end());
	nodeInitIndices[node] = (int)nodeInits.size();
	nodeInits.push_back(node);
}