#pragma once #include #include #include #include #include #include #include /** * Shows the scene through its active camera. Click a sprite to select it, * drag it to move it (in Move mode). * * Picking and moving are 2D: they assume an orthographic camera rotated only * around Z, and work in the z = 0 plane. */ class ViewportPanel : public sophia::Panel { public: ViewportPanel(sophia::UI& ui, sophia::RenderTargetHandle target, sophia::Scene& scene, sophia::Entity& selected) : Panel{{.name = "Viewport", .windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse}}, ui{ui}, target{target}, scene{scene}, selected{selected} {} void onUpdate(const sophia::FrameInfo& frameInfo) override; private: // Where the scene image is on screen this frame, and the camera looking // through it. struct ViewportTransform { ImVec2 origin; ImVec2 size; glm::mat4 viewProjection; glm::mat4 inverseViewProjection; ImVec2 worldToScreen(const glm::vec3& world) const; glm::vec2 screenToWorld(const ImVec2& screen) const; }; void drawToolbar(); void drawGrid(ImVec2 origin, ImVec2 size); void handleInput(const ViewportTransform& viewport); void drawSelection(const ViewportTransform& viewport); // The top-most sprite under `world`, or a null Entity. sophia::Entity pick(glm::vec2 world); sophia::UI& ui; sophia::RenderTargetHandle target; sophia::Scene& scene; sophia::Entity& selected; enum class GizmoMode { Move, Rotate, Scale }; GizmoMode gizmoMode = GizmoMode::Move; bool showGrid = true; // Set while a drag that started on the selected entity is moving it. bool dragging = false; };