Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Germen Pulchrum/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ target_link_libraries(Germen
Boost::locale
ImGui
ImGui-FreeType
ImGui-Markdown
ImGui-SDL3
ImGui-StdLib
ImGui-Vulkan
ImPlot
nlohmann_json::nlohmann_json
Expand Down
71 changes: 66 additions & 5 deletions Germen Pulchrum/Disegnatore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ ImFont *FontNormale = nullptr;
ImFont *FontGrassetto = nullptr;
ImFont *FontItalico = nullptr;
ImFont *FontItalicoGrassetto = nullptr;
ImFont *FontGrassettoH1 = nullptr;
ImFont *FontGrassettoH2 = nullptr;
ImFont *FontGrassettoH3 = nullptr;

static void CheckVkResultFn(VkResult err);
static bool CreaCatenaScambio();
Expand Down Expand Up @@ -251,7 +254,7 @@ int Disegnatore()
vkb::CustomQueueDescription(0, 1, &priorità) // presentazione
};

size_t numeroCode;
size_t numeroDescrizioniCode;

// Seleziono la prima famiglia di code di tipo grafico che trovo in modo da creare una sola coda di tale tipo.
{
Expand Down Expand Up @@ -298,11 +301,12 @@ int Disegnatore()

// Evito di duplicare le informazioni se la stessa famiglia di code supporta sia la grafica che la
// presentazione.
numeroCode = descrizioneCode[0].index == descrizioneCode[1].index ? 1 : 2;
numeroDescrizioniCode = descrizioneCode[0].index == descrizioneCode[1].index ? 1 : 2;
}

vkb::DeviceBuilder costruttore(dispositivoFisico);
const vkb::Result<vkb::Device> risultato = costruttore.custom_queue_setup(numeroCode, descrizioneCode).build();
const vkb::Result<vkb::Device> risultato =
costruttore.custom_queue_setup(numeroDescrizioniCode, descrizioneCode).build();
if (!risultato)
{
std::cout << "Creazione dispositivo di rendering fallita: " << risultato.error().message() << '\n';
Expand Down Expand Up @@ -449,7 +453,6 @@ int Disegnatore()
{
ImFontConfig configFont;

configFont.Name[0] = '\0';
snprintf(configFont.Name, std::size(configFont.Name), "%s %s", Fonts::IBMPlexSans::Name, "grassetto");
configFont.Flags = ImFontFlags_NoLoadError;
configFont.FontLoaderFlags = ImGuiFreeTypeLoaderFlags_Bold;
Expand Down Expand Up @@ -527,6 +530,63 @@ int Disegnatore()
return EXIT_FAILURE;
}
}

// ----- Grassetto H1

{
ImFontConfig configFont;

snprintf(configFont.Name, std::size(configFont.Name), "%s %s", Fonts::IBMPlexSans::Name, "grassetto H1");
configFont.Flags = ImFontFlags_NoLoadError;
configFont.FontLoaderFlags = ImGuiFreeTypeLoaderFlags_Bold;
configFont.SizePixels = 30.0f;

FontGrassettoH1 = io.Fonts->AddFontFromMemoryCompressedTTF(
Fonts::IBMPlexSans::CompressedData, std::size(Fonts::IBMPlexSans::CompressedData), 0.0f, &configFont);
if (FontGrassettoH1 == nullptr)
{
std::cout << "Impossible caricare il font per lo stile grassetto H1.\n";
return EXIT_FAILURE;
}
}

// ----- Grassetto H2

{
ImFontConfig configFont;

snprintf(configFont.Name, std::size(configFont.Name), "%s %s", Fonts::IBMPlexSans::Name, "grassetto H2");
configFont.Flags = ImFontFlags_NoLoadError;
configFont.FontLoaderFlags = ImGuiFreeTypeLoaderFlags_Bold;
configFont.SizePixels = 22.5f;

FontGrassettoH2 = io.Fonts->AddFontFromMemoryCompressedTTF(
Fonts::IBMPlexSans::CompressedData, std::size(Fonts::IBMPlexSans::CompressedData), 0.0f, &configFont);
if (FontGrassettoH2 == nullptr)
{
std::cout << "Impossible caricare il font per lo stile grassetto H2.\n";
return EXIT_FAILURE;
}
}

// ----- Grassetto H3

