Skyscraper 2.0
doorsystem.cpp
Go to the documentation of this file.
1/*
2 Scalable Building Simulator - Door System
3 The Skyscraper Project - Version 2.0
4 Copyright (C)2004-2024 Ryan Thoryk
5 https://www.skyscrapersim.net
6 https://sourceforge.net/projects/skyscraper/
7 Contact - ryan@skyscrapersim.net
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22*/
23
24#include "globals.h"
25#include "sbs.h"
26#include "profiler.h"
27#include "mesh.h"
28#include "floor.h"
29#include "elevator.h"
30#include "elevatorcar.h"
31#include "elevatordoor.h"
32#include "door.h"
33#include "doorsystem.h"
34
35namespace SBS {
36
37//
38// Door Component
39//
40
41DoorComponent::DoorComponent(const std::string &doorname, DoorWrapper *Wrapper, const std::string &Direction, bool OpenClockwise, Real OpenSpeed, Real CloseSpeed, DynamicMesh *dynmesh)
42{
43 name = doorname;
44 wrapper = Wrapper;
45
46 //create object mesh
47 mesh = new MeshObject(wrapper, doorname, dynmesh);
48
49 //keep colliders attached, to fix performance issues when moving in and out of an elevator
50 mesh->remove_on_disable = false;
51
52 std::string direction_check = Direction;
53 SetCase(direction_check, false);
54 TrimString(direction_check);
55
56 //set direction value from strings
57 direction = 0;
58 if (direction_check == "down")
59 direction = 1;
60 if (direction_check == "left" || direction_check == "forward" || direction_check == "front")
61 direction = 2;
62 if (direction_check == "right" || direction_check == "back")
63 direction = 3;
64
65 open_speed = OpenSpeed;
66 close_speed = CloseSpeed;
67 active_speed = 0;
68 openchange = 0;
69 marker1 = 0;
70 marker2 = 0;
71 door_section = 0;
73 temp_change = 0;
74 accelerating = false;
75 is_open = false;
76 finished = false;
77 sign_changed = false;
79 recheck_difference = false;
80 reversed = false;
81 offset = 0;
82 rotation = 0;
83 Clockwise = OpenClockwise;
84}
85
87{
88 if (mesh)
89 delete mesh;
90 mesh = 0;
91}
92
93void DoorComponent::MoveDoors(bool open, bool manual)
94{
95 //opens or closes elevator doors
96 //currently only supports doors on either the left/right or front/back
97 //diagonal doors will be done later, by possibly using relative plane movement
98
99 //this door system is based on offsets from the door origin (starting position).
100 //when opening, the door starts at the origin, accelerates to marker 1, moves at a constant
101 //rate to marker 2, and then decelerates after marker 2.
102 //the acceleration/deceleration sections aren't used if manual is true (in that case, it simply sets a speed value, and moves
103 //the doors until they reach the ends
104
105 //direction is either 0 for up, 1 for down, 2 for left/forward and 3 for right/backward
106
107 //first get position and origin of door, and adjust values to reflect the "edge" of the door
108 SBS_PROFILE("DoorComponent::MoveDoors");
109
110 Real tempposition, temporigin;
111
112 if (!wrapper)
113 return;
114
115 if (wrapper->rotate == true)
116 return;
117
118 //get parent values
119 bool DoorChanged = false;
120 bool DoorDirection = false;
121 bool NudgeStatus = false;
122 bool PreviousOpen = false;
124 {
125 DoorChanged = wrapper->parent_elevdoor->GetDoorChanged();
126 DoorDirection = wrapper->parent_elevdoor->DoorDirection;
127 NudgeStatus = wrapper->parent_elevdoor->GetNudgeStatus();
128 PreviousOpen = wrapper->parent_elevdoor->GetPreviousOpen();
129 }
130 else
131 {
132 DoorChanged = wrapper->parent_door->GetDoorChanged();
133 DoorDirection = wrapper->parent_door->DoorDirection;
134 NudgeStatus = false;
135 PreviousOpen = wrapper->parent_door->GetPreviousOpen();
136
137 //exit if trying to run standard doors in manual mode
138 if (manual == true)
139 return;
140 }
141
142 if (finished == true && DoorChanged == false)
143 return;
144
145 if (direction > 1)
146 {
147 if (DoorDirection == false)
148 tempposition = mesh->GetPosition(true).z + wrapper->Shift;
149 else
150 tempposition = mesh->GetPosition(true).x + wrapper->Shift;
151 temporigin = wrapper->Shift;
152 }
153 else
154 {
155 tempposition = mesh->GetPosition(true).y;
156 temporigin = 0;
157 }
158
159 //get distance from starting point
160 Real difference = std::abs(tempposition - temporigin);
161
162 if (old_difference != 0 && manual == true && recheck_difference == true)
163 {
164 //check if the position went beyond 0
165 if ((tempposition - temporigin > 0 && old_difference < 0) || (tempposition - temporigin < 0 && old_difference > 0))
166 sign_changed = true;
167 }
168
169 if (recheck_difference == false && old_difference != 0)
170 {
171 recheck_difference = true;
172 old_difference = 0;
173 }
174 else
175 old_difference = tempposition - temporigin;
176
177 //debug - show current section as function is running
178 //Report("Door section: " + ToString(door_section));
179
180 if ((DoorChanged == false && door_section == 0) || (DoorChanged == true && finished == true))
181 {
182 //initialization code
183
184 finished = false;
185 recheck_difference = false;
186
187 //marker1 is the position to stop accelerating at (accelerates to marker 1)
188 //marker2 is the position to start decelerating at (runs full speed until marker 2)
189 if (manual == false)
190 {
191 Real speed;
192 if (open == true)
193 speed = open_speed;
194 else
195 speed = close_speed;
196
198 {
199 if (NudgeStatus == false || wrapper->parent_elevdoor->SlowSpeed == 0)
200 openchange = speed / 50;
201 else
202 openchange = (speed * wrapper->parent_elevdoor->SlowSpeed) / 50;
203 }
204 else
205 openchange = speed / 50;
206
207 if (direction > 1)
208 {
209 //get width and offset values (offset is the distance the door component
210 //is from the edge of the door frame)
211 Real width;
212 Real mainwidth = wrapper->Width / 2;
213 if (DoorDirection == false)
214 {
215 width = std::abs(extents_max.z - extents_min.z);
216 if (direction == 2)
217 offset = mainwidth + (extents_min.z - wrapper->Shift);
218 else
219 offset = mainwidth - (extents_max.z - wrapper->Shift);
220 }
221 else
222 {
223 width = std::abs(extents_max.x - extents_min.x);
224 if (direction == 2)
225 offset = mainwidth + (extents_min.x - wrapper->Shift);
226 else
227 offset = mainwidth - (extents_max.x - wrapper->Shift);
228 }
229 Real newwidth = width + offset;
230 marker1 = newwidth / 4;
231 marker2 = (mainwidth + (width - mainwidth)) - marker1 + offset;
232 }
233 else
234 {
235 Real height = std::abs(extents_max.y - extents_min.y);
236 Real mainheight = wrapper->Height / 2;
237 if (direction == 0)
239 else
241
242 Real newheight = height + offset;
243 marker1 = newheight / 4;
244 marker2 = (mainheight + (height - mainheight)) - marker1 + offset;
245 }
246 active_speed = 0;
247 }
248 else
249 {
250 //manual movement positioning (same as normal positioning, but the markers are at the
251 //door frame extents
252 if (direction > 1)
253 {
254 Real width;
255 Real mainwidth = wrapper->Width / 2;
256 if (DoorDirection == false)
257 {
258 width = std::abs(extents_max.z - extents_min.z);
259 if (direction == 2)
260 offset = mainwidth + (extents_min.z - wrapper->Shift);
261 else
262 offset = mainwidth - (extents_max.z - wrapper->Shift);
263 }
264 else
265 {
266 width = std::abs(extents_max.x - extents_min.x);
267 if (direction == 2)
268 offset = mainwidth + (extents_min.x - wrapper->Shift);
269 else
270 offset = mainwidth - (extents_max.x - wrapper->Shift);
271 }
272 marker1 = 0;
273 marker2 = mainwidth + (width - mainwidth) + offset;
274 }
275 else
276 {
277 Real height = std::abs(extents_max.y - extents_min.y);
278 Real mainheight = wrapper->Height / 2;
279 if (direction == 0)
281 else
283
284 marker1 = 0;
285 marker2 = mainheight + (height - mainheight) + offset;
286 }
287
288 if (open == true)
290 else
292 }
293 }
294 else if (PreviousOpen != open && DoorChanged == true && reversed == false)
295 {
296 //if a different direction was specified during movement
297 //change directions immediately
298 if (open == true)
299 {
300 //relocate marker 1 to the door's current position, in order to stop it
301 Real offset = marker1 - difference;
302 if (difference >= marker1)
303 //place marker at door position
304 marker1 = difference;
305 else
306 //place marker to the right based on the offset, to bring door back to full speed
307 marker1 = difference + offset;
308 }
309 else //closing
310 {
311 //relocate marker 2 to the door's current position, in order to stop it
312 Real offset = difference - marker2;
313 if (difference <= marker2)
314 //place marker at door position
315 marker2 = difference;
316 else
317 //place marker to the left based on the offset, to bring door back to full speed
318 marker2 = difference - offset;
319 }
320 reversed = true;
321 }
322
323 //Speed up doors (only if manual is false)
324 if (manual == false)
325 {
326 //if door is opening and is left of marker 1
327 //or if door is closing and is to the right of marker 2
328 if ((difference <= marker1 && open == true) || (difference >= marker2 && open == false))
329 {
330 accelerating = true;
331 if (DoorChanged == false)
332 {
333 //normal door acceleration
334 if (open == true)
336 else
338 }
339 else
340 {
341 //reverse movement if transitioning from close to open, or open to close
342 //this will trigger if door is closing, and is told to open while left of relocated marker 1
343 //or will trigger if door is opening, and is told to close while right of relocated marker 2
344 if (difference <= marker1 && open == true)
346 else if (difference >= marker2 && open == false)
348 }
349
350 //move elevator doors
351 Move();
352
353 //get stopping distance
354 stopping_distance = difference;
355
356 door_section = 1;
357 return;
358 }
359 }
360
361 door_section = 2;
362
363 //Normal door movement
364 if ((difference < marker2 && open == true) || (difference > marker1 && open == false))
365 {
366 if (sign_changed == false) //don't run movement code if difference went beyond 0, for manual only
367 {
368 Move();
369 door_section = 3;
370 return;
371 }
372 }
373
374 accelerating = false;
375
376 //slow down doors (only if manual is false)
377 if (manual == false)
378 {
379 if ((active_speed > 0 && open == true) || (active_speed < 0 && open == false))
380 {
381 if (open == true)
383 else
385
386 Move();
387 door_section = 4;
388 return;
389 }
390 }
391
392 //report on what section preceded the finishing code (should be 4)
393 //Report("Door section: " + ToString(door_section));
394
395 //place doors in positions (fixes any overrun errors)
396 Reset(open);
397}
398
400{
401 if (!wrapper)
402 return;
403
404 if (wrapper->rotate == false)
405 return;
406
407 if (Clockwise == true)
408 {
409 if (open == true)
411 else
413 }
414 else
415 {
416 if (open == true)
418 else
420 }
421
422 //if opened fully, set state to opened
423 if (rotation >= 90 || rotation <= -90)
424 {
425 is_open = true;
426 finished = true;
427 if (rotation >= 90)
428 rotation = 90;
429 else
430 rotation = -90;
431 }
432
433 //if closed fully, set state to closed
434 if ((Clockwise == true && rotation <= 0) || (Clockwise == false && rotation >= 0))
435 {
436 is_open = false;
437 finished = true;
438 rotation = 0;
439 }
440
441 mesh->SetRotation(0, rotation, 0);
442}
443
445{
446 //move elevator doors
447
448 if (!wrapper)
449 return;
450
451 bool DoorDirection = false;
452 Real speed = 0;
454 {
455 DoorDirection = wrapper->parent_elevdoor->DoorDirection;
457 }
458 else
459 {
460 DoorDirection = wrapper->parent_door->DoorDirection;
462 }
463
464 //up movement
465 if (direction == 0)
466 mesh->Move(Vector3(0, 1, 0), speed);
467
468 //down movement
469 if (direction == 1)
470 mesh->Move(Vector3(0, -1, 0), speed);
471
472 if (DoorDirection == false)
473 {
474 //left movement
475 if (direction == 2)
476 mesh->Move(Vector3(0, 0, -1), speed);
477
478 //right movement
479 if (direction == 3)
480 mesh->Move(Vector3(0, 0, 1), speed);
481 }
482 else
483 {
484 //left movement
485 if (direction == 2)
486 mesh->Move(Vector3(-1, 0, 0), speed);
487
488 //right movement
489 if (direction == 3)
490 mesh->Move(Vector3(1, 0, 0), speed);
491 }
492}
493
494void DoorComponent::Reset(bool open)
495{
496 //reset door state
497
498 if (!wrapper)
499 return;
500
501 if (wrapper->rotate == true)
502 return;
503
504 //get parent values
505 bool DoorDirection = false;
507 {
508 DoorDirection = wrapper->parent_elevdoor->DoorDirection;
510 }
511 else
512 {
513 DoorDirection = wrapper->parent_door->DoorDirection;
515 }
516
517 if (open == true)
518 {
519 //move elevator doors
520 if (direction > 1)
521 {
522 Real mainwidth = wrapper->Width / 2;
523 if (DoorDirection == false)
524 {
525 Real width = std::abs(extents_max.z - extents_min.z);
526 if (direction == 2)
527 mesh->Move(Vector3(0, 0, -(mainwidth + (width - mainwidth) + offset)));
528 else
529 mesh->Move(Vector3(0, 0, mainwidth + (width - mainwidth) + offset));
530 }
531 else
532 {
533 Real width = std::abs(extents_max.x - extents_min.x);
534 if (direction == 2)
535 mesh->Move(Vector3(-(mainwidth + (width - mainwidth) + offset), 0, 0));
536 else
537 mesh->Move(Vector3(mainwidth + (width - mainwidth) + offset, 0, 0));
538 }
539 }
540 else
541 {
542 Real mainheight = wrapper->Height / 2;
543 Real height = std::abs(extents_max.y - extents_min.y);
544 if (direction == 0)
545 mesh->Move(Vector3(0, mainheight + (height - mainheight) + offset, 0));
546 else
547 mesh->Move(Vector3(0, -(mainheight + (height - mainheight) + offset), 0));
548 }
549
550 //the door is open now
551 is_open = true;
552 finished = true;
553
554 //reset values
555 active_speed = 0;
556 door_section = 0;
557 sign_changed = false;
558 old_difference = 0;
560 reversed = false;
561 }
562 else
563 {
564 //the door is closed now
565 is_open = false;
566 finished = true;
567
568 //reset values
569 openchange = 0;
570 marker1 = 0;
571 marker2 = 0;
572 temp_change = 0;
573 accelerating = false;
574 recheck_difference = false;
575 active_speed = 0;
576 door_section = 0;
577 sign_changed = false;
578 old_difference = 0;
580 reversed = false;
581 }
582}
583
584//
585// Door Wrapper
586//
587
588DoorWrapper::DoorWrapper(Object *parent_obj, ElevatorDoor *door_object, bool shaftdoor, int shaftdoor_floor) : Object(parent_obj)
589{
590 parent_elevdoor = door_object;
591 parent_door = 0;
592 Open = false;
593 IsEnabled = true;
594 Width = 0;
595 Height = 0;
596 Thickness = 0;
597 IsShaftDoor = shaftdoor;
598 Shift = 0;
599 voffset = 0;
600 floor = shaftdoor_floor;
601 rotate = false;
602
603 std::string name;
604 if (IsShaftDoor == true)
605 name = "Shaft Door " + ToString(parent_elevdoor->elev->Number) + ":" + ToString(parent_elevdoor->car->Number) + ":" + ToString(parent_elevdoor->Number) + ":" + ToString(shaftdoor_floor);
606 else
607 name = "Elevator Door " + ToString(parent_elevdoor->car->Number) + ":" + ToString(parent_elevdoor->Number);
608
609 SetValues("DoorWrapper", name, false);
610
611 if (IsShaftDoor == true)
613}
614
615DoorWrapper::DoorWrapper(Door *parent, bool rotate) : Object(parent)
616{
617 parent_elevdoor = 0;
618 parent_door = parent;
619 Open = false;
620 IsEnabled = true;
621 Width = 0;
622 Height = 0;
623 Thickness = 0;
624 IsShaftDoor = false;
625 Shift = 0;
626 voffset = 0;
627 floor = 0;
628 this->rotate = rotate;
629
630 std::string name = parent->GetName();
631 SetValues("DoorWrapper", name, false);
632}
633
635{
636 for (size_t i = 0; i < doors.size(); i++)
637 {
638 if (doors[i])
639 delete doors[i];
640 }
641 doors.clear();
642
643 //unregister from parent
644 if (parent_deleting == false)
645 {
646 if (parent_elevdoor)
648 }
649}
650
651DoorComponent* DoorWrapper::CreateDoor(const std::string &doorname, const std::string &direction, bool OpenClockwise, Real OpenSpeed, Real CloseSpeed, DynamicMesh *dynmesh)
652{
653 //initialize a door component
654
655 DoorComponent *door = new DoorComponent(doorname, this, direction, OpenClockwise, OpenSpeed, CloseSpeed, dynmesh);
656 doors.emplace_back(door);
657 return door;
658}
659
660void DoorWrapper::Enabled(bool value)
661{
662 //enable/disable door meshes
663
664 if (value == IsEnabled)
665 return;
666
667 for (size_t i = 0; i < doors.size(); i++)
668 {
669 if (doors[i])
670 doors[i]->mesh->Enabled(value);
671 }
672
673 IsEnabled = value;
674}
675
676void DoorWrapper::MoveDoors(bool open, bool manual)
677{
678 //calls per-door move function
679 for (size_t i = 0; i < doors.size(); i++)
680 {
681 if (doors[i])
682 {
683 if (rotate == false)
684 doors[i]->MoveDoors(open, manual);
685 else
686 doors[i]->RotateDoors(open);
687 }
688 }
689}
690
692{
693 //checks to see if doors are open or closed, and returns true if the status changed
694
695 for (size_t i = 0; i < doors.size(); i++)
696 {
697 if (doors[i])
698 {
699 //exit if the status is the same on any door
700 if (doors[i]->is_open == Open)
701 return false;
702 }
703 }
704
705 //if the status changed, set the new status and return true
706 Open = !Open;
707 return true;
708}
709
711{
712 //checks to see if all of the doors are finished
713
714 for (size_t i = 0; i < doors.size(); i++)
715 {
716 if (doors[i])
717 {
718 //exit if any door is not finished
719 if (doors[i]->finished == false)
720 return false;
721 }
722 }
723 return true;
724}
725
727{
728 //reset finished state on all doors
729
730 for (size_t i = 0; i < doors.size(); i++)
731 {
732 if (doors[i])
733 doors[i]->finished = false;
734 }
735}
736
738{
739 //stop all doors
740
741 for (size_t i = 0; i < doors.size(); i++)
742 {
743 if (doors[i])
744 {
745 doors[i]->active_speed = 0;
746 doors[i]->door_section = 0;
747 }
748 }
749}
750
752{
753 //reset door state in case of an internal malfunction
754
755 Open = false;
756
757 for (size_t i = 0; i < doors.size(); i++)
758 {
759 if (doors[i])
760 doors[i]->Reset(false);
761 }
762}
763
764void DoorWrapper::OnClick(Vector3 &position, bool shift, bool ctrl, bool alt, bool right)
765{
766 if (parent_door)
767 {
768 parent_door->OnClick(position, shift, ctrl, alt, right);
769 return;
770 }
771
772 if (shift == true && right == false)
773 {
774 if (parent_elevdoor)
775 {
777 if (!car)
778 return;
779
780 int number = parent_elevdoor->Number;
781
782 if (IsShaftDoor == true)
783 {
784 //check shaft doors
785 if (abs(car->AreDoorsMoving(number, false, true)) == 2)
786 car->StopDoors(number);
787 else
788 {
789 if (car->AreShaftDoorsOpen(number, floor) == false)
790 car->OpenDoorsEmergency(number, 3, floor);
791 else
792 car->CloseDoorsEmergency(number, 3, floor);
793 }
794 }
795 else
796 {
797 //check elevator doors
798 if (abs(car->AreDoorsMoving(number, true, false)) == 2)
799 car->StopDoors(number);
800 else
801 {
802 if (car->AreDoorsOpen(number) == false)
803 car->OpenDoorsEmergency(number, 2);
804 else
805 car->CloseDoorsEmergency(number, 2);
806 }
807 }
808 }
809 }
810}
811
813{
814 //check elevator doors (door bumpers feature)
815
816 if (parent_elevdoor)
817 {
818 //make sure both internal and external doors are closing
820 {
821 //either open doors if the hit door was an internal door or a shaft door on the elevator floor
822 if (IsShaftDoor == false || (IsShaftDoor == true && floor == parent_elevdoor->car->GetFloor()))
824 }
825 }
826}
827
828}
bool GetPreviousOpen()
Definition door.cpp:289
bool DoorDirection
Definition door.h:37
bool GetDoorChanged()
Definition door.cpp:284
void OnClick(Vector3 &position, bool shift, bool ctrl, bool alt, bool right)
Definition door.cpp:260
void StopDoors(int number=0)
bool OpenDoorsEmergency(int number=0, int whichdoors=1, int floor=0, bool hold=false)
void CloseDoorsEmergency(int number=0, int whichdoors=1, int floor=0, bool hold=false)
bool OpenDoors(int number=0, int whichdoors=1, int floor=0, bool manual=false, bool hold=false)
bool AreDoorsOpen(int number=0)
int AreDoorsMoving(int number=0, bool car_doors=true, bool shaft_doors=true)
bool AreShaftDoorsOpen(int number, int floor)
ElevatorCar * car
void RemoveShaftDoor(DoorWrapper *door)
Real GetBase(bool relative=false)
Definition floor.cpp:1140
void Enabled(bool value)
Definition mesh.cpp:154
bool remove_on_disable
Definition mesh.h:49
SBS * GetRoot()
Definition object.cpp:48
const std::string & GetName()
Definition object.cpp:53
Object * GetParent()
Definition object.cpp:42
bool parent_deleting
Definition object.h:64
virtual void SetRotation(const Vector3 &rotation)
Definition object.cpp:332
virtual void Move(const Vector3 &vector, Real speed=1.0)
Definition object.cpp:253
virtual Vector3 GetPosition(bool relative=false)
Definition object.cpp:321
void SetValues(const std::string &type, const std::string &name, bool is_permanent, bool is_movable=true)
Definition object.cpp:144
virtual void SetPosition(const Vector3 &position)
Definition object.cpp:274
Floor * GetFloor(int number)
Definition sbs.cpp:1739
Real delta
Definition sbs.h:134
Ogre::Vector3 Vector3
Definition globals.h:58
Ogre::Real Real
Definition globals.h:57
void SetCase(std::string &string, bool uppercase)
Definition globals.cpp:172
std::string ToString(int number)
Definition globals.cpp:279
void TrimString(std::string &string)
Definition globals.cpp:188
#define SBS_PROFILE(name)
Definition profiler.h:131
void RotateDoors(bool open)
DoorWrapper * wrapper
Definition doorsystem.h:48
void Reset(bool open)
void MoveDoors(bool open, bool manual)
std::string name
Definition doorsystem.h:47
MeshObject * mesh
Definition doorsystem.h:41
DoorComponent(const std::string &doorname, DoorWrapper *Wrapper, const std::string &direction, bool OpenClockwise, Real OpenSpeed, Real CloseSpeed, DynamicMesh *dynmesh)
ElevatorDoor * parent_elevdoor
Definition doorsystem.h:93
std::string name
Definition doorsystem.h:87
void MoveDoors(bool open, bool manual=false)
void Enabled(bool value)
DoorWrapper(Object *parent_obj, ElevatorDoor *door_object, bool shaftdoor, int shaftdoor_floor=0)
std::vector< DoorComponent * > doors
Definition doorsystem.h:86
DoorComponent * CreateDoor(const std::string &doorname, const std::string &Direction, bool OpenClockwise, Real OpenSpeed, Real CloseSpeed, DynamicMesh *dynmesh)
void OnClick(Vector3 &position, bool shift, bool ctrl, bool alt, bool right)