Initial claude dump

This commit is contained in:
2026-09-25 22:59:01 -07:00
parent 5644782a1f
commit a21a842b5b
26 changed files with 1101 additions and 158 deletions
+123 -18
View File
@@ -3,30 +3,135 @@
#include <imgui.h>
#include <cstdio>
#include <sophia/components.hpp>
void InspectorPanel::onUpdate(const sophia::FrameInfo&) {
char nameBuf[128];
std::snprintf(nameBuf, sizeof(nameBuf), "%s", name.c_str());
if (ImGui::InputText("Name", nameBuf, sizeof(nameBuf))) {
name = nameBuf;
if (!selected) {
ImGui::TextDisabled("No entity selected");
return;
}
ImGui::Text("Tag: %s", tag.c_str());
drawTag();
ImGui::Separator();
drawTransform();
drawCamera();
drawSprite();
ImGui::Separator();
drawAddComponent();
}
if (ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::DragFloat3("Position", &position.x, 0.1f);
ImGui::DragFloat3("Rotation", &rotation.x, 0.1f);
ImGui::DragFloat3("Scale", &scale.x, 0.1f);
}
void InspectorPanel::drawTag() {
auto& tag = selected.getComponent<sophia::TagComponent>();
if (ImGui::CollapsingHeader("Mesh Renderer",
ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::Text("Mesh: %s", meshName.c_str());
ImGui::Text("Material: %s", materialName.c_str());
}
if (ImGui::CollapsingHeader("Script", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::Text("%s", scriptName.c_str());
char nameBuf[128];
std::snprintf(nameBuf, sizeof(nameBuf), "%s", tag.tag.c_str());
if (ImGui::InputText("Name", nameBuf, sizeof(nameBuf))) {
tag.tag = nameBuf;
}
}
void InspectorPanel::drawTransform() {
if (!selected.hasComponent<sophia::TransformComponent>() ||
!ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) {
return;
}
auto& transform = selected.getComponent<sophia::TransformComponent>();
ImGui::DragFloat3("Position", &transform.position.x, 0.1f);
// 2D only: edits rotation around Z and drops any X/Y rotation.
float degrees = glm::degrees(glm::eulerAngles(transform.rotation).z);
if (ImGui::DragFloat("Rotation", &degrees, 1.0f)) {
transform.rotation =
glm::angleAxis(glm::radians(degrees), glm::vec3{0.f, 0.f, 1.f});
}
ImGui::DragFloat3("Scale", &transform.scale.x, 0.1f);
}
void InspectorPanel::drawCamera() {
if (!selected.hasComponent<sophia::CameraComponent>() ||
!ImGui::CollapsingHeader("Camera", ImGuiTreeNodeFlags_DefaultOpen)) {
return;
}
auto& camera = selected.getComponent<sophia::CameraComponent>();
int projection = static_cast<int>(camera.projection);
if (ImGui::Combo("Projection", &projection, "Orthographic\0Perspective\0")) {
camera.projection =
static_cast<sophia::CameraComponent::Projection>(projection);
}
if (camera.projection == sophia::CameraComponent::Projection::Orthographic) {
ImGui::DragFloat("Height", &camera.ortho.height, 0.1f, 0.01f, 10000.f);
} else {
float fov = glm::degrees(camera.perspective.fov);
if (ImGui::DragFloat("FOV", &fov, 0.5f, 1.f, 179.f)) {
camera.perspective.fov = glm::radians(fov);
}
}
}
void InspectorPanel::drawSprite() {
if (!selected.hasComponent<sophia::SpriteComponent>()) {
return;
}
bool open = true;
if (!ImGui::CollapsingHeader("Sprite", &open,
ImGuiTreeNodeFlags_DefaultOpen)) {
if (!open) {
selected.removeComponent<sophia::SpriteComponent>();
}
return;
}
auto& sprite = selected.getComponent<sophia::SpriteComponent>();
const char* current = "None";
for (const auto& [name, handle] : textures) {
if (handle == sprite.texture) {
current = name.c_str();
}
}
if (ImGui::BeginCombo("Texture", current)) {
if (ImGui::Selectable("None", !sprite.texture.isValid())) {
sprite.texture = sophia::INVALID_HANDLE;
}
for (const auto& [name, handle] : textures) {
if (ImGui::Selectable(name.c_str(), handle == sprite.texture)) {
sprite.texture = handle;
}
}
ImGui::EndCombo();
}
ImGui::ColorEdit4("Color", &sprite.color.x);
ImGui::DragFloat2("Size", &sprite.size.x, 0.05f);
ImGui::SliderFloat2("Pivot", &sprite.pivot.x, 0.f, 1.f);
ImGui::DragFloat4("UV Rect", &sprite.uvRect.x, 0.01f);
ImGui::DragInt("Sort Order", &sprite.sortOrder);
if (!open) {
selected.removeComponent<sophia::SpriteComponent>();
}
}
void InspectorPanel::drawAddComponent() {
if (ImGui::Button("Add Component")) {
ImGui::OpenPopup("AddComponent");
}
if (ImGui::BeginPopup("AddComponent")) {
if (!selected.hasComponent<sophia::SpriteComponent>() &&
ImGui::MenuItem("Sprite")) {
selected.addComponent<sophia::SpriteComponent>();
}
if (!selected.hasComponent<sophia::CameraComponent>() &&
ImGui::MenuItem("Camera")) {
selected.addComponent<sophia::CameraComponent>();
}
ImGui::EndPopup();
}
}
+17 -11
View File
@@ -1,25 +1,31 @@
#pragma once
#include <glm/glm.hpp>
#include <sophia/entity.hpp>
#include <sophia/frame_info.hpp>
#include <sophia/handles.hpp>
#include <sophia/ui/panel.hpp>
#include <string>
#include <utility>
#include <vector>
class InspectorPanel : public sophia::Panel {
public:
InspectorPanel() : Panel{{.name = "Inspector"}} {}
// Stand-in for an asset browser: the textures a sprite can pick from.
using TextureList =
std::vector<std::pair<std::string, sophia::TextureHandle>>;
InspectorPanel(sophia::Entity& selected, const TextureList& textures)
: Panel{{.name = "Inspector"}}, selected{selected}, textures{textures} {}
void onUpdate(const sophia::FrameInfo& frameInfo) override;
private:
std::string name = "Player";
std::string tag = "Player";
void drawTag();
void drawTransform();
void drawCamera();
void drawSprite();
void drawAddComponent();
glm::vec3 position{0.0f, 1.0f, 0.0f};
glm::vec3 rotation{0.0f, 0.0f, 0.0f};
glm::vec3 scale{1.0f, 1.0f, 1.0f};
std::string meshName = "player_capsule.fbx";
std::string materialName = "player_mat";
std::string scriptName = "PlayerController.lua";
sophia::Entity& selected;
const TextureList& textures;
};
+20 -20
View File
@@ -2,31 +2,31 @@
#include <imgui.h>
void SceneHierarchyPanel::drawNode(const Node& node) {
if (node.children.empty()) {
#include <sophia/components.hpp>
void SceneHierarchyPanel::onUpdate(const sophia::FrameInfo&) {
if (ImGui::Button("+ Sprite")) {
selected = scene.createEntity("Sprite");
selected.addComponent<sophia::SpriteComponent>();
}
ImGui::Separator();
// Flat for now: there is no parent/child component yet.
scene.forEachEntity([this](sophia::Entity entity) {
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf |
ImGuiTreeNodeFlags_NoTreePushOnOpen |
ImGuiTreeNodeFlags_SpanAvailWidth;
if (node.name == selected) {
if (entity == selected) {
flags |= ImGuiTreeNodeFlags_Selected;
}
ImGui::TreeNodeEx(node.name.c_str(), flags);
const std::string& name = entity.getComponent<sophia::TagComponent>().tag;
ImGui::PushID(static_cast<int>(static_cast<sophia::u32>(entity)));
ImGui::TreeNodeEx(name.c_str(), flags);
if (ImGui::IsItemClicked()) {
selected = node.name;
selected = entity;
}
return;
}
if (ImGui::TreeNodeEx(node.name.c_str(), ImGuiTreeNodeFlags_SpanAvailWidth)) {
for (const Node& child : node.children) {
drawNode(child);
}
ImGui::TreePop();
}
}
void SceneHierarchyPanel::onUpdate(const sophia::FrameInfo&) {
for (const Node& node : nodes) {
drawNode(node);
}
ImGui::PopID();
});
}
+8 -20
View File
@@ -1,32 +1,20 @@
#pragma once
#include <sophia/entity.hpp>
#include <sophia/frame_info.hpp>
#include <sophia/scene.hpp>
#include <sophia/ui/panel.hpp>
#include <string>
#include <vector>
class SceneHierarchyPanel : public sophia::Panel {
public:
SceneHierarchyPanel() : Panel{{.name = "Scene Hierarchy", .locked = true}} {}
SceneHierarchyPanel(sophia::Scene& scene, sophia::Entity& selected)
: Panel{{.name = "Scene Hierarchy", .locked = true}},
scene{scene},
selected{selected} {}
void onUpdate(const sophia::FrameInfo& frameInfo) override;
private:
struct Node {
std::string name;
std::vector<Node> children;
};
void drawNode(const Node& node);
std::vector<Node> nodes = {
{"Main Camera", {}},
{"Directional Light", {}},
{"Ground", {}},
{"Player", {}},
{"Enemies", {{"Enemy_01", {}}, {"Enemy_02", {}}, {"Enemy_03", {}}}},
{"Props", {{"Crate_01", {}}, {"Crate_02", {}}}},
};
std::string selected;
sophia::Scene& scene;
sophia::Entity& selected;
};