Cemu/src/gui/GraphicPacksWindow2.cpp
2022-10-12 08:03:26 +02:00

710 lines
21 KiB
C++

#include "gui/wxgui.h"
#include "gui/GraphicPacksWindow2.h"
#include "gui/DownloadGraphicPacksWindow.h"
#include "Cafe/GraphicPack/GraphicPack2.h"
#include "config/CemuConfig.h"
#include "config/ActiveSettings.h"
#include "Cafe/HW/Latte/Core/LatteAsyncCommands.h"
#include "Cafe/CafeSystem.h"
#include "Cafe/TitleList/TitleList.h"
#if BOOST_OS_LINUX || BOOST_OS_MACOS
#include "resource/embedded/resources.h"
#endif
// main.cpp
class wxGraphicPackData : public wxTreeItemData
{
public:
wxGraphicPackData(GraphicPackPtr pack)
: m_pack(std::move(pack)) { }
const GraphicPackPtr& GetGraphicPack() const { return m_pack; }
private:
GraphicPackPtr m_pack;
};
void GraphicPacksWindow2::FillGraphicPackList() const
{
wxWindowUpdateLocker lock(m_graphic_pack_tree);
m_graphic_pack_tree->DeleteAllItems();
auto graphic_packs = GraphicPack2::GetGraphicPacks();
const auto root = m_graphic_pack_tree->AddRoot("Root");
const bool has_filter = !m_filter.empty();
for(auto& p : graphic_packs)
{
// filter graphic packs by given title id
if (m_filter_installed_games && !m_installed_games.empty())
{
bool found = false;
for (uint64 titleId : p->GetTitleIds())
{
if (std::find(m_installed_games.cbegin(), m_installed_games.cend(), titleId) != m_installed_games.cend())
{
found = true;
break;
}
}
if (!found)
continue;
}
// filter graphic packs by given title id
if(has_filter)
{
bool found = false;
if (boost::icontains(p->GetPath(), m_filter))
found = true;
else
{
for (uint64 titleId : p->GetTitleIds())
{
if (boost::icontains(fmt::format("{:x}", titleId), m_filter))
{
found = true;
break;
}
}
}
if (!found)
continue;
}
const auto& path = p->GetPath();
auto tokens = TokenizeView(path, '/');
auto node = root;
for(size_t i=0; i<tokens.size(); i++)
{
auto& token = tokens[i];
const auto parent_node = node;
if (i < (tokens.size() - 1))
{
node = FindTreeItem(parent_node, wxString(token.data(), token.length()));
if (!node.IsOk())
{
node = m_graphic_pack_tree->AppendItem(parent_node, wxString(token.data(), token.length()));
}
}
else
{
// last token
// if a node with same name already exists, add a number suffix
for (sint32 s = 0; s < 999; s++)
{
wxString nodeName(token.data(), token.length());
if (s > 0)
nodeName.append(fmt::format(" #{}", s + 1));
node = FindTreeItem(parent_node, nodeName);
if (!node.IsOk())
{
node = m_graphic_pack_tree->AppendItem(parent_node, nodeName);
break;
}
}
}
}
if(node.IsOk() && node != root)
{
m_graphic_pack_tree->SetItemData(node, new wxGraphicPackData(p));
bool canEnable = true;
if (p->GetVersion() == 3)
{
auto tmp_text = m_graphic_pack_tree->GetItemText(node);
m_graphic_pack_tree->SetItemText(node, tmp_text + " (may not be compatible with Vulkan)");
}
else if (p->GetVersion() != 3 && p->GetVersion() != 4 && p->GetVersion() != 5 && p->GetVersion() != 6 && p->GetVersion() != GraphicPack2::GFXPACK_VERSION_7)
{
auto tmp_text = m_graphic_pack_tree->GetItemText(node);
m_graphic_pack_tree->SetItemText(node, tmp_text + " (Unsupported version)");
m_graphic_pack_tree->SetItemTextColour(node, 0x0000CC);
canEnable = false;
}
else if (p->IsActivated())
m_graphic_pack_tree->SetItemTextColour(node, 0x009900);
m_graphic_pack_tree->MakeCheckable(node, p->IsEnabled());
if (!canEnable)
m_graphic_pack_tree->DisableCheckBox(node);
}
}
m_graphic_pack_tree->Sort(root, true);
if (!m_filter.empty())
{
size_t counter = 0;
ExpandChildren({ root }, counter);
}
}
void GraphicPacksWindow2::GetChildren(const wxTreeItemId& id, std::vector<wxTreeItemId>& children) const
{
wxTreeItemIdValue cookie;
wxTreeItemId child = m_graphic_pack_tree->GetFirstChild(id, cookie);
while (child.IsOk())
{
children.emplace_back(child);
child = m_graphic_pack_tree->GetNextChild(child, cookie);
}
}
void GraphicPacksWindow2::ExpandChildren(const std::vector<wxTreeItemId>& ids, size_t& counter) const
{
std::vector<wxTreeItemId> children;
for (const auto& id : ids)
GetChildren(id, children);
counter += children.size();
if (counter >= 30 || children.empty())
return;
for (const auto& id : ids)
{
if(id != m_graphic_pack_tree->GetRootItem() && m_graphic_pack_tree->HasChildren(id))
m_graphic_pack_tree->Expand(id);
}
ExpandChildren(children, counter);
}
void GraphicPacksWindow2::RefreshGraphicPacks()
{
GraphicPack2::ClearGraphicPacks();
GraphicPack2::LoadAll();
}
GraphicPacksWindow2::GraphicPacksWindow2(wxWindow* parent, uint64_t title_id_filter)
: wxDialog(parent, wxID_ANY, _("Graphic packs"), wxDefaultPosition, wxSize(1000,670), wxCLOSE_BOX | wxCLIP_CHILDREN | wxCAPTION | wxRESIZE_BORDER),
m_installed_games(CafeTitleList::GetAllTitleIds())
{
if (title_id_filter != 0)
m_filter = fmt::format("{:x}", title_id_filter);
m_filter_installed_games = !m_installed_games.empty();
SetIcon(wxICON(X_BOX));
SetMinSize(wxSize(500, 400));
auto main_sizer = new wxBoxSizer(wxVERTICAL);
m_splitter_window = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3D);
m_splitter_window->Bind(wxEVT_SIZE, &GraphicPacksWindow2::OnSizeChanged, this);
m_splitter_window->Bind(wxEVT_SPLITTER_SASH_POS_CHANGED, &GraphicPacksWindow2::SashPositionChanged, this);
// left side
auto left_panel = new wxPanel(m_splitter_window);
{
auto sizer = new wxBoxSizer(wxVERTICAL);
wxFlexGridSizer* filter_row = new wxFlexGridSizer(0, 3, 0, 0);
filter_row->AddGrowableCol(1);
filter_row->SetFlexibleDirection(wxBOTH);
filter_row->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
const auto text = new wxStaticText(left_panel, wxID_ANY, _("Filter"), wxDefaultPosition, wxDefaultSize, 0);
text->Wrap(-1);
filter_row->Add(text, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
m_filter_text = new wxTextCtrl(left_panel, wxID_ANY, m_filter, wxDefaultPosition, wxDefaultSize, 0);
filter_row->Add(m_filter_text, 0, wxALL | wxEXPAND, 5);
m_filter_text->Bind(wxEVT_COMMAND_TEXT_UPDATED, &GraphicPacksWindow2::OnFilterUpdate, this);
m_installed_games_only = new wxCheckBox(left_panel, wxID_ANY, _("Installed games"), wxDefaultPosition, wxDefaultSize, 0);
m_installed_games_only->SetValue(m_filter_installed_games);
filter_row->Add(m_installed_games_only, 0, wxALL | wxEXPAND, 5);
m_installed_games_only->Bind(wxEVT_CHECKBOX, &GraphicPacksWindow2::OnInstalledGamesChanged, this);
if (m_installed_games.empty())
m_installed_games_only->Disable();
sizer->Add(filter_row, 0, wxEXPAND, 5);
m_graphic_pack_tree = new wxCheckTree(left_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_DEFAULT_STYLE | wxTR_HIDE_ROOT);
m_graphic_pack_tree->Bind(wxEVT_TREE_SEL_CHANGED, &GraphicPacksWindow2::OnTreeSelectionChanged, this);
m_graphic_pack_tree->Bind(wxEVT_CHECKTREE_CHOICE, &GraphicPacksWindow2::OnTreeChoiceChanged, this);
//m_graphic_pack_tree->SetMinSize(wxSize(600, 400));
sizer->Add(m_graphic_pack_tree, 1, wxEXPAND | wxALL, 5);
left_panel->SetSizerAndFit(sizer);
}
// right side
m_right_panel = new wxPanel(m_splitter_window, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxNO_BORDER | wxFULL_REPAINT_ON_RESIZE);
{
auto* sizer = new wxBoxSizer(wxVERTICAL);
{
m_gp_options = new wxScrolled<wxPanel>(m_right_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxNO_BORDER | wxVSCROLL);
m_gp_options->SetScrollRate(-1, 10);
auto* inner_sizer = new wxBoxSizer(wxVERTICAL);
{
auto* box = new wxStaticBox(m_gp_options, wxID_ANY, _("Graphic pack"));
auto* box_sizer = new wxStaticBoxSizer(box, wxVERTICAL);
m_graphic_pack_name = new wxStaticText(box, wxID_ANY, wxEmptyString);
box_sizer->Add(m_graphic_pack_name, 1, wxEXPAND | wxALL, 5);
inner_sizer->Add(box_sizer, 0, wxEXPAND | wxALL, 5);
}
{
auto* box = new wxStaticBox(m_gp_options, wxID_ANY, _("Description"));
auto* box_sizer = new wxStaticBoxSizer(box, wxVERTICAL);
m_graphic_pack_description = new wxStaticText(box, wxID_ANY, wxEmptyString);
box_sizer->Add(m_graphic_pack_description, 1, wxEXPAND | wxALL, 5);
inner_sizer->Add(box_sizer, 0, wxEXPAND | wxALL, 5);
}
m_preset_sizer = new wxBoxSizer(wxVERTICAL);
inner_sizer->Add(m_preset_sizer, 0, wxEXPAND, 0);
{
auto* box = new wxStaticBox(m_gp_options, wxID_ANY, _("Control"));
auto* box_sizer = new wxStaticBoxSizer(box, wxHORIZONTAL);
m_reload_shaders = new wxButton(box, wxID_ANY, _("Reload edited shaders"));
m_reload_shaders->Bind(wxEVT_BUTTON, &GraphicPacksWindow2::OnReloadShaders, this);
m_reload_shaders->Disable();
box_sizer->Add(m_reload_shaders, 0, wxEXPAND | wxALL, 5);
inner_sizer->Add(box_sizer, 0, wxEXPAND | wxALL, 5);
}
inner_sizer->Add(new wxStaticText(m_gp_options, wxID_ANY, wxEmptyString), 1, wxALL | wxEXPAND, 5);
m_gp_options->SetSizerAndFit(inner_sizer);
m_gp_options->Hide();
sizer->Add(m_gp_options, 1, wxEXPAND | wxRESERVE_SPACE_EVEN_IF_HIDDEN);
}
sizer->Add(new wxStaticLine(m_right_panel, wxID_ANY), 0, wxLEFT|wxRIGHT | wxEXPAND, 3);
auto* row = new wxBoxSizer(wxHORIZONTAL);
m_update_graphicPacks = new wxButton(m_right_panel, wxID_ANY, _("Download latest community graphic packs"));
m_update_graphicPacks->Bind(wxEVT_BUTTON, &GraphicPacksWindow2::OnCheckForUpdates, this);
row->Add(m_update_graphicPacks, 0, wxALL, 5);
sizer->Add(row, 0, wxALL | wxEXPAND, 5);
m_right_panel->SetSizerAndFit(sizer);
}
m_splitter_window->SetMinimumPaneSize(50);
m_splitter_window->SplitVertically(left_panel, m_right_panel, (sint32)(m_ratio * m_splitter_window->GetParent()->GetSize().GetWidth()));
main_sizer->Add(m_splitter_window, 1, wxEXPAND, 5);
m_info_bar = new wxInfoBar(this);
m_info_bar->SetShowHideEffects(wxSHOW_EFFECT_BLEND, wxSHOW_EFFECT_BLEND);
m_info_bar->SetEffectDuration(500);
main_sizer->Add(m_info_bar, 0, wxALL | wxEXPAND, 5);
SetSizer(main_sizer);
FillGraphicPackList();
}
void GraphicPacksWindow2::SaveStateToConfig()
{
auto& data = g_config.data();
data.graphic_pack_entries.clear();
for (const auto& gp : GraphicPack2::GetGraphicPacks())
{
auto filename = MakeRelativePath(ActiveSettings::GetUserDataPath(), gp->GetFilename()).lexically_normal();
if (gp->IsEnabled())
{
data.graphic_pack_entries.try_emplace(filename);
auto& it = data.graphic_pack_entries[filename];
// otherwise store all selected presets
for (const auto& preset : gp->GetActivePresets())
it.try_emplace(preset->category, preset->name);
}
else if(gp->IsDefaultEnabled())
{
// save that its disabled
data.graphic_pack_entries.try_emplace(filename);
auto& it = data.graphic_pack_entries[filename];
it.try_emplace("_disabled", "false");
}
}
g_config.Save();
}
GraphicPacksWindow2::~GraphicPacksWindow2()
{
m_graphic_pack_tree->Unbind(wxEVT_CHECKTREE_CHOICE, &GraphicPacksWindow2::OnTreeSelectionChanged, this);
m_graphic_pack_tree->Unbind(wxEVT_CHECKTREE_CHOICE, &GraphicPacksWindow2::OnTreeChoiceChanged, this);
// m_active_preset->Unbind(wxEVT_CHOICE, &GraphicPacksWindow2::OnActivePresetChanged, this);
m_reload_shaders->Unbind(wxEVT_BUTTON, &GraphicPacksWindow2::OnReloadShaders, this);
SaveStateToConfig();
}
wxTreeItemId GraphicPacksWindow2::FindTreeItem(const wxTreeItemId& root, const wxString& text) const
{
wxTreeItemIdValue cookie;
for(auto item = m_graphic_pack_tree->GetFirstChild(root, cookie); item.IsOk(); item = m_graphic_pack_tree->GetNextSibling(item))
{
if (m_graphic_pack_tree->GetItemText(item) == text)
return item;
}
return {};
}
void GraphicPacksWindow2::LoadPresetSelections(const GraphicPackPtr& gp)
{
std::vector<std::string> order;
auto presets = gp->GetCategorizedPresets(order);
for(const auto& category : order)
{
const auto& entry = presets[category];
// test if any preset is visible and update its status
if (std::none_of(entry.cbegin(), entry.cend(), [gp](const auto& p)
{
return p->visible;
}))
{
continue;
}
wxString label(category.empty() ? _("Active preset") : wxString(category));
auto* box = new wxStaticBox(m_preset_sizer->GetContainingWindow(), wxID_ANY, label);
auto* box_sizer = new wxStaticBoxSizer(box, wxVERTICAL);
auto* preset = new wxChoice(box, wxID_ANY);
preset->SetClientObject(new wxStringClientData(category));
preset->Bind(wxEVT_CHOICE, &GraphicPacksWindow2::OnActivePresetChanged, this);
std::optional<std::string> active_preset;
for (auto& pentry : entry)
{
if (!pentry->visible)
continue;
preset->AppendString(pentry->name);
if (pentry->active)
active_preset = pentry->name;
}
if (active_preset)
preset->SetStringSelection(active_preset.value());
else if (preset->GetCount() > 0)
preset->SetSelection(0);
box_sizer->Add(preset, 1, wxEXPAND | wxALL, 5);
m_preset_sizer->Add(box_sizer, 0, wxEXPAND | wxALL, 5);
}
}
void GraphicPacksWindow2::OnTreeSelectionChanged(wxTreeEvent& event)
{
wxWindowUpdateLocker lock(this);
bool item_deselected = m_graphic_pack_tree->GetSelection() == m_graphic_pack_tree->GetRootItem();
if (item_deselected)
return;
const auto selection = m_graphic_pack_tree->GetSelection();
if (selection.IsOk())
{
const auto data = dynamic_cast<wxGraphicPackData*>(m_graphic_pack_tree->GetItemData(selection));
if (data)
{
if(!m_gp_options->IsShown())
m_gp_options->Show();
const auto& gp = data->GetGraphicPack();
if (gp != m_shown_graphic_pack)
{
m_preset_sizer->Clear(true);
m_gp_name = gp->GetName();
m_graphic_pack_name->SetLabel(m_gp_name);
if (gp->GetDescription().empty())
m_gp_description = _("This graphic pack has no description");
else
m_gp_description = gp->GetDescription();
m_graphic_pack_description->SetLabel(m_gp_description);
LoadPresetSelections(gp);
m_reload_shaders->Enable(gp->HasShaders());
m_shown_graphic_pack = gp;
m_graphic_pack_name->Wrap(m_graphic_pack_name->GetParent()->GetClientSize().GetWidth() - 10);
m_graphic_pack_name->GetGrandParent()->Layout();
m_graphic_pack_description->Wrap(m_graphic_pack_description->GetParent()->GetClientSize().GetWidth() - 10);
m_graphic_pack_description->GetGrandParent()->Layout();
m_right_panel->FitInside();
m_right_panel->Layout();
}
return;
}
}
m_preset_sizer->Clear(true);
m_graphic_pack_name->SetLabel(wxEmptyString);
m_graphic_pack_description->SetLabel(wxEmptyString);
m_reload_shaders->Disable();
m_shown_graphic_pack.reset();
m_gp_options->Hide();
m_right_panel->FitInside();
m_right_panel->Layout();
}
void GraphicPacksWindow2::OnTreeChoiceChanged(wxTreeEvent& event)
{
auto item = event.GetItem();
if (!item.IsOk())
return;
const bool state = event.GetExtraLong() != 0;
const auto data = dynamic_cast<wxGraphicPackData*>(m_graphic_pack_tree->GetItemData(item));
if (!data)
return;
auto& graphic_pack = data->GetGraphicPack();
graphic_pack->SetEnabled(state);
bool has_texture_rules = false;
if (CafeSystem::IsTitleRunning() && graphic_pack->ContainsTitleId(CafeSystem::GetForegroundTitleId()))
{
if (state)
{
GraphicPack2::ActivateGraphicPack(graphic_pack);
has_texture_rules = !graphic_pack->GetTextureRules().empty();
if (!has_texture_rules)
{
ReloadPack(graphic_pack);
m_graphic_pack_tree->SetItemTextColour(item, 0x009900);
}
}
else
{
has_texture_rules = !graphic_pack->GetTextureRules().empty();
if (!has_texture_rules)
{
DeleteShadersFromRuntimeCache(graphic_pack);
m_graphic_pack_tree->SetItemTextColour(item, *wxBLACK);
}
GraphicPack2::DeactivateGraphicPack(graphic_pack);
}
}
if (!m_info_bar->IsShown() && has_texture_rules)
m_info_bar->ShowMessage(_("Restart of Cemu required for changes to take effect"));
// also change selection to activated gp
m_graphic_pack_tree->SelectItem(item);
}
// In some environments with GTK (e.g. a flatpak app with org.freedesktop.Platform 22.08 runtime),
// destroying the event source inside the handler crashes the app.
// As a workaround to that, the wxWindow that needs to be destroyed is hidden and then
// destroyed at a later time, outside the handler.
void GraphicPacksWindow2::ClearPresets()
{
size_t item_count = m_preset_sizer->GetItemCount();
std::vector<wxSizer*> sizers;
sizers.reserve(item_count);
for (size_t i = 0; i < item_count; i++)
sizers.push_back(m_preset_sizer->GetItem(i)->GetSizer());
for (auto&& sizer : sizers)
{
auto static_box_sizer = dynamic_cast<wxStaticBoxSizer*>(sizer);
if (static_box_sizer)
{
wxStaticBox* parent_window = static_box_sizer->GetStaticBox();
if (parent_window)
{
m_preset_sizer->Detach(sizer);
parent_window->Hide();
CallAfter([=]()
{
parent_window->DestroyChildren();
delete static_box_sizer;
});
}
}
}
}
void GraphicPacksWindow2::OnActivePresetChanged(wxCommandEvent& event)
{
if (!m_shown_graphic_pack)
return;
const auto obj = wxDynamicCast(event.GetEventObject(), wxChoice);
wxASSERT(obj);
const auto string_data = dynamic_cast<wxStringClientData*>(obj->GetClientObject());
wxASSERT(string_data);
const auto preset = obj->GetStringSelection().ToStdString();
if(m_shown_graphic_pack->SetActivePreset(string_data->GetData().c_str().AsChar(), preset))
{
wxWindowUpdateLocker lock(this);
ClearPresets();
LoadPresetSelections(m_shown_graphic_pack);
//m_preset_sizer->GetContainingWindow()->Layout();
//m_right_panel->FitInside();
m_right_panel->FitInside();
m_right_panel->Layout();
}
if (m_shown_graphic_pack->GetTextureRules().empty())
ReloadPack(m_shown_graphic_pack);
else if (!m_info_bar->IsShown())
m_info_bar->ShowMessage(_("Restart of Cemu required for changes to take effect"));
}
void GraphicPacksWindow2::OnReloadShaders(wxCommandEvent& event)
{
if (m_shown_graphic_pack)
ReloadPack(m_shown_graphic_pack);
}
void GraphicPacksWindow2::OnCheckForUpdates(wxCommandEvent& event)
{
DownloadGraphicPacksWindow frame(this);
SaveStateToConfig();
const int updateResult = frame.ShowModal();
if (updateResult == wxID_OK)
{
if (!CafeSystem::IsTitleRunning())
{
std::vector<GraphicPackPtr> old_packs = GraphicPack2::GetGraphicPacks();
RefreshGraphicPacks();
FillGraphicPackList();
// check if enabled graphic packs are lost:
const auto& new_packs = GraphicPack2::GetGraphicPacks();
std::stringstream str;
for(const auto& p : old_packs)
{
if (!p->IsEnabled())
continue;
const auto it = std::find_if(new_packs.cbegin(), new_packs.cend(), [&p](const auto& gp)
{
return gp->GetFilename() == p->GetFilename();
});
if(it == new_packs.cend())
{
str << p->GetPath() << std::endl;
}
}
const auto packs = str.str();
if(!packs.empty())
{
wxMessageBox(fmt::format("{}\n \n{} \n{}", _("This update removed or renamed the following graphic packs:").ToStdString(), packs, _("You may need to set them up again.").ToStdString()),
_("Warning"), wxOK | wxCENTRE | wxICON_INFORMATION, this);
}
}
}
}
void GraphicPacksWindow2::OnSizeChanged(wxSizeEvent& event)
{
const auto obj = (wxSplitterWindow*)event.GetEventObject();
wxASSERT(obj);
const auto width = std::max(obj->GetMinimumPaneSize(), obj->GetParent()->GetClientSize().GetWidth());
obj->SetSashPosition((sint32)(m_ratio * width));
if (!m_gp_name.empty())
m_graphic_pack_name->SetLabel(m_gp_name);
if (!m_gp_description.empty())
m_graphic_pack_description->SetLabel(m_gp_description);
m_graphic_pack_name->Wrap(m_graphic_pack_name->GetParent()->GetClientSize().GetWidth() - 10);
m_graphic_pack_description->Wrap(m_graphic_pack_description->GetParent()->GetClientSize().GetWidth() - 10);
event.Skip();
}
void GraphicPacksWindow2::SashPositionChanged(wxEvent& event)
{
const auto obj = (wxSplitterWindow*)event.GetEventObject();
wxASSERT(obj);
const auto width = std::max(obj->GetMinimumPaneSize(), obj->GetParent()->GetClientSize().GetWidth());
m_ratio = (float)obj->GetSashPosition() / width;
event.Skip();
}
void GraphicPacksWindow2::OnFilterUpdate(wxEvent& event)
{
m_filter = m_filter_text->GetValue();
FillGraphicPackList();
event.Skip();
}
void GraphicPacksWindow2::OnInstalledGamesChanged(wxCommandEvent& event)
{
m_filter_installed_games = m_installed_games_only->GetValue();
FillGraphicPackList();
event.Skip();
}
void GraphicPacksWindow2::ReloadPack(const GraphicPackPtr& graphic_pack) const
{
if (graphic_pack->HasShaders() || graphic_pack->HasPatches() || graphic_pack->HasCustomVSyncFrequency())
{
if (graphic_pack->Reload())
{
DeleteShadersFromRuntimeCache(graphic_pack);
}
}
}
void GraphicPacksWindow2::DeleteShadersFromRuntimeCache(const GraphicPackPtr& graphic_pack) const
{
for (const auto& shader : graphic_pack->GetCustomShaders())
{
LatteConst::ShaderType shaderType;
if (shader.type == GraphicPack2::GP_SHADER_TYPE::VERTEX)
shaderType = LatteConst::ShaderType::Vertex;
else if (shader.type == GraphicPack2::GP_SHADER_TYPE::GEOMETRY)
shaderType = LatteConst::ShaderType::Geometry;
else if (shader.type == GraphicPack2::GP_SHADER_TYPE::PIXEL)
shaderType = LatteConst::ShaderType::Pixel;
LatteAsyncCommands_queueDeleteShader(shader.shader_base_hash, shader.shader_aux_hash, shaderType);
}
}