Compare commits

..

15 commits

Author SHA1 Message Date
Chiller Dragon 40081b1806
Merge a4ed85e8c8 into 8d431f8feb 2024-09-12 19:20:18 +02:00
Dennis Felsing 8d431f8feb
Merge pull request #8934 from sjrc6/pr_freeze_stars
Add client setting to restore old freeze stars
2024-09-12 12:31:54 +00:00
Tater 80e2de13da Add client side freeze stars 2024-09-12 04:48:46 -05:00
Dennis Felsing 66fb5d5d7f
Merge pull request #8933 from Robyt3/UI-EditText-Searchable
Extract `CUi::DoEditBox_Search` function for quick search
2024-09-11 21:55:25 +00:00
Robert Müller d3f0c2a156 Extract CUi::DoEditBox_Search function for quick search
Reduce duplicate and inconsistent code for rendering quick search for the demo browser, ingame vote list, player flag, skin, skin 0.7 and asset search.

The quick search and exclude in the server browser are not refactored, as they have additional labels and different alignment, which would make a general function complicated.
2024-09-11 21:33:08 +02:00
Jupeyy d5e81ca78d
Merge pull request #8932 from Robyt3/Client-Network-Before-Graphics
Initialize client networking before graphics
2024-09-11 18:07:20 +00:00
Robert Müller 128ffd2313 Initialize client networking before graphics
Avoid Vulkan crash if the backend is destroyed immediately after being created.

