diff options
| author | Lywx <kiritodev01@gmail.com> | 2026-07-02 20:42:38 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-07-02 20:42:38 -0600 |
| commit | 58527d7bf8778bc67179454a19ad8c84a74aff13 (patch) | |
| tree | 37df9df3eb558977b84b5a33b8143f3859c5d057 /src/factories/sm64/TrajectoryFactory.cpp | |
| parent | b42a4fa16f7a75e2a96a7c107e6359c80b685863 (diff) | |
Implemented UI Framework (#225)
* Implemented base renderer among main UI framework implementation
* Implemented basic geo layout rendering
* Implemented animation support among fixing lightning among other things
* Implemented multiple ui factories for sm64
* Implemented first iteration of the custom sequence driver
* Added export buttons on multiple factories
* More sequence player fixes among f3dex2 working correctly
* Implemented pm64 viewers
* Implemented audio support for pm64
* Fully implemented pm64 factories
* Implemented more sm64 factories
* Added tons of missing sf64 factories
* Implemented all assets among sf64 wrong padding
* Run formatting
* Fixed wrong spacing on gfx too
* Fixed CI
* Fixed bad pipeline
Diffstat (limited to 'src/factories/sm64/TrajectoryFactory.cpp')
| -rw-r--r-- | src/factories/sm64/TrajectoryFactory.cpp | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/src/factories/sm64/TrajectoryFactory.cpp b/src/factories/sm64/TrajectoryFactory.cpp index 5849a96..3766eb1 100644 --- a/src/factories/sm64/TrajectoryFactory.cpp +++ b/src/factories/sm64/TrajectoryFactory.cpp @@ -94,3 +94,121 @@ std::optional<std::shared_ptr<IParsedData>> SM64::TrajectoryFactory::parse(std:: return std::make_shared<SM64::TrajectoryData>(trajectoryData); } + +#ifdef BUILD_UI +#include <cmath> +#include <cstring> +#include <unordered_map> + +#include "ui/BaseBackend.h" +#include "ui/Widgets.h" + +namespace { + +std::unordered_map<std::string, UI::OrbitView> sTrajectoryViews; + +void PushTri(std::vector<UI::PreviewVertex>& out, const float a[3], const float b[3], const float c[3], + const unsigned char color[4]) { + const float* pts[3] = { a, b, c }; + for (const auto* p : pts) { + UI::PreviewVertex v{}; + std::memcpy(v.position, p, sizeof(v.position)); + std::memcpy(v.color, color, 4); + out.push_back(v); + } +} + +// Each segment becomes two crossed ribbons so the path reads from any angle; +// color runs green (start) to red (end). +const std::vector<UI::PreviewVertex>& TrajectoryTris(const ParseResultData& item) { + static std::unordered_map<std::string, std::vector<UI::PreviewVertex>> sCache; + auto it = sCache.find(item.name); + if (it != sCache.end()) { + return it->second; + } + + auto data = std::static_pointer_cast<SM64::TrajectoryData>(item.data.value()); + const auto& pts = data->mTrajectoryData; + + std::vector<UI::PreviewVertex> tris; + float mn[3] = { 1e18f, 1e18f, 1e18f }, mx[3] = { -1e18f, -1e18f, -1e18f }; + for (const auto& p : pts) { + const float pos[3] = { (float)p.posX, (float)p.posY, (float)p.posZ }; + for (int k = 0; k < 3; ++k) { + mn[k] = std::min(mn[k], pos[k]); + mx[k] = std::max(mx[k], pos[k]); + } + } + const float dx = mx[0] - mn[0], dy = mx[1] - mn[1], dz = mx[2] - mn[2]; + const float w = std::max(std::sqrt(dx * dx + dy * dy + dz * dz) * 0.008f, 2.0f); + + for (size_t i = 0; i + 1 < pts.size(); ++i) { + const float a[3] = { (float)pts[i].posX, (float)pts[i].posY, (float)pts[i].posZ }; + const float b[3] = { (float)pts[i + 1].posX, (float)pts[i + 1].posY, (float)pts[i + 1].posZ }; + float d[3] = { b[0] - a[0], b[1] - a[1], b[2] - a[2] }; + const float len = std::sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + if (len < 0.0001f) { + continue; + } + for (float& v : d) { + v /= len; + } + float u[3] = { d[2], 0.0f, -d[0] }; + const float ulen = std::sqrt(u[0] * u[0] + u[2] * u[2]); + if (ulen > 0.0001f) { + u[0] = u[0] / ulen * w; + u[2] = u[2] / ulen * w; + } else { + u[0] = w; + u[2] = 0.0f; + } + const float v2[3] = { (d[1] * u[2] - d[2] * u[1]), (d[2] * u[0] - d[0] * u[2]), (d[0] * u[1] - d[1] * u[0]) }; + + const float t = pts.size() > 2 ? (float)i / (float)(pts.size() - 2) : 0.0f; + const unsigned char color[4] = { (unsigned char)(60 + 195 * t), (unsigned char)(220 - 160 * t), 60, 255 }; + + const float* offs[2] = { u, v2 }; + for (const auto* o : offs) { + const float q0[3] = { a[0] - o[0], a[1] - o[1], a[2] - o[2] }; + const float q1[3] = { a[0] + o[0], a[1] + o[1], a[2] + o[2] }; + const float q2[3] = { b[0] + o[0], b[1] + o[1], b[2] + o[2] }; + const float q3[3] = { b[0] - o[0], b[1] - o[1], b[2] - o[2] }; + PushTri(tris, q0, q1, q2, color); + PushTri(tris, q0, q2, q3, color); + } + } + return sCache.emplace(item.name, std::move(tris)).first->second; +} + +} // namespace + +float SM64::TrajectoryFactoryUI::GetItemHeight(const ParseResultData& item) { + return ImGui::GetTextLineHeightWithSpacing() * 2.0f + UI::PreviewBlockHeight(item.name) + 4.0f + + ImGui::GetStyle().ItemSpacing.y * 3.0f; +} + +void SM64::TrajectoryFactoryUI::DrawUI(const ParseResultData& item) { + UI::AssetHeader(item.name, item.type); + if (!item.data.has_value()) { + ImGui::TextDisabled("no data"); + return; + } + auto data = std::static_pointer_cast<SM64::TrajectoryData>(item.data.value()); + ImGui::TextDisabled("trajectory \xe2\x80\x94 %zu points, green start to red end", data->mTrajectoryData.size()); + + UI::OrbitView& view = sTrajectoryViews[item.name]; + const UI::PreviewCanvas canvas = UI::BeginResizableCanvas("##trajview", item.name, view); + if (canvas.visible) { + const auto& tris = TrajectoryTris(item); + if (tris.empty()) { + const char* label = "not enough points"; + const ImVec2 ts = ImGui::CalcTextSize(label); + ImGui::GetWindowDrawList()->AddText(ImVec2(canvas.origin.x + (canvas.size.x - ts.x) * 0.5f, + canvas.origin.y + (canvas.size.y - ts.y) * 0.5f), + IM_COL32(120, 120, 130, 255), label); + } else { + UI::GetBackend()->DrawTriangles(item.name, tris, canvas.origin, canvas.size, view); + } + } +} +#endif // BUILD_UI |
