80 lines
2.6 KiB
C++
80 lines
2.6 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.createEntity("Camera");
|
|
camera.addComponent<sophia::CameraComponent>();
|
|
|
|
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>();
|
|
views().create({.scene = sceneHandle,
|
|
.target = target,
|
|
.camera = camera,
|
|
.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)
|