Slightly decreases time of initial black screen before loading menu is rendered.
2024-09-11 19:34:31 +02:00
Dennis Felsing af1b32d296
Merge pull request #8930 from timakro/pr-fix-econ-listening-publicly
Fixes a bug where econ was exposed publicly when ec_bindaddr was set to localhost
2024-09-11 16:50:42 +00:00
Tim Schumacher 0ad1c08c22 Fixes a bug where econ was exposed publicly when ec_bindaddr was set to localhost
Also implements the original intention of 85f5e9c that is to disable
econ if ec_binaddr is invalid.
2024-09-11 18:28:07 +02:00
Dennis Felsing 9f278979e5
Merge pull request #8926 from Robyt3/Editor-RGB-Mapres-Fix
Fix editor crash when saving maps with RGB mapres
2024-09-10 22:01:35 +00:00
Robert Müller 32e9240634 Fix editor crash when saving maps with RGB mapres
Convert mapres to RGBA immediately when loading them, so the image data is always in RGBA format internally, instead of only converting when the map is saved (which was erroneously removed in #8670).

This means the `cl_editor_dilate` setting will now also be applied to converted RGB images.
2024-09-10 21:22:56 +02:00
Dennis Felsing b5d662622c
Merge pull request #8918 from Robyt3/Cleanup-Color-mem_comp
Use operator `!=` instead of `mem_comp` for colors
2024-09-09 16:14:43 +00:00
Robert Müller 58ce5985d4 Use operator != instead of mem_comp for colors 2024-09-09 17:17:17 +02:00
Dennis Felsing 46acbdd6bf
Merge pull request #8916 from Robyt3/Android-API-Version-Building-Fix
Fix minimum Android API version and linking errors
2024-09-08 16:41:58 +00:00
Robert Müller d536bceed6 Fix minimum Android API version and linking errors
The minimum supported API version must be specified when building the native libraries, otherwise this may cause linking errors when launching the app.

The minimum API level is increased to 24 (Android 7.0, covering 97.2% of usages) because:

- Vulkan is only available from API 24+ on ARM64 and x64.
- curl only compiles with API 23+.
- The NDK version we use supports only API 21+.

Ensure that the C++/Linker flags are set when building Android libraries, which was causing errors due to `-fPIC` not being set for all libraries.
2024-09-08 17:59:41 +02:00
20 changed files with 177 additions and 162 deletions

View file

@ -10,7 +10,8 @@ ANDROID_NDK_VERSION="${ANDROID_NDK_VERSION:2}"
# ANDROID_NDK_HOME must be exported for cargo-ndk # ANDROID_NDK_HOME must be exported for cargo-ndk
export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/$ANDROID_NDK_VERSION" export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/$ANDROID_NDK_VERSION"
ANDROID_API_LEVEL=34 # ANDROID_API_LEVEL must specify the _minimum_ supported SDK version, otherwise this will cause linking errors at launch
ANDROID_API_LEVEL=24
ANDROID_SUB_BUILD_DIR=build_arch ANDROID_SUB_BUILD_DIR=build_arch
COLOR_RED="\e[1;31m" COLOR_RED="\e[1;31m"

View file

@ -21,7 +21,7 @@ android {
defaultConfig { defaultConfig {
applicationId "org.ddnet.client" applicationId "org.ddnet.client"
namespace("org.ddnet.client") namespace("org.ddnet.client")
minSdkVersion 19 minSdkVersion 24
targetSdkVersion 34 targetSdkVersion 34
versionCode TW_VERSION_CODE versionCode TW_VERSION_CODE
versionName "TW_VERSION_NAME" versionName "TW_VERSION_NAME"

View file

@ -29,6 +29,8 @@ function compile_source_android() {
-DCMAKE_SYSTEM_NAME=Android \ -DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION="$1" \ -DCMAKE_SYSTEM_VERSION="$1" \
-DCMAKE_ANDROID_ARCH_ABI="${3}" \ -DCMAKE_ANDROID_ARCH_ABI="${3}" \
-DCMAKE_C_FLAGS="$COMPILEFLAGS" -DCMAKE_CXX_FLAGS="$COMPILEFLAGS" -DCMAKE_CXX_FLAGS_RELEASE="$COMPILEFLAGS" -DCMAKE_C_FLAGS_RELEASE="$COMPILEFLAGS" \
-DCMAKE_SHARED_LINKER_FLAGS="$LINKFLAGS" -DCMAKE_SHARED_LINKER_FLAGS_RELEASE="$LINKFLAGS" \
-B"$2" \ -B"$2" \
-DBUILD_SHARED_LIBS=OFF \ -DBUILD_SHARED_LIBS=OFF \
-DHIDAPI_SKIP_LIBUSB=TRUE \ -DHIDAPI_SKIP_LIBUSB=TRUE \

View file

@ -46,7 +46,8 @@ fi
mkdir -p "$1" mkdir -p "$1"
cd "$1" || exit 1 cd "$1" || exit 1
_ANDROID_ABI_LEVEL=34 # ANDROID_API_LEVEL must specify the _minimum_ supported SDK version, otherwise this will cause linking errors at launch
ANDROID_API_LEVEL=24
function build_cmake_lib() { function build_cmake_lib() {
if [ ! -d "${1}" ]; then if [ ! -d "${1}" ]; then
@ -59,7 +60,7 @@ function build_cmake_lib() {
( (
cd "${1}" || exit 1 cd "${1}" || exit 1
cp "${CURDIR}"/scripts/compile_libs/cmake_lib_compile.sh cmake_lib_compile.sh cp "${CURDIR}"/scripts/compile_libs/cmake_lib_compile.sh cmake_lib_compile.sh
./cmake_lib_compile.sh "$_ANDROID_ABI_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS" ./cmake_lib_compile.sh "$ANDROID_API_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS"
) )
} }
@ -74,7 +75,7 @@ cd compile_libs || exit 1
( (
cd openssl || exit 1 cd openssl || exit 1
cp "${CURDIR}"/scripts/compile_libs/make_lib_openssl.sh make_lib_openssl.sh cp "${CURDIR}"/scripts/compile_libs/make_lib_openssl.sh make_lib_openssl.sh
./make_lib_openssl.sh "$_ANDROID_ABI_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS" ./make_lib_openssl.sh "$ANDROID_API_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS"
) )
) )
@ -97,7 +98,7 @@ build_cmake_lib opus https://github.com/xiph/opus
./autogen.sh ./autogen.sh
fi fi
cp "${CURDIR}"/scripts/compile_libs/make_lib_opusfile.sh make_lib_opusfile.sh cp "${CURDIR}"/scripts/compile_libs/make_lib_opusfile.sh make_lib_opusfile.sh
./make_lib_opusfile.sh "$_ANDROID_ABI_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS" ./make_lib_opusfile.sh "$ANDROID_API_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS"
) )
# SQLite, just download and built by hand # SQLite, just download and built by hand
@ -109,7 +110,7 @@ fi
( (
cd sqlite3 || exit 1 cd sqlite3 || exit 1
cp "${CURDIR}"/scripts/compile_libs/make_lib_sqlite3.sh make_lib_sqlite3.sh cp "${CURDIR}"/scripts/compile_libs/make_lib_sqlite3.sh make_lib_sqlite3.sh
./make_lib_sqlite3.sh "$_ANDROID_ABI_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS" ./make_lib_sqlite3.sh "$ANDROID_API_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS"
) )
cd .. cd ..

View file

@ -2929,6 +2929,24 @@ void CClient::Run()
g_UuidManager.DebugDump(); g_UuidManager.DebugDump();
} }
#ifndef CONF_WEBASM
char aNetworkError[256];
if(!InitNetworkClient(aNetworkError, sizeof(aNetworkError)))
{
log_error("client", "%s", aNetworkError);
ShowMessageBox("Network Error", aNetworkError);
return;
}
#endif
if(!m_Http.Init(std::chrono::seconds{1}))
{
const char *pErrorMessage = "Failed to initialize the HTTP client.";
log_error("client", "%s", pErrorMessage);
ShowMessageBox("HTTP Error", pErrorMessage);
return;
}
// init graphics // init graphics
m_pGraphics = CreateEngineGraphicsThreaded(); m_pGraphics = CreateEngineGraphicsThreaded();
Kernel()->RegisterInterface(m_pGraphics); // IEngineGraphics Kernel()->RegisterInterface(m_pGraphics); // IEngineGraphics
@ -2952,24 +2970,6 @@ void CClient::Run()
CVideo::Init(); CVideo::Init();
#endif #endif
#ifndef CONF_WEBASM
char aNetworkError[256];
if(!InitNetworkClient(aNetworkError, sizeof(aNetworkError)))
{
log_error("client", "%s", aNetworkError);
ShowMessageBox("Network Error", aNetworkError);
return;
}
#endif
if(!m_Http.Init(std::chrono::seconds{1}))
{
const char *pErrorMessage = "Failed to initialize the HTTP client.";
log_error("client", "%s", pErrorMessage);
ShowMessageBox("HTTP Error", pErrorMessage);
return;
}
// init text render // init text render
m_pTextRender = Kernel()->RequestInterface<IEngineTextRender>(); m_pTextRender = Kernel()->RequestInterface<IEngineTextRender>();
m_pTextRender->Init(); m_pTextRender->Init();

View file

