2863: Add menu background map r=def- a=Jupeyy

In fact, none of the 0.7 maps seem to work, i get buffer overflows all over.
For testing i just used Gold mine now.

since this is just #2731 without logic, and without any menu stuff, the best would be we just merge them somehow:

Animations working
Always forces design rendering(full detail etc.)
Regular maps work just fine

as said no logic yet, just display it for testing:

![screenshot_2020-09-18_18-49-17](https://user-images.githubusercontent.com/6654924/93623876-b355f680-f9df-11ea-9794-e251c6541f63.png)


Co-authored-by: Jupeyy <jupjopjap@gmail.com>
Co-authored-by: def <dennis@felsin9.de>
Co-authored-by: ChillerDragon <chillerdragon@gmail.com>
This commit is contained in:
bors[bot] 2020-09-23 21:39:31 +00:00 committed by GitHub
commit d3691bf221
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 981 additions and 117 deletions

View file

@ -1279,6 +1279,21 @@ set(EXPECTED_DATA
skins/whis.png
skins/x_ninja.png
skins/x_spec.png
themes/auto.png
themes/autumn.png
themes/autumn_day.map
themes/autumn_night.map
themes/heavens.png
themes/heavens_day.map
themes/heavens_night.map
themes/jungle.png
themes/jungle_day.map
themes/jungle_night.map
themes/none.png
themes/rand.png
themes/winter.png
themes/winter_day.map
themes/winter_night.map
wordlist.txt
)
@ -1481,6 +1496,7 @@ set_src(ENGINE_SHARED GLOB src/engine/shared
linereader.cpp
linereader.h
map.cpp
map.h
masterserver.cpp
memheap.cpp
memheap.h
@ -1688,6 +1704,8 @@ if(CLIENT)
components/maplayers.h
components/mapsounds.cpp
components/mapsounds.h
components/menu_background.cpp
components/menu_background.h
components/menus.cpp
components/menus.h
components/menus_browser.cpp

BIN
data/themes/auto.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
data/themes/autumn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
data/themes/autumn_day.map Normal file

Binary file not shown.

Binary file not shown.

BIN
data/themes/heavens.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
data/themes/heavens_day.map Normal file

Binary file not shown.

Binary file not shown.

BIN
data/themes/jungle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

BIN
data/themes/jungle_day.map Normal file

Binary file not shown.

Binary file not shown.

BIN
data/themes/none.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 989 B

BIN
data/themes/rand.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

BIN
data/themes/winter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
data/themes/winter_day.map Normal file

Binary file not shown.

Binary file not shown.

View file

@ -2267,6 +2267,46 @@ int time_timestamp(void)
return time(0);
}
int time_houroftheday(void)
{
time_t time_data;
struct tm *time_info;
time(&time_data);
time_info = localtime(&time_data);
return time_info->tm_hour;
}
int time_season(void)
{
time_t time_data;
struct tm *time_info;
time(&time_data);
time_info = localtime(&time_data);
switch(time_info->tm_mon)
{
case 11:
case 0:
case 1:
return SEASON_WINTER;
case 2:
case 3:
case 4:
return SEASON_SPRING;
case 5:
case 6:
case 7:
return SEASON_SUMMER;
case 8:
case 9:
case 10:
return SEASON_AUTUMN;
}
return SEASON_SPRING; // should never happen
}
void str_append(char *dst, const char *src, int dst_size)
{
int s = strlen(dst);

View file

@ -617,6 +617,32 @@ int64 time_freq(void);
*/
int time_timestamp(void);
/*
Function: time_houroftheday
Retrieves the hours since midnight (0..23)
Returns:
The current hour of the day
*/
int time_houroftheday(void);
enum
{
SEASON_SPRING = 0,
SEASON_SUMMER,
SEASON_AUTUMN,
SEASON_WINTER
};
/*
Function: time_season
Retrieves the current season of the year.
Returns:
one of the SEASON_* enum literals
*/
int time_season(void);
/*
Function: time_get_microseconds
Fetches a sample from a high resolution timer and converts it in microseconds.

View file

@ -5,6 +5,8 @@
#include <math.h>
#include "math.h"
// ------------------------------------
template<typename T>
@ -132,6 +134,15 @@ inline T length(const vector3_base<T> &a)
return sqrtf(a.x*a.x + a.y*a.y + a.z*a.z);
}
template<typename T>
inline vector2_base<T> rotate(const vector2_base<T> &a, float angle)
{
angle = angle * pi / 180.0f;
float s = sinf(angle);
float c = cosf(angle);
return vector2_base<T>((T)(c * a.x - s * a.y), (T)(s * a.x + c * a.y));
}
template<typename T>
inline T distance(const vector3_base<T> &a, const vector3_base<T> &b)
{

View file

@ -295,6 +295,13 @@ MACRO_CONFIG_INT(ClZoomBackgroundLayers, cl_zoom_background_layers, 0, 0, 1, CFG
MACRO_CONFIG_COL(ClBackgroundColor, cl_background_color, 128, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Background color") //0 0 128
MACRO_CONFIG_COL(ClBackgroundEntitiesColor, cl_background_entities_color, 128, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Background (entities) color") //0 0 128
MACRO_CONFIG_STR(ClBackgroundEntities, cl_background_entities, 100, "", CFGFLAG_CLIENT | CFGFLAG_SAVE, "Background (entities)")
// menu background map
MACRO_CONFIG_STR(ClMenuMap, cl_menu_map, 100, "auto", CFGFLAG_CLIENT | CFGFLAG_SAVE, "Background map in the menu")
MACRO_CONFIG_INT(ClRotationRadius, cl_rotation_radius, 30, 1, 500, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Menu camera rotation radius")
MACRO_CONFIG_INT(ClRotationSpeed, cl_rotation_speed, 40, 1, 120, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Menu camera rotations in seconds")
MACRO_CONFIG_INT(ClCameraSpeed, cl_camera_speed, 5, 1, 40, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Menu camera speed")
MACRO_CONFIG_INT(ClBackgroundShowTilesLayers, cl_background_show_tiles_layers, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Whether draw tiles layers when using custom background (entities)")
MACRO_CONFIG_INT(SvShowOthers, sv_show_others, 1, 0, 1, CFGFLAG_SERVER, "Whether players can use the command showothers or not")
MACRO_CONFIG_INT(SvShowOthersDefault, sv_show_others_default, 0, 0, 2, CFGFLAG_SERVER, "Whether players see others by default (2 for own team)")

View file

@ -1,63 +1,85 @@
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <base/system.h>
#include <engine/map.h>
#include "map.h"
#include <engine/storage.h>
#include "datafile.h"
class CMap : public IEngineMap
CMap::CMap()
{
CDataFileReader m_DataFile;
public:
CMap() {}
}
virtual void *GetData(int Index) { return m_DataFile.GetData(Index); }
virtual int GetDataSize(int Index) { return m_DataFile.GetDataSize(Index); }
virtual void *GetDataSwapped(int Index) { return m_DataFile.GetDataSwapped(Index); }
virtual void UnloadData(int Index) { m_DataFile.UnloadData(Index); }
virtual void *GetItem(int Index, int *pType, int *pID) { return m_DataFile.GetItem(Index, pType, pID); }
virtual int GetItemSize(int Index) { return m_DataFile.GetItemSize(Index); }
virtual void GetType(int Type, int *pStart, int *pNum) { m_DataFile.GetType(Type, pStart, pNum); }
virtual void *FindItem(int Type, int ID) { return m_DataFile.FindItem(Type, ID); }
virtual int NumItems() { return m_DataFile.NumItems(); }
void *CMap::GetData(int Index)
{
return m_DataFile.GetData(Index);
}
int CMap::GetDataSize(int Index)
{
return m_DataFile.GetDataSize(Index);
}
void *CMap::GetDataSwapped(int Index)
{
return m_DataFile.GetDataSwapped(Index);
}
void CMap::UnloadData(int Index)
{
m_DataFile.UnloadData(Index);
}
void *CMap::GetItem(int Index, int *pType, int *pID)
{
return m_DataFile.GetItem(Index, pType, pID);
}
int CMap::GetItemSize(int Index)
{
return m_DataFile.GetItemSize(Index);
}
void CMap::GetType(int Type, int *pStart, int *pNum)
{
m_DataFile.GetType(Type, pStart, pNum);
}
void *CMap::FindItem(int Type, int ID)
{
return m_DataFile.FindItem(Type, ID);
}
int CMap::NumItems()
{
return m_DataFile.NumItems();
}
virtual void Unload()
{
m_DataFile.Close();
}
void CMap::Unload()
{
m_DataFile.Close();
}
virtual bool Load(const char *pMapName)
{
IStorage *pStorage = Kernel()->RequestInterface<IStorage>();
if(!pStorage)
return false;
return m_DataFile.Open(pStorage, pMapName, IStorage::TYPE_ALL);
}
bool CMap::Load(const char *pMapName)
{
IStorage *pStorage = Kernel()->RequestInterface<IStorage>();
if(!pStorage)
return false;
return m_DataFile.Open(pStorage, pMapName, IStorage::TYPE_ALL);
}
virtual bool IsLoaded()
{
return m_DataFile.IsOpen();
}
bool CMap::IsLoaded()
{
return m_DataFile.IsOpen();
}
virtual SHA256_DIGEST Sha256()
{
return m_DataFile.Sha256();
}
SHA256_DIGEST CMap::Sha256()
{
return m_DataFile.Sha256();
}
virtual unsigned Crc()
{
return m_DataFile.Crc();
}
unsigned CMap::Crc()
{
return m_DataFile.Crc();
}
virtual int MapSize()
{
return m_DataFile.MapSize();
}
int CMap::MapSize()
{
return m_DataFile.MapSize();
}
virtual IOHANDLE File()
{
return m_DataFile.File();
}
};
IOHANDLE CMap::File()
{
return m_DataFile.File();
}
extern IEngineMap *CreateEngineMap() { return new CMap; }

43
src/engine/shared/map.h Normal file
View file

@ -0,0 +1,43 @@
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#ifndef ENGINE_SHARED_MAP_H
#define ENGINE_SHARED_MAP_H
#include <base/system.h>
#include "datafile.h"
#include <engine/map.h>
class CMap : public IEngineMap
{
CDataFileReader m_DataFile;
public:
CMap();
virtual void *GetData(int Index);
virtual int GetDataSize(int Index);
virtual void *GetDataSwapped(int Index);
virtual void UnloadData(int Index);
virtual void *GetItem(int Index, int *pType, int *pID);
virtual int GetItemSize(int Index);
virtual void GetType(int Type, int *pStart, int *pNum);
virtual void *FindItem(int Type, int ID);
virtual int NumItems();
virtual void Unload();
virtual bool Load(const char *pMapName);
virtual bool IsLoaded();
virtual SHA256_DIGEST Sha256();
virtual unsigned Crc();
virtual int MapSize();
virtual IOHANDLE File();
};
#endif

View file

@ -10,14 +10,15 @@
#include "background.h"
CBackground::CBackground() : CMapLayers(CMapLayers::TYPE_BACKGROUND_FORCE)
CBackground::CBackground(int MapType, bool OnlineOnly)
: CMapLayers(MapType, OnlineOnly)
{
m_pLayers = new CLayers;
m_pBackgroundLayers = m_pLayers;
m_pImages = new CMapImages;
m_pBackgroundImages = m_pImages;
m_pMap = CreateEngineMap();
m_pBackgroundMap = m_pMap;
m_pBackgroundMap = CreateBGMap();
m_pMap = m_pBackgroundMap;
m_Loaded = false;
m_aMapName[0] = '\0';
m_LastLoad = 0;
@ -29,10 +30,15 @@ CBackground::~CBackground()
delete m_pBackgroundImages;
}
CBackgroundEngineMap *CBackground::CreateBGMap()
{
return new CBackgroundEngineMap;
}
void CBackground::OnInit()
{
m_pImages->m_pClient = GameClient();
Kernel()->ReregisterInterface(m_pMap);
Kernel()->RegisterInterface(m_pBackgroundMap);
if(g_Config.m_ClBackgroundEntities[0] != '\0' && str_comp(g_Config.m_ClBackgroundEntities, CURRENT))
LoadBackground();
}
@ -72,7 +78,7 @@ void CBackground::LoadBackground()
m_Loaded = true;
}
}
if(m_Loaded)
{
CMapLayers::OnMapLoad();

View file

@ -1,13 +1,20 @@
#ifndef GAME_CLIENT_COMPONENTS_BACKGROUND_H
#define GAME_CLIENT_COMPONENTS_BACKGROUND_H
#include <engine/shared/map.h>
#include <game/client/component.h>
#include <game/client/components/maplayers.h>
// Special value to use background of current map
#define CURRENT "%current%"
class CBackgroundEngineMap : public CMap
{
MACRO_INTERFACE("background_enginemap", 0)
};
class CBackground : public CMapLayers
{
protected:
IEngineMap *m_pMap;
bool m_Loaded;
char m_aMapName[MAX_MAP_LENGTH];
@ -16,13 +23,15 @@ class CBackground : public CMapLayers
int64 m_LastLoad;
//to avoid memory leak when switching to %current%
IEngineMap *m_pBackgroundMap;
CBackgroundEngineMap *m_pBackgroundMap;
CLayers *m_pBackgroundLayers;
CMapImages *m_pBackgroundImages;
virtual CBackgroundEngineMap *CreateBGMap();
public:
CBackground();
~CBackground();
CBackground(int MapType = CMapLayers::TYPE_BACKGROUND_FORCE, bool OnlineOnly = true);
virtual ~CBackground();
virtual void OnInit();
virtual void OnMapLoad();

View file

@ -8,9 +8,11 @@
class CCamera : public CComponent
{
friend class CMenuBackground;
enum
{
CAMTYPE_UNDEFINED=-1,
CAMTYPE_UNDEFINED = -1,
CAMTYPE_SPEC,
CAMTYPE_PLAYER,
};

View file

@ -31,6 +31,7 @@ enum EMapImageModType
class CMapImages : public CComponent
{
friend class CBackground;
friend class CMenuBackground;
IGraphics::CTextureHandle m_aTextures[64];
int m_aTextureUsedByTileOrQuadLayerFlag[64]; // 0: nothing, 1(as flag): tile layer, 2(as flag): quad layer

View file

@ -19,13 +19,14 @@
#include "maplayers.h"
CMapLayers::CMapLayers(int t)
CMapLayers::CMapLayers(int t, bool OnlineOnly)
{
m_Type = t;
m_pLayers = 0;
m_CurrentLocalTick = 0;
m_LastLocalTick = 0;
m_EnvelopeUpdate = false;
m_OnlineOnly = OnlineOnly;
}
void CMapLayers::OnInit()
@ -34,6 +35,11 @@ void CMapLayers::OnInit()
m_pImages = m_pClient->m_pMapimages;
}
CCamera *CMapLayers::GetCurCamera()
{
return m_pClient->m_pCamera;
}
void CMapLayers::EnvelopeUpdate()
{
if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
@ -109,19 +115,27 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void
}
else
{
if(pThis->m_pClient->m_Snap.m_pGameInfoObj) // && !(pThis->m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
if(pThis->m_OnlineOnly && (pItem->m_Version < 2 || pItem->m_Synchronized))
{
if(pItem->m_Version < 2 || pItem->m_Synchronized)
if(pThis->m_OnlineOnly && pThis->m_pClient->m_Snap.m_pGameInfoObj) // && !(pThis->m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
{
s_Time = mix((pThis->Client()->PrevGameTick(g_Config.m_ClDummy)-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(),
(pThis->Client()->GameTick(g_Config.m_ClDummy)-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(),
pThis->Client()->IntraGameTick(g_Config.m_ClDummy));
}
else
s_Time += pThis->LocalTime()-s_LastLocalTime;
}
pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels);
s_LastLocalTime = pThis->LocalTime();
else if(pThis->m_OnlineOnly)
{
s_Time += pThis->LocalTime() - s_LastLocalTime;
s_LastLocalTime = pThis->LocalTime();
}
else
{
float CurTime = (float)((double)time_get_microseconds() / 1000000.0);
s_Time += CurTime - s_LastLocalTime;
s_LastLocalTime = CurTime;
}
pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time + TimeOffset, pChannels);
}
}
@ -1480,13 +1494,13 @@ void CMapLayers::LayersOfGroupCount(CMapItemGroup* pGroup, int& TileLayerCount,
void CMapLayers::OnRender()
{
if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK)
if(m_OnlineOnly && Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK)
return;
CUIRect Screen;
Graphics()->GetScreen(&Screen.x, &Screen.y, &Screen.w, &Screen.h);
vec2 Center = m_pClient->m_pCamera->m_Center;
vec2 Center = GetCurCamera()->m_Center;
bool PassedGameLayer = false;
int TileLayerCounter = 0;
@ -1504,11 +1518,11 @@ void CMapLayers::OnRender()
continue;
}
if(!g_Config.m_GfxNoclip && pGroup->m_Version >= 2 && pGroup->m_UseClipping)
if((!g_Config.m_GfxNoclip || m_Type == TYPE_FULL_DESIGN) && pGroup->m_Version >= 2 && pGroup->m_UseClipping)
{
// set clipping
float Points[4];
MapScreenToGroup(Center.x, Center.y, m_pLayers->GameGroup(), m_pClient->m_pCamera->m_Zoom);
MapScreenToGroup(Center.x, Center.y, m_pLayers->GameGroup(), GetCurCamera()->m_Zoom);
Graphics()->GetScreen(&Points[0], &Points[1], &Points[2], &Points[3]);
float x0 = (pGroup->m_ClipX - Points[0]) / (Points[2]-Points[0]);
float y0 = (pGroup->m_ClipY - Points[1]) / (Points[3]-Points[1]);
@ -1526,11 +1540,12 @@ void CMapLayers::OnRender()
(int)((x1-x0)*Graphics()->ScreenWidth()), (int)((y1-y0)*Graphics()->ScreenHeight()));
}
if(!g_Config.m_ClZoomBackgroundLayers && !pGroup->m_ParallaxX && !pGroup->m_ParallaxY)
if((!g_Config.m_ClZoomBackgroundLayers || m_Type == TYPE_FULL_DESIGN) && !pGroup->m_ParallaxX && !pGroup->m_ParallaxY)
{
MapScreenToGroup(Center.x, Center.y, pGroup, 1.0f);
} else
MapScreenToGroup(Center.x, Center.y, pGroup, m_pClient->m_pCamera->m_Zoom);
}
else
MapScreenToGroup(Center.x, Center.y, pGroup, GetCurCamera()->m_Zoom);
for(int l = 0; l < pGroup->m_NumLayers; l++)
{
@ -1579,11 +1594,16 @@ void CMapLayers::OnRender()
continue;
}
}
else // TYPE_FOREGROUND
else if(m_Type == TYPE_FOREGROUND)
{
if(PassedGameLayer && !IsGameLayer)
Render = true;
}
else if(m_Type == TYPE_FULL_DESIGN)
{
if(!IsGameLayer)
Render = true;
}
if(Render && pLayer->m_Type == LAYERTYPE_TILES && Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyIsPressed(KEY_LSHIFT) && Input()->KeyPress(KEY_KP_0))
{
@ -1661,10 +1681,14 @@ void CMapLayers::OnRender()
}
// skip rendering if detail layers if not wanted, or is entity layer and we are a background map
if((pLayer->m_Flags&LAYERFLAG_DETAIL && !g_Config.m_GfxHighDetail && !IsGameLayer) || (m_Type == TYPE_BACKGROUND_FORCE && IsEntityLayer))
if((pLayer->m_Flags & LAYERFLAG_DETAIL && (!g_Config.m_GfxHighDetail && !(m_Type == TYPE_FULL_DESIGN)) && !IsGameLayer) || (m_Type == TYPE_BACKGROUND_FORCE && IsEntityLayer) || (m_Type == TYPE_FULL_DESIGN && IsEntityLayer))
continue;
if((Render && g_Config.m_ClOverlayEntities < 100 && !IsGameLayer && !IsFrontLayer && !IsSwitchLayer && !IsTeleLayer && !IsSpeedupLayer && !IsTuneLayer) || (g_Config.m_ClOverlayEntities && IsGameLayer) || (m_Type == TYPE_BACKGROUND_FORCE))
int EntityOverlayVal = g_Config.m_ClOverlayEntities;
if(m_Type == TYPE_FULL_DESIGN)
EntityOverlayVal = 0;
if((Render && EntityOverlayVal < 100 && !IsGameLayer && !IsFrontLayer && !IsSwitchLayer && !IsTeleLayer && !IsSpeedupLayer && !IsTuneLayer) || (EntityOverlayVal && IsGameLayer) || (m_Type == TYPE_BACKGROUND_FORCE))
{
if(pLayer->m_Type == LAYERTYPE_TILES)
{
@ -1684,11 +1708,11 @@ void CMapLayers::OnRender()
if(Size >= pTMap->m_Width*pTMap->m_Height*sizeof(CTile))
{
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f);
if(IsGameLayer && g_Config.m_ClOverlayEntities)
Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*g_Config.m_ClOverlayEntities/100.0f);
else if(!IsGameLayer && g_Config.m_ClOverlayEntities && !(m_Type == TYPE_BACKGROUND_FORCE))
Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*(100-g_Config.m_ClOverlayEntities)/100.0f);
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f);
if(IsGameLayer && EntityOverlayVal)
Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * EntityOverlayVal / 100.0f);
else if(!IsGameLayer && EntityOverlayVal && !(m_Type == TYPE_BACKGROUND_FORCE))
Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * (100 - EntityOverlayVal) / 100.0f);
if(!Graphics()->IsTileBufferingEnabled())
{
Graphics()->BlendNone();
@ -1739,9 +1763,9 @@ void CMapLayers::OnRender()
Graphics()->TextureSet(m_pImages->Get(pQLayer->m_Image));
CQuad *pQuads = (CQuad *)m_pLayers->Map()->GetDataSwapped(pQLayer->m_Data);
if(m_Type == TYPE_BACKGROUND_FORCE)
if(m_Type == TYPE_BACKGROUND_FORCE || m_Type == TYPE_FULL_DESIGN)
{
if(g_Config.m_ClShowQuads)
if(g_Config.m_ClShowQuads || m_Type == TYPE_FULL_DESIGN)
{
if(!Graphics()->IsQuadBufferingEnabled())
{
@ -1755,7 +1779,8 @@ void CMapLayers::OnRender()
RenderQuadLayer(QuadLayerCounter-1, pQLayer, pGroup, true);
}
}
} else
}
else
{
if(!Graphics()->IsQuadBufferingEnabled())
{
@ -1771,7 +1796,7 @@ void CMapLayers::OnRender()
}
}
}
else if(Render && g_Config.m_ClOverlayEntities && IsFrontLayer)
else if(Render && EntityOverlayVal && IsFrontLayer)
{
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
Graphics()->TextureSet(m_pImages->GetEntities(MAP_IMAGE_ENTITY_LAYER_TYPE_FRONT));
@ -1781,7 +1806,7 @@ void CMapLayers::OnRender()
if(Size >= pTMap->m_Width*pTMap->m_Height*sizeof(CTile))
{
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*g_Config.m_ClOverlayEntities/100.0f);
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * EntityOverlayVal / 100.0f);
if(!Graphics()->IsTileBufferingEnabled())
{
Graphics()->BlendNone();
@ -1798,7 +1823,7 @@ void CMapLayers::OnRender()
}
}
}
else if(Render && g_Config.m_ClOverlayEntities && IsSwitchLayer)
else if(Render && EntityOverlayVal && IsSwitchLayer)
{
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
Graphics()->TextureSet(m_pImages->GetEntities(MAP_IMAGE_ENTITY_LAYER_TYPE_SWITCH));
@ -1808,14 +1833,14 @@ void CMapLayers::OnRender()
if(Size >= pTMap->m_Width*pTMap->m_Height*sizeof(CSwitchTile))
{
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*g_Config.m_ClOverlayEntities/100.0f);
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * EntityOverlayVal / 100.0f);
if(!Graphics()->IsTileBufferingEnabled())
{
Graphics()->BlendNone();
RenderTools()->RenderSwitchmap(pSwitchTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE);
Graphics()->BlendNormal();
RenderTools()->RenderSwitchmap(pSwitchTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT);
RenderTools()->RenderSwitchOverlay(pSwitchTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, g_Config.m_ClOverlayEntities/100.0f);
RenderTools()->RenderSwitchmap(pSwitchTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_TRANSPARENT);
RenderTools()->RenderSwitchOverlay(pSwitchTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, EntityOverlayVal / 100.0f);
}
else
{
@ -1831,7 +1856,7 @@ void CMapLayers::OnRender()
}
}
}
else if(Render && g_Config.m_ClOverlayEntities && IsTeleLayer)
else if(Render && EntityOverlayVal && IsTeleLayer)
{
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
Graphics()->TextureSet(m_pImages->GetEntities(MAP_IMAGE_ENTITY_LAYER_TYPE_TELE));
@ -1841,14 +1866,14 @@ void CMapLayers::OnRender()
if(Size >= pTMap->m_Width*pTMap->m_Height*sizeof(CTeleTile))
{
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*g_Config.m_ClOverlayEntities/100.0f);
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * EntityOverlayVal / 100.0f);
if(!Graphics()->IsTileBufferingEnabled())
{
Graphics()->BlendNone();
RenderTools()->RenderTelemap(pTeleTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE);
Graphics()->BlendNormal();
RenderTools()->RenderTelemap(pTeleTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT);
RenderTools()->RenderTeleOverlay(pTeleTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, g_Config.m_ClOverlayEntities/100.0f);
RenderTools()->RenderTelemap(pTeleTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_TRANSPARENT);
RenderTools()->RenderTeleOverlay(pTeleTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, EntityOverlayVal / 100.0f);
}
else
{
@ -1862,7 +1887,7 @@ void CMapLayers::OnRender()
}
}
}
else if(Render && g_Config.m_ClOverlayEntities && IsSpeedupLayer)
else if(Render && EntityOverlayVal && IsSpeedupLayer)
{
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
Graphics()->TextureSet(m_pImages->GetEntities(MAP_IMAGE_ENTITY_LAYER_TYPE_SPEEDUP));
@ -1872,14 +1897,14 @@ void CMapLayers::OnRender()
if(Size >= pTMap->m_Width*pTMap->m_Height*sizeof(CSpeedupTile))
{
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*g_Config.m_ClOverlayEntities/100.0f);
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * EntityOverlayVal / 100.0f);
if(!Graphics()->IsTileBufferingEnabled())
{
Graphics()->BlendNone();
RenderTools()->RenderSpeedupmap(pSpeedupTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE);
Graphics()->BlendNormal();
RenderTools()->RenderSpeedupmap(pSpeedupTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT);
RenderTools()->RenderSpeedupOverlay(pSpeedupTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, g_Config.m_ClOverlayEntities/100.0f);
RenderTools()->RenderSpeedupmap(pSpeedupTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_TRANSPARENT);
RenderTools()->RenderSpeedupOverlay(pSpeedupTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, EntityOverlayVal / 100.0f);
}
else
{
@ -1900,7 +1925,7 @@ void CMapLayers::OnRender()
}
}
}
else if(Render && g_Config.m_ClOverlayEntities && IsTuneLayer)
else if(Render && EntityOverlayVal && IsTuneLayer)
{
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
Graphics()->TextureSet(m_pImages->GetEntities(MAP_IMAGE_ENTITY_LAYER_TYPE_TUNE));
@ -1910,14 +1935,14 @@ void CMapLayers::OnRender()
if(Size >= pTMap->m_Width*pTMap->m_Height*sizeof(CTuneTile))
{
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*g_Config.m_ClOverlayEntities/100.0f);
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * EntityOverlayVal / 100.0f);
if(!Graphics()->IsTileBufferingEnabled())
{
Graphics()->BlendNone();
RenderTools()->RenderTunemap(pTuneTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE);
Graphics()->BlendNormal();
RenderTools()->RenderTunemap(pTuneTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT);
//RenderTools()->RenderTuneOverlay(pTuneTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, g_Config.m_ClOverlayEntities/100.0f);
RenderTools()->RenderTunemap(pTuneTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_TRANSPARENT);
//RenderTools()->RenderTuneOverlay(pTuneTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, EntityOverlayVal/100.0f);
}
else
{
@ -1927,11 +1952,11 @@ void CMapLayers::OnRender()
}
}
}
if(!g_Config.m_GfxNoclip)
if(!g_Config.m_GfxNoclip || m_Type == TYPE_FULL_DESIGN)
Graphics()->ClipDisable();
}
if(!g_Config.m_GfxNoclip)
if(!g_Config.m_GfxNoclip || m_Type == TYPE_FULL_DESIGN)
Graphics()->ClipDisable();
// reset the screen like it was before

View file

@ -19,6 +19,7 @@ typedef unsigned int offset_ptr32;
class CMapLayers : public CComponent
{
friend class CBackground;
friend class CMenuBackground;
CLayers *m_pLayers;
class CMapImages *m_pImages;
@ -27,6 +28,8 @@ class CMapLayers : public CComponent
int m_LastLocalTick;
bool m_EnvelopeUpdate;
bool m_OnlineOnly;
void MapScreenToGroup(float CenterX, float CenterY, CMapItemGroup *pGroup, float Zoom = 1.0f);
struct STileLayerVisuals
@ -114,18 +117,22 @@ class CMapLayers : public CComponent
};
std::vector<SQuadLayerVisuals*> m_QuadLayerVisuals;
void LayersOfGroupCount(CMapItemGroup* pGroup, int& TileLayerCount, int& QuadLayerCount, bool& PassedGameLayer);
virtual class CCamera *GetCurCamera();
void LayersOfGroupCount(CMapItemGroup *pGroup, int &TileLayerCount, int &QuadLayerCount, bool &PassedGameLayer);
void RenderTileBorderCornerTiles(int WidthOffsetToOrigin, int HeightOffsetToOrigin, int TileCountWidth, int TileCountHeight, int BufferContainerIndex, float *pColor, offset_ptr_size IndexBufferOffset, float *pOffset, float *pDir);
public:
enum
{
TYPE_BACKGROUND=0,
TYPE_BACKGROUND = 0,
TYPE_BACKGROUND_FORCE,
TYPE_FOREGROUND,
TYPE_FULL_DESIGN,
TYPE_ALL = -1,
};
CMapLayers(int Type);
CMapLayers(int Type, bool OnlineOnly = true);
virtual void OnInit();
virtual void OnRender();
virtual void OnMapLoad();

View file

@ -0,0 +1,368 @@
#include <base/system.h>
#include <algorithm>
#include <engine/graphics.h>
#include <engine/map.h>
#include <engine/shared/config.h>
#include <game/client/components/camera.h>
#include <game/client/components/mapimages.h>
#include <game/client/components/maplayers.h>
#include "menu_background.h"
CMenuBackground::CMenuBackground()
: CBackground(CMapLayers::TYPE_FULL_DESIGN, false)
{
m_RotationCenter = vec2(0.0f, 0.0f);
m_AnimationStartPos = vec2(0.0f, 0.0f);
m_Camera.m_Center = vec2(0.0f, 0.0f);
m_Camera.m_PrevCenter = vec2(0.0f, 0.0f);
m_MenuCenter = vec2(0.0f, 0.0f);
ResetPositions();
m_CurrentPosition = -1;
m_MoveTime = 0.0f;
m_IsInit = false;
}
CBackgroundEngineMap *CMenuBackground::CreateBGMap()
{
return new CMenuMap;
}
void CMenuBackground::OnInit()
{
m_IsInit = true;
m_pImages->m_pClient = GameClient();
Kernel()->RegisterInterface<CMenuMap>((CMenuMap *)m_pBackgroundMap);
if(g_Config.m_ClMenuMap[0] != '\0')
LoadMenuBackground();
m_Camera.m_pClient = GameClient();
m_Camera.m_ZoomSet = false;
m_Camera.m_ZoomSmoothingTarget = 0;
}
void CMenuBackground::ResetPositions()
{
m_Positions[POS_START] = vec2(500.0f, 500.0f);
m_Positions[POS_INTERNET] = vec2(1000.0f, 1000.0f);
m_Positions[POS_LAN] = vec2(1100.0f, 1000.0f);
m_Positions[POS_DEMOS] = vec2(900.0f, 100.0f);
m_Positions[POS_NEWS] = vec2(500.0f, 750.0f);
m_Positions[POS_FAVORITES] = vec2(1250.0f, 500.0f);
m_Positions[POS_SETTINGS_LANGUAGE] = vec2(500.0f, 1200.0f);
m_Positions[POS_SETTINGS_GENERAL] = vec2(500.0f, 1000.0f);
m_Positions[POS_SETTINGS_PLAYER] = vec2(600.0f, 1000.0f);
m_Positions[POS_SETTINGS_TEE] = vec2(700.0f, 1000.0f);
m_Positions[POS_SETTINGS_HUD] = vec2(200.0f, 1000.0f);
m_Positions[POS_SETTINGS_CONTROLS] = vec2(800.0f, 1000.0f);
m_Positions[POS_SETTINGS_GRAPHICS] = vec2(900.0f, 1000.0f);
m_Positions[POS_SETTINGS_SOUND] = vec2(1000.0f, 1000.0f);
m_Positions[POS_SETTINGS_DDNET] = vec2(1200.0f, 200.0f);
for(int i = 0; i < POS_CUSTOM_NUM; ++i)
m_Positions[POS_CUSTOM0 + i] = vec2(500.0f + (75.0f * (float)i), 1250.0f - (75.0f * (float)i));
}
int CMenuBackground::ThemeScan(const char *pName, int IsDir, int DirType, void *pUser)
{
CMenuBackground *pSelf = (CMenuBackground *)pUser;
const char *pSuffix = str_endswith(pName, ".map");
if(IsDir || !pSuffix)
return 0;
char aFullName[128];
char aThemeName[128];
str_truncate(aFullName, sizeof(aFullName), pName, pSuffix - pName);
bool IsDay = false;
bool IsNight = false;
if((pSuffix = str_endswith(aFullName, "_day")))
{
str_truncate(aThemeName, sizeof(aThemeName), pName, pSuffix - aFullName);
IsDay = true;
}
else if((pSuffix = str_endswith(aFullName, "_night")))
{
str_truncate(aThemeName, sizeof(aThemeName), pName, pSuffix - aFullName);
IsNight = true;
}
else
str_copy(aThemeName, aFullName, sizeof(aThemeName));
if(str_comp(aThemeName, "none") == 0 || str_comp(aThemeName, "auto") == 0 || str_comp(aThemeName, "rand") == 0) // "none", "auto" and "rand" reserved, disallowed for maps
return 0;
// try to edit an existing theme
for(int i = 0; i < (int)pSelf->m_lThemes.size(); i++)
{
if(str_comp(pSelf->m_lThemes[i].m_Name, aThemeName) == 0)
{
if(IsDay)
pSelf->m_lThemes[i].m_HasDay = true;
if(IsNight)
pSelf->m_lThemes[i].m_HasNight = true;
return 0;
}
}
// make new theme
CTheme Theme(aThemeName, IsDay, IsNight);
char aBuf[512];
str_format(aBuf, sizeof(aBuf), "added theme %s from themes/%s", aThemeName, pName);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf);
pSelf->m_lThemes.push_back(Theme);
return 0;
}
int CMenuBackground::ThemeIconScan(const char *pName, int IsDir, int DirType, void *pUser)
{
CMenuBackground *pSelf = (CMenuBackground *)pUser;
const char *pSuffix = str_endswith(pName, ".png");
if(IsDir || !pSuffix)
return 0;
char aThemeName[128];
str_truncate(aThemeName, sizeof(aThemeName), pName, pSuffix - pName);
// save icon for an existing theme
for(CTheme &Theme : pSelf->m_lThemes) // bit slow but whatever
{
if(str_comp(Theme.m_Name, aThemeName) == 0 || (!Theme.m_Name[0] && str_comp(aThemeName, "none") == 0))
{
char aBuf[MAX_PATH_LENGTH];
str_format(aBuf, sizeof(aBuf), "themes/%s", pName);
CImageInfo Info;
if(!pSelf->Graphics()->LoadPNG(&Info, aBuf, DirType))
{
str_format(aBuf, sizeof(aBuf), "failed to load theme icon from %s", pName);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf);
return 0;
}
str_format(aBuf, sizeof(aBuf), "loaded theme icon %s", pName);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf);
Theme.m_IconTexture = pSelf->Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0);
return 0;
}
}
return 0; // no existing theme
}
void CMenuBackground::LoadMenuBackground(bool HasDayHint, bool HasNightHint)
{
if(!m_IsInit)
return;
if(m_Loaded && m_pMap == m_pBackgroundMap)
m_pMap->Unload();
m_Loaded = false;
m_pMap = m_pBackgroundMap;
m_pLayers = m_pBackgroundLayers;
m_pImages = m_pBackgroundImages;
ResetPositions();
bool NeedImageLoading = false;
str_copy(m_aMapName, g_Config.m_ClMenuMap, sizeof(m_aMapName));
if(g_Config.m_ClMenuMap[0] != '\0')
{
const char *pMenuMap = g_Config.m_ClMenuMap;
if(str_comp(pMenuMap, "auto") == 0)
{
switch(time_season())
{
case SEASON_SPRING:
pMenuMap = "heavens";
break;
case SEASON_SUMMER:
pMenuMap = "jungle";
break;
case SEASON_AUTUMN:
pMenuMap = "autumn";
break;
case SEASON_WINTER:
pMenuMap = "winter";
break;
}
}
else if(str_comp(pMenuMap, "rand") == 0)
{
//make sure to load themes
std::vector<CTheme> &ThemesRef = GetThemes();
int RandomThemeIndex = rand() % (ThemesRef.size() - PREDEFINED_THEMES_COUNT);
if(RandomThemeIndex + PREDEFINED_THEMES_COUNT < (int)ThemesRef.size())
pMenuMap = ThemesRef[RandomThemeIndex + PREDEFINED_THEMES_COUNT].m_Name.cstr();
}
char aBuf[128];
const int HourOfTheDay = time_houroftheday();
const bool IsDaytime = HourOfTheDay >= 6 && HourOfTheDay < 18;
if(!m_Loaded && ((HasDayHint && IsDaytime) || (HasNightHint && !IsDaytime)))
{
str_format(aBuf, sizeof(aBuf), "themes/%s_%s.map", pMenuMap, IsDaytime ? "day" : "night");
if(m_pMap->Load(aBuf))
{
m_Loaded = true;
}
}
if(!m_Loaded)
{
str_format(aBuf, sizeof(aBuf), "themes/%s.map", pMenuMap);
if(m_pMap->Load(aBuf))
{
m_Loaded = true;
}
}
if(!m_Loaded && ((HasDayHint && !IsDaytime) || (HasNightHint && IsDaytime)))
{
str_format(aBuf, sizeof(aBuf), "themes/%s_%s.map", pMenuMap, IsDaytime ? "night" : "day");
if(m_pMap->Load(aBuf))
{
m_Loaded = true;
}
}
if(m_Loaded)
{
m_pLayers->InitBackground(m_pMap);
RenderTools()->RenderTilemapGenerateSkip(m_pLayers);
NeedImageLoading = true;
CMapLayers::OnMapLoad();
if(NeedImageLoading)
m_pImages->LoadBackground(m_pLayers, m_pMap);
// look for custom positions
CMapItemLayerTilemap *pTLayer = m_pLayers->GameLayer();
if(pTLayer)
{
int DataIndex = pTLayer->m_Data;
unsigned int Size = m_pLayers->Map()->GetDataSize(DataIndex);
void *pTiles = m_pLayers->Map()->GetData(DataIndex);
unsigned int TileSize = sizeof(CTile);
if(Size >= pTLayer->m_Width * pTLayer->m_Height * TileSize)
{
int x = 0;
int y = 0;
for(y = 0; y < pTLayer->m_Height; ++y)
{
for(x = 0; x < pTLayer->m_Width; ++x)
{
unsigned char Index = ((CTile *)pTiles)[y * pTLayer->m_Width + x].m_Index;
if(Index >= TILE_CHECKPOINT_FIRST && Index <= TILE_CHECKPOINT_LAST)
{
int ArrayIndex = clamp<int>((Index - TILE_CHECKPOINT_FIRST), 0, NUM_POS);
m_Positions[ArrayIndex] = vec2(x * 32.0f + 16.0f, y * 32.0f + 16.0f);
}
x += ((CTile *)pTiles)[y * pTLayer->m_Width + x].m_Skip;
}
}
}
}
}
m_LastLoad = time_get();
}
}
void CMenuBackground::OnMapLoad()
{
return;
}
void CMenuBackground::OnRender()
{
return;
}
bool CMenuBackground::Render()
{
if(!m_Loaded)
return false;
if(Client()->State() >= IClient::STATE_ONLINE)
return false;
m_Camera.m_Zoom = 0.7f;
static vec2 Dir = vec2(1.0f, 0.0f);
if(distance(m_Camera.m_Center, m_RotationCenter) <= (float)g_Config.m_ClRotationRadius + 0.5f)
{
// do little rotation
float RotPerTick = 360.0f / (float)g_Config.m_ClRotationSpeed * clamp(Client()->RenderFrameTime(), 0.0f, 0.1f);
Dir = rotate(Dir, RotPerTick);
m_Camera.m_Center = m_RotationCenter + Dir * (float)g_Config.m_ClRotationRadius;
}
else
{
// positions for the animation
Dir = normalize(m_AnimationStartPos - m_RotationCenter);
vec2 TargetPos = m_RotationCenter + Dir * (float)g_Config.m_ClRotationRadius;
float Distance = distance(m_AnimationStartPos, TargetPos);
// move time
m_MoveTime += clamp(Client()->RenderFrameTime(), 0.0f, 0.1f) * g_Config.m_ClCameraSpeed / 10.0f;
float XVal = 1 - m_MoveTime;
XVal = pow(XVal, 7.0f);
m_Camera.m_Center = TargetPos + Dir * (XVal * Distance);
}
CMapLayers::OnRender();
return true;
}
CCamera *CMenuBackground::GetCurCamera()
{
return &m_Camera;
}
void CMenuBackground::ChangePosition(int PositionNumber)
{
if(PositionNumber != m_CurrentPosition)
{
if(PositionNumber >= POS_START && PositionNumber < NUM_POS)
{
m_CurrentPosition = PositionNumber;
}
else
{
m_CurrentPosition = POS_START;
}
}
m_AnimationStartPos = m_Camera.m_Center;
m_RotationCenter = m_Positions[m_CurrentPosition];
m_MoveTime = 0.0f;
}
std::vector<CTheme> &CMenuBackground::GetThemes()
{
if(m_lThemes.size() == 0) // not loaded yet
{
// when adding more here, make sure to change the value of PREDEFINED_THEMES_COUNT too
m_lThemes.push_back(CTheme("", true, true)); // no theme
m_lThemes.push_back(CTheme("auto", true, true)); // auto theme
m_lThemes.push_back(CTheme("rand", true, true)); // random theme
Storage()->ListDirectory(IStorage::TYPE_ALL, "themes", ThemeScan, (CMenuBackground *)this);
Storage()->ListDirectory(IStorage::TYPE_ALL, "themes", ThemeIconScan, (CMenuBackground *)this);
std::sort(m_lThemes.begin() + PREDEFINED_THEMES_COUNT, m_lThemes.end());
}
return m_lThemes;
}

View file

@ -0,0 +1,110 @@
#ifndef GAME_CLIENT_COMPONENTS_MENU_BACKGROUND_H
#define GAME_CLIENT_COMPONENTS_MENU_BACKGROUND_H
#include <game/client/components/background.h>
#include <game/client/components/camera.h>
#include <vector>
class CMenuMap : public CBackgroundEngineMap
{
MACRO_INTERFACE("menu_enginemap", 0)
};
// themes
class CTheme
{
public:
CTheme() {}
CTheme(const char *n, bool HasDay, bool HasNight)
: m_Name(n), m_HasDay(HasDay), m_HasNight(HasNight) {}
string m_Name;
bool m_HasDay;
bool m_HasNight;
IGraphics::CTextureHandle m_IconTexture;
bool operator<(const CTheme &Other) const { return m_Name < Other.m_Name; }
};
class CMenuBackground : public CBackground
{
public:
enum
{
POS_START = 0,
POS_INTERNET,
POS_LAN,
POS_DEMOS,
POS_NEWS,
POS_FAVORITES,
POS_SETTINGS_LANGUAGE,
POS_SETTINGS_GENERAL,
POS_SETTINGS_PLAYER,
POS_SETTINGS_TEE,
POS_SETTINGS_HUD,
POS_SETTINGS_CONTROLS,
POS_SETTINGS_GRAPHICS,
POS_SETTINGS_SOUND,
POS_SETTINGS_DDNET,
POS_CUSTOM,
POS_CUSTOM0 = POS_CUSTOM, // ddnet tab
POS_CUSTOM1, // kog tab
POS_CUSTOM2,
POS_CUSTOM3,
POS_CUSTOM4,
POS_CUSTOM5,
POS_CUSTOM6,
POS_CUSTOM7,
POS_CUSTOM8,
POS_CUSTOM9,
NUM_POS,
POS_CUSTOM_NUM = (POS_CUSTOM9 - POS_CUSTOM0) + 1,
};
enum
{
PREDEFINED_THEMES_COUNT = 3,
};
CCamera m_Camera;
CBackgroundEngineMap *CreateBGMap() override;
vec2 m_MenuCenter;
vec2 m_RotationCenter;
vec2 m_Positions[NUM_POS];
int m_CurrentPosition;
vec2 m_AnimationStartPos;
float m_MoveTime;
bool m_IsInit;
void ResetPositions();
static int ThemeScan(const char *pName, int IsDir, int DirType, void *pUser);
static int ThemeIconScan(const char *pName, int IsDir, int DirType, void *pUser);
std::vector<CTheme> m_lThemes;
public:
CMenuBackground();
~CMenuBackground() override {}
void OnInit() override;
void OnMapLoad() override;
void OnRender() override;
void LoadMenuBackground(bool HasDayHint = true, bool HasNightHint = true);
bool Render();
class CCamera *GetCurCamera() override;
void ChangePosition(int PositionNumber);
std::vector<CTheme> &GetThemes();
};
#endif

View file

@ -1,6 +1,8 @@
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <vector>
#include <base/tl/array.h>
#include <math.h>
@ -27,6 +29,7 @@
#include <game/client/components/binds.h>
#include <game/client/components/console.h>
#include <game/client/components/menu_background.h>
#include <game/client/components/sounds.h>
#include <game/client/gameclient.h>
#include <game/client/lineinput.h>
@ -1002,7 +1005,10 @@ void CMenus::RenderLoading()
CUIRect Screen = *UI()->Screen();
Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
RenderBackground();
if(!m_pBackground->Render())
{
RenderBackground();
}
float w = 700;
float h = 200;
@ -1164,7 +1170,10 @@ int CMenus::Render()
}
else
{
RenderBackground();
if(!m_pBackground->Render())
{
RenderBackground();
}
ms_ColorTabbarInactive = ms_ColorTabbarInactiveOutgame;
ms_ColorTabbarActive = ms_ColorTabbarActiveOutgame;
ms_ColorTabbarHover = ms_ColorTabbarHoverOutgame;
@ -1187,7 +1196,10 @@ int CMenus::Render()
if(m_Popup == POPUP_NONE)
{
if(m_ShowStart && Client()->State() == IClient::STATE_OFFLINE)
{
m_pBackground->ChangePosition(CMenuBackground::POS_START);
RenderStartMenu(Screen);
}
else
{
Screen.HSplitTop(24.0f, &TabBar, &MainView);
@ -1224,21 +1236,44 @@ int CMenus::Render()
RenderSettings(MainView);
}
else if(m_MenuPage == PAGE_NEWS)
{
m_pBackground->ChangePosition(CMenuBackground::POS_NEWS);
RenderNews(MainView);
}
else if(m_MenuPage == PAGE_INTERNET)
{
m_pBackground->ChangePosition(CMenuBackground::POS_INTERNET);
RenderServerbrowser(MainView);
}
else if(m_MenuPage == PAGE_LAN)
{
m_pBackground->ChangePosition(CMenuBackground::POS_LAN);
RenderServerbrowser(MainView);
}
else if(m_MenuPage == PAGE_DEMOS)
{
m_pBackground->ChangePosition(CMenuBackground::POS_DEMOS);
RenderDemoList(MainView);
}
else if(m_MenuPage == PAGE_FAVORITES)
{
m_pBackground->ChangePosition(CMenuBackground::POS_FAVORITES);
RenderServerbrowser(MainView);
}
else if(m_MenuPage == PAGE_DDNET)
{
m_pBackground->ChangePosition(CMenuBackground::POS_CUSTOM0);
RenderServerbrowser(MainView);
}
else if(m_MenuPage == PAGE_KOG)
{
m_pBackground->ChangePosition(CMenuBackground::POS_CUSTOM0 + 1);
RenderServerbrowser(MainView);
}
else if(m_MenuPage == PAGE_SETTINGS)
{
RenderSettings(MainView);
}
// do tab bar
RenderMenubar(TabBar);
@ -2013,6 +2048,78 @@ int CMenus::Render()
return 0;
}
void CMenus::RenderThemeSelection(CUIRect MainView, bool Header)
{
std::vector<CTheme> &ThemesRef = m_pBackground->GetThemes();
int SelectedTheme = -1;
for(int i = 0; i < (int)ThemesRef.size(); i++)
{
if(str_comp(ThemesRef[i].m_Name, g_Config.m_ClMenuMap) == 0)
{
SelectedTheme = i;
break;
}
}
static int s_ListBox = 0;
static float s_ScrollValue = 0.0f;
UiDoListboxStart(&s_ListBox, &MainView, 26.0f, Localize("Theme"), "", ThemesRef.size(), 1, -1, s_ScrollValue);
for(int i = 0; i < (int)ThemesRef.size(); i++)
{
CListboxItem Item = UiDoListboxNextItem(&ThemesRef[i].m_Name, i == SelectedTheme);
CTheme &Theme = ThemesRef[i];
if(!Item.m_Visible)
continue;
CUIRect Icon;
Item.m_Rect.VSplitLeft(Item.m_Rect.h * 2.0f, &Icon, &Item.m_Rect);
// draw icon if it exists
if(Theme.m_IconTexture != -1)
{
Icon.VMargin(6.0f, &Icon);
Icon.HMargin(3.0f, &Icon);
Graphics()->TextureSet(Theme.m_IconTexture);
Graphics()->QuadsBegin();
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
IGraphics::CQuadItem QuadItem(Icon.x, Icon.y, Icon.w, Icon.h);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
}
char aName[128];
if(!Theme.m_Name[0])
str_copy(aName, "(none)", sizeof(aName));
else if(str_comp(Theme.m_Name, "auto") == 0)
str_copy(aName, "(seasons)", sizeof(aName));
else if(str_comp(Theme.m_Name, "rand") == 0)
str_copy(aName, "(random)", sizeof(aName));
else if(Theme.m_HasDay && Theme.m_HasNight)
str_format(aName, sizeof(aName), "%s", Theme.m_Name.cstr());
else if(Theme.m_HasDay && !Theme.m_HasNight)
str_format(aName, sizeof(aName), "%s (day)", Theme.m_Name.cstr());
else if(!Theme.m_HasDay && Theme.m_HasNight)
str_format(aName, sizeof(aName), "%s (night)", Theme.m_Name.cstr());
else // generic
str_format(aName, sizeof(aName), "%s", Theme.m_Name.cstr());
UI()->DoLabel(&Item.m_Rect, aName, 16 * ms_FontmodHeight, -1);
}
bool ItemActive = false;
int NewSelected = UiDoListboxEnd(&s_ScrollValue, 0, &ItemActive);
if(ItemActive && NewSelected != SelectedTheme)
{
str_format(g_Config.m_ClMenuMap, sizeof(g_Config.m_ClMenuMap), "%s", ThemesRef[NewSelected].m_Name.cstr());
m_pBackground->LoadMenuBackground(ThemesRef[NewSelected].m_HasDay, ThemesRef[NewSelected].m_HasNight);
}
}
void CMenus::SetActive(bool Active)
{
if(Active != m_MenuActive)

View file

@ -326,6 +326,7 @@ class CMenus : public CComponent
// found in menus_settings.cpp
void RenderLanguageSelection(CUIRect MainView);
void RenderThemeSelection(CUIRect MainView, bool Header = true);
void RenderSettingsGeneral(CUIRect MainView);
void RenderSettingsPlayer(CUIRect MainView);
void RenderSettingsDummyPlayer(CUIRect MainView);
@ -341,9 +342,13 @@ class CMenus : public CComponent
bool CheckHotKey(int Key) const;
class CMenuBackground *m_pBackground;
public:
void RenderBackground();
void SetMenuBackground(class CMenuBackground *pBackground) { m_pBackground = pBackground; }
void UseMouseButtons(bool Use) { m_UseMouseButtons = Use; }
static CMenusKeyBinder m_Binder;

View file

@ -17,11 +17,12 @@
#include <game/generated/protocol.h>
#include <game/generated/client_data.h>
#include <game/client/components/sounds.h>
#include <game/client/ui.h>
#include <game/client/render.h>
#include <game/client/gameclient.h>
#include <game/client/animstate.h>
#include <game/client/components/menu_background.h>
#include <game/client/components/sounds.h>
#include <game/client/gameclient.h>
#include <game/client/render.h>
#include <game/client/ui.h>
#include <game/localization.h>
#include "binds.h"
@ -74,9 +75,8 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
#endif
char aBuf[128];
CUIRect Label, Button, Left, Right, Game, Client, AutoReconnect;
MainView.HSplitTop(180.0f, &Game, &Client);
Client.HSplitTop(160.0f, &Client, &AutoReconnect);
CUIRect Label, Button, Left, Right, Game, Client;
MainView.HSplitTop(150.0f, &Game, &Client);
// game
{
@ -178,6 +178,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
if(DoButton_CheckBox(&g_Config.m_ClAutoDemoRecord, Localize("Automatically record demos"), g_Config.m_ClAutoDemoRecord, &Button))
g_Config.m_ClAutoDemoRecord ^= 1;
Right.HSplitTop(30.0f, 0, &Right);
Right.HSplitTop(20.0f, &Button, &Right);
if(DoButton_CheckBox(&g_Config.m_ClAutoScreenshot, Localize("Automatically take game over screenshot"), g_Config.m_ClAutoScreenshot, &Button))
g_Config.m_ClAutoScreenshot ^= 1;
@ -217,12 +218,11 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
else
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Refresh Rate"), "");
UI()->DoLabelScaled(&Label, aBuf, 13.0f, -1);
Left.HSplitTop(20.0f, &Button, 0);
Left.HSplitTop(20.0f, &Button, &Left);
Button.HMargin(2.0f, &Button);
g_Config.m_ClRefreshRate= static_cast<int>(DoScrollbarH(&g_Config.m_ClRefreshRate, &Button, g_Config.m_ClRefreshRate/10000.0f)*10000.0f+0.1f);
#if defined(CONF_FAMILY_WINDOWS)
Left.HSplitTop(20.0f, 0, &Left);
Left.HSplitTop(20.0f, &Button, &Left);
if(DoButton_CheckBox(&g_Config.m_ClShowConsole, Localize("Show console window"), g_Config.m_ClShowConsole, &Button))
{
@ -234,6 +234,9 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
m_NeedRestartGeneral = s_ClShowConsole != g_Config.m_ClShowConsole;
#endif
Left.HSplitTop(20.0f, 0, &Left);
RenderThemeSelection(Left);
// auto statboard screenshot
{
Right.HSplitTop(20.0f, 0, &Right); //
@ -1398,23 +1401,50 @@ void CMenus::RenderSettings(CUIRect MainView)
MainView.Margin(10.0f, &MainView);
if(g_Config.m_UiSettingsPage == SETTINGS_LANGUAGE)
{
m_pBackground->ChangePosition(CMenuBackground::POS_SETTINGS_LANGUAGE);
RenderLanguageSelection(MainView);
}
else if(g_Config.m_UiSettingsPage == SETTINGS_GENERAL)
{
m_pBackground->ChangePosition(CMenuBackground::POS_SETTINGS_GENERAL);
RenderSettingsGeneral(MainView);
}
else if(g_Config.m_UiSettingsPage == SETTINGS_PLAYER)
{
m_pBackground->ChangePosition(CMenuBackground::POS_SETTINGS_PLAYER);
RenderSettingsPlayer(MainView);
}
else if(g_Config.m_UiSettingsPage == SETTINGS_TEE)
{
m_pBackground->ChangePosition(CMenuBackground::POS_SETTINGS_TEE);
RenderSettingsTee(MainView);
}
else if(g_Config.m_UiSettingsPage == SETTINGS_HUD)
{
m_pBackground->ChangePosition(CMenuBackground::POS_SETTINGS_HUD);
RenderSettingsHUD(MainView);
}
else if(g_Config.m_UiSettingsPage == SETTINGS_CONTROLS)
{
m_pBackground->ChangePosition(CMenuBackground::POS_SETTINGS_CONTROLS);
RenderSettingsControls(MainView);
}
else if(g_Config.m_UiSettingsPage == SETTINGS_GRAPHICS)
{
m_pBackground->ChangePosition(CMenuBackground::POS_SETTINGS_GRAPHICS);
RenderSettingsGraphics(MainView);
}
else if(g_Config.m_UiSettingsPage == SETTINGS_SOUND)
{
m_pBackground->ChangePosition(CMenuBackground::POS_SETTINGS_SOUND);
RenderSettingsSound(MainView);
}
else if(g_Config.m_UiSettingsPage == SETTINGS_DDNET)
{
m_pBackground->ChangePosition(CMenuBackground::POS_SETTINGS_DDNET);
RenderSettingsDDNet(MainView);
}
if(m_NeedRestartUpdate)
{

View file

@ -50,11 +50,12 @@
#include "components/mapimages.h"
#include "components/maplayers.h"
#include "components/mapsounds.h"
#include "components/menu_background.h"
#include "components/menus.h"
#include "components/motd.h"
#include "components/nameplates.h"
#include "components/particles.h"
#include "components/players.h"
#include "components/nameplates.h"
#include "components/scoreboard.h"
#include "components/skins.h"
#include "components/sounds.h"
@ -101,6 +102,7 @@ static CMapImages gs_MapImages;
static CMapLayers gs_MapLayersBackGround(CMapLayers::TYPE_BACKGROUND);
static CMapLayers gs_MapLayersForeGround(CMapLayers::TYPE_FOREGROUND);
static CBackground gs_BackGround;
static CMenuBackground gs_MenuBackground;
static CMapSounds gs_MapSounds;
@ -135,6 +137,7 @@ void CGameClient::OnConsoleInit()
#endif
// setup pointers
m_pMenuBackground = &::gs_MenuBackground;
m_pBinds = &::gs_Binds;
m_pGameConsole = &::gs_GameConsole;
m_pParticles = &::gs_Particles;
@ -164,6 +167,8 @@ void CGameClient::OnConsoleInit()
m_pRaceDemo = &::gs_RaceDemo;
m_pGhost = &::gs_Ghost;
m_pMenus->SetMenuBackground(m_pMenuBackground);
gs_NamePlates.SetPlayers(m_pPlayers);
// make a list of all the systems, make sure to add them in the correct render order
@ -207,6 +212,8 @@ void CGameClient::OnConsoleInit()
m_All.Add(&m_pMenus->m_Binder);
m_All.Add(m_pGameConsole);
m_All.Add(m_pMenuBackground);
// build the input stack
m_Input.Add(&m_pMenus->m_Binder); // this will take over all input when we want to bind a key
m_Input.Add(&m_pBinds->m_SpecialBinds);
@ -272,6 +279,8 @@ void CGameClient::OnConsoleInit()
Console()->Chain("cl_dummy", ConchainSpecialDummy, this);
Console()->Chain("cl_text_entities_size", ConchainClTextEntitiesSize, this);
Console()->Chain("cl_menu_map", ConchainMenuMap, this);
//
m_SuppressEvents = false;
}
@ -2536,3 +2545,18 @@ void CGameClient::ConTuneZone(IConsole::IResult *pResult, void *pUserData)
if(List >= 0 && List < NUM_TUNEZONES)
pSelf->TuningList()[List].Set(pParamName, NewValue);
}
void CGameClient::ConchainMenuMap(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
CGameClient *pSelf = (CGameClient *)pUserData;
if(pResult->NumArguments())
{
if(str_comp(g_Config.m_ClMenuMap, pResult->GetString(0)) != 0)
{
str_format(g_Config.m_ClMenuMap, sizeof(g_Config.m_ClMenuMap), "%s", pResult->GetString(0));
pSelf->m_pMenuBackground->LoadMenuBackground();
}
}
else
pfnCallback(pResult, pCallbackUserData);
}

View file

@ -122,6 +122,8 @@ class CGameClient : public IGameClient
static void ConTuneZone(IConsole::IResult *pResult, void *pUserData);
static void ConchainMenuMap(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
public:
IKernel *Kernel() { return IInterface::Kernel(); }
IEngine *Engine() const { return m_pEngine; }
@ -377,6 +379,7 @@ public:
void SendKill(int ClientID);
// pointers to all systems
class CMenuBackground *m_pMenuBackground;
class CGameConsole *m_pGameConsole;
class CBinds *m_pBinds;
class CParticles *m_pParticles;