Zwracanie klikniętego pola na mapie

0

Piszę "Edytor Mapy". Potrzebuję uzyskać informacje, które pole (HexTile) zostało naduszone, aby móc za pomocą kliknięć myszy edytować mapę.
image

#include <irrlicht.h>

using namespace irr;	// I don't want to use it irr::

using namespace core;	// also ( irr::core:: )
using namespace scene;	// also ( irr::scene::)
using namespace video;	// also ... 
using namespace io;		// ... 
using namespace gui;	// ...

#include<iostream>
#include<set>
#include<vector>

// device
int screenWidth = 1080;
int screenHeight = 720;
int bitsPerPixel = 32;
bool fullscreen = false;
bool stencilbuffer = false;		// Specifies if we want to use the stencil buffer (for drawing shadows)
bool vsync = false;				// Specifies if we want to have vsync enabled, this is only useful in fullscreen mode.
int eventReceiver = 0;			// An object to receive events.We do not want to use this parameter here, and set it to 0.
int cam_x, cam_y, cam_z;

// clearing screen colors
int clear_r = 48;	
int clear_g = 48;	
int clear_b = 48;	
int clear_a = 256;

// Basic things
IrrlichtDevice* device;
IVideoDriver* driver;
ISceneManager* sceneManager;
IGUIEnvironment* GUI;

// Fonts
IGUIFont* basicFont;
IGUIFont* boldFont;

// Textures
ITexture* TWTexture;

// Model pathfiles
std::string modelPathfile = "Media/TT_RTS_Demo_Character.obj";
std::string modelTexturePathfile = "Media/TT_RTS_Units_blue.png";

// Meshes
IAnimatedMesh* modelMesh;		// mesh

// Animators
IAnimatedMeshSceneNode* animModel1;		// model1
IAnimatedMeshSceneNode* animModel2;		// model2
IAnimatedMeshSceneNode* animModel3;		// model3

// Textures
ITexture* modelTexture;


// Buttons ID's
enum
{
	// World
	GUI_CREATEWORLD, GUI_LOADWORLD, GUI_SAVEWORLD, GUI_GENERATEWORLD,
	
	// Help
	GUI_TUTORIAL, GUI_INFO,
	
	// bar
	BAR_BUTTON_WATER, BAR_BUTTON_SANDS, BAR_BUTTON_GRASS, BAR_BUTTON_ROCKS, BAR_BUTTON_HIGHLANDS, BAR_BUTTON_DARKNESS
};

float outerRadius = 10.0f;
float innerRadius = outerRadius * 0.866025404f;
float heighStep = 0.8f;

float hexVertices[] =
{
	0.0f, outerRadius,
	innerRadius, outerRadius * 0.5f,
	innerRadius, -outerRadius * 0.5f,
	0.0f, -outerRadius,
	-innerRadius, -outerRadius * 0.5f,
	-innerRadius, outerRadius * 0.5f,
	0.0f, outerRadius
};

float texture_uv[]
{
	0.0f, 1.0f,
	1.0f, 0.5f,
	1.0f, -0.5f,
	0.0f, -1.0f,
	-1.0f, -0.5f,
	-1.0f, 0.5f,
	0.0f, 1.0f,
};

float hexToGlobalX(float x, float z)
{
	return x * 2.0f * innerRadius + (int(z) % 2) * innerRadius;
}

float hexToGlobalZ(float z)
{
	return z* 1.5f * outerRadius;
}

enum class terrainType { water, sands, grass, rocks, highlands, darkness };

terrainType paint = terrainType::grass;

ITexture* getTexture(terrainType ttype)
{
	ITexture* tex = 0;
	
	if (ttype == terrainType::water)
		tex = driver->getTexture("Media/Terrains/water.png");

	if (ttype == terrainType::sands)
		tex = driver->getTexture("Media/Terrains/sands.png");
	
	if (ttype == terrainType::grass)
		tex = driver->getTexture("Media/Terrains/grass.png");

	if (ttype == terrainType::rocks)
		tex = driver->getTexture("Media/Terrains/rocks.png");

	if (ttype == terrainType::highlands)
		tex = driver->getTexture("Media/Terrains/highlands.png");

	if (ttype == terrainType::darkness)
		tex = driver->getTexture("Media/Terrains/darkness.png");

	return tex;
}

class HexTile : public scene::ISceneNode
{