@ -300,7 +300,7 @@ void CGraphics_Threaded::UnloadTexture(CTextureHandle *pIndex)
FreeTextureIndex(pIndex); FreeTextureIndex(pIndex);
} }
static bool ConvertToRGBA(uint8_t *pDest, const CImageInfo &SrcImage) bool ConvertToRGBA(uint8_t *pDest, const CImageInfo &SrcImage)
{ {
if(SrcImage.m_Format == CImageInfo::FORMAT_RGBA) if(SrcImage.m_Format == CImageInfo::FORMAT_RGBA)
{ {

View file

@ -124,6 +124,8 @@ public:
} }
}; };
bool ConvertToRGBA(uint8_t *pDest, const CImageInfo &SrcImage);
/* /*
Structure: CVideoMode Structure: CVideoMode
*/ */

View file

@ -73,6 +73,7 @@ MACRO_CONFIG_INT(ClShowfps, cl_showfps, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE,
MACRO_CONFIG_INT(ClShowpred, cl_showpred, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show ingame prediction time in milliseconds") MACRO_CONFIG_INT(ClShowpred, cl_showpred, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show ingame prediction time in milliseconds")
MACRO_CONFIG_INT(ClEyeWheel, cl_eye_wheel, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show eye wheel along together with emotes") MACRO_CONFIG_INT(ClEyeWheel, cl_eye_wheel, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show eye wheel along together with emotes")
MACRO_CONFIG_INT(ClEyeDuration, cl_eye_duration, 999999, 1, 999999, CFGFLAG_CLIENT | CFGFLAG_SAVE, "How long the eyes emotes last") MACRO_CONFIG_INT(ClEyeDuration, cl_eye_duration, 999999, 1, 999999, CFGFLAG_CLIENT | CFGFLAG_SAVE, "How long the eyes emotes last")
MACRO_CONFIG_INT(ClFreezeStars, cl_freeze_stars, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show old star particles for frozen tees")
MACRO_CONFIG_INT(ClAirjumpindicator, cl_airjumpindicator, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show the air jump indicator") MACRO_CONFIG_INT(ClAirjumpindicator, cl_airjumpindicator, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show the air jump indicator")
MACRO_CONFIG_INT(ClThreadsoundloading, cl_threadsoundloading, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Load sound files threaded") MACRO_CONFIG_INT(ClThreadsoundloading, cl_threadsoundloading, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Load sound files threaded")

View file

@ -341,7 +341,7 @@ void CConsole::Print(int Level, const char *pFrom, const char *pStr, ColorRGBA P
{ {
LEVEL LogLevel = IConsole::ToLogLevel(Level); LEVEL LogLevel = IConsole::ToLogLevel(Level);
// if console colors are not enabled or if the color is pure white, use default terminal color // if console colors are not enabled or if the color is pure white, use default terminal color
if(g_Config.m_ConsoleEnableColors && mem_comp(&PrintColor, &gs_ConsoleDefaultColor, sizeof(ColorRGBA)) != 0) if(g_Config.m_ConsoleEnableColors && PrintColor != gs_ConsoleDefaultColor)
{ {
log_log_color(LogLevel, ColorToLogColor(PrintColor), pFrom, "%s", pStr); log_log_color(LogLevel, ColorToLogColor(PrintColor), pFrom, "%s", pStr);
} }

View file

@ -70,18 +70,18 @@ void CEcon::Init(CConfig *pConfig, IConsole *pConsole, CNetBan *pNetBan)
} }
NETADDR BindAddr; NETADDR BindAddr;
if(g_Config.m_EcBindaddr[0] == '\0') if(g_Config.m_EcBindaddr[0] && net_host_lookup(g_Config.m_EcBindaddr, &BindAddr, NETTYPE_ALL) == 0)
{ {
mem_zero(&BindAddr, sizeof(BindAddr)); // got bindaddr
BindAddr.port = g_Config.m_EcPort;
} }
else if(net_host_lookup(g_Config.m_EcBindaddr, &BindAddr, NETTYPE_ALL) != 0) else
{ {
char aBuf[256]; char aBuf[256];
str_format(aBuf, sizeof(aBuf), "The configured bindaddr '%s' cannot be resolved.", g_Config.m_Bindaddr); str_format(aBuf, sizeof(aBuf), "The configured bindaddr '%s' cannot be resolved.", g_Config.m_EcBindaddr);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "econ", aBuf); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "econ", aBuf);
return;
} }
BindAddr.type = NETTYPE_ALL;
BindAddr.port = g_Config.m_EcPort;
if(m_NetConsole.Open(BindAddr, pNetBan)) if(m_NetConsole.Open(BindAddr, pNetBan))
{ {

View file

@ -1397,22 +1397,10 @@ void CMenus::RenderDemoBrowserButtons(CUIRect ButtonsView, bool WasListboxItemAc
// quick search // quick search
{ {
SetIconMode(true); CUIRect DemoSearch;
CUIRect DemoSearch, SearchIcon;
ButtonBarTop.VSplitLeft(ButtonBarBottom.h * 21.0f, &DemoSearch, &ButtonBarTop); ButtonBarTop.VSplitLeft(ButtonBarBottom.h * 21.0f, &DemoSearch, &ButtonBarTop);
ButtonBarTop.VSplitLeft(ButtonBarTop.h / 2.0f, nullptr, &ButtonBarTop); ButtonBarTop.VSplitLeft(ButtonBarTop.h / 2.0f, nullptr, &ButtonBarTop);
DemoSearch.VSplitLeft(TextRender()->TextWidth(14.0f, FONT_ICON_MAGNIFYING_GLASS), &SearchIcon, &DemoSearch); if(Ui()->DoEditBox_Search(&m_DemoSearchInput, &DemoSearch, 14.0f, !Ui()->IsPopupOpen() && m_pClient->m_GameConsole.IsClosed()))
DemoSearch.VSplitLeft(5.0f, nullptr, &DemoSearch);
Ui()->DoLabel(&SearchIcon, FONT_ICON_MAGNIFYING_GLASS, 14.0f, TEXTALIGN_ML);
SetIconMode(false);
m_DemoSearchInput.SetEmptyText(Localize("Search"));
if(Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed())
{
Ui()->SetActiveItem(&m_DemoSearchInput);
m_DemoSearchInput.SelectAll();
}
if(Ui()->DoClearableEditBox(&m_DemoSearchInput, &DemoSearch, 12.0f))
{ {
RefreshFilteredDemos(); RefreshFilteredDemos();
DemolistOnUpdate(false); DemolistOnUpdate(false);

View file

@ -683,26 +683,15 @@ void CMenus::RenderServerControl(CUIRect MainView)
// render quick search // render quick search
CUIRect QuickSearch; CUIRect QuickSearch;
Bottom.VSplitLeft(5.0f, 0, &Bottom); Bottom.VSplitLeft(5.0f, nullptr, &Bottom);
Bottom.VSplitLeft(250.0f, &QuickSearch, &Bottom); Bottom.VSplitLeft(250.0f, &QuickSearch, &Bottom);
TextRender()->SetFontPreset(EFontPreset::ICON_FONT); if(m_ControlPageOpening)
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
Ui()->DoLabel(&QuickSearch, FONT_ICON_MAGNIFYING_GLASS, 14.0f, TEXTALIGN_ML);
float SearchWidth = TextRender()->TextWidth(14.0f, FONT_ICON_MAGNIFYING_GLASS, -1, -1.0f);
TextRender()->SetRenderFlags(0);
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
QuickSearch.VSplitLeft(SearchWidth, 0, &QuickSearch);
QuickSearch.VSplitLeft(5.0f, 0, &QuickSearch);
if(m_ControlPageOpening || (Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed()))
{ {
Ui()->SetActiveItem(&m_FilterInput);
m_ControlPageOpening = false; m_ControlPageOpening = false;
Ui()->SetActiveItem(&m_FilterInput);
m_FilterInput.SelectAll(); m_FilterInput.SelectAll();
} }
m_FilterInput.SetEmptyText(Localize("Search")); Ui()->DoEditBox_Search(&m_FilterInput, &QuickSearch, 14.0f, !Ui()->IsPopupOpen() && m_pClient->m_GameConsole.IsClosed());
Ui()->DoClearableEditBox(&m_FilterInput, &QuickSearch, 14.0f);
// call vote // call vote
Bottom.VSplitRight(10.0f, &Bottom, 0); Bottom.VSplitRight(10.0f, &Bottom, 0);

View file

@ -257,7 +257,7 @@ void CMenus::SetNeedSendInfo()
void CMenus::RenderSettingsPlayer(CUIRect MainView) void CMenus::RenderSettingsPlayer(CUIRect MainView)
{ {
CUIRect TabBar, PlayerTab, DummyTab, ChangeInfo, QuickSearch, QuickSearchClearButton; CUIRect TabBar, PlayerTab, DummyTab, ChangeInfo, QuickSearch;
MainView.HSplitTop(20.0f, &TabBar, &MainView); MainView.HSplitTop(20.0f, &TabBar, &MainView);
TabBar.VSplitMid(&TabBar, &ChangeInfo, 20.f); TabBar.VSplitMid(&TabBar, &ChangeInfo, 20.f);
TabBar.VSplitMid(&PlayerTab, &DummyTab); TabBar.VSplitMid(&PlayerTab, &DummyTab);
@ -340,7 +340,10 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView)
} }
MainView.HSplitTop(10.0f, nullptr, &MainView); MainView.HSplitTop(10.0f, nullptr, &MainView);
MainView.HSplitBottom(25.0f, &MainView, &QuickSearch); MainView.HSplitBottom(20.0f, &MainView, &QuickSearch);
MainView.HSplitBottom(5.0f, &MainView, nullptr);
QuickSearch.VSplitLeft(220.0f, &QuickSearch, nullptr);
int OldSelected = -1; int OldSelected = -1;
static CListBox s_ListBox; static CListBox s_ListBox;
s_ListBox.DoStart(48.0f, vpFilteredFlags.size(), 10, 3, OldSelected, &MainView); s_ListBox.DoStart(48.0f, vpFilteredFlags.size(), 10, 3, OldSelected, &MainView);
@ -378,30 +381,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView)
SetNeedSendInfo(); SetNeedSendInfo();
} }
// render quick search Ui()->DoEditBox_Search(&s_FlagFilterInput, &QuickSearch, 14.0f, !Ui()->IsPopupOpen() && m_pClient->m_GameConsole.IsClosed());
QuickSearch.VSplitLeft(240.0f, &QuickSearch, nullptr);
QuickSearch.HSplitTop(5.0f, nullptr, &QuickSearch);
TextRender()->SetFontPreset(EFontPreset::ICON_FONT);
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
Ui()->DoLabel(&QuickSearch, FONT_ICON_MAGNIFYING_GLASS, 14.0f, TEXTALIGN_ML);
TextRender()->SetRenderFlags(0);
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
float SearchWidth = TextRender()->TextWidth(14.0f, FONT_ICON_MAGNIFYING_GLASS, -1, -1.0f);
QuickSearch.VSplitLeft(SearchWidth - 1.5f, nullptr, &QuickSearch);
QuickSearch.VSplitLeft(5.0f, nullptr, &QuickSearch);
QuickSearch.VSplitLeft(QuickSearch.w - 10.0f, &QuickSearch, &QuickSearchClearButton);
TextRender()->SetRenderFlags(0);
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
if(Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed())
{
Ui()->SetActiveItem(&s_FlagFilterInput);
s_FlagFilterInput.SelectAll();
}
s_FlagFilterInput.SetEmptyText(Localize("Search"));
Ui()->DoClearableEditBox(&s_FlagFilterInput, &QuickSearch, 14.0f);
} }
struct CUISkin struct CUISkin
@ -770,8 +750,8 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
CUIRect QuickSearch, DatabaseButton, DirectoryButton, RefreshButton; CUIRect QuickSearch, DatabaseButton, DirectoryButton, RefreshButton;
MainView.HSplitBottom(20.0f, &MainView, &QuickSearch); MainView.HSplitBottom(20.0f, &MainView, &QuickSearch);
MainView.HSplitBottom(5.0f, &MainView, nullptr); MainView.HSplitBottom(5.0f, &MainView, nullptr);
QuickSearch.VSplitLeft(240.0f, &QuickSearch, &DatabaseButton); QuickSearch.VSplitLeft(220.0f, &QuickSearch, &DatabaseButton);
QuickSearch.VSplitRight(10.0f, &QuickSearch, nullptr); DatabaseButton.VSplitLeft(10.0f, nullptr, &DatabaseButton);
DatabaseButton.VSplitLeft(150.0f, &DatabaseButton, &DirectoryButton); DatabaseButton.VSplitLeft(150.0f, &DatabaseButton, &DirectoryButton);
DirectoryButton.VSplitRight(175.0f, nullptr, &DirectoryButton); DirectoryButton.VSplitRight(175.0f, nullptr, &DirectoryButton);
DirectoryButton.VSplitRight(25.0f, &DirectoryButton, &RefreshButton); DirectoryButton.VSplitRight(25.0f, &DirectoryButton, &RefreshButton);
@ -904,24 +884,10 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
SetNeedSendInfo(); SetNeedSendInfo();
} }
// Quick search static CLineInput s_SkinFilterInput(g_Config.m_ClSkinFilterString, sizeof(g_Config.m_ClSkinFilterString));
if(Ui()->DoEditBox_Search(&s_SkinFilterInput, &QuickSearch, 14.0f, !Ui()->IsPopupOpen() && m_pClient->m_GameConsole.IsClosed()))
{ {
TextRender()->SetFontPreset(EFontPreset::ICON_FONT); m_SkinListNeedsUpdate = true;
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
Ui()->DoLabel(&QuickSearch, FONT_ICON_MAGNIFYING_GLASS, 14.0f, TEXTALIGN_ML);
float SearchWidth = TextRender()->TextWidth(14.0f, FONT_ICON_MAGNIFYING_GLASS, -1, -1.0f);
TextRender()->SetRenderFlags(0);
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
QuickSearch.VSplitLeft(SearchWidth + 5.0f, nullptr, &QuickSearch);
static CLineInput s_SkinFilterInput(g_Config.m_ClSkinFilterString, sizeof(g_Config.m_ClSkinFilterString));
if(Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed())
{
Ui()->SetActiveItem(&s_SkinFilterInput);
s_SkinFilterInput.SelectAll();
}
s_SkinFilterInput.SetEmptyText(Localize("Search"));
if(Ui()->DoClearableEditBox(&s_SkinFilterInput, &QuickSearch, 14.0f))
m_SkinListNeedsUpdate = true;
} }
static CButtonContainer s_SkinDatabaseButton; static CButtonContainer s_SkinDatabaseButton;

