<commit_before>#include "ZhongCai.h"
#include "..\GameGrail.h"
#include "..\UserTask.h"

ZhongCai::ZhongCai(GameGrail *engine, int id, int color): PlayerEntity(engine, id, color)
{
	setCrystal(2);
	GameInfo game_info;
	Coder::energyNotice(id, gem, crystal, game_info);
	engine->sendMessage(-1, MSG_GAME, game_info);
	tokenMax[0] = 4;
}

bool ZhongCai::cmdMsgParse(UserTask *session, uint16_t type, ::google::protobuf::Message *proto)
{
	switch(type)
	{
	case MSG_RESPOND:
		Respond* respond = (Respond*)proto;
		switch(respond->respond_id())
		{
		case YI_SHI_ZHONG_DUAN:
			//tryNotifyϷ̴߳ϢֻidڵǰȴidstateڵǰstatestepڵǰstepϷ̲߳Ż
			session->tryNotify(id, STATE_BOOT, YI_SHI_ZHONG_DUAN, respond);
			return true;
		case ZHONG_CAI_YI_SHI:
			//tryNotifyϷ̴߳ϢֻidڵǰȴidstateڵǰstatestepڵǰstepϷ̲߳Ż
			session->tryNotify(id, STATE_BOOT, ZHONG_CAI_YI_SHI, respond);
			return true;
		}
	}
	//ûƥ򷵻false
	return false;
}

int ZhongCai::p_turn_begin(int &step, int currentPlayerID)
{
	if (currentPlayerID == id && tap)
	{
		ZhongCaiYiShiAddToken();
	}
	step = STEP_DONE;
	return GE_SUCCESS;
}

int ZhongCai::p_boot(int &step, int currentPlayerID)
{
	if (currentPlayerID != id)
		return GE_SUCCESS;
	int ret;
	if (tap)
	{
		step = YI_SHI_ZHONG_DUAN;
		ret = YiShiZhongDuan();
		if(toNextStep(ret) || ret == GE_URGENT){
			//ȫstepSTEP_DONE
			step = STEP_DONE;
		}
		return ret;
	}
	else if (gem > 0)
	{
		step = ZHONG_CAI_YI_SHI;
		ret = ZhongCaiYiShi();
		if(toNextStep(ret) || ret == GE_URGENT){
			//ȫstepSTEP_DONE
			step = STEP_DONE;
		}
		return ret;
	}
	return GE_SUCCESS;
}

int ZhongCai::p_timeline_6_drawn(int &step, CONTEXT_TIMELINE_6_DRAWN *con)
{
	if (con->dstID != id || con->harm.type == HARM_NONE)
		return GE_SUCCESS;
	int ret = ShenPanLangChao();
	step = STEP_DONE;
	return ret;
}

int ZhongCai::v_allow_action(Action* action, int allow, bool canGiveUp)
{
	if (token[0] < 4)
		return PlayerEntity::v_allow_action(action, allow, canGiveUp);

	if(canGiveUp && action->action_type() == ACTION_NONE)
		return GE_SUCCESS;

	if (action->action_type() != ACTION_MAGIC_SKILL || action->action_id() != MO_RI_SHEN_PAN)
		return GE_INVALID_ACTION;

	return GE_SUCCESS;
}

int ZhongCai::v_magic_skill(Action* action)
{
	int actionID = action->action_id();
	int playerID = action->src_id();
	PlayerEntity* dst;

	if(playerID != id){
		return GE_INVALID_PLAYERID;
	}

	switch(actionID)
	{
	case MO_RI_SHEN_PAN:
		//  û
		if (token[0] == 0){
			return GE_INVALID_ACTION;
		}
		break;
	case PAN_JUE_TIAN_PING:
		//          || ©˲               || û
		if (token[0] == 4 || action->args_size() == 0 || crystal + gem == 0){
			return GE_INVALID_ACTION;
		}
		break;
	default:
		return GE_INVALID_ACTION;
	}
	return GE_SUCCESS;
}

int ZhongCai::p_magic_skill(int &step, Action *action)
{
	int actionID = action->action_id();
	int ret;

	switch(actionID)
	{
	case MO_RI_SHEN_PAN:
		ret = MoRiShenPan(action);
		if (ret == GE_URGENT)
			step = STEP_DONE;
		break;
	case PAN_JUE_TIAN_PING:
		ret = PanJueTianPing(action);
		if (ret == GE_URGENT)
			step = STEP_DONE;
		break;
	default:
		return GE_INVALID_ACTION;
	}
	return ret;
}

int ZhongCai::YiShiZhongDuan()
{
	CommandRequest cmd_req;
	int ret;
	Coder::askForSkill(id, YI_SHI_ZHONG_DUAN, cmd_req);
	Command *cmd = (Command*)(&cmd_req.commands(cmd_req.commands_size()-1));
	//޵ȴUserTasktryNotify
	if(engine->waitForOne(id, network::MSG_CMD_REQ, cmd_req))
	{
		void* reply;
		if (GE_SUCCESS == (ret = engine->getReply(id, reply)))
		{
			Respond* respond = (Respond*) reply;
			if (respond->args_size()>0 && respond->args(0) == 1)
			{
				SkillMsg skill_msg;
				Coder::skillNotice(id, id, YI_SHI_ZHONG_DUAN, skill_msg);
				engine->sendMessage(-1, MSG_SKILL, skill_msg);

				TeamArea* team_area = engine->getTeamArea();
				team_area->setGem(color, team_area->getGem(color)+1);
				tap = false;

				GameInfo game_info;
				Coder::stoneNotice(color, team_area->getGem(color), team_area->getCrystal(color), game_info);
				Coder::tapNotice(id, tap, game_info);
				engine->sendMessage(-1, MSG_GAME, game_info);

				engine->setStateChangeMaxHand(id, true, false, 6, 0);
				return GE_URGENT;
			}
		}
	}
	else{
		return GE_TIMEOUT;
	}
	return GE_SUCCESS;
}

int ZhongCai::ZhongCaiYiShi()
{
	CommandRequest cmd_req;
	int ret;
	Coder::askForSkill(id, ZHONG_CAI_YI_SHI, cmd_req);
	Command *cmd = (Command*)(&cmd_req.commands(cmd_req.commands_size()-1));
	//޵ȴUserTasktryNotify
	if(engine->waitForOne(id, network::MSG_CMD_REQ, cmd_req))
	{
		void* reply;
		if (GE_SUCCESS == (ret = engine->getReply(id, reply)))
		{
			Respond* respond = (Respond*) reply;
			if (respond->args_size()>0 && respond->args(0) == 1)
			{
				SkillMsg skill_msg;
				Coder::skillNotice(id, id, ZHONG_CAI_YI_SHI, skill_msg);
				engine->sendMessage(-1, MSG_SKILL, skill_msg);

				setGem(gem-1);
				tap = true;

				GameInfo game_info;
				Coder::tapNotice(id, tap, game_info);
				Coder::energyNotice(id, gem, crystal, game_info);
				engine->sendMessage(-1, MSG_GAME, game_info);

				engine->setStateChangeMaxHand(id, true, true, 5, 0);
				return GE_URGENT;
			}
		}
	}
	else{
		return GE_TIMEOUT;
	}
	return GE_SUCCESS;
}

int ZhongCai::MoRiShenPan(Action* action)
{
	SkillMsg skill_msg;
	Coder::skillNotice(id, id, MO_RI_SHEN_PAN, skill_msg);
	engine->sendMessage(-1, MSG_SKILL, skill_msg);

	HARM shenpan;
	shenpan.cause = MO_RI_SHEN_PAN;
	shenpan.point = token[0];
	shenpan.srcID = id;
	shenpan.type = HARM_MAGIC;
	engine->setStateTimeline3(action->dst_ids(0), shenpan);

	setToken(0, 0);

	GameInfo game_info;
	Coder::tokenNotice(id, 0, token[0], game_info);
	engine->sendMessage(-1, MSG_GAME, game_info);
	return GE_URGENT;
}

int ZhongCai::ShenPanLangChao()
{
	SkillMsg skill_msg;
	Coder::skillNotice(id, id, SHEN_PAN_LANG_CHAO, skill_msg);
	engine->sendMessage(-1, MSG_SKILL, skill_msg);

	setToken(0, token[0]+1);

	GameInfo game_info;
	Coder::tokenNotice(id, 0, token[0], game_info);
	engine->sendMessage(-1, MSG_GAME, game_info);

	return GE_SUCCESS;
}

int ZhongCai::PanJueTianPing(Action* action)
{
	//
	if (crystal > 0)
		setCrystal(crystal-1);
	else
		setGem(gem-1);

	// +1
	setToken(0, token[0]+1);
	SkillMsg skill_msg;
	Coder::skillNotice(id, id, YI_SHI_ZHONG_DUAN, skill_msg);
	engine->sendMessage(-1, MSG_SKILL, skill_msg);

	GameInfo game_info;
	Coder::energyNotice(id, gem, crystal, game_info);
	Coder::tokenNotice(id, 0, token[0], game_info);

	if (action->args(0) == 0)
	{
		vector<int> hands;
		list<int>::iterator hand_card_it;
		for (hand_card_it=handCards.begin(); hand_card_it!=handCards.end(); ++hand_card_it)
			hands.push_back(*hand_card_it);
		//
		engine->setStateMoveCardsNotToHand(id, DECK_HAND, -1, DECK_DISCARD, handCards.size(), hands, id, PAN_JUE_TIAN_PING, false);
	}
	else
	{
		//
		if (handCardsMax > handCards.size())
		{
			vector<int> cards;
			HARM tianping;
			tianping.cause = PAN_JUE_TIAN_PING;
			tianping.point = handCardsMax-handCards.size();
			tianping.srcID = id;
			tianping.type = HARM_NONE;
			engine->setStateMoveCardsToHand(-1, DECK_PILE, id, DECK_HAND, handCardsMax-handCards.size(), cards, tianping, false);
		}
		// ս+1ʯ
		TeamArea* team_area = engine->getTeamArea();
		team_area->setGem(color, team_area->getGem(color)+1);

		Coder::stoneNotice(color, team_area->getGem(color), team_area->getCrystal(color), game_info);
	}

	engine->sendMessage(-1, MSG_GAME, game_info);
	return GE_URGENT;
}

int ZhongCai::ZhongCaiYiShiAddToken()
{
	setToken(0, token[0]+1);

	GameInfo game_info;
	Coder::tokenNotice(id, 0, token[0], game_info);
	engine->sendMessage(-1, MSG_GAME, game_info);
	return GE_SUCCESS;
}<commit_msg>仲裁skill notice更新<commit_after>#include "ZhongCai.h"
#include "..\GameGrail.h"
#include "..\UserTask.h"

ZhongCai::ZhongCai(GameGrail *engine, int id, int color): PlayerEntity(engine, id, color)
{
	setCrystal(2);
	GameInfo game_info;
	Coder::energyNotice(id, gem, crystal, game_info);
	engine->sendMessage(-1, MSG_GAME, game_info);
	tokenMax[0] = 4;
}

bool ZhongCai::cmdMsgParse(UserTask *session, uint16_t type, ::google::protobuf::Message *proto)
{
	switch(type)
	{
	case MSG_RESPOND:
		Respond* respond = (Respond*)proto;
		switch(respond->respond_id())
		{
		case YI_SHI_ZHONG_DUAN:
			//tryNotifyϷ̴߳ϢֻidڵǰȴidstateڵǰstatestepڵǰstepϷ̲߳Ż
			session->tryNotify(id, STATE_BOOT, YI_SHI_ZHONG_DUAN, respond);
			return true;
		case ZHONG_CAI_YI_SHI:
			//tryNotifyϷ̴߳ϢֻidڵǰȴidstateڵǰstatestepڵǰstepϷ̲߳Ż
			session->tryNotify(id, STATE_BOOT, ZHONG_CAI_YI_SHI, respond);
			return true;
		}
	}
	//ûƥ򷵻false
	return false;
}

int ZhongCai::p_turn_begin(int &step, int currentPlayerID)
{
	if (currentPlayerID == id && tap)
	{
		ZhongCaiYiShiAddToken();
	}
	step = STEP_DONE;
	return GE_SUCCESS;
}

int ZhongCai::p_boot(int &step, int currentPlayerID)
{
	if (currentPlayerID != id)
		return GE_SUCCESS;
	int ret;
	if (tap)
	{
		step = YI_SHI_ZHONG_DUAN;
		ret = YiShiZhongDuan();
		if(toNextStep(ret) || ret == GE_URGENT){
			//ȫstepSTEP_DONE
			step = STEP_DONE;
		}
		return ret;
	}
	else if (gem > 0)
	{
		step = ZHONG_CAI_YI_SHI;
		ret = ZhongCaiYiShi();
		if(toNextStep(ret) || ret == GE_URGENT){
			//ȫstepSTEP_DONE
			step = STEP_DONE;
		}
		return ret;
	}
	return GE_SUCCESS;
}

int ZhongCai::p_timeline_6_drawn(int &step, CONTEXT_TIMELINE_6_DRAWN *con)
{
	if (con->dstID != id || con->harm.type == HARM_NONE)
		return GE_SUCCESS;
	int ret = ShenPanLangChao();
	step = STEP_DONE;
	return ret;
}

int ZhongCai::v_allow_action(Action* action, int allow, bool canGiveUp)
{
	if (token[0] < 4)
		return PlayerEntity::v_allow_action(action, allow, canGiveUp);

	if(canGiveUp && action->action_type() == ACTION_NONE)
		return GE_SUCCESS;

	if (action->action_type() != ACTION_MAGIC_SKILL || action->action_id() != MO_RI_SHEN_PAN)
		return GE_INVALID_ACTION;

	return GE_SUCCESS;
}