{
ImFontConfig configFont;

snprintf(configFont.Name, std::size(configFont.Name), "%s %s", Fonts::IBMPlexSans::Name, "grassetto H3");
configFont.Flags = ImFontFlags_NoLoadError;
configFont.FontLoaderFlags = ImGuiFreeTypeLoaderFlags_Bold;
configFont.SizePixels = 17.55f;

FontGrassettoH3 = io.Fonts->AddFontFromMemoryCompressedTTF(
Fonts::IBMPlexSans::CompressedData, std::size(Fonts::IBMPlexSans::CompressedData), 0.0f, &configFont);
if (FontGrassettoH3 == nullptr)
{
std::cout << "Impossible caricare il font per lo stile grassetto H3.\n";
return EXIT_FAILURE;
}
}
}

// ----- ImGui back-end SDL3 -----
Expand Down Expand Up @@ -1000,7 +1060,8 @@ int Disegnatore()
// configurazione ma poi non lo onorano (per esempio llvmpipe), per tanto utilizzo un clock per assicurarmi di
// non superare la frequenza massima di disegno.
if (AbilitàVSync) DurataFotogramma = clock.AspettaTicchettioSuccessivo() * 1000.0;
else {
else
{
high_resolution_clock::time_point tempoFine = high_resolution_clock::now();
DurataFotogramma = duration_cast<DurataMillisecondi>(tempoFine - tempoInizio).count();
tempoInizio = tempoFine;
Expand Down
3 changes: 3 additions & 0 deletions Germen Pulchrum/Disegnatore.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ extern ImFont *FontNormale;
extern ImFont *FontGrassetto;
extern ImFont *FontItalico;
extern ImFont *FontItalicoGrassetto;
extern ImFont *FontGrassettoH1;
extern ImFont *FontGrassettoH2;
extern ImFont *FontGrassettoH3;

// ----- Temi -----

Expand Down
2 changes: 1 addition & 1 deletion Germen Pulchrum/Estensioni ImGui/Barra di stato.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
bool ImGui::BeginMainStatusBar()
{
const ImGuiContext &g = *GImGui;
auto *viewport = reinterpret_cast<ImGuiViewportP *>(GetMainViewport());
auto *viewport = static_cast<ImGuiViewportP *>(GetMainViewport());

constexpr ImGuiWindowFlags window_flags =
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar;
Expand Down
193 changes: 193 additions & 0 deletions Germen Pulchrum/GUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,100 @@ static bool finestraEditorStileAperta = false;
static bool finestraMetricheImGuiAperta = false;
static bool finestraDebugLogAperta = false;
static bool finestraDemoPlotAperta = false;
static bool finestraMarkdownAperta = false;
static int ScalaGUIPercentuale = 100; // [%]

static ImGui::MarkdownConfig configurazioneMarkdown;

static std::string testoMarkdown = R"(# Aetate ego terras habebas

## Esse pars gravi consule

Lorem markdownum et neve meritis terrae festum, corpora quem Ampycides laudemque
velamina Halesi nitidissimus. Fatebor his tetigit enim, est placare; o Pallas
pro flammas. Spatio efferre, sonuere et nondum lugent plenos, verbis sit dictis
crevit amor [rogari horrida auctoris](https://duckduckgo.com/) crine adflata. Et magna crescit Tritoniaca
nec habere, non undas concutiens vaticinatus vixque.

## Eadem lunaribus ad spectatas

Atque ait quam possimne proceres; et mihi, est in voles. Scire temporis aliquid
et nostra per **aequorea** umbra quondam fassusque utque intremuit. Profusis
nostra gravis digitosque membra quicquid nostrae cum avem carpsit, est. Illa
iugulata: ante videri altera Cadmeida ter.

- Pereat Iovi signa invenit tepidique fessis veretur
- Tura seque ut venit aeternum possim
- Ereptas preces sole nostri superbia in sacro

## Fulgura tendentemque notavi saepe

Forma dolens tamen iuppiter veni circumspicit vidit; retinete satyri. Inquit
suspiria litus notissima nomen, lapidosos, arreptum eripe? Est tardi ad usae;
toto mors ira [vinaque cantare](https://www.example.com/), timidus nos dicta
amplexas quaeras molle. Iunctoque desierat vero, inquirant scilicet Idaeo magnas
feruntur augustae posse, Pelion? In pruinosas cunctantem, nostris **in qua**
Tigris venire.

1. Recursus fibris recessit geminum
1. Suspicit addere animum nec femineos sanguine luna
2. Aquoso aequales triceps ego
2. Iam vera
3. Ad detinet duo Erycina quod fores sic

## Imbribus orbis ex ictus

Harenis manes sua tempora? Bacchaeque sustinuere resoluta ardere nostrae frater,
Calydonius saltus simulacra. Tacetve carpitur moveres.

- Regi dentibus Liternum notum effecta
- Si aurea
- Sed ni qui parenti isdem meus carinas
- Vesana fremit domo meos pariter
- Suam pulcherrime mane studiosius Liber tumet
- Manu opus munus obtusum
- Hylonome Danaas deprensum medullis coniunx inventa

## Hector Alemonides

Fluctus ille, enodisque defrenato partes mirabile Nycteus vixque clamantem
tellus et. Perdidit membra comites serpentis Sabaea, illic hanc aevo negabo.
Ante bis pectore futuri *et quid utque* ait exsul **nubibus**. Et erat ultimus,
has habuere artis, movit tuos nisi relinqui *curis* dotatissima, mea annua.
Defendit postquam hastas, ore ut cruor umida nescio: ubi miratur!

- Ille comitem Phoebus ostia potentia gratare auxilium
- Finemque vincula est nomen herbas adest
- Hylonome Danaas deprensum medullis coniunx inventa
- Manu opus munus obtusum
- Dum ater
- Ede feci Achille)";

static bool LinguaSelezionabile(size_t i);

static void CallbackApriCollegamentoMarkdown(ImGui::MarkdownLinkCallbackData data);
static void CallbackSuggerimentoMarkdown(ImGui::MarkdownTooltipCallbackData data);
static void CallbackFormattazioneMarkdown(const ImGui::MarkdownFormatInfo &infoFormattazione, bool inizio);

// ----- -----

void InizializzaGUI()
{
ScalaGUIPercentuale = static_cast<int>(Impostazioni.scalaGUI * 100); // [%]

ImGui::GetPlatformIO().Platform_LocaleDecimalPoint = '.';

configurazioneMarkdown = { .linkCallback = CallbackApriCollegamentoMarkdown,
.tooltipCallback = CallbackSuggerimentoMarkdown, // opzionale
.imageCallback = nullptr,
.linkIcon = reinterpret_cast<const char *>(u8"🔗"),
.headingFormats = { { .font = FontGrassettoH1, .separator = true },
{ .font = FontGrassettoH2, .separator = true },
{ .font = FontGrassettoH3, .separator = false } },
.userData = nullptr,
.formatCallback = CallbackFormattazioneMarkdown,
.formatFlags = ImGuiMarkdownFormatFlags_DiscardExtraNewLines
| ImGuiMarkdownFormatFlags_SeparatorDoesNotAdvance };
}

void GUI()
Expand All @@ -45,6 +128,7 @@ void GUI()
ImGui::MenuItem(TestiGUI.editorStile.data(), nullptr, &finestraEditorStileAperta);
ImGui::MenuItem(TestiGUI.metricheImGui.data(), nullptr, &finestraMetricheImGuiAperta);
ImGui::MenuItem(TestiGUI.debugLog.data(), nullptr, &finestraDebugLogAperta);
ImGui::MenuItem("Markdown", nullptr, &finestraMarkdownAperta);

ImGui::EndMenu();
}
Expand All @@ -60,6 +144,7 @@ void GUI()
if (ImGui::SmallButton(TestiGUI.metricheImGui.data()))
finestraMetricheImGuiAperta = !finestraMetricheImGuiAperta;
if (ImGui::SmallButton(TestiGUI.debugLog.data())) finestraDebugLogAperta = !finestraDebugLogAperta;
if (ImGui::SmallButton("Markdown")) finestraMarkdownAperta = !finestraMarkdownAperta;

ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);

Expand Down Expand Up @@ -189,6 +274,32 @@ void GUI()
}

if (finestraDemoPlotAperta) ImPlot::ShowDemoWindow(&finestraDemoPlotAperta);

if (finestraMarkdownAperta)
{
if (ImGui::Begin("Markdown", &finestraMarkdownAperta))
{
constexpr bool OrientamentoVerticale = true;

ImVec2 dimensioneInputTesto = { -1, -1 };
if constexpr (OrientamentoVerticale) dimensioneInputTesto.x = ImGui::GetContentRegionAvail().x * 0.5f;
else dimensioneInputTesto.y = ImGui::GetContentRegionAvail().y * 0.4f;

ImGui::InputTextMultiline(
"###TestoMarkdown",
&testoMarkdown,
dimensioneInputTesto,
ImGuiInputTextFlags_AllowTabInput | ImGuiInputTextFlags_WordWrap);

if constexpr (OrientamentoVerticale) ImGui::SameLine();
else ImGui::Spacing();

ImGui::BeginChild("###Anteprima", ImVec2(0, 0), ImGuiChildFlags_Borders);
ImGui::Markdown(testoMarkdown.data(), testoMarkdown.size(), configurazioneMarkdown);
ImGui::EndChild();
}
ImGui::End();
}
}

