Files

78 lines
2.5 KiB
C++

#include <imgui.h>
#include <algorithm>
#include <sophia/application.hpp>
#include <sophia/components.hpp>
#include <sophia/entity.hpp>
#include <sophia/scene_view.hpp>
#include <sophia/ui/panel.hpp>
#include <string>
// Shows a render target filling the whole panel.
class ViewportPanel : public sophia::Panel {
public:
ViewportPanel(sophia::UI& ui, sophia::RenderTargetHandle target)
: Panel{{.name = "Image",
.windowFlags = ImGuiWindowFlags_NoScrollbar |
ImGuiWindowFlags_NoScrollWithMouse}},
ui{ui},
target{target} {}
void onUpdate(const sophia::FrameInfo&) override { ui.image(target); }
private:
sophia::UI& ui;
sophia::RenderTargetHandle target;
};
// Displays an image file (anything stb_image reads: JPEG, PNG, BMP, ...) as a
// sprite in a 2D scene, scaled to fit the viewport.
// image_viewer [path]
class ImageViewer : public sophia::Application {
public:
ImageViewer()
: Application{{.width = 1000, .height = 750, .name = "ImageViewer"}} {}
void onCreate() override {
std::string path =
args.size() > 1 ? args[1] : IMAGE_VIEWER_ASSET_DIR "/dog.jpeg";
sophia::SceneHandle sceneHandle = scenes().create();
sophia::Scene& scene = scenes().get(sceneHandle);
camera = scene.createCamera();
sophia::TextureHandle texture = resources().load<sophia::Texture>(path);
imageSize = resources().getExtent(texture);
// One world unit per image pixel; the camera zooms to fit.
sophia::Entity image = scene.createEntity("Image");
image.addComponent<sophia::SpriteComponent>(
sophia::SpriteComponent{.texture = texture, .size = imageSize});
target = resources().create<sophia::RenderTarget>();
sceneViews().create({.scene = sceneHandle,
.target = target,
.clearColor = {0.1f, 0.1f, 0.15f, 1.f}});
panels().emplace<ViewportPanel>(ui(), target);
// panels().setDefaultLayout({.center = {"Image"}});
}
void onUpdate(const sophia::FrameInfo&) override {
// Fit the whole image: show enough height that neither dimension of the
// image overflows the viewport.
glm::vec2 viewport = resources().getExtent(target);
float viewportAspect = viewport.x / viewport.y;
camera.getComponent<sophia::CameraComponent>().ortho.height =
std::max(imageSize.y, imageSize.x / viewportAspect);
}
private:
sophia::Entity camera;
sophia::RenderTargetHandle target{};
glm::vec2 imageSize{1.f};
};
SOPHIA_MAIN(ImageViewer)