mirror of
https://github.com/ZDoom/Raze.git
synced 2025-01-18 22:51:50 +00:00
- added a map preview to the user map browser.
This commit is contained in:
parent
6dfd975f88
commit
00a7be545d
7 changed files with 293 additions and 62 deletions
|
@ -510,6 +510,170 @@ void loadMap(const char* filename, int flags, vec3_t* pos, int16_t* ang, int* cu
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Decrypt
|
||||
//
|
||||
// Note that this is different from the general RFF encryption.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void Decrypt(void* to_, const void* from_, int len, int key)
|
||||
{
|
||||
uint8_t* to = (uint8_t*)to_;
|
||||
const uint8_t* from = (const uint8_t*)from_;
|
||||
|
||||
for (int i = 0; i < len; ++i, ++key)
|
||||
{
|
||||
to[i] = from[i] ^ key;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_LoadBloodMap
|
||||
//
|
||||
// This was adapted from ZDoom's old Build map loader.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void P_LoadBloodMapWalls(uint8_t* data, size_t len, TArray<walltype>& lwalls)
|
||||
{
|
||||
uint8_t infoBlock[37];
|
||||
int mapver = data[5];
|
||||
uint32_t matt;
|
||||
int i;
|
||||
int k;
|
||||
|
||||
if (mapver != 6 && mapver != 7)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
matt = *(uint32_t*)(data + 28);
|
||||
if (matt != 0 &&
|
||||
matt != MAKE_ID('M', 'a', 't', 't') &&
|
||||
matt != MAKE_ID('t', 't', 'a', 'M'))
|
||||
{
|
||||
Decrypt(infoBlock, data + 6, 37, 0x7474614d);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(infoBlock, data + 6, 37);
|
||||
}
|
||||
int numRevisions = *(uint32_t*)(infoBlock + 27);
|
||||
int numSectors = *(uint16_t*)(infoBlock + 31);
|
||||
int numWalls = *(uint16_t*)(infoBlock + 33);
|
||||
int numSprites = *(uint16_t*)(infoBlock + 35);
|
||||
int skyLen = 2 << *(uint16_t*)(infoBlock + 16);
|
||||
|
||||
if (mapver == 7)
|
||||
{
|
||||
// Version 7 has some extra stuff after the info block. This
|
||||
// includes a copyright, and I have no idea what the rest of
|
||||
// it is.
|
||||
data += 171;
|
||||
}
|
||||
else
|
||||
{
|
||||
data += 43;
|
||||
}
|
||||
|
||||
// Skip the sky info.
|
||||
data += skyLen;
|
||||
|
||||
lwalls.Reserve(numWalls);
|
||||
|
||||
// Read sectors
|
||||
k = numRevisions * sizeof(sectortypedisk);
|
||||
for (i = 0; i < numSectors; ++i)
|
||||
{
|
||||
sectortypedisk bsec;
|
||||
if (mapver == 7)
|
||||
{
|
||||
Decrypt(&bsec, data, sizeof(sectortypedisk), k);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&bsec, data, sizeof(sectortypedisk));
|
||||
}
|
||||
data += sizeof(sectortypedisk);
|
||||
if (bsec.extra > 0) // skip Xsector
|
||||
{
|
||||
data += 60;
|
||||
}
|
||||
}
|
||||
|
||||
// Read walls
|
||||
k |= 0x7474614d;
|
||||
for (i = 0; i < numWalls; ++i)
|
||||
{
|
||||
walltypedisk load;
|
||||
if (mapver == 7)
|
||||
{
|
||||
Decrypt(&load, data, sizeof(walltypedisk), k);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&load, data, sizeof(walltypedisk));
|
||||
}
|
||||
// only copy what we need to draw the map preview.
|
||||
|
||||
auto pWall = &lwalls[i];
|
||||
pWall->pos.X = LittleLong(load.x);
|
||||
pWall->pos.Y = LittleLong(load.y);
|
||||
pWall->point2 = LittleShort(load.point2);
|
||||
pWall->nextwall = LittleShort(load.nextwall);
|
||||
pWall->nextsector = LittleShort(load.nextsector);
|
||||
|
||||
data += sizeof(walltypedisk);
|
||||
if (load.extra > 0) // skip Xwall
|
||||
{
|
||||
data += 24;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TArray<walltype> loadMapWalls(const char* filename)
|
||||
{
|
||||
TArray<walltype> lwalls;
|
||||
FileReader fr = fileSystem.OpenFileReader(filename);
|
||||
if (!fr.isOpen()) return lwalls;
|
||||
|
||||
if (isBlood())
|
||||
{
|
||||
auto data = fr.Read();
|
||||
P_LoadBloodMapWalls(data.Data(), data.Size(), lwalls);
|
||||
return lwalls;
|
||||
}
|
||||
|
||||
|
||||
int mapversion = fr.ReadInt32();
|
||||
if (mapversion < 5 || mapversion > 9) return lwalls;
|
||||
|
||||
fr.Seek(16, FileReader::SeekCur);
|
||||
|
||||
// Get the basics out before loading the data so that we can set up the global storage.
|
||||
unsigned numsectors = fr.ReadUInt16();
|
||||
fr.Seek((mapversion == 5 ? sectorsize5 : mapversion == 6 ? sectorsize6 : sectorsize7) * numsectors, FileReader::SeekCur);
|
||||
unsigned numwalls = fr.ReadUInt16();
|
||||
|
||||
lwalls.Resize(numwalls);
|
||||
for (unsigned i = 0; i < lwalls.Size(); i++)
|
||||
{
|
||||
switch (mapversion)
|
||||
{
|
||||
case 5: ReadWallV5(fr, lwalls[i]); break;
|
||||
case 6: ReadWallV6(fr, lwalls[i]); break;
|
||||
default: ReadWallV7(fr, lwalls[i]); break;
|
||||
}
|
||||
}
|
||||
return lwalls;
|
||||
}
|
||||
|
||||
|
||||
void qloadboard(const char* filename, char flags, vec3_t* dapos, int16_t* daang);
|
||||
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
|
|||
#include "ns.h"
|
||||
#include "tarray.h"
|
||||
#include "tflags.h"
|
||||
#include "intvec.h"
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
|
@ -700,5 +701,6 @@ void allocateMapArrays(int numwall, int numsector, int numsprites);
|
|||
void validateSprite(spritetype& spr, int secno, int index);
|
||||
void fixSectors();
|
||||
void loadMap(const char *filename, int flags, vec3_t *pos, int16_t *ang, int *cursectnum, SpawnSpriteDef& sprites);
|
||||
TArray<walltype> loadMapWalls(const char* filename);
|
||||
void loadMapBackup(const char* filename);
|
||||
void loadMapHack(const char* filename, const unsigned char*, SpawnSpriteDef& sprites);
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "usermap.h"
|
||||
#include "gamecontrol.h"
|
||||
#include "mapinfo.h"
|
||||
#include "v_draw.h"
|
||||
|
||||
static FUsermapDirectory root;
|
||||
|
||||
|
@ -139,6 +140,25 @@ void ReadUserMaps()
|
|||
SortEntries(root);
|
||||
}
|
||||
|
||||
void LoadMapPreview(FUsermapEntry* entry)
|
||||
{
|
||||
if (entry->wallsread) return;
|
||||
entry->walls = loadMapWalls(entry->filename);
|
||||
}
|
||||
|
||||
void UnloadMapPreviews(FUsermapDirectory* dir)
|
||||
{
|
||||
for (auto& entry : dir->entries)
|
||||
{
|
||||
if (entry.walls.Size() > 0) entry.wallsread = false;
|
||||
entry.walls.Reset();
|
||||
}
|
||||
for (auto& sub : dir->subdirectories)
|
||||
{
|
||||
UnloadMapPreviews(&sub);
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_FIELD(FUsermapEntry, filename);
|
||||
DEFINE_FIELD(FUsermapEntry, container);
|
||||
DEFINE_FIELD(FUsermapEntry, displayname);
|
||||
|
@ -185,17 +205,51 @@ DEFINE_ACTION_FUNCTION(FUsermapDirectory, GetDirectory)
|
|||
ACTION_RETURN_POINTER(&self->subdirectories[num]);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FUsermapDirectory, DrawPreview)
|
||||
DEFINE_ACTION_FUNCTION(_UserMapMenu, DrawPreview)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FUsermapDirectory);
|
||||
|
||||
PARAM_UINT(num);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER(entry, FUsermapEntry);
|
||||
PARAM_INT(left);
|
||||
PARAM_INT(top);
|
||||
PARAM_INT(width);
|
||||
PARAM_INT(height);
|
||||
if (num >= self->entries.Size()) return 0;
|
||||
// todo
|
||||
if (!entry) return 0;
|
||||
LoadMapPreview(entry);
|
||||
if (entry->walls.Size() == 0) return 0;
|
||||
int minx = INT_MAX, miny = INT_MAX, maxx = INT_MIN, maxy = INT_MIN;
|
||||
for (auto& wal : entry->walls)
|
||||
{
|
||||
if (wal.pos.X < minx) minx = wal.pos.X;
|
||||
if (wal.pos.X > maxx) maxx = wal.pos.X;
|
||||
if (wal.pos.Y < miny) miny = wal.pos.Y;
|
||||
if (wal.pos.Y > maxy) maxy = wal.pos.Y;
|
||||
}
|
||||
float scalex = float(width) / (maxx - minx);
|
||||
float scaley = float(height) / (maxy - miny);
|
||||
int centerx = (minx + maxx) >> 1;
|
||||
int centery = (miny + maxy) >> 1;
|
||||
int dcenterx = left + (width >> 1);
|
||||
int dcentery = top + (height >> 1);
|
||||
float scale = min(scalex, scaley);
|
||||
float drawleft = dcenterx - (centerx - minx) * scale;
|
||||
float drawtop = dcentery - (centery - miny) * scale;
|
||||
|
||||
for (auto& wal : entry->walls)
|
||||
{
|
||||
if (wal.nextwall < 0) continue;
|
||||
auto point2 = &entry->walls[wal.point2];
|
||||
twod->AddLine(dcenterx + (wal.pos.X - centerx) * scale, dcentery + (wal.pos.Y - centery) * scale,
|
||||
dcenterx + (point2->pos.X - centerx) * scale, dcentery + (point2->pos.Y - centery) * scale,
|
||||
-1, -1, INT_MAX, INT_MAX, 0xff808080);
|
||||
}
|
||||
for (auto& wal : entry->walls)
|
||||
{
|
||||
if (wal.nextwall >= 0) continue;
|
||||
auto point2 = &entry->walls[wal.point2];
|
||||
twod->AddLine(dcenterx + (wal.pos.X - centerx) * scale, dcentery + (wal.pos.Y - centery) * scale,
|
||||
dcenterx + (point2->pos.X - centerx) * scale, dcentery + (point2->pos.Y - centery) * scale,
|
||||
-1, -1, INT_MAX, INT_MAX, 0xffffffff);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -213,5 +267,6 @@ DEFINE_ACTION_FUNCTION(_UsermapMenu, StartMap)
|
|||
|
||||
DoStartMap(entry->filename);
|
||||
M_ClearMenus();
|
||||
UnloadMapPreviews(&root);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "maptypes.h"
|
||||
|
||||
struct FUsermapEntry
|
||||
{
|
||||
|
@ -7,7 +8,9 @@ struct FUsermapEntry
|
|||
FString container;
|
||||
FString filename;
|
||||
FString info;
|
||||
int size;
|
||||
int size = 0;
|
||||
bool wallsread = false;
|
||||
TArray<walltype> walls; // for rendering a preview of the map
|
||||
};
|
||||
|
||||
struct FUsermapDirectory
|
||||
|
|
|
@ -119,58 +119,6 @@ const int nXSpriteSize = 56;
|
|||
const int nXWallSize = 24;
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
// This is the on-disk format. Only Blood still needs this for its retarded encryption that has to read this in as a block so that it can be decoded.
|
||||
// Keep it local so that the engine's sprite type is no longer limited by file format restrictions.
|
||||
struct spritetypedisk
|
||||
{
|
||||
int32_t x, y, z;
|
||||
uint16_t cstat;
|
||||
int16_t picnum;
|
||||
int8_t shade;
|
||||
uint8_t pal, clipdist, detail;
|
||||
uint8_t xrepeat, yrepeat;
|
||||
int8_t xoffset, yoffset;
|
||||
int16_t sectnum, statnum;
|
||||
int16_t ang, owner;
|
||||
int16_t index, yvel, inittype;
|
||||
int16_t type;
|
||||
int16_t hitag;
|
||||
int16_t extra;
|
||||
};
|
||||
|
||||
struct sectortypedisk
|
||||
{
|
||||
int16_t wallptr, wallnum;
|
||||
int32_t ceilingz, floorz;
|
||||
uint16_t ceilingstat, floorstat;
|
||||
int16_t ceilingpicnum, ceilingheinum;
|
||||
int8_t ceilingshade;
|
||||
uint8_t ceilingpal, ceilingxpanning, ceilingypanning;
|
||||
int16_t floorpicnum, floorheinum;
|
||||
int8_t floorshade;
|
||||
uint8_t floorpal, floorxpanning, floorypanning;
|
||||
uint8_t visibility, fogpal;
|
||||
int16_t type;
|
||||
int16_t hitag;
|
||||
int16_t extra;
|
||||
};
|
||||
|
||||
struct walltypedisk
|
||||
{
|
||||
int32_t x, y;
|
||||
int16_t point2, nextwall, nextsector;
|
||||
uint16_t cstat;
|
||||
int16_t picnum, overpicnum;
|
||||
int8_t shade;
|
||||
uint8_t pal, xrepeat, yrepeat, xpanning, ypanning;
|
||||
int16_t type;
|
||||
int16_t hitag;
|
||||
int16_t extra;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sectortype** ppSector, unsigned int* pCRC, BloodSpawnSpriteDef& sprites)
|
||||
{
|
||||
int16_t tpskyoff[256];
|
||||
|
|
|
@ -2,8 +2,62 @@
|
|||
#pragma once
|
||||
#include "ns.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
// This is the on-disk format. Only Blood still needs this for its retarded encryption that has to read this in as a block so that it can be decoded.
|
||||
// Keep it local so that the engine's sprite type is no longer limited by file format restrictions.
|
||||
struct spritetypedisk
|
||||
{
|
||||
int32_t x, y, z;
|
||||
uint16_t cstat;
|
||||
int16_t picnum;
|
||||
int8_t shade;
|
||||
uint8_t pal, clipdist, detail;
|
||||
uint8_t xrepeat, yrepeat;
|
||||
int8_t xoffset, yoffset;
|
||||
int16_t sectnum, statnum;
|
||||
int16_t ang, owner;
|
||||
int16_t index, yvel, inittype;
|
||||
int16_t type;
|
||||
int16_t hitag;
|
||||
int16_t extra;
|
||||
};
|
||||
|
||||
struct sectortypedisk
|
||||
{
|
||||
int16_t wallptr, wallnum;
|
||||
int32_t ceilingz, floorz;
|
||||
uint16_t ceilingstat, floorstat;
|
||||
int16_t ceilingpicnum, ceilingheinum;
|
||||
int8_t ceilingshade;
|
||||
uint8_t ceilingpal, ceilingxpanning, ceilingypanning;
|
||||
int16_t floorpicnum, floorheinum;
|
||||
int8_t floorshade;
|
||||
uint8_t floorpal, floorxpanning, floorypanning;
|
||||
uint8_t visibility, fogpal;
|
||||
int16_t type;
|
||||
int16_t hitag;
|
||||
int16_t extra;
|
||||
};
|
||||
|
||||
struct walltypedisk
|
||||
{
|
||||
int32_t x, y;
|
||||
int16_t point2, nextwall, nextsector;
|
||||
uint16_t cstat;
|
||||
int16_t picnum, overpicnum;
|
||||
int8_t shade;
|
||||
uint8_t pal, xrepeat, yrepeat, xpanning, ypanning;
|
||||
int16_t type;
|
||||
int16_t hitag;
|
||||
int16_t extra;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
TArray<walltype> dbLoadMapWalls(const char* pPath);
|
||||
|
||||
class DBloodActor;
|
||||
struct AISTATE;
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@ struct UsermapDirectory native
|
|||
native int GetNumDirectories();
|
||||
native UsermapEntry GetEntry(int num);
|
||||
native UsermapDirectory GetDirectory(int num);
|
||||
native void DrawPreview(int num, int left, int top, int width, int height);
|
||||
String GetInfo(int Selected)
|
||||
{
|
||||
if (parent) Selected--;
|
||||
|
@ -105,7 +104,7 @@ class UsermapMenu : ListMenu
|
|||
|
||||
// private to this menu to prevent exploits.
|
||||
private native static void StartMap(UsermapEntry entry);
|
||||
|
||||
private native static void DrawPreview(UsermapEntry entry, int left, int top, int width, int height);
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
|
@ -183,7 +182,13 @@ class UsermapMenu : ListMenu
|
|||
SetWindows();
|
||||
DrawFrame(previewLeft, previewTop, previewWidth, previewHeight);
|
||||
screen.Dim(0, 0.6, previewLeft, previewTop, previewWidth, previewHeight);
|
||||
currentDir.DrawPreview(Selected, previewLeft, previewTop, previewWidth, previewHeight);
|
||||
|
||||
if (Selected >= numparent + numdirs)
|
||||
{
|
||||
let entry = currentDir.GetEntry(Selected - numparent - numdirs);
|
||||
DrawPreview(entry, previewLeft, previewTop, previewWidth, previewHeight);
|
||||
}
|
||||
|
||||
|
||||
// Draw comment area
|
||||
DrawFrame (commentLeft, commentTop, commentWidth, commentHeight);
|
||||
|
|
Loading…
Reference in a new issue