5754: Auto refresh skins when changing related settings r=def- a=Jupeyy

motivation: downloaded skins aren't resettet, e.g. if they failed before. config change -> resets everything

## Checklist

- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


5757: Make file link absolute, add `fs_is_relative_path` r=def- a=Robyt3

This fixes links not opening for relative paths, as links like `file://temp/skins` cannot be resolved by the shell.

Closes #5746.

## Checklist

- [X] Tested the change ingame (only on Windows)
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Jupeyy <jupjopjap@gmail.com>
Co-authored-by: Robert Müller <robytemueller@gmail.com>
This commit is contained in:
bors[bot] 2022-08-20 20:34:45 +00:00 committed by GitHub
commit 4fc6a5b924
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 56 additions and 18 deletions

View file

@ -721,7 +721,7 @@ endif()
if(TARGET_OS STREQUAL "windows") if(TARGET_OS STREQUAL "windows")
set(PLATFORM_CLIENT) set(PLATFORM_CLIENT)
set(PLATFORM_CLIENT_LIBS opengl32 winmm) set(PLATFORM_CLIENT_LIBS opengl32 winmm)
set(PLATFORM_LIBS version ws2_32) # Windows sockets set(PLATFORM_LIBS shlwapi version ws2_32) # Windows sockets
elseif(TARGET_OS STREQUAL "mac") elseif(TARGET_OS STREQUAL "mac")
find_library(CARBON Carbon) find_library(CARBON Carbon)
find_library(COCOA Cocoa) find_library(COCOA Cocoa)

View file

@ -68,6 +68,7 @@
#include <process.h> #include <process.h>
#include <share.h> #include <share.h>
#include <shellapi.h> #include <shellapi.h>
#include <shlwapi.h>
#include <wincrypt.h> #include <wincrypt.h>
#else #else
#error NOT IMPLEMENTED #error NOT IMPLEMENTED
@ -2309,6 +2310,17 @@ int fs_is_dir(const char *path)
#endif #endif
} }
int fs_is_relative_path(const char *path)
{
#if defined(CONF_FAMILY_WINDOWS)
WCHAR wPath[IO_MAX_PATH_LENGTH];
MultiByteToWideChar(CP_UTF8, 0, path, -1, wPath, std::size(wPath));
return PathIsRelativeW(wPath) ? 1 : 0;
#else
return path[0] == '/' ? 0 : 1; // yes, it's that simple
#endif
}
int fs_chdir(const char *path) int fs_chdir(const char *path)
{ {
if(fs_is_dir(path)) if(fs_is_dir(path))
@ -3866,8 +3878,18 @@ int open_file(const char *path)
#if defined(CONF_PLATFORM_MACOS) #if defined(CONF_PLATFORM_MACOS)
return open_link(path); return open_link(path);
#else #else
// Create a file link so the path can contain forward and
// backward slashes. But the file link must be absolute.
char buf[512]; char buf[512];
str_format(buf, sizeof(buf), "file://%s", path); char workingDir[IO_MAX_PATH_LENGTH];
if(fs_is_relative_path(path))
{
fs_getcwd(workingDir, sizeof(workingDir));
str_append(workingDir, "/", sizeof(workingDir));
}
else
workingDir[0] = '\0';
str_format(buf, sizeof(buf), "file://%s%s", workingDir, path);
return open_link(buf); return open_link(buf);
#endif #endif
} }

View file