	aabbox3d<f32> Box;
	S3DVertex Vertices[8];
	SMaterial Material;
	

public:
	terrainType ttype;

	HexTile(ISceneNode* parent, ISceneManager* mgr, s32 id);
	virtual void OnRegisterSceneNode();
	virtual void render();
	virtual const aabbox3d<f32>& getBoundingBox() const;
	virtual u32 getMaterialCount() const;
	virtual SMaterial& getMaterial(u32 i);
	void setTexture(ITexture*);
	void setTerrainType(terrainType);
};

HexTile::HexTile(ISceneNode* parent, ISceneManager* mgr, s32 id)
	: ISceneNode(parent, mgr, id)
{
	ttype = terrainType::grass;

	/////////////////////////////////////////////////
	Material.Wireframe = false;
	Material.Lighting = false;
	Material.setTexture(0, getTexture(ttype));
	
	SColor color =  SColor(255, 255, 255, 255);

	// vertices of hexagons
	for (int i = 0; i < 7; i++)
		Vertices[i+1] = S3DVertex(hexVertices[2*i], 0.0f, hexVertices[2 * i + 1], 0, 0, 0, color, texture_uv[2 * i], texture_uv[2 * i + 1]);

	Box.reset(Vertices[0].Pos);
	for (s32 i = 1; i < 7; ++i)
		Box.addInternalPoint(Vertices[i].Pos);
}

void HexTile::OnRegisterSceneNode()
{
	if (IsVisible)
		SceneManager->registerNodeForRendering(this);

	ISceneNode::OnRegisterSceneNode();
}

void HexTile::render()
{
	u16 indices[] = { 0, 1, 2, /**/ 0, 2, 3, /**/ 0, 3, 4, /**/ 0, 4, 5, /**/ 0, 5, 6, /**/ 0, 6, 7 };
	IVideoDriver* driver = SceneManager->getVideoDriver();
	driver->setMaterial(Material);
	driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
	driver->drawVertexPrimitiveList(&Vertices[0], 3, &indices[0], 6, video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);

}

const aabbox3d<f32>& HexTile::getBoundingBox() const
{
	return Box;
}

u32 HexTile::getMaterialCount() const
{
	return 1;
}

SMaterial& HexTile::getMaterial(u32 i)
{
	return Material;
}

void HexTile::setTexture(ITexture* tex)
{
	Material.setTexture(0, tex);
}

void HexTile::setTerrainType(terrainType ttype)
{
	this->ttype = ttype;
	setTexture(getTexture(ttype));
}

class HexMap
{
public:
	std::vector < HexTile* > tiles;

	HexMap();
	~HexMap();
	void addTile(HexTile*);
	void setTerrainType(terrainType);
};

HexMap::HexMap()
{
	tiles.clear();
}

HexMap::~HexMap()
{

}

void HexMap::addTile(HexTile* tile)
{
	tiles.push_back(tile);
}

void HexMap::setTerrainType(terrainType ttype)
{
	for (auto& t : tiles)
		t->setTerrainType(ttype);

}

HexMap* hexMap;

void thisIsNotBuildYet()
{
	int rectWidth = 300;
	int rectHeight = 300;
	int x1 = (screenWidth - rectWidth) / 2;
	int x2 = (screenWidth + rectWidth) / 2;
	int y1 = (screenHeight - rectHeight) / 2;
	int y2 = (screenHeight + rectHeight) / 2;

	rect<s32> rectangle = rect<s32>(x1, y1, x2, y2);

	IGUIWindow* window = GUI->addWindow(rectangle);

	const wchar_t* t = L"This section is not build yed";
	IGUIStaticText* text = GUI->addStaticText(t, rect<s32>(0, 20, rectWidth, rectHeight), true, true, window, -1, true);
	text->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);

}

void createWorld()
{
	std::cout << "created new world" << std::endl;
	thisIsNotBuildYet();
}

void loadWorld()
{
	std::cout << "load world" << std::endl;
	thisIsNotBuildYet();
}

void saveWorld()
{
	std::cout << "save world" << std::endl;
	thisIsNotBuildYet();
}

void generateWorld()
{
	std::cout << "generate world" << std::endl;
	thisIsNotBuildYet();
}

void tutorial()
{
	std::cout << "tutorial" << std::endl;
	thisIsNotBuildYet();
}

