145 kTriforceGold = GetThemedColor(
"triforce_gold", kTriforceGoldFallback);
146 kHyruleGreen = GetThemedColor(
"hyrule_green", kHyruleGreenFallback);
148 GetThemedColor(
"master_sword_blue", kMasterSwordBlueFallback);
149 kGanonPurple = GetThemedColor(
"ganon_purple", kGanonPurpleFallback);
150 kHeartRed = GetThemedColor(
"heart_red", kHeartRedFallback);
151 kSpiritOrange = GetThemedColor(
"spirit_orange", kSpiritOrangeFallback);
156 ImVec2 mouse_pos = ImGui::GetMousePos();
158 bool action_taken =
false;
161 ImGuiViewport* viewport = ImGui::GetMainViewport();
162 ImVec2 viewport_size = viewport->WorkSize;
167 float dockspace_center_x = dockspace_x + dockspace_width / 2.0f;
168 float dockspace_center_y = viewport->WorkPos.y + viewport_size.y / 2.0f;
169 ImVec2 center(dockspace_center_x, dockspace_center_y);
172 float width = std::min(dockspace_width * 0.85f, 1400.0f);
173 float height = std::min(viewport_size.y * 0.85f, 900.0f);
175 ImGui::SetNextWindowPos(center, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
176 ImGui::SetNextWindowSize(ImVec2(width, height), ImGuiCond_Always);
182 ImGui::SetNextWindowCollapsed(
false);
188 ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoCollapse |
189 ImGuiWindowFlags_NoResize |
190 ImGuiWindowFlags_NoMove |
191 ImGuiWindowFlags_NoBringToFrontOnFocus |
192 ImGuiWindowFlags_NoTitleBar;
194 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20, 20));
196 if (ImGui::Begin(
"##WelcomeScreen", p_open, window_flags)) {
197 ImDrawList* bg_draw_list = ImGui::GetWindowDrawList();
198 ImVec2 window_pos = ImGui::GetWindowPos();
199 ImVec2 window_size = ImGui::GetWindowSize();
202 struct TriforceConfig {
206 float repel_distance;
209 TriforceConfig triforce_configs[] = {
210 {0.08f, 0.12f, 36.0f, 0.025f, 50.0f},
211 {0.92f, 0.15f, 34.0f, 0.022f, 50.0f},
212 {0.06f, 0.88f, 32.0f, 0.020f, 45.0f},
213 {0.94f, 0.85f, 34.0f, 0.023f, 50.0f},
214 {0.50f, 0.08f, 38.0f, 0.028f, 55.0f},
215 {0.50f, 0.92f, 32.0f, 0.020f, 45.0f},
221 float x = window_pos.x + window_size.x * triforce_configs[i].x_pct;
222 float y = window_pos.y + window_size.y * triforce_configs[i].y_pct;
232 float base_x = window_pos.x + window_size.x * triforce_configs[i].x_pct;
233 float base_y = window_pos.y + window_size.y * triforce_configs[i].y_pct;
237 float time_offset = i * 1.2f;
238 float float_speed_x =
240 float float_speed_y =
242 float float_amount_x = (20.0f + (i % 2) * 10.0f) *
244 float float_amount_y =
248 float float_x = std::sin(
animation_time_ * float_speed_x + time_offset) *
257 float dist = std::sqrt(dx * dx + dy * dy);
265 target_pos.x += float_x;
266 target_pos.y += float_y;
271 float dir_x = dx / dist;
272 float dir_y = dy / dist;
275 float normalized_dist = dist / repel_radius;
276 float repel_strength = (1.0f - normalized_dist * normalized_dist) *
277 triforce_configs[i].repel_distance;
279 target_pos.x += dir_x * repel_strength;
280 target_pos.y += dir_y * repel_strength;
292 float adjusted_alpha =
294 float adjusted_size =
297 adjusted_size, adjusted_alpha, 0.0f);
303 static float spawn_accumulator = 0.0f;
305 while (spawn_accumulator >= 1.0f &&
315 float angle = (rand() % 360) * (
M_PI / 180.0f);
316 float speed = 20.0f + (rand() % 40);
318 ImVec2(std::cos(angle) * speed, std::sin(angle) * speed);
328 spawn_accumulator -= 1.0f;
332 float dt = ImGui::GetIO().DeltaTime;
353 ImU32 particle_color =
354 ImGui::GetColorU32(ImVec4(1.0f, 0.843f, 0.0f, alpha));
355 bg_draw_list->AddCircleFilled(
particles_[i].position,
367 ImDrawList* draw_list = ImGui::GetWindowDrawList();
368 ImVec2 separator_start = ImGui::GetCursorScreenPos();
369 ImVec2 separator_end(separator_start.x + ImGui::GetContentRegionAvail().x,
370 separator_start.y + 1);
371 ImVec4 gold_faded = kTriforceGold;
373 ImVec4 blue_faded = kMasterSwordBlue;
375 draw_list->AddRectFilledMultiColor(
376 separator_start, separator_end, ImGui::GetColorU32(gold_faded),
377 ImGui::GetColorU32(blue_faded), ImGui::GetColorU32(blue_faded),
378 ImGui::GetColorU32(gold_faded));
380 ImGui::Dummy(ImVec2(0, 10));
382 ImGui::BeginChild(
"WelcomeContent", ImVec2(0, -60),
false);
385 ImGui::BeginChild(
"LeftPanel",
386 ImVec2(ImGui::GetContentRegionAvail().x * 0.3f, 0),
true,
387 ImGuiWindowFlags_NoScrollbar);
392 ImVec2 sep_start = ImGui::GetCursorScreenPos();
395 ImVec2(sep_start.x + ImGui::GetContentRegionAvail().x, sep_start.y),
397 ImVec4(kTriforceGold.x, kTriforceGold.y, kTriforceGold.z, 0.2f)),
400 ImGui::Dummy(ImVec2(0, 5));
407 ImGui::BeginChild(
"RightPanel", ImVec2(0, 0),
true);
412 sep_start = ImGui::GetCursorScreenPos();
415 ImVec2(sep_start.x + ImGui::GetContentRegionAvail().x, sep_start.y),
416 ImGui::GetColorU32(ImVec4(kMasterSwordBlue.x, kMasterSwordBlue.y,
417 kMasterSwordBlue.z, 0.2f)),
420 ImGui::Dummy(ImVec2(0, 5));
427 ImVec2 footer_start = ImGui::GetCursorScreenPos();
428 ImVec2 footer_end(footer_start.x + ImGui::GetContentRegionAvail().x,
430 ImVec4 red_faded = kHeartRed;
432 ImVec4 green_faded = kHyruleGreen;
433 green_faded.w = 0.3f;
434 draw_list->AddRectFilledMultiColor(
435 footer_start, footer_end, ImGui::GetColorU32(red_faded),
436 ImGui::GetColorU32(green_faded), ImGui::GetColorU32(green_faded),
437 ImGui::GetColorU32(red_faded));
439 ImGui::Dummy(ImVec2(0, 5));
444 ImGui::PopStyleVar();
514 ImDrawList* draw_list = ImGui::GetWindowDrawList();
516 ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[2]);
520 auto windowWidth = ImGui::GetWindowSize().x;
521 auto textWidth = ImGui::CalcTextSize(title).x;
522 float xPos = (windowWidth - textWidth) * 0.5f;
524 ImGui::SetCursorPosX(xPos);
525 ImVec2 text_pos = ImGui::GetCursorScreenPos();
528 float glow_size = 30.0f;
529 ImU32 glow_color = ImGui::GetColorU32(
530 ImVec4(kTriforceGold.x, kTriforceGold.y, kTriforceGold.z, 0.15f));
531 draw_list->AddCircleFilled(
532 ImVec2(text_pos.x + textWidth / 2, text_pos.y + 15), glow_size,
536 ImGui::TextColored(kTriforceGold,
"%s", title);
540 const char* subtitle =
"Yet Another Zelda3 Editor";
541 textWidth = ImGui::CalcTextSize(subtitle).x;
542 ImGui::SetCursorPosX((windowWidth - textWidth) * 0.5f);
544 ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f),
"%s", subtitle);
548 ImVec2 left_tri_pos(xPos - 80, text_pos.y + 20);
549 ImVec2 right_tri_pos(xPos + textWidth + 50, text_pos.y + 20);
550 DrawTriforceBackground(draw_list, left_tri_pos, 20, 0.12f, 0.0f);
551 DrawTriforceBackground(draw_list, right_tri_pos, 20, 0.12f, 0.0f);
664 ImVec2 card_size(200, 95);
665 ImVec2 cursor_pos = ImGui::GetCursorScreenPos();
670 ImVec2 center(cursor_pos.x + card_size.x / 2,
671 cursor_pos.y + card_size.y / 2);
672 cursor_pos.x = center.x - (card_size.x * scale) / 2;
673 cursor_pos.y = center.y - (card_size.y * scale) / 2;
674 card_size.x *= scale;
675 card_size.y *= scale;
679 ImDrawList* draw_list = ImGui::GetWindowDrawList();
682 ImU32 color_top = ImGui::GetColorU32(ImVec4(0.15f, 0.20f, 0.25f, 1.0f));
683 ImU32 color_bottom = ImGui::GetColorU32(ImVec4(0.10f, 0.15f, 0.20f, 1.0f));
684 draw_list->AddRectFilledMultiColor(
686 ImVec2(cursor_pos.x + card_size.x, cursor_pos.y + card_size.y), color_top,
687 color_top, color_bottom, color_bottom);
690 ImVec4 border_color_base = (index % 3 == 0) ? kHyruleGreen
691 : (index % 3 == 1) ? kMasterSwordBlue
693 ImU32 border_color = ImGui::GetColorU32(ImVec4(
694 border_color_base.x, border_color_base.y, border_color_base.z, 0.5f));
698 ImVec2(cursor_pos.x + card_size.x, cursor_pos.y + card_size.y),
699 border_color, 6.0f, 0, 2.0f);
702 ImGui::SetCursorScreenPos(cursor_pos);
703 ImGui::InvisibleButton(absl::StrFormat(
"ProjectPanel_%d", index).c_str(),
705 bool is_hovered = ImGui::IsItemHovered();
706 bool is_clicked = ImGui::IsItemClicked();
713 ImU32 hover_color = ImGui::GetColorU32(
714 ImVec4(kTriforceGold.x, kTriforceGold.y, kTriforceGold.z, 0.15f));
715 draw_list->AddRectFilled(
717 ImVec2(cursor_pos.x + card_size.x, cursor_pos.y + card_size.y),
722 ImVec2 content_pos(cursor_pos.x + 8, cursor_pos.y + 8);
725 ImVec2 icon_center(content_pos.x + 13, content_pos.y + 13);
726 ImU32 icon_bg = ImGui::GetColorU32(border_color_base);
727 draw_list->AddCircleFilled(icon_center, 15, icon_bg, 24);
731 ImGui::SetCursorScreenPos(
732 ImVec2(icon_center.x - icon_size.x / 2, icon_center.y - icon_size.y / 2));
733 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1, 1, 1, 1));
735 ImGui::PopStyleColor();
738 ImGui::SetCursorScreenPos(ImVec2(content_pos.x + 32, content_pos.y + 8));
739 ImGui::PushTextWrapPos(cursor_pos.x + card_size.x - 8);
740 ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]);
741 std::string short_name = project.
name;
742 if (short_name.length() > 22) {
743 short_name = short_name.substr(0, 19) +
"...";
745 ImGui::TextColored(kTriforceGold,
"%s", short_name.c_str());
747 ImGui::PopTextWrapPos();
750 ImGui::SetCursorScreenPos(ImVec2(content_pos.x + 4, content_pos.y + 35));
751 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.65f, 0.65f, 0.65f, 1.0f));
753 ImGui::PopStyleColor();
756 ImGui::SetCursorScreenPos(ImVec2(content_pos.x + 4, content_pos.y + 58));
757 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.4f, 0.4f, 0.4f, 1.0f));
758 std::string short_path = project.
filepath;
759 if (short_path.length() > 26) {
760 short_path =
"..." + short_path.substr(short_path.length() - 23);
763 ImGui::PopStyleColor();
767 ImGui::BeginTooltip();
768 ImGui::TextColored(kMasterSwordBlue,
ICON_MD_INFO " Project Details");
770 ImGui::Text(
"Name: %s", project.
name.c_str());
771 ImGui::Text(
"ROM: %s", project.
rom_title.c_str());
772 ImGui::Text(
"Path: %s", project.
filepath.c_str());
788 float content_width = ImGui::GetContentRegionAvail().x;
789 ImGui::TextColored(kGanonPurple,
ICON_MD_LAYERS " Project Templates");
790 ImGui::SameLine(content_width - 25);
795 if (ImGui::IsItemHovered()) {
803 ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.18f, 0.15f, 0.22f, 0.4f));
804 ImGui::BeginChild(
"VisualSettingsCompact", ImVec2(0, 115),
true,
805 ImGuiWindowFlags_NoScrollbar);
811 ImGui::SetNextItemWidth(-1);
816 ImGui::SetNextItemWidth(-1);
835 ImGui::PopStyleColor();
844 const char* description;
845 const char* template_id;
849 Template templates[] = {
851 "Standard editing without custom ASM",
"Vanilla ROM Hack", kHyruleGreen},
853 "Full overworld expansion features",
"ZSCustomOverworld v3 (Recommended)",
856 "Basic overworld expansion",
"ZSCustomOverworld v2", kShadowPurple},
858 "Minimal custom features for rando",
"Randomizer Compatible",
862 for (
int i = 0; i < 4; ++i) {
867 ImGui::PushStyleColor(
869 ImVec4(templates[i].color.x * 0.6f, templates[i].color.y * 0.6f,
870 templates[i].color.z * 0.6f, 0.6f));
873 if (ImGui::Selectable(
874 absl::StrFormat(
"%s %s", templates[i].icon, templates[i].name)
881 ImGui::PopStyleColor();
884 if (ImGui::IsItemHovered()) {
885 ImGui::SetTooltip(
"%s %s\n%s",
ICON_MD_INFO, templates[i].name,
886 templates[i].description);
893 ImGui::PushStyleColor(ImGuiCol_Button,
894 ImVec4(kSpiritOrange.x * 0.6f, kSpiritOrange.y * 0.6f,
895 kSpiritOrange.z * 0.6f, 0.8f));
896 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, kSpiritOrange);
897 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
898 ImVec4(kSpiritOrange.x * 1.2f, kSpiritOrange.y * 1.2f,
899 kSpiritOrange.z * 1.2f, 1.0f));
913 ImGui::PopStyleColor(3);
915 if (ImGui::IsItemHovered()) {
916 ImGui::SetTooltip(
"%s Create new project with '%s' template\nThis will "
917 "open a ROM and apply the template settings.",