fiore@3: #pragma once fiore@3: #include "stdAfx.h" fiore@3: #include fiore@3: #include "HapticException.h" fiore@3: #include "CollectionsManager.h" fiore@3: fiore@3: #define NOVIBRATION fiore@3: fiore@3: /* The haptic manager draws the diagram openGL scene haptically. * fiore@3: * In order to get all the data about the diagram it's constructed * fiore@3: * passing a reference to the CollectionManager */ fiore@3: class HapticManager fiore@3: { fiore@3: enum AttractionStatus {START_ATTRACTION, DOING_ATTRACTION, NO_ATTRACTION, STOP_ATTRACTION}; fiore@3: enum SpringStatus { DRAGGING, RELEASED, START_DRAGGING, STOP_DRAGGING }; fiore@3: enum VibrationStatus { START_VIBRATION , DOING_VIBRATION , NO_VIBRATION, CAN_VIBRATE}; fiore@3: fiore@3: fiore@3: /* Haptic device and rendering context handles. */ fiore@3: HLuint wall1Id; fiore@3: HLuint wall2Id; fiore@3: HLuint frictionFX; fiore@3: HLuint vibrationFX; fiore@3: HLuint attractionFX; fiore@3: HLuint springFX; fiore@3: VibrationStatus vibrationStatus; fiore@3: AttractionStatus attractionStatus; fiore@3: SpringStatus springStatus; fiore@3: #ifdef VIBRATION fiore@3: static const HDdouble VIBRATION_AMPLITUDE; fiore@3: static const HDint VIBRATION_FREQUENCY; fiore@3: static const unsigned int VIBRATION_DURATION; fiore@3: #endif fiore@3: static const double EDGE_SHORTEND_VAL; fiore@3: static const double EDGE_SPEECH_DISTANCE_WHEN_LEAVING_NODE; fiore@3: static const unsigned int CLICK_INTERVAL; fiore@3: clock_t clickStart; fiore@3: clock_t vibrationEnd; fiore@3: HDdouble forceBeforeVibration[3]; fiore@3: CollectionsManager *collectionsManager; fiore@3: bool wall; fiore@3: jint attractToHapticId; fiore@3: bool alreadyTouchingAttractingElement; fiore@3: jdouble attractToCoord[3]; fiore@3: // this is needed to calulate the distance between the proxy and the last touched node fiore@3: HLdouble lastTouchedNodePosition[3]; fiore@3: HLint lastTouchedNodeID; fiore@3: HLint lastTouchedEdgeID; fiore@3: jint lastTouchedEdgeStipplePattern; fiore@3: HLint lastHighlightElementID; fiore@3: HLint draggedElementID; fiore@3: /* when dropping a node after moving it, unless one detouches and touches again the node, fiore@3: the hlGetShapeBooleanv(HL_PROXY_IS_TOUCHING) routine will return a false value when fiore@3: one tries to hook the node again. Even tough the touch and untouch callback are called fiore@3: correctly. this variable keeps track of the last moved element, setting it to HL_OBJECT_ANY fiore@3: on the detouch callback so that this "buggy" behaviour is worked around fiore@3: */ fiore@3: HLuint lastMovedElement; fiore@3: bool stillTouchingLastMovedElement; fiore@3: /* this variable is to workaround the HL_PROXY_IS_TOUCHNIG problem to fix issue of stipple pattern: fiore@3: when dropping a node after having picked it up, then the hlGetShapeBooleanv may return false fiore@3: for all the edges attached to a moved node or for a moved edge. Because of that the stipple fiore@3: pattern for dotted and dashed lines might not be enabled. The check is however necessary to stop the fiore@3: effect when actually untouching the node or when changing tab after the pick up and drop. fiore@3: The variable is set/unset in the touching callbacks which works fine. fiore@3: */ fiore@3: bool lastTouchedEdgeIsUntouched; fiore@3: HLdouble springStart[3]; fiore@3: GLuint displayList1; fiore@3: GLuint displayList2; fiore@3: bool frictionDisabled; fiore@3: bool doneOnce; fiore@3: bool secondClick; fiore@3: bool stickyMode; fiore@3: bool doubleClick; fiore@3: void drawPlane(float offset); fiore@3: void (*executeCommand)(const jchar cmd, const jint ID, const jdouble startx, const jdouble starty, const jdouble endx, const jdouble endy); fiore@3: fiore@3: static void HLCALLBACK hlButton1CB(HLenum event, HLuint object, HLenum thread, fiore@3: HLcache *cache, void *userdata); fiore@3: static void HLCALLBACK hlButton2CB(HLenum event, HLuint object, HLenum thread, fiore@3: HLcache *cache, void *userdata); fiore@3: static void HLCALLBACK hlTouchCB(HLenum event, HLuint object, HLenum thread, fiore@3: HLcache *cache, void *userdata); fiore@3: static void HLCALLBACK hlUntouchCB(HLenum event, HLuint object, HLenum thread, fiore@3: HLcache *cache, void *userdata); fiore@3: static void HLCALLBACK hlMotionCB(HLenum event, HLuint object, HLenum thread, fiore@3: HLcache *cache, void *userdata); fiore@3: #ifdef VIBRATION fiore@3: static void HLCALLBACK vibrationCB(HDdouble force[3], HLcache *cache, void *userdata); fiore@3: fiore@3: static void HLCALLBACK beforeVibrationCB(HLcache *cache, void *userdata); fiore@3: fiore@3: static void HLCALLBACK afterVibrationCB(HLcache *cache, void *userdata); fiore@3: #endif fiore@3: fiore@3: public: fiore@3: fiore@3: enum ClickStatus { NO_CLICK, ONE_CLICK, TWO_CLICK }; fiore@3: fiore@3: static HHD ghHD; fiore@3: static HHLRC ghHLRC; fiore@3: HapticManager(CollectionsManager * cManager, void (*func)(const jchar cmd, const jint ID, const jdouble startx, const jdouble starty, const jdouble endx, const jdouble endy)) fiore@3: : executeCommand(func), wall(true), collectionsManager(cManager), vibrationStatus(NO_VIBRATION), springStatus(RELEASED), alreadyTouchingAttractingElement(false), fiore@3: doneOnce(false), attractionStatus(NO_ATTRACTION), frictionDisabled(false), secondClick(false), clickStart(0), stickyMode(true), fiore@3: lastMovedElement(HL_OBJECT_ANY),stillTouchingLastMovedElement(false),lastTouchedEdgeIsUntouched(false){}; fiore@3: ~HapticManager(void) {} fiore@3: void init(void) throw(HapticException); fiore@3: void draw(void); fiore@3: void setAttractTo(jint hapticId); fiore@3: void pickUp(jint hapticId); fiore@3: bool wasAlreadyTouchingAttractingElement(void); fiore@3: fiore@3: void enableWall(void){ wall = true; } fiore@3: void disableWall(void){ wall = false; } fiore@3: fiore@3: bool isDraggingNode() const { return springStatus == DRAGGING && collectionsManager->isNode(draggedElementID); } fiore@3: bool isDraggingEdge() const { return springStatus == DRAGGING && collectionsManager->isEdge(draggedElementID); } fiore@3: ClickStatus getButton1Status(); fiore@3: void doButton1Click(bool doubleClick); fiore@3: fiore@3: };