void info()
{
	std::cout << "info" << std::endl;

	int rectWidth = 300;
	int rectHeight = 300;
	int x1 = (screenWidth - rectWidth) / 2;
	int x2 = (screenWidth + rectWidth) / 2;
	int y1 = (screenHeight - rectHeight) / 2;
	int y2 = (screenHeight + rectHeight) / 2;

	rect<s32> rectangle = rect<s32>(x1, y1, x2, y2);

	IGUIWindow* window = GUI->addWindow(rectangle);
	const wchar_t* t = L"Program created by tBane";

	IGUIStaticText* text = GUI->addStaticText(t, rect<s32>(0, 20, rectWidth, rectHeight), true, true, window, -1, true);
	text->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
}

class MyEventReceiver : public IEventReceiver
{
public:
	bool KeyIsDown[KEY_KEY_CODES_COUNT];

	MyEventReceiver();
	virtual bool OnEvent(const SEvent&);
	virtual bool IsKeyDown(EKEY_CODE);
	bool OnMenuItemSelected(IGUIContextMenu* menu);
};


MyEventReceiver::MyEventReceiver()
{
	for (u32 i = 0; i < KEY_KEY_CODES_COUNT; ++i)
		KeyIsDown[i] = false;
}

bool MyEventReceiver::OnEvent(const SEvent& event)
{
	// Remember whether each key is down or up
	if (event.EventType == irr::EET_KEY_INPUT_EVENT)
	{
		KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
		return true;
	}

	if (event.EventType == EET_GUI_EVENT)
	{
		switch (event.GUIEvent.EventType)
		{
		case EGET_MENU_ITEM_SELECTED:		// main menu events
		{
			IGUIContextMenu* menu = (IGUIContextMenu*)event.GUIEvent.Caller;
			s32 id = menu->getItemCommandId(menu->getSelectedItem());

			if (id == GUI_CREATEWORLD)
				createWorld();

			if (id == GUI_LOADWORLD)
				loadWorld();

			if (id == GUI_SAVEWORLD)
				saveWorld();

			if (id == GUI_GENERATEWORLD)
				generateWorld();

			if (id == GUI_TUTORIAL)
				tutorial();

			if (id == GUI_INFO)
				info();

		}
		break;
		
		case EGET_BUTTON_CLICKED:
		{
			s32 id = event.GUIEvent.Caller->getID();

			if (id == BAR_BUTTON_WATER)
			{
				paint = terrainType::water;
				hexMap->setTerrainType(paint);
				std::cout << "setted a water to paint" << std::endl;
			}
				
			if (id == BAR_BUTTON_SANDS)
			{
				paint = terrainType::sands;
				hexMap->setTerrainType(paint);
				std::cout << "setted a sands to paint" << std::endl;
			}

			if (id == BAR_BUTTON_GRASS)
			{
				paint = terrainType::grass;
				hexMap->setTerrainType(paint);
				std::cout << "setted a grass to paint" << std::endl;
			}

			if (id == BAR_BUTTON_ROCKS)
			{
				paint = terrainType::rocks;
				hexMap->setTerrainType(paint);
				std::cout << "setted a rocks to paint" << std::endl;
			}

			if (id == BAR_BUTTON_HIGHLANDS)
			{
				paint = terrainType::highlands;
				hexMap->setTerrainType(paint);
				std::cout << "setted a highlands to paint" << std::endl;
			}

			if (id == BAR_BUTTON_DARKNESS)
			{
				paint = terrainType::darkness;
				hexMap->setTerrainType(paint);
				std::cout << "setted a darkness to paint" << std::endl;
			}
		}
		break;

		default:
			break;
		}
	}

	return false;
}

bool MyEventReceiver::IsKeyDown(EKEY_CODE keyCode)
{
	return KeyIsDown[keyCode];
}


