#include "primitive_plugin.h" #include "../world_editor/world_editor.h" #include "../world_editor/display.h" #include #include #include #include using namespace std; using namespace NLMISC; using namespace NLLIGO; CFileDisplayer *PrimitivePluginLogDisplayer= NULL; extern "C" { void *createPlugin() { return new CPrimitivePlugin(); } } CPrimitivePlugin::CPrimitivePlugin() { NLMISC::createDebug(); PrimitivePluginLogDisplayer= new CFileDisplayer("world_editor_primitive_plugin.log", true, "WORLD_EDITOR_PRIMITIVE_PLUGIN.LOG"); DebugLog->addDisplayer (PrimitivePluginLogDisplayer); InfoLog->addDisplayer (PrimitivePluginLogDisplayer); WarningLog->addDisplayer (PrimitivePluginLogDisplayer); ErrorLog->addDisplayer (PrimitivePluginLogDisplayer); AssertLog->addDisplayer (PrimitivePluginLogDisplayer); nlinfo("Starting primitive plugin..."); _PluginActive = false; _PluginAccess = NULL; } bool CPrimitivePlugin::isActive() { return _PluginActive; } bool CPrimitivePlugin::activatePlugin() { _PluginActive = true; // TODO : open the 'rebuild npc data' dialog box return true; } bool CPrimitivePlugin::closePlugin() { _PluginActive = false; return true; } std::string& CPrimitivePlugin::getName() { static string name("Primitive displayer"); return name; } void CPrimitivePlugin::TCreatureInfo::readGeorges (const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId) { const NLGEORGES::UFormElm &item=form->getRootNode(); // the form was found so read the true values from Georges item.getValueByName(Radius, "Collision.CollisionRadius"); HaveRadius = Radius != 0.0f; item.getValueByName(Length, "Collision.Length"); item.getValueByName(Width, "Collision.Width"); HaveBox = (Length != 0 && Width != 0); } void CPrimitivePlugin::TCreatureInfo::serial (NLMISC::IStream &s) { s.serial(HaveRadius); s.serial(Radius); s.serial(HaveBox); s.serial(Width); s.serial(Length); } uint CPrimitivePlugin::TCreatureInfo::getVersion () { return 1; } // @{ // \name Overload for IPluginCallback void CPrimitivePlugin::init(IPluginAccess *pluginAccess) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); AfxEnableControlContainer(); _PluginAccess = pluginAccess; string packedFileName("primitive_plugin.packed_sheets"); vector paths; string sheetIdPath; // add the search path CConfigFile &cf = pluginAccess->getConfigFile(); CConfigFile::CVar *pv = cf.getVarPtr("PrimitivePluginPath"); if (pv) { for (uint i=0; isize(); ++i) paths.push_back(pv->asString(i)); } // add the sheetId file pv = cf.getVarPtr("PrimitivePluginSheetId"); sheetIdPath = pv->asString(); // Init the sheet id CPath::addSearchFile(sheetIdPath); CSheetId::init(false); // Read the sheets if (NLMISC::CFile::fileExists(packedFileName)) loadForm("creature", packedFileName, _CreatureInfos, false, false); else { for (uint i=0; i classNames; classNames.push_back("npc_bot"); _PluginAccess->registerPrimitiveDisplayer(this, classNames); } /// The current region has changed. void CPrimitivePlugin::primitiveChanged(const NLLIGO::IPrimitive *root) { } void CPrimitivePlugin::drawPrimitive(const NLLIGO::IPrimitive *primitive, const TRenderContext &ctx) { // AFX_MANAGE_STATE(AfxGetStaticModuleState()); static const float POINT_ARROW_LINE_SIZE = 20.f; static const float POINT_ARROW_HEAD_SIZE = 8.f; static const float POINT_DOT_SIZE = 3.f; static const uint CIRCLE_SEGMENT_SIZE = 20; static const uint CIRCLE_MIN_SEGMENT_COUNT = 8; std::string *sheetName; primitive->getPropertyByName("sheet_client", sheetName); TCreatureInfo *info = NULL; if (!sheetName->empty()) { // two step init of id to remove a flooding NeL warning CSheetId id; id.buildSheetId(*sheetName+".creature"); std::map::iterator it(_CreatureInfos.find(id)); if (it != _CreatureInfos.end()) { info = &(it->second); } } const CPrimPoint *point = dynamic_cast(primitive); if (point) { // Clip ? if (!ctx.Display->isClipped (&point->Point, 1)) { // Position in world CVector center = point->Point; ctx.Display->worldToPixel (center); // Dot CVector dot0, dot1, dot2, dot3; dot0 = center; dot0.x += POINT_DOT_SIZE; dot0.y += POINT_DOT_SIZE; dot1 = center; dot1.x -= POINT_DOT_SIZE; dot1.y += POINT_DOT_SIZE; dot2 = center; dot2.x -= POINT_DOT_SIZE; dot2.y -= POINT_DOT_SIZE; dot3 = center; dot3.x += POINT_DOT_SIZE; dot3.y -= POINT_DOT_SIZE; // Transform primitive transformVector (dot0, point->Angle, center); transformVector (dot1, point->Angle, center); transformVector (dot2, point->Angle, center); transformVector (dot3, point->Angle, center); // In world space ctx.Display->pixelToWorld (center); ctx.Display->pixelToWorld (dot0); ctx.Display->pixelToWorld (dot1); ctx.Display->pixelToWorld (dot2); ctx.Display->pixelToWorld (dot3); // Draw it ctx.Display->triRenderProxy (ctx.MainColor, dot0, dot1, dot2, ctx.Selected?2:0); ctx.Display->triRenderProxy (ctx.MainColor, dot2, dot3, dot0, ctx.Selected?2:0); // Need detail? if (ctx.ShowDetail) { // Prim class available ? const CPrimitiveClass *primClass = ctx.PrimitiveClass; if (primClass != NULL) { // Draw an arraow ? if (primClass->ShowArrow) { // Position in world center = point->Point; ctx.Display->worldToPixel (center); CVector arrow = center; CVector arrow0 = center; arrow.x += POINT_ARROW_LINE_SIZE; CVector arrow1 = arrow; CVector arrow2 = arrow; arrow0.x += POINT_ARROW_LINE_SIZE + POINT_ARROW_HEAD_SIZE; arrow1.y += POINT_ARROW_HEAD_SIZE; arrow2.y -= POINT_ARROW_HEAD_SIZE; // Transform primitive transformVector (arrow, point->Angle, center); transformVector (arrow0, point->Angle, center); transformVector (arrow1, point->Angle, center); transformVector (arrow2, point->Angle, center); // In world space ctx.Display->pixelToWorld (center); ctx.Display->pixelToWorld (arrow); ctx.Display->pixelToWorld (arrow0); ctx.Display->pixelToWorld (arrow1); ctx.Display->pixelToWorld (arrow2); // Draw it ctx.Display->lineRenderProxy (ctx.MainColor, center, arrow, ctx.Selected?2:0); ctx.Display->triRenderProxy (ctx.ArrowColor, arrow0, arrow1, arrow2, ctx.Selected?2:0); } } // Have bounding info ? if (info != NULL) { if (info->HaveRadius) { // Get it float fRadius = info->Radius; // Get the perimeter float perimeter = 2.f*(float)Pi*fRadius; // Get the perimeter on the screen perimeter *= (float)ctx.Display->getWidth() / (ctx.Display->_CurViewMax.x - ctx.Display->_CurViewMin.x); // Get the segement count perimeter /= (float)CIRCLE_SEGMENT_SIZE; // Clamp if (perimeter < CIRCLE_MIN_SEGMENT_COUNT) perimeter = CIRCLE_MIN_SEGMENT_COUNT; // Segment count uint segmentCount = (uint)perimeter; // Draw a circle CVector posInit = center; posInit.x += fRadius; CVector posPrevious = posInit; for (uint i=1; ilineRenderProxy (ctx.MainColor, pos, posPrevious, ctx.Selected?2:0); posPrevious = pos; } } if (info->HaveBox) { CVector center = point->Point; // ctx.Display->worldToPixel (center); // Dot CVector dot0, dot1, dot2, dot3; dot0 = center; dot0.x += info->Length/2; dot0.y += info->Width/2; dot1 = center; dot1.x -= info->Length/2; dot1.y += info->Width/2; dot2 = center; dot2.x -= info->Length/2; dot2.y -= info->Width/2; dot3 = center; dot3.x += info->Length/2; dot3.y -= info->Width/2; // Transform primitive transformVector (dot0, point->Angle, center); transformVector (dot1, point->Angle, center); transformVector (dot2, point->Angle, center); transformVector (dot3, point->Angle, center); // In world space /* ctx.Display->pixelToWorld (center); ctx.Display->pixelToWorld (dot0); ctx.Display->pixelToWorld (dot1); ctx.Display->pixelToWorld (dot2); ctx.Display->pixelToWorld (dot3); */ // Draw it ctx.Display->lineRenderProxy (ctx.MainColor, dot0, dot1, ctx.Selected?2:0); ctx.Display->lineRenderProxy (ctx.MainColor, dot1, dot2, ctx.Selected?2:0); ctx.Display->lineRenderProxy (ctx.MainColor, dot2, dot3, ctx.Selected?2:0); ctx.Display->lineRenderProxy (ctx.MainColor, dot3, dot0, ctx.Selected?2:0); } } } } } }