// Copyright (c) 2008-2023 the Urho3D project // License: MIT #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Urho2DStretchableSprite.h" #include URHO3D_DEFINE_APPLICATION_MAIN(Urho2DStretchableSprite) Urho2DStretchableSprite::Urho2DStretchableSprite(Context* context) : Sample(context) { } void Urho2DStretchableSprite::Start() { // Execute base class startup Sample::Start(); // Create the scene content CreateScene(); // Create the UI content CreateInstructions(); // Setup the viewport for displaying the scene SetupViewport(); // Hook up to the frame update events SubscribeToEvents(); // Set the mouse mode to use in the sample Sample::InitMouseMode(MM_FREE); } void Urho2DStretchableSprite::CreateScene() { scene_ = new Scene(context_); scene_->CreateComponent(); // Create camera node cameraNode_ = scene_->CreateChild("Camera"); // Set camera's position cameraNode_->SetPosition(Vector3(0.0f, 0.0f, -10.0f)); auto* camera = cameraNode_->CreateComponent(); camera->SetOrthographic(true); auto* graphics = GetSubsystem(); camera->SetOrthoSize((float)graphics->GetHeight() * PIXEL_SIZE); refSpriteNode_ = scene_->CreateChild("regular sprite"); stretchSpriteNode_ = scene_->CreateChild("stretchable sprite"); auto* cache = GetSubsystem(); auto* sprite = cache->GetResource("Urho2D/Stretchable.png"); if (sprite) { refSpriteNode_->CreateComponent()->SetSprite(sprite); auto stretchSprite = stretchSpriteNode_->CreateComponent(); stretchSprite->SetSprite(sprite); stretchSprite->SetBorder({25, 25, 25, 25}); refSpriteNode_->Translate2D(Vector2{-2.0f, 0.0f}); stretchSpriteNode_->Translate2D(Vector2{2.0f, 0.0f}); } } void Urho2DStretchableSprite::CreateInstructions() { auto* cache = GetSubsystem(); auto* ui = GetSubsystem(); // Construct new Text object, set string to display and font to use auto* instructionText = ui->GetRoot()->CreateChild(); instructionText->SetText( "Use WASD keys to transform, Tab key to cycle through\n" "Scale, Rotate, and Translate transform modes. In Rotate\n" "mode, combine A/D keys with Ctrl key to rotate about\n" "the Z axis"); instructionText->SetFont(cache->GetResource("Fonts/Anonymous Pro.ttf"), 12); // Position the text relative to the screen center instructionText->SetHorizontalAlignment(HA_CENTER); instructionText->SetVerticalAlignment(VA_CENTER); instructionText->SetPosition(0, ui->GetRoot()->GetHeight() / 4); } void Urho2DStretchableSprite::SetupViewport() { auto* renderer = GetSubsystem(); // Set up a viewport to the Renderer subsystem so that the 3D scene can be seen SharedPtr viewport(new Viewport(context_, scene_, cameraNode_->GetComponent())); renderer->SetViewport(0, viewport); } void Urho2DStretchableSprite::SubscribeToEvents() { SubscribeToEvent(E_KEYUP, URHO3D_HANDLER(Urho2DStretchableSprite, OnKeyUp)); // Subscribe HandleUpdate() function for processing update events SubscribeToEvent(E_UPDATE, URHO3D_HANDLER(Urho2DStretchableSprite, HandleUpdate)); // Unsubscribe the SceneUpdate event from base class to prevent camera pitch and yaw in 2D sample UnsubscribeFromEvent(E_SCENEUPDATE); } void Urho2DStretchableSprite::HandleUpdate(StringHash /*eventType*/, VariantMap& eventData) { using namespace Update; // Take the frame time step, which is stored as a float float timeStep = eventData[P_TIMESTEP].GetFloat(); switch (selectTransform_) { case 0: ScaleSprites(timeStep); break; case 1: RotateSprites(timeStep); break; case 2: TranslateSprites(timeStep); break; default: URHO3D_LOGERRORF("bad transform selection: %d", selectTransform_); } } void Urho2DStretchableSprite::OnKeyUp(StringHash /*eventType*/, VariantMap& eventData) { using namespace KeyUp; const auto key = eventData[P_KEY].GetI32(); if (key == KEY_TAB) { ++selectTransform_; selectTransform_ %= 3; } else if (key == KEY_ESCAPE) engine_->Exit(); } void Urho2DStretchableSprite::TranslateSprites(float timeStep) { static constexpr auto speed = 1.0f; const auto input = GetSubsystem(); const auto left = input->GetKeyDown(KEY_A), right = input->GetKeyDown(KEY_D), up = input->GetKeyDown(KEY_W), down = input->GetKeyDown(KEY_S); if (left || right || up || down) { const auto quantum = timeStep * speed; const auto translate = Vector2{(left ? -quantum : 0.0f) + (right ? quantum : 0.0f), (down ? -quantum : 0.0f) + (up ? quantum : 0.0f)}; refSpriteNode_->Translate2D(translate); stretchSpriteNode_->Translate2D(translate); } } void Urho2DStretchableSprite::RotateSprites(float timeStep) { static constexpr auto speed = 45.0f; const auto input = GetSubsystem(); const auto left = input->GetKeyDown(KEY_A), right = input->GetKeyDown(KEY_D), up = input->GetKeyDown(KEY_W), down = input->GetKeyDown(KEY_S), ctrl = input->GetKeyDown(KEY_CTRL); if (left || right || up || down) { const auto quantum = timeStep * speed; const auto xrot = (up ? -quantum : 0.0f) + (down ? quantum : 0.0f); const auto rot2 = (left ? -quantum : 0.0f) + (right ? quantum : 0.0f); const auto totalRot = Quaternion{xrot, ctrl ? 0.0f : rot2, ctrl ? rot2 : 0.0f}; refSpriteNode_->Rotate(totalRot); stretchSpriteNode_->Rotate(totalRot); } } void Urho2DStretchableSprite::ScaleSprites(float timeStep) { static constexpr auto speed = 0.5f; const auto input = GetSubsystem(); const auto left = input->GetKeyDown(KEY_A), right = input->GetKeyDown(KEY_D), up = input->GetKeyDown(KEY_W), down = input->GetKeyDown(KEY_S); if (left || right || up || down) { const auto quantum = timeStep * speed; const auto scale = Vector2{1.0f + (right ? quantum : left ? -quantum : 0.0f), 1.0f + (up ? quantum : down ? -quantum : 0.0f)}; refSpriteNode_->Scale2D(scale); stretchSpriteNode_->Scale2D(scale); } }