int main()
{
	MyEventReceiver receiver;
	// CREATE DEVICE ( OpenGL )
	device = createDevice(EDT_SOFTWARE, dimension2d<u32>(screenWidth, screenHeight), bitsPerPixel, fullscreen, stencilbuffer, vsync, &receiver);

	if (!device)	// if no Device then error
		return 1;

	// GET THE BASIC THINGS
	driver = device->getVideoDriver();			// get the Video Driver
	sceneManager = device->getSceneManager();	// get the Scene
	GUI = device->getGUIEnvironment();			// get the GUI Manager

	// LOAD THE FONTS
	basicFont = device->getGUIEnvironment()->getBuiltInFont();							// get the Default Font
	boldFont = device->getGUIEnvironment()->getFont("media/fonthaettenschweiler.bmp");	// get the Bold Font


	// STYLES FOR GUI
	IGUISkin* GUIskin = GUI->getSkin();
	GUIskin->setFont(boldFont);

	for (s32 i = 0; i < gui::EGDC_COUNT; ++i)
	{
		GUIskin->setColor((EGUI_DEFAULT_COLOR)i, SColor(255, 96, 96, 96));	// coloring the Background
		GUIskin->setColor(EGDC_BUTTON_TEXT, SColor(255, 224, 224, 224));	// coloring the Text
		GUIskin->setColor(EGDC_HIGH_LIGHT_TEXT, SColor(255, 128, 48, 48));	// coloring the Highlighed Text
	}

	// CREATE MAIN MENU
	IGUIContextMenu* menu = GUI->addMenu();
		menu->addItem(L"World", -1, true, true);
		menu->addItem(L"Help", -1, true, true);

	// Create World Menu
	IGUIContextMenu* worldMenu = menu->getSubMenu(0);
		worldMenu->addItem(L"Create World", GUI_CREATEWORLD);
		worldMenu->addItem(L"Load World", GUI_LOADWORLD);
		worldMenu->addItem(L"Save world", GUI_SAVEWORLD);
		worldMenu->addItem(L"Generate World", GUI_GENERATEWORLD);

	// Create Help Menu
	IGUIContextMenu* helpMenu = menu->getSubMenu(1);				
		helpMenu->addItem(L"Tutorial", GUI_TUTORIAL);
		helpMenu->addItem(L"Info", GUI_INFO);

	//
	gui::IGUIToolBar* bar = GUI->addToolBar();
	bar->setMinSize(dimension2du(screenWidth, 48));
	IGUIButton* water = bar->addButton(BAR_BUTTON_WATER, 0, L"water", driver->getTexture("Media/GUI/water.png"), 0, false, true);
	IGUIButton* sands = bar->addButton(BAR_BUTTON_SANDS, 0, L"sands", driver->getTexture("Media/GUI/sands.png"), 0, false, true);
	IGUIButton* grass = bar->addButton(BAR_BUTTON_GRASS, 0, L"grass", driver->getTexture("Media/GUI/grass.png"), 0, false, true);
	IGUIButton* rocks = bar->addButton(BAR_BUTTON_ROCKS, 0, L"rocks", driver->getTexture("Media/GUI/rocks.png"), 0, false, true);
	IGUIButton* highlands = bar->addButton(BAR_BUTTON_HIGHLANDS, 0, L"highlands", driver->getTexture("Media/GUI/highlands.png"), 0, false, true);
	IGUIButton* darkness = bar->addButton(BAR_BUTTON_DARKNESS, 0, L"darkness", driver->getTexture("Media/GUI/darkness.png"), 0, false, true);

	// LOAD THE "TW Editor Logo"
	TWTexture = driver->getTexture("Media/TW.png");

	// ADD CAMERA
	cam_x = 0;
	cam_y = 100;
	cam_z = -40;

	ICameraSceneNode* cam = sceneManager->addCameraSceneNode(0, vector3df(cam_x, 30, cam_z), vector3df(0, 5, 0));
	cam->setTarget(vector3df(cam_x, cam_y, cam_z));
	
	
	// CURSOR IS HIDDEN
	device->getCursorControl()->setVisible(true);

	// LOAD THE MODEL 
	modelMesh = sceneManager->getMesh(modelPathfile.c_str());
	if (!modelMesh)
		device->drop();
	
	
	animModel1 = sceneManager->addAnimatedMeshSceneNode(modelMesh);		// Add Model1
		animModel1->setScale(vector3df(10, 10, 10));
		animModel1->setPosition(vector3df(hexToGlobalX(0,0), 0, hexToGlobalZ(0)));
		animModel1->setRotation(vector3df(0, 180, 0));
		animModel1->setMaterialFlag(EMF_LIGHTING, false);
		animModel1->setMD2Animation(scene::EMAT_STAND);
		animModel1->setMaterialTexture(0, driver->getTexture(modelTexturePathfile.c_str()));
	
	animModel2 = sceneManager->addAnimatedMeshSceneNode(modelMesh);		// Add Model2
		animModel2->setScale(vector3df(10, 10, 10));
		animModel2->setPosition(vector3df(hexToGlobalX(3, 4), 0, hexToGlobalZ(4)));
		animModel2->setRotation(vector3df(0, 180, 0));
		animModel2->setMaterialFlag(EMF_LIGHTING, false);
		animModel2->setMD2Animation(scene::EMAT_STAND);
		animModel2->setMaterialTexture(0, driver->getTexture(modelTexturePathfile.c_str()));

	animModel3 = sceneManager->addAnimatedMeshSceneNode(modelMesh);		// Add Model3
		animModel3->setScale(vector3df(10, 10, 10));
		animModel3->setPosition(vector3df(hexToGlobalX(7, 5), 0, hexToGlobalZ(5)));
		animModel3->setRotation(vector3df(0, 180, 0));
		animModel3->setMaterialFlag(EMF_LIGHTING, false);
		animModel3->setMD2Animation(scene::EMAT_STAND);
		animModel3->setMaterialTexture(0, driver->getTexture(modelTexturePathfile.c_str()));

	// Create HexMap
	hexMap = new HexMap();
	for (int z = 0; z < 40; z++)
	{
		for (int x = 0; x < 40; x++)
		{
			HexTile* tile = new HexTile(sceneManager->getRootSceneNode(), sceneManager, -1);
			tile->setPosition(vector3df(hexToGlobalX(x,z), 0, hexToGlobalZ(z)));
			hexMap->addTile(tile);
		}
	}
	
	// MAIN "TW Editor" LOOP 
	while (device->run())
	{
		if (device->isWindowActive())
		{
			
			// EVENTS
			if (receiver.IsKeyDown(irr::KEY_ESCAPE))	// if press ESCAPE then exit
			{
				device->drop();
				return 0;
			}

			if (receiver.IsKeyDown(irr::KEY_KEY_A) || receiver.IsKeyDown(irr::KEY_LEFT))	cam_x -= 2.0f;
			if (receiver.IsKeyDown(irr::KEY_KEY_D) || receiver.IsKeyDown(irr::KEY_RIGHT))	cam_x += 2.0f;
			if (receiver.IsKeyDown(irr::KEY_KEY_W) || receiver.IsKeyDown(irr::KEY_UP))		cam_z += 2.0f;
			if (receiver.IsKeyDown(irr::KEY_KEY_S) || receiver.IsKeyDown(irr::KEY_DOWN))	cam_z -= 2.0f;

			// UPDATE
			cam->setPosition(vector3df(cam_x, cam_y, cam_z));
			cam->setTarget(vector3df(cam_x, 30, cam_z+50));

			// RENDER
			driver->beginScene(true, true, SColor(clear_a, clear_r, clear_g, clear_b));														// clear screen
				sceneManager->drawAll();																										// render scene
				driver->draw2DImage(TWTexture, position2d<s32>(0, screenHeight - 128 - 20), rect<s32>(0, 0, 128, 128));							// render TW Logo
				boldFont->draw(L"TW World Editor v0.1", recti(20, screenHeight - 20, 100, screenHeight), SColor(256, 128, 48, 48), true, true);	// render text on bottom
				GUI->drawAll();																													// render GUI
				position2d<s32> m = device->getCursorControl()->getPosition();																	// render cursor
			driver->endScene();																												// render submit

			// FPS
			int currentFPS = driver->getFPS();
			core::stringw str = L"FPS: ";
			str += currentFPS;
			device->setWindowCaption(str.c_str());
		}
		else
			device->yield();	// if window is inactive not use CPU

	}

	// In the end, delete the Irrlicht device.
	device->drop();
	return 0;
}
0

Napisałem taką funkcję, używając Ray Casting ale nie działa:


	position2d < s32 > mousePos = device->getCursorControl()->getPosition();
	cout << "mouse position: " << mousePos.X << ", " << mousePos.Y<<" - ";
			
	core::line3d<f32> ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(mousePos, cam);
	core::vector3df intersection;
	core::triangle3df hitTriangle;
	scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager();

	if (collMan != nullptr)
		cout << "collman ok - ";

	scene::ISceneNode* selectedSceneNode =
	collMan->getSceneNodeAndCollisionPointFromRay(
			ray,
			intersection,	// This will be the position of the collision
			hitTriangle);// ,	// This will be the triangle hit in the collision

	if (selectedSceneNode != nullptr)
		cout << " | " << selectedSceneNode->getPosition().X << ", " << selectedSceneNode->getPosition().Y << endl;
	else
		cout << " node is null\n";

1 użytkowników online, w tym zalogowanych: 0, gości: 1