Add infos into target window
[ryzomcore.git] / ryzom / client / src / r2 / tool_draw_prim.cpp
blob3cf05944f133d9a651d4f61ea6f24a477092ffac
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "stdpch.h"
23 #include "../interface_v3/group_map.h"
25 #include "tool_draw_prim.h"
26 #include "game_share/object.h"
27 #include "dmc/idmc.h"
28 #include "editor.h"
29 #include "r2_config.h"
30 #include "object_factory_client.h"
31 #include "displayer_visual_group.h"
32 #include "tool_maintained_action.h"
34 #include "nel/misc/vectord.h"
35 #include "nel/misc/i18n.h"
36 #include "nel/misc/polygon.h"
38 // tmp tmp
39 #include "nel/gui/ctrl_quad.h"
41 #ifdef DEBUG_NEW
42 #define new DEBUG_NEW
43 #endif
45 using namespace NLMISC;
47 namespace R2
51 // ***************************************************************
52 CToolDrawPrim::CToolDrawPrim(TPrimType primType, CInstance *extending /*= NULL*/)
54 _NumPoints = 0;
55 _ValidPos = false;
56 _PrimType = primType;
57 _MustClose = false;
58 _PrimInitialized = false;
59 _ValidPrim = true;
60 _DistinctLastPoint = true;
61 _ExtendedPrimitive = extending;
62 _Extending = (_ExtendedPrimitive != NULL);
63 _StartNumPoints = 0;
64 _InaccessibleParts = false;
65 _Commited = false;
66 _ForceShowPrims = false;
70 // ***************************************************************
71 bool CToolDrawPrim::canTerminate() const
73 //H_AUTO(R2_CToolDrawPrim_canTerminate)
74 return ((_PrimType == Road && _NumPoints >= 1) || _NumPoints >= 3) && _ValidPrim;
77 // ***************************************************************
78 const char *CToolDrawPrim::getToolUIName() const
80 //H_AUTO(R2_CToolDrawPrim_getToolUIName)
81 return _PrimType == Road ? "drawRoad" : "drawRegion";
85 // ***************************************************************
86 bool CToolDrawPrim::init(const CLuaObject &parameters)
88 //H_AUTO(R2_CToolDrawPrim_init)
89 _Points.clear();
90 _PrimLook.init(parameters["Look"]);
91 if (!parameters["InvalidLook"].isNil())
93 _PrimLookInvalid.init(parameters["InvalidLook"]);
95 else
97 _PrimLookInvalid = _PrimLook;
99 if (!parameters["CanCloseLook"].isNil())
101 _PrimLookCanClose.init(parameters["CanCloseLook"]);
103 else
105 _PrimLookCanClose = _PrimLook;
108 if (!parameters["InaccessibleLook"].isNil())
110 _PrimLookInaccessible.init(parameters["InaccessibleLook"]);
112 else
114 _PrimLookInaccessible = _PrimLook;
117 //TMP TMP hardcoded for first test
118 _PrimLookInaccessible.init(getEditor().getEnv()["PrimRender"]["RoadLookInaccessible"]);
120 _InaccessiblePrim.setLook(_PrimLookInaccessible);
122 CLuaObject vertices = parameters["Vertices"];
123 if (vertices.isTable())
125 // if start points where given, use them
126 ENUM_LUA_TABLE(vertices, it)
128 CLuaObject &vertex = it.nextValue();
129 _Points.push_back(NLMISC::CVector((float) vertex["x"].toNumber(), (float) vertex["y"].toNumber(), (float) vertex["z"].toNumber()));
132 if (!parameters["ExtendedPrimitiveId"].isNil())
134 std::string extendedPrimitiveId = parameters["ExtendedPrimitiveId"];
135 _ExtendedPrimitive = getEditor().getInstanceFromId(extendedPrimitiveId);
136 if (!_ExtendedPrimitive)
138 _Extending = false;
139 nlwarning("Can't extend primitive with id %s", extendedPrimitiveId.c_str());
140 return false;
142 _Extending = true;
144 _CancelFunc = parameters["OnCancel"];
145 _CookieKey = parameters["CookieKey"].toString();
146 _CookieValue = parameters["CookieValue"];
147 _PrimType = parameters["Type"].toString() == "Region" ? Region : Road;
148 _Prim.setLook(_PrimLook);
149 _NumPoints = (uint)_Points.size();
151 if (!parameters["ForceShowPrims"].isNil())
153 _ForceShowPrims = parameters["ForceShowPrims"].toBoolean();
156 if (!parameters["SelectInstance"].isNil())
158 _SelectInstance = parameters["SelectInstance"].toBoolean();
160 else
162 _SelectInstance = true;
165 CGroupMap *worldMap = getWorldMap();
166 if (worldMap)
168 worldMap->addDeco(&_Prim); // display primitive on the map
170 return true;
173 // ***************************************************************
174 void CToolDrawPrim::updateAfterRender()
176 //H_AUTO(R2_CToolDrawPrim_updateAfterRender)
179 // ***************************************************************
180 void CToolDrawPrim::removeFromWorldMap()
182 //H_AUTO(R2_CToolDrawPrim_removeFromWorldMap)
183 CGroupMap *worldMap = getWorldMap();
184 if (worldMap)
186 if (_Prim.isAddedToWorldMap())
188 worldMap->removeDeco(&_Prim);
190 if (_InaccessiblePrim.isAddedToWorldMap())
192 worldMap->removeDeco(&_InaccessiblePrim);
197 // ***************************************************************
198 void CToolDrawPrim::cancel()
200 //H_AUTO(R2_CToolDrawPrim_cancel)
201 if (_ExtendedPrimitive)
203 CDisplayerVisualGroup *dv = dynamic_cast<CDisplayerVisualGroup *>(_ExtendedPrimitive->getDisplayerVisual());
204 if (dv)
206 dv->setActiveRecurse(true);
209 removeFromWorldMap();
210 if (!_Commited)
212 if (_CancelFunc.isFunction())
214 _CancelFunc.callNoThrow(0, 0);
219 // ***************************************************************
220 void CToolDrawPrim::setPrimLook(bool closed, bool lastEdgeIsValid, bool valid)
222 //H_AUTO(R2_CToolDrawPrim_setPrimLook)
223 CPrimLook *look;
224 if (!valid) look = &_PrimLookInvalid;
225 else if (closed) look = &_PrimLookCanClose;
226 else look = &_PrimLook;
227 look->LastEdgeIsValid = lastEdgeIsValid;
228 _Prim.setLook(*look);
231 // ***************************************************************
232 void CToolDrawPrim::updateBeforeRender()
234 //H_AUTO(R2_CToolDrawPrim_updateBeforeRender)
235 doUpdateBeforeRender();
236 CGroupMap *worldMap = getWorldMap();
237 if (worldMap && !_InaccessibleParts && _InaccessiblePrim.isAddedToWorldMap())
239 worldMap->removeDeco(&_InaccessiblePrim); // display primitive on the map
243 // ***************************************************************
244 void CToolDrawPrim::doUpdateBeforeRender()
246 //H_AUTO(R2_CToolDrawPrim_doUpdateBeforeRender)
247 if (_Extending && !_ExtendedPrimitive)
249 cancel();
250 return;
252 _MustClose = false;
253 // Build vector for direction pointed by mouse in world
254 sint32 mouseX, mouseY;
255 getMousePos(mouseX, mouseY);
256 if (!isInScreen(mouseX, mouseY))
258 // mouse not in screen so don't display the last point
259 _Points.resize(_NumPoints);
260 _Prim.setVertices(_Points);
261 updateValidityFlag(false);
262 setPrimLook(false, true, _ValidPrim);
263 _Prim.addDecalsToRenderList();
264 return;
267 sint32 autoPanDx, autoPanDy;
268 if (_NumPoints >= 1)
270 handleWorldMapAutoPan(autoPanDx, autoPanDy);
273 CTool::CWorldViewRay worldViewRay;
275 computeWorldViewRay(mouseX, mouseY, worldViewRay);
277 _ValidPos = false;
278 CVector inter;
279 CVector wpPos;
280 TRayIntersectionType interType = computeLandscapeRayIntersection(worldViewRay, inter);
281 switch(interType)
283 case NoIntersection:
284 if (worldViewRay.OnMiniMap)
286 _Points.resize(_NumPoints);
287 _Prim.setVertices(_Points);
288 updateValidityFlag(false);
289 setPrimLook(false, true, _ValidPrim);
290 _Prim.addDecalsToRenderList();
291 setMouseCursor("curs_stop.tga");
292 return;
294 // no collision, can't drop entity
295 wpPos = worldViewRay.Origin + 3.f * worldViewRay.Dir;
296 break;
297 case ValidPacsPos:
298 wpPos = inter;
299 _ValidPos = isValid2DPos(inter); // good pos to drop entity
300 break;
301 case InvalidPacsPos:
302 wpPos = inter;
303 break;
304 default:
305 nlassert(0);
306 break;
308 // If there are at least 3 vertices and the primitive is a region, then see whether mouse
309 // is near the first vertex -> in this case, propose to the user to close the primitive
310 // If landscape is intersected too, then the vertex must be nearer then the first vertex
311 if (_PrimType == Region && _NumPoints >= 3)
313 bool canClose = false;
314 CGroupMap *gm = isMouseOnWorldMap();
315 if (gm)
317 CViewBitmap *bm = _Prim.getWorldMapVertexView(0);
318 if (bm)
320 canClose = bm->isIn(mouseX, mouseY);
323 else
325 if (!_Prim.getVerticesShapeInstance().empty())
327 if (!_Prim.getVerticesShapeInstance()[0].empty())
329 NLMISC::CAABBox vertexBBox;
330 _Prim.getVerticesShapeInstance()[0].getShapeAABBox(vertexBBox);
331 vertexBBox.setCenter(_Points[0]);
332 if (vertexBBox.intersect(worldViewRay.Origin, worldViewRay.Origin + 200.f * worldViewRay.Dir))
334 // if vertex nearer than landscape
335 bool landscapeNearest = false;
336 if (interType != NoIntersection)
338 // TODO nico : the test is not exact : should use intersection with the bbox to do
339 // length comparison over the same line ...
340 landscapeNearest = (wpPos - worldViewRay.Origin).norm() < (_Points[0] - worldViewRay.Origin).norm();
342 canClose = !landscapeNearest;
347 if (canClose)
349 _Points.resize(_NumPoints);
350 _Prim.setVertices(_Points);
351 updateValidityFlag(false);
352 setPrimLook(true, true, _ValidPrim); // show a closed polygon
353 _MustClose = true;
354 setMouseCursor("curs_pick.tga");
355 _Prim.addDecalsToRenderList();
356 return;
359 _Prim.setEmissive(CRGBA::Black);
361 _Points.resize(_NumPoints + 1);
362 if (_Points.size() >= 2)
364 _DistinctLastPoint = (_Points[_NumPoints] != _Points[_NumPoints - 1]);
366 else
368 _DistinctLastPoint = true;
371 _Points.back() = wpPos;
372 _Prim.setVertices(_Points);
373 updateValidityFlag(!_ValidPos);
374 // updateValidityFlag(interType == NoIntersection);
375 setPrimLook(false, _ValidPos, _ValidPrim);
377 // change mouse depending on result
378 if (!isMouseOnUI() || isMouseOnWorldMap() || !_ValidPrim)
380 setMouseCursor(_ValidPos /* && !_InaccessibleParts */ ? "curs_create.tga" : "curs_stop.tga");
382 else
384 setMouseCursor("curs_create.tga");
386 _Prim.addDecalsToRenderList();
387 CGroupMap *worldMap = getWorldMap();
388 //static CCtrlQuad *testQuad = NULL;
389 if (_InaccessibleParts)
391 /*if (!testQuad)
393 testQuad = new CCtrlQuad;
394 testQuad->setModulateGlobalColor(false);
395 float thickness = 256.f;
396 testQuad->setQuad(CVector(0.f, thickness, 0.f), CVector(thickness * 2.f, thickness, 0.f), thickness);
397 testQuad->setTexture("*accessibility_texture*");
398 worldMap->addCtrl(testQuad);
399 testQuad->setParent(worldMap);
401 if (worldMap && !_InaccessiblePrim.isAddedToWorldMap())
403 worldMap->addDeco(&_InaccessiblePrim); // display primitive on the map
406 updateInaccessiblePrimRenderLook(_InaccessiblePrim);
407 _InaccessiblePrim.setVertices(_Points);
408 _InaccessiblePrim.addDecalsToRenderList();
410 // TMP TMP
411 static volatile bool testDecal = false;
412 if (testDecal)
414 R2::CScenarioEntryPoints::CCompleteIsland *id = getEditor().getIslandCollision().getCurrIslandDesc();
415 if (id)
417 CMatrix m;
418 m.setScale(CVector(40000.f, 40000.f, 40000.f));
419 m.setPos(CVector(0.f, -40000.f, 0.f));
420 _TestDecal.setWorldMatrix(m);
421 _TestDecal.setCustomUVMatrix(true, getEditor().getIslandCollision().getWorldToAccessibilityTexMat(true));
422 _TestDecal.setTexture("*accessibility_texture*");
423 _TestDecal.addToRenderList();
428 // ***************************************************************
429 void CToolDrawPrim::updateInaccessiblePrimRenderLook(CPrimRender &dest)
431 //H_AUTO(R2_CToolDrawPrim_updateInaccessiblePrimRenderLook)
432 double duration = CV_InaccessiblePosAnimDurationInMS.get();
433 if (duration <= 0) duration = 0.1;
434 CRGBA color = blend(CV_InaccessiblePosColor0.get(),
435 CV_InaccessiblePosColor1.get(),
436 0.5f + 0.5f * (float) cos(NLMISC::Pi * fmod((double) T1, duration) / duration));
437 CPrimLook look = dest.getLook();
438 look.EdgeLook.WorldMapColor = color;
439 look.EdgeLook.DecalColor = color;
440 dest.setLook(look);
441 dest.setCustomWorldMapEdgeUVMatrix(true, getEditor().getIslandCollision().getWorldToAccessibilityTexMat());
442 dest.setCustomDecalEdgeUVMatrix(true, getEditor().getIslandCollision().getWorldToAccessibilityTexMat(true)); // cropped version for decal rendering
445 // ***************************************************************
446 bool CToolDrawPrim::onMouseLeftButtonClicked()
448 //H_AUTO(R2_CToolDrawPrim_onMouseLeftButtonClicked)
449 if (!checkRoomLeft())
451 displayNoMoreRoomLeftMsg();
452 return true;
454 if (_ValidPos /*&& !_InaccessibleParts*/ && _DistinctLastPoint)
456 ++ _NumPoints;
458 if (_ValidPos)
460 startDoubleClickCheck();
462 return true;
465 // ***************************************************************
466 bool CToolDrawPrim::onMouseLeftButtonDown()
468 //H_AUTO(R2_CToolDrawPrim_onMouseLeftButtonDown)
469 if (_MustClose && _ValidPos)
471 commit();
472 captureMouse(); // mouse will be released on "mouse up" by the default tool
473 return true;
475 if (!checkDoubleClick()) return false;
476 if (canTerminate())
478 // the 2 last points must have a different position
479 commit();
480 CToolMaintainedAction *tma = dynamic_cast<CToolMaintainedAction *>(getEditor().getCurrentTool());
481 if (tma)
483 tma->markPreviousToolClickEnd();
486 return true;
490 // ***************************************************************
491 void CToolDrawPrim::commit()
493 //H_AUTO(R2_CToolDrawPrim_commit)
494 if (_Extending && !_ExtendedPrimitive)
496 cancel();
497 return;
499 removeFromWorldMap();
500 _Points.resize(_NumPoints);
501 if (_Points.empty()) return;
502 // send network command to create a new road
503 CObject *desc = NULL;
504 if (!_Extending)
506 getDMC().newAction(NLMISC::CI18N::get(_PrimType == Road ? "uiR2EDCreateRouteAction" : "uiR2EDCreateZoneAction"));
508 else
510 getDMC().newAction(NLMISC::CI18N::get(_PrimType == Road ? "uiR2EDExtendRouteAction" : "uiR2EDExtendZoneAction"));
512 if (!_Extending)
514 // creating a new primitive, rather than growing an existing one
515 std::string className = _PrimType == Road ? "Road": "Region";
516 desc = getDMC().newComponent(className);
518 if (desc || _Extending)
520 CObject *points = NULL;
521 if (!_Extending)
523 std::string instanceId = getString(desc, "InstanceId");
524 if (!instanceId.empty())
526 // ask a flag to prompt user to enter name for this object when it is created
527 getEditor().setCookie(instanceId, "AskName", true);
528 if (_CookieValue.isValid())
530 if (!_CookieKey.empty() && !_CookieValue.isNil())
532 getEditor().setCookie(instanceId, _CookieKey, _CookieValue);
536 getEditor().setCookie(instanceId, "Select", _SelectInstance);
538 static volatile bool wantDump = false;
539 if (wantDump)
541 desc->dump();
543 points = desc->getAttr("Points");
544 for(uint k = 0; k < _Points.size(); ++k)
546 CObject *wp = getDMC().newComponent(_PrimType == Road ? "WayPoint" : "RegionVertex");
547 if (!wp) continue;
548 wp->setObject("Position", buildVector(CVectorD(_Points[k])));
549 points->insert("", wp, -1);
552 if (!_Extending)
554 // set readable name
555 string readableName = NLMISC::CI18N::get(_PrimType == Road ? "uiR2EDNameBotRoad" : "uiR2EDNameBotRegion");
556 readableName = getEditor().genInstanceName(readableName).toUtf8();
557 desc->set("Name", readableName);
558 // send creation command
559 // tmp : static npc counter
560 // add in component list of default feature
561 if (getEditor().getDefaultFeature())
563 getDMC().requestInsertNode(getEditor().getDefaultFeature(getEditor().getBaseAct())->getId(),
564 "Components",
567 desc);
570 delete desc;
571 // NB : if display of primitives is 'hide all', then force to 'show all', else
572 // the new prim wouldn't be visible
573 if (_ForceShowPrims)
575 if (getEditor().getEnv()["PrimDisplayVisible"].toBoolean() == false ||
576 getEditor().getEnv()["PrimDisplayContextualVisibility"].toBoolean() == true)
578 getEditor().callEnvMethod("notifyPrimDisplayShowAll", 0, 0);
582 else
584 nlassert(!desc);
585 CVectorD offset = CVectorD::Null;
586 CDisplayerVisualGroup *dv = dynamic_cast<CDisplayerVisualGroup *>(_ExtendedPrimitive->getDisplayerVisual());
587 if (dv)
589 offset = - dv->getWorldPos();
592 std::vector<CDisplayerVisual *> sons;
593 dv->getSons(sons);
595 for(uint k = _StartNumPoints - 1; k > _Points.size() - 1; --k)
597 getDMC().requestEraseNode(sons[k]->getDisplayedInstance()->getId(), "", -1);
600 for (uint k = 0; k < std::min(_StartNumPoints, uint(_Points.size())); ++k)
602 // change modified vertices
603 CVector newWorldPos = CVectorD(_Points[k]).asVector();
604 if (newWorldPos != _InitialPoints[k])
606 CObject *wp = getDMC().newComponent(_PrimType == Road ? "WayPoint" : "RegionVertex");
607 if (wp)
609 CObject *newPos = buildVector(offset + CVectorD(_Points[k]));
610 getDMC().requestSetNode(sons[k]->getDisplayedInstance()->getId(), "Position", newPos);
611 delete newPos;
615 // insert newly created vertices
616 for(uint k = _StartNumPoints; k < _Points.size(); ++k)
618 CObject *wp = getDMC().newComponent(_PrimType == Road ? "WayPoint" : "RegionVertex");
619 if (!wp) continue;
620 wp->setObject("Position", buildVector(offset + CVectorD(_Points[k])));
621 getDMC().requestInsertNode(_ExtendedPrimitive->getId(), "Points", -1, "", wp);
622 delete wp;
624 if (dv)
626 dv->setActiveRecurse(true);
630 _Commited = true;
631 getEditor().setCurrentTool(NULL); // set the default tool
632 return;
636 // ***************************************************************
637 bool CToolDrawPrim::onMouseRightButtonClicked()
639 //H_AUTO(R2_CToolDrawPrim_onMouseRightButtonClicked)
640 // TMP : exception for primitive drawing : right button finish the road
641 if (!checkRoomLeft())
643 displayNoMoreRoomLeftMsg();
644 return true;
646 if (_ValidPos && _DistinctLastPoint)
648 if (!_MustClose)
650 ++ _NumPoints;
652 if (canTerminate())
654 commit();
657 return true;
658 // cancel the drawing
659 //getEditor().setCurrentTool(NULL);
660 //return true;
663 // ***************************************************************
664 bool CToolDrawPrim::onDeleteCmd()
666 //H_AUTO(R2_CToolDrawPrim_onDeleteCmd)
667 CTool::TSmartPtr hold(this);
668 if (_NumPoints == 0)
670 if (_Extending)
672 getDMC().newAction(CI18N::get("uiR2EDDeleteRoad") + _ExtendedPrimitive->getDisplayName());
673 // just erase the road
674 getDMC().requestEraseNode(_ExtendedPrimitive->getId(), "", -1);
675 getDMC().getActionHistoric().endAction();
677 // cancel the drawing
678 getEditor().setCurrentTool(NULL);
680 else
682 -- _NumPoints;
683 _Points.resize(_NumPoints);
685 return true;
689 // ***************************************************************
690 bool CToolDrawPrim::isValidPolyShape(bool ignoreLast, std::list<CPolygon> &splitPoly) const
692 //H_AUTO(R2_CToolDrawPrim_isValidPolyShape)
693 splitPoly.clear();
694 if(_Points.size() <= 3)
696 return true;
698 // test that no self-intersection is found
699 static NLMISC::CPolygon2D poly2D;
700 poly2D.Vertices.resize(_Points.size());
701 for(uint k = 0; k < _Points.size(); ++k)
703 poly2D.Vertices[k] = _Points[k];
705 if (poly2D.selfIntersect()) return false;
706 CPolygon poly;
707 poly.Vertices = _Points;
708 if (poly.Vertices.back() == poly.Vertices[poly.Vertices.size() - 2] || ignoreLast)
710 poly.Vertices.pop_back(); // duplicated point at the end will always fails the test, so remove it
712 bool validPrim = poly.toConvexPolygons(splitPoly, CMatrix::Identity);
713 if (!validPrim)
715 std::reverse(poly.Vertices.begin(), poly.Vertices.end());
716 validPrim = poly.toConvexPolygons(splitPoly, CMatrix::Identity);
718 return validPrim;
721 // ***************************************************************
722 bool CToolDrawPrim::testAccessibleEdges(bool ignoreLast)
724 //H_AUTO(R2_CToolDrawPrim_testAccessibleEdges)
725 uint numPoints = (uint)_Points.size();
726 if (_PrimType == Road)
728 numPoints -= ignoreLast ? 2 : 1;
730 else
732 numPoints -= ignoreLast ? 2 : 0;
734 for (sint k = 0; k < (sint) numPoints; ++k)
736 if (!getEditor().getIslandCollision().isValidSegment(_Points[k], _Points[(k + 1) % _Points.size()]))
738 return false;
741 return true;
744 // ***************************************************************
745 void CToolDrawPrim::updateValidityFlag(bool ignoreLast)
747 //H_AUTO(R2_CToolDrawPrim_updateValidityFlag)
748 _ValidPrim = true;
749 if (_PrimType != Road)
751 std::list<CPolygon> splitPoly;
752 if (!isValidPolyShape(ignoreLast, splitPoly))
754 _ValidPrim = false;
761 nlassert(0); // old code
762 if (_LastPoints.size() == _Points.size() && std::equal(_Points.begin(), _Points.end(), _LastPoints.begin()))
763 return; // not modified, so last flag remains valid
764 _InaccessibleParts = false;
765 _LastPoints = _Points;
766 // CHANGE: accessibility for edges not tested anymore ...
768 // bool accessible = testAccessibleEdges(ignoreLast);
769 // _InaccessibleParts = !accessible;
771 _InaccessibleParts = false;
772 sint testPointIndex = _Points.size() - (ignoreLast ? 2 : 1);
773 if (testPointIndex < 0)
775 _ValidPrim = false;
776 return;
778 // change : valid to create if current mouse pos is valid (test 0.5f meters around)
779 CVector2f testPos = _Points[testPointIndex];
780 _ValidPrim = getEditor().getIslandCollision().isValidPos(testPos);
782 if (!_ValidPrim) return;
783 // old test : all parts crossed by the edges needed to be accessible
785 // if (!accessible)
786 // {
787 // _ValidPrim = false;
789 if (_PrimType != Road)
791 std::list<CPolygon> splitPoly;
792 if (!isValidPolyShape(ignoreLast, splitPoly))
794 _ValidPrim = false;
799 // ***************************************************************
800 void CToolDrawPrim::onActivate()
802 //H_AUTO(R2_CToolDrawPrim_onActivate)
803 setContextHelp(CI18N::get("uiR2EDToolDrawPrim"));
804 if (_ExtendedPrimitive)
806 CDisplayerVisualGroup *dv = dynamic_cast<CDisplayerVisualGroup *>(_ExtendedPrimitive->getDisplayerVisual());
807 if (!dv)
809 cancel();
810 return;
812 else
814 dv->setActiveRecurse(false); // hide the primitive being extended, because we display
815 // our own version until we are finished
817 std::vector<CDisplayerVisual *> sons;
818 dv->getSons(sons);
819 for(uint k = 0; k < sons.size(); ++k)
821 _Points.push_back(sons[k]->getWorldPos().asVector());
823 _NumPoints = (uint)_Points.size();
824 _StartNumPoints = _NumPoints;
825 _InitialPoints = _Points;
829 // ***************************************************************
830 bool CToolDrawPrim::checkRoomLeft()
832 //H_AUTO(R2_CToolDrawPrim_checkRoomLeft)
833 return _NumPoints < PrimMaxNumPoints;
836 // ***************************************************************
837 void CToolDrawPrim::displayNoMoreRoomLeftMsg()
839 //H_AUTO(R2_CToolDrawPrim_displayNoMoreRoomLeftMsg)
840 getEditor().callEnvMethod("noMoreRoomLeftInPrimitveMsg", 0, 0);
844 } // R2