View file

@ -282,24 +282,10 @@ void CMenus::RenderSettingsTee7(CUIRect MainView)
} }
} }
// Quick search static CLineInput s_SkinFilterInput(g_Config.m_ClSkinFilterString, sizeof(g_Config.m_ClSkinFilterString));
if(Ui()->DoEditBox_Search(&s_SkinFilterInput, &QuickSearch, 14.0f, !Ui()->IsPopupOpen() && m_pClient->m_GameConsole.IsClosed()))
{ {
TextRender()->SetFontPreset(EFontPreset::ICON_FONT); m_SkinListNeedsUpdate = true;
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
Ui()->DoLabel(&QuickSearch, FontIcons::FONT_ICON_MAGNIFYING_GLASS, 14.0f, TEXTALIGN_ML);
float SearchWidth = TextRender()->TextWidth(14.0f, FontIcons::FONT_ICON_MAGNIFYING_GLASS, -1, -1.0f);
TextRender()->SetRenderFlags(0);
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
QuickSearch.VSplitLeft(SearchWidth + 5.0f, nullptr, &QuickSearch);
static CLineInput s_SkinFilterInput(g_Config.m_ClSkinFilterString, sizeof(g_Config.m_ClSkinFilterString));
if(Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed())
{
Ui()->SetActiveItem(&s_SkinFilterInput);
s_SkinFilterInput.SelectAll();
}
s_SkinFilterInput.SetEmptyText(Localize("Search"));
if(Ui()->DoClearableEditBox(&s_SkinFilterInput, &QuickSearch, 14.0f))
m_SkinListNeedsUpdate = true;
} }
static CButtonContainer s_DirectoryButton; static CButtonContainer s_DirectoryButton;

