2022-06-20 09:55:55 +00:00
|
|
|
#include <algorithm>
|
2022-06-21 12:35:55 +00:00
|
|
|
#include <base/logger.h>
|
2022-03-16 16:01:23 +00:00
|
|
|
#include <base/system.h>
|
|
|
|
#include <engine/shared/datafile.h>
|
|
|
|
#include <engine/storage.h>
|
|
|
|
#include <game/gamecore.h>
|
|
|
|
#include <game/mapitems.h>
|
2022-06-20 09:55:55 +00:00
|
|
|
#define INEXISTENT INT_MAX
|
2022-03-16 16:01:23 +00:00
|
|
|
|
|
|
|
// global new layers data (set by ReplaceAreaTiles and ReplaceAreaQuads)
|
|
|
|
void *g_pNewData[1024];
|
|
|
|
void *g_pNewItem[1024];
|
2022-06-20 09:55:55 +00:00
|
|
|
int g_pNewDataSize[1024];
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-20 09:55:55 +00:00
|
|
|
struct MapObject // quad pivot or tile layer
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
static constexpr float m_pStandardScreen[2] = {1430 / 2, 1050 / 2};
|
|
|
|
|
|
|
|
float m_pLayerOffset[2];
|
2022-06-21 13:21:33 +00:00
|
|
|
bool m_UseClipping;
|
2022-06-21 12:47:27 +00:00
|
|
|
float m_pClipArea[2][2];
|
|
|
|
float m_pSpeed[2];
|
|
|
|
float m_pScreenOffset[2][2];
|
2022-06-21 13:21:33 +00:00
|
|
|
float m_pBaseArea[2][2]; // adapted to offset
|
|
|
|
float m_pExtendedArea[2][2]; // extended with parallax
|
2022-06-20 09:55:55 +00:00
|
|
|
};
|
|
|
|
|
2022-06-21 13:21:33 +00:00
|
|
|
bool ReplaceArea(IStorage *, const char[][64], const float[][2][2]);
|
|
|
|
bool OpenMaps(IStorage *, const char[][64], CDataFileReader[], CDataFileWriter &);
|
|
|
|
void SaveOutputMap(CDataFileReader &, CDataFileWriter &);
|
2022-03-16 16:01:23 +00:00
|
|
|
bool CompareLayers(const char[][64], CDataFileReader[]);
|
2022-06-20 09:55:55 +00:00
|
|
|
void CompareGroups(const char[][64], CDataFileReader[]);
|
2022-06-21 15:13:57 +00:00
|
|
|
const CMapItemGroup *GetLayerGroup(CDataFileReader &, int);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 13:21:33 +00:00
|
|
|
void ReplaceAreaTiles(CDataFileReader[], const float[][2][2], const CMapItemGroup *[], CMapItemLayer *[]);
|
|
|
|
void RemoveDestinationTiles(CMapItemLayerTilemap *, CTile *, float[][2]);
|
|
|
|
void ReplaceDestinationTiles(CMapItemLayerTilemap *[], CTile *[], float[][2][2]);
|
2022-06-20 09:55:55 +00:00
|
|
|
bool AdaptVisibleAreas(const float[][2][2], const MapObject[], float[][2][2]);
|
|
|
|
bool AdaptReplaceableAreas(const float[][2][2], const float[][2][2], const MapObject[], float[][2][2]);
|
|
|
|
|
2022-06-21 15:13:57 +00:00
|
|
|
void ReplaceAreaQuads(CDataFileReader[], const float[][2][2], const CMapItemGroup *[], CMapItemLayer *[], int);
|
|
|
|
bool RemoveDestinationQuads(const float[][2], const CQuad *, int, const CMapItemGroup *, CQuad *, int &);
|
|
|
|
bool InsertDestinationQuads(const float[][2][2], const CQuad *, int, const CMapItemGroup *[], CQuad *, int &);
|
2022-06-21 13:21:33 +00:00
|
|
|
bool AdaptVisiblePoint(const float[][2][2], const float[][2], const MapObject[], float[]);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 15:13:57 +00:00
|
|
|
MapObject CreateMapObject(const CMapItemGroup *, int, int, int, int);
|
2022-06-21 13:21:33 +00:00
|
|
|
void SetExtendedArea(MapObject &);
|
2022-06-21 15:13:57 +00:00
|
|
|
bool GetVisibleArea(const float[][2], MapObject, float[][2] = 0x0);
|
|
|
|
bool GetReplaceableArea(const float[][2], MapObject, float[][2]);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
|
|
|
void GetGameAreaDistance(const float[][2][2], const MapObject[], const float[][2][2], float[]);
|
|
|
|
void GetGameAreaDistance(const float[][2][2], const MapObject[], const float[][2], float[]);
|
|
|
|
void GetSignificantScreenPos(const MapObject, const float[][2], const float[][2], float[]);
|
|
|
|
void ConvertToTiles(const float[][2], int[][2]);
|
|
|
|
|
|
|
|
bool GetLineIntersection(const float[], const float[], float[] = 0x0);
|
2022-06-21 15:13:57 +00:00
|
|
|
bool GetLineIntersection(const float[], float);
|
|
|
|
void SetInexistent(float *, int);
|
|
|
|
bool IsInexistent(const float *, int);
|
|
|
|
bool IsInexistent(float);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-03-16 16:01:23 +00:00
|
|
|
int main(int argc, const char *argv[])
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
CCmdlineFix CmdlineFix(&argc, &argv);
|
|
|
|
log_set_global_logger_default();
|
|
|
|
|
|
|
|
if(argc != 10)
|
|
|
|
{
|
|
|
|
dbg_msg("map_replace_area", "Invalid arguments");
|
|
|
|
dbg_msg("map_replace_area", "Usage: %s <from_map> <from_x> <from_y> <to_map> <to_x> <to_y> <width> <height> <output_map>", argv[0]);
|
|
|
|
dbg_msg("map_replace_area", "Note: use game layer tiles as a reference for both coordinates and sizes");
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char pMapNames[3][64];
|
2022-06-21 15:13:57 +00:00
|
|
|
snprintf(pMapNames[0], 64, "%s", argv[1]); //from_map
|
|
|
|
snprintf(pMapNames[1], 64, "%s", argv[4]); //to_map
|
|
|
|
snprintf(pMapNames[2], 64, "%s", argv[9]); //output_map
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
float pGameAreas[2][2][2];
|
|
|
|
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
pGameAreas[i][0][0] = atof(argv[2 + i * 3]) * 32; //x
|
|
|
|
pGameAreas[i][1][0] = atof(argv[3 + i * 3]) * 32; //y
|
2022-06-21 13:21:33 +00:00
|
|
|
pGameAreas[i][0][1] = pGameAreas[i][0][0] + atof(argv[7]) * 32; //x + width
|
|
|
|
pGameAreas[i][1][1] = pGameAreas[i][1][0] + atof(argv[8]) * 32; //y + height
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cmdline_free(argc, argv);
|
|
|
|
|
|
|
|
dbg_msg("map_replace_area", "from_map='%s'; to_map='%s'; from_area='%fx,%fy'; to_area='%fx,%fy'; area_width='%fpx'; area_heigth='%fpx'; output_map='%s'",
|
|
|
|
pMapNames[0], pMapNames[1], pGameAreas[0][0][0], pGameAreas[0][1][0], pGameAreas[1][0][0], pGameAreas[1][1][0],
|
|
|
|
pGameAreas[0][0][1] - pGameAreas[0][0][0], pGameAreas[0][1][1] - pGameAreas[0][1][0], pMapNames[2]);
|
|
|
|
|
|
|
|
IStorage *pStorage = CreateLocalStorage();
|
|
|
|
for(int i = 0; i < 1024; i++)
|
|
|
|
{
|
|
|
|
g_pNewData[i] = g_pNewItem[i] = 0;
|
|
|
|
g_pNewDataSize[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ReplaceArea(pStorage, pMapNames, pGameAreas) ? 0 : 1;
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-06-20 09:55:55 +00:00
|
|
|
bool ReplaceArea(IStorage *pStorage, const char pMapNames[3][64], const float pGameAreas[][2][2])
|
2022-03-16 16:01:23 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
CDataFileReader InputMaps[2];
|
|
|
|
CDataFileWriter OutputMap;
|
|
|
|
|
|
|
|
if(!OpenMaps(pStorage, pMapNames, InputMaps, OutputMap))
|
|
|
|
return false;
|
|
|
|
if(!CompareLayers(pMapNames, InputMaps))
|
|
|
|
return false;
|
|
|
|
CompareGroups(pMapNames, InputMaps);
|
|
|
|
|
|
|
|
int LayersStart[2], LayersCount;
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
InputMaps[i].GetType(MAPITEMTYPE_LAYER, &LayersStart[i], &LayersCount);
|
|
|
|
|
|
|
|
for(int i = 0; i < LayersCount; i++)
|
|
|
|
{
|
|
|
|
const CMapItemGroup *pLayerGroups[2];
|
|
|
|
CMapItemLayer *pItem[2];
|
|
|
|
for(int j = 0; j < 2; j++)
|
|
|
|
{
|
|
|
|
pLayerGroups[j] = GetLayerGroup(InputMaps[j], i + 1);
|
|
|
|
pItem[j] = (CMapItemLayer *)InputMaps[j].GetItem(LayersStart[j] + i, 0, 0);
|
|
|
|
}
|
|
|
|
|
2022-06-21 15:13:57 +00:00
|
|
|
if(!pLayerGroups[0] || !pLayerGroups[1])
|
|
|
|
continue;
|
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
if(pItem[0]->m_Type == LAYERTYPE_TILES)
|
|
|
|
ReplaceAreaTiles(InputMaps, pGameAreas, pLayerGroups, pItem);
|
|
|
|
else if(pItem[0]->m_Type == LAYERTYPE_QUADS)
|
|
|
|
ReplaceAreaQuads(InputMaps, pGameAreas, pLayerGroups, pItem, LayersStart[1] + i);
|
|
|
|
}
|
|
|
|
|
|
|
|
SaveOutputMap(InputMaps[1], OutputMap);
|
|
|
|
|
|
|
|
return true;
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-06-20 09:55:55 +00:00
|
|
|
bool OpenMaps(IStorage *pStorage, const char pMapNames[3][64], CDataFileReader InputMaps[2], CDataFileWriter &OutputMap)
|
2022-03-16 16:01:23 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if(!InputMaps[i].Open(pStorage, pMapNames[i], IStorage::TYPE_ABSOLUTE))
|
|
|
|
{
|
2022-06-21 15:13:57 +00:00
|
|
|
dbg_msg("map_replace_area", "ERROR: unable to open map '%s'", pMapNames[i]);
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!OutputMap.Open(pStorage, pMapNames[2], IStorage::TYPE_ABSOLUTE))
|
|
|
|
{
|
2022-06-21 15:13:57 +00:00
|
|
|
dbg_msg("map_replace_area", "ERROR: unable to open map '%s'", pMapNames[2]);
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-06-20 09:55:55 +00:00
|
|
|
void SaveOutputMap(CDataFileReader &InputMap, CDataFileWriter &OutputMap)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < InputMap.NumItems(); i++)
|
|
|
|
{
|
|
|
|
int ID, Type;
|
|
|
|
void *pItem = InputMap.GetItem(i, &Type, &ID);
|
|
|
|
|
|
|
|
if(Type == ITEMTYPE_EX)
|
|
|
|
continue;
|
|
|
|
if(g_pNewItem[i])
|
|
|
|
pItem = g_pNewItem[i];
|
|
|
|
|
|
|
|
int Size = InputMap.GetItemSize(i);
|
|
|
|
OutputMap.AddItem(Type, ID, Size, pItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int i = 0; i < InputMap.NumData(); i++)
|
|
|
|
{
|
|
|
|
void *pData = g_pNewData[i] ? g_pNewData[i] : InputMap.GetData(i);
|
|
|
|
int Size = g_pNewDataSize[i] ? g_pNewDataSize[i] : InputMap.GetDataSize(i);
|
|
|
|
OutputMap.AddData(Size, pData);
|
|
|
|
}
|
|
|
|
|
|
|
|
OutputMap.Finish();
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-03-16 16:01:23 +00:00
|
|
|
bool CompareLayers(const char pMapNames[3][64], CDataFileReader InputMaps[2])
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
int Start[2], Num[2];
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
InputMaps[i].GetType(MAPITEMTYPE_LAYER, &Start[i], &Num[i]);
|
|
|
|
|
|
|
|
if(Num[0] != Num[1])
|
|
|
|
{
|
2022-06-21 15:13:57 +00:00
|
|
|
dbg_msg("map_replace_area", "ERROR: different layers quantity");
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
dbg_msg("map_replace_area", " \"%s\": %d layers", pMapNames[i], Num[i]);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int i = 0; i < Num[0]; i++)
|
|
|
|
{
|
|
|
|
CMapItemLayer *pItem[2];
|
|
|
|
for(int j = 0; j < 2; j++)
|
|
|
|
pItem[j] = (CMapItemLayer *)InputMaps[j].GetItem(Start[j] + i, 0, 0);
|
|
|
|
|
|
|
|
if(pItem[0]->m_Type != pItem[1]->m_Type)
|
|
|
|
{
|
2022-06-21 15:13:57 +00:00
|
|
|
dbg_msg("map_replace_area", "ERROR: different types on layer #%d", i);
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int j = 0; j < 2; j++)
|
2022-06-21 15:13:57 +00:00
|
|
|
dbg_msg("map_replace_area", " \"%s\": %s", pMapNames[j], pItem[j]->m_Type == LAYERTYPE_TILES ? "tiles layer" : "quad layer");
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-06-20 09:55:55 +00:00
|
|
|
void CompareGroups(const char pMapNames[3][64], CDataFileReader InputMaps[2])
|
2022-03-16 16:01:23 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
int Start[2], Num[2];
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
InputMaps[i].GetType(MAPITEMTYPE_GROUP, &Start[i], &Num[i]);
|
|
|
|
|
|
|
|
for(int i = 0; i < std::max(Num[0], Num[1]); i++)
|
|
|
|
{
|
|
|
|
CMapItemGroup *pItem[2];
|
|
|
|
for(int j = 0; j < 2; j++)
|
|
|
|
pItem[j] = (CMapItemGroup *)InputMaps[j].GetItem(Start[j] + i, 0, 0);
|
|
|
|
|
2022-06-21 13:21:33 +00:00
|
|
|
bool bSameConfig = pItem[0]->m_ParallaxX == pItem[1]->m_ParallaxX && pItem[0]->m_ParallaxY == pItem[1]->m_ParallaxY && pItem[0]->m_OffsetX == pItem[1]->m_OffsetX && pItem[0]->m_OffsetY == pItem[1]->m_OffsetY && pItem[0]->m_UseClipping == pItem[1]->m_UseClipping && pItem[0]->m_ClipX == pItem[1]->m_ClipX && pItem[0]->m_ClipY == pItem[1]->m_ClipY && pItem[0]->m_ClipW == pItem[1]->m_ClipW && pItem[0]->m_ClipH == pItem[1]->m_ClipH;
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
if(!bSameConfig)
|
2022-06-21 15:13:57 +00:00
|
|
|
dbg_msg("map_replace_area", "WARNING: different configuration on layergroup #%d, this might lead to unexpected results", i);
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 13:21:33 +00:00
|
|
|
const CMapItemGroup *GetLayerGroup(CDataFileReader &InputMap, const int LayerNumber)
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
int Start, Num;
|
|
|
|
InputMap.GetType(MAPITEMTYPE_GROUP, &Start, &Num);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < Num; i++)
|
|
|
|
{
|
|
|
|
CMapItemGroup *pItem = (CMapItemGroup *)InputMap.GetItem(Start + i, 0, 0);
|
|
|
|
if(LayerNumber >= pItem->m_StartLayer && LayerNumber <= pItem->m_StartLayer + pItem->m_NumLayers)
|
|
|
|
return pItem;
|
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
return 0x0;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ReplaceAreaTiles(CDataFileReader InputMaps[2], const float pGameAreas[][2][2], const CMapItemGroup *pLayerGroups[2], CMapItemLayer *pItem[2])
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
CMapItemLayerTilemap *pTilemap[2];
|
|
|
|
CTile *pTile[2];
|
|
|
|
float pVisibleAreas[2][2][2], pReplaceableAreas[2][2][2];
|
|
|
|
MapObject Obs[2];
|
|
|
|
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
pTilemap[i] = (CMapItemLayerTilemap *)pItem[i];
|
|
|
|
pTile[i] = (CTile *)InputMaps[i].GetData(pTilemap[i]->m_Data);
|
|
|
|
Obs[i] = CreateMapObject(pLayerGroups[i], 0, 0, pTilemap[i]->m_Width * 32, pTilemap[i]->m_Height * 32);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!GetVisibleArea(pGameAreas[1], Obs[1], pVisibleAreas[1]))
|
|
|
|
return;
|
|
|
|
|
|
|
|
GetReplaceableArea(pVisibleAreas[1], Obs[1], pReplaceableAreas[1]);
|
|
|
|
RemoveDestinationTiles(pTilemap[1], pTile[1], pReplaceableAreas[1]);
|
|
|
|
|
|
|
|
if(GetVisibleArea(pGameAreas[0], Obs[0], pVisibleAreas[0]) && AdaptVisibleAreas(pGameAreas, Obs, pVisibleAreas))
|
|
|
|
{
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
GetReplaceableArea(pVisibleAreas[i], Obs[i], pReplaceableAreas[i]);
|
|
|
|
|
|
|
|
if(AdaptReplaceableAreas(pGameAreas, pVisibleAreas, Obs, pReplaceableAreas))
|
|
|
|
ReplaceDestinationTiles(pTilemap, pTile, pReplaceableAreas);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_pNewData[pTilemap[1]->m_Data] = pTile[1];
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void RemoveDestinationTiles(CMapItemLayerTilemap *pTilemap, CTile *pTile, float pReplaceableArea[2][2])
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
int pRange[2][2];
|
|
|
|
ConvertToTiles(pReplaceableArea, pRange);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
CTile EmptyTile;
|
|
|
|
EmptyTile.m_Index = EmptyTile.m_Flags = EmptyTile.m_Skip = EmptyTile.m_Reserved = 0;
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int y = pRange[1][0]; y < pRange[1][1]; y++)
|
|
|
|
for(int x = pRange[0][0]; x < pRange[0][1]; x++)
|
|
|
|
pTile[x + (y * pTilemap->m_Width)] = EmptyTile;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ReplaceDestinationTiles(CMapItemLayerTilemap *pTilemap[2], CTile *pTile[2], float pReplaceableAreas[2][2][2])
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
int pRanges[2][2][2];
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
ConvertToTiles(pReplaceableAreas[i], pRanges[i]);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int y0 = pRanges[0][1][0], y1 = pRanges[1][1][0]; y0 < pRanges[0][1][1] && y1 < pRanges[1][1][1]; y0++, y1++)
|
|
|
|
for(int x0 = pRanges[0][0][0], x1 = pRanges[1][0][0]; x0 < pRanges[0][0][1] && x1 < pRanges[1][0][1]; x0++, x1++)
|
|
|
|
pTile[1][x1 + (y1 * pTilemap[1]->m_Width)] = pTile[0][x0 + (y0 * pTilemap[0]->m_Width)];
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool AdaptVisibleAreas(const float pGameAreas[2][2][2], const MapObject Obs[2], float pVisibleAreas[2][2][2])
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
float pDistance[2];
|
|
|
|
GetGameAreaDistance(pGameAreas, Obs, pVisibleAreas, pDistance);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if(Obs[0].m_pSpeed[i] == 1 || Obs[1].m_pSpeed[i] == 1)
|
|
|
|
continue;
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int j = 0; j < 2; j++)
|
|
|
|
pVisibleAreas[1][i][j] -= pDistance[i];
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
if(!GetLineIntersection(pVisibleAreas[0][i], pVisibleAreas[1][i], pVisibleAreas[0][i]))
|
|
|
|
return false;
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int j = 0; j < 2; j++)
|
|
|
|
pVisibleAreas[1][i][j] = pVisibleAreas[0][i][j] + pDistance[i];
|
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
return true;
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-06-20 09:55:55 +00:00
|
|
|
bool AdaptReplaceableAreas(const float pGameAreas[2][2][2], const float pVisibleAreas[2][2][2], const MapObject Obs[2], float pReplaceableAreas[2][2][2])
|
2022-03-16 16:01:23 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
float pDistance[2], pScreenPos[2];
|
|
|
|
GetGameAreaDistance(pGameAreas, Obs, pVisibleAreas, pDistance);
|
|
|
|
GetSignificantScreenPos(Obs[0], pVisibleAreas[0], pReplaceableAreas[0], pScreenPos);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
float pDestLine[2], pSourceLine[2], pVisibleLine[2];
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
pDestLine[0] = Obs[1].m_pBaseArea[i][0] + (pScreenPos[i] + pDistance[i]) * Obs[1].m_pSpeed[i];
|
|
|
|
pDestLine[1] = pDestLine[0] + (Obs[1].m_pBaseArea[i][1] - Obs[1].m_pBaseArea[i][0]);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
if(!GetLineIntersection(pDestLine, pVisibleAreas[1][i], pVisibleLine))
|
|
|
|
return false;
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
pSourceLine[0] = pVisibleAreas[0][i][0] + pDistance[i] - pReplaceableAreas[0][i][0];
|
|
|
|
pSourceLine[1] = pVisibleAreas[0][i][1] + pDistance[i] + pReplaceableAreas[0][i][1] - pReplaceableAreas[0][i][0];
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
if(!GetLineIntersection(pSourceLine, pVisibleLine, pVisibleLine))
|
|
|
|
return false;
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
pReplaceableAreas[0][i][0] = pVisibleLine[0] - pSourceLine[0];
|
|
|
|
pReplaceableAreas[1][i][0] = pVisibleLine[0] - pDestLine[0];
|
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
return true;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ReplaceAreaQuads(CDataFileReader InputMaps[2], const float pGameAreas[][2][2], const CMapItemGroup *pLayerGroups[2], CMapItemLayer *pItem[2], const int ItemNumber)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
CMapItemLayerQuads *pQuadLayer[2];
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
pQuadLayer[i] = (CMapItemLayerQuads *)pItem[i];
|
|
|
|
|
|
|
|
CQuad *pQuads[3];
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
pQuads[i] = (CQuad *)InputMaps[i].GetDataSwapped(pQuadLayer[i]->m_Data);
|
|
|
|
|
|
|
|
pQuads[2] = new CQuad[pQuadLayer[0]->m_NumQuads + pQuadLayer[1]->m_NumQuads];
|
|
|
|
int QuadsCounter = 0;
|
|
|
|
|
|
|
|
bool bDataChanged = RemoveDestinationQuads(pGameAreas[1], pQuads[1], pQuadLayer[1]->m_NumQuads, pLayerGroups[1], pQuads[2], QuadsCounter);
|
|
|
|
bDataChanged |= InsertDestinationQuads(pGameAreas, pQuads[0], pQuadLayer[0]->m_NumQuads, pLayerGroups, pQuads[2], QuadsCounter);
|
|
|
|
|
|
|
|
if(bDataChanged)
|
|
|
|
{
|
|
|
|
g_pNewData[pQuadLayer[1]->m_Data] = pQuads[2];
|
|
|
|
g_pNewDataSize[pQuadLayer[1]->m_Data] = ((int)sizeof(CQuad)) * QuadsCounter;
|
|
|
|
pQuadLayer[1]->m_NumQuads = QuadsCounter;
|
|
|
|
g_pNewItem[ItemNumber] = pItem[1];
|
|
|
|
}
|
|
|
|
else
|
2022-06-21 15:13:57 +00:00
|
|
|
delete[] pQuads[2];
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool RemoveDestinationQuads(const float pGameArea[2][2], const CQuad *pQuads, const int NumQuads, const CMapItemGroup *pLayerGroup, CQuad *pDestQuads, int &QuadsCounter)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
bool bDataChanged = false;
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < NumQuads; i++)
|
|
|
|
{
|
|
|
|
MapObject Ob = CreateMapObject(pLayerGroup, fx2f(pQuads[i].m_aPoints[4].x), fx2f(pQuads[i].m_aPoints[4].y), 0, 0);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
if(GetVisibleArea(pGameArea, Ob))
|
|
|
|
{
|
|
|
|
bDataChanged = true;
|
|
|
|
continue;
|
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
pDestQuads[QuadsCounter] = pQuads[i];
|
|
|
|
QuadsCounter++;
|
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
return bDataChanged;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool InsertDestinationQuads(const float pGameAreas[2][2][2], const CQuad *pQuads, const int NumQuads, const CMapItemGroup *pLayerGroups[2], CQuad *pDestQuads, int &QuadsCounter)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
bool bDataChanged = false;
|
|
|
|
|
|
|
|
for(int i = 0; i < NumQuads; i++)
|
|
|
|
{
|
|
|
|
MapObject Obs[2];
|
|
|
|
Obs[0] = CreateMapObject(pLayerGroups[0], fx2f(pQuads[i].m_aPoints[4].x), fx2f(pQuads[i].m_aPoints[4].y), 0, 0);
|
|
|
|
float pVisibleArea[2][2];
|
|
|
|
|
|
|
|
if(GetVisibleArea(pGameAreas[0], Obs[0], pVisibleArea))
|
|
|
|
{
|
|
|
|
float pQuadPos[2];
|
|
|
|
Obs[1] = CreateMapObject(pLayerGroups[1], 0, 0, 0, 0);
|
|
|
|
|
|
|
|
if(!AdaptVisiblePoint(pGameAreas, pVisibleArea, Obs, pQuadPos))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pDestQuads[QuadsCounter] = pQuads[i];
|
2022-06-21 15:13:57 +00:00
|
|
|
for(auto & m_aPoint : pDestQuads[QuadsCounter].m_aPoints)
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
2022-06-21 15:13:57 +00:00
|
|
|
m_aPoint.x += f2fx(pQuadPos[0]) - pDestQuads[QuadsCounter].m_aPoints[4].x;
|
|
|
|
m_aPoint.y += f2fx(pQuadPos[1]) - pDestQuads[QuadsCounter].m_aPoints[4].y;
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QuadsCounter++;
|
|
|
|
bDataChanged = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bDataChanged;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool AdaptVisiblePoint(const float pGameAreas[2][2][2], const float pVisibleArea[2][2], const MapObject Obs[2], float pPos[2])
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
float pDistance[2], pScreenPos[2];
|
|
|
|
GetGameAreaDistance(pGameAreas, Obs, pVisibleArea, pDistance);
|
|
|
|
GetSignificantScreenPos(Obs[0], pVisibleArea, 0x0, pScreenPos);
|
|
|
|
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
pPos[i] = pVisibleArea[i][0] + pDistance[i] + Obs[1].m_pLayerOffset[i] - (pScreenPos[i] + pDistance[i]) * Obs[1].m_pSpeed[i];
|
2022-06-21 13:21:33 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
MapObject FinalOb = Obs[1];
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
FinalOb.m_pBaseArea[i][0] = FinalOb.m_pBaseArea[i][1] += pPos[i];
|
|
|
|
SetExtendedArea(FinalOb);
|
|
|
|
|
|
|
|
return GetVisibleArea(pGameAreas[1], FinalOb);
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MapObject CreateMapObject(const CMapItemGroup *pLayerGroup, const int PosX, const int PosY, const int Width, const int Height)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
MapObject Ob;
|
|
|
|
|
2022-06-21 13:21:33 +00:00
|
|
|
Ob.m_pBaseArea[0][0] = PosX - pLayerGroup->m_OffsetX;
|
|
|
|
Ob.m_pBaseArea[1][0] = PosY - pLayerGroup->m_OffsetY;
|
|
|
|
Ob.m_pBaseArea[0][1] = Ob.m_pBaseArea[0][0] + Width;
|
|
|
|
Ob.m_pBaseArea[1][1] = Ob.m_pBaseArea[1][0] + Height;
|
|
|
|
Ob.m_pLayerOffset[0] = pLayerGroup->m_OffsetX;
|
|
|
|
Ob.m_pLayerOffset[1] = pLayerGroup->m_OffsetY;
|
|
|
|
Ob.m_UseClipping = pLayerGroup->m_UseClipping;
|
|
|
|
Ob.m_pClipArea[0][0] = pLayerGroup->m_ClipX;
|
|
|
|
Ob.m_pClipArea[1][0] = pLayerGroup->m_ClipY;
|
|
|
|
Ob.m_pClipArea[0][1] = pLayerGroup->m_ClipX + pLayerGroup->m_ClipW;
|
|
|
|
Ob.m_pClipArea[1][1] = pLayerGroup->m_ClipY + pLayerGroup->m_ClipH;
|
|
|
|
Ob.m_pSpeed[0] = 1 - (pLayerGroup->m_ParallaxX / 100.0f);
|
|
|
|
Ob.m_pSpeed[1] = 1 - (pLayerGroup->m_ParallaxY / 100.0f);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
Ob.m_pScreenOffset[i][0] = -Ob.m_pStandardScreen[i];
|
2022-06-21 13:21:33 +00:00
|
|
|
Ob.m_pScreenOffset[i][1] = Ob.m_pStandardScreen[i];
|
2022-06-21 12:47:27 +00:00
|
|
|
if(Ob.m_pSpeed[i] < 0)
|
|
|
|
std::swap(Ob.m_pScreenOffset[i][0], Ob.m_pScreenOffset[i][1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetExtendedArea(Ob);
|
|
|
|
return Ob;
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-06-20 09:55:55 +00:00
|
|
|
void SetExtendedArea(MapObject &Ob)
|
2022-03-16 16:01:23 +00:00
|
|
|
{
|
2022-06-21 13:21:33 +00:00
|
|
|
SetInexistent((float *)Ob.m_pExtendedArea, 4);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if(Ob.m_pSpeed[i] == 1)
|
2022-06-21 13:21:33 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
float pInspectedArea[2];
|
|
|
|
if(GetLineIntersection(Ob.m_pBaseArea[i], Ob.m_pScreenOffset[i], pInspectedArea))
|
|
|
|
memcpy(Ob.m_pExtendedArea[i], pInspectedArea, sizeof(float[2]));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int j = 0; j < 2; j++)
|
|
|
|
Ob.m_pExtendedArea[i][j] = (Ob.m_pBaseArea[i][j] + Ob.m_pScreenOffset[i][j] * Ob.m_pSpeed[i]) / (1 - Ob.m_pSpeed[i]);
|
2022-06-21 13:21:33 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
if(Ob.m_pExtendedArea[i][0] > Ob.m_pExtendedArea[i][1])
|
|
|
|
std::swap(Ob.m_pExtendedArea[i][0], Ob.m_pExtendedArea[i][1]);
|
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-06-20 09:55:55 +00:00
|
|
|
bool GetVisibleArea(const float pGameArea[2][2], const MapObject Ob, float pVisibleArea[2][2])
|
2022-03-16 16:01:23 +00:00
|
|
|
{
|
2022-06-21 13:21:33 +00:00
|
|
|
if(IsInexistent((float *)Ob.m_pExtendedArea, 4))
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
if(pVisibleArea)
|
2022-06-21 13:21:33 +00:00
|
|
|
SetInexistent((float *)pVisibleArea, 4);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
float pInspectedArea[2][2];
|
|
|
|
memcpy(pInspectedArea, pGameArea, sizeof(float[2][2]));
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if(Ob.m_pSpeed[i] == 1)
|
|
|
|
{
|
|
|
|
memcpy(pInspectedArea[i], Ob.m_pExtendedArea[i], sizeof(float[2]));
|
|
|
|
continue;
|
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
if(Ob.m_UseClipping && !GetLineIntersection(pInspectedArea[i], Ob.m_pClipArea[i], pInspectedArea[i]))
|
|
|
|
return false;
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
if(!GetLineIntersection(pInspectedArea[i], Ob.m_pExtendedArea[i], pInspectedArea[i]))
|
|
|
|
return false;
|
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
if(pVisibleArea)
|
|
|
|
memcpy(pVisibleArea, pInspectedArea, sizeof(float[2][2]));
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
return true;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GetReplaceableArea(const float pVisibleArea[2][2], const MapObject Ob, float pReplaceableArea[2][2])
|
|
|
|
{
|
2022-06-21 13:21:33 +00:00
|
|
|
SetInexistent((float *)pReplaceableArea, 4);
|
|
|
|
if(IsInexistent((float *)pVisibleArea, 4))
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
for(int i = 0; i < 2; i++)
|
2022-06-21 13:21:33 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
if(Ob.m_pSpeed[i] == 1)
|
|
|
|
{
|
|
|
|
pReplaceableArea[i][0] = pVisibleArea[i][0] - Ob.m_pBaseArea[i][0];
|
|
|
|
pReplaceableArea[i][1] = pVisibleArea[i][1] - Ob.m_pBaseArea[i][0];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int j = 0; j < 2; j++)
|
|
|
|
{
|
|
|
|
float pVisibleLine[2], pReplaceableLine[2];
|
|
|
|
int k = Ob.m_pSpeed[i] > 1 ? !j : j;
|
|
|
|
|
|
|
|
pVisibleLine[0] = Ob.m_pBaseArea[i][0] + (pVisibleArea[i][j] - Ob.m_pScreenOffset[i][k]) * Ob.m_pSpeed[i];
|
|
|
|
pVisibleLine[1] = pVisibleLine[0] + Ob.m_pBaseArea[i][1] - Ob.m_pBaseArea[i][0];
|
|
|
|
|
|
|
|
if(GetLineIntersection(pVisibleArea[i], pVisibleLine, pReplaceableLine))
|
|
|
|
pReplaceableArea[i][k] = pReplaceableLine[j] - pVisibleLine[0];
|
|
|
|
else
|
|
|
|
pReplaceableArea[i][k] = k * (Ob.m_pBaseArea[i][1] - Ob.m_pBaseArea[i][0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GetGameAreaDistance(const float pGameAreas[2][2][2], const MapObject Obs[2], const float pVisibleAreas[2][2][2], float pDistance[2])
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if(Obs[0].m_pSpeed[i] == 1 && Obs[1].m_pSpeed[i] == 1)
|
|
|
|
pDistance[i] = 0;
|
|
|
|
else if(Obs[0].m_pSpeed[i] == 1 && Obs[1].m_pSpeed[i] != 1)
|
|
|
|
pDistance[i] = pGameAreas[1][i][0] - pVisibleAreas[0][i][0];
|
|
|
|
else if(Obs[0].m_pSpeed[i] != 1 && Obs[1].m_pSpeed[i] == 1)
|
|
|
|
pDistance[i] = pVisibleAreas[1][i][0] - pGameAreas[0][i][0];
|
|
|
|
else
|
|
|
|
pDistance[i] = pGameAreas[1][i][0] - pGameAreas[0][i][0];
|
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-20 09:55:55 +00:00
|
|
|
void GetGameAreaDistance(const float pGameAreas[2][2][2], const MapObject Obs[2], const float pVisibleArea[2][2], float pDistance[2])
|
|
|
|
{
|
2022-06-21 13:02:26 +00:00
|
|
|
float pVisibleAreas[2][2][2];
|
2022-06-21 12:47:27 +00:00
|
|
|
memcpy(pVisibleAreas[0], pVisibleArea[0], sizeof(float[2][2]));
|
|
|
|
memcpy(pVisibleAreas[1], pVisibleArea[0], sizeof(float[2][2]));
|
|
|
|
GetGameAreaDistance(pGameAreas, Obs, pVisibleAreas, pDistance);
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GetSignificantScreenPos(const MapObject Ob, const float pVisibleArea[2][2], const float pReplaceableArea[2][2], float pScreen[2])
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if(!Ob.m_pSpeed[i])
|
|
|
|
{
|
|
|
|
pScreen[i] = pVisibleArea[i][0] + Ob.m_pScreenOffset[i][1];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
float BaseOffset = pReplaceableArea ? pReplaceableArea[i][0] : 0;
|
|
|
|
pScreen[i] = (pVisibleArea[i][0] - Ob.m_pBaseArea[i][0] - BaseOffset) / Ob.m_pSpeed[i];
|
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToTiles(const float pArea[2][2], int pTiles[2][2])
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
pTiles[i][0] = floor((floor(pArea[i][0] * 100.0f) / 100.0f) / 32.0f);
|
2022-06-21 13:21:33 +00:00
|
|
|
pTiles[i][1] = ceil((floor(pArea[i][1] * 100.0f) / 100.0f) / 32.0f);
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GetLineIntersection(const float pLine1[2], const float pLine2[2], float pIntersection[2])
|
|
|
|
{
|
2022-06-21 13:21:33 +00:00
|
|
|
float pBorders[2] = {
|
2022-06-21 12:47:27 +00:00
|
|
|
std::max(pLine1[0], pLine2[0]),
|
2022-06-21 13:21:33 +00:00
|
|
|
std::min(pLine1[1], pLine2[1])};
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
if(pIntersection)
|
2022-06-21 13:21:33 +00:00
|
|
|
SetInexistent((float *)pIntersection, 2);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
if(pBorders[0] - pBorders[1] > 0.01f)
|
|
|
|
return false;
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
if(pIntersection)
|
|
|
|
memcpy(pIntersection, pBorders, sizeof(float[2]));
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
return true;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GetLineIntersection(const float pLine[2], const float Point)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
return pLine[0] - Point <= 0.01f && pLine[1] - Point >= 0.01f;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetInexistent(float *pArray, const int Count)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < Count; i++)
|
|
|
|
pArray[i] = (float)INEXISTENT;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool IsInexistent(const float *pArray, const int Count)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < Count; i++)
|
|
|
|
if((float)pArray[i] == (float)INEXISTENT)
|
|
|
|
return true;
|
|
|
|
return false;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool IsInexistent(const float Value)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
return Value == INEXISTENT;
|
2022-03-16 18:09:29 +00:00
|
|
|
}
|