1 module unecht.core.components.editor.mouseControls; 2 3 version(UEIncludeEditor): 4 5 import unecht.ue; 6 import unecht.core.events; 7 import unecht.core.entity; 8 import unecht.core.component; 9 import unecht.core.components.internal.gui; 10 import unecht.core.components.editor.mousePicking; 11 import unecht.core.components.editor.gismo; 12 13 import gl3n.linalg; 14 15 /// 16 final class UEEditorMouseControls : UEComponent 17 { 18 mixin(UERegisterObject!()); 19 20 static immutable SPEED_NORMAL = 0.02f; 21 static immutable SPEED_FAST = 0.25f; 22 static immutable MOUSE_CLICK_TIMEOUT = 1.0f; 23 static immutable MOUSE_CLICK_DISTANCE_THRESHOLT = 2.0f; 24 25 private struct MouseClickState 26 { 27 int mouseButtonDown; 28 float time = 0; 29 vec2 pos; 30 } 31 32 private bool mouseDown; 33 private bool moveMode; 34 private vec2 lastMousePos; 35 private MouseClickState mouseClickState; 36 37 override void onCreate() { 38 super.onCreate; 39 40 registerEvent(UEEventType.mouseButton, &onMouseEvent); 41 registerEvent(UEEventType.mousePos, &onMouseEvent); 42 registerEvent(UEEventType.mouseScroll, &onMouseEvent); 43 } 44 45 private void onMouseEvent(UEEvent _ev) 46 { 47 if(_ev.eventType == UEEventType.mouseButton) 48 { 49 if(_ev.mouseButtonEvent.isClick) 50 { 51 onClick(_ev.mouseButtonEvent); 52 return; 53 } 54 55 if(!UEGui.capturesMouse) 56 { 57 if(_ev.mouseButtonEvent.button == 0) 58 { 59 mouseDown = _ev.mouseButtonEvent.isDown; 60 moveMode = !_ev.mouseButtonEvent.pos.mods.isModAlt; 61 } 62 63 if(_ev.mouseButtonEvent.isDown) 64 { 65 mouseClickState.mouseButtonDown = _ev.mouseButtonEvent.button; 66 mouseClickState.time = ue.tickTime; 67 mouseClickState.pos = vec2(_ev.mouseButtonEvent.pos.x,_ev.mouseButtonEvent.pos.y); 68 } 69 else 70 { 71 auto mpos = vec2(_ev.mouseButtonEvent.pos.x,_ev.mouseButtonEvent.pos.y); 72 auto delta = mouseClickState.pos - mpos; 73 if(_ev.mouseButtonEvent.button == mouseClickState.mouseButtonDown && 74 ue.tickTime - mouseClickState.time < MOUSE_CLICK_TIMEOUT && 75 delta.length < MOUSE_CLICK_DISTANCE_THRESHOLT) 76 { 77 triggerMouseClick(mouseClickState.mouseButtonDown, mpos); 78 } 79 } 80 } 81 } 82 else if(_ev.eventType == UEEventType.mousePos) 83 { 84 auto curPos = vec2(_ev.mousePosEvent.x,_ev.mousePosEvent.y); 85 auto delta = curPos - lastMousePos; 86 87 if(mouseDown) 88 { 89 static bool ignoreNext = false; 90 91 const isInsideOfWindow = ue.application.mainWindow.isCursorPosInside(curPos.x,curPos.y); 92 93 if(isInsideOfWindow) 94 { 95 if(!ignoreNext) 96 onDrag(delta,0,_ev.mousePosEvent.mods.isModShift); 97 98 ignoreNext = false; 99 } 100 else 101 { 102 ue.application.mainWindow.wrapAroundCursorPos(curPos.x, curPos.y); 103 ignoreNext = true; 104 } 105 } 106 107 lastMousePos = curPos; 108 } 109 else if(_ev.eventType == UEEventType.mouseScroll) 110 { 111 if(!UEGui.capturesMouse) 112 onDrag(vec2(0), _ev.mouseScrollEvent.yoffset,_ev.mouseScrollEvent.mods.isModShift); 113 } 114 } 115 116 private static triggerMouseClick(int button, vec2 pos) 117 { 118 UEEvent ev; 119 ev.eventType = UEEventType.mouseButton; 120 ev.mouseButtonEvent.action = UEEvent.MouseButtonEvent.Action.click; 121 ev.mouseButtonEvent.button = button; 122 ev.mouseButtonEvent.pos.x = pos.x; 123 ev.mouseButtonEvent.pos.y = pos.y; 124 125 ue.events.trigger(ev); 126 } 127 128 private void onDrag(vec2 delta, double scroll=0, bool fastMode=false) 129 { 130 auto speedNow = fastMode?SPEED_FAST:SPEED_NORMAL; 131 132 //TODO: only zoom like this in move mode and move cam in direction of the ray (eye, cursorPosDir-from-screen-to-frustum) 133 sceneNode.position = sceneNode.position + (sceneNode.forward * scroll * speedNow * 10.0f); 134 135 if(moveMode) 136 { 137 sceneNode.position = sceneNode.position + (sceneNode.right * delta.x * -speedNow); 138 sceneNode.position = sceneNode.position + (sceneNode.up * delta.y * speedNow); 139 } 140 else 141 { 142 sceneNode.angles = sceneNode.angles + vec3(delta.y*speedNow*3,delta.x*-speedNow*3,0); 143 } 144 } 145 146 private void onClick(UEEvent.MouseButtonEvent event) 147 { 148 auto pos = vec2(event.pos.x,event.pos.y); 149 import unecht.core.components._editor; 150 151 auto ray = EditorRootComponent.camera.screenToRay(pos); 152 153 MousePicking.onPick(ray); 154 } 155 }