2015-01-07 23:06:44 +01:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
//#include <iostream>
|
|
|
|
//#include <fstream>
|
|
|
|
#include <new>
|
|
|
|
|
|
|
|
#include "rwbase.h"
|
|
|
|
#include "rwplugin.h"
|
|
|
|
#include "rwobjects.h"
|
|
|
|
#include "gtaplg.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
namespace Rw {
|
|
|
|
|
|
|
|
//
|
|
|
|
// Frame
|
|
|
|
//
|
|
|
|
|
|
|
|
// Node Name
|
|
|
|
|
2015-01-17 00:29:50 +01:00
|
|
|
int32 NodeNameOffset;
|
|
|
|
|
2015-01-07 23:06:44 +01:00
|
|
|
static void*
|
|
|
|
createNodeName(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
char *name = PLUGINOFFSET(char, object, offset);
|
|
|
|
name[0] = '\0';
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
copyNodeName(void *dst, void *src, int32 offset, int32)
|
|
|
|
{
|
|
|
|
char *dstname = PLUGINOFFSET(char, dst, offset);
|
|
|
|
char *srcname = PLUGINOFFSET(char, src, offset);
|
2015-01-17 00:29:50 +01:00
|
|
|
strncpy(dstname, srcname, 23);
|
2015-01-07 23:06:44 +01:00
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
destroyNodeName(void *object, int32, int32)
|
|
|
|
{
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
readNodeName(Stream *stream, int32 len, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
char *name = PLUGINOFFSET(char, object, offset);
|
|
|
|
stream->read(name, len);
|
|
|
|
name[len] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
writeNodeName(Stream *stream, int32 len, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
char *name = PLUGINOFFSET(char, object, offset);
|
|
|
|
stream->write(name, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32
|
2015-01-17 00:29:50 +01:00
|
|
|
getSizeNodeName(void *object, int32 offset, int32)
|
2015-01-07 23:06:44 +01:00
|
|
|
{
|
|
|
|
char *name = PLUGINOFFSET(char, object, offset);
|
|
|
|
int32 len = strlen(name);
|
|
|
|
return len > 0 ? len : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
RegisterNodeNamePlugin(void)
|
|
|
|
{
|
2015-01-17 00:29:50 +01:00
|
|
|
NodeNameOffset = Frame::registerPlugin(24, ID_NODENAME,
|
|
|
|
createNodeName,
|
|
|
|
destroyNodeName,
|
|
|
|
copyNodeName);
|
|
|
|
Frame::registerPluginStream(ID_NODENAME,
|
|
|
|
readNodeName,
|
|
|
|
writeNodeName,
|
|
|
|
getSizeNodeName);
|
2015-01-07 23:06:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Geometry
|
|
|
|
//
|
|
|
|
|
|
|
|
// Breakable Model
|
|
|
|
|
2015-01-17 00:29:50 +01:00
|
|
|
int32 BreakableOffset;
|
|
|
|
|
2015-01-07 23:06:44 +01:00
|
|
|
static void*
|
|
|
|
createBreakableModel(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
*PLUGINOFFSET(uint8*, object, offset) = 0;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
destroyBreakableModel(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
uint8 *p = *PLUGINOFFSET(uint8*, object, offset);
|
|
|
|
delete[] p;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
readBreakableModel(Stream *stream, int32, void *object, int32 o, int32)
|
|
|
|
{
|
|
|
|
uint32 header[13];
|
|
|
|
uint32 hasBreakable = stream->readU32();
|
|
|
|
if(hasBreakable == 0)
|
|
|
|
return;
|
|
|
|
stream->read(header, 13*4);
|
|
|
|
uint32 size = header[1]*(12+8+4) + header[5]*(6+2) +
|
|
|
|
header[8]*(32+32+12);
|
|
|
|
uint8 *p = new uint8[sizeof(Breakable)+size];
|
|
|
|
Breakable *breakable = (Breakable*)p;
|
|
|
|
*PLUGINOFFSET(Breakable*, object, o) = breakable;
|
|
|
|
breakable->position = header[0];
|
|
|
|
breakable->numVertices = header[1];
|
|
|
|
breakable->numFaces = header[5];
|
|
|
|
breakable->numMaterials = header[8];
|
|
|
|
p += sizeof(Breakable);
|
|
|
|
stream->read(p, size);
|
|
|
|
breakable->vertices = (float*)p;
|
|
|
|
p += breakable->numVertices*12;
|
|
|
|
breakable->texCoords = (float*)p;
|
|
|
|
p += breakable->numVertices*8;
|
|
|
|
breakable->colors = (uint8*)p;
|
|
|
|
p += breakable->numVertices*4;
|
|
|
|
breakable->faces = (uint16*)p;
|
|
|
|
p += breakable->numFaces*6;
|
|
|
|
breakable->matIDs = (uint16*)p;
|
|
|
|
p += breakable->numFaces*2;
|
|
|
|
breakable->texNames = (char(*)[32])p;
|
|
|
|
p += breakable->numMaterials*32;
|
|
|
|
breakable->maskNames = (char(*)[32])p;
|
|
|
|
p += breakable->numMaterials*32;
|
|
|
|
breakable->surfaceProps = (float32(*)[3])p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
writeBreakableModel(Stream *stream, int32, void *object, int32 o, int32)
|
|
|
|
{
|
|
|
|
uint32 header[13];
|
|
|
|
Breakable *breakable = *PLUGINOFFSET(Breakable*, object, o);
|
|
|
|
uint8 *p = (uint8*)breakable;
|
|
|
|
if(breakable == NULL){
|
|
|
|
stream->writeU32(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
stream->writeU32(1);
|
|
|
|
memset((char*)header, 0, 13*4);
|
|
|
|
header[0] = breakable->position;
|
|
|
|
header[1] = breakable->numVertices;
|
|
|
|
header[5] = breakable->numFaces;
|
|
|
|
header[8] = breakable->numMaterials;
|
|
|
|
stream->write(header, 13*4);
|
|
|
|
p += sizeof(Breakable);
|
|
|
|
stream->write(p, breakable->numVertices*(12+8+4) +
|
|
|
|
breakable->numFaces*(6+2) +
|
|
|
|
breakable->numMaterials*(32+32+12));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32
|
|
|
|
getSizeBreakableModel(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
Breakable *breakable = *PLUGINOFFSET(Breakable*, object, offset);
|
|
|
|
if(breakable == NULL)
|
|
|
|
return 4;
|
|
|
|
return 56 + breakable->numVertices*(12+8+4) +
|
|
|
|
breakable->numFaces*(6+2) +
|
|
|
|
breakable->numMaterials*(32+32+12);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RegisterBreakableModelPlugin(void)
|
|
|
|
{
|
2015-01-17 00:29:50 +01:00
|
|
|
BreakableOffset = Geometry::registerPlugin(sizeof(Breakable*),
|
|
|
|
ID_BREAKABLE,
|
|
|
|
createBreakableModel,
|
|
|
|
destroyBreakableModel, NULL);
|
2015-01-07 23:06:44 +01:00
|
|
|
Geometry::registerPluginStream(ID_BREAKABLE,
|
2015-01-17 00:29:50 +01:00
|
|
|
readBreakableModel,
|
|
|
|
writeBreakableModel,
|
|
|
|
getSizeBreakableModel);
|
2015-01-07 23:06:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Extra colors
|
|
|
|
|
2015-01-17 00:29:50 +01:00
|
|
|
int32 ExtraVertColorOffset;
|
2015-01-07 23:06:44 +01:00
|
|
|
|
|
|
|
static void*
|
|
|
|
createExtraVertColors(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
ExtraVertColors *colordata =
|
|
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
|
|
colordata->nightColors = NULL;
|
|
|
|
colordata->dayColors = NULL;
|
|
|
|
colordata->balance = 0.0f;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
destroyExtraVertColors(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
ExtraVertColors *colordata =
|
|
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
|
|
delete[] colordata->nightColors;
|
|
|
|
delete[] colordata->dayColors;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
readExtraVertColors(Stream *stream, int32, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
uint32 hasData;
|
|
|
|
ExtraVertColors *colordata =
|
|
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
|
|
hasData = stream->readU32();
|
|
|
|
if(!hasData)
|
|
|
|
return;
|
|
|
|
Geometry *geometry = (Geometry*)object;
|
|
|
|
colordata->nightColors = new uint8[geometry->numVertices*4];
|
|
|
|
colordata->dayColors = new uint8[geometry->numVertices*4];
|
|
|
|
colordata->balance = 1.0f;
|
|
|
|
stream->read(colordata->nightColors, geometry->numVertices*4);
|
|
|
|
if(geometry->colors)
|
|
|
|
memcpy(colordata->dayColors, geometry->colors,
|
|
|
|
geometry->numVertices*4);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
writeExtraVertColors(Stream *stream, int32, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
ExtraVertColors *colordata =
|
|
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
|
|
stream->writeU32(colordata->nightColors != NULL);
|
|
|
|
if(colordata->nightColors){
|
|
|
|
Geometry *geometry = (Geometry*)object;
|
|
|
|
stream->write(colordata->nightColors, geometry->numVertices*4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32
|
|
|
|
getSizeExtraVertColors(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
ExtraVertColors *colordata =
|
|
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
|
|
Geometry *geometry = (Geometry*)object;
|
|
|
|
if(colordata->nightColors)
|
|
|
|
return 4 + geometry->numVertices*4;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RegisterExtraVertColorPlugin(void)
|
|
|
|
{
|
2015-01-17 00:29:50 +01:00
|
|
|
ExtraVertColorOffset = Geometry::registerPlugin(sizeof(ExtraVertColors),
|
|
|
|
ID_EXTRAVERTCOLORS,
|
|
|
|
createExtraVertColors,
|
|
|
|
destroyExtraVertColors, NULL);
|
2015-01-07 23:06:44 +01:00
|
|
|
Geometry::registerPluginStream(ID_EXTRAVERTCOLORS,
|
2015-01-17 00:29:50 +01:00
|
|
|
readExtraVertColors,
|
|
|
|
writeExtraVertColors,
|
|
|
|
getSizeExtraVertColors);
|
2015-01-07 23:06:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|