8#include "absl/strings/str_format.h"
13#include "imgui/imgui.h"
14#include "imgui/misc/cpp/imgui_stdlib.h"
20constexpr ImVec4
kGreen{0.2f, 0.75f, 0.3f, 1.0f};
21constexpr ImVec4
kRed{0.85f, 0.2f, 0.2f, 1.0f};
22constexpr ImVec4
kYellow{0.85f, 0.75f, 0.1f, 1.0f};
23constexpr ImVec4
kGrey{0.55f, 0.55f, 0.55f, 1.0f};
30 return flag ?
"OK" :
"X";
35 ImGui::TextColored(
kGreen, tr(
"[ran]"));
38 if (state ==
"skipped") {
39 ImGui::TextColored(
kGrey, tr(
"[skipped]"));
42 ImGui::TextColored(
kYellow,
"[%s]", state.c_str());
46 ImGui::Text(
" %s", label);
48 if (flag.has_value()) {
52 ImGui::TextColored(
kGrey,
"-");
59 std::ifstream file(path);
60 if (!file.is_open()) {
83 project->GetZ3dkArtifactPath(
"annotations.json"), &annotations);
84 const bool has_hooks =
86 if (!has_lint && !has_annotations && !has_hooks) {
90 if (!ImGui::CollapsingHeader(tr(
"z3dk Artifacts"),
91 ImGuiTreeNodeFlags_DefaultOpen)) {
97 ?
static_cast<int>(lint[
"errors"].
size())
101 ?
static_cast<int>(lint[
"warnings"].
size())
103 ImGui::Text(tr(
"Lint diagnostics: %d error(s), %d warning(s)"), errors,
106 if (has_annotations) {
107 const int count = annotations.
contains(
"annotations") &&
108 annotations[
"annotations"].
is_array()
109 ?
static_cast<int>(annotations[
"annotations"].
size())
111 ImGui::Text(tr(
"Annotations: %d"), count);
115 ?
static_cast<int>(hooks[
"hooks"].
size())
117 ImGui::Text(tr(
"Hook/write blocks: %d"), count);
129 return "oracle.validation";
133 return "Hack Validation";
149 return "Hack Validation";
153 return "Run project validation and readiness checks for the active hack";
159 return project !=
nullptr && project->project_opened() && backend !=
nullptr;
163 return "Validation backend is not available for the active hack project";
191 return project->rom_filename;
196 return "roms/zelda3.sfc";
203 if (
pending_.wait_for(std::chrono::milliseconds(0)) !=
204 std::future_status::ready) {
237 Rom* rom_context =
nullptr;
245 pending_ = std::async(std::launch::async, [mode, smoke_opts, preflight_opts,
248 return backend->RunValidation(mode, smoke_opts, preflight_opts,
255 result.
error_message =
"No hack workflow backend registered";
256 result.
status_code = absl::StatusCode::kFailedPrecondition;
262 ImGui::SeparatorText(tr(
"Options"));
264 ImGui::SetNextItemWidth(320.0f);
265 ImGui::InputText(tr(
"ROM Path"), &
rom_path_);
267 if (ImGui::SmallButton(tr(
"From ROM"))) {
271 ImGui::SetNextItemWidth(80.0f);
277 ImGui::SeparatorText(tr(
"Preflight options"));
278 ImGui::SetNextItemWidth(200.0f);
281 ImGui::TextDisabled(tr(
"(e.g. 0x25,0x27)"));
285 ImGui::SetNextItemWidth(280.0f);
292 const bool rom_missing =
295 ImGui::BeginDisabled();
298 ImGui::BeginDisabled();
301 if (ImGui::Button(tr(
"Run Structural Smoke"))) {
305 if (ImGui::Button(tr(
"Run Strict Readiness"))) {
309 if (ImGui::Button(tr(
"Run Oracle Preflight"))) {
314 ImGui::EndDisabled();
319 ImGui::EndDisabled();
321 ImGui::TextColored(kRed, tr(
"Load a ROM first"));
327 ImGui::TextDisabled(tr(
"No results yet. Run a check above."));
332 const char* mode_label =
336 ?
"Strict Readiness Smoke"
337 :
"Structural Smoke");
338 const bool overall_ok =
339 result.smoke.has_value()
341 : (result.preflight.has_value() && result.preflight->ok);
343 ImGui::TextColored(overall_ok ? kGreen : kRed,
"%s %s", CheckStr(overall_ok),
345 ImGui::SameLine(0.0f, 16.0f);
346 ImGui::TextColored(kGrey,
"%s", result.timestamp.c_str());
348 ImGui::SetNextItemWidth(380.0f);
349 ImGui::InputText(
"##cli_cmd",
const_cast<char*
>(result.cli_command.c_str()),
350 result.cli_command.size() + 1, ImGuiInputTextFlags_ReadOnly);
352 if (ImGui::SmallButton(tr(
"Copy"))) {
353 ImGui::SetClipboardText(result.cli_command.c_str());
356 if (!result.error_message.empty()) {
357 ImGui::TextColored(kRed,
ICON_MD_ERROR " %s", result.error_message.c_str());
359 tr(
"Hint: check that the ROM is loaded and the command is available."));
364 if (result.json_parse_failed) {
365 ImGui::TextColored(kYellow,
371 if (result.smoke.has_value()) {
374 if (result.preflight.has_value()) {
377 DrawZ3dkArtifactSummary();
382 if (ImGui::CollapsingHeader(tr(
"D4 Zora Temple"),
383 ImGuiTreeNodeFlags_DefaultOpen)) {
385 tr(
" Structural %s"),
387 ImGui::Text(tr(
" Required rooms check:"));
390 DrawOptionalBool(
" Rooms 0x25/0x27 have collision:",
394 if (ImGui::CollapsingHeader(tr(
"D6 Goron Mines"),
395 ImGuiTreeNodeFlags_DefaultOpen)) {
401 ImGui::TextColored(BoolColor(smoke.
d6.
ok), tr(
" Audit command %s"),
402 CheckStr(smoke.
d6.
ok));
405 if (ImGui::CollapsingHeader(tr(
"D3 Kalyxo Castle"),
406 ImGuiTreeNodeFlags_DefaultOpen)) {
407 ImGui::Text(tr(
" Readiness check:"));
410 DrawOptionalBool(
" Room 0x32 has collision:", smoke.
d3.
ok);
416 if (ImGui::CollapsingHeader(tr(
"Water Fill"),
417 ImGuiTreeNodeFlags_DefaultOpen)) {
419 tr(
" Region present %s"),
422 tr(
" Table valid %s"),
426 if (ImGui::CollapsingHeader(tr(
"Custom Collision"),
427 ImGuiTreeNodeFlags_DefaultOpen)) {
429 tr(
" Maps valid %s"),
431 ImGui::Text(tr(
" Required rooms check:"));
434 DrawOptionalBool(
" Required rooms have data:",
438 if (!preflight.
errors.empty()) {
439 const std::string errors_label = absl::StrFormat(
440 "Errors (%d)###preflight_errors", preflight.
error_count);
441 if (ImGui::CollapsingHeader(errors_label.c_str())) {
442 for (
const auto& err : preflight.
errors) {
443 ImGui::TextColored(kRed,
" [%s] %s", err.code.c_str(),
444 err.message.c_str());
445 if (err.room_id.has_value()) {
447 ImGui::TextColored(kGrey, tr(
" room %s"), err.room_id->c_str());
456 if (ImGui::CollapsingHeader(tr(
"Raw Output (diagnostics)"))) {
457 ImGui::InputTextMultiline(
458 "##raw",
const_cast<char*
>(result.
raw_output.c_str()),
459 result.
raw_output.size() + 1, ImVec2(-1.0f, 120.0f),
460 ImGuiInputTextFlags_ReadOnly);
bool contains(const std::string &) const
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
void DrawSmokeCards(const oracle_validation::SmokeResult &smoke)
std::optional< oracle_validation::OracleRunResult > last_result_
std::string GetWorkflowDescription() const override
Optional workflow description for menus/command palette.
std::string status_message_
void DrawRawOutput(const oracle_validation::OracleRunResult &result)
float GetPreferredWidth() const override
Get preferred width for this panel (optional)
std::string GetIcon() const override
Material Design icon for this panel.
std::string GetWorkflowGroup() const override
Optional workflow group for hack-centric actions.
std::string required_collision_rooms_
WindowLifecycle GetWindowLifecycle() const override
Get the lifecycle category for this window.
std::string GetId() const override
Unique identifier for this panel.
std::string GetWorkflowLabel() const override
Optional workflow label for menus/command palette.
void Draw(bool *p_open) override
Draw the panel content.
std::future< oracle_validation::OracleRunResult > pending_
std::string GetDisplayName() const override
Human-readable name shown in menus and title bars.
bool IsEnabled() const override
Check if this panel is currently enabled.
void LaunchRun(oracle_validation::RunMode mode)
std::string GetDisabledTooltip() const override
Get tooltip text when panel is disabled.
static std::string DefaultRomPath()
~OracleValidationPanel() override
std::string GetEditorCategory() const override
Editor category this panel belongs to.
void DrawPreflightCards(const oracle_validation::PreflightResult &preflight)
#define ICON_MD_VERIFIED_USER
Rom * rom()
Get the current ROM instance.
::yaze::project::YazeProject * current_project()
Get the current project instance.
workflow::ValidationCapability * hack_validation_backend()
ImVec4 BoolColor(bool flag)
void DrawZ3dkArtifactSummary()
void DrawOptionalBool(const char *label, const std::optional< bool > &flag)
void DrawCheckBadge(const std::string &state)
const char * CheckStr(bool flag)
bool LoadJsonSummaryFile(const std::string &path, Json *out)
std::string CurrentTimestamp()
Editors are the view controllers for the application.
WindowLifecycle
Defines lifecycle behavior for editor windows.
@ CrossEditor
User can pin to persist across editors.
#define REGISTER_PANEL(PanelClass)
Auto-registration macro for panels with default constructors.
std::string error_message
absl::StatusCode status_code
std::string required_collision_rooms
std::string required_rooms_check
bool water_fill_region_ok
bool custom_collision_maps_ok
std::vector< PreflightError > errors
std::optional< bool > required_rooms_ok
std::string readiness_check
std::string required_rooms_check
std::optional< bool > required_rooms_ok
bool meets_min_track_rooms