void AggiornaScalaGUI()
Expand Down Expand Up @@ -217,3 +328,85 @@ static bool LinguaSelezionabile(const size_t i)

return false;
}

// ----- Markdown -----

static void CallbackApriCollegamentoMarkdown(ImGui::MarkdownLinkCallbackData data)
{
const std::string url(data.link, data.linkLength);
if (!SDL_OpenURL(url.data()))
std::cout << "[Errore] Impossibile aprire il URL '" << url << "': " << SDL_GetError() << '\n';
}

/// @brief Invocata da ImGui Markdown quando è necessario mostrare un suggerimento (tooltip).
/// Al momento è invocata quando il mouse si trova sopra un collegamento.
static void CallbackSuggerimentoMarkdown(ImGui::MarkdownTooltipCallbackData data)
{
if (data.linkData.isImage) ImGui::SetTooltip("%.*s", data.linkData.linkLength, data.linkData.link);
else ImGui::SetTooltip("%s %.*s", data.linkIcon, data.linkData.linkLength, data.linkData.link);
}

/// @brief Invocata da ImGui Markdown subito prima e subito dopo il rendering di un elemento così da poter
/// personalizzare l'aspetto di quest'ultimo.
/// @param infoFormattazione informazioni sull'elemento disegnato e sulla configurazione di ImGui Markdown.
/// @param inizio value True prima del disegno dell'elemento e False dopo.
static void CallbackFormattazioneMarkdown(const ImGui::MarkdownFormatInfo &infoFormattazione, const bool inizio)
{
switch (infoFormattazione.type)
{
case ImGui::MarkdownFormatType::NORMAL_TEXT:
break;
case ImGui::MarkdownFormatType::EMPHASIS:
// Italico (enfasi normale)
if (infoFormattazione.level == 1)
if (inizio) ImGui::PushFont(FontItalico, 0.0f);
else ImGui::PopFont();
// Grassetto (enfasi forte)
else if (inizio) ImGui::PushFont(FontGrassetto, 0.0f);
else ImGui::PopFont();

break;
case ImGui::MarkdownFormatType::HEADING:
{
const ImGui::MarkdownHeadingFormat &formatoIntestazione =
infoFormattazione.level > ImGui::MarkdownConfig::NUMHEADINGS
? infoFormattazione.config->headingFormats[ImGui::MarkdownConfig::NUMHEADINGS - 1]
: infoFormattazione.config->headingFormats[infoFormattazione.level - 1];

if (inizio)
{
if (!(infoFormattazione.config->formatFlags & ImGuiMarkdownFormatFlags_NoNewLineBeforeHeading))
ImGui::NewLine();
if (formatoIntestazione.font)
ImGui::PushFont(
formatoIntestazione.font,
formatoIntestazione.fontSize > 0.0f ? formatoIntestazione.fontSize
: formatoIntestazione.font->LegacySize);
}
else
{
if (formatoIntestazione.separator)
{
const ImVec2 cursor = ImGui::GetCursorPos();
ImGui::Separator();
if (infoFormattazione.config->formatFlags & ImGuiMarkdownFormatFlags_SeparatorDoesNotAdvance)
ImGui::SetCursorPos(cursor);
}
if (formatoIntestazione.font) ImGui::PopFont();
ImGui::NewLine();
}
break;
}
case ImGui::MarkdownFormatType::UNORDERED_LIST:
break;
case ImGui::MarkdownFormatType::LINK:
if (inizio) ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered]);
else
{
ImGui::PopStyleColor();
if (infoFormattazione.itemHovered) ImGui::UnderLine(ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered]);
else ImGui::UnderLine(ImGui::GetStyle().Colors[ImGuiCol_Button]);
}
break;
}
}
8 changes: 8 additions & 0 deletions Germen Pulchrum/IntestazionePrecompilata.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@
#include <imgui_impl_sdl3.h>
#include <imgui_impl_vulkan.h>

// ImGui StdLib

#include <imgui_stdlib.h>

// ImGui Markdown

#include <imgui_markdown.h>

// ImPlot

#define IMPLOT_DISABLE_OBSOLETE_FUNCTIONS
Expand Down
Loading