void CMouseHandler::DrawSelectionBox() { dir = hide ? camera->forward : camera->CalcPixelDir(lastx, lasty); if (activeReceiver) { return; } if (gu->fpsMode) { return; } ButtonPressEvt& bp = buttons[SDL_BUTTON_LEFT]; if (bp.pressed && !bp.chorded && (bp.movement > 4) && (!inMapDrawer || !inMapDrawer->IsDrawMode())) { float2 topright, btmleft; GetSelectionBoxCoeff(bp.camPos, bp.dir, camera->pos, dir, topright, btmleft); float3 dir1S = camera->right * topright.x; float3 dir1U = camera->up * topright.y; float3 dir2S = camera->right * btmleft.x; float3 dir2U = camera->up * btmleft.y; glColor4fv(cmdColors.mouseBox); glPushAttrib(GL_ENABLE_BIT); glDisable(GL_FOG); glDisable(GL_DEPTH_TEST); glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc((GLenum)cmdColors.MouseBoxBlendSrc(), (GLenum)cmdColors.MouseBoxBlendDst()); glLineWidth(cmdColors.MouseBoxLineWidth()); float3 verts[] = { camera->pos + (dir1U + dir1S + camera->forward) * 30, camera->pos + (dir2U + dir1S + camera->forward) * 30, camera->pos + (dir2U + dir2S + camera->forward) * 30, camera->pos + (dir1U + dir2S + camera->forward) * 30, }; glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, verts); glDrawArrays(GL_LINE_LOOP, 0, 4); glDisableClientState(GL_VERTEX_ARRAY); glLineWidth(1.0f); glPopAttrib(); } }
void CMouseHandler::MouseRelease(int x, int y, int button) { if (button > NUM_BUTTONS) return; camHandler->GetCurrentController().MouseRelease(x, y, button); dir = hide ? camera->forward : camera->CalcPixelDir(x, y); buttons[button].pressed = false; if (inMapDrawer && inMapDrawer->IsDrawMode()){ inMapDrawer->MouseRelease(x, y, button); return; } if (activeReceiver) { activeReceiver->MouseRelease(x, y, button); if(!buttons[SDL_BUTTON_LEFT].pressed && !buttons[SDL_BUTTON_MIDDLE].pressed && !buttons[SDL_BUTTON_RIGHT].pressed) activeReceiver = NULL; return; } GML_RECMUTEX_LOCK(sel); //FIXME redundant? (selectedUnits already has mutexes) // Switch camera mode on a middle click that wasn't a middle mouse drag scroll. // the latter is determined by the time the mouse was held down: // switch (dragScrollThreshold) // <= means a camera mode switch // > means a drag scroll if (button == SDL_BUTTON_MIDDLE) { if (buttons[SDL_BUTTON_MIDDLE].time > (gu->gameTime - dragScrollThreshold)) ToggleMiddleClickScroll(); return; } if (gu->fpsMode) { return; } if ((button == SDL_BUTTON_LEFT) && !buttons[button].chorded) { ButtonPressEvt& bp = buttons[SDL_BUTTON_LEFT]; if (!keyInput->IsKeyPressed(SDLK_LSHIFT) && !keyInput->IsKeyPressed(SDLK_LCTRL)) { selectedUnits.ClearSelected(); } if (bp.movement > 4) { // select box float2 topright, btmleft; GetSelectionBoxCoeff(bp.camPos, bp.dir, camera->pos, dir, topright, btmleft); // GetSelectionBoxCoeff returns us the corner pos, but we want to do a inview frustum check. // To do so we need the frustum planes (= plane normal + plane offset). float3 norm1 = camera->up; float3 norm2 = -camera->up; float3 norm3 = camera->right; float3 norm4 = -camera->right; #define signf(x) ((x>0.0f) ? 1.0f : -1) if (topright.y != 0) norm1 = (camera->forward * signf(-topright.y)) + (camera->up / math::fabs(topright.y)); if (btmleft.y != 0) norm2 = (camera->forward * signf( btmleft.y)) - (camera->up / math::fabs(btmleft.y)); if (topright.x != 0) norm3 = (camera->forward * signf(-topright.x)) + (camera->right / math::fabs(topright.x)); if (btmleft.x != 0) norm4 = (camera->forward * signf( btmleft.x)) - (camera->right / math::fabs(btmleft.x)); const float4 plane1(norm1, -(norm1.dot(camera->pos))); const float4 plane2(norm2, -(norm2.dot(camera->pos))); const float4 plane3(norm3, -(norm3.dot(camera->pos))); const float4 plane4(norm4, -(norm4.dot(camera->pos))); selectedUnits.HandleUnitBoxSelection(plane1, plane2, plane3, plane4); } else { CUnit* unit; CFeature* feature; TraceRay::GuiTraceRay(camera->pos, dir, globalRendering->viewRange * 1.4f, NULL, unit, feature, false); selectedUnits.HandleSingleUnitClickSelection(unit, true); } bp.lastRelease = gu->gameTime; } }
void CMouseHandler::MouseRelease(int x, int y, int button) { const CUnit *_lastClicked = lastClicked; lastClicked = nullptr; if (button > NUM_BUTTONS) return; dir = hide ? camera->GetDir() : camera->CalcPixelDir(x, y); buttons[button].pressed = false; if (inMapDrawer && inMapDrawer->IsDrawMode()){ inMapDrawer->MouseRelease(x, y, button); return; } if (activeReceiver != nullptr) { activeReceiver->MouseRelease(x, y, button); if (!buttons[SDL_BUTTON_LEFT].pressed && !buttons[SDL_BUTTON_MIDDLE].pressed && !buttons[SDL_BUTTON_RIGHT].pressed) activeReceiver = nullptr; return; } // Switch camera mode on a middle click that wasn't a middle mouse drag scroll. // the latter is determined by the time the mouse was held down: // switch (dragScrollThreshold) // <= means a camera mode switch // > means a drag scroll if (button == SDL_BUTTON_MIDDLE) { if (buttons[SDL_BUTTON_MIDDLE].time > (gu->gameTime - dragScrollThreshold)) ToggleMiddleClickScroll(); return; } if (gu->fpsMode) return; // outside game, neither guiHandler nor quadField exist and TraceRay would crash if (guihandler == nullptr) return; if ((button == SDL_BUTTON_LEFT) && !buttons[button].chorded) { ButtonPressEvt& bp = buttons[SDL_BUTTON_LEFT]; if (!KeyInput::GetKeyModState(KMOD_SHIFT) && !KeyInput::GetKeyModState(KMOD_CTRL)) selectedUnitsHandler.ClearSelected(); if (bp.movement > 4) { // select box float2 topright, btmleft; GetSelectionBoxCoeff(bp.camPos, bp.dir, camera->GetPos(), dir, topright, btmleft); // GetSelectionBoxCoeff returns us the corner pos, but we want to do a inview frustum check. // To do so we need the frustum planes (= plane normal + plane offset). float3 norm1 = camera->GetUp(); float3 norm2 = -camera->GetUp(); float3 norm3 = camera->GetRight(); float3 norm4 = -camera->GetRight(); #define signf(x) ((x>0.0f) ? 1.0f : -1) if (topright.y != 0) norm1 = (camera->GetDir() * signf(-topright.y)) + (camera->GetUp() / math::fabs(topright.y)); if (btmleft.y != 0) norm2 = (camera->GetDir() * signf( btmleft.y)) - (camera->GetUp() / math::fabs(btmleft.y)); if (topright.x != 0) norm3 = (camera->GetDir() * signf(-topright.x)) + (camera->GetRight() / math::fabs(topright.x)); if (btmleft.x != 0) norm4 = (camera->GetDir() * signf( btmleft.x)) - (camera->GetRight() / math::fabs(btmleft.x)); const float4 plane1(norm1, -(norm1.dot(camera->GetPos()))); const float4 plane2(norm2, -(norm2.dot(camera->GetPos()))); const float4 plane3(norm3, -(norm3.dot(camera->GetPos()))); const float4 plane4(norm4, -(norm4.dot(camera->GetPos()))); selectedUnitsHandler.HandleUnitBoxSelection(plane1, plane2, plane3, plane4); } else { const CUnit* unit = nullptr; const CFeature* feature = nullptr; TraceRay::GuiTraceRay(camera->GetPos(), dir, globalRendering->viewRange * 1.4f, NULL, unit, feature, false); lastClicked = unit; const bool selectType = (bp.lastRelease >= (gu->gameTime - doubleClickTime) && unit == _lastClicked); selectedUnitsHandler.HandleSingleUnitClickSelection(const_cast<CUnit*>(unit), true, selectType); } bp.lastRelease = gu->gameTime; } }