@ -1821,6 +1821,15 @@ int fs_storage_path(const char *appname, char *path, int max);
*/ */
int fs_is_dir(const char *path); int fs_is_dir(const char *path);
/*
Function: fs_is_relative_path
Checks whether a given path is relative or absolute.
Returns:
Returns 1 if relative, 0 if absolute.
*/
int fs_is_relative_path(const char *path);
/* /*
Function: fs_chdir Function: fs_chdir
Changes current working directory Changes current working directory

View file

@ -103,6 +103,8 @@ class CMenus : public CComponent
void RenderColorPicker(); void RenderColorPicker();
void RefreshSkins();
// new gui with gui elements // new gui with gui elements
template<typename T> template<typename T>
int DoButtonMenu(CUIElement &UIElement, const void *pID, T &&GetTextLambda, int Checked, const CUIRect *pRect, bool HintRequiresStringCheck, bool HintCanChangePositionOrSize = false, int Corners = IGraphics::CORNER_ALL, float r = 5.0f, float FontFactor = 0.0f, vec4 ColorHot = vec4(1.0f, 1.0f, 1.0f, 0.75f), vec4 Color = vec4(1, 1, 1, 0.5f), int AlignVertically = 1) int DoButtonMenu(CUIElement &UIElement, const void *pID, T &&GetTextLambda, int Checked, const CUIRect *pRect, bool HintRequiresStringCheck, bool HintCanChangePositionOrSize = false, int Corners = IGraphics::CORNER_ALL, float r = 5.0f, float FontFactor = 0.0f, vec4 ColorHot = vec4(1.0f, 1.0f, 1.0f, 0.75f), vec4 Color = vec4(1, 1, 1, 0.5f), int AlignVertically = 1)

View file

@ -409,6 +409,18 @@ struct CUISkin
bool operator==(const char *pOther) const { return !str_comp_nocase(m_pSkin->m_aName, pOther); } bool operator==(const char *pOther) const { return !str_comp_nocase(m_pSkin->m_aName, pOther); }
}; };
void CMenus::RefreshSkins()
{
auto SkinStartLoadTime = time_get_nanoseconds();
m_pClient->m_Skins.Refresh([&](int) {
// if skin refreshing takes to long, swap to a loading screen
if(time_get_nanoseconds() - SkinStartLoadTime > 500ms)
{
RenderLoading(Localize("Loading skin files"), "", 0, false);
}
});
}
void CMenus::RenderSettingsTee(CUIRect MainView) void CMenus::RenderSettingsTee(CUIRect MainView)
{ {
CUIRect Button, Label, Dummy, DummyLabel, SkinList, QuickSearch, QuickSearchClearButton, SkinDB, SkinPrefix, SkinPrefixLabel, DirectoryButton, RefreshButton, Eyes, EyesLabel, EyesTee, EyesRight; CUIRect Button, Label, Dummy, DummyLabel, SkinList, QuickSearch, QuickSearchClearButton, SkinDB, SkinPrefix, SkinPrefixLabel, DirectoryButton, RefreshButton, Eyes, EyesLabel, EyesTee, EyesRight;
@ -470,6 +482,8 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
if(DoButton_CheckBox(&g_Config.m_ClDownloadSkins, Localize("Download skins"), g_Config.m_ClDownloadSkins, &DummyLabel)) if(DoButton_CheckBox(&g_Config.m_ClDownloadSkins, Localize("Download skins"), g_Config.m_ClDownloadSkins, &DummyLabel))
{ {
g_Config.m_ClDownloadSkins ^= 1; g_Config.m_ClDownloadSkins ^= 1;
RefreshSkins();
s_InitSkinlist = true;
} }
Dummy.HSplitTop(20.0f, &DummyLabel, &Dummy); Dummy.HSplitTop(20.0f, &DummyLabel, &Dummy);
@ -477,6 +491,8 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
if(DoButton_CheckBox(&g_Config.m_ClDownloadCommunitySkins, Localize("Download community skins"), g_Config.m_ClDownloadCommunitySkins, &DummyLabel)) if(DoButton_CheckBox(&g_Config.m_ClDownloadCommunitySkins, Localize("Download community skins"), g_Config.m_ClDownloadCommunitySkins, &DummyLabel))
{ {
g_Config.m_ClDownloadCommunitySkins ^= 1; g_Config.m_ClDownloadCommunitySkins ^= 1;
RefreshSkins();
s_InitSkinlist = true;
} }
Dummy.HSplitTop(20.0f, &DummyLabel, &Dummy); Dummy.HSplitTop(20.0f, &DummyLabel, &Dummy);
@ -484,6 +500,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
if(DoButton_CheckBox(&g_Config.m_ClVanillaSkinsOnly, Localize("Vanilla skins only"), g_Config.m_ClVanillaSkinsOnly, &DummyLabel)) if(DoButton_CheckBox(&g_Config.m_ClVanillaSkinsOnly, Localize("Vanilla skins only"), g_Config.m_ClVanillaSkinsOnly, &DummyLabel))
{ {
g_Config.m_ClVanillaSkinsOnly ^= 1; g_Config.m_ClVanillaSkinsOnly ^= 1;
RefreshSkins();
s_InitSkinlist = true; s_InitSkinlist = true;
} }
@ -651,10 +668,6 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
if((pSkinToBeSelected->m_aName[0] == 'x' && pSkinToBeSelected->m_aName[1] == '_')) if((pSkinToBeSelected->m_aName[0] == 'x' && pSkinToBeSelected->m_aName[1] == '_'))
continue; continue;
// vanilla skins only
if(g_Config.m_ClVanillaSkinsOnly && !pSkinToBeSelected->m_IsVanilla)
continue;
if(pSkinToBeSelected == 0) if(pSkinToBeSelected == 0)
continue; continue;
@ -779,14 +792,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
// reset render flags for possible loading screen // reset render flags for possible loading screen
TextRender()->SetRenderFlags(0); TextRender()->SetRenderFlags(0);
TextRender()->SetCurFont(NULL); TextRender()->SetCurFont(NULL);
auto SkinStartLoadTime = time_get_nanoseconds(); RefreshSkins();
m_pClient->m_Skins.Refresh([&](int) {
// if skin refreshing takes to long, swap to a loading screen
if(time_get_nanoseconds() - SkinStartLoadTime > 500ms)
{
RenderLoading(Localize("Loading skin files"), "", 0, false);
}
});
s_InitSkinlist = true; s_InitSkinlist = true;
if(Client()->State() >= IClient::STATE_ONLINE) if(Client()->State() >= IClient::STATE_ONLINE)
{ {

View file

@ -65,6 +65,9 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser)
str_copy(aNameWithoutPng, pName); str_copy(aNameWithoutPng, pName);
aNameWithoutPng[str_length(aNameWithoutPng) - 4] = 0; aNameWithoutPng[str_length(aNameWithoutPng) - 4] = 0;
if(g_Config.m_ClVanillaSkinsOnly && !IsVanillaSkin(aNameWithoutPng))
return 0;
// Don't add duplicate skins (one from user's config directory, other from // Don't add duplicate skins (one from user's config directory, other from
// client itself) // client itself)
for(int i = 0; i < pSelf->Num(); i++) for(int i = 0; i < pSelf->Num(); i++)
@ -154,7 +157,6 @@ int CSkins::LoadSkin(const char *pName, CImageInfo &Info)
} }
CSkin Skin; CSkin Skin;
Skin.m_IsVanilla = IsVanillaSkin(pName);
Skin.m_OriginalSkin.m_Body = Graphics()->LoadSpriteTexture(Info, &g_pData->m_aSprites[SPRITE_TEE_BODY]); Skin.m_OriginalSkin.m_Body = Graphics()->LoadSpriteTexture(Info, &g_pData->m_aSprites[SPRITE_TEE_BODY]);
Skin.m_OriginalSkin.m_BodyOutline = Graphics()->LoadSpriteTexture(Info, &g_pData->m_aSprites[SPRITE_TEE_BODY_OUTLINE]); Skin.m_OriginalSkin.m_BodyOutline = Graphics()->LoadSpriteTexture(Info, &g_pData->m_aSprites[SPRITE_TEE_BODY_OUTLINE]);
Skin.m_OriginalSkin.m_Feet = Graphics()->LoadSpriteTexture(Info, &g_pData->m_aSprites[SPRITE_TEE_FOOT]); Skin.m_OriginalSkin.m_Feet = Graphics()->LoadSpriteTexture(Info, &g_pData->m_aSprites[SPRITE_TEE_FOOT]);
@ -355,7 +357,6 @@ void CSkins::Refresh(TSkinLoadedCBFunc &&SkinLoadedFunc)
{ {
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gameclient", "failed to load skins. folder='skins/'"); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gameclient", "failed to load skins. folder='skins/'");
CSkin DummySkin; CSkin DummySkin;
DummySkin.m_IsVanilla = true;
str_copy(DummySkin.m_aName, "dummy"); str_copy(DummySkin.m_aName, "dummy");
DummySkin.m_BloodColor = ColorRGBA(1.0f, 1.0f, 1.0f); DummySkin.m_BloodColor = ColorRGBA(1.0f, 1.0f, 1.0f);
m_vSkins.push_back(DummySkin); m_vSkins.push_back(DummySkin);

View file

@ -8,8 +8,6 @@
// do this better and nicer // do this better and nicer
struct CSkin struct CSkin
{ {
bool m_IsVanilla;
struct SSkinTextures struct SSkinTextures
{ {
IGraphics::CTextureHandle m_Body; IGraphics::CTextureHandle m_Body;