int ZhongCai::v_magic_skill(Action* action)
{
	int actionID = action->action_id();
	int playerID = action->src_id();
	PlayerEntity* dst;

	if(playerID != id){
		return GE_INVALID_PLAYERID;
	}

	switch(actionID)
	{
	case MO_RI_SHEN_PAN:
		//  û
		if (token[0] == 0){
			return GE_INVALID_ACTION;
		}
		break;
	case PAN_JUE_TIAN_PING:
		//          || ©˲               || û
		if (token[0] == 4 || action->args_size() == 0 || crystal + gem == 0){
			return GE_INVALID_ACTION;
		}
		break;
	default:
		return GE_INVALID_ACTION;
	}
	return GE_SUCCESS;
}

int ZhongCai::p_magic_skill(int &step, Action *action)
{
	int actionID = action->action_id();
	int ret;

	switch(actionID)
	{
	case MO_RI_SHEN_PAN:
		ret = MoRiShenPan(action);
		if (ret == GE_URGENT)
			step = STEP_DONE;
		break;
	case PAN_JUE_TIAN_PING:
		ret = PanJueTianPing(action);
		if (ret == GE_URGENT)
			step = STEP_DONE;
		break;
	default:
		return GE_INVALID_ACTION;
	}
	return ret;
}

int ZhongCai::YiShiZhongDuan()
{
	CommandRequest cmd_req;
	int ret;
	Coder::askForSkill(id, YI_SHI_ZHONG_DUAN, cmd_req);
	Command *cmd = (Command*)(&cmd_req.commands(cmd_req.commands_size()-1));
	//޵ȴUserTasktryNotify
	if(engine->waitForOne(id, network::MSG_CMD_REQ, cmd_req))
	{
		void* reply;
		if (GE_SUCCESS == (ret = engine->getReply(id, reply)))
		{
			Respond* respond = (Respond*) reply;
			if (respond->args_size()>0 && respond->args(0) == 1)
			{
				SkillMsg skill_msg;
				Coder::skillNotice(id, id, YI_SHI_ZHONG_DUAN, skill_msg);
				engine->sendMessage(-1, MSG_SKILL, skill_msg);

				TeamArea* team_area = engine->getTeamArea();
				team_area->setGem(color, team_area->getGem(color)+1);
				tap = false;

				GameInfo game_info;
				Coder::stoneNotice(color, team_area->getGem(color), team_area->getCrystal(color), game_info);
				Coder::tapNotice(id, tap, game_info);
				engine->sendMessage(-1, MSG_GAME, game_info);

				engine->setStateChangeMaxHand(id, true, false, 6, 0);
				return GE_URGENT;
			}
		}
	}
	else{
		return GE_TIMEOUT;
	}
	return GE_SUCCESS;
}

int ZhongCai::ZhongCaiYiShi()
{
	CommandRequest cmd_req;
	int ret;
	Coder::askForSkill(id, ZHONG_CAI_YI_SHI, cmd_req);
	Command *cmd = (Command*)(&cmd_req.commands(cmd_req.commands_size()-1));
	//޵ȴUserTasktryNotify
	if(engine->waitForOne(id, network::MSG_CMD_REQ, cmd_req))
	{
		void* reply;
		if (GE_SUCCESS == (ret = engine->getReply(id, reply)))
		{
			Respond* respond = (Respond*) reply;
			if (respond->args_size()>0 && respond->args(0) == 1)
			{
				SkillMsg skill_msg;
				Coder::skillNotice(id, id, ZHONG_CAI_YI_SHI, skill_msg);
				engine->sendMessage(-1, MSG_SKILL, skill_msg);

				setGem(gem-1);
				tap = true;

				GameInfo game_info;
				Coder::tapNotice(id, tap, game_info);
				Coder::energyNotice(id, gem, crystal, game_info);
				engine->sendMessage(-1, MSG_GAME, game_info);

				engine->setStateChangeMaxHand(id, true, true, 5, 0);
				return GE_URGENT;
			}
		}
	}
	else{
		return GE_TIMEOUT;
	}
	return GE_SUCCESS;
}

int ZhongCai::MoRiShenPan(Action* action)
{
	SkillMsg skill_msg;
	Coder::skillNotice(id, id, MO_RI_SHEN_PAN, skill_msg);
	engine->sendMessage(-1, MSG_SKILL, skill_msg);

	HARM shenpan;
	shenpan.cause = MO_RI_SHEN_PAN;
	shenpan.point = token[0];
	shenpan.srcID = id;
	shenpan.type = HARM_MAGIC;
	engine->setStateTimeline3(action->dst_ids(0), shenpan);

	setToken(0, 0);

	GameInfo game_info;
	Coder::tokenNotice(id, 0, token[0], game_info);
	engine->sendMessage(-1, MSG_GAME, game_info);
	return GE_URGENT;
}

int ZhongCai::ShenPanLangChao()
{
	SkillMsg skill_msg;
	Coder::skillNotice(id, id, SHEN_PAN_LANG_CHAO, skill_msg);
	engine->sendMessage(-1, MSG_SKILL, skill_msg);

	setToken(0, token[0]+1);

	GameInfo game_info;
	Coder::tokenNotice(id, 0, token[0], game_info);
	engine->sendMessage(-1, MSG_GAME, game_info);

	return GE_SUCCESS;
}

int ZhongCai::PanJueTianPing(Action* action)
{
	//
	if (crystal > 0)
		setCrystal(crystal-1);
	else
		setGem(gem-1);

	// +1
	setToken(0, token[0]+1);
	SkillMsg skill_msg;
	Coder::skillNotice(id, id, PAN_JUE_TIAN_PING, skill_msg);
	engine->sendMessage(-1, MSG_SKILL, skill_msg);

	GameInfo game_info;
	Coder::energyNotice(id, gem, crystal, game_info);
	Coder::tokenNotice(id, 0, token[0], game_info);

	if (action->args(0) == 0)
	{
		vector<int> hands;
		list<int>::iterator hand_card_it;
		for (hand_card_it=handCards.begin(); hand_card_it!=handCards.end(); ++hand_card_it)
			hands.push_back(*hand_card_it);
		//
		engine->setStateMoveCardsNotToHand(id, DECK_HAND, -1, DECK_DISCARD, handCards.size(), hands, id, PAN_JUE_TIAN_PING, false);
	}
	else
	{
		//
		if (handCardsMax > handCards.size())
		{
			vector<int> cards;
			HARM tianping;
			tianping.cause = PAN_JUE_TIAN_PING;
			tianping.point = handCardsMax-handCards.size();
			tianping.srcID = id;
			tianping.type = HARM_NONE;
			engine->setStateMoveCardsToHand(-1, DECK_PILE, id, DECK_HAND, handCardsMax-handCards.size(), cards, tianping, false);
		}
		// ս+1ʯ
		TeamArea* team_area = engine->getTeamArea();
		team_area->setGem(color, team_area->getGem(color)+1);

		Coder::stoneNotice(color, team_area->getGem(color), team_area->getCrystal(color), game_info);
	}

	engine->sendMessage(-1, MSG_GAME, game_info);
	return GE_URGENT;
}

int ZhongCai::ZhongCaiYiShiAddToken()
{
	setToken(0, token[0]+1);

	GameInfo game_info;
	Coder::tokenNotice(id, 0, token[0], game_info);
	engine->sendMessage(-1, MSG_GAME, game_info);
	return GE_SUCCESS;
}<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"

#include "OgreException.h"
#include "OgreLogManager.h"
#include "OgreRoot.h"
#include "OgreStringConverter.h"

#include "OgreGLRenderSystem.h"

#include "OgreGLXRenderTexture.h"
#include "OgreGLXContext.h"
#include "OgreGLXUtils.h"
#include "OgreGLXGLSupport.h"
#include <iostream>

namespace Ogre
{
	//-------------------------------------------------------------------------------------------------//
	GLXPBuffer::GLXPBuffer(GLXGLSupport* glsupport, PixelComponentType format, size_t width, size_t height):
		mGLSupport(glsupport), GLPBuffer(format, width, height), mContext(0)
	{
		Display *glDisplay = mGLSupport->getGLDisplay();
		::GLXDrawable glxDrawable = 0;
		::GLXFBConfig fbConfig = 0;

		bool isFloat = false;
		int bits = 0;

		switch (mFormat)
		{
		case PCT_BYTE:
			bits = 8;
			break;

		case PCT_SHORT:
			bits = 16;
			break;

		case PCT_FLOAT16:
			bits = 16;
			break;

		case PCT_FLOAT32:
			bits = 32;
			break;

		default:
			break;
		}

		int renderAttrib = GLX_RENDER_TYPE;
		int renderValue  = GLX_RGBA_BIT;

		if (mFormat == PCT_FLOAT16 || mFormat == PCT_FLOAT32)
		{
			if (GLXEW_NV_float_buffer)
			{
				renderAttrib = GLX_FLOAT_COMPONENTS_NV;
				renderValue  = GL_TRUE;
			}

			if (GLXEW_ATI_pixel_format_float)
			{
				renderAttrib = GLX_RENDER_TYPE;
				renderValue  = GLX_RGBA_FLOAT_ATI_BIT;
			}

			if (GLXEW_ARB_fbconfig_float)
			{
				renderAttrib = GLX_RENDER_TYPE;
				renderValue  = GLX_RGBA_FLOAT_BIT;
			}

			if (renderAttrib == GLX_RENDER_TYPE && renderValue == GLX_RGBA_BIT)
			{
				OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "No support for Floating point PBuffers",  "GLRenderTexture::createPBuffer");
			}
		}

		int minAttribs[] = {
			GLX_DRAWABLE_TYPE, GLX_PBUFFER,
			renderAttrib,	  renderValue,
			GLX_DOUBLEBUFFER,  0,
			None
		};

		int maxAttribs[] = {
			GLX_RED_SIZE,	  bits,
			GLX_GREEN_SIZE,	bits,
			GLX_BLUE_SIZE,	 bits,
			GLX_ALPHA_SIZE,	bits,
			GLX_STENCIL_SIZE,  INT_MAX,
			None
		};

		int pBufferAttribs[] = {
			GLX_PBUFFER_WIDTH,	  mWidth,
			GLX_PBUFFER_HEIGHT,	 mHeight,
			GLX_PRESERVED_CONTENTS, GL_TRUE,
			None
		};

		fbConfig = mGLSupport->selectFBConfig(minAttribs, maxAttribs);

		glxDrawable = glXCreatePbuffer(glDisplay, fbConfig, pBufferAttribs);

		if (! fbConfig || ! glxDrawable)
		{
			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to create Pbuffer", "GLXPBuffer::GLXPBuffer");
		}

		GLint fbConfigID;
		GLuint iWidth, iHeight;

		glXGetFBConfigAttrib(glDisplay, fbConfig, GLX_FBCONFIG_ID, &fbConfigID);
		glXQueryDrawable(glDisplay, glxDrawable, GLX_WIDTH, &iWidth);
		glXQueryDrawable(glDisplay, glxDrawable, GLX_HEIGHT, &iHeight);

		mWidth = iWidth;
		mHeight = iHeight;
		LogManager::getSingleton().logMessage(LML_NORMAL, "GLXPBuffer::create used final dimensions " + StringConverter::toString(mWidth) + " x " + StringConverter::toString(mHeight));
		LogManager::getSingleton().logMessage("GLXPBuffer::create used FBConfigID " + StringConverter::toString(fbConfigID));

		mContext = new GLXContext(mGLSupport, fbConfig, glxDrawable);
	}

	//-------------------------------------------------------------------------------------------------//
	GLXPBuffer::~GLXPBuffer()
	{
		glXDestroyPbuffer(mGLSupport->getGLDisplay(), mContext->mDrawable);

		delete mContext;

		LogManager::getSingleton().logMessage(LML_NORMAL, "GLXPBuffer::PBuffer destroyed");
	}

	//-------------------------------------------------------------------------------------------------//
	GLContext *GLXPBuffer::getContext()
	{
		return mContext;
	}
}
<commit_msg>Adding climits include to GLXRenderTexture, supposedly needed on some distros<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"

#include "OgreException.h"
#include "OgreLogManager.h"
#include "OgreRoot.h"
#include "OgreStringConverter.h"

#include "OgreGLRenderSystem.h"

#include "OgreGLXRenderTexture.h"
#include "OgreGLXContext.h"
#include "OgreGLXUtils.h"
#include "OgreGLXGLSupport.h"
#include <iostream>
#include <climits>

namespace Ogre
{
	//-------------------------------------------------------------------------------------------------//
	GLXPBuffer::GLXPBuffer(GLXGLSupport* glsupport, PixelComponentType format, size_t width, size_t height):
		mGLSupport(glsupport), GLPBuffer(format, width, height), mContext(0)
	{
		Display *glDisplay = mGLSupport->getGLDisplay();
		::GLXDrawable glxDrawable = 0;
		::GLXFBConfig fbConfig = 0;

		bool isFloat = false;
		int bits = 0;

		switch (mFormat)
		{
		case PCT_BYTE:
			bits = 8;
			break;

		case PCT_SHORT:
			bits = 16;
			break;

		case PCT_FLOAT16:
			bits = 16;
			break;

		case PCT_FLOAT32:
			bits = 32;
			break;

		default:
			break;
		}

		int renderAttrib = GLX_RENDER_TYPE;
		int renderValue  = GLX_RGBA_BIT;

		if (mFormat == PCT_FLOAT16 || mFormat == PCT_FLOAT32)
		{
			if (GLXEW_NV_float_buffer)
			{
				renderAttrib = GLX_FLOAT_COMPONENTS_NV;
				renderValue  = GL_TRUE;
			}

			if (GLXEW_ATI_pixel_format_float)
			{
				renderAttrib = GLX_RENDER_TYPE;
				renderValue  = GLX_RGBA_FLOAT_ATI_BIT;
			}

			if (GLXEW_ARB_fbconfig_float)
			{
				renderAttrib = GLX_RENDER_TYPE;
				renderValue  = GLX_RGBA_FLOAT_BIT;
			}

			if (renderAttrib == GLX_RENDER_TYPE && renderValue == GLX_RGBA_BIT)
			{
				OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "No support for Floating point PBuffers",  "GLRenderTexture::createPBuffer");
			}
		}