View file

@ -352,7 +352,7 @@ int InitSearchList(std::vector<const TName *> &vpSearchList, std::vector<TName>
void CMenus::RenderSettingsCustom(CUIRect MainView) void CMenus::RenderSettingsCustom(CUIRect MainView)
{ {
CUIRect TabBar, CustomList, QuickSearch, QuickSearchClearButton, DirectoryButton, ReloadButton; CUIRect TabBar, CustomList, QuickSearch, DirectoryButton, ReloadButton;
MainView.HSplitTop(20.0f, &TabBar, &MainView); MainView.HSplitTop(20.0f, &TabBar, &MainView);
const float TabWidth = TabBar.w / NUMBER_OF_ASSETS_TABS; const float TabWidth = TabBar.w / NUMBER_OF_ASSETS_TABS;
@ -599,29 +599,13 @@ void CMenus::RenderSettingsCustom(CUIRect MainView)
} }
} }
// render quick search // Quick search
MainView.HSplitBottom(ms_ButtonHeight, &MainView, &QuickSearch);
QuickSearch.VSplitLeft(220.0f, &QuickSearch, &DirectoryButton);
QuickSearch.HSplitTop(5.0f, nullptr, &QuickSearch);
if(Ui()->DoEditBox_Search(&s_aFilterInputs[s_CurCustomTab], &QuickSearch, 14.0f, !Ui()->IsPopupOpen() && m_pClient->m_GameConsole.IsClosed()))
{ {
MainView.HSplitBottom(ms_ButtonHeight, &MainView, &QuickSearch); gs_aInitCustomList[s_CurCustomTab] = true;
QuickSearch.VSplitLeft(240.0f, &QuickSearch, &DirectoryButton);
QuickSearch.HSplitTop(5.0f, 0, &QuickSearch);
TextRender()->SetFontPreset(EFontPreset::ICON_FONT);
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
Ui()->DoLabel(&QuickSearch, FONT_ICON_MAGNIFYING_GLASS, 14.0f, TEXTALIGN_ML);
float SearchWidth = TextRender()->TextWidth(14.0f, FONT_ICON_MAGNIFYING_GLASS, -1, -1.0f);
TextRender()->SetRenderFlags(0);
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
QuickSearch.VSplitLeft(SearchWidth, 0, &QuickSearch);
QuickSearch.VSplitLeft(5.0f, 0, &QuickSearch);
QuickSearch.VSplitLeft(QuickSearch.w - 10.0f, &QuickSearch, &QuickSearchClearButton);
if(Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed())
{
Ui()->SetActiveItem(&s_aFilterInputs[s_CurCustomTab]);
s_aFilterInputs[s_CurCustomTab].SelectAll();
}
s_aFilterInputs[s_CurCustomTab].SetEmptyText(Localize("Search"));
if(Ui()->DoClearableEditBox(&s_aFilterInputs[s_CurCustomTab], &QuickSearch, 14.0f))
gs_aInitCustomList[s_CurCustomTab] = true;
} }
DirectoryButton.HSplitTop(5.0f, 0, &DirectoryButton); DirectoryButton.HSplitTop(5.0f, 0, &DirectoryButton);

