//------------------------------------------------------------------------------------------------------------------------------------------------------ void BaseApplication::HandleSceneUpdate(StringHash eventType, VariantMap& eventData) { // Move the camera by touch, if the camera node is initialized by descendant sample class if (touchEnabled_ && cameraNode_) { Input* input = GetSubsystem<Input>(); for (unsigned i = 0; i < input->GetNumTouches(); ++i) { TouchState* state = input->GetTouch(i); if (!state->touchedElement_) // Touch on empty space { if (state->delta_.x_ ||state->delta_.y_) { Camera* camera = cameraNode_->GetComponent<Camera>(); if (!camera) return; Graphics* graphics = GetSubsystem<Graphics>(); yaw_ += TOUCH_SENSITIVITY * camera->GetFov() / graphics->GetHeight() * state->delta_.x_; pitch_ += TOUCH_SENSITIVITY * camera->GetFov() / graphics->GetHeight() * state->delta_.y_; // Construct new orientation for the camera scene node from yaw and pitch; roll is fixed to zero cameraNode_->SetRotation(Quaternion(pitch_, yaw_, 0.0f)); } else { // Move the cursor to the touch position Cursor* cursor = GetSubsystem<UI>()->GetCursor(); if (cursor && cursor->IsVisible()) cursor->SetPosition(state->position_); } } } } }
void Touch::UpdateTouches(Controls& controls) // Called from HandleUpdate { zoom_ = false; // reset bool Input* input = GetSubsystem<Input>(); // Zoom in/out if (input->GetNumTouches() == 2) { TouchState* touch1 = input->GetTouch(0); TouchState* touch2 = input->GetTouch(1); // Check for zoom pattern (touches moving in opposite directions and on empty space) if (!touch1->touchedElement_ && !touch2->touchedElement_ && ((touch1->delta_.y_ > 0 && touch2->delta_.y_ < 0) || (touch1->delta_.y_ < 0 && touch2->delta_.y_ > 0))) zoom_ = true; else zoom_ = false; if (zoom_) { int sens = 0; // Check for zoom direction (in/out) if (Abs(touch1->position_.y_ - touch2->position_.y_) > Abs(touch1->lastPosition_.y_ - touch2->lastPosition_.y_)) sens = -1; else sens = 1; cameraDistance_ += Abs(touch1->delta_.y_ - touch2->delta_.y_) * sens * touchSensitivity_ / 50.0f; cameraDistance_ = Clamp(cameraDistance_, CAMERA_MIN_DIST, CAMERA_MAX_DIST); // Restrict zoom range to [1;20] } } // Gyroscope (emulated by SDL through a virtual joystick) if (useGyroscope_ && input->GetNumJoysticks() > 0) // numJoysticks = 1 on iOS & Android { JoystickState* joystick = input->GetJoystickByIndex(0); if (joystick->GetNumAxes() >= 2) { if (joystick->GetAxisPosition(0) < -GYROSCOPE_THRESHOLD) controls.Set(CTRL_LEFT, true); if (joystick->GetAxisPosition(0) > GYROSCOPE_THRESHOLD) controls.Set(CTRL_RIGHT, true); if (joystick->GetAxisPosition(1) < -GYROSCOPE_THRESHOLD) controls.Set(CTRL_FORWARD, true); if (joystick->GetAxisPosition(1) > GYROSCOPE_THRESHOLD) controls.Set(CTRL_BACK, true); } } }
void UIDrag::HandleUpdate(StringHash eventType, VariantMap& eventData) { UI* ui = GetSubsystem<UI>(); UIElement* root = ui->GetRoot(); Input* input = GetSubsystem<Input>(); unsigned n = input->GetNumTouches(); for (unsigned i = 0; i < n; i++) { Text* t = (Text*)root->GetChild("Touch " + String(i)); TouchState* ts = input->GetTouch(i); t->SetText("Touch " + String(ts->touchID_)); IntVector2 pos = ts->position_; pos.y_ -= 30; t->SetPosition(pos); t->SetVisible(true); } for (unsigned i = n; i < 10; i++) { Text* t = (Text*)root->GetChild("Touch " + String(i)); t->SetVisible(false); } if (input->GetKeyPress(KEY_SPACE)) { PODVector<UIElement*> elements; root->GetChildrenWithTag(elements, "SomeTag"); for (PODVector<UIElement*>::ConstIterator i = elements.Begin(); i != elements.End(); ++i) { UIElement* element = *i; element->SetVisible(!element->IsVisible()); } } }
void VehicleDemo::HandleUpdate(StringHash eventType, VariantMap& eventData) { using namespace Update; Input* input = GetSubsystem<Input>(); if (vehicle_) { UI* ui = GetSubsystem<UI>(); // Get movement controls and assign them to the vehicle component. If UI has a focused element, clear controls if (!ui->GetFocusElement()) { vehicle_->controls_.Set(CTRL_FORWARD, input->GetKeyDown(KEY_W)); vehicle_->controls_.Set(CTRL_BACK, input->GetKeyDown(KEY_S)); vehicle_->controls_.Set(CTRL_LEFT, input->GetKeyDown(KEY_A)); vehicle_->controls_.Set(CTRL_RIGHT, input->GetKeyDown(KEY_D)); // Add yaw & pitch from the mouse motion or touch input. Used only for the camera, does not affect motion if (touchEnabled_) { for (unsigned i = 0; i < input->GetNumTouches(); ++i) { TouchState* state = input->GetTouch(i); if (!state->touchedElement_) // Touch on empty space { Camera* camera = cameraNode_->GetComponent<Camera>(); if (!camera) return; Graphics* graphics = GetSubsystem<Graphics>(); vehicle_->controls_.yaw_ += TOUCH_SENSITIVITY * camera->GetFov() / graphics->GetHeight() * state->delta_.x_; vehicle_->controls_.pitch_ += TOUCH_SENSITIVITY * camera->GetFov() / graphics->GetHeight() * state->delta_.y_; } } } else { vehicle_->controls_.yaw_ += (float)input->GetMouseMoveX() * YAW_SENSITIVITY; vehicle_->controls_.pitch_ += (float)input->GetMouseMoveY() * YAW_SENSITIVITY; } // Limit pitch vehicle_->controls_.pitch_ = Clamp(vehicle_->controls_.pitch_, 0.0f, 80.0f); // Check for loading / saving the scene if (input->GetKeyPress(KEY_F5)) { File saveFile(context_, GetSubsystem<FileSystem>()->GetProgramDir() + "Data/Scenes/VehicleDemo.xml", FILE_WRITE); scene_->SaveXML(saveFile); } if (input->GetKeyPress(KEY_F7)) { File loadFile(context_, GetSubsystem<FileSystem>()->GetProgramDir() + "Data/Scenes/VehicleDemo.xml", FILE_READ); scene_->LoadXML(loadFile); // After loading we have to reacquire the weak pointer to the Vehicle component, as it has been recreated // Simply find the vehicle's scene node by name as there's only one of them Node* vehicleNode = scene_->GetChild("Vehicle", true); if (vehicleNode) vehicle_ = vehicleNode->GetComponent<Vehicle>(); } } else vehicle_->controls_.Set(CTRL_FORWARD | CTRL_BACK | CTRL_LEFT | CTRL_RIGHT, false); } }
void CharacterDemo::HandleUpdate(StringHash eventType, VariantMap& eventData) { using namespace Update; Input* input = GetSubsystem<Input>(); if (character_) { // Clear previous controls character_->controls_.Set(CTRL_FORWARD | CTRL_BACK | CTRL_LEFT | CTRL_RIGHT | CTRL_JUMP, false); // Update controls using touch utility class if (touch_) touch_->UpdateTouches(character_->controls_); // Update controls using keys UI* ui = GetSubsystem<UI>(); if (!ui->GetFocusElement()) { if (!touch_ || !touch_->useGyroscope_) { character_->controls_.Set(CTRL_FORWARD, input->GetKeyDown(KEY_W)); character_->controls_.Set(CTRL_BACK, input->GetKeyDown(KEY_S)); character_->controls_.Set(CTRL_LEFT, input->GetKeyDown(KEY_A)); character_->controls_.Set(CTRL_RIGHT, input->GetKeyDown(KEY_D)); } character_->controls_.Set(CTRL_JUMP, input->GetKeyDown(KEY_SPACE)); // Add character yaw & pitch from the mouse motion or touch input if (touchEnabled_) { for (unsigned i = 0; i < input->GetNumTouches(); ++i) { TouchState* state = input->GetTouch(i); if (!state->touchedElement_) // Touch on empty space { Camera* camera = cameraNode_->GetComponent<Camera>(); if (!camera) return; Graphics* graphics = GetSubsystem<Graphics>(); character_->controls_.yaw_ += TOUCH_SENSITIVITY * camera->GetFov() / graphics->GetHeight() * state->delta_.x_; character_->controls_.pitch_ += TOUCH_SENSITIVITY * camera->GetFov() / graphics->GetHeight() * state->delta_.y_; } } } else { character_->controls_.yaw_ += (float)input->GetMouseMoveX() * YAW_SENSITIVITY; character_->controls_.pitch_ += (float)input->GetMouseMoveY() * YAW_SENSITIVITY; } // Limit pitch character_->controls_.pitch_ = Clamp(character_->controls_.pitch_, -80.0f, 80.0f); // Set rotation already here so that it's updated every rendering frame instead of every physics frame character_->GetNode()->SetRotation(Quaternion(character_->controls_.yaw_, Vector3::UP)); // Switch between 1st and 3rd person if (input->GetKeyPress(KEY_F)) firstPerson_ = !firstPerson_; // Turn on/off gyroscope on mobile platform if (touch_ && input->GetKeyPress(KEY_G)) touch_->useGyroscope_ = !touch_->useGyroscope_; // Check for loading / saving the scene if (input->GetKeyPress(KEY_F5)) { File saveFile(context_, GetSubsystem<FileSystem>()->GetProgramDir() + "Data/Scenes/CharacterDemo.xml", FILE_WRITE); scene_->SaveXML(saveFile); } if (input->GetKeyPress(KEY_F7)) { File loadFile(context_, GetSubsystem<FileSystem>()->GetProgramDir() + "Data/Scenes/CharacterDemo.xml", FILE_READ); scene_->LoadXML(loadFile); // After loading we have to reacquire the weak pointer to the Character component, as it has been recreated // Simply find the character's scene node by name as there's only one of them Node* characterNode = scene_->GetChild("Jack", true); if (characterNode) character_ = characterNode->GetComponent<Character>(); } } } }