		int minAttribs[] = {
			GLX_DRAWABLE_TYPE, GLX_PBUFFER,
			renderAttrib,	  renderValue,
			GLX_DOUBLEBUFFER,  0,
			None
		};

		int maxAttribs[] = {
			GLX_RED_SIZE,	  bits,
			GLX_GREEN_SIZE,	bits,
			GLX_BLUE_SIZE,	 bits,
			GLX_ALPHA_SIZE,	bits,
			GLX_STENCIL_SIZE,  INT_MAX,
			None
		};

		int pBufferAttribs[] = {
			GLX_PBUFFER_WIDTH,	  mWidth,
			GLX_PBUFFER_HEIGHT,	 mHeight,
			GLX_PRESERVED_CONTENTS, GL_TRUE,
			None
		};

		fbConfig = mGLSupport->selectFBConfig(minAttribs, maxAttribs);

		glxDrawable = glXCreatePbuffer(glDisplay, fbConfig, pBufferAttribs);

		if (! fbConfig || ! glxDrawable)
		{
			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to create Pbuffer", "GLXPBuffer::GLXPBuffer");
		}

		GLint fbConfigID;
		GLuint iWidth, iHeight;

		glXGetFBConfigAttrib(glDisplay, fbConfig, GLX_FBCONFIG_ID, &fbConfigID);
		glXQueryDrawable(glDisplay, glxDrawable, GLX_WIDTH, &iWidth);
		glXQueryDrawable(glDisplay, glxDrawable, GLX_HEIGHT, &iHeight);

		mWidth = iWidth;
		mHeight = iHeight;
		LogManager::getSingleton().logMessage(LML_NORMAL, "GLXPBuffer::create used final dimensions " + StringConverter::toString(mWidth) + " x " + StringConverter::toString(mHeight));
		LogManager::getSingleton().logMessage("GLXPBuffer::create used FBConfigID " + StringConverter::toString(fbConfigID));

		mContext = new GLXContext(mGLSupport, fbConfig, glxDrawable);
	}

	//-------------------------------------------------------------------------------------------------//
	GLXPBuffer::~GLXPBuffer()
	{
		glXDestroyPbuffer(mGLSupport->getGLDisplay(), mContext->mDrawable);

		delete mContext;

		LogManager::getSingleton().logMessage(LML_NORMAL, "GLXPBuffer::PBuffer destroyed");
	}

	//-------------------------------------------------------------------------------------------------//
	GLContext *GLXPBuffer::getContext()
	{
		return mContext;
	}
}
<|endoftext|>


<commit_before>#include "VulkanQuad.h"

#include "Shaders.h"
#include "Utility.h"
#include "Window.h"

#include <vector>

namespace AMD {
///////////////////////////////////////////////////////////////////////////////
void VulkanQuad::ShutdownImpl ()
{
	vkDestroyPipeline (device_, pipeline_, nullptr);
	vkDestroyPipelineLayout (device_, pipelineLayout_, nullptr);

	vkDestroyBuffer (device_, vertexBuffer_, nullptr);
	vkDestroyBuffer (device_, indexBuffer_, nullptr);
	vkFreeMemory (device_, deviceMemory_, nullptr);

	vkDestroyShaderModule (device_, vertexShader_, nullptr);
	vkDestroyShaderModule (device_, fragmentShader_, nullptr);

	VulkanSample::ShutdownImpl ();
}

///////////////////////////////////////////////////////////////////////////////
void VulkanQuad::RenderImpl (VkCommandBuffer commandBuffer)
{
	VulkanSample::RenderImpl (commandBuffer);

	vkCmdBindPipeline (commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
		pipeline_);
	VkDeviceSize offsets [] = { 0 };
	vkCmdBindIndexBuffer (commandBuffer, indexBuffer_, 0, VK_INDEX_TYPE_UINT32);
	vkCmdBindVertexBuffers (commandBuffer, 0, 1, &vertexBuffer_, offsets);
	vkCmdDrawIndexed (commandBuffer, 6, 1, 0, 0, 0);
}

///////////////////////////////////////////////////////////////////////////////
void VulkanQuad::InitializeImpl (VkCommandBuffer uploadCommandBuffer)
{
	VulkanSample::InitializeImpl (uploadCommandBuffer);

	CreatePipelineStateObject ();
	CreateMeshBuffers (uploadCommandBuffer);
}

namespace {
struct MemoryTypeInfo
{
	bool deviceLocal = false;
	bool hostVisible = false;
	bool hostCoherent = false;
	bool hostCached = false;
	bool lazilyAllocated = false;

	struct Heap
	{
		uint64_t size = 0;
		bool deviceLocal = false;
	};