View file

@ -2071,6 +2071,32 @@ void CGameClient::OnNewSnapshot()
m_Effects.AirJump(Pos, Alpha); m_Effects.AirJump(Pos, Alpha);
} }
if(g_Config.m_ClFreezeStars && !m_SuppressEvents)
{
for(auto &Character : m_Snap.m_aCharacters)
{
if(Character.m_Active && Character.m_HasExtendedData && Character.m_PrevExtendedData)
{
int FreezeTimeNow = Character.m_ExtendedData.m_FreezeEnd - Client()->GameTick(g_Config.m_ClDummy);
int FreezeTimePrev = Character.m_PrevExtendedData->m_FreezeEnd - Client()->PrevGameTick(g_Config.m_ClDummy);
vec2 Pos = vec2(Character.m_Cur.m_X, Character.m_Cur.m_Y);
int StarsNow = (FreezeTimeNow + 1) / Client()->GameTickSpeed();
int StarsPrev = (FreezeTimePrev + 1) / Client()->GameTickSpeed();
if(StarsNow < StarsPrev || (StarsPrev == 0 && StarsNow > 0))
{
int Amount = StarsNow + 1;
float Mid = 3 * pi / 2;
float Min = Mid - pi / 3;
float Max = Mid + pi / 3;
for(int j = 0; j < Amount; j++)
{
float Angle = mix(Min, Max, (j + 1) / (float)(Amount + 2));
m_Effects.DamageIndicator(Pos, direction(Angle));
}
}
}
}
}
if(m_Snap.m_LocalClientId != m_PrevLocalId) if(m_Snap.m_LocalClientId != m_PrevLocalId)
m_PredictedDummyId = m_PrevLocalId; m_PredictedDummyId = m_PrevLocalId;
m_PrevLocalId = m_Snap.m_LocalClientId; m_PrevLocalId = m_Snap.m_LocalClientId;

View file

