//在小地图中描画出路径的轮廓.仿造艾尔之光副本中小地图
//粗糙的版本.自行修改.
#ifndef __UI3DRadarMap_H__
#define __UI3DRadarMap_H__
#include "Loki/Singleton.h"
#include "SeerBaseConfig.h"
#include <Ogre/Ogre.h>
#include <map>
#include "SeerNetProcotolData.h"
#include "Loki/Singleton.h"
#define UI3DRadarMapExport __declspec( dllexport )
namespace Orz
{
class CSeerEntityInterface;
class UI3DRadarMapExport UI3DRadarMap
{
public:
typedef std::vector<Ogre::Vector3> WayPointList;
typedef std::map<std::string, WayPointList> PathList;
private:
typedef Loki::SingletonHolder<UI3DRadarMap> MySingleton;
public:
inline static UI3DRadarMap& Instance() { return MySingleton::Instance(); }
UI3DRadarMap();
void init(Ogre::SceneManager* sm = NULL);
void shutdown();
void update(TimeType time);
void setup();
void loadPath();
void drawWay(WayPointList & waylist);
void reset();
void updateMonstersCursor();
void hideMonsterCursor(guid_t id);
void setSceneVisible(bool visible);
struct Compare
{
typedef guid_t key_type;
bool operator () (const key_type& ls, const key_type& rs) const
{
return ls.id < rs.id ||
ls.id == rs.id && ls.type < rs.type ||
ls.id == rs.id && ls.type == rs.type && ls.index < rs.index;
}
};
typedef std::map<guid_t, ComponentPtr, Compare> MonsterCursorMap;
CEGUI::Window* _window;
CEGUI::OgreRenderer* _render;
CEGUI::RenderingWindow* _cerenderwindow;
Ogre::SceneManager* _scenemgr;
Ogre::TexturePtr _rtttexture;
Ogre::RenderTarget * _renderTarget;
Ogre::Camera * _camera;
Ogre::SceneNode * _node;
Ogre::ManualObject* _3dobject;
Ogre::Entity* _entity;
float _aspectFactor;
MonsterCursorMap _monstersCursors;
ComponentPtr _charCursorComp;
CSeerEntityInterface* _charCursor;
PathList _paths;
};
}
#endif
#include "SeerUIComponentStableHeaders.h"
#include "UI3DRadarMap.h"
#include <cegui/CEGUI.h>
#include <cegui/RendererModules/Ogre/CEGUIOgreRenderer.h>
#include <Orz/View_CEGUI/CEGUIManager.h>
#include "SimpleLogManager.h"
#include "RadarMapCursorInterface.h"
#include "SeerInterfaceManager.h"
#include "SeerMonsterLayoutInterface.h"
#include "CSeerEntityInterface.h"
#include "SeerInterfaceManager.h"
#include "SeerCharactorMoveInterface.h"
#include "SeerInterfaceManager.h"
#include "SeerHelper.h"
#include "SeerSquareInterface.h"
static float G_WIDTH_X = 3000;
static float G_HEIGHT_Y = 1500;
#define SMALLDELTA 0.05
namespace Orz
{
//////////////////////////////////////////////////////////////////////////
UI3DRadarMap::UI3DRadarMap():
_window(NULL),
_scenemgr(NULL),
_cerenderwindow(NULL),
_render(NULL),
_renderTarget(NULL),
_camera(NULL),
_node(NULL),
_3dobject(NULL)
{
}
void UI3DRadarMap::init(Ogre::SceneManager* sm)
{
_window = CEGUI::WindowManager::getSingleton().getWindow("KJMainGame2_Nmap");
_cerenderwindow = (CEGUI::RenderingWindow*)_window->getRenderingSurface();
_render = Orz::CEGUIManager::getSingletonPtr()->getRenderer();
_aspectFactor = _window->getPixelSize().d_width / _window->getPixelSize().d_height;
_rtttexture = Ogre::TextureManager::getSingleton().createManual("rtt_3dradarmap",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D, 256, 256, 1, 0,
Ogre::PF_R8G8B8A8, Ogre::TU_RENDERTARGET);
_renderTarget = _rtttexture->getBuffer()->getRenderTarget();
_renderTarget->setActive(true);
_renderTarget->setAutoUpdated(true);
if (sm!=NULL) {
_scenemgr = sm;
} else {
_scenemgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC, "ui3dradarmap_scenemanager");
}
_node = _scenemgr->getRootSceneNode()->createChildSceneNode("ui3dradarmap_rootnode");
_camera = _scenemgr->createCamera("ui3dradarmap_camera");
_node->attachObject(_camera);
_camera->setNearClipDistance(5);
_camera->move(Ogre::Vector3(0, 0.0f, 100.0f));
_camera->lookAt(Ogre::Vector3(0, 0.0f, -100.0f));
_camera->setProjectionType(Ogre::PT_PERSPECTIVE);
_camera->setAspectRatio(_aspectFactor);//图片比例
_camera->setFOVy(Ogre::Degree(45.0f));
Ogre::Viewport *vp = _renderTarget->addViewport(_camera);
vp->setAutoUpdated(true);
vp->setBackgroundColour(Ogre::ColourValue(0,0,0,0));
vp->setOverlaysEnabled(false);
vp->setClearEveryFrame(true);
vp->setSkiesEnabled(false);
CEGUI::Texture &ctex = CEGUIManager::getSingletonPtr()->getRenderer()->createTexture(_rtttexture,false);
CEGUI::Imageset &imgset = CEGUI::ImagesetManager::getSingleton().create("ui3dradarmap_imageset",ctex);
imgset.defineImage("RttImage",CEGUI::Point(0,0),ctex.getSize(),CEGUI::Point(0,0));
_window->setProperty("Image", CEGUI::PropertyHelper::imageToString(&imgset.getImage("RttImage")));
_window->show();
_charCursorComp = Orz::ComponentFactories::getInstance().create("entity");
_charCursor = _charCursorComp->queryInterface<CSeerEntityInterface>();
_charCursor->load("ui3dradarmap_char_cursor", "Effect/map/cursor/char/char_cursor.mesh", false, _node);
_charCursor->getSceneNode()->setScale(2.5, 2.5, 2.5);
}
void UI3DRadarMap::loadPath()
{
_paths.clear();
SeerSquareInterface* square = SeerInterfaceManager::getSingleton().queryInterface<SeerSquareInterface>();
typedef std::vector<SeerHelperPtr> PathNodeList;
std::vector<SeerHelperPtr>& pathnodes = square->getHelperMap();
std::vector<SeerHelperPtr>::iterator it = pathnodes.begin();
for (; it != pathnodes.end(); ++it)
{
SeerHelperPtr helper = *it;
if(helper->type == "path") continue;
PathList::iterator it_path = _paths.find(helper->name);
if (it_path == _paths.end())
{
WayPointList waylist;
if(helper->node)
waylist.push_back(helper->node->_getDerivedPosition());
_paths.insert(std::make_pair(helper->name, waylist));
}
else
{
if(helper->node)
it_path->second.push_back(helper->node->_getDerivedPosition());
}
}
}
void UI3DRadarMap::setup()
{
reset();
PathList::iterator it_path = _paths.begin();
for (; it_path != _paths.end(); ++it_path)
{
drawWay(it_path->second);
}
//WayPointList waylist;
//for (int i = 0; i < 50; i+=2)
//{
// waylist.push_back(Ogre::Vector3(-10000+400*i, -200, 0));
// waylist.push_back(Ogre::Vector3(-10000+400*(i+1), -200, 0));
// waylist.push_back(Ogre::Vector3(-10000+400*(i+1), 200, 0));
// waylist.push_back(Ogre::Vector3(-10000+400*(i+2), 200, 0));
//}
//drawWay(waylist);
//waylist.clear();
//waylist.push_back(Ogre::Vector3(-10000, -50, 0));
//waylist.push_back(Ogre::Vector3(-5000, 50, 0));
//waylist.push_back(Ogre::Vector3(5000, -50, 0));
//waylist.push_back(Ogre::Vector3(10000, 50, 0));
//drawWay(waylist);
}
void UI3DRadarMap::drawWay(WayPointList & waylist)
{
static int width = 40;
_3dobject->begin("ui3dradarmap_road");
WayPointList::iterator it_p = waylist.begin();
_3dobject->position(*it_p);
_3dobject->position(*it_p + width* Ogre::Vector3::UNIT_Y);
++it_p;
if(it_p == waylist.end()) return;
for (; (it_p + 1) != waylist.end(); ++it_p)
{
Ogre::Vector3 cur_point = *it_p;
Ogre::Vector3 pre_point = *(it_p-1);
Ogre::Vector3 nex_point = *(it_p+1);
Ogre::Vector3 pre_dir = cur_point - pre_point;
Ogre::Vector3 nex_dir = nex_point - cur_point;
Ogre::Vector3 mid_dir = (nex_dir - pre_dir) / 2;
Ogre::Vector3 vertical_dir(-pre_dir.y, pre_dir.x, pre_dir.z);
pre_dir.normalise();
nex_dir.normalise();
mid_dir.normalise();
vertical_dir.normalise();
Ogre::Vector3 offset;
float cos_v = nex_dir.dotProduct(pre_dir);
float angle_v = std::acos(cos_v);
if(angle_v < SMALLDELTA )
{
offset = width * vertical_dir;
}
else
{
if(nex_dir.crossProduct(pre_dir).z > 0)
mid_dir = - mid_dir;
offset = ( width / std::abs(sin(angle_v/2)) ) * mid_dir;
}
Ogre::Vector3 cur_point_up = cur_point + offset;
_3dobject->position(cur_point);
_3dobject->position(cur_point_up);
}
_3dobject->position(*it_p);
_3dobject->position(*it_p + width* Ogre::Vector3::UNIT_Y);
for (size_t i = 0; i < waylist.size()-1; i++)
_3dobject->quad(2*i+3, 2*i+1, 2*i, 2*i+2);
_3dobject->end();
}
void UI3DRadarMap::shutdown()
{
}
void UI3DRadarMap::update(TimeType time)
{
if(!_camera) return;
Ogre::Camera* cam = OgreGraphicsManager::getSingletonPtr()->getCamera();
_camera->setPosition(cam->getDerivedPosition());
_camera->setDirection(cam->getDerivedDirection());
SeerCharactorMoveInterface* move = SeerInterfaceManager::getSingletonPtr()->queryInterface<SeerCharactorMoveInterface>();
if(move == NULL) return;
Ogre::Vector3 charpos = move->getBodySceneNode()->_getDerivedPosition();
_charCursor->getSceneNode()->_setDerivedPosition(charpos);
updateMonstersCursor();
}
void UI3DRadarMap::updateMonstersCursor()
{
SeerMonsterLayoutInterface* monsterLayout = SeerInterfaceManager::getSingleton().queryInterface<SeerMonsterLayoutInterface>();
if(monsterLayout == NULL) return;
std::vector<std::pair<guid_t, Ogre::Vector3>> monstersPosList = monsterLayout->getMonstersPosition();
std::vector<std::pair<guid_t, Ogre::Vector3>>::iterator it_pair = monstersPosList.begin();
for (; it_pair != monstersPosList.end(); ++it_pair)
{
MonsterCursorMap::iterator it = _monstersCursors.find(it_pair->first);
ComponentPtr cursorComp;
CSeerEntityInterface* cursorEnt;
if (it == _monstersCursors.end())
{
cursorComp = Orz::ComponentFactories::getInstance().create("entity");
cursorEnt = cursorComp->queryInterface<CSeerEntityInterface>();
cursorEnt->setSceneManager(_scenemgr);
cursorEnt->load(
"ui3dradarmap_monster_cursor_"+boost::lexical_cast<std::string>(_monstersCursors.size()),
"Effect/map/cursor/monster/monster_cursor.mesh", false, _node);
cursorEnt->getSceneNode()->setScale(2.5, 2.5, 2.5);
_monstersCursors.insert(std::make_pair(it_pair->first, cursorComp));
}
else
{
cursorComp = it->second;
cursorEnt = cursorComp->queryInterface<CSeerEntityInterface>();
}
cursorEnt->getSceneNode()->_setDerivedPosition(it_pair->second);
}
}
void UI3DRadarMap::reset()
{
_monstersCursors.clear();
if(_3dobject) {
_3dobject->detachFromParent();
if(_scenemgr) {
_scenemgr->destroyManualObject(_3dobject->getName());
}
}
_3dobject = _scenemgr->createManualObject("ui3dradarmap_manualobject");
_node->attachObject(_3dobject);
}
void UI3DRadarMap::hideMonsterCursor(guid_t id)
{
MonsterCursorMap::iterator it = _monstersCursors.find(id);
if(it == _monstersCursors.end()) return;
CSeerEntityInterface* radarCursor = it->second->queryInterface<CSeerEntityInterface>();
radarCursor->getSceneNode()->setVisible(false);
}
void UI3DRadarMap::setSceneVisible(bool visible)
{
if(_node)
_node->setVisible(visible);
CEGUI::Window* roleCursor = CEGUI::WindowManager::getSingleton().getWindow("KJMainGame2_mapRole");
if(roleCursor)
roleCursor->setVisible(!visible);
}
}