	Heap heap;
	int index;
};

///////////////////////////////////////////////////////////////////////////////
std::vector<MemoryTypeInfo> EnumerateHeaps (VkPhysicalDevice device)
{
	VkPhysicalDeviceMemoryProperties memoryProperties = {};
	vkGetPhysicalDeviceMemoryProperties (device, &memoryProperties);

	std::vector<MemoryTypeInfo::Heap> heaps;

	for (uint32_t i = 0; i < memoryProperties.memoryHeapCount; ++i) {
		MemoryTypeInfo::Heap info;
		info.size = memoryProperties.memoryHeaps [i].size;
		info.deviceLocal = (memoryProperties.memoryHeaps [i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0;

		heaps.push_back (info);
	}

	std::vector<MemoryTypeInfo> result;

	for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) {
		MemoryTypeInfo typeInfo;

		typeInfo.deviceLocal = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0;
		typeInfo.hostVisible = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
		typeInfo.hostCoherent = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0;
		typeInfo.hostCached = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0;
		typeInfo.lazilyAllocated = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0;

		typeInfo.heap = heaps [memoryProperties.memoryTypes [i].heapIndex];

		typeInfo.index = static_cast<int> (i);

		result.push_back (typeInfo);
	}

	return result;
}

///////////////////////////////////////////////////////////////////////////////
VkDeviceMemory AllocateMemory (const std::vector<MemoryTypeInfo>& memoryInfos,
	VkDevice device, const int size)
{
	// We take the first HOST_VISIBLE memory
	for (auto& memoryInfo : memoryInfos) {
		if (memoryInfo.hostVisible) {
			VkMemoryAllocateInfo memoryAllocateInfo = {};
			memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
			memoryAllocateInfo.memoryTypeIndex = memoryInfo.index;
			memoryAllocateInfo.allocationSize = size;

			VkDeviceMemory deviceMemory;
			vkAllocateMemory (device, &memoryAllocateInfo, nullptr,
				&deviceMemory);
			return deviceMemory;
		}
	}

	return VK_NULL_HANDLE;
}

///////////////////////////////////////////////////////////////////////////////
VkBuffer AllocateBuffer (VkDevice device, const int size,
	const VkBufferUsageFlagBits bits)
{
	VkBufferCreateInfo bufferCreateInfo = {};
	bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
	bufferCreateInfo.size = static_cast<uint32_t> (size);
	bufferCreateInfo.usage = bits;

	VkBuffer result;
	vkCreateBuffer (device, &bufferCreateInfo, nullptr, &result);
	return result;
}

///////////////////////////////////////////////////////////////////////////////
VkPipelineLayout CreatePipelineLayout (VkDevice device)
{
	VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {};
	pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;

	VkPipelineLayout result;
	vkCreatePipelineLayout (device, &pipelineLayoutCreateInfo, nullptr,
		&result);

	return result;
}

///////////////////////////////////////////////////////////////////////////////
VkShaderModule LoadShader (VkDevice device, const void* shaderContents,
	const size_t size)
{
	VkShaderModuleCreateInfo shaderModuleCreateInfo = {};
	shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;

	shaderModuleCreateInfo.pCode = static_cast<const uint32_t*> (shaderContents);
	shaderModuleCreateInfo.codeSize = size;

	VkShaderModule result;
	vkCreateShaderModule (device, &shaderModuleCreateInfo, nullptr, &result);

	return result;
}

///////////////////////////////////////////////////////////////////////////////
VkPipeline CreatePipeline (VkDevice device, VkRenderPass renderPass, VkPipelineLayout layout,
	VkShaderModule vertexShader, VkShaderModule fragmentShader,
	VkExtent2D viewportSize)
{
	VkVertexInputBindingDescription vertexInputBindingDescription;
	vertexInputBindingDescription.binding = 0;
	vertexInputBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
	vertexInputBindingDescription.stride = sizeof (float) * 5;

	VkVertexInputAttributeDescription vertexInputAttributeDescription [2] = {};
	vertexInputAttributeDescription [0].binding = vertexInputBindingDescription.binding;
	vertexInputAttributeDescription [0].format = VK_FORMAT_R32G32B32_SFLOAT;
	vertexInputAttributeDescription [0].location = 0;
	vertexInputAttributeDescription [0].offset = 0;

	vertexInputAttributeDescription [1].binding = vertexInputBindingDescription.binding;
	vertexInputAttributeDescription [1].format = VK_FORMAT_R32G32_SFLOAT;
	vertexInputAttributeDescription [1].location = 1;
	vertexInputAttributeDescription [1].offset = sizeof (float) * 3;

	VkPipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = {};
	pipelineVertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
	pipelineVertexInputStateCreateInfo.vertexAttributeDescriptionCount = std::extent<decltype(vertexInputAttributeDescription)>::value;
	pipelineVertexInputStateCreateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescription;
	pipelineVertexInputStateCreateInfo.vertexBindingDescriptionCount = 1;
	pipelineVertexInputStateCreateInfo.pVertexBindingDescriptions = &vertexInputBindingDescription;

	VkPipelineInputAssemblyStateCreateInfo  pipelineInputAssemblyStateCreateInfo = {};
	pipelineInputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
	pipelineInputAssemblyStateCreateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;

	VkPipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = {};
	pipelineViewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;

	VkViewport viewport;
	viewport.height = static_cast<float> (viewportSize.height);
	viewport.width = static_cast<float> (viewportSize.width);
	viewport.x = 0;
	viewport.y = 0;
	viewport.minDepth = 0;
	viewport.maxDepth = 1;

	pipelineViewportStateCreateInfo.viewportCount = 1;
	pipelineViewportStateCreateInfo.pViewports = &viewport;

	VkRect2D rect;
	rect.extent = viewportSize;
	rect.offset.x = 0;
	rect.offset.y = 0;

	pipelineViewportStateCreateInfo.scissorCount = 1;
	pipelineViewportStateCreateInfo.pScissors = ▭

	VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = {};
	pipelineColorBlendAttachmentState.colorWriteMask = 0xF;
	pipelineColorBlendAttachmentState.blendEnable = VK_FALSE;

	VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo = {};
	pipelineColorBlendStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;

	pipelineColorBlendStateCreateInfo.attachmentCount = 1;
	pipelineColorBlendStateCreateInfo.pAttachments = &pipelineColorBlendAttachmentState;

	VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo = {};
	pipelineRasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
	pipelineRasterizationStateCreateInfo.polygonMode = VK_POLYGON_MODE_FILL;
	pipelineRasterizationStateCreateInfo.cullMode = VK_CULL_MODE_NONE;
	pipelineRasterizationStateCreateInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
	pipelineRasterizationStateCreateInfo.depthClampEnable = VK_FALSE;
	pipelineRasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE;
	pipelineRasterizationStateCreateInfo.depthBiasEnable = VK_FALSE;

	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo = {};
	pipelineDepthStencilStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
	pipelineDepthStencilStateCreateInfo.depthTestEnable = VK_FALSE;
	pipelineDepthStencilStateCreateInfo.depthWriteEnable = VK_FALSE;
	pipelineDepthStencilStateCreateInfo.depthCompareOp = VK_COMPARE_OP_ALWAYS;
	pipelineDepthStencilStateCreateInfo.depthBoundsTestEnable = VK_FALSE;
	pipelineDepthStencilStateCreateInfo.back.failOp = VK_STENCIL_OP_KEEP;
	pipelineDepthStencilStateCreateInfo.back.passOp = VK_STENCIL_OP_KEEP;
	pipelineDepthStencilStateCreateInfo.back.compareOp = VK_COMPARE_OP_ALWAYS;
	pipelineDepthStencilStateCreateInfo.stencilTestEnable = VK_FALSE;
	pipelineDepthStencilStateCreateInfo.front = pipelineDepthStencilStateCreateInfo.back;

	VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = {};
	pipelineMultisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
	pipelineMultisampleStateCreateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;

	VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfos [2] = {};
	pipelineShaderStageCreateInfos [0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
	pipelineShaderStageCreateInfos [0].module = vertexShader;
	pipelineShaderStageCreateInfos [0].pName = "main";
	pipelineShaderStageCreateInfos [0].stage = VK_SHADER_STAGE_VERTEX_BIT;

	pipelineShaderStageCreateInfos [1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
	pipelineShaderStageCreateInfos [1].module = fragmentShader;
	pipelineShaderStageCreateInfos [1].pName = "main";
	pipelineShaderStageCreateInfos [1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;

	VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo = {};
	graphicsPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;

	graphicsPipelineCreateInfo.layout = layout;
	graphicsPipelineCreateInfo.pVertexInputState = &pipelineVertexInputStateCreateInfo;
	graphicsPipelineCreateInfo.pInputAssemblyState = &pipelineInputAssemblyStateCreateInfo;
	graphicsPipelineCreateInfo.renderPass = renderPass;
	graphicsPipelineCreateInfo.pViewportState = &pipelineViewportStateCreateInfo;
	graphicsPipelineCreateInfo.pColorBlendState = &pipelineColorBlendStateCreateInfo;
	graphicsPipelineCreateInfo.pRasterizationState = &pipelineRasterizationStateCreateInfo;
	graphicsPipelineCreateInfo.pDepthStencilState = &pipelineDepthStencilStateCreateInfo;
	graphicsPipelineCreateInfo.pMultisampleState = &pipelineMultisampleStateCreateInfo;
	graphicsPipelineCreateInfo.pStages = pipelineShaderStageCreateInfos;
	graphicsPipelineCreateInfo.stageCount = 2;

	VkPipeline pipeline;
	vkCreateGraphicsPipelines (device, VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo,
		nullptr, &pipeline);

	return pipeline;
}
}

///////////////////////////////////////////////////////////////////////////////
void VulkanQuad::CreateMeshBuffers (VkCommandBuffer /*uploadCommandBuffer*/)
{
	struct Vertex
	{
		float position[3];
		float uv[2];
	};

	static const Vertex vertices[4] = {
		// Upper Left
		{ { -1.0f, 1.0f, 0 },{ 0, 0 } },
		// Upper Right
		{ { 1.0f, 1.0f, 0 },{ 1, 0 } },
		// Bottom right
		{ { 1.0f, -1.0f, 0 },{ 1, 1 } },
		// Bottom left
		{ { -1.0f, -1.0f, 0 },{ 0, 1 } }
	};

	static const int indices[6] = {
		0, 1, 2, 2, 3, 0
	};

	auto memoryHeaps = EnumerateHeaps (physicalDevice_);

	indexBuffer_ = AllocateBuffer (device_, sizeof (indices),
		VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
	vertexBuffer_ = AllocateBuffer (device_, sizeof (vertices),
		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);

	// We want to store the index buffer behind the vertex buffer, so we need
	// to know the alignment
	VkMemoryRequirements vertexBufferMemoryRequirements = {};
	vkGetBufferMemoryRequirements (device_, vertexBuffer_,
		&vertexBufferMemoryRequirements);
	VkMemoryRequirements indexBufferMemoryRequirements = {};
	vkGetBufferMemoryRequirements (device_, indexBuffer_,
		&indexBufferMemoryRequirements);

	VkDeviceSize bufferSize = vertexBufferMemoryRequirements.size;
	// We want to place the index buffer behind it - round up to the next
	// alignment which allows that
	VkDeviceSize indexBufferOffset = RoundToNextMultiple (bufferSize,
		indexBufferMemoryRequirements.alignment);
	bufferSize = indexBufferOffset + indexBufferMemoryRequirements.size;

	deviceMemory_ = AllocateMemory (memoryHeaps, device_,
		static_cast<int>(bufferSize));
	vkBindBufferMemory (device_, vertexBuffer_, deviceMemory_, 0);
	vkBindBufferMemory (device_, indexBuffer_, deviceMemory_,
		indexBufferOffset);

	void* mapping = nullptr;
	vkMapMemory (device_, deviceMemory_, 0, VK_WHOLE_SIZE,
		0, &mapping);
	::memcpy (mapping, vertices, sizeof (vertices));

	::memcpy (static_cast<uint8_t*> (mapping) + indexBufferOffset,
		indices, sizeof (indices));
	vkUnmapMemory (device_, deviceMemory_);
}

///////////////////////////////////////////////////////////////////////////////
void VulkanQuad::CreatePipelineStateObject ()
{
	vertexShader_ = LoadShader (device_, BasicVertexShader, sizeof (BasicVertexShader));
	fragmentShader_ = LoadShader (device_, BasicFragmentShader, sizeof (BasicFragmentShader));

	pipelineLayout_ = CreatePipelineLayout (device_);
	pipeline_ = CreatePipeline (device_, renderPass_, pipelineLayout_,
		vertexShader_, fragmentShader_,
		VkExtent2D{
		static_cast<uint32_t> (window_->GetWidth ()),
		static_cast<uint32_t> (window_->GetHeight ())
	}
	);
}
}<commit_msg>Clarify the alignment handling.<commit_after>#include "VulkanQuad.h"

#include "Shaders.h"
#include "Utility.h"
#include "Window.h"

#include <vector>

namespace AMD {
///////////////////////////////////////////////////////////////////////////////
void VulkanQuad::ShutdownImpl ()
{
	vkDestroyPipeline (device_, pipeline_, nullptr);
	vkDestroyPipelineLayout (device_, pipelineLayout_, nullptr);

	vkDestroyBuffer (device_, vertexBuffer_, nullptr);
	vkDestroyBuffer (device_, indexBuffer_, nullptr);
	vkFreeMemory (device_, deviceMemory_, nullptr);

	vkDestroyShaderModule (device_, vertexShader_, nullptr);
	vkDestroyShaderModule (device_, fragmentShader_, nullptr);

	VulkanSample::ShutdownImpl ();
}

///////////////////////////////////////////////////////////////////////////////
void VulkanQuad::RenderImpl (VkCommandBuffer commandBuffer)
{
	VulkanSample::RenderImpl (commandBuffer);

	vkCmdBindPipeline (commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
		pipeline_);
	VkDeviceSize offsets [] = { 0 };
	vkCmdBindIndexBuffer (commandBuffer, indexBuffer_, 0, VK_INDEX_TYPE_UINT32);
	vkCmdBindVertexBuffers (commandBuffer, 0, 1, &vertexBuffer_, offsets);
	vkCmdDrawIndexed (commandBuffer, 6, 1, 0, 0, 0);
}

///////////////////////////////////////////////////////////////////////////////
void VulkanQuad::InitializeImpl (VkCommandBuffer uploadCommandBuffer)
{
	VulkanSample::InitializeImpl (uploadCommandBuffer);

	CreatePipelineStateObject ();
	CreateMeshBuffers (uploadCommandBuffer);
}

namespace {
struct MemoryTypeInfo
{
	bool deviceLocal = false;
	bool hostVisible = false;
	bool hostCoherent = false;
	bool hostCached = false;
	bool lazilyAllocated = false;

	struct Heap
	{
		uint64_t size = 0;
		bool deviceLocal = false;
	};

	Heap heap;
	int index;
};

///////////////////////////////////////////////////////////////////////////////
std::vector<MemoryTypeInfo> EnumerateHeaps (VkPhysicalDevice device)
{
	VkPhysicalDeviceMemoryProperties memoryProperties = {};
	vkGetPhysicalDeviceMemoryProperties (device, &memoryProperties);

	std::vector<MemoryTypeInfo::Heap> heaps;

	for (uint32_t i = 0; i < memoryProperties.memoryHeapCount; ++i) {
		MemoryTypeInfo::Heap info;
		info.size = memoryProperties.memoryHeaps [i].size;
		info.deviceLocal = (memoryProperties.memoryHeaps [i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0;

		heaps.push_back (info);
	}

	std::vector<MemoryTypeInfo> result;

	for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) {
		MemoryTypeInfo typeInfo;

		typeInfo.deviceLocal = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0;
		typeInfo.hostVisible = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
		typeInfo.hostCoherent = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0;
		typeInfo.hostCached = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0;
		typeInfo.lazilyAllocated = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0;

		typeInfo.heap = heaps [memoryProperties.memoryTypes [i].heapIndex];

		typeInfo.index = static_cast<int> (i);

		result.push_back (typeInfo);
	}

	return result;
}

///////////////////////////////////////////////////////////////////////////////
VkDeviceMemory AllocateMemory (const std::vector<MemoryTypeInfo>& memoryInfos,
	VkDevice device, const int size)
{
	// We take the first HOST_VISIBLE memory
	for (auto& memoryInfo : memoryInfos) {
		if (memoryInfo.hostVisible) {
			VkMemoryAllocateInfo memoryAllocateInfo = {};
			memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
			memoryAllocateInfo.memoryTypeIndex = memoryInfo.index;
			memoryAllocateInfo.allocationSize = size;

			VkDeviceMemory deviceMemory;
			vkAllocateMemory (device, &memoryAllocateInfo, nullptr,
				&deviceMemory);
			return deviceMemory;
		}
	}

	return VK_NULL_HANDLE;
}

///////////////////////////////////////////////////////////////////////////////
VkBuffer AllocateBuffer (VkDevice device, const int size,
	const VkBufferUsageFlagBits bits)
{
	VkBufferCreateInfo bufferCreateInfo = {};
	bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
	bufferCreateInfo.size = static_cast<uint32_t> (size);
	bufferCreateInfo.usage = bits;

	VkBuffer result;
	vkCreateBuffer (device, &bufferCreateInfo, nullptr, &result);
	return result;
}

///////////////////////////////////////////////////////////////////////////////
VkPipelineLayout CreatePipelineLayout (VkDevice device)
{
	VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {};
	pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;

	VkPipelineLayout result;
	vkCreatePipelineLayout (device, &pipelineLayoutCreateInfo, nullptr,
		&result);

	return result;
}

///////////////////////////////////////////////////////////////////////////////
VkShaderModule LoadShader (VkDevice device, const void* shaderContents,
	const size_t size)
{
	VkShaderModuleCreateInfo shaderModuleCreateInfo = {};
	shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;

	shaderModuleCreateInfo.pCode = static_cast<const uint32_t*> (shaderContents);
	shaderModuleCreateInfo.codeSize = size;

	VkShaderModule result;
	vkCreateShaderModule (device, &shaderModuleCreateInfo, nullptr, &result);

	return result;
}

///////////////////////////////////////////////////////////////////////////////
VkPipeline CreatePipeline (VkDevice device, VkRenderPass renderPass, VkPipelineLayout layout,
	VkShaderModule vertexShader, VkShaderModule fragmentShader,
	VkExtent2D viewportSize)
{
	VkVertexInputBindingDescription vertexInputBindingDescription;
	vertexInputBindingDescription.binding = 0;
	vertexInputBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
	vertexInputBindingDescription.stride = sizeof (float) * 5;

	VkVertexInputAttributeDescription vertexInputAttributeDescription [2] = {};
	vertexInputAttributeDescription [0].binding = vertexInputBindingDescription.binding;
	vertexInputAttributeDescription [0].format = VK_FORMAT_R32G32B32_SFLOAT;
	vertexInputAttributeDescription [0].location = 0;
	vertexInputAttributeDescription [0].offset = 0;

	vertexInputAttributeDescription [1].binding = vertexInputBindingDescription.binding;
	vertexInputAttributeDescription [1].format = VK_FORMAT_R32G32_SFLOAT;
	vertexInputAttributeDescription [1].location = 1;
	vertexInputAttributeDescription [1].offset = sizeof (float) * 3;

	VkPipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = {};
	pipelineVertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
	pipelineVertexInputStateCreateInfo.vertexAttributeDescriptionCount = std::extent<decltype(vertexInputAttributeDescription)>::value;
	pipelineVertexInputStateCreateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescription;
	pipelineVertexInputStateCreateInfo.vertexBindingDescriptionCount = 1;
	pipelineVertexInputStateCreateInfo.pVertexBindingDescriptions = &vertexInputBindingDescription;

	VkPipelineInputAssemblyStateCreateInfo  pipelineInputAssemblyStateCreateInfo = {};
	pipelineInputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
	pipelineInputAssemblyStateCreateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;

	VkPipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = {};
	pipelineViewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;

	VkViewport viewport;
	viewport.height = static_cast<float> (viewportSize.height);
	viewport.width = static_cast<float> (viewportSize.width);
	viewport.x = 0;
	viewport.y = 0;
	viewport.minDepth = 0;
	viewport.maxDepth = 1;

	pipelineViewportStateCreateInfo.viewportCount = 1;
	pipelineViewportStateCreateInfo.pViewports = &viewport;

	VkRect2D rect;
	rect.extent = viewportSize;
	rect.offset.x = 0;
	rect.offset.y = 0;

	pipelineViewportStateCreateInfo.scissorCount = 1;
	pipelineViewportStateCreateInfo.pScissors = ▭

	VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = {};
	pipelineColorBlendAttachmentState.colorWriteMask = 0xF;
	pipelineColorBlendAttachmentState.blendEnable = VK_FALSE;

	VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo = {};
	pipelineColorBlendStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;

	pipelineColorBlendStateCreateInfo.attachmentCount = 1;
	pipelineColorBlendStateCreateInfo.pAttachments = &pipelineColorBlendAttachmentState;

	VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo = {};
	pipelineRasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
	pipelineRasterizationStateCreateInfo.polygonMode = VK_POLYGON_MODE_FILL;
	pipelineRasterizationStateCreateInfo.cullMode = VK_CULL_MODE_NONE;
	pipelineRasterizationStateCreateInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
	pipelineRasterizationStateCreateInfo.depthClampEnable = VK_FALSE;
	pipelineRasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE;
	pipelineRasterizationStateCreateInfo.depthBiasEnable = VK_FALSE;

	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo = {};
	pipelineDepthStencilStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
	pipelineDepthStencilStateCreateInfo.depthTestEnable = VK_FALSE;
	pipelineDepthStencilStateCreateInfo.depthWriteEnable = VK_FALSE;
	pipelineDepthStencilStateCreateInfo.depthCompareOp = VK_COMPARE_OP_ALWAYS;
	pipelineDepthStencilStateCreateInfo.depthBoundsTestEnable = VK_FALSE;
	pipelineDepthStencilStateCreateInfo.back.failOp = VK_STENCIL_OP_KEEP;
	pipelineDepthStencilStateCreateInfo.back.passOp = VK_STENCIL_OP_KEEP;
	pipelineDepthStencilStateCreateInfo.back.compareOp = VK_COMPARE_OP_ALWAYS;
	pipelineDepthStencilStateCreateInfo.stencilTestEnable = VK_FALSE;
	pipelineDepthStencilStateCreateInfo.front = pipelineDepthStencilStateCreateInfo.back;

	VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = {};
	pipelineMultisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
	pipelineMultisampleStateCreateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;

	VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfos [2] = {};
	pipelineShaderStageCreateInfos [0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
	pipelineShaderStageCreateInfos [0].module = vertexShader;
	pipelineShaderStageCreateInfos [0].pName = "main";
	pipelineShaderStageCreateInfos [0].stage = VK_SHADER_STAGE_VERTEX_BIT;

	pipelineShaderStageCreateInfos [1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
	pipelineShaderStageCreateInfos [1].module = fragmentShader;
	pipelineShaderStageCreateInfos [1].pName = "main";
	pipelineShaderStageCreateInfos [1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;

	VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo = {};
	graphicsPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;

	graphicsPipelineCreateInfo.layout = layout;
	graphicsPipelineCreateInfo.pVertexInputState = &pipelineVertexInputStateCreateInfo;
	graphicsPipelineCreateInfo.pInputAssemblyState = &pipelineInputAssemblyStateCreateInfo;
	graphicsPipelineCreateInfo.renderPass = renderPass;
	graphicsPipelineCreateInfo.pViewportState = &pipelineViewportStateCreateInfo;
	graphicsPipelineCreateInfo.pColorBlendState = &pipelineColorBlendStateCreateInfo;
	graphicsPipelineCreateInfo.pRasterizationState = &pipelineRasterizationStateCreateInfo;
	graphicsPipelineCreateInfo.pDepthStencilState = &pipelineDepthStencilStateCreateInfo;
	graphicsPipelineCreateInfo.pMultisampleState = &pipelineMultisampleStateCreateInfo;
	graphicsPipelineCreateInfo.pStages = pipelineShaderStageCreateInfos;
	graphicsPipelineCreateInfo.stageCount = 2;

	VkPipeline pipeline;
	vkCreateGraphicsPipelines (device, VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo,
		nullptr, &pipeline);

	return pipeline;
}
}

///////////////////////////////////////////////////////////////////////////////
void VulkanQuad::CreateMeshBuffers (VkCommandBuffer /*uploadCommandBuffer*/)
{
	struct Vertex
	{
		float position[3];
		float uv[2];
	};

	static const Vertex vertices[4] = {
		// Upper Left
		{ { -1.0f, 1.0f, 0 },{ 0, 0 } },
		// Upper Right
		{ { 1.0f, 1.0f, 0 },{ 1, 0 } },
		// Bottom right
		{ { 1.0f, -1.0f, 0 },{ 1, 1 } },
		// Bottom left
		{ { -1.0f, -1.0f, 0 },{ 0, 1 } }
	};

	static const int indices[6] = {
		0, 1, 2, 2, 3, 0
	};

	auto memoryHeaps = EnumerateHeaps (physicalDevice_);

	indexBuffer_ = AllocateBuffer (device_, sizeof (indices),
		VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
	vertexBuffer_ = AllocateBuffer (device_, sizeof (vertices),
		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);

	VkMemoryRequirements vertexBufferMemoryRequirements = {};
	vkGetBufferMemoryRequirements (device_, vertexBuffer_,
		&vertexBufferMemoryRequirements);
	VkMemoryRequirements indexBufferMemoryRequirements = {};
	vkGetBufferMemoryRequirements (device_, indexBuffer_,
		&indexBufferMemoryRequirements);

	VkDeviceSize bufferSize = vertexBufferMemoryRequirements.size;
	// We want to place the index buffer behind the vertex buffer. Need to take
	// the alignment into account to find the next suitable location
	VkDeviceSize indexBufferOffset = RoundToNextMultiple (bufferSize,
		indexBufferMemoryRequirements.alignment);

	bufferSize = indexBufferOffset + indexBufferMemoryRequirements.size;
	deviceMemory_ = AllocateMemory (memoryHeaps, device_,
		static_cast<int>(bufferSize));

	vkBindBufferMemory (device_, vertexBuffer_, deviceMemory_, 0);
	vkBindBufferMemory (device_, indexBuffer_, deviceMemory_,
		indexBufferOffset);

	void* mapping = nullptr;
	vkMapMemory (device_, deviceMemory_, 0, VK_WHOLE_SIZE,
		0, &mapping);
	::memcpy (mapping, vertices, sizeof (vertices));

	::memcpy (static_cast<uint8_t*> (mapping) + indexBufferOffset,
		indices, sizeof (indices));
	vkUnmapMemory (device_, deviceMemory_);
}

///////////////////////////////////////////////////////////////////////////////
void VulkanQuad::CreatePipelineStateObject ()
{
	vertexShader_ = LoadShader (device_, BasicVertexShader, sizeof (BasicVertexShader));
	fragmentShader_ = LoadShader (device_, BasicFragmentShader, sizeof (BasicFragmentShader));

	pipelineLayout_ = CreatePipelineLayout (device_);
	pipeline_ = CreatePipeline (device_, renderPass_, pipelineLayout_,
		vertexShader_, fragmentShader_,
		VkExtent2D{
		static_cast<uint32_t> (window_->GetWidth ()),
		static_cast<uint32_t> (window_->GetHeight ())
	}
	);
}
}<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include "ROOT/THist.hxx"
#include "ROOT/TCanvas.hxx"
#include "ROOT/TColor.hxx"

class FixtureBase: public ::testing::Test {
protected:
   virtual void SetUp();
};

struct DrawTest: public FixtureBase {};

// Test drawing of histograms.
TEST_F(DrawTest, OneD)
{
   using namespace ROOT::Experimental;
   TAxisConfig xaxis{10, 0., 1.};
   auto h = std::make_shared<TH1D>(xaxis);
   TCanvas canv;
   canv.Draw(h);
   EXPECT_EQ(canv.GetPrimitives().size(), 1u);
}

TEST_F(DrawTest, TwoD)
{
   using namespace ROOT::Experimental;
   TAxisConfig xaxis{10, 0., 1.};
   TAxisConfig yaxis{{0., 1., 10., 100.}};
   auto h = std::make_shared<TH2I>(xaxis, yaxis);
   TCanvas canv;
   canv.Draw(h);
   // No THist copy c'tor:
   // canv.Draw(TH2F(xaxis, yaxis));
   canv.Draw(std::make_unique<TH2C>(xaxis, yaxis));
   EXPECT_EQ(canv.GetPrimitives().size(), 2u);
}

TEST_F(DrawTest, ThreeD)
{
   using namespace ROOT::Experimental;
   TAxisConfig xaxis{{0., 1.}};
   TAxisConfig yaxis{10, 0., 1.};
   TAxisConfig zaxis{{0., 1., 10., 100.}};
   auto h = std::make_shared<TH3F>(xaxis, yaxis, zaxis);
   TCanvas canv;
   canv.Draw(h);
   EXPECT_EQ(canv.GetPrimitives().size(), 1u);
}

struct DrawOptTest: public FixtureBase {};

// Drawing options:
TEST_F(DrawOptTest, OneD)
{
   using namespace ROOT::Experimental;
   TAxisConfig xaxis{10, 0., 1.};
   auto h = std::make_shared<TH1D>(xaxis);
   TCanvas canv;
   auto &Opts = canv.Draw(h);
   Opts.SetLineColor(TColor::kRed);
   TColor shouldBeRed = Opts.GetLineColor();
   EXPECT_EQ(shouldBeRed, TColor::kRed);
}

#include "TROOT.h" // for gROOT->SetBatch()

void FixtureBase::SetUp() {
   gROOT->SetBatch();
};
<commit_msg>Revert "Try to fix test on macOS."; it doesn't help.<commit_after>#include "gtest/gtest.h"
#include "ROOT/THist.hxx"
#include "ROOT/TCanvas.hxx"
#include "ROOT/TColor.hxx"

using namespace ROOT::Experimental;

// Test drawing of histograms.
TEST(DrawTest, OneD)
{
   TAxisConfig xaxis{10, 0., 1.};
   auto h = std::make_shared<TH1D>(xaxis);
   TCanvas canv;
   canv.Draw(h);
   EXPECT_EQ(canv.GetPrimitives().size(), 1u);
}

TEST(DrawTest, TwoD)
{
   TAxisConfig xaxis{10, 0., 1.};
   TAxisConfig yaxis{{0., 1., 10., 100.}};
   auto h = std::make_shared<TH2I>(xaxis, yaxis);
   TCanvas canv;
   canv.Draw(h);
   // No THist copt c'tor:
   // canv.Draw(TH2F(xaxis, yaxis));
   canv.Draw(std::make_unique<TH2C>(xaxis, yaxis));
   EXPECT_EQ(canv.GetPrimitives().size(), 2u);
}

TEST(DrawTest, ThreeD)
{
   TAxisConfig xaxis{{0., 1.}};
   TAxisConfig yaxis{10, 0., 1.};
   TAxisConfig zaxis{{0., 1., 10., 100.}};
   auto h = std::make_shared<TH3F>(xaxis, yaxis, zaxis);
   TCanvas canv;
   canv.Draw(h);
   EXPECT_EQ(canv.GetPrimitives().size(), 1u);
}

// Drawing options:
TEST(DrawOptTest, OneD)
{
   TAxisConfig xaxis{10, 0., 1.};
   auto h = std::make_shared<TH1D>(xaxis);
   TCanvas canv;
   auto &Opts = canv.Draw(h);
   Opts.SetLineColor(TColor::kRed);
   TColor shouldBeRed = Opts.GetLineColor();
   EXPECT_EQ(shouldBeRed, TColor::kRed);
}
<|endoftext|>


<commit_before>//
// Created by monty on 30/07/16.
//

#include <map>
#include <memory>
#include <functional>
#include <EASTL/vector.h>
#include <EASTL/array.h>

using eastl::vector;
using eastl::array;

#include <sg14/fixed_point>
#include <EASTL/vector.h>
#include <EASTL/array.h>

using sg14::fixed_point;
using eastl::vector;
using eastl::array;

#include "NativeBitmap.h"
#include "ETextures.h"
#include "IFileLoaderDelegate.h"
#include "NativeBitmap.h"
#include "Vec2i.h"
#include "IMapElement.h"
#include "CTeam.h"
#include "CItem.h"
#include "CActor.h"
#include "CGameDelegate.h"
#include "CMap.h"
#include "VisibilityStrategy.h"

namespace odb {

    const bool kNarrowByDistance = true;

	bool VisibilityStrategy::isValid(const Knights::Vec2i& pos) {
		return 0 <= pos.x && pos.x < Knights::kMapSize && 0 <= pos.y && pos.y < Knights::kMapSize;
	}

	void VisibilityStrategy::mergeInto(const VisMap &map1, const VisMap &map2, VisMap &result) {
		for ( int y = 0; y < Knights::kMapSize; ++y ) {
			for ( int x = 0; x < Knights::kMapSize; ++x ) {
				if ( map1[ y ][ x ] == EVisibility::kVisible || map2[ y ][ x ] == EVisibility::kVisible ) {
					result[ y ][ x ] = EVisibility::kVisible;
				} else {
					result[ y ][ x ] = EVisibility::kInvisible;
				}
			}
		}
	}

	bool VisibilityStrategy::isBlock(const IntMap& occluders, Knights::EDirection direction, const Knights::Vec2i& currentPos) {

        auto transformed = transform( direction, currentPos );

		auto tile = occluders[ transformed.y][transformed.x];

		for (auto candidate : {'1', 'I','Y', 'X', 'R', '\\', '/', 'S', 'Z', '|', '%', '<', '>'}) {
			if (candidate == tile) {
				return true;
			}
		}

		return false;
	}

	void VisibilityStrategy::castVisibility(VisMap &visMap, const IntMap &occluders, const Knights::Vec2i& pos, Knights::EDirection direction, bool cleanPrevious, DistanceDistribution& distances) {
		if ( cleanPrevious ) {
			for (auto &line : visMap) {
				std::fill(std::begin(line), std::end(line), EVisibility::kInvisible);
			}

			for ( auto& distanceLine : distances ) {
				distanceLine.clear();
				distanceLine.reserve(Knights::kMapSize + Knights::kMapSize);
			}
		}

		castVisibility(direction, visMap, occluders, transform( direction, pos ), {0, 0}, distances);
	}

	bool VisibilityStrategy::isVisibleAt(const VisMap& visMap, Knights::EDirection from, const Knights::Vec2i& currentPos ) {
		auto converted = transform( from, currentPos );
		return visMap[ converted.y ][ converted.x ] == EVisibility::kVisible;
	}

	void VisibilityStrategy::setIsVisible(VisMap& visMap, Knights::EDirection from, const Knights::Vec2i& currentPos ) {
		auto converted = transform( from, currentPos );
		visMap[ converted.y ][ converted.x ] = EVisibility::kVisible;
	}

	Knights::Vec2i VisibilityStrategy::transform( Knights::EDirection from, const Knights::Vec2i& currentPos ) {

		switch( from ) {
			case Knights::EDirection::kNorth:
				return currentPos;
			case Knights::EDirection::kSouth:
				return { Knights::kMapSize - currentPos.x - 1, Knights::kMapSize - currentPos.y - 1};
			case Knights::EDirection::kEast:
				return { Knights::kMapSize - currentPos.y - 1, Knights::kMapSize - currentPos.x - 1};
			case Knights::EDirection::kWest:
				return { currentPos.y, currentPos.x};
		}
	}

	void VisibilityStrategy::castVisibility(Knights::EDirection from, VisMap &visMap, const IntMap &occluders,
	                                        const Knights::Vec2i& originalPos, const Knights::Vec2i& offset, DistanceDistribution& distances) {

		array<Knights::Vec2i, Knights::kMapSize + Knights::kMapSize> positions;
		int stackPos = 0;
		Knights::Vec2i currentPos;

		positions[stackPos] = originalPos;
		++stackPos;

		while (stackPos > 0) {
			--stackPos;

			currentPos = positions[ stackPos ];

			auto transformed = transform( from, currentPos);

			if (!isValid(transformed)) {
				continue;
			}

			if ( isVisibleAt( visMap, from, currentPos ) ) {
				continue;
			}

			setIsVisible( visMap, from, currentPos );

            int manhattanDistance = std::abs( currentPos.y - originalPos.y ) + std::abs( currentPos.x - originalPos.x );
            distances[ manhattanDistance ].push_back( transformed );

            if (isBlock(occluders, from, currentPos )) {
				continue;
			}

			auto leftDirection = Knights::EDirection::kWest;
			auto rightDirection = Knights::EDirection::kEast;
			auto rightOffset = Knights::mapOffsetForDirection(rightDirection);
			auto leftOffset = Knights::mapOffsetForDirection(leftDirection);

            //The -1 is due to the fact I will add a new element.

            int distance = ( currentPos.y - originalPos.y );
            int narrowing = kNarrowByDistance ? distance : 1;

			if ( ( !kNarrowByDistance || ( currentPos.x - originalPos.x ) >= -std::abs(narrowing) )&& ( currentPos.x - originalPos.x ) <= 0 && stackPos < positions.size() - 1) {
				positions[stackPos] =  Knights::Vec2i{currentPos.x + leftOffset.x, currentPos.y + leftOffset.y};
				++stackPos;
			}

			if ( ( !kNarrowByDistance || ( currentPos.x - originalPos.x ) <= std::abs(narrowing) ) && ( currentPos.x - originalPos.x ) >= 0 && stackPos < positions.size() - 1) {
				positions[stackPos] =  Knights::Vec2i{currentPos.x + rightOffset.x, currentPos.y + rightOffset.y};
				++stackPos;
			}

            if (  distance <= 0 && stackPos < positions.size() - 1) {
                auto mapOffset = Knights::mapOffsetForDirection(Knights::EDirection::kNorth);
                positions[stackPos] =  Knights::Vec2i{currentPos.x + mapOffset.x, currentPos.y + mapOffset.y};
                ++stackPos;
            }

		}
	}

    void VisibilityStrategy::makeAllVisible(VisMap& map) {
		for ( int y = 0; y < Knights::kMapSize; ++y ) {
			for ( int x = 0; x < Knights::kMapSize; ++x ) {
				map[ y ][ x ] = EVisibility::kVisible;
			}
		}
    }
}
<commit_msg>Fix bug on visibility<commit_after>//
// Created by monty on 30/07/16.
//

#include <map>
#include <memory>
#include <functional>
#include <EASTL/vector.h>
#include <EASTL/array.h>

using eastl::vector;
using eastl::array;

#include <sg14/fixed_point>
#include <EASTL/vector.h>
#include <EASTL/array.h>

using sg14::fixed_point;
using eastl::vector;
using eastl::array;

#include "NativeBitmap.h"
#include "ETextures.h"
#include "IFileLoaderDelegate.h"
#include "NativeBitmap.h"
#include "Vec2i.h"
#include "IMapElement.h"
#include "CTeam.h"
#include "CItem.h"
#include "CActor.h"
#include "CGameDelegate.h"
#include "CMap.h"
#include "VisibilityStrategy.h"

namespace odb {

    const bool kNarrowByDistance = true;
	const bool kConservativeOccluders = false;

	bool VisibilityStrategy::isValid(const Knights::Vec2i& pos) {
		return 0 <= pos.x && pos.x < Knights::kMapSize && 0 <= pos.y && pos.y < Knights::kMapSize;
	}

	void VisibilityStrategy::mergeInto(const VisMap &map1, const VisMap &map2, VisMap &result) {
		for ( int y = 0; y < Knights::kMapSize; ++y ) {
			for ( int x = 0; x < Knights::kMapSize; ++x ) {
				if ( map1[ y ][ x ] == EVisibility::kVisible || map2[ y ][ x ] == EVisibility::kVisible ) {
					result[ y ][ x ] = EVisibility::kVisible;
				} else {
					result[ y ][ x ] = EVisibility::kInvisible;
				}
			}
		}
	}

	bool VisibilityStrategy::isBlock(const IntMap& occluders, Knights::EDirection direction, const Knights::Vec2i& currentPos) {

        auto transformed = transform( direction, currentPos );

		auto tile = occluders[ transformed.y][transformed.x];

		std::string occluderString = "";

		if (kConservativeOccluders ) {
			occluderString = "1IYXR";
		} else {
			occluderString = "1IYXR\\/SZ|%<>";
		}

		for (const auto& candidate : occluderString ) {
			if (candidate == tile) {
				return true;
			}
		}

		return false;
	}

	void VisibilityStrategy::castVisibility(VisMap &visMap, const IntMap &occluders, const Knights::Vec2i& pos, Knights::EDirection direction, bool cleanPrevious, DistanceDistribution& distances) {
		if ( cleanPrevious ) {
			for (auto &line : visMap) {
				std::fill(std::begin(line), std::end(line), EVisibility::kInvisible);
			}

			for ( auto& distanceLine : distances ) {
				distanceLine.clear();
				distanceLine.reserve(Knights::kMapSize + Knights::kMapSize);
			}
		}

		castVisibility(direction, visMap, occluders, transform( direction, pos ), {0, 0}, distances);
	}

	bool VisibilityStrategy::isVisibleAt(const VisMap& visMap, Knights::EDirection from, const Knights::Vec2i& currentPos ) {
		auto converted = transform( from, currentPos );
		return visMap[ converted.y ][ converted.x ] == EVisibility::kVisible;
	}

	void VisibilityStrategy::setIsVisible(VisMap& visMap, Knights::EDirection from, const Knights::Vec2i& currentPos ) {
		auto converted = transform( from, currentPos );
		visMap[ converted.y ][ converted.x ] = EVisibility::kVisible;
	}

	Knights::Vec2i VisibilityStrategy::transform( Knights::EDirection from, const Knights::Vec2i& currentPos ) {

		switch( from ) {
			case Knights::EDirection::kNorth:
				return currentPos;
			case Knights::EDirection::kSouth:
				return { Knights::kMapSize - currentPos.x - 1, Knights::kMapSize - currentPos.y - 1};
			case Knights::EDirection::kEast:
				return { Knights::kMapSize - currentPos.y - 1, Knights::kMapSize - currentPos.x - 1};
			case Knights::EDirection::kWest:
				return { currentPos.y, currentPos.x};
		}
	}

	void VisibilityStrategy::castVisibility(Knights::EDirection from, VisMap &visMap, const IntMap &occluders,
	                                        const Knights::Vec2i& originalPos, const Knights::Vec2i& offset, DistanceDistribution& distances) {

		array<Knights::Vec2i, Knights::kMapSize + Knights::kMapSize> positions;
		int stackPos = 0;
		Knights::Vec2i currentPos;

		positions[stackPos] = originalPos;
		++stackPos;

		while (stackPos > 0) {
			--stackPos;

			currentPos = positions[ stackPos ];

			auto transformed = transform( from, currentPos);

			if (!isValid(transformed)) {
				continue;
			}

			if ( isVisibleAt( visMap, from, currentPos ) ) {
				continue;
			}

			setIsVisible( visMap, from, currentPos );

            int manhattanDistance = std::abs( currentPos.y - originalPos.y ) + std::abs( currentPos.x - originalPos.x );
            distances[ manhattanDistance ].push_back( transformed );

            if (isBlock(occluders, from, currentPos )) {
				continue;
			}

			auto leftDirection = Knights::EDirection::kWest;
			auto rightDirection = Knights::EDirection::kEast;
			auto rightOffset = Knights::mapOffsetForDirection(rightDirection);
			auto leftOffset = Knights::mapOffsetForDirection(leftDirection);

            //The -1 is due to the fact I will add a new element.

            int distance = ( currentPos.y - originalPos.y );
            int narrowing = kNarrowByDistance ? distance : 1;

			if ( ( !kNarrowByDistance || ( currentPos.x - originalPos.x ) >= -std::abs(narrowing) )&& ( currentPos.x - originalPos.x ) <= 0 && stackPos < positions.size() - 1) {
				positions[stackPos] =  Knights::Vec2i{currentPos.x + leftOffset.x, currentPos.y + leftOffset.y};
				++stackPos;
			}

			if ( ( !kNarrowByDistance || ( currentPos.x - originalPos.x ) <= std::abs(narrowing) ) && ( currentPos.x - originalPos.x ) >= 0 && stackPos < positions.size() - 1) {
				positions[stackPos] =  Knights::Vec2i{currentPos.x + rightOffset.x, currentPos.y + rightOffset.y};
				++stackPos;
			}

            if (  distance <= 0 && stackPos < positions.size() - 1) {
                auto mapOffset = Knights::mapOffsetForDirection(Knights::EDirection::kNorth);
                positions[stackPos] =  Knights::Vec2i{currentPos.x + mapOffset.x, currentPos.y + mapOffset.y};
                ++stackPos;
            }

		}
	}

    void VisibilityStrategy::makeAllVisible(VisMap& map) {
		for ( int y = 0; y < Knights::kMapSize; ++y ) {
			for ( int x = 0; x < Knights::kMapSize; ++x ) {
				map[ y ][ x ] = EVisibility::kVisible;
			}
		}
    }
}
<|endoftext|>


<commit_before>// ----------------------------------------------------------------------------
// ------------- AI Battleground, Copyright(C) Maciej Pryc, 2016 --------------
// ----------------------------------------------------------------------------

#include <iostream>

#include "LevelInfo.h"
#include "Actor.h"
#include "TextureManager.h"

LevelInfo::LevelInfo(class TextureManager* TexManager, const sf::FloatRect& LevelBoundaries) :
Boundaries(LevelBoundaries), RightBottomEdge(LevelBoundaries.left + LevelBoundaries.width, LevelBoundaries.top + LevelBoundaries.height),
HealZoneA(TexManager, sf::Vector2f(200.0f, 400.0f), ETeam::TEAM_A, Actors, ACTORS_AMOUNT),
HealZoneB(TexManager, sf::Vector2f(800.0f, 400.0f), ETeam::TEAM_B, Actors, ACTORS_AMOUNT)
{
	const float InitialRectSize = 0.15f;

	ETeam InitialTeam = ETeam::TEAM_A;
	std::string TexName("RobotA");
	Actor** ArrayToPopulate = ActorsTeamA;
	sf::FloatRect RectToSpawnIn(Boundaries.left, Boundaries.top, Boundaries.width * InitialRectSize, Boundaries.height);

	for (int i = 0; i < ACTORS_AMOUNT; ++i)
	{
		if (i == ACTORS_PER_TEAM_AMOUNT)
		{
			InitialTeam = ETeam::TEAM_B;
			TexName = "RobotB";
			ArrayToPopulate = ActorsTeamB;
			RectToSpawnIn = sf::FloatRect(Boundaries.left + Boundaries.width * (1.0f - InitialRectSize), Boundaries.top, Boundaries.width * InitialRectSize, Boundaries.height);
		}

		Actors[i] = new Actor(this, TexManager, TexName, InitialTeam, GetRandomPointInRect(RectToSpawnIn));
		ArrayToPopulate[i % ACTORS_PER_TEAM_AMOUNT] = Actors[i];
	}

	TexManager->InitTexture(&BackgroundSprite, "Background256", true);
	BackgroundSprite.setTextureRect(sf::IntRect(0, 0, (int)Boundaries.width, (int)Boundaries.height));
	BackgroundSprite.setPosition(sf::Vector2f(Boundaries.left, Boundaries.top));

#if defined DRAW_DEBUG_GRID
	TexManager->InitTexture(&DebugGridSprite, "DebugGrid1000x800");
#endif
}

LevelInfo::~LevelInfo()
{
	for (int i = 0; i < ACTORS_AMOUNT; ++i)
		if (Actors[i])
			delete Actors[i];
}

sf::Vector2f LevelInfo::GetRandomPointInRect(const sf::FloatRect& Rect)
{
	return sf::Vector2f(Rect.left + GetRandomFloat(Rect.width), Rect.top + GetRandomFloat(Rect.height));
}

void LevelInfo::Draw(sf::RenderWindow* Window) const
{
	Window->draw(BackgroundSprite);

#if defined DRAW_DEBUG_GRID
	Window->draw(DebugGridSprite);
#endif

	HealZoneA.Draw(Window);
	HealZoneB.Draw(Window);

	for (Actor* CurrActor : Actors)
		if (CurrActor)
			CurrActor->DrawLaserBeam(Window);

	for (Actor* CurrActor : Actors)
		if (CurrActor)
			CurrActor->DrawRobot(Window);
}

void LevelInfo::Update(const float DeltaTime, const sf::Time MainTimeCounter)
{
	static int LastIndex = 0;

	int NewIndex = (int)(MainTimeCounter.asSeconds() * ACTORS_AMOUNT);

	if (NewIndex < LastIndex)
		NewIndex = ACTORS_AMOUNT;

	for (int i = LastIndex; i < NewIndex; ++i)
		if (Actors[i])
			FindNearestEnemyForActor(Actors[i]);

	LastIndex = NewIndex != ACTORS_AMOUNT ? NewIndex: 0;

	for (Actor* CurrActor : Actors)
		if (CurrActor)
			CurrActor->Update(DeltaTime);

	HealZoneA.Update(DeltaTime);
	HealZoneB.Update(DeltaTime);
}

void LevelInfo::FindNearestEnemyForActor(class Actor* RequestingActor)
{
	Actor* NearestOtherActor = nullptr;
	float MinSquaredDist = FLT_MAX;

	Actor** EnemyActors = RequestingActor->GetTeam() == ETeam::TEAM_A ? ActorsTeamB : ActorsTeamA;

	for (int j = 0; j < ACTORS_PER_TEAM_AMOUNT; ++j)
	{
		Actor* CurrEnemyActor = EnemyActors[j];

		if (CurrEnemyActor)
		{
			const float SquaredDist = GetSquaredDist(RequestingActor->GetPosition(), CurrEnemyActor->GetPosition());

			if (SquaredDist < MinSquaredDist)
			{
				MinSquaredDist = SquaredDist;
				NearestOtherActor = CurrEnemyActor;
			}
		}
	}

	RequestingActor->SetNearestEnemy(NearestOtherActor);
}

void LevelInfo::DestroyActor(class Actor* ActorToDestroy)
{
	for (int i = 0; i < ACTORS_AMOUNT; ++i)
	{
		if (Actors[i] == ActorToDestroy)
		{
			Actors[i] = nullptr;
			break;
		}
	}

	Actor** TeamActors = ActorToDestroy->GetTeam() == ETeam::TEAM_A ? ActorsTeamA : ActorsTeamB;

	for (int i = 0; i < ACTORS_PER_TEAM_AMOUNT; ++i)
	{
		if (TeamActors[i] == ActorToDestroy)
		{
			TeamActors[i] = nullptr;
			break;
		}
	}

	Actor** EnemyActors = ActorToDestroy->GetTeam() == ETeam::TEAM_A ? ActorsTeamB : ActorsTeamA;

	for (int i = 0; i < ACTORS_PER_TEAM_AMOUNT; ++i)
		if (EnemyActors[i] && EnemyActors[i]->GetNearestEnemy() == ActorToDestroy)
			FindNearestEnemyForActor(EnemyActors[i]);

	delete ActorToDestroy;
}

sf::Vector2f LevelInfo::GetHealZonePosition(ETeam Team) const
{
	return Team == ETeam::TEAM_A ? HealZoneA.GetPosition() : HealZoneB.GetPosition();
}
<commit_msg>Positions of HealZones are now relative to level boundaries.<commit_after>// ----------------------------------------------------------------------------
// ------------- AI Battleground, Copyright(C) Maciej Pryc, 2016 --------------
// ----------------------------------------------------------------------------

#include <iostream>

#include "LevelInfo.h"
#include "Actor.h"
#include "TextureManager.h"

LevelInfo::LevelInfo(class TextureManager* TexManager, const sf::FloatRect& LevelBoundaries) :
Boundaries(LevelBoundaries), RightBottomEdge(LevelBoundaries.left + LevelBoundaries.width, LevelBoundaries.top + LevelBoundaries.height),
HealZoneA(TexManager, sf::Vector2f(LevelBoundaries.left + LevelBoundaries.width * 0.2f, LevelBoundaries.top + LevelBoundaries.height * 0.5f), ETeam::TEAM_A, Actors, ACTORS_AMOUNT),
HealZoneB(TexManager, sf::Vector2f(LevelBoundaries.left + LevelBoundaries.width * 0.8f, LevelBoundaries.top + LevelBoundaries.height * 0.5f), ETeam::TEAM_B, Actors, ACTORS_AMOUNT)
{
	const float InitialRectSize = 0.15f;

	ETeam InitialTeam = ETeam::TEAM_A;
	std::string TexName("RobotA");
	Actor** ArrayToPopulate = ActorsTeamA;
	sf::FloatRect RectToSpawnIn(Boundaries.left, Boundaries.top, Boundaries.width * InitialRectSize, Boundaries.height);

	for (int i = 0; i < ACTORS_AMOUNT; ++i)
	{
		if (i == ACTORS_PER_TEAM_AMOUNT)
		{
			InitialTeam = ETeam::TEAM_B;
			TexName = "RobotB";
			ArrayToPopulate = ActorsTeamB;
			RectToSpawnIn = sf::FloatRect(Boundaries.left + Boundaries.width * (1.0f - InitialRectSize), Boundaries.top, Boundaries.width * InitialRectSize, Boundaries.height);
		}

		Actors[i] = new Actor(this, TexManager, TexName, InitialTeam, GetRandomPointInRect(RectToSpawnIn));
		ArrayToPopulate[i % ACTORS_PER_TEAM_AMOUNT] = Actors[i];
	}

	TexManager->InitTexture(&BackgroundSprite, "Background256", true);
	BackgroundSprite.setTextureRect(sf::IntRect(0, 0, (int)Boundaries.width, (int)Boundaries.height));
	BackgroundSprite.setPosition(sf::Vector2f(Boundaries.left, Boundaries.top));

#if defined DRAW_DEBUG_GRID
	TexManager->InitTexture(&DebugGridSprite, "DebugGrid1000x800");
#endif
}

LevelInfo::~LevelInfo()
{
	for (int i = 0; i < ACTORS_AMOUNT; ++i)
		if (Actors[i])
			delete Actors[i];
}

sf::Vector2f LevelInfo::GetRandomPointInRect(const sf::FloatRect& Rect)
{
	return sf::Vector2f(Rect.left + GetRandomFloat(Rect.width), Rect.top + GetRandomFloat(Rect.height));
}

void LevelInfo::Draw(sf::RenderWindow* Window) const
{
	Window->draw(BackgroundSprite);

#if defined DRAW_DEBUG_GRID
	Window->draw(DebugGridSprite);
#endif

	HealZoneA.Draw(Window);
	HealZoneB.Draw(Window);

	for (Actor* CurrActor : Actors)
		if (CurrActor)
			CurrActor->DrawLaserBeam(Window);

	for (Actor* CurrActor : Actors)
		if (CurrActor)
			CurrActor->DrawRobot(Window);
}

void LevelInfo::Update(const float DeltaTime, const sf::Time MainTimeCounter)
{
	static int LastIndex = 0;

	int NewIndex = (int)(MainTimeCounter.asSeconds() * ACTORS_AMOUNT);

	if (NewIndex < LastIndex)
		NewIndex = ACTORS_AMOUNT;

	for (int i = LastIndex; i < NewIndex; ++i)
		if (Actors[i])
			FindNearestEnemyForActor(Actors[i]);

	LastIndex = NewIndex != ACTORS_AMOUNT ? NewIndex: 0;

	for (Actor* CurrActor : Actors)
		if (CurrActor)
			CurrActor->Update(DeltaTime);

	HealZoneA.Update(DeltaTime);
	HealZoneB.Update(DeltaTime);
}

void LevelInfo::FindNearestEnemyForActor(class Actor* RequestingActor)
{
	Actor* NearestOtherActor = nullptr;
	float MinSquaredDist = FLT_MAX;

	Actor** EnemyActors = RequestingActor->GetTeam() == ETeam::TEAM_A ? ActorsTeamB : ActorsTeamA;

	for (int j = 0; j < ACTORS_PER_TEAM_AMOUNT; ++j)
	{
		Actor* CurrEnemyActor = EnemyActors[j];

		if (CurrEnemyActor)
		{
			const float SquaredDist = GetSquaredDist(RequestingActor->GetPosition(), CurrEnemyActor->GetPosition());

			if (SquaredDist < MinSquaredDist)
			{
				MinSquaredDist = SquaredDist;
				NearestOtherActor = CurrEnemyActor;
			}
		}
	}

	RequestingActor->SetNearestEnemy(NearestOtherActor);
}

void LevelInfo::DestroyActor(class Actor* ActorToDestroy)
{
	for (int i = 0; i < ACTORS_AMOUNT; ++i)
	{
		if (Actors[i] == ActorToDestroy)
		{
			Actors[i] = nullptr;
			break;
		}
	}

	Actor** TeamActors = ActorToDestroy->GetTeam() == ETeam::TEAM_A ? ActorsTeamA : ActorsTeamB;

	for (int i = 0; i < ACTORS_PER_TEAM_AMOUNT; ++i)
	{
		if (TeamActors[i] == ActorToDestroy)
		{
			TeamActors[i] = nullptr;
			break;
		}
	}

	Actor** EnemyActors = ActorToDestroy->GetTeam() == ETeam::TEAM_A ? ActorsTeamB : ActorsTeamA;

	for (int i = 0; i < ACTORS_PER_TEAM_AMOUNT; ++i)
		if (EnemyActors[i] && EnemyActors[i]->GetNearestEnemy() == ActorToDestroy)
			FindNearestEnemyForActor(EnemyActors[i]);

	delete ActorToDestroy;
}

sf::Vector2f LevelInfo::GetHealZonePosition(ETeam Team) const
{
	return Team == ETeam::TEAM_A ? HealZoneA.GetPosition() : HealZoneB.GetPosition();
}
<|endoftext|>


<commit_before>/**
 * \file OversamplingFilter.hxx
 */

#include <ATK/Tools/OversamplingFilter.h>

#include <cassert>

namespace ATK
{
  template<class DataType_>
  Oversampling6points5order_2<DataType_>::Oversampling6points5order_2()
  {
    coeffs[0][0] = 0.40513396007145713;
    coeffs[0][1] = 0.09251794438424393;
    coeffs[0][2] = 0.00234806603570670;
    coeffs[1][0] = 0.28342806338906690;
    coeffs[1][1] = 0.21703277024054901;
    coeffs[1][2] = 0.01309294748731515;
    coeffs[2][0] = -0.191337682540351941;
    coeffs[2][1] = 0.16187844487943592;
    coeffs[2][2] = 0.02946017143111912;
    coeffs[3][0] = -0.16471626390554542;
    coeffs[3][1] = -0.00154547203542499;
    coeffs[3][2] = 0.03399271444851909;
    coeffs[4][0] = 0.03845798729588149;
    coeffs[4][1] = -0.05712936104242644;
    coeffs[4][2] = 0.01866750929921070;
    coeffs[5][0] = 0.04317950185225609;
    coeffs[5][1] = -0.01802814255926417;
    coeffs[5][2] = 0.00152170021558204;
  }

  template<class DataType_>
  Oversampling6points5order_4<DataType_>::Oversampling6points5order_4()
  {
    coeffs[0][0] = 0.41496902959240894;
    coeffs[0][1] = 0.08343081932889224;
    coeffs[0][2] = 0.00160015038681571;
    coeffs[1][0] = 0.31625515004859783;
    coeffs[1][1] = 0.21197848565176958;
    coeffs[1][2] = 0.02337283412161328;
    coeffs[2][0] = -0.203271896548875371;
    coeffs[2][1] = 0.17989908432249280;
    coeffs[2][2] = 0.02337283412161328;
    coeffs[3][0] = -0.20209241069835732;
    coeffs[3][1] = 0.01760734419526000;
    coeffs[3][2] = 0.02985927012435252;
    coeffs[4][0] = 0.04100948858761910;
    coeffs[4][1] = -0.06147760875085254;
    coeffs[4][2] = 0.02046802954581191;
    coeffs[5][0] = 0.06607747864416924;
    coeffs[5][1] = -0.03255079211953620;
    coeffs[5][2] = 0.00628989632244913;
  }

  template<class DataType_>
  Oversampling6points5order_8<DataType_>::Oversampling6points5order_8()
  {
    coeffs[0][0] = 0.41660797292569773;
    coeffs[0][1] = 0.08188468587188069;
    coeffs[0][2] = 0.00150734119050266;
    coeffs[1][0] = 0.32232780822726981;
    coeffs[1][1] = 0.21076321997422021;
    coeffs[1][2] = 0.00907649978070957;
    coeffs[2][0] = -0.205219993961471501;
    coeffs[2][1] = 0.18282942057327367;
    coeffs[2][2] = 0.02239057377093268;
    coeffs[3][0] = -0.21022298520246224;
    coeffs[3][1] = 0.02176417471349534;
    coeffs[3][2] = 0.02898626924395209;
    coeffs[4][0] = 0.04149963966704384;
    coeffs[4][1] = -0.06224707096203808;
    coeffs[4][2] = 0.02074742969707599;
    coeffs[5][0] = 0.07517133281176167;
    coeffs[5][1] = -0.03751837438141215;
    coeffs[5][2] = 0.00747588873055296;
  }

  template<class DataType_>
  Oversampling6points5order_16<DataType_>::Oversampling6points5order_16()
  {
    coeffs[0][0] = 0.41809989254549901;
    coeffs[0][1] = 0.08049339946273310;
    coeffs[0][2] = 0.00140670799165932;
    coeffs[1][0] = 0.32767596257424964;
    coeffs[1][1] = 0.20978189376640677;
    coeffs[1][2] = 0.00859567104974701;
    coeffs[2][0] = -0.2069944618112960001;
    coeffs[2][1] = 0.18541689550861262;
    coeffs[2][2] = 0.02152772260740132;
    coeffs[3][0] = -0.21686095413034051;
    coeffs[3][1] = 0.02509557922091643;
    coeffs[3][2] = 0.02831484751363800;
    coeffs[4][0] = 0.04163046817137675;
    coeffs[4][1] = -0.06244556931623735;
    coeffs[4][2] = 0.02081510113314315;
    coeffs[5][0] = 0.07990500783668089;
    coeffs[5][1] = -0.03994519162531633;
    coeffs[5][2] = 0.00798609327859495;
  }

  template<class DataType_>
  Oversampling6points5order_32<DataType_>::Oversampling6points5order_32()
  {
    coeffs[0][0] = 0.42685983409379380;
    coeffs[0][1] = 0.07238123511170030;
    coeffs[0][2] = 0.00075893079450573;
    coeffs[1][0] = 0.35831772348893259;
    coeffs[1][1] = 0.20451644554758297;
    coeffs[1][2] = 0.00562658797241955;
    coeffs[2][0] = -0.217009177221292431;
    coeffs[2][1] = 0.20051376594086157;
    coeffs[2][2] = 0.01649541128040211;
    coeffs[3][0] = -0.25112715343740988;
    coeffs[3][1] = 0.04223025992200458;
    coeffs[3][2] = 0.02488727472995134;
    coeffs[4][0] = 0.04166746673533273;
    coeffs[4][1] = -0.06250420114356986;
    coeffs[4][2] = 0.02083473440841799;
    coeffs[5][0] = 0.08349799235675044;
    coeffs[5][1] = -0.04174912841630993;
    coeffs[5][2] = 0.00834987866042734;
  }

  template<class DataType, class Coefficients>
  OversamplingFilter<DataType, Coefficients>::OversamplingFilter(gsl::index nb_channels)
    :TypedBaseFilter<DataType>(nb_channels, nb_channels)
  {
    input_delay = Coefficients::points;
  }

  template<class DataType, class Coefficients>
  void OversamplingFilter<DataType, Coefficients>::process_impl(gsl::index size) const
  {
    assert(input_sampling_rate * Coefficients::oversampling_factor == output_sampling_rate);
    assert(nb_input_ports == nb_output_ports);

    for(gsl::index channel = 0; channel < nb_input_ports; ++channel)
    {
      const DataType* ATK_RESTRICT input = converted_inputs[channel];
      DataType* ATK_RESTRICT output = outputs[channel];
    }
  }

  template<class DataType, class Coefficients>
  void OversamplingFilter<DataType, Coefficients>::process_one_channel(gsl::index size, const DataType* ATK_RESTRICT input, DataType* ATK_RESTRICT output) const
  {
    for(gsl::index i = 0; i < size / Coefficients::oversampling_factor; ++i)
    {
      DataType even[Coefficients::points / 2];
      for(gsl::index j = 0; j < Coefficients::points / 2; ++j)
      {
        even[j] = input[i - Coefficients::points + Coefficients::points / 2 + j] + input[i - Coefficients::points + Coefficients::points / 2 - 1 - j];
      }
      DataType odd[Coefficients::points / 2];
      for(gsl::index j = 0; j < Coefficients::points / 2; ++j)
      {
        odd[j] = input[i - Coefficients::points + Coefficients::points / 2 + j] - input[i - Coefficients::points + Coefficients::points / 2 - 1 - j];
      }
      DataType c[Coefficients::order + 1];

      for(gsl::index j = 0; j < Coefficients::order + 1; j += 2)
      {
      c[j] = TypeTraits<DataType>::Zero();
        for(gsl::index k = 0; k < Coefficients::points / 2; ++k)
        {
          c[j] = c[j] + even[k] * coeffs.coeffs[j][k];
        }
      }
      for(gsl::index j = 1; j < Coefficients::order + 1; j += 2)
      {
        c[j] = TypeTraits<DataType>::Zero();
        for(gsl::index k = 0; k < Coefficients::points / 2; ++k)
        {
          c[j] = c[j] + odd[k] * coeffs.coeffs[j][k];
        }
      }

      for (gsl::index j = 0; j < Coefficients::oversampling_factor; ++j)
      {
        auto z = static_cast<typename TypeTraits<DataType>::Scalar>(j) / Coefficients::oversampling_factor - static_cast<typename TypeTraits<DataType>::Scalar>(1 / 2.);

        DataType temp = TypeTraits<DataType>::Zero();
        for(gsl::index k = 0; k <= Coefficients::order; ++k)
        {
          temp = temp * z + c[Coefficients::order - k];
        }
        *(output++) = temp;
      }
    }
  }
}
<commit_msg>Fix oversampling filter...<commit_after>/**
 * \file OversamplingFilter.hxx
 */

#include <ATK/Tools/OversamplingFilter.h>

#include <cassert>

namespace ATK
{
  template<class DataType_>
  Oversampling6points5order_2<DataType_>::Oversampling6points5order_2()
  {
    coeffs[0][0] = 0.40513396007145713;
    coeffs[0][1] = 0.09251794438424393;
    coeffs[0][2] = 0.00234806603570670;
    coeffs[1][0] = 0.28342806338906690;
    coeffs[1][1] = 0.21703277024054901;
    coeffs[1][2] = 0.01309294748731515;
    coeffs[2][0] = -0.191337682540351941;
    coeffs[2][1] = 0.16187844487943592;
    coeffs[2][2] = 0.02946017143111912;
    coeffs[3][0] = -0.16471626390554542;
    coeffs[3][1] = -0.00154547203542499;
    coeffs[3][2] = 0.03399271444851909;
    coeffs[4][0] = 0.03845798729588149;
    coeffs[4][1] = -0.05712936104242644;
    coeffs[4][2] = 0.01866750929921070;
    coeffs[5][0] = 0.04317950185225609;
    coeffs[5][1] = -0.01802814255926417;
    coeffs[5][2] = 0.00152170021558204;
  }

  template<class DataType_>
  Oversampling6points5order_4<DataType_>::Oversampling6points5order_4()
  {
    coeffs[0][0] = 0.41496902959240894;
    coeffs[0][1] = 0.08343081932889224;
    coeffs[0][2] = 0.00160015038681571;
    coeffs[1][0] = 0.31625515004859783;
    coeffs[1][1] = 0.21197848565176958;
    coeffs[1][2] = 0.02337283412161328;
    coeffs[2][0] = -0.203271896548875371;
    coeffs[2][1] = 0.17989908432249280;
    coeffs[2][2] = 0.02337283412161328;
    coeffs[3][0] = -0.20209241069835732;
    coeffs[3][1] = 0.01760734419526000;
    coeffs[3][2] = 0.02985927012435252;
    coeffs[4][0] = 0.04100948858761910;
    coeffs[4][1] = -0.06147760875085254;
    coeffs[4][2] = 0.02046802954581191;
    coeffs[5][0] = 0.06607747864416924;
    coeffs[5][1] = -0.03255079211953620;
    coeffs[5][2] = 0.00628989632244913;
  }

  template<class DataType_>
  Oversampling6points5order_8<DataType_>::Oversampling6points5order_8()
  {
    coeffs[0][0] = 0.41660797292569773;
    coeffs[0][1] = 0.08188468587188069;
    coeffs[0][2] = 0.00150734119050266;
    coeffs[1][0] = 0.32232780822726981;
    coeffs[1][1] = 0.21076321997422021;
    coeffs[1][2] = 0.00907649978070957;
    coeffs[2][0] = -0.205219993961471501;
    coeffs[2][1] = 0.18282942057327367;
    coeffs[2][2] = 0.02239057377093268;
    coeffs[3][0] = -0.21022298520246224;
    coeffs[3][1] = 0.02176417471349534;
    coeffs[3][2] = 0.02898626924395209;
    coeffs[4][0] = 0.04149963966704384;
    coeffs[4][1] = -0.06224707096203808;
    coeffs[4][2] = 0.02074742969707599;
    coeffs[5][0] = 0.07517133281176167;
    coeffs[5][1] = -0.03751837438141215;
    coeffs[5][2] = 0.00747588873055296;
  }

  template<class DataType_>
  Oversampling6points5order_16<DataType_>::Oversampling6points5order_16()
  {
    coeffs[0][0] = 0.41809989254549901;
    coeffs[0][1] = 0.08049339946273310;
    coeffs[0][2] = 0.00140670799165932;
    coeffs[1][0] = 0.32767596257424964;
    coeffs[1][1] = 0.20978189376640677;
    coeffs[1][2] = 0.00859567104974701;
    coeffs[2][0] = -0.2069944618112960001;
    coeffs[2][1] = 0.18541689550861262;
    coeffs[2][2] = 0.02152772260740132;
    coeffs[3][0] = -0.21686095413034051;
    coeffs[3][1] = 0.02509557922091643;
    coeffs[3][2] = 0.02831484751363800;
    coeffs[4][0] = 0.04163046817137675;
    coeffs[4][1] = -0.06244556931623735;
    coeffs[4][2] = 0.02081510113314315;
    coeffs[5][0] = 0.07990500783668089;
    coeffs[5][1] = -0.03994519162531633;
    coeffs[5][2] = 0.00798609327859495;
  }

  template<class DataType_>
  Oversampling6points5order_32<DataType_>::Oversampling6points5order_32()
  {
    coeffs[0][0] = 0.42685983409379380;
    coeffs[0][1] = 0.07238123511170030;
    coeffs[0][2] = 0.00075893079450573;
    coeffs[1][0] = 0.35831772348893259;
    coeffs[1][1] = 0.20451644554758297;
    coeffs[1][2] = 0.00562658797241955;
    coeffs[2][0] = -0.217009177221292431;
    coeffs[2][1] = 0.20051376594086157;
    coeffs[2][2] = 0.01649541128040211;
    coeffs[3][0] = -0.25112715343740988;
    coeffs[3][1] = 0.04223025992200458;
    coeffs[3][2] = 0.02488727472995134;
    coeffs[4][0] = 0.04166746673533273;
    coeffs[4][1] = -0.06250420114356986;
    coeffs[4][2] = 0.02083473440841799;
    coeffs[5][0] = 0.08349799235675044;
    coeffs[5][1] = -0.04174912841630993;
    coeffs[5][2] = 0.00834987866042734;
  }

  template<class DataType, class Coefficients>
  OversamplingFilter<DataType, Coefficients>::OversamplingFilter(gsl::index nb_channels)
    :TypedBaseFilter<DataType>(nb_channels, nb_channels)
  {
    input_delay = Coefficients::points;
  }

  template<class DataType, class Coefficients>
  void OversamplingFilter<DataType, Coefficients>::process_impl(gsl::index size) const
  {
    assert(input_sampling_rate * Coefficients::oversampling_factor == output_sampling_rate);
    assert(nb_input_ports == nb_output_ports);

    for(gsl::index channel = 0; channel < nb_input_ports; ++channel)
    {
      const DataType* ATK_RESTRICT input = converted_inputs[channel];
      DataType* ATK_RESTRICT output = outputs[channel];

      process_one_channel(size, input, output);
    }
  }

  template<class DataType, class Coefficients>
  void OversamplingFilter<DataType, Coefficients>::process_one_channel(gsl::index size, const DataType* ATK_RESTRICT input, DataType* ATK_RESTRICT output) const
  {
    for(gsl::index i = 0; i < size / Coefficients::oversampling_factor; ++i)
    {
      DataType even[Coefficients::points / 2];
      for(gsl::index j = 0; j < Coefficients::points / 2; ++j)
      {
        even[j] = input[i - Coefficients::points + Coefficients::points / 2 + j] + input[i - Coefficients::points + Coefficients::points / 2 - 1 - j];
      }
      DataType odd[Coefficients::points / 2];
      for(gsl::index j = 0; j < Coefficients::points / 2; ++j)
      {
        odd[j] = input[i - Coefficients::points + Coefficients::points / 2 + j] - input[i - Coefficients::points + Coefficients::points / 2 - 1 - j];
      }
      DataType c[Coefficients::order + 1];

      for(gsl::index j = 0; j < Coefficients::order + 1; j += 2)
      {
      c[j] = TypeTraits<DataType>::Zero();
        for(gsl::index k = 0; k < Coefficients::points / 2; ++k)
        {
          c[j] = c[j] + even[k] * coeffs.coeffs[j][k];
        }
      }
      for(gsl::index j = 1; j < Coefficients::order + 1; j += 2)
      {
        c[j] = TypeTraits<DataType>::Zero();
        for(gsl::index k = 0; k < Coefficients::points / 2; ++k)
        {
          c[j] = c[j] + odd[k] * coeffs.coeffs[j][k];
        }
      }

      for (gsl::index j = 0; j < Coefficients::oversampling_factor; ++j)
      {
        auto z = static_cast<typename TypeTraits<DataType>::Scalar>(j) / Coefficients::oversampling_factor - static_cast<typename TypeTraits<DataType>::Scalar>(1 / 2.);

        DataType temp = TypeTraits<DataType>::Zero();
        for(gsl::index k = 0; k <= Coefficients::order; ++k)
        {
          temp = temp * z + c[Coefficients::order - k];
        }
        *(output++) = temp;
      }
    }
  }
}
<|endoftext|>