@ -57,7 +57,7 @@ void CUIElement::SUIElementRect::Reset()
void CUIElement::SUIElementRect::Draw(const CUIRect *pRect, ColorRGBA Color, int Corners, float Rounding) void CUIElement::SUIElementRect::Draw(const CUIRect *pRect, ColorRGBA Color, int Corners, float Rounding)
{ {
bool NeedsRecreate = false; bool NeedsRecreate = false;
if(m_UIRectQuadContainer == -1 || m_Width != pRect->w || m_Height != pRect->h || mem_comp(&m_QuadColor, &Color, sizeof(Color)) != 0) if(m_UIRectQuadContainer == -1 || m_Width != pRect->w || m_Height != pRect->h || m_QuadColor != Color)
{ {
m_pParent->Ui()->Graphics()->DeleteQuadContainer(m_UIRectQuadContainer); m_pParent->Ui()->Graphics()->DeleteQuadContainer(m_UIRectQuadContainer);
NeedsRecreate = true; NeedsRecreate = true;
@ -1004,6 +1004,25 @@ bool CUi::DoClearableEditBox(CLineInput *pLineInput, const CUIRect *pRect, float
return ReturnValue; return ReturnValue;
} }
bool CUi::DoEditBox_Search(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, bool HotkeyEnabled)
{
CUIRect QuickSearch = *pRect;
TextRender()->SetFontPreset(EFontPreset::ICON_FONT);
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
DoLabel(&QuickSearch, FONT_ICON_MAGNIFYING_GLASS, FontSize, TEXTALIGN_ML);
const float SearchWidth = TextRender()->TextWidth(FontSize, FONT_ICON_MAGNIFYING_GLASS);
TextRender()->SetRenderFlags(0);
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
QuickSearch.VSplitLeft(SearchWidth + 5.0f, nullptr, &QuickSearch);
if(HotkeyEnabled && Input()->ModifierIsPressed() && Input()->KeyPress(KEY_F))
{
SetActiveItem(pLineInput);
pLineInput->SelectAll();
}
pLineInput->SetEmptyText(Localize("Search"));
return DoClearableEditBox(pLineInput, &QuickSearch, FontSize);
}
int CUi::DoButton_Menu(CUIElement &UIElement, const CButtonContainer *pId, const std::function<const char *()> &GetTextLambda, const CUIRect *pRect, const SMenuButtonProperties &Props) int CUi::DoButton_Menu(CUIElement &UIElement, const CButtonContainer *pId, const std::function<const char *()> &GetTextLambda, const CUIRect *pRect, const SMenuButtonProperties &Props)
{ {
CUIRect Text = *pRect, DropDownIcon; CUIRect Text = *pRect, DropDownIcon;

View file

@ -603,6 +603,24 @@ public:
*/ */
bool DoClearableEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, int Corners = IGraphics::CORNER_ALL, const std::vector<STextColorSplit> &vColorSplits = {}); bool DoClearableEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, int Corners = IGraphics::CORNER_ALL, const std::vector<STextColorSplit> &vColorSplits = {});
/**
* Creates an input field with a search icon and a clear [x] button attached to it.
* The input will have default text "Search" and the hotkey Ctrl+F can be used to activate the input.
*
* @see DoEditBox
*
* @param pLineInput This pointer will be stored and written to on next user input.
* So you can not pass in a pointer that goes out of scope such as a local variable.
* Pass in either a member variable of the current class or a static variable.
* For example ```static CLineInputBuffered<IO_MAX_PATH_LENGTH> s_MyInput;```
* @param pRect the UI rect it will attach to
* @param FontSize Size of the font (`10.0f`, `12.0f` and `14.0f` are commonly used here)
* @param HotkeyEnabled Whether the hotkey to enable this editbox is currently enabled.
*
* @return true if the value of the input field changed since the last call.
*/
bool DoEditBox_Search(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, bool HotkeyEnabled);
int DoButton_Menu(CUIElement &UIElement, const CButtonContainer *pId, const std::function<const char *()> &GetTextLambda, const CUIRect *pRect, const SMenuButtonProperties &Props = {}); int DoButton_Menu(CUIElement &UIElement, const CButtonContainer *pId, const std::function<const char *()> &GetTextLambda, const CUIRect *pRect, const SMenuButtonProperties &Props = {});
// only used for popup menus // only used for popup menus
int DoButton_PopupMenu(CButtonContainer *pButtonContainer, const char *pText, const CUIRect *pRect, float Size, int Align, float Padding = 0.0f, bool TransparentInactive = false, bool Enabled = true); int DoButton_PopupMenu(CButtonContainer *pButtonContainer, const char *pText, const CUIRect *pRect, float Size, int Align, float Padding = 0.0f, bool TransparentInactive = false, bool Enabled = true);

View file

@ -4384,7 +4384,7 @@ bool CEditor::ReplaceImage(const char *pFileName, int StorageType, bool CheckDup
} }
} }
CEditorImage ImgInfo(this); CImageInfo ImgInfo;
if(!Graphics()->LoadPng(ImgInfo, pFileName, StorageType)) if(!Graphics()->LoadPng(ImgInfo, pFileName, StorageType))
{ {
ShowFileDialogError("Failed to load image from file '%s'.", pFileName); ShowFileDialogError("Failed to load image from file '%s'.", pFileName);
@ -4394,21 +4394,33 @@ bool CEditor::ReplaceImage(const char *pFileName, int StorageType, bool CheckDup
std::shared_ptr<CEditorImage> pImg = m_Map.m_vpImages[m_SelectedImage]; std::shared_ptr<CEditorImage> pImg = m_Map.m_vpImages[m_SelectedImage];
Graphics()->UnloadTexture(&(pImg->m_Texture)); Graphics()->UnloadTexture(&(pImg->m_Texture));
pImg->Free(); pImg->Free();
*pImg = ImgInfo; pImg->m_Width = ImgInfo.m_Width;
pImg->m_Height = ImgInfo.m_Height;
pImg->m_Format = ImgInfo.m_Format;
pImg->m_pData = ImgInfo.m_pData;
str_copy(pImg->m_aName, aBuf); str_copy(pImg->m_aName, aBuf);
pImg->m_External = IsVanillaImage(pImg->m_aName); pImg->m_External = IsVanillaImage(pImg->m_aName);
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1 && pImg->m_Format == CImageInfo::FORMAT_RGBA) if(!pImg->m_External && pImg->m_Format != CImageInfo::FORMAT_RGBA)
{ {
DilateImage(ImgInfo.m_pData, ImgInfo.m_Width, ImgInfo.m_Height); uint8_t *pRgbaData = static_cast<uint8_t *>(malloc((size_t)pImg->m_Width * pImg->m_Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA)));
ConvertToRGBA(pRgbaData, *pImg);
free(pImg->m_pData);
pImg->m_pData = pRgbaData;
pImg->m_Format = CImageInfo::FORMAT_RGBA;
}
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1)
{
DilateImage(pImg->m_pData, pImg->m_Width, pImg->m_Height);
} }
pImg->m_AutoMapper.Load(pImg->m_aName); pImg->m_AutoMapper.Load(pImg->m_aName);
int TextureLoadFlag = Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE; int TextureLoadFlag = Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0) if(pImg->m_Width % 16 != 0 || pImg->m_Height % 16 != 0)
TextureLoadFlag = 0; TextureLoadFlag = 0;
pImg->m_Texture = Graphics()->LoadTextureRaw(ImgInfo, TextureLoadFlag, pFileName); pImg->m_Texture = Graphics()->LoadTextureRaw(*pImg, TextureLoadFlag, pFileName);
ImgInfo.m_pData = nullptr;
SortImages(); SortImages();
for(size_t i = 0; i < m_Map.m_vpImages.size(); ++i) for(size_t i = 0; i < m_Map.m_vpImages.size(); ++i)
{ {
@ -4447,7 +4459,7 @@ bool CEditor::AddImage(const char *pFileName, int StorageType, void *pUser)
return false; return false;
} }
CEditorImage ImgInfo(pEditor); CImageInfo ImgInfo;
if(!pEditor->Graphics()->LoadPng(ImgInfo, pFileName, StorageType)) if(!pEditor->Graphics()->LoadPng(ImgInfo, pFileName, StorageType))
{ {
pEditor->ShowFileDialogError("Failed to load image from file '%s'.", pFileName); pEditor->ShowFileDialogError("Failed to load image from file '%s'.", pFileName);
@ -4455,19 +4467,30 @@ bool CEditor::AddImage(const char *pFileName, int StorageType, void *pUser)
} }
std::shared_ptr<CEditorImage> pImg = std::make_shared<CEditorImage>(pEditor); std::shared_ptr<CEditorImage> pImg = std::make_shared<CEditorImage>(pEditor);
*pImg = ImgInfo; pImg->m_Width = ImgInfo.m_Width;
pImg->m_Height = ImgInfo.m_Height;
pImg->m_Format = ImgInfo.m_Format;
pImg->m_pData = ImgInfo.m_pData;
pImg->m_External = IsVanillaImage(aBuf); pImg->m_External = IsVanillaImage(aBuf);
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1 && pImg->m_Format == CImageInfo::FORMAT_RGBA) if(pImg->m_Format != CImageInfo::FORMAT_RGBA)
{ {
DilateImage(ImgInfo.m_pData, ImgInfo.m_Width, ImgInfo.m_Height); uint8_t *pRgbaData = static_cast<uint8_t *>(malloc((size_t)pImg->m_Width * pImg->m_Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA)));
ConvertToRGBA(pRgbaData, *pImg);
free(pImg->m_pData);
pImg->m_pData = pRgbaData;
pImg->m_Format = CImageInfo::FORMAT_RGBA;
}
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1)
{
DilateImage(pImg->m_pData, pImg->m_Width, pImg->m_Height);
} }
int TextureLoadFlag = pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE; int TextureLoadFlag = pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0) if(pImg->m_Width % 16 != 0 || pImg->m_Height % 16 != 0)
TextureLoadFlag = 0; TextureLoadFlag = 0;
pImg->m_Texture = pEditor->Graphics()->LoadTextureRaw(ImgInfo, TextureLoadFlag, pFileName); pImg->m_Texture = pEditor->Graphics()->LoadTextureRaw(*pImg, TextureLoadFlag, pFileName);
ImgInfo.m_pData = nullptr;
str_copy(pImg->m_aName, aBuf); str_copy(pImg->m_aName, aBuf);
pImg->m_AutoMapper.Load(pImg->m_aName); pImg->m_AutoMapper.Load(pImg->m_aName);
pEditor->m_Map.m_vpImages.push_back(pImg); pEditor->m_Map.m_vpImages.push_back(pImg);

View file

@ -509,6 +509,15 @@ bool CEditorMap::Load(const char *pFileName, int StorageType, const std::functio
pImg->m_Height = ImgInfo.m_Height; pImg->m_Height = ImgInfo.m_Height;
pImg->m_Format = ImgInfo.m_Format; pImg->m_Format = ImgInfo.m_Format;
pImg->m_pData = ImgInfo.m_pData; pImg->m_pData = ImgInfo.m_pData;
if(pImg->m_Format != CImageInfo::FORMAT_RGBA)
{
uint8_t *pRgbaData = static_cast<uint8_t *>(malloc((size_t)pImg->m_Width * pImg->m_Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA)));
ConvertToRGBA(pRgbaData, *pImg);
free(pImg->m_pData);
pImg->m_pData = pRgbaData;
pImg->m_Format = CImageInfo::FORMAT_RGBA;
}
int TextureLoadFlag = m_pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE; int TextureLoadFlag = m_pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0) if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0)
TextureLoadFlag = 0; TextureLoadFlag = 0;