Initial commit
This commit is contained in:
187
engines/watchmaker/2d_stuff.cpp
Normal file
187
engines/watchmaker/2d_stuff.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/2d_stuff.h"
|
||||
#include "watchmaker/fonts.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void TwoDeeStuff::writeBitmapListTo(SDDBitmap* target) {
|
||||
memcpy(target, DDBitmapsList, sizeof(struct SDDBitmap)*MAX_DD_BITMAPS);
|
||||
}
|
||||
|
||||
void TwoDeeStuff::garbageCollectPreRenderedText() {
|
||||
// Destroys pre-rendered writings that are no longer needed
|
||||
SDDText *r, *t;
|
||||
int32 c, a;
|
||||
for (c = 0, r = &RendText[0]; c < MAX_REND_TEXTS; c++, r++) {
|
||||
if (!r->text[0]) continue;
|
||||
|
||||
for (a = 0, t = &DDTextsList[0]; a < MAX_DD_TEXTS; a++, t++) {
|
||||
if (!t->text[0]) continue;
|
||||
|
||||
if (!strcmp(t->text, r->text) && (t->color == r->color) && (t->font == r->font))
|
||||
break;
|
||||
}
|
||||
// If it should no longer be displayed
|
||||
if (a >= MAX_DD_TEXTS) {
|
||||
rReleaseBitmap(r->tnum);
|
||||
if (r) r->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TwoDeeStuff::clearBitmapList() {
|
||||
int32 a;
|
||||
SDDBitmap *b;
|
||||
for (a = 0, b = &DDBitmapsList[0]; a < MAX_DD_BITMAPS; a++, b++) {
|
||||
b->tnum = b->px = b->py = b->ox = b->oy = b->dx = b->dy = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TwoDeeStuff::clearTextList() {
|
||||
int32 a;
|
||||
SDDText *t;
|
||||
for (a = 0, t = &DDTextsList[0]; a < MAX_DD_TEXTS; a++, t++) {
|
||||
memset(t->text, 0, sizeof(t->text));
|
||||
t->tnum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int32 TwoDeeStuff::findFreeBitmap() {
|
||||
int32 a = 0;
|
||||
for (a = 0; a < MAX_DD_BITMAPS; a++)
|
||||
if (!DDBitmapsList[a].tnum)
|
||||
return a;
|
||||
|
||||
warning("Too many DD Bitmaps!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void TwoDeeStuff::displayDDBitmap(int32 tnum, int32 px, int32 py, int32 ox, int32 oy, int32 dx, int32 dy) {
|
||||
int32 a = findFreeBitmap();
|
||||
if (a == -1) {
|
||||
warning("Skipping draw");
|
||||
return;
|
||||
}
|
||||
|
||||
DDBitmapsList[a].tnum = tnum;
|
||||
DDBitmapsList[a].px = _renderer->rFitX(px);
|
||||
DDBitmapsList[a].py = _renderer->rFitY(py);
|
||||
DDBitmapsList[a].ox = _renderer->rFitX(px + ox) - _renderer->rFitX(px);
|
||||
DDBitmapsList[a].oy = _renderer->rFitY(py + oy) - _renderer->rFitY(py);
|
||||
DDBitmapsList[a].dx = _renderer->rFitX(px + dx) - _renderer->rFitX(px);
|
||||
DDBitmapsList[a].dy = _renderer->rFitY(py + dy) - _renderer->rFitY(py);
|
||||
if (dx <= 0) DDBitmapsList[a].dx += _renderer->getBitmapDimX(tnum) - DDBitmapsList[a].ox;
|
||||
if (dy <= 0) DDBitmapsList[a].dy += _renderer->getBitmapDimY(tnum) - DDBitmapsList[a].oy;
|
||||
}
|
||||
|
||||
void TwoDeeStuff::displayDDBitmap_NoFit(int32 tnum, int32 px, int32 py, int32 ox, int32 oy, int32 dx, int32 dy) {
|
||||
int32 a = findFreeBitmap();
|
||||
if (a == -1) {
|
||||
warning("Skipping draw");
|
||||
return;
|
||||
}
|
||||
|
||||
DDBitmapsList[a].tnum = tnum;
|
||||
DDBitmapsList[a].px = (px);
|
||||
DDBitmapsList[a].py = (py);
|
||||
DDBitmapsList[a].ox = (px + ox) - (px);
|
||||
DDBitmapsList[a].oy = (py + oy) - (py);
|
||||
DDBitmapsList[a].dx = (px + dx) - (px);
|
||||
DDBitmapsList[a].dy = (py + dy) - (py);
|
||||
if (dx <= 0) DDBitmapsList[a].dx += _renderer->getBitmapDimX(tnum) - DDBitmapsList[a].ox;
|
||||
if (dy <= 0) DDBitmapsList[a].dy += _renderer->getBitmapDimY(tnum) - DDBitmapsList[a].oy;
|
||||
}
|
||||
|
||||
int32 TwoDeeStuff::rendDDText(char *text, FontKind font, FontColor color) {
|
||||
struct SDDText *r;
|
||||
int32 c, tdx, tdy;
|
||||
char info[100];
|
||||
|
||||
if ((!text) || (text[0] == '\0')) return -1;
|
||||
|
||||
for (c = 0, r = &RendText[0]; c < MAX_REND_TEXTS; c++, r++) {
|
||||
if (r->text[0]) continue;
|
||||
// Get the size of the text to render
|
||||
_renderer->_fonts->getTextDim(text, font, &tdx, &tdy);
|
||||
// Create a surface to contain it
|
||||
r->tnum = rCreateSurface(tdx, tdy, rBITMAPSURFACE);
|
||||
_renderer->clearBitmap(r->tnum, 0, 0, tdx, tdy, 0, 0, 0);
|
||||
// Render the lettering on the surface
|
||||
//DebugLogWindow("Creo testo %s | %d %d",text,tdx,tdy );
|
||||
_renderer->printText(text, r->tnum, font, color, 0, 0);
|
||||
Common::strlcpy(info, "text: ", sizeof(info));
|
||||
strncat(info, text, 15);
|
||||
//DebugLogWindow("Creato %s",info);
|
||||
rSetBitmapName(r->tnum, info);
|
||||
Common::strlcpy(r->text, text, sizeof(r->text));
|
||||
r->color = color;
|
||||
r->font = font;
|
||||
return r->tnum;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void TwoDeeStuff::displayDDText(char *text, FontKind font, FontColor color, int32 px, int32 py, int32 ox, int32 oy, int32 dx, int32 dy) {
|
||||
struct SDDText *t, *r;
|
||||
int32 a, c;
|
||||
|
||||
if ((!text) || (text[0] == '\0')) return;
|
||||
|
||||
for (a = 0; a < MAX_DD_TEXTS; a++)
|
||||
if (!DDTextsList[a].text[0])
|
||||
break;
|
||||
|
||||
if (a >= MAX_DD_TEXTS) {
|
||||
warning("Too many DD Texts!");
|
||||
return ;
|
||||
}
|
||||
|
||||
DDTextsList[a] = SDDText(text, font, color, -1);
|
||||
|
||||
t = &DDTextsList[a];
|
||||
// Try searching the pre-rendered scripts
|
||||
for (c = 0, r = &RendText[0]; c < MAX_REND_TEXTS; c++, r++) {
|
||||
if (!r->text[0]) continue;
|
||||
|
||||
if (!strcmp(t->text, r->text) && (t->color == r->color) && (t->font == r->font)) {
|
||||
this->displayDDBitmap(r->tnum, px, py, ox, oy, dx, dy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if I didn't prerender the script, I render it now
|
||||
if (c >= MAX_REND_TEXTS) {
|
||||
/* if( ( r->tnum = RendDDText( t->text, t->font, t->color ) ) > 0 )
|
||||
// Add the bitmap with pre-rendered lettering to display
|
||||
DisplayDDBitmap( r->tnum, px, py, ox, oy, dx, dy );*/
|
||||
|
||||
int32 tn;
|
||||
if ((tn = rendDDText(t->text, t->font, t->color)) > 0)
|
||||
// Add the bitmap with pre-rendered lettering to display
|
||||
this->displayDDBitmap(tn, px, py, ox, oy, dx, dy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
59
engines/watchmaker/2d_stuff.h
Normal file
59
engines/watchmaker/2d_stuff.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_2D_STUFF_H
|
||||
#define WATCHMAKER_2D_STUFF_H
|
||||
|
||||
#include "watchmaker/sysdef.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/struct.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
class Renderer;
|
||||
|
||||
class TwoDeeStuff {
|
||||
SDDBitmap DDBitmapsList[MAX_DD_BITMAPS];
|
||||
SDDText DDTextsList[MAX_DD_TEXTS];
|
||||
SDDText RendText[MAX_REND_TEXTS];
|
||||
|
||||
Renderer *_renderer;
|
||||
public:
|
||||
TwoDeeStuff(Renderer *renderer) : _renderer(renderer) {}
|
||||
void writeBitmapListTo(SDDBitmap* target);
|
||||
void garbageCollectPreRenderedText();
|
||||
|
||||
void clearBitmapList();
|
||||
void clearTextList();
|
||||
|
||||
int32 findFreeBitmap();
|
||||
|
||||
void displayDDBitmap(int32 tnum, int32 px, int32 py, int32 ox, int32 oy, int32 dx, int32 dy);
|
||||
void displayDDBitmap_NoFit(int32 tnum, int32 px, int32 py, int32 ox, int32 oy, int32 dx, int32 dy);
|
||||
void displayDDText(char *text, FontKind font, FontColor color, int32 px, int32 py, int32 ox, int32 oy, int32 dx, int32 dy);
|
||||
private:
|
||||
int32 rendDDText(char *text, FontKind font, FontColor color);
|
||||
};
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // SCUMMVM_2D_STUFF_H
|
||||
729
engines/watchmaker/3d/animation.cpp
Normal file
729
engines/watchmaker/3d/animation.cpp
Normal file
@@ -0,0 +1,729 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_strcat
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_strcpy
|
||||
|
||||
#include "watchmaker/3d/animation.h"
|
||||
#include "watchmaker/3d/geometry.h"
|
||||
#include "watchmaker/3d/loader.h"
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/3d/t3d_body.h"
|
||||
#include "watchmaker/3d/t3d_mesh.h"
|
||||
#include "watchmaker/file_utils.h"
|
||||
#include "watchmaker/game.h"
|
||||
#include "watchmaker/ll/ll_system.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/utils.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
|
||||
/* -----------------16/12/98 10.32-------------------
|
||||
* PRELOADEDANIMS
|
||||
* --------------------------------------------------*/
|
||||
#define MAX_BONES 40
|
||||
#define MAX_PRELOADED_ANIMS 8
|
||||
#define A3DFILEVERSION 5
|
||||
#define SCALE_DEFAULT_ANIM 1
|
||||
#define SCALE_ANIM 3
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
struct t3dLOADBONE {
|
||||
t3dV3F *Trasl;
|
||||
t3dV3F *Euler;
|
||||
uint32 NumBone;
|
||||
};
|
||||
|
||||
struct t3dLOADANIM {
|
||||
Common::String name;
|
||||
uint32 NumFrames = 0, NumBones = 0, HiBone = 0, LastTime = 0;
|
||||
t3dF32 *Dist = nullptr;
|
||||
t3dLOADBONE Bone[MAX_BONES] = {};
|
||||
};
|
||||
|
||||
t3dLOADANIM PreloadedAnim[MAX_PRELOADED_ANIMS];
|
||||
|
||||
/* -----------------30/12/98 10.56-------------------
|
||||
* t3dMatRotXYZ
|
||||
* --------------------------------------------------*/
|
||||
void t3dMatRotXYZ(t3dM3X3F *dest, t3dF32 x, t3dF32 y, t3dF32 z) {
|
||||
t3dM3X3F matrix, matrix_x, matrix_y, matrix_z;
|
||||
|
||||
t3dMatIdentity(&matrix_x);
|
||||
t3dMatIdentity(&matrix_y);
|
||||
t3dMatIdentity(&matrix_z);
|
||||
|
||||
matrix_x.M[4] = (float)cos(x);
|
||||
matrix_x.M[5] = (float)sin(x);
|
||||
matrix_x.M[7] = -(float)sin(x);
|
||||
matrix_x.M[8] = (float)cos(x);
|
||||
|
||||
matrix_y.M[0] = (float)cos(y);
|
||||
matrix_y.M[2] = -(float)sin(y);
|
||||
matrix_y.M[6] = (float)sin(y);
|
||||
matrix_y.M[8] = (float)cos(y);
|
||||
|
||||
matrix_z.M[0] = (float)cos(z);
|
||||
matrix_z.M[1] = (float)sin(z);
|
||||
matrix_z.M[3] = -(float)sin(z);
|
||||
matrix_z.M[4] = (float)cos(z);
|
||||
|
||||
t3dMatMul(&matrix, &matrix_x, &matrix_y);
|
||||
t3dMatMul(&matrix, &matrix, &matrix_z);
|
||||
|
||||
dest->M[0] = matrix.M[0];
|
||||
dest->M[2] = matrix.M[1];
|
||||
dest->M[1] = matrix.M[2];
|
||||
dest->M[6] = matrix.M[3];
|
||||
dest->M[8] = matrix.M[4];
|
||||
dest->M[7] = matrix.M[5];
|
||||
dest->M[3] = matrix.M[6];
|
||||
dest->M[5] = matrix.M[7];
|
||||
dest->M[4] = matrix.M[8];
|
||||
}
|
||||
|
||||
Common::Array<t3dPLIGHT> t3dBODY::getPositionalLight(uint8 pos) {
|
||||
Common::Array<t3dPLIGHT> result;
|
||||
for (const auto &light : PosLightTable) {
|
||||
if (light.Num == pos) {
|
||||
result.push_back(light);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* -----------------04/07/98 15.52-------------------
|
||||
* GetLightPosition
|
||||
* --------------------------------------------------*/
|
||||
uint8 GetLightPosition(t3dV3F *dest, uint8 pos) {
|
||||
if (!pos) return 0;
|
||||
|
||||
auto pLights = t3dCurRoom->getPositionalLight(pos);
|
||||
dest->y = CurFloorY;
|
||||
for (const auto &light : pLights) {
|
||||
if (light.Pos.x && light.Pos.z) {
|
||||
dest->x = light.Pos.x;
|
||||
dest->z = light.Pos.z;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
if (pos != 99)
|
||||
warning("Can't find lpos %d in %s", pos, t3dCurRoom->name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------04/07/98 15.52-------------------
|
||||
* GetLightPosition
|
||||
* --------------------------------------------------*/
|
||||
uint8 GetLightDirection(t3dV3F *dest, uint8 pos) {
|
||||
if (!pos) return 0;
|
||||
|
||||
auto pLights = t3dCurRoom->getPositionalLight(pos);
|
||||
dest->y = CurFloorY;
|
||||
for (const auto &light : pLights) {
|
||||
if (light.Dir.x && light.Dir.z) {
|
||||
dest->x = light.Dir.x;
|
||||
dest->z = light.Dir.x;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
if (pos != 99)
|
||||
warning("Can't find ldir %d in %s", pos, t3dCurRoom->name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------15/12/98 16.26-------------------
|
||||
* t3dLoadAnimation
|
||||
* --------------------------------------------------*/
|
||||
int8 t3dLoadAnimation(WGame &game, const char *s, t3dMESH *mesh, uint16 Flag) {
|
||||
uint32 nf, nb, i, k, h, older, ScaleAnim, CurPreloadedAnim;
|
||||
uint32 j = 0;
|
||||
t3dLOADANIM *p;
|
||||
t3dLOADBONE *bone;
|
||||
t3dBONEANIM *db;
|
||||
t3dBONE *b;
|
||||
t3dV3F t;
|
||||
t3dF32 c;
|
||||
|
||||
// Prova a vedere se l'ho gia' precaricata
|
||||
for (CurPreloadedAnim = 0; CurPreloadedAnim < MAX_PRELOADED_ANIMS; CurPreloadedAnim++)
|
||||
if (PreloadedAnim[CurPreloadedAnim].NumFrames)
|
||||
if (PreloadedAnim[CurPreloadedAnim].name.equalsIgnoreCase(s))
|
||||
break;
|
||||
// Se la devo precaricare, cerco quella piu' vecchia e la scarico
|
||||
if (CurPreloadedAnim >= MAX_PRELOADED_ANIMS) {
|
||||
older = 0;
|
||||
// Prima cerco se ci sono ancora degli slot liberi
|
||||
for (CurPreloadedAnim = 0; CurPreloadedAnim < MAX_PRELOADED_ANIMS; CurPreloadedAnim++) {
|
||||
if (!PreloadedAnim[CurPreloadedAnim].NumFrames)
|
||||
break;
|
||||
else if (!(older) || (older > PreloadedAnim[CurPreloadedAnim].LastTime))
|
||||
older = PreloadedAnim[j = CurPreloadedAnim].LastTime;
|
||||
}
|
||||
// Se non c'erano slot liberi, rilascia vecchia animazione precaricata
|
||||
if (CurPreloadedAnim >= MAX_PRELOADED_ANIMS) {
|
||||
CurPreloadedAnim = j;
|
||||
//t DebugFile( "Precarico animazione %s nello slot %d occupato da %s", s, CurPreloadedAnim, PreloadedAnim[j].Name );
|
||||
// Disalloca tutto
|
||||
for (i = 0; i < MAX_BONES; i++) {
|
||||
t3dFree(PreloadedAnim[j].Bone[i].Trasl);
|
||||
t3dFree(PreloadedAnim[j].Bone[i].Euler);
|
||||
}
|
||||
delete[] PreloadedAnim[j].Dist;
|
||||
PreloadedAnim[j] = t3dLOADANIM();
|
||||
}
|
||||
//t else
|
||||
//t DebugFile( "Precarico animazione %s nello slot libero %d", s, CurPreloadedAnim );
|
||||
|
||||
p = &PreloadedAnim[CurPreloadedAnim];
|
||||
p->name = s;
|
||||
|
||||
// Carica la nuova animazione
|
||||
Common::String name = game.workDirs._a3dDir + replaceExtension(s, "a3d");
|
||||
|
||||
{
|
||||
auto stream = game.resolveFile(name.c_str());
|
||||
if (!stream) {
|
||||
warning("File %s not found", name.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((i = stream->readByte()) != A3DFILEVERSION) {
|
||||
warning("%s file incompatible: current version: %d.\tFile version: %d", name.c_str(), A3DFILEVERSION, i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
nb = stream->readSint16LE();
|
||||
nf = stream->readSint16LE();
|
||||
if (nf == 0) {
|
||||
warning("%s has N0 frames!", name.c_str());
|
||||
return -1;
|
||||
}
|
||||
if (nb >= MAX_BONES) {
|
||||
warning("%s has too many bones (%d, MAX is %d)!", name.c_str(), j, MAX_BONES);
|
||||
return -1;
|
||||
}
|
||||
p->NumBones = nb;
|
||||
p->NumFrames = nf;
|
||||
|
||||
for (i = 0; i < nb; i++) {
|
||||
j = (uint32)(stream->readByte());
|
||||
if (!(p->HiBone) || (p->HiBone < j))
|
||||
p->HiBone = j;
|
||||
|
||||
bone = &p->Bone[i];
|
||||
bone->NumBone = j;
|
||||
bone->Euler = t3dCalloc<t3dV3F>(nf);
|
||||
bone->Trasl = t3dCalloc<t3dV3F>(nf);
|
||||
|
||||
for (k = 0; k < nf; k++) {
|
||||
bone->Euler[k] = t3dV3F(*stream);
|
||||
}
|
||||
|
||||
for (k = 0; k < nf; k++) {
|
||||
bone->Trasl[k] = t3dV3F(*stream);
|
||||
}
|
||||
}
|
||||
if (stream->readByte()) {
|
||||
p->Dist = new t3dF32[nf]{};
|
||||
for (k = 0; k < nf; k++)
|
||||
p->Dist[k] = stream->readFloatLE();
|
||||
}
|
||||
} // Close file
|
||||
}
|
||||
//t else
|
||||
//t DebugFile( "Animazione %s gia' precaricata nello slot %d", s, CurPreloadedAnim );
|
||||
|
||||
p = &PreloadedAnim[CurPreloadedAnim];
|
||||
// Scrive l'ultima volta che l'ho usata
|
||||
p->LastTime = t3dReadTime();
|
||||
|
||||
// Finalmente copia l'animazione precaricata nella mesh
|
||||
if (Flag & T3D_MESH_DEFAULTANIM) {
|
||||
db = &mesh->DefaultAnim;
|
||||
mesh->Flags |= T3D_MESH_DEFAULTANIM;
|
||||
if (db) mesh->releaseAnim(T3D_MESH_DEFAULTANIM);
|
||||
if (db) mesh->releaseAnim(0);
|
||||
ScaleAnim = SCALE_DEFAULT_ANIM;
|
||||
db->NumFrames = p->NumFrames;
|
||||
} else {
|
||||
db = &mesh->Anim;
|
||||
mesh->Flags &= ~T3D_MESH_DEFAULTANIM;
|
||||
if (db) mesh->releaseAnim(0);
|
||||
ScaleAnim = SCALE_ANIM;
|
||||
db->NumFrames = (p->NumFrames - 2) * ScaleAnim + 2;
|
||||
}
|
||||
if (db->BoneTable) mesh->releaseAnim(0);
|
||||
mesh->NumNormals = 0;
|
||||
db->NumBones = 0;
|
||||
db->BoneTable = nullptr;
|
||||
db->BoneTable = t3dCalloc<t3dBONE>(p->HiBone + 1);
|
||||
db->NumBones = p->HiBone + 1;
|
||||
|
||||
c = 1.0f / (t3dF32)(ScaleAnim);
|
||||
for (i = 0; i < p->NumBones; i++) {
|
||||
bone = &p->Bone[i];
|
||||
b = &db->BoneTable[bone->NumBone];
|
||||
|
||||
b->Matrix = t3dCalloc<t3dM3X3F>(db->NumFrames);
|
||||
b->Trasl = t3dCalloc<t3dV3F>(db->NumFrames);
|
||||
|
||||
for (k = 0; k < db->NumFrames; k++) {
|
||||
j = ((k - 1) / ScaleAnim) + 1;
|
||||
h = ((k - 1) % ScaleAnim);
|
||||
|
||||
if ((!h) || (k < 1)) {
|
||||
if (k < 1)
|
||||
j = k;
|
||||
t3dMatRotXYZ(&b->Matrix[k], bone->Euler[j].x, bone->Euler[j].y, bone->Euler[j].z);
|
||||
memcpy(&b->Trasl[k], &bone->Trasl[j], sizeof(t3dV3F));
|
||||
} else {
|
||||
t3dVectSub(&t, &bone->Euler[j + 1], &bone->Euler[j]);
|
||||
if ((t.x < T3D_2PI) && (t.x > T3D_PI)) t.x = t.x - T3D_2PI;
|
||||
if ((t.x > -T3D_2PI) && (t.x < -T3D_PI)) t.x = t.x + T3D_2PI;
|
||||
if ((t.y < T3D_2PI) && (t.y > T3D_PI)) t.y = t.y - T3D_2PI;
|
||||
if ((t.y > -T3D_2PI) && (t.y < -T3D_PI)) t.y = t.y + T3D_2PI;
|
||||
if ((t.z < T3D_2PI) && (t.z > T3D_PI)) t.z = t.z - T3D_2PI;
|
||||
if ((t.z > -T3D_2PI) && (t.z < -T3D_PI)) t.z = t.z + T3D_2PI;
|
||||
t *= (c * (t3dF32)(h));
|
||||
t3dVectAdd(&t, &bone->Euler[j], &t);
|
||||
t3dMatRotXYZ(&b->Matrix[k], t.x, t.y, t.z);
|
||||
|
||||
t3dVectSub(&t, &bone->Trasl[j + 1], &bone->Trasl[j]);
|
||||
t *= (c * (t3dF32)(h));
|
||||
t3dVectAdd(&b->Trasl[k], &bone->Trasl[j], &t);
|
||||
}
|
||||
|
||||
/* if(!(mesh->Flags&T3D_MESH_CHARACTER))
|
||||
DebugFile("%3d;%3d;%9f;%9f;%9f;%9f;%9f;%9f;%9f;%9f;%9f;%9f;%9f;%9f;",k,i,
|
||||
(bone->Euler[j].x)*180.0f/T3D_PI,(bone->Euler[j].y)*180.0f/T3D_PI,(bone->Euler[j].z)*180.0f/T3D_PI,
|
||||
b->Matrix[k].M[0],b->Matrix[k].M[1],b->Matrix[k].M[2],
|
||||
b->Matrix[k].M[3],b->Matrix[k].M[4],b->Matrix[k].M[5],
|
||||
b->Matrix[k].M[6],b->Matrix[k].M[7],b->Matrix[k].M[8] );
|
||||
*/
|
||||
}
|
||||
|
||||
b->ModVertices.clear();
|
||||
// Poi inserisce tutti i vertici modificati nell'array gia' alloocato della dimensione giusta
|
||||
for (auto &modVertices : mesh->ModVertices) {
|
||||
if (modVertices.NumBone == bone->NumBone) {
|
||||
b->ModVertices.push_back(modVertices.NumVert);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p->Dist) {
|
||||
db->Dist = new t3dF32[db->NumFrames]{};
|
||||
for (k = 0; k < db->NumFrames; k++)
|
||||
db->Dist[k] = p->Dist[k];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* -----------------30/12/98 11.27-------------------
|
||||
* FixupAnim
|
||||
* --------------------------------------------------*/
|
||||
void FixupAnim(t3dMESH *mesh, uint8 pos, const char *room) {
|
||||
t3dBONEANIM *db;
|
||||
t3dBONE *bone, *bone0;
|
||||
t3dV3F lp, ld, Frame0Trasl, cc, tmp, tmp1, tmp2, zero;
|
||||
t3dM3X3F lm, mx, BoneInitMatrix;
|
||||
uint32 i, k, frame;
|
||||
t3dBODY *OldCurRoom = t3dCurRoom;
|
||||
|
||||
if (mesh->Flags & T3D_MESH_DEFAULTANIM) {
|
||||
db = &mesh->DefaultAnim;
|
||||
pos = 0;
|
||||
} else {
|
||||
db = &mesh->Anim;
|
||||
if (pos) {
|
||||
if (room && (room[0] != '\0')) {
|
||||
t3dBODY *roomPtr = _vm->_roomManager->getRoomIfLoaded(room);
|
||||
if (room) {
|
||||
t3dCurRoom = roomPtr;
|
||||
}
|
||||
}
|
||||
if (!GetLightPosition(&lp, pos) || (lp.x == 0.0f) || (lp.z == 0.0f)) pos = 0;
|
||||
if (!GetLightDirection(&ld, pos) || (ld.x == 0.0f) || (ld.z == 0.0f)) pos = 0;
|
||||
t3dCurRoom = OldCurRoom;
|
||||
|
||||
t3dVectSub(&ld, &ld, &lp);
|
||||
ld.z = -ld.z;
|
||||
t3dVectAdd(&ld, &ld, &lp);
|
||||
t3dMatView(&lm, &lp, &ld);
|
||||
|
||||
if ((!pos) || (mesh->Flags & (T3D_MESH_ABS_ANIM | T3D_MESH_CHARACTER))) {
|
||||
t3dVectCopy(&lp, &mesh->Trasl);
|
||||
t3dMatCopy(&lm, &mesh->Matrix);
|
||||
pos = 99;
|
||||
}
|
||||
|
||||
if (mesh->Flags & T3D_MESH_ABS_ANIM)
|
||||
t3dVectTransform(&cc, &CharCorrection, &lm);
|
||||
}
|
||||
}
|
||||
// Ora sistema tutte le altre bones 1..32 (mesh) e 33/34 (camera)
|
||||
for (i = 1; i < db->NumBones; i++) {
|
||||
if (!(bone = &db->BoneTable[i]) || !(bone->Trasl) || !(bone->Matrix)) continue;
|
||||
// Salva la prima matrice di ogni bone
|
||||
t3dMatCopy(&BoneInitMatrix, &bone->Matrix[0]);
|
||||
// Calcola scostamento iniziale bone per azioni assolute personaggi
|
||||
if (i == 1) t3dVectSub(&Frame0Trasl, &bone->Trasl[1], &bone->Trasl[0]);
|
||||
|
||||
for (k = 0; k < db->NumFrames; k++) {
|
||||
// Tutte le matrici diventano relative al frame 0
|
||||
t3dMatMulInv(&bone->Matrix[k], &bone->Matrix[k], &BoneInitMatrix);
|
||||
// Aggiunge la correzione a:
|
||||
// - Azioni di default (tutti frames personaggi)
|
||||
// - Azioni relative (tutti frames, personaggi e oggetti)
|
||||
// - Azioni assolute (personaggi frame 0)
|
||||
if ((mesh->Flags & T3D_MESH_DEFAULTANIM) || !(mesh->Flags & T3D_MESH_ABS_ANIM) ||
|
||||
((!k) && (mesh->Flags & T3D_MESH_ABS_ANIM) && (mesh->Flags & T3D_MESH_CHARACTER)))
|
||||
t3dVectAdd(&bone->Trasl[k], &CharCorrection, &bone->Trasl[k]);
|
||||
|
||||
if (pos) {
|
||||
// Oggetti relativi
|
||||
if (!(mesh->Flags & T3D_MESH_CHARACTER) && !(mesh->Flags & T3D_MESH_ABS_ANIM)) {
|
||||
t3dVectTransform(&ld, &bone->Trasl[k], &lm);
|
||||
t3dVectAdd(&bone->Trasl[k], &ld, &lp);
|
||||
}
|
||||
// Personaggi assoluti
|
||||
else if ((mesh->Flags & T3D_MESH_ABS_ANIM) && (mesh->Flags & T3D_MESH_CHARACTER) && (k)) {
|
||||
t3dVectSub(&bone->Trasl[k], &bone->Trasl[k], &Frame0Trasl);
|
||||
t3dVectTransformInv(&bone->Trasl[k], &bone->Trasl[k], &lm);
|
||||
t3dVectAdd(&bone->Trasl[k], &bone->Trasl[k], &CharCorrection);
|
||||
|
||||
t3dMatMul(&bone->Matrix[k], &bone->Matrix[k], &lm);
|
||||
}
|
||||
}
|
||||
/* if(!(mesh->Flags&T3D_MESH_CHARACTER))
|
||||
DebugFile("%3d;%3d;%9f;%9f;%9f;%9f;%9f;%9f;%9f;%9f;%9f;",k,i,
|
||||
bone->Matrix[k].M[0],bone->Matrix[k].M[1],bone->Matrix[k].M[2],
|
||||
bone->Matrix[k].M[3],bone->Matrix[k].M[4],bone->Matrix[k].M[5],
|
||||
bone->Matrix[k].M[6],bone->Matrix[k].M[7],bone->Matrix[k].M[8] );
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if (db->Dist)
|
||||
for (k = 0; k < db->NumFrames; k++)
|
||||
if ((mesh->Flags & T3D_MESH_CHARACTER) && ((!k) || (mesh->Flags & T3D_MESH_DEFAULTANIM)))
|
||||
db->Dist[k] -= CharCorrection.z;
|
||||
|
||||
if (!(bone0 = &db->BoneTable[0]) || !(bone0->Trasl) || !(bone0->Matrix)) {
|
||||
bone0->Matrix = t3dCalloc<t3dM3X3F>(db->NumFrames);
|
||||
bone0->Trasl = t3dCalloc<t3dV3F>(db->NumFrames);
|
||||
} else
|
||||
warning("Guarda che il bone0 e' gia' stato allocato nella mesh %s", mesh->name.c_str());
|
||||
|
||||
for (k = 0; k < db->NumFrames; k++) {
|
||||
t3dVectCopy(&bone0->Trasl[k], &mesh->Trasl);
|
||||
t3dMatCopy(&bone0->Matrix[k], &mesh->Matrix);
|
||||
}
|
||||
|
||||
if ((mesh->Flags & T3D_MESH_CHARACTER) && !(mesh->Flags & T3D_MESH_DEFAULTANIM)) {
|
||||
if (!(bone = &db->BoneTable[1]) || !(bone->Trasl) || !(bone->Matrix))
|
||||
return ;
|
||||
|
||||
t3dVectInit(&tmp1, bone->Trasl[1].x, 0.0f, bone->Trasl[1].z);
|
||||
t3dVectInit(&tmp, 0.0f, 0.0f, 1.0f);
|
||||
t3dVectTransform(&tmp, &tmp, &bone->Matrix[1]);
|
||||
tmp.y = 0;
|
||||
t3dVectFill(&zero, 0.0f);
|
||||
t3dMatView(&mx, &zero, &tmp);
|
||||
t3dVectTransform(&cc, &CharCorrection, &mx);
|
||||
t3dVectSub(&tmp1, &tmp1, &cc);
|
||||
|
||||
for (frame = 0; frame < db->NumFrames; frame++) {
|
||||
t3dVectInit(&tmp2, bone->Trasl[frame].x, 0.0f, bone->Trasl[frame].z);
|
||||
t3dVectInit(&tmp, 0.0f, 0.0f, 1.0f);
|
||||
t3dVectTransform(&tmp, &tmp, &bone->Matrix[frame]);
|
||||
tmp.y = 0;
|
||||
t3dVectFill(&zero, 0.0f);
|
||||
t3dMatView(&mx, &zero, &tmp);
|
||||
t3dVectTransform(&cc, &CharCorrection, &mx);
|
||||
t3dVectSub(&tmp2, &tmp2, &cc);
|
||||
|
||||
t3dVectSub(&tmp, &tmp2, &tmp1);
|
||||
// t3dVectTransform( &tmp, &tmp, &mesh->Matrix );
|
||||
|
||||
tmp.x += bone->Trasl[1].x - bone->Trasl[0].x;
|
||||
tmp.z += bone->Trasl[1].z - bone->Trasl[0].z;
|
||||
|
||||
t3dVectCopy(&bone0->Trasl[frame], &tmp);
|
||||
t3dVectInit(&tmp, 0.0f, 0.0f, -1.0f);
|
||||
t3dVectTransform(&tmp, &tmp, &bone->Matrix[frame]);
|
||||
tmp.z = -tmp.z;
|
||||
tmp.y = 0;
|
||||
t3dVectFill(&zero, 0.0f);
|
||||
t3dMatView(&bone0->Matrix[frame], &zero, &tmp);
|
||||
}
|
||||
|
||||
for (i = 1; i < db->NumBones; i++) {
|
||||
if (!(bone = &db->BoneTable[i]) || !(bone->Trasl) || !(bone->Matrix))
|
||||
continue;
|
||||
|
||||
for (k = 0; k < db->NumFrames; k++) {
|
||||
t3dVectSub(&bone->Trasl[k], &bone->Trasl[k], &bone0->Trasl[k]);
|
||||
t3dVectTransform(&bone->Trasl[k], &bone->Trasl[k], &bone0->Matrix[k]);
|
||||
t3dMatMulInv(&bone->Matrix[k], &bone->Matrix[k], &bone0->Matrix[k]);
|
||||
}
|
||||
}
|
||||
|
||||
for (k = 0; k < db->NumFrames; k++) {
|
||||
t3dMatMulInv(&bone0->Matrix[k], &mesh->Matrix, &bone0->Matrix[k]);
|
||||
t3dVectTransform(&tmp, &bone0->Trasl[k], &mesh->Matrix);
|
||||
t3dVectAdd(&bone0->Trasl[k], &mesh->Trasl, &tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------13/04/99 14.57-------------------
|
||||
* LoadShadowMeshes
|
||||
* --------------------------------------------------*/
|
||||
t3dBODY *LoadShadowMeshes(WGame &game, const char *pname, t3dBODY *Body) {
|
||||
uint16 ref;
|
||||
char Name[255];
|
||||
t3dBODY *shadow = new t3dBODY();
|
||||
gVertex *Original = Body->MeshTable[0].VertexBuffer;
|
||||
t3dF32 dist, rez;
|
||||
|
||||
strcpy(Name, pname);
|
||||
strncpy(&Name[strlen(pname) - 4], "_Shadow.t3d\0", 12);
|
||||
uint16 numBodys = 0;
|
||||
shadow = _vm->_roomManager->loadRoom(Name, shadow, &numBodys, (T3D_NOLIGHTMAPS | T3D_NORECURSION | T3D_NOVOLUMETRICLIGHTS | T3D_NOCAMERAS | T3D_NOBOUNDS | T3D_STATIC_SET0 | T3D_STATIC_SET1));
|
||||
if (!shadow) return nullptr;
|
||||
|
||||
for (uint16 i = 0; i < shadow->NumMeshes(); i++) {
|
||||
t3dMESH &m = shadow->MeshTable[i];
|
||||
m.VBptr = m.VertexBuffer;
|
||||
for (uint16 j = 0; j < m.NumFaces(); j++) {
|
||||
t3dFACE &f = m.FList[j];
|
||||
for (uint16 n = 0; n < 3; n++) {
|
||||
t3dV3F pnt;
|
||||
pnt.x = m.VBptr[f.VertexIndex[n]].x;
|
||||
pnt.y = m.VBptr[f.VertexIndex[n]].y;
|
||||
pnt.z = m.VBptr[f.VertexIndex[n]].z;
|
||||
|
||||
ref = 0;
|
||||
dist = 999999999.0f;
|
||||
for (uint16 k = 0; k < Body->MeshTable[0].NumVerts; k++) {
|
||||
t3dV3F tpnt;
|
||||
tpnt.x = Original[k].x;
|
||||
tpnt.y = Original[k].y;
|
||||
tpnt.z = Original[k].z;
|
||||
if ((rez = t3dVectDistance(&pnt, &tpnt)) < dist) {
|
||||
dist = rez;
|
||||
ref = k;
|
||||
}
|
||||
}
|
||||
f.VertexIndex[n] = ref;
|
||||
}
|
||||
}
|
||||
m.VBptr = nullptr;
|
||||
delete[] m.VertexBuffer;
|
||||
m.VertexBuffer = nullptr;
|
||||
delete[] m.OldVertexBuffer;
|
||||
m.OldVertexBuffer = nullptr;
|
||||
delete[] m.SavedVertexBuffer;
|
||||
m.SavedVertexBuffer = nullptr;
|
||||
|
||||
m.VertexBuffer = Body->MeshTable[0].VertexBuffer;
|
||||
m.NumVerts = Body->MeshTable[0].NumVerts;
|
||||
m.Flags |= T3D_MESH_CHARACTER; //this is a character
|
||||
}
|
||||
return shadow;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------30/12/98 11.27-------------------
|
||||
* t3dLoadCharacter
|
||||
* --------------------------------------------------*/
|
||||
t3dCHARACTER *t3dLoadCharacter(WGame &game, const char *pname, uint16 num) {
|
||||
warning("LoadCharacter(%s)", pname);
|
||||
uint8 Mirror = 1;
|
||||
uint16 numBody = 0, f;
|
||||
t3dV3F tmp;
|
||||
// gVertex *v;
|
||||
|
||||
t3dCHARACTER *b = new t3dCHARACTER[1] {};
|
||||
b->Body = _vm->_roomManager->loadRoom(pname, b->Body, &numBody, (T3D_NOLIGHTMAPS | T3D_NORECURSION | T3D_NOVOLUMETRICLIGHTS | T3D_NOCAMERAS | T3D_STATIC_SET0 | T3D_STATIC_SET1));
|
||||
if (!b->Body) {
|
||||
delete[] b;
|
||||
return nullptr;
|
||||
}
|
||||
b->Mesh = &b->Body->MeshTable[0];
|
||||
b->CurRoom = t3dCurRoom;
|
||||
b->Flags = T3D_CHARACTER_HIDE | T3D_CHARACTER_REALTIMELIGHTING;
|
||||
if (num >= 2) b->Flags |= T3D_CHARACTER_BNDHIDE;
|
||||
//Try to load animation
|
||||
if (t3dLoadAnimation(game, pname, b->Mesh, T3D_MESH_DEFAULTANIM) == -1) {
|
||||
warning("t3dLoadCharacter: Error loading %s", pname);
|
||||
delete[] b;
|
||||
return nullptr;
|
||||
}
|
||||
FixupAnim(b->Mesh, 0, "");
|
||||
|
||||
// Zero's all the Normals vars, 'cause I recalc all the normals runtime...
|
||||
b->Body->NumNormals = 0;
|
||||
b->Body->NumVerticesNormals = 0;
|
||||
|
||||
for (uint16 i = 0; i < b->Body->NumMeshes(); i++) {
|
||||
t3dMESH &mesh = b->Body->MeshTable[i];
|
||||
for (f = 0; f < mesh.NumFaces(); f++) {
|
||||
mesh.FList[f].n = nullptr;
|
||||
}
|
||||
//sb
|
||||
//sb mesh->Flags|=T3D_MESH_CASTREALTIMESHADOWS;
|
||||
//sb
|
||||
}
|
||||
b->Body->NList.clear();
|
||||
//sb
|
||||
//sb b->Flags|=T3D_CHARACTER_CASTREALTIMESHADOWS;
|
||||
//sb
|
||||
// Per gli specchi
|
||||
if (Mirror) { // Ogni personaggio potrebbe apparire in uno specchio
|
||||
b->Body->MirrorMatTable.resize(b->Body->NumMaterials());
|
||||
|
||||
rCopyMaterialList(b->Body->MirrorMatTable, b->Body->MatTable, b->Body->NumMaterials());
|
||||
}
|
||||
|
||||
// Per le ombre, altezza e raggio del cilindro
|
||||
b->Height = (t3dF32)sqrt(b->Mesh->BBox[0].p.x * b->Mesh->BBox[0].p.x + b->Mesh->BBox[0].p.z * b->Mesh->BBox[0].p.z);
|
||||
b->Radius = (t3dF32)sqrt(b->Mesh->BBox[5].p.x * b->Mesh->BBox[5].p.x + b->Mesh->BBox[5].p.z * b->Mesh->BBox[5].p.z);
|
||||
if (b->Radius < b->Height) b->Radius = b->Height;
|
||||
b->Height = (b->Mesh->BBox[0].p.y - b->Mesh->BBox[2].p.y) * 1.2f;
|
||||
|
||||
// No bounding box detection
|
||||
/* t3dVectFill(&b->Mesh->BBox[0].p,0.0f);
|
||||
t3dVectFill(&b->Mesh->BBox[1].p,0.0f);
|
||||
t3dVectFill(&b->Mesh->BBox[2].p,0.0f);
|
||||
t3dVectFill(&b->Mesh->BBox[3].p,0.0f);
|
||||
t3dVectFill(&b->Mesh->BBox[4].p,0.0f);
|
||||
t3dVectFill(&b->Mesh->BBox[5].p,0.0f);
|
||||
t3dVectFill(&b->Mesh->BBox[6].p,0.0f);
|
||||
t3dVectFill(&b->Mesh->BBox[7].p,0.0f);
|
||||
b->Mesh->Flags|=T3D_MESH_NOBOUNDBOX;
|
||||
*/
|
||||
for (uint16 i = 0; i < b->Body->NumMeshes(); i++) {
|
||||
b->Body->MeshTable[i].Flags |= T3D_MESH_CHARACTER;
|
||||
b->Body->MeshTable[i].Flags &= ~T3D_MESH_MIRROR;
|
||||
}
|
||||
|
||||
t3dVectFill(&b->Pos, 0.0f);
|
||||
t3dVectInit(&tmp, 0.0f, 0.0f, -1.0f);
|
||||
t3dVectAdd(&tmp, &b->Pos, &tmp);
|
||||
t3dMatView(&b->Mesh->Matrix, &b->Pos, &tmp);
|
||||
|
||||
b->Mesh->Matrix.Flags &= ~T3D_MATRIX_IDENTITY;
|
||||
b->Mesh->CurFrame = 4;
|
||||
b->Mesh->LastFrame = 0;
|
||||
b->Mesh->BlendPercent = 255;
|
||||
|
||||
b->Walk.OldPanel = -1;
|
||||
b->Walk.CurPanel = -1;
|
||||
b->Walk.NumPathNodes = -1;
|
||||
|
||||
t3dVectInit(&b->Dir, 0.0f, 0.0f, -1.0f);
|
||||
t3dVectTransform(&b->Dir, &b->Dir, &b->Mesh->Matrix); //rotate by Character angle
|
||||
|
||||
//sb
|
||||
if (num < 2)
|
||||
b->Shadow = LoadShadowMeshes(game, pname, b->Body);
|
||||
else
|
||||
b->Shadow = nullptr;
|
||||
//sb
|
||||
return b;
|
||||
}
|
||||
|
||||
/* -----------------25/09/98 16.07-------------------
|
||||
* GetFullLightPosition
|
||||
* --------------------------------------------------*/
|
||||
uint8 GetFullLightDirection(t3dV3F *dest, uint8 pos) {
|
||||
if (!pos) return 0;
|
||||
|
||||
auto pLights = t3dCurRoom->getPositionalLight(pos);
|
||||
for (const auto &light : pLights) {
|
||||
if (light.Dir.x && light.Dir.z) {
|
||||
*dest = light.Dir;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos != 99)
|
||||
DebugLogFile("Can't find fldir %d in %s", pos, t3dCurRoom->name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------21/12/98 16.40-------------------
|
||||
* ReleasePreloadedAnims
|
||||
* --------------------------------------------------*/
|
||||
void ReleasePreloadedAnims() {
|
||||
int32 i, j;
|
||||
|
||||
for (j = 0; j < MAX_PRELOADED_ANIMS; j++) {
|
||||
// Disalloca tutto
|
||||
for (i = 0; i < MAX_BONES; i++) {
|
||||
t3dFree(PreloadedAnim[j].Bone[i].Trasl);
|
||||
t3dFree(PreloadedAnim[j].Bone[i].Euler);
|
||||
}
|
||||
delete[] PreloadedAnim[j].Dist;
|
||||
PreloadedAnim[j] = t3dLOADANIM();
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------02/05/00 9.30--------------------
|
||||
* CompareLightPosition
|
||||
* --------------------------------------------------*/
|
||||
uint8 CompareLightPosition(char *roomname, uint8 pos1, t3dV3F *pos2, t3dF32 acceptable_dist) {
|
||||
t3dV3F p1;
|
||||
t3dBODY *t;
|
||||
|
||||
if ((pos1 <= 0) || (pos2 == nullptr)) return FALSE;
|
||||
|
||||
// cerco la stanza
|
||||
t = nullptr;
|
||||
if (roomname && (roomname[0] != '\0')) {
|
||||
t = _vm->_roomManager->getRoomIfLoaded(roomname);
|
||||
} else t = t3dCurRoom;
|
||||
|
||||
if (!t) return FALSE;
|
||||
|
||||
auto pLights = t->getPositionalLight(pos1);
|
||||
bool foundLight = false;
|
||||
for (auto &light : pLights) {
|
||||
if (light.Pos.x && light.Pos.z) {
|
||||
p1.x = light.Pos.x;
|
||||
p1.y = light.Pos.y;
|
||||
p1.z = light.Pos.z;
|
||||
foundLight = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundLight) return FALSE;
|
||||
|
||||
if (t3dVectSquaredDistance(&p1, pos2) <= acceptable_dist) return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
44
engines/watchmaker/3d/animation.h
Normal file
44
engines/watchmaker/3d/animation.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_ANIMATION_H
|
||||
#define WATCHMAKER_ANIMATION_H
|
||||
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/3d/t3d_body.h"
|
||||
#include "watchmaker/work_dirs.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
uint8 GetLightDirection(t3dV3F *dest, uint8 pos);
|
||||
unsigned char GetLightPosition(t3dV3F *dest, unsigned char pos);
|
||||
uint8 GetFullLightDirection(t3dV3F *dest, uint8 pos);
|
||||
|
||||
void FixupAnim(t3dMESH *mesh, unsigned char pos, const char *room);
|
||||
t3dBODY *LoadShadowMeshes(WGame &game, const char *pname, t3dBODY *Body);
|
||||
int8 t3dLoadAnimation(WGame &game, const char *s, t3dMESH *mesh, uint16 Flag);
|
||||
t3dCHARACTER *t3dLoadCharacter(WGame &game, const char *pname, uint16 num);
|
||||
void ReleasePreloadedAnims();
|
||||
uint8 CompareLightPosition(char *roomname, uint8 pos1, t3dV3F *pos2, t3dF32 acceptable_dist);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_ANIMATION_H
|
||||
105
engines/watchmaker/3d/dds_header.cpp
Normal file
105
engines/watchmaker/3d/dds_header.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/textconsole.h"
|
||||
#include "common/ptr.h"
|
||||
#include "watchmaker/3d/dds_header.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
DDSHeader::DDSHeader(Common::SeekableReadStream &stream) {
|
||||
//warning("TODO: Implement DDS Header parsing");
|
||||
uint32 retv = MKTAG(' ', 'S', 'D', 'D');
|
||||
uint32 magic = stream.readUint32LE();
|
||||
if (magic != retv) {
|
||||
error("parseDDSHeader: Wrong Magic, expected %08X, got %08X\n", retv, magic);
|
||||
}
|
||||
// The size counts the datastructure, which doesn't include the magic
|
||||
int initialPos = stream.pos();
|
||||
uint32 size = stream.readUint32LE();
|
||||
/*uint32 flags = */ stream.readUint32LE();
|
||||
this->height = stream.readUint32LE();
|
||||
this->width = stream.readUint32LE();
|
||||
/*uint32 dataSize = */ stream.readUint32LE();
|
||||
stream.seek(13 * 4, SEEK_CUR);
|
||||
stream.readUint32LE();
|
||||
uint32 pfFlags = stream.readUint32LE();
|
||||
assert(pfFlags & 0x4); // For now we assume compressed DDS only.
|
||||
compression = (DxtCompression)stream.readUint32LE();
|
||||
// Since we're ignoring a fair amount of header, we still need to position
|
||||
// ourselves as if we read it.
|
||||
stream.seek(initialPos + size, SEEK_SET);
|
||||
}
|
||||
|
||||
uint32 blockSize(DxtCompression compression) {
|
||||
switch (compression) {
|
||||
case DxtCompression::DXT1:
|
||||
return 8;
|
||||
default:
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 DDSHeader::dataSize() const {
|
||||
int blockCount = ceil(width / 4.0) * ceil(height / 4.0);
|
||||
return blockCount * blockSize(compression);
|
||||
}
|
||||
|
||||
class DDSTextureData : public TextureData {
|
||||
private:
|
||||
unsigned int _dataSize = 0;
|
||||
byte *_data = nullptr;
|
||||
DDSHeader _header;
|
||||
public:
|
||||
DDSTextureData(byte *data, uint32 dataSize, DDSHeader header) : TextureData(header.compression),
|
||||
_data(data),
|
||||
_dataSize(dataSize),
|
||||
_header(header) {}
|
||||
~DDSTextureData() override {
|
||||
delete[] _data;
|
||||
}
|
||||
int getWidth() const override {
|
||||
return _header.width;
|
||||
}
|
||||
int getHeight() const override {
|
||||
return _header.height;
|
||||
}
|
||||
int getDataSize() const override {
|
||||
return _dataSize;
|
||||
}
|
||||
const void *getData() const override {
|
||||
return _data;
|
||||
}
|
||||
};
|
||||
|
||||
Common::SharedPtr<TextureData> loadDdsTexture(Common::SeekableReadStream &stream) {
|
||||
DDSHeader header(stream);
|
||||
return loadDdsTexture(stream, header);
|
||||
}
|
||||
|
||||
Common::SharedPtr<TextureData> loadDdsTexture(Common::SeekableReadStream &stream, DDSHeader &header) {
|
||||
assert(header.width > 0);
|
||||
unsigned char *data = new unsigned char[header.dataSize()]();
|
||||
stream.read(data, header.dataSize());
|
||||
return Common::SharedPtr<TextureData>(new DDSTextureData(data, header.dataSize(), header));
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
73
engines/watchmaker/3d/dds_header.h
Normal file
73
engines/watchmaker/3d/dds_header.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DDSHEADER_H
|
||||
#define WATCHMAKER_DDSHEADER_H
|
||||
|
||||
#include "common/ptr.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
enum class DxtCompression : uint32 {
|
||||
UNCOMPRESSED = 0,
|
||||
DXT1 = MKTAG('1', 'T', 'X', 'D'),
|
||||
DXT2 = MKTAG('2', 'T', 'X', 'D'),
|
||||
DXT3 = MKTAG('3', 'T', 'X', 'D'),
|
||||
DXT4 = MKTAG('4', 'T', 'X', 'D'),
|
||||
DXT5 = MKTAG('5', 'T', 'X', 'D')
|
||||
};
|
||||
|
||||
class TextureData {
|
||||
public:
|
||||
DxtCompression _compression;
|
||||
TextureData(DxtCompression compression) : _compression(compression) {}
|
||||
virtual ~TextureData() {}
|
||||
virtual int getWidth() const = 0;
|
||||
virtual int getHeight() const = 0;
|
||||
virtual int getDataSize() const = 0;
|
||||
virtual const void *getData() const = 0;
|
||||
};
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
virtual ~Texture() {}
|
||||
virtual void assignData(const TextureData &data) = 0;
|
||||
virtual void bind() = 0;
|
||||
};
|
||||
|
||||
|
||||
struct DDSHeader {
|
||||
DDSHeader() {}
|
||||
DDSHeader(Common::SeekableReadStream &stream);
|
||||
int height = 0;
|
||||
int width = 0;
|
||||
uint32 dataSize() const;
|
||||
DxtCompression compression = DxtCompression::UNCOMPRESSED;
|
||||
};
|
||||
|
||||
//Common::SharedPtr<Texture> loadTgaTextureData(Common::SeekableReadStream &stream);
|
||||
Common::SharedPtr<TextureData> loadDdsTexture(Common::SeekableReadStream &stream, DDSHeader &header);
|
||||
Common::SharedPtr<TextureData> loadDdsTexture(Common::SeekableReadStream &stream);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DDSHEADER_H
|
||||
3412
engines/watchmaker/3d/geometry.cpp
Normal file
3412
engines/watchmaker/3d/geometry.cpp
Normal file
File diff suppressed because it is too large
Load Diff
90
engines/watchmaker/3d/geometry.h
Normal file
90
engines/watchmaker/3d/geometry.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_GEOMETRY_H
|
||||
#define WATCHMAKER_GEOMETRY_H
|
||||
|
||||
#include "watchmaker/t3d.h"
|
||||
|
||||
#define MAX_RECURSION_LEVEL 10
|
||||
|
||||
#define MAX_PARTICLES 10
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
#define LEFTCLIP 0
|
||||
#define RIGHTCLIP 1
|
||||
#define TOPCLIP 2
|
||||
#define BOTTOMCLIP 3
|
||||
#define NUMCLIPPLANES 4
|
||||
|
||||
extern t3dNORMAL ClipPlanes[NUMCLIPPLANES];
|
||||
|
||||
extern t3dBODY *t3dCurRoom, *t3dOrigRoom;
|
||||
extern t3dCAMERA *t3dCurCamera;
|
||||
extern t3dM3X3F t3dCurViewMatrix;
|
||||
extern t3dBODY *PortalCrossed;
|
||||
extern t3dCHARACTER *t3dCurCharacter;
|
||||
extern uint32 t3d_NumMeshesVisible;
|
||||
extern t3dMESH *t3d_VisibleMeshes[];
|
||||
|
||||
extern t3dBODY *t3dRxt;
|
||||
extern t3dBODY *t3dSky;
|
||||
//s extern t3dBODY *t3dSun;
|
||||
|
||||
extern uint8 FloorHit;
|
||||
extern t3dV3F t3d3dMousePos;
|
||||
extern t3dV3F FloorHitCoords;
|
||||
extern uint32 StatNumTris, StatNumVerts;
|
||||
|
||||
struct WindowInfo;
|
||||
|
||||
uint16 t3dBackfaceCulling(NormalList &normals, uint32 NumNormals, t3dV3F *eye);
|
||||
|
||||
void t3dReleaseBody(t3dBODY *b);
|
||||
void t3dReleaseCharacter(t3dCHARACTER *b);
|
||||
unsigned char t3dCreateSmokeParticle(unsigned int Num, unsigned char Type, unsigned int Opacity);
|
||||
void t3dCalcRejectedMeshFromPortal(t3dBODY *body);
|
||||
void t3dSetViewport(t3dCAMERA *cam, WindowInfo &info, t3dF32 fov, uint8 sup);
|
||||
t3dF32 t3dCheckWithFloor();
|
||||
void t3dCreateProceduralSky();
|
||||
void t3dCalcMeshBones(t3dMESH *mesh, int32 last);
|
||||
void t3dResetPipeline();
|
||||
void t3dRotateMoveCamera(t3dCAMERA *cam, t3dF32 AngleX, t3dF32 AngleY, t3dF32 AngleSpeed);
|
||||
void t3dReleaseParticles();
|
||||
void t3dResetMesh(t3dMESH *mesh);
|
||||
void t3dShowBoundingBox(t3dBODY *b);
|
||||
void t3dShowBounds(t3dPAN *p, uint32 numpan);
|
||||
bool t3dTransformBody(t3dBODY *b);
|
||||
void t3dTransformSky();
|
||||
bool t3dTransformCharacter(t3dCHARACTER *c);
|
||||
void t3dProcessPortals();
|
||||
t3dBODY *t3dCheckPortalCrossed(t3dV3F *a);
|
||||
void t3dSortMeshes();
|
||||
void QueueMaterialList(MaterialTable &MatList, unsigned int NumMat, signed short int ViewMatrixNum);
|
||||
void ProcessMaterialList();
|
||||
void t3dAddTriangle(t3dF32 x1, t3dF32 y1, t3dF32 x2, t3dF32 y2, t3dF32 x3, t3dF32 y3,
|
||||
int32 r, int32 g, int32 b, int32 a);
|
||||
void t3dAddQuad(t3dF32 x1, t3dF32 y1, t3dF32 x2, t3dF32 y2, t3dF32 x3, t3dF32 y3, t3dF32 x4, t3dF32 y4,
|
||||
int32 r, int32 g, int32 b, int32 a);
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_GEOMETRY_H
|
||||
464
engines/watchmaker/3d/light.cpp
Normal file
464
engines/watchmaker/3d/light.cpp
Normal file
@@ -0,0 +1,464 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_strcat
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_strcpy
|
||||
|
||||
#include "watchmaker/3d/light.h"
|
||||
#include "watchmaker/3d/geometry.h"
|
||||
#include "watchmaker/3d/loader.h"
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/3d/t3d_body.h"
|
||||
#include "watchmaker/3d/t3d_mesh.h"
|
||||
#include "watchmaker/file_utils.h"
|
||||
#include "watchmaker/game.h"
|
||||
#include "watchmaker/ll/ll_system.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/utils.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
/* -----------------29/05/99 11.41-------------------
|
||||
* Illumina un t3dVERTEX (per WmGen)
|
||||
* --------------------------------------------------*/
|
||||
uint8 LightVertex(t3dVERTEX *vv, t3dV3F *v, t3dLIGHT *light) {
|
||||
t3dF32 dist, direction, ang, deg, Intensity1 = 1.0f, Intensity2 = 1.0f;
|
||||
t3dV3F vdist, dir, finallight;
|
||||
t3dF32 half_hotspot = DEGREE_TO_RADIANS(light->HotSpot) * 0.5f,
|
||||
half_falloff = DEGREE_TO_RADIANS(light->FallOff) * 0.5f;
|
||||
|
||||
t3dVectSub(&vdist, v, &light->Source);
|
||||
dist = t3dVectMod(&vdist);
|
||||
|
||||
t3dVectFill(&finallight, 0.0f);
|
||||
|
||||
if ((light->Type & T3D_LIGHT_SPOTLIGHT)) {
|
||||
t3dVectSub(&dir, &light->Target, &light->Source); // Serve per Spot
|
||||
direction = t3dVectMod(&dir);
|
||||
|
||||
ang = (float)acos(t3dVectDot(&vdist, &dir) / (direction * dist));
|
||||
if ((ang > (half_hotspot))) {
|
||||
if (ang > (half_falloff)) {
|
||||
Intensity2 = 0.0f;
|
||||
Intensity1 = 0.0f;
|
||||
} else {
|
||||
Intensity1 = 1.0;
|
||||
deg = half_hotspot + (ang - half_hotspot);
|
||||
Intensity2 = (half_falloff - deg) / (half_falloff - half_hotspot);
|
||||
}
|
||||
} else {
|
||||
Intensity1 = 1.0;
|
||||
Intensity2 = 1.0;
|
||||
}
|
||||
|
||||
if ((light->Type & T3D_LIGHT_ATTENUATION)) {
|
||||
if ((dist > light->NearRange)) {
|
||||
if (dist > light->FarRange) {
|
||||
Intensity1 = 0.0f;
|
||||
Intensity2 = 0.0f;
|
||||
} else {
|
||||
dist = light->NearRange + (dist - light->NearRange);
|
||||
Intensity2 *= (light->FarRange - dist) / (light->FarRange - light->NearRange);
|
||||
Intensity1 *= 1.0f;
|
||||
}
|
||||
} else {
|
||||
Intensity1 *= 1.0f;
|
||||
Intensity2 *= 1.0f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((light->Type & T3D_LIGHT_ATTENUATION)) {
|
||||
if ((dist < light->NearRange)) {
|
||||
Intensity1 = 1.0f;
|
||||
Intensity2 = 1.0f;
|
||||
} else {
|
||||
Intensity1 = 1.0f;
|
||||
|
||||
if (dist > light->FarRange)
|
||||
Intensity2 = 0.0f;
|
||||
else {
|
||||
dist = light->NearRange + (dist - light->NearRange);
|
||||
Intensity2 *= (light->FarRange - dist) / (light->FarRange - light->NearRange);
|
||||
Intensity1 *= 1.0f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Intensity1 = 1.0;
|
||||
Intensity2 = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((Intensity1 == 0.0f) || (Intensity2 == 0.0f)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
finallight = light->Color * (Intensity1 * Intensity2 * light->Multiplier);
|
||||
|
||||
if (finallight.x > 255.0f) finallight.x = 255.0f;
|
||||
if (finallight.y > 255.0f) finallight.y = 255.0f;
|
||||
if (finallight.z > 255.0f) finallight.z = 255.0f;
|
||||
vv->r = (uint8)finallight.x;
|
||||
vv->g = (uint8)finallight.y;
|
||||
vv->b = (uint8)finallight.z;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* -----------------29/05/99 11.41-------------------
|
||||
* Illumina un gVertex (per game)
|
||||
* --------------------------------------------------*/
|
||||
uint8 LightgVertex(gVertex *v, t3dLIGHT *light) {
|
||||
t3dVERTEX vv;
|
||||
t3dV3F vt;
|
||||
|
||||
vt.x = v->x;
|
||||
vt.y = v->y;
|
||||
vt.z = v->z;
|
||||
|
||||
if (LightVertex(&vv, &vt, light))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -----------------29/05/99 11.55-------------------
|
||||
* setDirectoryAndName
|
||||
* --------------------------------------------------*/
|
||||
Common::String setDirectoryAndName(const Common::String &path, const Common::String &name) {
|
||||
int32 len = name.size();
|
||||
|
||||
auto backSlashPos = name.findLastOf("\\");
|
||||
|
||||
if (backSlashPos != Common::String::npos) {
|
||||
len = backSlashPos;
|
||||
}
|
||||
|
||||
return path + name.substr(0, len);
|
||||
}
|
||||
|
||||
/* -----------------29/05/99 12.03-------------------
|
||||
* LoadVolumetricMap
|
||||
* --------------------------------------------------*/
|
||||
void LoadVolumetricMap(WorkDirs &workDirs, const char *pname, t3dBODY *b) {
|
||||
uint32 i, j, k;
|
||||
|
||||
auto stream = workDirs.resolveFile(pname);
|
||||
if (!(stream)) {
|
||||
//t DebugLogWindow("File %s not found: assuming no volumetriclights informations",pname);
|
||||
return ;
|
||||
}
|
||||
|
||||
if ((i = stream->readSint32LE()) != VOLLIGHTFILEVERSION) {
|
||||
warning("Invalid File version: %s file version is: %d\t You need the version: %d", pname, i, VOLLIGHTFILEVERSION);
|
||||
return ;
|
||||
}
|
||||
|
||||
b->VolumetricLights = Common::SharedPtr<t3dVolLights>(new t3dVolLights());
|
||||
b->VolumetricLights->CellsSize = stream->readFloatLE();
|
||||
b->VolumetricLights->xcells = stream->readSint32LE();
|
||||
b->VolumetricLights->ycells = stream->readSint32LE();
|
||||
b->VolumetricLights->zcells = stream->readSint32LE();
|
||||
|
||||
b->VolumetricLights->VolMap.resize(b->VolumetricLights->ycells * b->VolumetricLights->xcells * b->VolumetricLights->zcells);
|
||||
for (i = 0; i < b->VolumetricLights->ycells - 1; i++) {
|
||||
for (j = 0; j < b->VolumetricLights->zcells - 1; j++) {
|
||||
for (k = 0; k < b->VolumetricLights->xcells - 1; k++) {
|
||||
b->VolumetricLights->VolMap[(k) + ((j)*b->VolumetricLights->xcells) + ((i)*b->VolumetricLights->xcells * b->VolumetricLights->zcells)] = stream->readByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------29/05/99 12.04-------------------
|
||||
* t3dLoadOutdoorLights
|
||||
* --------------------------------------------------*/
|
||||
void t3dLoadOutdoorLights(const char *pname, t3dBODY *b, int32 ora) {
|
||||
warning("STUBBED, t3dLoadOutdoorLights");
|
||||
#if 0
|
||||
t3dU32 i, j, k;
|
||||
t3dMESH *m;
|
||||
gVertex *gv;
|
||||
t3dU32 nverts;
|
||||
char Name[T3D_NAMELEN];
|
||||
t3dU32 len;
|
||||
DWORD *Buf, *t;
|
||||
t3dLIGHT *l;
|
||||
|
||||
if (!pname || !b) return;
|
||||
|
||||
i = 0;
|
||||
if (ora >= 1130) i++;
|
||||
if ((ora >= 1300) && (ora <= 1310)) i++;
|
||||
if (ora >= 1800) i++;
|
||||
if (ora >= 2030) i++;
|
||||
|
||||
if (i == (t3dU32)t3dCurOliSet) return;
|
||||
|
||||
len = strlen(pname);
|
||||
memset(Name, 0, sizeof(Name));
|
||||
strncpy(Name, pname, len - 4);
|
||||
strcat(Name, ".oli");
|
||||
|
||||
if (!(t3dOpenFile(Name))) {
|
||||
DebugLogWindow("Unable to open OLI file %s", Name);
|
||||
return ;
|
||||
}
|
||||
|
||||
if ((i = t3dRead32()) != OUTDOORLIGHTSFILEVERSION) {
|
||||
DebugLogWindow("Invalid File version: %s file version is: %d\t You need the version: %d", pname, i, VOLLIGHTFILEVERSION);
|
||||
return ;
|
||||
}
|
||||
|
||||
if ((nverts = t3dRead32()) != b->NumTotVerts) {
|
||||
DebugLogWindow("Old OLI File %s!", pname);
|
||||
t3dCurOliSet = i;
|
||||
t3dCreateProceduralSky();
|
||||
return ;
|
||||
}
|
||||
|
||||
Buf = t = (DWORD *)t3dMalloc(nverts * sizeof(DWORD));
|
||||
|
||||
t3dCurOliSet = 0;
|
||||
t3dCurTime = ora;
|
||||
if (ora >= 1130) {
|
||||
t3dReadData(Buf, nverts * sizeof(DWORD));
|
||||
t3dCurOliSet++;
|
||||
}
|
||||
if ((ora >= 1300) && (ora <= 1310)) {
|
||||
t3dReadData(Buf, nverts * sizeof(DWORD));
|
||||
t3dCurOliSet++;
|
||||
}
|
||||
if (ora >= 1800) {
|
||||
t3dReadData(Buf, nverts * sizeof(DWORD));
|
||||
t3dCurOliSet++;
|
||||
}
|
||||
if (ora >= 2030) {
|
||||
t3dReadData(Buf, nverts * sizeof(DWORD));
|
||||
t3dCurOliSet++;
|
||||
}
|
||||
|
||||
t3dReadData(Buf, nverts * sizeof(DWORD));
|
||||
t3dCloseFile();
|
||||
|
||||
for (i = 0, m = b->MeshTable; i < b->NumMeshes; i++, m++) {
|
||||
#ifndef WMGEN
|
||||
m->VBptr = m->VertexBuffer;
|
||||
#endif
|
||||
for (j = 0, gv = m->VBptr; j < m->NumVerts; j++, gv++, t++) {
|
||||
gv->diffuse = *t;
|
||||
}
|
||||
m->Flags |= T3D_MESH_UPDATEVB;
|
||||
#ifndef WMGEN
|
||||
m->VBptr = nullptr;
|
||||
#endif
|
||||
}
|
||||
t3dFree(Buf);
|
||||
|
||||
t3dVectCopy(&b->AmbientLight, &OliAmbient[t3dCurOliSet]);
|
||||
|
||||
l = b->LightTable;
|
||||
for (k = 0; k < b->NumLights; k++, l++) {
|
||||
if (l->Type & T3D_LIGHT_SOLARVARIATION) {
|
||||
if (l->Type & T3D_LIGHT_SUN)
|
||||
t3dVectCopy(&l->Source, &l->SolarPos[t3dCurOliSet]);
|
||||
t3dVectCopy(&l->Color, &l->SolarColor[t3dCurOliSet]);
|
||||
|
||||
l->Type |= T3D_LIGHT_LIGHTON;
|
||||
if ((t3dCurOliSet == 0) && (l->Type & T3D_LIGHT_OFF_MORNING)) l->Type &= ~T3D_LIGHT_LIGHTON;
|
||||
if ((t3dCurOliSet == 1) && (l->Type & T3D_LIGHT_OFF_AFTERNOON)) l->Type &= ~T3D_LIGHT_LIGHTON;
|
||||
if ((t3dCurOliSet == 2) && (l->Type & T3D_LIGHT_OFF_EVENING)) l->Type &= ~T3D_LIGHT_LIGHTON;
|
||||
if ((t3dCurOliSet == 3) && (l->Type & T3D_LIGHT_OFF_NIGHT)) l->Type &= ~T3D_LIGHT_LIGHTON;
|
||||
|
||||
if (l->Color.x > 255.0f) l->Color.x = 255.0f;
|
||||
if (l->Color.y > 255.0f) l->Color.y = 255.0f;
|
||||
if (l->Color.z > 255.0f) l->Color.z = 255.0f;
|
||||
if (l->Color.x < 0.0f) l->Color.x = 0.0f;
|
||||
if (l->Color.y < 0.0f) l->Color.y = 0.0f;
|
||||
if (l->Color.z < 0.0f) l->Color.z = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
t3dCreateProceduralSky();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* -----------------29/05/99 12.01-------------------
|
||||
* GetBoundaries
|
||||
* --------------------------------------------------*/
|
||||
void GetBoundaries(t3dBODY *b, t3dF32 *minx, t3dF32 *miny, t3dF32 *minz, t3dF32 *maxx, t3dF32 *maxy, t3dF32 *maxz) {
|
||||
gVertex *gv;
|
||||
|
||||
*minx = *miny = *minz = 999999999.9f;
|
||||
*maxx = *maxy = *maxz = -999999999.9f;
|
||||
|
||||
for (uint32 i = 0; i < b->NumMeshes(); i++) {
|
||||
#ifndef WMGEN
|
||||
gv = b->MeshTable[i].VertexBuffer;
|
||||
#else
|
||||
gv = (gVertex *)(m->VBptr);
|
||||
#endif
|
||||
|
||||
for (uint32 j = 0; j < b->MeshTable[i].NumVerts; j++, gv++) {
|
||||
if (gv->x < *minx) *minx = gv->x;
|
||||
if (gv->y < *miny) *miny = gv->y;
|
||||
if (gv->z < *minz) *minz = gv->z;
|
||||
|
||||
if (gv->x > *maxx) *maxx = gv->x;
|
||||
if (gv->y > *maxy) *maxy = gv->y;
|
||||
if (gv->z > *maxz) *maxz = gv->z;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
t3dLIGHT::t3dLIGHT(WGame &game, t3dBODY *b, WorkDirs &workDirs, Common::SeekableReadStream &stream) {
|
||||
Type = stream.readUint32LE(); // Legge tipo
|
||||
// DebugFile("%d: SPOT %X ATTEN %X SHAD %X",light,Light[light].Type&T3D_LIGHT_SPOTLIGHT,Light[light].Type&T3D_LIGHT_ATTENUATION,Light[light].Type&T3D_LIGHT_CASTSHADOWS);
|
||||
Source = t3dV3F(stream) * SCALEFACTOR; // Legge Source
|
||||
Target = t3dV3F(stream) * SCALEFACTOR; // Legge Target
|
||||
|
||||
HotSpot = stream.readFloatLE() * SCALEFACTOR;
|
||||
FallOff = stream.readFloatLE() * SCALEFACTOR;
|
||||
|
||||
Color = t3dV3F(stream); // Legge Color
|
||||
|
||||
NearRange = stream.readFloatLE() * SCALEFACTOR;
|
||||
FarRange = stream.readFloatLE() * SCALEFACTOR;
|
||||
|
||||
Multiplier = stream.readFloatLE();
|
||||
Flicker = stream.readByte();
|
||||
|
||||
t3dBackfaceCulling(b->NList, (uint16)(b->NumNormals + b->NumVerticesNormals), &Source); // Setta le facce che sono backface
|
||||
//f t3dPreLigthVertices(b->NList, b->VList, (t3dU16)b->NumVerts, &Light[light]); // Illumina facce che non sono backface
|
||||
|
||||
|
||||
if (Flicker) { // Aggiorna Vertici visibili per flicker
|
||||
Type |= T3D_LIGHT_PULSE;
|
||||
setupVisibleVerticesFromLight(b);
|
||||
AnimLight.LastRandomizer = 0;
|
||||
}
|
||||
|
||||
if (Type & T3D_LIGHT_FLARE) { // Se ha una flare
|
||||
//f Light[light].Type&=~T3D_LIGHT_LIGHTON; // La spegne
|
||||
FlareSize = stream.readFloatLE() * SCALEFACTOR; // Legge il size della flare
|
||||
|
||||
Common::String name = readT3dString(stream); // Legge nome dellaq texture
|
||||
Common::String appo;
|
||||
#ifndef WMGEN
|
||||
if (hasFileExtension(name, "avi")) {
|
||||
appo = workDirs._moviesDir + name; // altrimenti prende quello di default
|
||||
} else {
|
||||
appo = workDirs._mapsDir + name;; // altrimenti prende quello di default
|
||||
}
|
||||
#else
|
||||
strcpy(Appo, WmMapsDir);
|
||||
strcat(Appo, Name);
|
||||
#endif
|
||||
|
||||
#ifndef WMGEN
|
||||
if (!(game._renderer->addMaterial(Material[0], appo, 15, 0))) { // Aggiunge il materiale
|
||||
warning("File %s not found", appo.c_str());
|
||||
Material[0].Texture = nullptr;
|
||||
assert(false);
|
||||
}
|
||||
//f rAddNumFacesMaterial(&Light[light].Material[0], /*f2*/7); // Aggiunge 7 facce ???
|
||||
Material[0].addProperty(T3D_MATERIAL_FLARE); // Assegna al materiale la prop flare
|
||||
warning("TODO!, Implement the user vertex buffer");
|
||||
#if 0
|
||||
Light[light].Material[0].VB = rGetUserVertexBuffer();
|
||||
#endif
|
||||
warning("TODO: Lights");
|
||||
//Material[0].NumAllocatedVerts += 45;
|
||||
#endif
|
||||
}
|
||||
|
||||
Particle = nullptr;
|
||||
if (Type & T3D_LIGHT_CANDLESMOKE) { // Se ha una smoke-particle
|
||||
Particle = Common::SharedPtr<t3dParticle>(new t3dParticle(stream)); // Legge data
|
||||
}
|
||||
if (Type & T3D_LIGHT_SOLARVARIATION) { // Se ha una variazione in base al sole
|
||||
if (!(Type & T3D_LIGHT_OFF_MORNING)) {
|
||||
SolarPos[0] = t3dV3F(stream);
|
||||
SolarColor[0] = t3dV3F::fromStreamAsBytes(stream);
|
||||
}
|
||||
if (!(Type & T3D_LIGHT_OFF_AFTERNOON)) {
|
||||
t3dVectCopy(&SolarPos[1], &Source);
|
||||
t3dVectCopy(&SolarColor[1], &Color);
|
||||
}
|
||||
if (!(Type & T3D_LIGHT_OFF_EVENING)) {
|
||||
SolarPos[2] = t3dV3F(stream);
|
||||
SolarColor[2] = t3dV3F::fromStreamAsBytes(stream);
|
||||
}
|
||||
if (!(Type & T3D_LIGHT_OFF_NIGHT)) {
|
||||
SolarPos[3] = t3dV3F(stream);
|
||||
SolarColor[3] = t3dV3F::fromStreamAsBytes(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -----------------10/06/99 16.02-------------------
|
||||
* SetVisibleFromLight
|
||||
* --------------------------------------------------*/
|
||||
void t3dLIGHT::SetVisibleFromLight(gVertex *v) {
|
||||
AnimLight.VisVerts.push_back(v);
|
||||
}
|
||||
|
||||
|
||||
/* -----------------10/06/99 16.02-------------------
|
||||
* setupVisibleVerticesFromLight
|
||||
* --------------------------------------------------*/
|
||||
void t3dLIGHT::setupVisibleVerticesFromLight(t3dBODY *b) {
|
||||
gVertex *gv;
|
||||
for (uint32 k = 0; k < b->NumMeshes(); k++) {
|
||||
t3dMESH &m = b->MeshTable[k];
|
||||
#ifndef WMGEN
|
||||
m.VBptr = m.VertexBuffer;
|
||||
gv = m.VBptr;
|
||||
#else
|
||||
gv = m->VBptr;
|
||||
#endif
|
||||
for (int j = 0; j < m.NumVerts; j++, gv++)
|
||||
if (LightgVertex(gv, this))
|
||||
SetVisibleFromLight(gv);
|
||||
|
||||
#ifndef WMGEN
|
||||
gv = nullptr;
|
||||
m.VBptr = nullptr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
t3dPLIGHT::t3dPLIGHT(Common::SeekableReadStream &stream) {
|
||||
Num = stream.readByte(); // Legge numero pos
|
||||
|
||||
Pos.x = stream.readFloatLE(); // Legge Pos
|
||||
Pos.y = stream.readFloatLE();
|
||||
Pos.z = stream.readFloatLE();
|
||||
|
||||
Dir.x = stream.readFloatLE(); // Legge Dir
|
||||
Dir.y = stream.readFloatLE();
|
||||
Dir.z = stream.readFloatLE();
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
46
engines/watchmaker/3d/light.h
Normal file
46
engines/watchmaker/3d/light.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_LIGHT_H
|
||||
#define WATCHMAKER_LIGHT_H
|
||||
|
||||
#include "watchmaker/t3d.h"
|
||||
|
||||
#define LIGHT_MAPVERSION 1
|
||||
#define VOLLIGHTFILEVERSION 1
|
||||
#define OUTDOORLIGHTSFILEVERSION 2
|
||||
|
||||
#define LIGHT_COORDS (1<<0)
|
||||
#define LIGHT_LIGHTMAPS (1<<1)
|
||||
#define LIGHT_SHADOWMAPS (1<<2)
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void GetBoundaries(t3dBODY *b, float *minx, float *miny, float *minz, float *maxx, float *maxy, float *maxz);
|
||||
unsigned char LightgVertex(gVertex *v, t3dLIGHT *light);
|
||||
void t3dLoadOutdoorLights(const char *pname, t3dBODY *b, int32 ora);
|
||||
void LoadVolumetricMap(WorkDirs &workDirs, const char *pname, t3dBODY *b);
|
||||
Common::String setDirectoryAndName(const Common::String &path, const Common::String &name);
|
||||
uint8 LightVertex(t3dVERTEX *vv, t3dV3F *v, t3dLIGHT *light);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_LIGHT_H
|
||||
653
engines/watchmaker/3d/loader.cpp
Normal file
653
engines/watchmaker/3d/loader.cpp
Normal file
@@ -0,0 +1,653 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/loader.h"
|
||||
#include "common/stream.h"
|
||||
#include "watchmaker/3d/geometry.h"
|
||||
#include "watchmaker/3d/light.h"
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/3d/t3d_body.h"
|
||||
#include "watchmaker/3d/t3d_mesh.h"
|
||||
#include "watchmaker/game.h"
|
||||
#include "watchmaker/ll/ll_mesh.h"
|
||||
#include "watchmaker/ll/ll_system.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/utils.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/work_dirs.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
#define T3DFILEVERSION 11
|
||||
|
||||
t3dV3F CharCorrection;
|
||||
t3dF32 CurFloorY;
|
||||
int32 t3dCurTime = 900, t3dCurOliSet = 0;
|
||||
|
||||
t3dPathCamera::t3dPathCamera(Common::SeekableReadStream &stream) {
|
||||
NumCamera = stream.readByte();
|
||||
PathIndex = stream.readByte();
|
||||
Direction = stream.readByte();
|
||||
}
|
||||
|
||||
t3dCAMERA::t3dCAMERA(Common::SeekableReadStream &stream) {
|
||||
Index = stream.readByte();
|
||||
|
||||
Source = t3dV3F(stream) * SCALEFACTOR;
|
||||
Target = t3dV3F(stream) * SCALEFACTOR;
|
||||
|
||||
t3dVectCopy(&MaxTarget, &Target);
|
||||
|
||||
// Camera[camera].Fov=t3dReadReal();
|
||||
Fov = RADIANS_TO_DEGREE(stream.readFloatLE()); //FOV
|
||||
NearClipPlane = stream.readFloatLE() * SCALEFACTOR;
|
||||
FarClipPlane = stream.readFloatLE() * SCALEFACTOR;
|
||||
|
||||
int numPaths = stream.readByte();
|
||||
CameraPaths.reserve(numPaths);
|
||||
for (int i = 0; i < numPaths; i++) {
|
||||
CameraPaths.push_back(t3dPathCamera(stream));
|
||||
}
|
||||
}
|
||||
|
||||
t3dCAMERAPATH::t3dCAMERAPATH(Common::SeekableReadStream &stream) {
|
||||
int numPoints = stream.readSint16LE();
|
||||
CarrelloDist = stream.readSint32LE();
|
||||
|
||||
PList.resize(numPoints);
|
||||
for (int j = 0; j < numPoints; j++) {
|
||||
PList[j].x = stream.readFloatLE() * SCALEFACTOR;
|
||||
PList[j].y = stream.readFloatLE() * SCALEFACTOR;
|
||||
PList[j].z = stream.readFloatLE() * SCALEFACTOR;
|
||||
}
|
||||
}
|
||||
void decodeLoaderFlags(uint32 flags) {
|
||||
warning("%d: T3D_GENERATESHADOWMAPS", flags & T3D_GENERATESHADOWMAPS);
|
||||
warning("%d: T3D_NOLIGHTMAPS", flags & T3D_NOLIGHTMAPS);
|
||||
warning("%d: T3D_NORECURSION", flags & T3D_NORECURSION);
|
||||
warning("%d: T3D_HALFTEXTURESIZE", flags & T3D_HALFTEXTURESIZE);
|
||||
warning("%d: T3D_FULLSCREEN", flags & T3D_FULLSCREEN);
|
||||
warning("%d: T3D_FASTRENDERING", flags & T3D_FASTRENDERING);
|
||||
warning("%d: T3D_OUTDOORLIGHTS", flags & T3D_OUTDOORLIGHTS);
|
||||
warning("%d: T3D_NOVOLUMETRICLIGHTS", flags & T3D_NOVOLUMETRICLIGHTS);
|
||||
warning("%d: T3D_NOBOUNDS", flags & T3D_NOBOUNDS);
|
||||
warning("%d: T3D_NOCAMERAS", flags & T3D_NOCAMERAS);
|
||||
warning("%d: T3D_NONEXCLUSIVEMOUSE", flags & T3D_NONEXCLUSIVEMOUSE);
|
||||
warning("%d: T3D_RECURSIONLEVEL1", flags & T3D_RECURSIONLEVEL1);
|
||||
warning("%d: T3D_SKY", flags & T3D_SKY);
|
||||
warning("%d: T3D_PRELOAD_RXT", flags & T3D_PRELOAD_RXT);
|
||||
warning("%d: T3D_STATIC_SET0", flags & T3D_STATIC_SET0);
|
||||
warning("%d: T3D_STATIC_SET1", flags & T3D_STATIC_SET1);
|
||||
warning("%d: T3D_NOSHADOWS", flags & T3D_NOSHADOWS);
|
||||
warning("%d: T3D_NOICONS", flags & T3D_NOICONS);
|
||||
warning("%d: T3D_NOSOUND", flags & T3D_NOSOUND);
|
||||
warning("%d: T3D_PRELOADBASE", flags & T3D_PRELOADBASE);
|
||||
warning("%d: T3D_NOMUSIC", flags & T3D_NOMUSIC);
|
||||
warning("%d: T3D_DEBUGMODE", flags & T3D_DEBUGMODE);
|
||||
warning("%d: T3D_FASTFILE", flags & T3D_FASTFILE);
|
||||
warning("%d: T3D_HIPOLYPLAYERS", flags & T3D_HIPOLYPLAYERS);
|
||||
warning("%d: T3D_HIPOLYCHARACTERS", flags & T3D_HIPOLYCHARACTERS);
|
||||
}
|
||||
|
||||
Common::String constructPath(const Common::String &prefix, const Common::String &filename, const char *suffix) {
|
||||
Common::String name = prefix + filename;
|
||||
uint16 len = name.size();
|
||||
if (suffix != nullptr) {
|
||||
uint16 suffixLen = strlen(suffix);
|
||||
name = name.substr(0, len - suffixLen) + suffix;
|
||||
assert(suffixLen == 3);
|
||||
}
|
||||
return Common::String(Common::move(name));
|
||||
}
|
||||
|
||||
class RoomManagerImplementation : public RoomManager {
|
||||
WGame *_game;
|
||||
#define MAX_LOADED_FILES 100
|
||||
RecStruct LoadedFiles[MAX_LOADED_FILES];
|
||||
uint16 NumLoadedFiles = 0;
|
||||
public:
|
||||
RoomManagerImplementation(WGame *game) : _game(game) {}
|
||||
#define MAX_T3D_LOADLIST_ITEMS 50
|
||||
struct _t3dLOADLIST {
|
||||
Common::String pname = {};
|
||||
uint32 LoaderFlags = 0;
|
||||
t3dMESH *m = nullptr;
|
||||
};
|
||||
_t3dLOADLIST t3dLoadList[MAX_T3D_LOADLIST_ITEMS] = {};
|
||||
|
||||
void addToLoadList(t3dMESH *m, const Common::String &pname, uint32 _LoaderFlags) override {
|
||||
if (!pname.empty()) {
|
||||
int32 a;
|
||||
for (a = 0; a < MAX_T3D_LOADLIST_ITEMS; a++) {
|
||||
if (t3dLoadList[a].pname.empty()) {
|
||||
t3dLoadList[a].LoaderFlags = _LoaderFlags;
|
||||
t3dLoadList[a].m = m;
|
||||
t3dLoadList[a].pname = pname;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (a >= MAX_T3D_LOADLIST_ITEMS)
|
||||
warning("Cannot add %s to LoadList", pname.c_str());
|
||||
} else {
|
||||
warning("Invalid parameters invoking AddToLoadList()");
|
||||
warning("Mesh (%s), pname %s", m->name.c_str(), pname.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
_t3dLOADLIST* getFromLoadList() {
|
||||
for (int a = 0; a < MAX_T3D_LOADLIST_ITEMS; a++) {
|
||||
if (!t3dLoadList[a].pname.empty())
|
||||
return &t3dLoadList[a];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
t3dBODY *getRoomIfLoaded(const Common::String &roomname) override {
|
||||
t3dBODY *t = nullptr;
|
||||
for (int i = 0; i < NumLoadedFiles; i++)
|
||||
if ((LoadedFiles[i].b != nullptr) && LoadedFiles[i].b->name.equalsIgnoreCase(roomname))
|
||||
t = LoadedFiles[i].b;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
t3dBODY* loadRoom(const Common::String &pname, t3dBODY *b, uint16 *NumBody, uint32 LoaderFlags) override;
|
||||
t3dBODY* loadSingleRoom(const Common::String &pname, uint16 *NumBody, uint32 LoaderFlags);
|
||||
void hideRoomMeshesMatching(const Common::String &pname) override {
|
||||
for (int i = 0; i < NumLoadedFiles; i++)
|
||||
if (LoadedFiles[i].b)
|
||||
if (LoadedFiles[i].b->name.equalsIgnoreCase(pname)) {
|
||||
HideRoomMeshes(_game->init, LoadedFiles[i].b);
|
||||
}
|
||||
}
|
||||
Common::Array<t3dBODY*> getLoadedFiles() override {
|
||||
// TODO: This won't need to be a copy if we maintain a Common::Array only containing the valid ones.
|
||||
Common::Array<t3dBODY*> files;
|
||||
for (int i = 0; i < NumLoadedFiles; i++)
|
||||
if (LoadedFiles[i].b)
|
||||
files.push_back(LoadedFiles[i].b);
|
||||
return files;
|
||||
}
|
||||
t3dBODY *checkIfAlreadyLoaded(const Common::String &Name) override {
|
||||
if (Name.empty()) return nullptr;
|
||||
|
||||
for (uint16 i = 0; i < NumLoadedFiles; i++) {
|
||||
if ((LoadedFiles[i].b != nullptr) && /*(LoadedFiles[i].Name != nullptr) &&*/ (!LoadedFiles[i].name.empty()))
|
||||
if (LoadedFiles[i].name.equalsIgnoreCase(Name))
|
||||
return LoadedFiles[i].b;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
t3dMESH *linkMeshToStr(Init &init, const Common::String &str) override {
|
||||
if (str.empty()) return nullptr;
|
||||
|
||||
// Cerca tra le camere
|
||||
if (str.equalsIgnoreCase("camera"))
|
||||
return &init._globals._invVars.CameraDummy;
|
||||
// Cerca tra i personaggi
|
||||
for (uint16 i = 0; i < T3D_MAX_CHARACTERS; i++)
|
||||
if ((Character[i]) && (str.equalsIgnoreCase(init.Obj[i].getMeshLink(0))))
|
||||
return Character[i]->Mesh;
|
||||
// Cerca nelle stanze caricate
|
||||
for (uint16 i = 0; i < NumLoadedFiles; i++) {
|
||||
if (LoadedFiles[i].b)
|
||||
for (uint16 j = 0; j < LoadedFiles[i].b->NumMeshes(); j++) {
|
||||
if (str.equalsIgnoreCase(LoadedFiles[i].b->MeshTable[j].name))
|
||||
return &LoadedFiles[i].b->MeshTable[j];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
void releaseBody(const Common::String &name, const Common::String &altName) override {
|
||||
for (int j = 0; j < NumLoadedFiles; j++) {
|
||||
if (LoadedFiles[j].name.equalsIgnoreCase(name) || LoadedFiles[j].name.equalsIgnoreCase(altName)) {
|
||||
t3dReleaseBody(LoadedFiles[j].b);
|
||||
LoadedFiles[j].b = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void releaseLoadedFiles(uint32 exceptFlag) override {
|
||||
for (int i = 0; i < NumLoadedFiles; i++) {
|
||||
if (LoadedFiles[i].b && !(LoadedFiles[i].Flags & exceptFlag)) {
|
||||
t3dReleaseBody(LoadedFiles[i].b);
|
||||
LoadedFiles[i] = RecStruct(); // TODO: Deduplicate.
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
void loadFromList();
|
||||
};
|
||||
|
||||
RoomManager *RoomManager::create(WGame *game) {
|
||||
return new RoomManagerImplementation(game);
|
||||
}
|
||||
|
||||
/* -----------------10/06/99 16.04-------------------
|
||||
* t3dLoadRoom
|
||||
* --------------------------------------------------*/
|
||||
t3dBODY* RoomManagerImplementation::loadRoom(const Common::String &pname, t3dBODY *b, uint16 *NumBody, uint32 _LoaderFlags) {
|
||||
warning("t3dLoadRoom(%s, b, %d, %d)", pname.c_str(), *NumBody, _LoaderFlags);
|
||||
struct _t3dLOADLIST *l;
|
||||
t3dBODY *r = nullptr;
|
||||
t3dBODY *rez = nullptr;
|
||||
|
||||
// reset everything that was previously in the load list
|
||||
for (int i = 0; i < MAX_T3D_LOADLIST_ITEMS; i++) {
|
||||
t3dLoadList[i] = _t3dLOADLIST();
|
||||
}
|
||||
|
||||
// Add the base stanza to the upload list
|
||||
addToLoadList(nullptr, pname, _LoaderFlags);
|
||||
|
||||
while ((l = getFromLoadList())) {
|
||||
uint16 num = 0;
|
||||
if (l->m) {
|
||||
if ((rez = _vm->_roomManager->checkIfAlreadyLoaded(l->pname)))
|
||||
l->m->PortalList = rez;
|
||||
else {
|
||||
// if (l->m->Flags&T3D_MESH_PREPROCESSPORTAL)
|
||||
// body=l->m->PortalList = t3dLoadSingleRoom( l->pname, l->m->PortalList, &num, (l->LoaderFlags|T3D_HALFTEXTURESIZE) );
|
||||
// else
|
||||
// TODO: This should increase some refcount on the PortalList
|
||||
warning("TODO: Handle refcounts on PortalList");
|
||||
l->m->PortalList = loadSingleRoom(l->pname, &num, l->LoaderFlags);
|
||||
}
|
||||
} else
|
||||
r = loadSingleRoom(l->pname, NumBody, l->LoaderFlags);
|
||||
|
||||
*l = _t3dLOADLIST();
|
||||
}
|
||||
|
||||
if (!(_LoaderFlags & T3D_NORECURSION)) {
|
||||
for (uint16 i = 0; i < NumLoadedFiles; i++)
|
||||
if (LoadedFiles[i].b)
|
||||
t3dCalcRejectedMeshFromPortal(LoadedFiles[i].b);
|
||||
}
|
||||
|
||||
warning("Room loaded");
|
||||
return r;
|
||||
}
|
||||
|
||||
t3dBODY* RoomManagerImplementation::loadSingleRoom(const Common::String &_pname, uint16 *NumBody, uint32 _LoaderFlags) {
|
||||
//warning("t3dLoadSingleRoom(workDirs, %s, b, %d, %d)", _pname, *NumBody, _LoaderFlags);
|
||||
//decodeLoaderFlags(_LoaderFlags);
|
||||
Common::String pname(_pname);
|
||||
|
||||
WorkDirs &workdirs = _game->workDirs;
|
||||
|
||||
if (pname.equalsIgnoreCase("r1c.t3d"))
|
||||
if (((t3dCurTime >= 1300) && (t3dCurTime <= 1310)) || (t3dCurTime >= 1800)) //se viene cambiato l'orario cambiarlo anche in UpdateRoomVis...
|
||||
pname = "r1c-notte.t3d";
|
||||
if (pname.equalsIgnoreCase("r15.t3d"))
|
||||
if (((t3dCurTime >= 1300) && (t3dCurTime <= 1310)) || (t3dCurTime >= 1800))
|
||||
pname = "r15-notte.t3d";
|
||||
|
||||
auto name = constructPath(workdirs._t3dDir, pname);
|
||||
|
||||
//warning("t3dLoadSingleRoom opening(%s)", name.c_str());
|
||||
auto stream = openFile(name);
|
||||
if (!(stream)) { // Apre file
|
||||
warning("t3dLoadSingleRoom: Failed to open(%s)", name.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (*NumBody != 0) {
|
||||
// TODO: This currently means that we never free the dependant bodies.
|
||||
warning("Loading a dependant body, should also be deleted alongside the base body");
|
||||
}
|
||||
t3dBODY *b = new t3dBODY();
|
||||
|
||||
//warning("Loading %s ...", name.c_str());
|
||||
*b = t3dBODY(); // Azzera Body
|
||||
|
||||
uint16 fileVersion = stream->readByte();
|
||||
if (fileVersion != T3DFILEVERSION) { // Controlla la versione del file
|
||||
warning("%s file incompatible: current version: %d.\tFile version: %d", name.c_str(), T3DFILEVERSION, fileVersion);
|
||||
delete b;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
uint16 j = 1;
|
||||
while (j < MAX_LOADED_FILES && LoadedFiles[j].b != nullptr) {
|
||||
j++;
|
||||
}
|
||||
if (j >= MAX_LOADED_FILES) {
|
||||
warning("Too many t3d files loaded!");
|
||||
delete b;
|
||||
return nullptr;
|
||||
}
|
||||
if ((j + 1) > NumLoadedFiles)
|
||||
NumLoadedFiles = j + 1;
|
||||
|
||||
LoadedFiles[j].name = _pname; // Aggiunge il file alla lista
|
||||
LoadedFiles[j].Flags = LoaderFlags; // Aggiunge Flags alla lista
|
||||
LoadedFiles[j].b = b; // Aggiunge Body alla lista
|
||||
j = 0;
|
||||
}
|
||||
b->loadFromStream(*_game, pname, *stream, _LoaderFlags);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
t3dParticle::t3dParticle(Common::SeekableReadStream &stream) {
|
||||
t3dF32 difR1, difG1, difB1;
|
||||
t3dF32 difR2, difG2, difB2;
|
||||
Num = (uint32)stream.readFloatLE();
|
||||
Lung = stream.readFloatLE();
|
||||
Size = stream.readFloatLE();
|
||||
Seg1 = stream.readFloatLE();
|
||||
Seg2 = stream.readFloatLE();
|
||||
Dim1 = stream.readFloatLE() / 1000.0f;
|
||||
Dim2 = stream.readFloatLE() / 1000.0f;
|
||||
Speed = stream.readFloatLE() / 10.0f;
|
||||
Speed1 = stream.readFloatLE() / 10.0f;
|
||||
Speed2 = stream.readFloatLE() / 10.0f;
|
||||
Caos = stream.readFloatLE() / 10;
|
||||
Caos1 = stream.readFloatLE() / 10;
|
||||
Caos2 = stream.readFloatLE() / 10;
|
||||
Delay = (uint32)stream.readFloatLE();
|
||||
OR1 = (uint8)stream.readSint32LE();
|
||||
R1 = (uint8)stream.readSint32LE();
|
||||
G1 = (uint8)stream.readSint32LE();
|
||||
B1 = (uint8)stream.readSint32LE();
|
||||
R2 = (uint8)stream.readSint32LE();
|
||||
G2 = (uint8)stream.readSint32LE();
|
||||
B2 = (uint8)stream.readSint32LE();
|
||||
R3 = (uint8)stream.readSint32LE();
|
||||
G3 = (uint8)stream.readSint32LE();
|
||||
B3 = (uint8)stream.readSint32LE();
|
||||
Type = (uint8)stream.readSint32LE();
|
||||
|
||||
#ifndef WMGEN
|
||||
ParticleIndex = t3dCreateSmokeParticle(Num,
|
||||
Type,
|
||||
OR1);
|
||||
#endif
|
||||
difR1 = (R2 - R1) / (Seg1 / Speed1);
|
||||
difG1 = (G2 - G1) / (Seg1 / Speed1);
|
||||
difB1 = (B2 - B1) / (Seg1 / Speed1);
|
||||
difR2 = (R3 - R2) / (Seg2 / Speed2);
|
||||
difG2 = (G3 - G2) / (Seg2 / Speed2);
|
||||
difB2 = (B3 - B2) / (Seg2 / Speed2);
|
||||
R2 = difR1;
|
||||
G2 = difG1;
|
||||
B2 = difB1;
|
||||
R3 = difR2;
|
||||
G3 = difG2;
|
||||
B3 = difB2;
|
||||
}
|
||||
|
||||
/* -----------------24/05/00 10.24-------------------
|
||||
* t3dPrecalcLight
|
||||
* --------------------------------------------------*/
|
||||
void t3dPrecalcLight(t3dBODY *b, uint8 *sun) {
|
||||
t3dV3F tmp, l, *normal;
|
||||
t3dVERTEX vv;
|
||||
t3dF32 nlight;
|
||||
int32 k, aa, rr, gg, bb;
|
||||
uint32 i, j, cv;
|
||||
|
||||
for (i = 0, cv = 0; i < b->NumMeshes(); i++) { // Si ripassa tutte le mesh
|
||||
t3dMESH &Mesh = b->MeshTable[i];
|
||||
#ifndef WMGEN
|
||||
Mesh.VBptr = Mesh.VertexBuffer;
|
||||
#endif
|
||||
for (j = 0; j < Mesh.NumVerts; j++, cv++) { // Si passa tutti i vertici
|
||||
rr = RGBA_GETRED(Mesh.VBptr[j].diffuse);
|
||||
gg = RGBA_GETGREEN(Mesh.VBptr[j].diffuse);
|
||||
bb = RGBA_GETBLUE(Mesh.VBptr[j].diffuse);
|
||||
aa = RGBA_GETALPHA(Mesh.VBptr[j].diffuse);
|
||||
tmp.x = Mesh.VBptr[j].x;
|
||||
tmp.y = Mesh.VBptr[j].y;
|
||||
tmp.z = Mesh.VBptr[j].z;
|
||||
for (k = 0; k < (int)b->NumLights(); k++) { // Si passa tutte le luci
|
||||
if ((b->LightTable[k].Type & T3D_LIGHT_REALTIME) || (b->LightTable[k].Type & T3D_LIGHT_FLARE) || !(b->LightTable[k].Type & T3D_LIGHT_LIGHTON)) continue;
|
||||
|
||||
t3dVectSub(&l, &b->LightTable[k].Source, &tmp); // Calcola vettore luce->vertice
|
||||
t3dVectNormalize(&l); // lo normalizza
|
||||
|
||||
normal = &Mesh.NList[j]->n; // Calcola normale
|
||||
if ((nlight = t3dVectDot(normal, &l)) >= 0) {
|
||||
if (LightVertex(&vv, &tmp, &b->LightTable[k])) {
|
||||
if ((sun) && (!sun[cv]) && (b->LightTable[k].Type & T3D_LIGHT_SUN)) {
|
||||
rr += t3dFloatToInt(vv.r * nlight * 0.50f);
|
||||
gg += t3dFloatToInt(vv.g * nlight * 0.35f);
|
||||
bb += t3dFloatToInt(vv.b * nlight * 0.27f);
|
||||
} else {
|
||||
rr += t3dFloatToInt(vv.r * nlight);
|
||||
gg += t3dFloatToInt(vv.g * nlight);
|
||||
bb += t3dFloatToInt(vv.b * nlight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rr < 0) rr = 0;
|
||||
if (gg < 0) gg = 0;
|
||||
if (bb < 0) bb = 0;
|
||||
if (rr > 255) rr = 255;
|
||||
if (gg > 255) gg = 255;
|
||||
if (bb > 255) bb = 255;
|
||||
|
||||
Mesh.VBptr[j].diffuse = RGBA_MAKE(rr, gg, bb, aa);
|
||||
}
|
||||
#ifndef WMGEN
|
||||
Mesh.VBptr = nullptr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -----------------10/06/99 16.06-------------------
|
||||
* t3dLoadSky
|
||||
* --------------------------------------------------*/
|
||||
void t3dLoadSky(WGame &game, t3dBODY * /*body*/) {
|
||||
t3dF32 Skyminx, Skyminy, Skyminz, Skymaxx, Skymaxy, Skymaxz;
|
||||
uint16 n = 0, i;
|
||||
gVertex *gv;
|
||||
// t3dF32 Tile=1.5f;
|
||||
t3dF32 div;
|
||||
|
||||
if (!(t3dSky = _vm->_roomManager->loadRoom("sky.t3d", t3dSky, &n, T3D_NORECURSION | T3D_NOLIGHTMAPS | T3D_NOVOLUMETRICLIGHTS | T3D_NOCAMERAS | T3D_NOBOUNDS | T3D_STATIC_SET0))) {
|
||||
warning("Error during t3dLoadRoom: Sky not loaded");
|
||||
}
|
||||
|
||||
GetBoundaries(t3dSky, &Skyminx, &Skyminy, &Skyminz, &Skymaxx, &Skymaxy, &Skymaxz);
|
||||
|
||||
for (i = 0; i < t3dSky->NumMeshes(); i++) {
|
||||
gv = t3dSky->MeshTable[i].VertexBuffer;
|
||||
for (n = 0; n < t3dSky->MeshTable[i].NumVerts; n++, gv++) {
|
||||
gv->x -= Skyminx + ((Skymaxx - Skyminx) / 2.0f);
|
||||
gv->y -= Skyminy + ((Skymaxy - Skyminy) / 2.0f);
|
||||
gv->z -= Skyminz + ((Skymaxz - Skyminz) / 2.0f);
|
||||
div = (t3dF32)sqrt(gv->x * gv->x + gv->y * gv->y + gv->z * gv->z);
|
||||
gv->x /= div;
|
||||
gv->y /= div;
|
||||
gv->z /= div;
|
||||
|
||||
gv->x *= 15000;
|
||||
gv->y *= 500;
|
||||
gv->z *= 15000;
|
||||
|
||||
gv->u1 *= 1.0f;
|
||||
gv->v1 *= 1.0f;
|
||||
}
|
||||
|
||||
t3dSky->MeshTable[0].Radius = 15000.0f * 2;
|
||||
}
|
||||
|
||||
for (n = 0; n < t3dSky->NumNormals; n++) {
|
||||
t3dSky->NList[n]->dist *= 15000.0f;
|
||||
}
|
||||
|
||||
for (n = 0; n < t3dSky->NumMaterials(); n++) {
|
||||
t3dSky->MatTable[n]->addProperty(T3D_MATERIAL_SKY);
|
||||
t3dSky->MatTable[n]->addProperty(T3D_MATERIAL_NOLIGHTMAP);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------02/08/99 15.40-------------------
|
||||
* t3dAddVertexBuffer
|
||||
* --------------------------------------------------*/
|
||||
Common::SharedPtr<VertexBuffer> t3dAddVertexBuffer(t3dBODY *b, uint32 numv) {
|
||||
return b->addVertexBuffer();
|
||||
}
|
||||
|
||||
/* -----------------10/06/99 16.03-------------------
|
||||
* t3dOptimizeMaterialList
|
||||
* --------------------------------------------------*/
|
||||
void t3dOptimizeMaterialList(t3dBODY *b) {
|
||||
for (uint32 i = 0; i < b->NumMaterials(); i++) { // Scorre tutti materilai di un body
|
||||
MaterialPtr Mat = b->MatTable[i];
|
||||
if ((Mat == nullptr) || /*(!Mat->Texture->Name) ||*/ (Mat->Movie) || (Mat->hasFlag(T3D_MATERIAL_MOVIE))) // Se non esiste o non ha texture
|
||||
continue; // esce
|
||||
|
||||
for (uint32 j = 0; j < b->NumMaterials(); j++) { // Cerca materiali uguali
|
||||
MaterialPtr CurMat = b->MatTable[j];
|
||||
if (Mat == CurMat)
|
||||
continue;
|
||||
|
||||
if (CurMat == nullptr /*|| (!CurMat->Texture->Name)*/)
|
||||
continue;
|
||||
|
||||
if (Mat->Texture->name.equalsIgnoreCase(CurMat->Texture->name)) { // Se ha lo setsso nome di texture
|
||||
//warning("TODO: Implement Material-merging");
|
||||
// This is currently broken.
|
||||
|
||||
Mat = rMergeMaterial(Mat, CurMat); // Unisce i due materiali
|
||||
for (uint32 k = 0; k < b->NumMeshes(); k++) { // Aggiorna in tutte le mesh id materiale
|
||||
auto &m = b->MeshTable[k];
|
||||
for (int q = 0; q < m.NumFaces(); q++) {
|
||||
auto &f = m.FList[q];
|
||||
if (f.getMaterialIndex() == j)
|
||||
f.setMaterialIndex(i);
|
||||
}
|
||||
}
|
||||
warning("Deduplicating: %s (%d v %d", Mat->Texture->name.c_str(), i, j);
|
||||
b->MatTable[j] = nullptr; // TODO: This should probably happen in rMergeMaterial
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: The optimization leaves a bunch of materials as nullptr, we need to update all the
|
||||
// references to them. Currently we do this by subtracting 1 from all references that were above
|
||||
// a removed material. This works, but isn't really optimal.
|
||||
//int subtract = 0;
|
||||
for (uint32 i = 0; i < b->NumMaterials(); i++) {
|
||||
if (!b->MatTable[i]) {
|
||||
b->MatTable.remove_at(i);
|
||||
//subtract++;
|
||||
for (uint32 k = 0; k < b->NumMeshes(); k++) {
|
||||
auto &m = b->MeshTable[k];
|
||||
for (int q = 0; q < m.NumFaces(); q++) {
|
||||
auto &f = m.FList[q];
|
||||
if (f.getMaterialIndex() >= i) {
|
||||
f.setMaterialIndex(f.getMaterialIndex() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------30/07/99 10.55-------------------
|
||||
* t3dFinalizeMaterialList
|
||||
* --------------------------------------------------*/
|
||||
void t3dFinalizeMaterialList(t3dBODY *b) {
|
||||
for (uint32 i = 0; i < b->NumMeshes(); i++) {
|
||||
t3dMESH &Mesh = b->MeshTable[i];
|
||||
#ifndef WMGEN
|
||||
Mesh.VBptr = Mesh.VertexBuffer;
|
||||
#endif
|
||||
for (uint32 j = 0; j < Mesh.NumFaces(); j++) {
|
||||
t3dFACE &Face = Mesh.FList[j];
|
||||
MaterialPtr Mat = Face.getMaterial();
|
||||
if (Face.lightmap) {
|
||||
Mat = nullptr;
|
||||
for (const auto &material : Face.getMaterial()->AddictionalMaterial) {
|
||||
if (material->Texture->ID == Face.lightmap->Texture->ID) {
|
||||
Mat = material;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Mat == nullptr) {
|
||||
warning("%s: Can't find Lightmap Sub-Material!", Mesh.name.c_str());
|
||||
warning("%d %d", Face.getMaterial()->NumAddictionalMaterial, Face.lightmap->Texture->ID);
|
||||
for (const auto &material : Face.getMaterial()->AddictionalMaterial) {
|
||||
warning("%d", material->Texture->ID);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 k = 0;
|
||||
for (k = 0; k < (uint32)Mat->NumAllocatedMesh; k++)
|
||||
if (Mat->FlagsList[k] == &Mesh.Flags)
|
||||
break;
|
||||
|
||||
if (k >= (uint32)Mat->NumAllocatedMesh) {
|
||||
Mat->FlagsList.push_back(&Mesh.Flags);
|
||||
Mat->NumAllocatedMesh++;
|
||||
Mesh.Flags |= T3D_MESH_UPDATEVB;
|
||||
}
|
||||
Mesh.Flags |= T3D_MESH_UPDATEVB;
|
||||
|
||||
for (uint32 h = 0; h < 3; h++) {
|
||||
for (k = 0; k < (uint32)Mat->NumAllocatedVerts(); k++)
|
||||
if (Mat->VertsList[k] == &Mesh.VBptr[Face.VertexIndex[h]])
|
||||
break;
|
||||
|
||||
if (k >= (uint32)Mat->NumAllocatedVerts()) {
|
||||
Mat->VertsList.push_back(&Mesh.VBptr[Face.VertexIndex[h]]);
|
||||
}
|
||||
assert(k < Mat->VertsList.size());
|
||||
Face.setMatVertexIndex(h, k);
|
||||
}
|
||||
|
||||
}
|
||||
#ifndef WMGEN
|
||||
Mesh.VBptr = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < b->NumMaterials(); i++) {
|
||||
auto &Mat = b->MatTable[i];
|
||||
if (!Mat) {
|
||||
warning("nullptr");
|
||||
}
|
||||
Mat->VBO = b->addVertexBuffer(); // t3dAddVertexBuffer(b, Mat->NumAllocatedVerts);
|
||||
for (int j = 0; j < Mat->NumAddictionalMaterial; j++)
|
||||
Mat->AddictionalMaterial[j]->VBO = t3dAddVertexBuffer(b, Mat->AddictionalMaterial[j]->NumAllocatedVerts());
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
96
engines/watchmaker/3d/loader.h
Normal file
96
engines/watchmaker/3d/loader.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_LOADER_H
|
||||
#define WATCHMAKER_LOADER_H
|
||||
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/work_dirs.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
#define SCALEFACTOR 1.0f//(1.0f/7.0f)
|
||||
|
||||
#define MAX_MIRRORS 10
|
||||
|
||||
#define T3D_GENERATESHADOWMAPS (1<<0) //Generate shadow maps
|
||||
#define T3D_NOLIGHTMAPS (1<<1) //view without lightmaps
|
||||
#define T3D_NORECURSION (1<<2) //do not recurse sub-rooms mirrors, reflections
|
||||
#define T3D_HALFTEXTURESIZE (1<<3) //Half the texture dimension when load .t3d texture
|
||||
#define T3D_FULLSCREEN (1<<4) //run in fullscreen
|
||||
#define T3D_FASTRENDERING (1<<5) //render shadow/light maps with minimum dimension
|
||||
#define T3D_OUTDOORLIGHTS (1<<6) //load .oli files for outdoor lights informations
|
||||
#define T3D_NOVOLUMETRICLIGHTS (1<<7) //do not load .vol file
|
||||
#define T3D_NOBOUNDS (1<<8) //do not load .vol file
|
||||
#define T3D_NOCAMERAS (1<<9) //do not load .vol file
|
||||
#define T3D_NONEXCLUSIVEMOUSE (1<<10) // mouse is not in exclusive mode
|
||||
#define T3D_RECURSIONLEVEL1 (1<<12) // one recursion level only
|
||||
#define T3D_SKY (1<<13) // if the sky is visible
|
||||
#define T3D_PRELOAD_RXT (1<<14) // preload extern
|
||||
#define T3D_STATIC_SET0 (1<<15) // static loaded elements
|
||||
#define T3D_STATIC_SET1 (1<<16) // static loaded elements
|
||||
#define T3D_NOSHADOWS (1<<17) // do not calc shadows
|
||||
#define T3D_NOICONS (1<<18) // do not load icons
|
||||
#define T3D_NOSOUND (1<<19) // do not use sound system
|
||||
#define T3D_PRELOADBASE (1<<20) // preload basic elements
|
||||
#define T3D_NOMUSIC (1<<21) // do not use music system
|
||||
#define T3D_DEBUGMODE (1<<22) // debug mode
|
||||
#define T3D_FASTFILE (1<<23) // fastfile
|
||||
#define T3D_HIPOLYPLAYERS (1<<24) // hipoly players (darrell e victoria hipoly)
|
||||
#define T3D_HIPOLYCHARACTERS (1<<25) // hipoly characters (gli abitanti del castello hipoly)
|
||||
|
||||
// TODO: Unglobalize
|
||||
extern t3dV3F CharCorrection;
|
||||
extern t3dF32 CurFloorY;
|
||||
extern int32 t3dCurTime, t3dCurOliSet;
|
||||
|
||||
struct RecStruct {
|
||||
Common::String name;
|
||||
t3dBODY *b = nullptr;
|
||||
uint32 Flags = 0;
|
||||
};
|
||||
|
||||
void t3dOptimizeMaterialList(t3dBODY *b);
|
||||
void t3dFinalizeMaterialList(t3dBODY *b);
|
||||
void t3dPrecalcLight(t3dBODY *b, unsigned char *sun);
|
||||
void t3dLoadSky(WGame &game, t3dBODY *b);
|
||||
|
||||
Common::String constructPath(const Common::String &prefix, const Common::String &filename, const char *suffix = nullptr);
|
||||
|
||||
class RoomManager {
|
||||
public:
|
||||
virtual ~RoomManager() {}
|
||||
virtual void addToLoadList(t3dMESH *m, const Common::String &pname, uint32 LoaderFlags) = 0;
|
||||
virtual t3dBODY* loadRoom(const Common::String &pname, t3dBODY *b, uint16 *NumBody, uint32 LoaderFlags) = 0;
|
||||
static RoomManager *create(WGame *game);
|
||||
virtual t3dBODY *getRoomIfLoaded(const Common::String &roomname) = 0;
|
||||
virtual t3dMESH *linkMeshToStr(Init &init, const Common::String &str) = 0;
|
||||
virtual void hideRoomMeshesMatching(const Common::String &pname) = 0;
|
||||
virtual void releaseBody(const Common::String &name, const Common::String &altName) = 0;
|
||||
virtual void releaseLoadedFiles(uint32 exceptFlag) = 0;
|
||||
virtual t3dBODY *checkIfAlreadyLoaded(const Common::String &Name) = 0;
|
||||
virtual Common::Array<t3dBODY*> getLoadedFiles() = 0;
|
||||
};
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_LOADER_H
|
||||
299
engines/watchmaker/3d/material.cpp
Normal file
299
engines/watchmaker/3d/material.cpp
Normal file
@@ -0,0 +1,299 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/material.h"
|
||||
#include "common/util.h"
|
||||
#include "watchmaker/3d/render/opengl_2d.h"
|
||||
#include "watchmaker/render.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
MaterialPtr rAddMaterial(gMaterial &Material, const Common::String &TextName, int NumFaces, unsigned int LoaderFlags) {
|
||||
// TODO: This is duplicated in opengl_3d.cpp
|
||||
warning("TODO: Fix rAddMaterial");
|
||||
#if 0
|
||||
bool AlreadyLoaded = FALSE;
|
||||
int len = strlen(TextName);
|
||||
|
||||
if (((TextName[len - 1 - 0] == 'i') || (TextName[len - 1 - 0] == 'I')) &&
|
||||
((TextName[len - 1 - 1] == 'v') || (TextName[len - 1 - 1] == 'V')) &&
|
||||
((TextName[len - 1 - 2] == 'a') || (TextName[len - 1 - 2] == 'A'))) {
|
||||
if ((Material.Movie = gLoadMovie(TextName)) == NULL)
|
||||
return NULL;
|
||||
if ((Material.Texture = gUserTexture(64,
|
||||
128)) == NULL)
|
||||
// if( (Material->Texture=gUserTexture( Material->Movie->g_psiStreamInfo.rcFrame.right,
|
||||
// Material->Movie->g_psiStreamInfo.rcFrame.bottom)) == NULL )
|
||||
return NULL;
|
||||
Material.Flags |= T3D_MATERIAL_MOVIE;
|
||||
} else {
|
||||
if ((Material.Texture = gLoadTexture(TextName, LoaderFlags)) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//f
|
||||
//f Material->FacesList=(WORD *)t3dRealloc(Material->FacesList,sizeof(WORD)*3*NumFaces+1);
|
||||
//f Material->NumAllocatedFaces+=3*NumFaces+1;
|
||||
Material.FacesList.resize(Material.FacesList.size() + NumFaces * 3);
|
||||
Material.NumAllocatedFaces += NumFaces * 3;
|
||||
//f
|
||||
Material.Flags |= T3D_MATERIAL_NOLIGHTMAP;
|
||||
return Material;
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void gMaterial::addProperty(int flag) {
|
||||
this->Flags |= flag;
|
||||
}
|
||||
|
||||
void gMaterial::clearFlag(int flag) {
|
||||
this->Flags &= ~flag;
|
||||
}
|
||||
|
||||
bool gMaterial::hasFlag(int flag) {
|
||||
return this->Flags & flag;
|
||||
}
|
||||
|
||||
void gMaterial::addColor(unsigned char r_add, unsigned char g_add, unsigned char b_add) {
|
||||
int rr, gg, bb;
|
||||
|
||||
rr = this->r;
|
||||
gg = this->g;
|
||||
bb = this->b;
|
||||
|
||||
rr += r;
|
||||
gg += g;
|
||||
bb += b;
|
||||
|
||||
rr = MIN(MAX(rr, 0), 255);
|
||||
gg = MIN(MAX(gg, 0), 255);
|
||||
bb = MIN(MAX(bb, 0), 255);
|
||||
|
||||
this->r = (unsigned char)rr;
|
||||
this->g = (unsigned char)gg;
|
||||
this->b = (unsigned char)bb;
|
||||
}
|
||||
|
||||
bool gMaterial::addNumFacesAdditionalMaterial(MaterialPtr am, unsigned int num) {
|
||||
if (!num || !am)
|
||||
return false;
|
||||
|
||||
Common::SharedPtr<gMaterial> cm;
|
||||
int i;
|
||||
for (i = 0; i < this->NumAddictionalMaterial; i++) {
|
||||
cm = this->AddictionalMaterial[i];
|
||||
if (cm->Texture->ID == am->Texture->ID)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == this->NumAddictionalMaterial) {
|
||||
this->AddictionalMaterial.push_back(Common::SharedPtr<gMaterial>(new gMaterial(*am)));
|
||||
cm = this->AddictionalMaterial.back();
|
||||
cm->FacesList.resize(0);
|
||||
this->NumAddictionalMaterial++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gMaterial::addNumFaces(unsigned int num) {
|
||||
// TODO: Remove, as this is not necessary with a Common::Array
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
MaterialPtr rMergeMaterial(MaterialPtr Mat1, MaterialPtr Mat2) {
|
||||
if (!Mat1 || !Mat2)
|
||||
return nullptr;
|
||||
|
||||
for (int i = 0; i < Mat2->NumAddictionalMaterial; i++) {
|
||||
Mat1->addNumFacesAdditionalMaterial(Mat2->AddictionalMaterial[i],
|
||||
/*Mat2->AddictionalMaterial[i]->NumAllocatedFaces*/ Mat2->AddictionalMaterial[i]->NumFaces());
|
||||
}
|
||||
//reset mat2
|
||||
rRemoveMaterial(Mat2);
|
||||
*Mat2 = gMaterial();
|
||||
|
||||
return Mat1;
|
||||
}
|
||||
|
||||
void rRemoveMaterials(Common::Array<Common::SharedPtr<gMaterial>> &m) {
|
||||
for (auto &material : m) {
|
||||
material->clear();
|
||||
}
|
||||
m.clear();
|
||||
}
|
||||
|
||||
Common::SharedPtr<gMaterial> rCopyMaterial(Common::SharedPtr<gMaterial> Mat1, Common::SharedPtr<gMaterial> Mat2) {
|
||||
if (!Mat1 || !Mat2)
|
||||
return nullptr;
|
||||
|
||||
Mat1->clearFaceList();
|
||||
Mat1->AddictionalMaterial.clear();
|
||||
Mat1->clearFaceList();
|
||||
Mat1->VertsList.clear();
|
||||
//t3dFree(Mat1->FlagsList);
|
||||
*Mat1 = gMaterial();
|
||||
|
||||
if (Mat2->NumFaces()) {
|
||||
for (int i = 0; i < Mat2->NumFaces(); i++) {
|
||||
Mat1->addFace(Mat2->getFace(i));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < Mat2->NumFaces(); i++) {
|
||||
if (Mat2->getFace(i) >= Mat2->VertsList.size()) {
|
||||
warning("TODO");
|
||||
}
|
||||
}
|
||||
if (Mat2->NumAllocatedVerts()) {
|
||||
Mat1->VertsList = Mat2->VertsList;
|
||||
}
|
||||
if (Mat2->NumAllocatedMesh) {
|
||||
Mat1->FlagsList = Mat2->FlagsList;
|
||||
}
|
||||
|
||||
Mat1->Texture = Mat2->Texture;
|
||||
Mat1->Movie = Mat2->Movie;
|
||||
Mat1->Flags = Mat2->Flags;
|
||||
Mat1->VBO = Mat2->VBO;
|
||||
Mat1->NumAllocatedMesh = Mat2->NumAllocatedMesh;
|
||||
Mat1->r = Mat2->r;
|
||||
Mat1->g = Mat2->g;
|
||||
Mat1->b = Mat2->b;
|
||||
Mat1->NumAddictionalMaterial = Mat2->NumAddictionalMaterial;
|
||||
|
||||
rCopyMaterialList(Mat1->AddictionalMaterial, Mat2->AddictionalMaterial, Mat2->NumAddictionalMaterial); // TODO: Does this mean that we don't copy any extras?
|
||||
|
||||
return Mat1;
|
||||
}
|
||||
|
||||
void rCopyMaterialList(MaterialTable &dst, MaterialTable &src, uint count) {
|
||||
dst.resize(count);
|
||||
if (count > src.size()) {
|
||||
error("Copying more materials than there are in the src");
|
||||
}
|
||||
for (uint i = 0; i < count; i++) {
|
||||
if (!dst[i]) {
|
||||
dst[i] = Common::SharedPtr<gMaterial>(new gMaterial());
|
||||
}
|
||||
rCopyMaterial(dst[i], src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void gMaterial::clear() {
|
||||
// TODO: This flag clearing doesn't happen in the original, but shouldn't matter as the class is instantiated again when used in Particles.
|
||||
Flags = 0;
|
||||
|
||||
if (Movie) {
|
||||
Movie = nullptr;
|
||||
}
|
||||
FacesList.clear();
|
||||
VertsList.clear();
|
||||
FlagsList.clear();
|
||||
// rDeleteVertexBuffer(m->VB);
|
||||
VBO = 0;
|
||||
|
||||
for (int j = 0; j < NumAddictionalMaterial; j++) {
|
||||
Common::SharedPtr<gMaterial> cm = AddictionalMaterial[j];
|
||||
cm->FacesList.clear();
|
||||
cm->VertsList.clear();
|
||||
cm->FlagsList.clear();
|
||||
// rDeleteVertexBuffer(cm->VB);
|
||||
cm->VBO = 0;
|
||||
}
|
||||
AddictionalMaterial.clear();
|
||||
}
|
||||
|
||||
|
||||
void rRemoveMaterial(Common::SharedPtr<gMaterial> &m) {
|
||||
m->clear();
|
||||
}
|
||||
|
||||
|
||||
/* -----------------29/07/99 15.53-------------------
|
||||
* Aggiunge un materiale alla MaterialList
|
||||
* --------------------------------------------------*/
|
||||
void rAddToMaterialList(gMaterial &mat, signed short int ViewMatrixNum) {
|
||||
gBatchBlock *bb = nullptr;
|
||||
|
||||
if ((mat.Flags & T3D_MATERIAL_MOVIE)) {
|
||||
warning("Movie: %s %d", mat.Movie->_name.c_str(), mat.Texture->ID);
|
||||
mat.Movie->updateMovie();
|
||||
}
|
||||
|
||||
if ((mat.NumFaces() >= 3) && (mat.VBO)) {
|
||||
if (mat.Texture) {
|
||||
// if (mat.Texture->name == "./TMaps/bianco.tga")
|
||||
// return;
|
||||
}
|
||||
bb = rNewBatchBlock(mat.Texture->ID, mat.Flags, 0, 0);
|
||||
bb->ViewMatrixNum = ViewMatrixNum;
|
||||
bb->FacesList = mat.getFacesList();
|
||||
bb->VBO = mat.VBO;
|
||||
for (uint f = 0; f < bb->FacesList.size(); f++) {
|
||||
if (bb->FacesList[f] >= bb->VBO->_buffer.size()) {
|
||||
for (uint o = 0; o < bb->FacesList.size(); o++) {
|
||||
warning("%d", bb->FacesList[o]);
|
||||
}
|
||||
warning("%d > %d (%d)", bb->FacesList[f], bb->VBO->_buffer.size(), bb->NumVerts());
|
||||
}
|
||||
}
|
||||
mat.emptyFacesList(); // We may want to keep the reservation to avoid the extra reallocs here.
|
||||
}
|
||||
|
||||
for (auto &cm : mat.AddictionalMaterial) {
|
||||
if (cm->NumFaces() < 3) continue;
|
||||
if (cm->VBO == NULL) continue;
|
||||
bb = rNewBatchBlock(mat.Texture->ID, mat.Flags, cm->Texture->ID, cm->Flags);
|
||||
bb->ViewMatrixNum = ViewMatrixNum;
|
||||
bb->FacesList = cm->getFacesList();
|
||||
bb->VBO = cm->VBO;
|
||||
cm->emptyFacesList();
|
||||
}
|
||||
}
|
||||
|
||||
void rAddToMaterialList(MaterialPtr mat, signed short int ViewMatrixNum) {
|
||||
if (mat) {
|
||||
rAddToMaterialList(*mat, ViewMatrixNum);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------31/05/99 10.07-------------------
|
||||
* Costruisce la lista dei materiali ordinata
|
||||
* --------------------------------------------------*/
|
||||
void rBuildMaterialList(MaterialTable &MatList, unsigned int NumMat, signed short int ViewMatrixNum) {
|
||||
if (NumMat == 0)
|
||||
return;
|
||||
|
||||
for (auto &mat : MatList) {
|
||||
rAddToMaterialList(mat, ViewMatrixNum);
|
||||
}
|
||||
}
|
||||
|
||||
MaterialTable rCreateMaterialList(int num) {
|
||||
MaterialTable list;
|
||||
// We avoid actually allocating the gMaterial-objects, as we want the size() to
|
||||
// represent the actually loaded elements.
|
||||
list.reserve(num);
|
||||
return list;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
99
engines/watchmaker/3d/material.h
Normal file
99
engines/watchmaker/3d/material.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_MATERIAL_H
|
||||
#define WATCHMAKER_MATERIAL_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/ptr.h"
|
||||
#include "watchmaker/3d/texture.h"
|
||||
#include "watchmaker/3d/movie.h"
|
||||
#include "watchmaker/3d/vertex.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
struct gMaterial;
|
||||
typedef Common::SharedPtr<gMaterial> MaterialPtr;
|
||||
typedef Common::Array<MaterialPtr> MaterialTable;
|
||||
|
||||
struct VertexBuffer;
|
||||
// Material definition
|
||||
struct gMaterial {
|
||||
gTexture *Texture = nullptr; // pointer to texture struct
|
||||
Common::SharedPtr<gMovie> Movie; // pointer to movie struct
|
||||
unsigned int Flags = 0; // material flags
|
||||
int NumFaces() {
|
||||
return FacesList.size();
|
||||
}; // current number of faces to be processed
|
||||
void addFace(uint16 face) {
|
||||
FacesList.push_back(face);
|
||||
}
|
||||
uint16 getFace(int index) const {
|
||||
return FacesList[index];
|
||||
}
|
||||
void clearFaceList() {
|
||||
FacesList.clear();
|
||||
}
|
||||
void emptyFacesList() {
|
||||
FacesList.resize(0);
|
||||
}
|
||||
Common::Array<uint16> getFacesList() {
|
||||
return FacesList;
|
||||
}
|
||||
private:
|
||||
Common::Array<uint16> FacesList; // list of verts indices
|
||||
public:
|
||||
Common::Array<gVertex *> VertsList; // pointers to pointers to verts
|
||||
int NumAllocatedVerts() {
|
||||
return this->VertsList.size();
|
||||
}; // number of allocated vertex in mat VB
|
||||
Common::SharedPtr<VertexBuffer> VBO = nullptr;
|
||||
// LPDIRECT3DVERTEXBUFFER7 VB; // mat VB struct
|
||||
int NumAllocatedMesh = 0; // num mesh to check for modifications
|
||||
Common::Array<unsigned int *> FlagsList; // vector of pointer to mesh flags
|
||||
unsigned char r, g, b; // default material color
|
||||
int NumAddictionalMaterial = 0; // number of addictional material (lightmaps)
|
||||
MaterialTable AddictionalMaterial; // pointer to addictional material struct
|
||||
public:
|
||||
gMaterial() : r(0), g(0), b(0) {
|
||||
|
||||
}
|
||||
void addColor(unsigned char r, unsigned char g, unsigned char b);
|
||||
void addProperty(int flag);
|
||||
bool hasFlag(int flag);
|
||||
void clearFlag(int flag);
|
||||
bool addNumFaces(unsigned int num);
|
||||
bool addNumFacesAdditionalMaterial(MaterialPtr am, unsigned int num);
|
||||
void clear();
|
||||
};
|
||||
|
||||
MaterialPtr rAddMaterial(MaterialTable &MList, const Common::String &TextName, int NumFaces, unsigned int LoaderFlags);
|
||||
MaterialPtr rAddMaterial(gMaterial &Material, const Common::String &TextName, int NumFaces, unsigned int LoaderFlags);
|
||||
void rRemoveMaterial(MaterialPtr &m);
|
||||
void rRemoveMaterials(MaterialTable &m);
|
||||
void rCopyMaterialList(MaterialTable &dst, MaterialTable &src, uint count);
|
||||
MaterialPtr rMergeMaterial(MaterialPtr Mat1, MaterialPtr Mat2);
|
||||
void rAddToMaterialList(gMaterial &mat, signed short int ViewMatrixNum);
|
||||
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_MATERIAL_H
|
||||
26
engines/watchmaker/3d/math/Matrix4x4.cpp
Normal file
26
engines/watchmaker/3d/math/Matrix4x4.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/math/Matrix4x4.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
69
engines/watchmaker/3d/math/Matrix4x4.h
Normal file
69
engines/watchmaker/3d/math/Matrix4x4.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_MATRIX4X4_H
|
||||
#define WATCHMAKER_MATRIX4X4_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
struct Matrix4x4 {
|
||||
float data[16] = {};
|
||||
|
||||
void setIdentity() {
|
||||
setValue(1, 1, 1.0f);
|
||||
setValue(2, 2, 1.0f);
|
||||
setValue(3, 3, 1.0f);
|
||||
setValue(4, 4, 1.0f);
|
||||
}
|
||||
|
||||
void setValue(int row, int col, float value) {
|
||||
data[(col - 1) * 4 + (row - 1)] = value;
|
||||
}
|
||||
float getValue(int row, int col) const {
|
||||
return data[(col - 1) * 4 + (row - 1)];
|
||||
}
|
||||
void print() const {
|
||||
for (int row = 1; row <= 4; row++) {
|
||||
for (int col = 1; col <= 4; col++) {
|
||||
warning("%f ", getValue(row, col));
|
||||
}
|
||||
warning(" ");
|
||||
}
|
||||
}
|
||||
bool operator==(const Matrix4x4 &rhs) const {
|
||||
for (int row = 1; row <= 4; row++) {
|
||||
for (int col = 1; col <= 4; col++) {
|
||||
if (getValue(row, col) != rhs.getValue(row, col)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_MATRIX4X4_H
|
||||
427
engines/watchmaker/3d/math/llmath.cpp
Normal file
427
engines/watchmaker/3d/math/llmath.cpp
Normal file
@@ -0,0 +1,427 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/utils.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
int32 t3dFloatToInt(t3dF32 nfloat) {
|
||||
int32 sint = nfloat;
|
||||
// warning("STUBBED: t3dFloatToInt");
|
||||
/*
|
||||
__asm
|
||||
{
|
||||
fld nfloat
|
||||
fistp sint
|
||||
}*/
|
||||
return sint;
|
||||
}
|
||||
|
||||
void t3dMatIdentity(t3dM3X3F *d) {
|
||||
d->M[1] = d->M[2] = d->M[3] = d->M[5] = d->M[6] = d->M[7] = 0.0;
|
||||
d->M[0] = d->M[4] = d->M[8] = 1.0;
|
||||
|
||||
d->Flags |= T3D_MATRIX_IDENTITY;
|
||||
}
|
||||
|
||||
void t3dMatMul(t3dM3X3F *Dest, t3dM3X3F *a, t3dM3X3F *b) {
|
||||
t3dM3X3F Tmp, *d = &Tmp;
|
||||
/* t3dM3X3F Tmp,*d=&Tmp;
|
||||
int r,c;
|
||||
|
||||
if (Dest == a || Dest == b)
|
||||
d=&Tmp;
|
||||
else
|
||||
d=Dest;
|
||||
|
||||
for (r=0; r<3; r++)
|
||||
for (c=0; c<3; c++)
|
||||
d->M[r][c]=a->M[r][0]*b->M[0][c]+a->M[r][1]*b->M[1][c]+a->M[r][2]*b->M[2][c];*/
|
||||
|
||||
d->M[0] = (a->M[0] * b->M[0] + a->M[1] * b->M[3] + a->M[2] * b->M[6]);
|
||||
d->M[1] = (a->M[0] * b->M[1] + a->M[1] * b->M[4] + a->M[2] * b->M[7]);
|
||||
d->M[2] = (a->M[0] * b->M[2] + a->M[1] * b->M[5] + a->M[2] * b->M[8]);
|
||||
|
||||
d->M[3] = (a->M[3] * b->M[0] + a->M[4] * b->M[3] + a->M[5] * b->M[6]);
|
||||
d->M[4] = (a->M[3] * b->M[1] + a->M[4] * b->M[4] + a->M[5] * b->M[7]);
|
||||
d->M[5] = (a->M[3] * b->M[2] + a->M[4] * b->M[5] + a->M[5] * b->M[8]);
|
||||
|
||||
d->M[6] = (a->M[6] * b->M[0] + a->M[7] * b->M[3] + a->M[8] * b->M[6]);
|
||||
d->M[7] = (a->M[6] * b->M[1] + a->M[7] * b->M[4] + a->M[8] * b->M[7]);
|
||||
d->M[8] = (a->M[6] * b->M[2] + a->M[7] * b->M[5] + a->M[8] * b->M[8]);
|
||||
|
||||
if (d != Dest)
|
||||
t3dMatCopy(Dest, &Tmp);
|
||||
|
||||
}
|
||||
|
||||
void t3dMatCopy(t3dM3X3F *d, t3dM3X3F *s) {
|
||||
d->M[0] = s->M[0];
|
||||
d->M[1] = s->M[1];
|
||||
d->M[2] = s->M[2];
|
||||
d->M[3] = s->M[3];
|
||||
d->M[4] = s->M[4];
|
||||
d->M[5] = s->M[5];
|
||||
d->M[6] = s->M[6];
|
||||
d->M[7] = s->M[7];
|
||||
d->M[8] = s->M[8];
|
||||
d->Flags = 0;
|
||||
}
|
||||
|
||||
void t3dMatView(t3dM3X3F *dest, t3dV3F *eye, t3dV3F *center) {
|
||||
t3dM3X3F *fm = dest;
|
||||
t3dM3X3F fmat;
|
||||
|
||||
// D3DVECTOR from,at,up;
|
||||
|
||||
if ((!eye) || (!dest)) return;
|
||||
|
||||
// F
|
||||
t3dF32 dx = (t3dF32)(center->x - eye->x);
|
||||
t3dF32 dy = (t3dF32)(center->y - eye->y);
|
||||
t3dF32 dz = (t3dF32)(center->z - eye->z);
|
||||
|
||||
t3dF32 dd = (dx * dx + dy * dy + dz * dz);
|
||||
if (dd == 0.0)dd = 1.0;
|
||||
dd = (float)sqrt((t3dF64)dd); // dd = ||F||
|
||||
|
||||
t3dF32 d2 = (dz * dz + dx * dx);
|
||||
if (d2 == 0.0)d2 = 1.0;
|
||||
d2 = (float)sqrt((t3dF64)d2); // |s|
|
||||
|
||||
t3dF32 fcosa = (dz / d2);
|
||||
t3dF32 fsina = (dx / d2);
|
||||
fm->M[0] = fcosa;
|
||||
fm->M[1] = 0;
|
||||
fm->M[2] = -fsina;
|
||||
fm->M[3] = 0;
|
||||
fm->M[4] = 1;
|
||||
fm->M[5] = 0;
|
||||
fm->M[6] = fsina;
|
||||
fm->M[7] = 0;
|
||||
fm->M[8] = fcosa;
|
||||
|
||||
fcosa = (d2 / dd);
|
||||
fsina = (dy / dd);
|
||||
fmat.M[0] = 1;
|
||||
fmat.M[1] = 0;
|
||||
fmat.M[2] = 0;
|
||||
fmat.M[3] = 0;
|
||||
fmat.M[4] = fcosa;
|
||||
fmat.M[5] = -fsina;
|
||||
fmat.M[6] = 0;
|
||||
fmat.M[7] = fsina;
|
||||
fmat.M[8] = fcosa;
|
||||
t3dMatMul(dest, &fmat, dest);
|
||||
|
||||
const float roll = 0.0f;
|
||||
fcosa = (t3dF32)cos((-roll) / 180.0f * T3D_PI);
|
||||
fsina = (t3dF32)sin((-roll) / 180.0f * T3D_PI);
|
||||
fmat.M[0] = fcosa;
|
||||
fmat.M[1] = fsina;
|
||||
fmat.M[2] = 0;
|
||||
fmat.M[3] = -fsina;
|
||||
fmat.M[4] = fcosa;
|
||||
fmat.M[5] = 0;
|
||||
fmat.M[6] = 0;
|
||||
fmat.M[7] = 0;
|
||||
fmat.M[8] = 1;
|
||||
t3dMatMul(dest, &fmat, dest);
|
||||
|
||||
dest->Flags &= ~T3D_MATRIX_IDENTITY;
|
||||
}
|
||||
|
||||
void t3dVectTransform(t3dV3F *d, t3dV3F *s, t3dM3X3F *mat) {
|
||||
t3dV3F Tmp;
|
||||
Tmp.x = (s->x * mat->M[0]) + (s->y * mat->M[1]) + (s->z * mat->M[2]);
|
||||
Tmp.y = (s->x * mat->M[3]) + (s->y * mat->M[4]) + (s->z * mat->M[5]);
|
||||
Tmp.z = (s->x * mat->M[6]) + (s->y * mat->M[7]) + (s->z * mat->M[8]);
|
||||
d->x = Tmp.x;
|
||||
d->y = Tmp.y;
|
||||
d->z = Tmp.z;
|
||||
}
|
||||
|
||||
void t3dVectTransformInv(t3dV3F *d, t3dV3F *s, t3dM3X3F *mat) {
|
||||
t3dV3F Tmp;
|
||||
Tmp.x = (s->x * mat->M[0]) + (s->y * mat->M[3]) + (s->z * mat->M[6]);
|
||||
Tmp.y = (s->x * mat->M[1]) + (s->y * mat->M[4]) + (s->z * mat->M[7]);
|
||||
Tmp.z = (s->x * mat->M[2]) + (s->y * mat->M[5]) + (s->z * mat->M[8]);
|
||||
d->x = Tmp.x;
|
||||
d->y = Tmp.y;
|
||||
d->z = Tmp.z;
|
||||
}
|
||||
|
||||
void t3dVectCross(t3dV3F *d, t3dV3F *v2, t3dV3F *v3) {
|
||||
t3dV3F Tmp;
|
||||
Tmp.x = (v2->y * v3->z) - (v2->z * v3->y);
|
||||
Tmp.y = (v2->z * v3->x) - (v2->x * v3->z);
|
||||
Tmp.z = (v2->x * v3->y) - (v2->y * v3->x);
|
||||
d->x = Tmp.x;
|
||||
d->y = Tmp.y;
|
||||
d->z = Tmp.z;
|
||||
}
|
||||
|
||||
void t3dVectSub(t3dV3F *d, t3dV3F *a, t3dV3F *b) { // d = a - b
|
||||
d->x = a->x - b->x;
|
||||
d->y = a->y - b->y;
|
||||
d->z = a->z - b->z;
|
||||
}
|
||||
|
||||
void t3dVectAdd(t3dV3F *d, t3dV3F *a, t3dV3F *b) { // d = a - b
|
||||
d->x = a->x + b->x;
|
||||
d->y = a->y + b->y;
|
||||
d->z = a->z + b->z;
|
||||
}
|
||||
|
||||
void t3dVectFill(t3dV3F *d, t3dF32 a) {
|
||||
d->x = a;
|
||||
d->y = a;
|
||||
d->z = a;
|
||||
}
|
||||
|
||||
void t3dVectInit(t3dV3F *d, t3dF32 a1, t3dF32 a2, t3dF32 a3) {
|
||||
d->x = a1;
|
||||
d->y = a2;
|
||||
d->z = a3;
|
||||
}
|
||||
|
||||
void t3dVectCopy(t3dV3F *d, t3dV3F *s) {
|
||||
memcpy(d, s, sizeof(t3dV3F));
|
||||
}
|
||||
|
||||
|
||||
t3dF32 t3dVectMod(t3dV3F *c) {
|
||||
t3dF32 mod = (c->x * c->x + c->y * c->y + c->z * c->z);
|
||||
if (mod)
|
||||
return (float)sqrt((double)mod);
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
t3dF32 t3dVectDistance(t3dV3F *a, t3dV3F *b) {
|
||||
t3dF32 mod;
|
||||
t3dV3F c;
|
||||
c.x = b->x - a->x;
|
||||
c.y = b->y - a->y;
|
||||
c.z = b->z - a->z;
|
||||
mod = (c.x * c.x + c.y * c.y + c.z * c.z);
|
||||
|
||||
if (mod)
|
||||
return ((float)sqrt((double)mod));
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
t3dF32 t3dVectDot(t3dV3F *a, t3dV3F *b) {
|
||||
return (t3dF32)(a->x * b->x + a->y * b->y + a->z * b->z);
|
||||
}
|
||||
|
||||
void t3dMatMulInv(t3dM3X3F *Dest, t3dM3X3F *a, t3dM3X3F *b) {
|
||||
t3dM3X3F Tmp, *d = &Tmp;
|
||||
|
||||
d->M[0] = (a->M[0] * b->M[0] + a->M[1] * b->M[1] + a->M[2] * b->M[2]);
|
||||
d->M[1] = (a->M[0] * b->M[3] + a->M[1] * b->M[4] + a->M[2] * b->M[5]);
|
||||
d->M[2] = (a->M[0] * b->M[6] + a->M[1] * b->M[7] + a->M[2] * b->M[8]);
|
||||
|
||||
d->M[3] = (a->M[3] * b->M[0] + a->M[4] * b->M[1] + a->M[5] * b->M[2]);
|
||||
d->M[4] = (a->M[3] * b->M[3] + a->M[4] * b->M[4] + a->M[5] * b->M[5]);
|
||||
d->M[5] = (a->M[3] * b->M[6] + a->M[4] * b->M[7] + a->M[5] * b->M[8]);
|
||||
|
||||
d->M[6] = (a->M[6] * b->M[0] + a->M[7] * b->M[1] + a->M[8] * b->M[2]);
|
||||
d->M[7] = (a->M[6] * b->M[3] + a->M[7] * b->M[4] + a->M[8] * b->M[5]);
|
||||
d->M[8] = (a->M[6] * b->M[6] + a->M[7] * b->M[7] + a->M[8] * b->M[8]);
|
||||
|
||||
if (d != Dest)
|
||||
t3dMatCopy(Dest, &Tmp);
|
||||
}
|
||||
|
||||
void t3dPlaneNormal(t3dNORMAL *n, t3dV3F *p0, t3dV3F *p1, t3dV3F *p2) {
|
||||
t3dV3F a, b;
|
||||
|
||||
t3dVectSub(&a, p1, p0);
|
||||
t3dVectSub(&b, p2, p0);
|
||||
t3dVectCross(&n->n, &a, &b);
|
||||
t3dVectNormalize(&n->n);
|
||||
|
||||
n->dist = t3dVectDot(&n->n, p0);
|
||||
}
|
||||
|
||||
void t3dVectNormalize(t3dV3F *c) {
|
||||
t3dF32 mod = (float)sqrt((double)(c->x * c->x + c->y * c->y + c->z * c->z));
|
||||
if (!mod)return;
|
||||
mod = 1.0f / mod;
|
||||
c->x = c->x * mod;
|
||||
c->y = c->y * mod;
|
||||
c->z = c->z * mod;
|
||||
}
|
||||
|
||||
void t3dMatRot(t3dM3X3F *matrix, t3dF32 x, t3dF32 y, t3dF32 z) {
|
||||
/* t3dF32 cx, cy, cz, sx, sy, sz,sxsy,szsy,szcy,czcy;
|
||||
|
||||
sx = sin(x);cx = cos(x); // qui ci vorrebbe una FSINCOS in asm
|
||||
sy = sin(y);cy = cos(y);
|
||||
sz = sin(z);cz = cos(z);
|
||||
sxsy=sx*sy;szsy=sz*sy;szcy=sz*cy;czcy=cz*cy;
|
||||
matrix->M[0] = czcy + sx*szsy ;
|
||||
matrix->M[1] = -szcy + sxsy*cz ;
|
||||
matrix->M[2] = cx*sy;
|
||||
matrix->M[3] = cx*sz;
|
||||
matrix->M[4] = cx*cz;
|
||||
matrix->M[5] = -sx;
|
||||
matrix->M[6] = -cz*sy + sx*szcy;
|
||||
matrix->M[7] = szsy + sx*czcy;
|
||||
matrix->M[8] = cx*cy ;*/
|
||||
|
||||
|
||||
t3dM3X3F matrix_x, matrix_y, matrix_z;
|
||||
|
||||
t3dMatIdentity(&matrix_x);
|
||||
t3dMatIdentity(&matrix_y);
|
||||
t3dMatIdentity(&matrix_z);
|
||||
|
||||
/* | 1 0 0 0 | x' = x
|
||||
| 0 cos <20> -sin <20> 0 | y' = (cos <20>) * y - (sin <20>) * z
|
||||
| 0 sin <20> cos <20> 0 | z' = (sin <20>) * y + (cos <20>) * z
|
||||
| 0 0 0 1 |*/
|
||||
|
||||
matrix_x.M[4] = (float)cos(x);
|
||||
matrix_x.M[5] = -(float)sin(x);
|
||||
matrix_x.M[7] = (float)sin(x);
|
||||
matrix_x.M[8] = (float)cos(x);
|
||||
|
||||
/* | cos <20> 0 sin <20> 0 | x' = (cos <20>) * x + (sin <20>) * z
|
||||
| 0 1 0 0 | y' = y
|
||||
| -sin <20> 0 cos <20> 0 | z' = -(sin <20>) * x + (cos <20>) * z
|
||||
| 0 0 0 1 |*/
|
||||
|
||||
matrix_y.M[0] = (float)cos(y);
|
||||
matrix_y.M[2] = (float)sin(y);
|
||||
matrix_y.M[6] = -(float)sin(y);
|
||||
matrix_y.M[8] = (float)cos(y);
|
||||
|
||||
/* | cos <20> -sin <20> 0 0 | x' = (cos <20>) * x - (sin <20>) * y
|
||||
| sin <20> cos <20> 0 0 | y' = (sin <20>) * x + (cos <20>) * y
|
||||
| 0 0 1 0 | z' = z
|
||||
| 0 0 0 1 |*/
|
||||
|
||||
matrix_z.M[0] = (float)cos(z);
|
||||
matrix_z.M[1] = -(float)sin(z);
|
||||
matrix_z.M[3] = (float)sin(z);
|
||||
matrix_z.M[4] = (float)cos(z);
|
||||
|
||||
t3dMatMul(matrix, &matrix_x, &matrix_y);
|
||||
t3dMatMul(matrix, matrix, &matrix_z);
|
||||
}
|
||||
|
||||
t3dF32 t3dVectPlaneDistance(t3dV3F start, t3dNORMAL n) {
|
||||
return t3dVectDot(&start, &n.n) - n.dist;
|
||||
}
|
||||
|
||||
uint8 t3dVectPlaneIntersection(t3dV3F *inter, t3dV3F start, t3dV3F end, t3dNORMAL n) {
|
||||
t3dF32 divi;
|
||||
t3dF32 d1 = t3dVectPlaneDistance(start, n);
|
||||
t3dF32 d2 = t3dVectPlaneDistance(end, n);
|
||||
|
||||
if ((d1 < 0) && (d2 < 0))
|
||||
return 0;
|
||||
else if ((d1 >= 0) && (d2 >= 0))
|
||||
return 1;
|
||||
|
||||
|
||||
if ((d1 < 0) && (d2 >= 0)) {
|
||||
d2 = d2 - d1;
|
||||
divi = -d1 / d2;
|
||||
inter->x = start.x + divi * (end.x - start.x);
|
||||
inter->y = start.y + divi * (end.y - start.y);
|
||||
inter->z = start.z + divi * (end.z - start.z);
|
||||
return 2;
|
||||
} else {
|
||||
d1 = d1 - d2;
|
||||
divi = -d2 / d1;
|
||||
inter->x = end.x + divi * (start.x - end.x);
|
||||
inter->y = end.y + divi * (start.y - end.y);
|
||||
inter->z = end.z + divi * (start.z - end.z);
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 t3dVectTriangleIntersection(t3dV3F *inter, t3dV3F start, t3dV3F end,
|
||||
t3dV3F v1, t3dV3F v2, t3dV3F v3, t3dNORMAL n) {
|
||||
t3dV3F appo;
|
||||
t3dNORMAL normal;
|
||||
|
||||
if (t3dVectPlaneIntersection(inter, start, end, n) <= 1)
|
||||
return 0;
|
||||
|
||||
t3dVectAdd(&appo, &n.n, &v1);
|
||||
t3dPlaneNormal(&normal, &appo, &v1, &v2);
|
||||
|
||||
if (t3dVectPlaneDistance(*inter, normal) >= 0.0f) {
|
||||
t3dVectAdd(&appo, &n.n, &v2);
|
||||
t3dPlaneNormal(&normal, &appo, &v2, &v3);
|
||||
if (t3dVectPlaneDistance(*inter, normal) >= 0.0f) {
|
||||
t3dVectAdd(&appo, &n.n, &v3);
|
||||
t3dPlaneNormal(&normal, &appo, &v3, &v1);
|
||||
if (t3dVectPlaneDistance(*inter, normal) >= 0.0f)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
t3dF32 t3dVectSquaredDistance(t3dV3F *a, t3dV3F *b) {
|
||||
t3dV3F c;
|
||||
c.x = b->x - a->x;
|
||||
c.y = b->y - a->y;
|
||||
c.z = b->z - a->z;
|
||||
|
||||
return (c.x * c.x + c.y * c.y + c.z * c.z);
|
||||
}
|
||||
|
||||
t3dF32 t3dPointSquaredDistance(t3dV3F *c) {
|
||||
return (c->x * c->x + c->y * c->y + c->z * c->z);
|
||||
}
|
||||
|
||||
void t3dMatReflect(t3dM3X3F *Matrix, t3dV3F *mirrorpos, t3dNORMAL *n) {
|
||||
// | 1-2*nx*nx -2*nx*ny -2*nx*nz -2*nx*k |
|
||||
// | -2*ny*nx 1-2*ny*ny -2*ny*nz -2*ny*k |
|
||||
// | -2*nz*nx -2*nz*ny 1-2*nz*nz -2*nz*k |
|
||||
// | 0 0 0 1 |
|
||||
|
||||
Matrix->M[0] = 1 - 2 * n->n.x * n->n.x;
|
||||
Matrix->M[1] = -2 * n->n.x * n->n.y;
|
||||
Matrix->M[2] = -2 * n->n.x * n->n.z;
|
||||
Matrix->M[3] = -2 * n->n.y * n->n.x;
|
||||
Matrix->M[4] = 1 - 2 * n->n.y * n->n.y;
|
||||
Matrix->M[5] = -2 * n->n.y * n->n.z;
|
||||
Matrix->M[6] = -2 * n->n.z * n->n.x;
|
||||
Matrix->M[7] = -2 * n->n.z * n->n.y;
|
||||
Matrix->M[8] = 1 - 2 * n->n.z * n->n.z;
|
||||
|
||||
mirrorpos->x = -2 * n->n.x * n->dist;
|
||||
mirrorpos->y = -2 * n->n.y * n->dist;
|
||||
mirrorpos->z = -2 * n->n.z * n->dist;
|
||||
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
66
engines/watchmaker/3d/math/llmath.h
Normal file
66
engines/watchmaker/3d/math/llmath.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_LLMATH_H
|
||||
#define WATCHMAKER_LLMATH_H
|
||||
|
||||
#include "watchmaker/t3d.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void t3dMatCopy(t3dM3X3F *d, t3dM3X3F *s);
|
||||
void t3dMatIdentity(t3dM3X3F *d);
|
||||
void t3dMatSet(t3dM3X3F *d,
|
||||
t3dF32 _m11, t3dF32 _m12, t3dF32 _m13,
|
||||
t3dF32 _m21, t3dF32 _m22, t3dF32 _m23,
|
||||
t3dF32 _m31, t3dF32 _m32, t3dF32 _m33);
|
||||
void t3dMatMul(t3dM3X3F *Dest, t3dM3X3F *a, t3dM3X3F *b);
|
||||
void t3dMatRotAxis(t3dM3X3F *m, t3dF32 x, t3dF32 y, t3dF32 z, t3dF32 rad);
|
||||
void t3dMatRot(t3dM3X3F *matrix, t3dF32 x, t3dF32 y, t3dF32 z);
|
||||
void t3dMatReflect(t3dM3X3F *Matrix, t3dV3F *mirrorpos, t3dNORMAL *n);
|
||||
void t3dMatView(t3dM3X3F *dest, t3dV3F *eye, t3dV3F *center);
|
||||
void t3dVectTransform(t3dV3F *d, t3dV3F *s, t3dM3X3F *mat);
|
||||
void t3dVectTransformInv(t3dV3F *d, t3dV3F *s, t3dM3X3F *mat);
|
||||
void t3dVectInit(t3dV3F *a, t3dF32 x, t3dF32 y, t3dF32 z);
|
||||
void t3dVectCross(t3dV3F *d, t3dV3F *v2, t3dV3F *v3);
|
||||
void t3dVectSub(t3dV3F *d, t3dV3F *a, t3dV3F *b); // d = a - b
|
||||
void t3dVectAdd(t3dV3F *d, t3dV3F *a, t3dV3F *b); // d = a - b
|
||||
void t3dVectFill(t3dV3F *d, t3dF32 a);
|
||||
void t3dVectCopy(t3dV3F *d, t3dV3F *s);
|
||||
t3dF32 t3dVectMod(t3dV3F *c);
|
||||
t3dF32 t3dVectDistance(t3dV3F *a, t3dV3F *b);
|
||||
t3dF32 t3dVectSquaredDistance(t3dV3F *a, t3dV3F *b);
|
||||
t3dF32 t3dPointSquaredDistance(t3dV3F *c);
|
||||
void t3dVectNormalize(t3dV3F *c);
|
||||
t3dF32 t3dVectDot(t3dV3F *a, t3dV3F *b);
|
||||
void t3dMatMulInv(t3dM3X3F *Dest, t3dM3X3F *a, t3dM3X3F *b);
|
||||
void t3dVectReflection(t3dV3F *r, t3dV3F *p1, t3dNORMAL *plane, t3dF32 dist);
|
||||
void t3dMatInv(t3dM3X3F *d, t3dM3X3F *s);
|
||||
void t3dPlaneNormal(t3dNORMAL *n, t3dV3F *p0, t3dV3F *p1, t3dV3F *p2);
|
||||
void t3dVector2dTo3d(t3dV3F *end, t3dV2F *start);
|
||||
int32 t3dFloatToInt(t3dF32 nfloat);
|
||||
t3dF32 t3dVectPlaneDistance(t3dV3F start, t3dNORMAL n); //return the distance of start from plane normal n
|
||||
uint8 t3dVectPlaneIntersection(t3dV3F *inter, t3dV3F start, t3dV3F end, t3dNORMAL n); //if return value !=0 inter contains the intersection point
|
||||
uint8 t3dVectTriangleIntersection(t3dV3F *inter, t3dV3F start, t3dV3F end, t3dV3F v1, t3dV3F v2, t3dV3F v3, t3dNORMAL n); //return 1 if the vector from start to end pass trought the triangle v1,v2,v3
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_LLMATH_H
|
||||
90
engines/watchmaker/3d/mem_management.cpp
Normal file
90
engines/watchmaker/3d/mem_management.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/mem_management.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/ll/ll_system.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
static int8 *MemoryPool = nullptr;
|
||||
static uint32 MemoryPoolPointer = 0;
|
||||
static uint32 MaxAllocatedMem = 0;
|
||||
|
||||
// Memory Management
|
||||
// Only linear (non dynamic) stack allocations
|
||||
|
||||
|
||||
/* -----------------10/06/99 16.06-------------------
|
||||
* t3dAllocMemoryPool
|
||||
* --------------------------------------------------*/
|
||||
uint8 t3dAllocMemoryPool(uint32 pool) {
|
||||
uint8 allocated = 0;
|
||||
|
||||
MemoryPoolPointer = 0;
|
||||
while ((allocated == 0) && (pool > 0)) {
|
||||
if (!(MemoryPool = t3dCalloc<int8>(pool)))
|
||||
pool -= 10000;
|
||||
else
|
||||
allocated = 1;
|
||||
}
|
||||
|
||||
if (allocated == 0)
|
||||
return 0;
|
||||
else {
|
||||
MaxAllocatedMem = pool;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------10/06/99 16.07-------------------
|
||||
* t3dDeallocMemoryPool
|
||||
* --------------------------------------------------*/
|
||||
void t3dDeallocMemoryPool() {
|
||||
if (MemoryPool == nullptr) return;
|
||||
t3dFree(MemoryPool);
|
||||
MemoryPool = nullptr;
|
||||
MaxAllocatedMem = 0;
|
||||
}
|
||||
|
||||
/* -----------------10/06/99 16.07-------------------
|
||||
* t3dAlloc
|
||||
* --------------------------------------------------*/
|
||||
void *t3dAlloc(uint32 size) {
|
||||
if (MemoryPool == nullptr) return nullptr;
|
||||
MemoryPoolPointer += size;
|
||||
if (MemoryPoolPointer > MaxAllocatedMem) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &MemoryPool[MemoryPoolPointer - size];
|
||||
}
|
||||
|
||||
/* -----------------10/06/99 16.07-------------------
|
||||
* t3dDealloc
|
||||
* --------------------------------------------------*/
|
||||
void *t3dDealloc(uint32 size) {
|
||||
if (MemoryPool == nullptr) return nullptr;
|
||||
MemoryPoolPointer -= size;
|
||||
return &MemoryPool[MemoryPoolPointer];
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
34
engines/watchmaker/3d/mem_management.h
Normal file
34
engines/watchmaker/3d/mem_management.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_MEM_MANAGEMENT_H
|
||||
#define WATCHMAKER_MEM_MANAGEMENT_H
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
unsigned char t3dAllocMemoryPool(unsigned int pool);
|
||||
void t3dDeallocMemoryPool();
|
||||
void *t3dAlloc(unsigned int size);
|
||||
void *t3dDealloc(unsigned int size);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_MEM_MANAGEMENT_H
|
||||
219
engines/watchmaker/3d/movie.cpp
Normal file
219
engines/watchmaker/3d/movie.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/movie.h"
|
||||
#include "watchmaker/3d/dds_header.h"
|
||||
#include "watchmaker/file_utils.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/work_dirs.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
gMovie::gMovie(Common::SharedPtr<Common::SeekableReadStream> stream, Texture *texture, const Common::String &name) : _name(name), _stream(stream), _texture(texture) {
|
||||
_numFrames = stream->readUint16LE();
|
||||
_width = stream->readUint16LE();
|
||||
_height = stream->readUint16LE();
|
||||
_keyFrame = stream->readByte();
|
||||
_frameRate = stream->readByte();
|
||||
|
||||
_header = DDSHeader(*stream);
|
||||
_numBlocks = _width * _height / 16;
|
||||
_curFrame = 0xFFFF;
|
||||
|
||||
_frameOffsets = new uint32[_numFrames] {};
|
||||
if (!_frameOffsets) {
|
||||
error("gLoadMovie FAILED: Can't alloc Movie->frameOffsets struct");
|
||||
}
|
||||
|
||||
_buffer = new uint8[bufferSize()] {};
|
||||
_surfaceBuffer = new uint8[_header.dataSize()] {};
|
||||
_frameStream = new Common::MemoryReadStream(_surfaceBuffer, _header.dataSize(), DisposeAfterUse::NO);
|
||||
if (!_buffer) {
|
||||
error("gLoadMovie FAILED: Can't alloc Movie->buffer struct");
|
||||
}
|
||||
|
||||
//read frame offsets
|
||||
for (int i = 0; i < _numFrames; i++) {
|
||||
_frameOffsets[i] = _stream->readUint32LE();
|
||||
}
|
||||
|
||||
_startTime = 0;
|
||||
}
|
||||
|
||||
gMovie::~gMovie() {
|
||||
delete[] _frameOffsets;
|
||||
delete[] _buffer;
|
||||
delete[] _surfaceBuffer;
|
||||
delete _frameStream;
|
||||
}
|
||||
|
||||
Common::SharedPtr<gMovie> gLoadMovie(WorkDirs &workDirs, const char *TextName, Texture *texture) {
|
||||
//convert .avi name in .wmm
|
||||
Common::String finalName = replaceExtension(TextName, "wmm");
|
||||
|
||||
auto stream = workDirs.resolveFile(finalName);
|
||||
if (!stream) {
|
||||
DebugLogFile("gLoadMovie FAILED: Can't find movie file\n");
|
||||
return nullptr;
|
||||
}
|
||||
auto Movie = Common::SharedPtr<gMovie>(new gMovie(stream, texture, TextName));
|
||||
Movie->_name = TextName;
|
||||
if (!Movie) {
|
||||
DebugLogFile("gLoadMovie FAILED: Can't alloc Movie struct");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Movie->frameRate=240;
|
||||
return Movie;
|
||||
}
|
||||
|
||||
void gMovie::loadThisFrameData(uint16 frame) {
|
||||
_stream->seek(_frameOffsets[frame], SEEK_SET);
|
||||
//read frame data
|
||||
int32 size = 0;
|
||||
if ((frame + 1) == _numFrames) {
|
||||
size = _stream->size() - _frameOffsets[frame];
|
||||
} else {
|
||||
size = _frameOffsets[frame + 1] - _frameOffsets[frame];
|
||||
}
|
||||
assert(size <= (int32)bufferSize());
|
||||
_stream->read(_buffer, size);
|
||||
}
|
||||
|
||||
//build a new frame by difference from previous
|
||||
void gMovie::buildNewFrame(byte *surf, uint16 frame) {
|
||||
loadThisFrameData(frame);
|
||||
|
||||
DWORD bitArraySize = _numBlocks >> 3;
|
||||
byte *buf = &_buffer[bitArraySize];
|
||||
WORD curBlock = 0;
|
||||
|
||||
for (int i = 0; i < bitArraySize; i++) {
|
||||
byte block = _buffer[i];
|
||||
if (!block) {
|
||||
curBlock += 8;
|
||||
continue; //everything is equal
|
||||
}
|
||||
|
||||
for (int j = 0; j < 8; j++, curBlock++) {
|
||||
if (block & (1 << j)) {
|
||||
memcpy(&surf[curBlock << 3], buf, 8);
|
||||
buf += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool gMovie::setFrame(uint16 newFrame) {
|
||||
warning("Set Frame: %d\t%s", newFrame, _name.c_str());
|
||||
if (_curFrame == newFrame)
|
||||
return true;
|
||||
|
||||
//do we have to replace the whole frame or do we have to built it?
|
||||
bool rebuildFrame = true;
|
||||
if (_curFrame == 0xFFFF) rebuildFrame = false;
|
||||
else if (!(newFrame % _keyFrame)) rebuildFrame = false; //it's a keyframe
|
||||
|
||||
_header.dataSize();
|
||||
#if 0
|
||||
DDSURFACEDESC2 ddsd2;
|
||||
ddsd2.dwSize = sizeof(DDSURFACEDESC2);
|
||||
|
||||
if ((mv->surf->Lock(NULL, &ddsd2, DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL))) { // Lock and fill with the dds
|
||||
DebugLogFile("gMovie_SetFrame: Can't lock surface DDS");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
if (!rebuildFrame) {
|
||||
loadThisFrameData(newFrame);
|
||||
memcpy(_surfaceBuffer, _buffer, _header.dataSize());
|
||||
} else {
|
||||
if ((_curFrame + 1) != newFrame) { //we can't directly build this frame because the current frame is not his previous
|
||||
uint16 startFrame;
|
||||
uint16 prevKey = (newFrame / _keyFrame) * _keyFrame;
|
||||
|
||||
if ((_curFrame > newFrame) || (_curFrame < prevKey)) {
|
||||
loadThisFrameData(prevKey);
|
||||
memcpy(_surfaceBuffer, _buffer, _header.dataSize());
|
||||
startFrame = prevKey + 1;
|
||||
} else startFrame = _curFrame + 1;
|
||||
for (uint16 i = startFrame; i < newFrame; i++) {
|
||||
buildNewFrame(_surfaceBuffer, i);
|
||||
}
|
||||
}
|
||||
buildNewFrame(_surfaceBuffer, newFrame);
|
||||
}
|
||||
|
||||
_frameStream->seek(0, SEEK_SET);
|
||||
auto tex = loadDdsTexture(*_frameStream, _header);
|
||||
_texture->assignData(*tex);
|
||||
#if 0
|
||||
if (mat->Texture->lpDDSurface->Blt(NULL, mv->surf, NULL, DDBLT_WAIT, NULL) != DD_OK) {
|
||||
DebugLogFile("gMovie_SetFrame: Can't Blit DDS texture");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
_curFrame = newFrame;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
bool gMovie::updateMovie() {
|
||||
int16 newFrame = 0;
|
||||
|
||||
if (_paused)
|
||||
return TRUE;
|
||||
|
||||
warning("Update Movie: %s", _name.c_str());
|
||||
|
||||
if ((_curFrame == 0xFFFF) || (!_startTime)) {
|
||||
_startTime = timeGetTime();
|
||||
newFrame = 0;
|
||||
} else {
|
||||
// Use the time to find which frame we should be drawing
|
||||
uint32 curTime = timeGetTime();
|
||||
DWORD elapsedTime = curTime - _startTime;
|
||||
newFrame = (WORD)((float)elapsedTime / (1000.f / (float)_frameRate));
|
||||
|
||||
if (newFrame >= _numFrames) {
|
||||
_startTime = curTime;
|
||||
newFrame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return setFrame(newFrame);
|
||||
}
|
||||
|
||||
int gMovie::frameSize(int index) {
|
||||
if ((index + 1) < _numFrames) {
|
||||
return _frameOffsets[index + 1] - _frameOffsets[index];
|
||||
} else {
|
||||
return _stream->size() - _frameOffsets[index];
|
||||
}
|
||||
}
|
||||
|
||||
uint32 gMovie::bufferSize() const {
|
||||
return (_numBlocks / 8) + 8 * _numBlocks; //bit array + max different blocks
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
74
engines/watchmaker/3d/movie.h
Normal file
74
engines/watchmaker/3d/movie.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_MOVIE_H
|
||||
#define WATCHMAKER_MOVIE_H
|
||||
|
||||
#include "common/memstream.h"
|
||||
#include "watchmaker/3d/dds_header.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/utils.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
struct gMovie {
|
||||
private:
|
||||
Common::MemoryReadStream *_frameStream = nullptr;
|
||||
public:
|
||||
Common::String _name;
|
||||
Common::SharedPtr<Common::SeekableReadStream> _stream;
|
||||
uint16 _numFrames;
|
||||
uint16 _curFrame;
|
||||
uint16 _width;
|
||||
uint16 _height;
|
||||
uint16 _numBlocks;
|
||||
uint32 _startTime;
|
||||
uint8 _keyFrame;
|
||||
uint8 _frameRate;
|
||||
|
||||
uint32 *_frameOffsets;
|
||||
uint8 *_buffer;
|
||||
uint8 *_surfaceBuffer;
|
||||
|
||||
DDSHeader _header;
|
||||
|
||||
Texture *_texture = nullptr;
|
||||
|
||||
bool _paused = false;
|
||||
|
||||
gMovie(Common::SharedPtr<Common::SeekableReadStream> stream, Texture *texture, const Common::String &name);
|
||||
~gMovie();
|
||||
|
||||
bool setFrame(uint16 newFrame);
|
||||
void loadThisFrameData(uint16 frame);
|
||||
void buildNewFrame(byte *surf, uint16 frame);
|
||||
bool updateMovie();
|
||||
private:
|
||||
int frameSize(int index);
|
||||
uint32 bufferSize() const;
|
||||
};
|
||||
|
||||
class WorkDirs;
|
||||
Common::SharedPtr<gMovie> gLoadMovie(WorkDirs &workDirs, const char *TextName, Texture *texture);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_MOVIE_H
|
||||
36
engines/watchmaker/3d/render/opengl.cpp
Normal file
36
engines/watchmaker/3d/render/opengl.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/render/opengl.h"
|
||||
#include "watchmaker/utils.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
//*********************************************************************************************
|
||||
bool rGetStencilBitDepth() {
|
||||
#if 0
|
||||
return gStencilBitDepth;
|
||||
#endif
|
||||
//warning("TODO: Implement rGetStencilBitDepth");
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
29
engines/watchmaker/3d/render/opengl.h
Normal file
29
engines/watchmaker/3d/render/opengl.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_OPENGL_H
|
||||
#define WATCHMAKER_OPENGL_H
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_OPENGL_H
|
||||
369
engines/watchmaker/3d/render/opengl_2d.cpp
Normal file
369
engines/watchmaker/3d/render/opengl_2d.cpp
Normal file
@@ -0,0 +1,369 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
#if defined(USE_OPENGL_GAME)
|
||||
|
||||
#include "graphics/pixelformat.h"
|
||||
#include "watchmaker/3d/render/opengl_2d.h"
|
||||
#include "watchmaker/3d/render/opengl_renderer.h"
|
||||
#include "watchmaker/game.h"
|
||||
#include "watchmaker/rect.h"
|
||||
#include "watchmaker/render.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
#include "watchmaker/sdl_wrapper.h"
|
||||
#include "watchmaker/tga_util.h"
|
||||
#include "watchmaker/utils.h"
|
||||
#include "watchmaker/work_dirs.h"
|
||||
|
||||
#include "graphics/opengl/system_headers.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
Common::Rect gBlitterExtends;
|
||||
int gStencilBitDepth;
|
||||
|
||||
unsigned int CurLoaderFlags;
|
||||
|
||||
//*********************************************************************************************
|
||||
unsigned int Renderer::BitmapList::acquirePosition() {
|
||||
unsigned int pos = 1;
|
||||
|
||||
while (!bitmaps[pos].isEmpty()) {
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (pos > MAX_BITMAP_LIST)
|
||||
return 0;
|
||||
|
||||
if (pos > _numBitmaps)
|
||||
_numBitmaps = pos;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
unsigned int Renderer::getBitmapDimX(int32 id) const {
|
||||
return _bitmapList.bitmaps[id].DimX;
|
||||
}
|
||||
|
||||
unsigned int Renderer::getBitmapDimY(int32 id) const {
|
||||
return _bitmapList.bitmaps[id].DimY;
|
||||
}
|
||||
|
||||
unsigned int Renderer::getBitmapRealDimX(int32 id) const {
|
||||
return _bitmapList.bitmaps[id].RealDimX;
|
||||
}
|
||||
|
||||
unsigned int Renderer::getBitmapRealDimY(int32 id) const {
|
||||
return _bitmapList.bitmaps[id].RealDimY;
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************************
|
||||
void rUpdateExtends(int x1, int y1, int x2, int y2) {
|
||||
//Update extends
|
||||
if (x1 < gBlitterExtends.left)
|
||||
gBlitterExtends.left = x1;
|
||||
if (y1 < gBlitterExtends.top)
|
||||
gBlitterExtends.top = y1;
|
||||
if (x2 > gBlitterExtends.right)
|
||||
gBlitterExtends.right = x2;
|
||||
if (y2 > gBlitterExtends.bottom)
|
||||
gBlitterExtends.bottom = y2;
|
||||
}
|
||||
|
||||
//************************************************************************************************************************
|
||||
void rGetExtends(int *x1, int *y1, int *x2, int *y2) {
|
||||
*x1 = gBlitterExtends.left;
|
||||
*y1 = gBlitterExtends.top;
|
||||
*x2 = gBlitterExtends.right;
|
||||
*y2 = gBlitterExtends.bottom;
|
||||
}
|
||||
|
||||
//************************************************************************************************************************
|
||||
void rResetExtends() {
|
||||
gBlitterExtends.left = SHRT_MAX;
|
||||
gBlitterExtends.top = SHRT_MAX;
|
||||
gBlitterExtends.right = SHRT_MIN;
|
||||
gBlitterExtends.bottom = SHRT_MIN;
|
||||
}
|
||||
|
||||
// TODO: Move this to Renderer
|
||||
extern Common::Rect gBlitterViewport;
|
||||
bool gClipToBlitterViewport(int *sposx, int *sposy, int *sdimx, int *sdimy,
|
||||
int *dposx, int *dposy) {
|
||||
int dwWidth, dwHeight;
|
||||
|
||||
dwWidth = (gBlitterViewport.right - gBlitterViewport.left);
|
||||
dwHeight = (gBlitterViewport.bottom - gBlitterViewport.top);
|
||||
|
||||
if (((*dposx) + (*sdimx)) > dwWidth) {
|
||||
(*sdimx) = (*sdimx) - ((*dposx) + (*sdimx) - dwWidth);
|
||||
}
|
||||
if (((*dposy) + (*sdimy)) > dwHeight) {
|
||||
(*sdimy) = (*sdimy) - ((*dposy) + (*sdimy) - dwHeight);
|
||||
}
|
||||
|
||||
if ((*dposx) < gBlitterViewport.left) {
|
||||
(*sposx) += gBlitterViewport.left - (*dposx);
|
||||
(*sdimx) -= gBlitterViewport.left - (*dposx);
|
||||
(*dposx) = gBlitterViewport.left;
|
||||
}
|
||||
if ((*dposy) < gBlitterViewport.top) {
|
||||
(*sposy) += gBlitterViewport.top - (*dposy);
|
||||
(*sdimy) -= gBlitterViewport.top - (*dposy);
|
||||
(*dposy) = gBlitterViewport.top;
|
||||
}
|
||||
|
||||
if (((*sdimx) <= 0) || ((*sdimy) <= 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void renderTexture(WGame &game, gTexture &bitmap, Common::Rect srcRect, Common::Rect dstRect) {
|
||||
checkGlError("Entering renderTexture");
|
||||
glClearColor(0, 0, 1, 0);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
bitmap._texture->bind();
|
||||
glLoadIdentity();
|
||||
glTranslatef(0, 0, 0.0);
|
||||
|
||||
float bottomSrc = ((float)srcRect.bottom) / bitmap.RealDimY;
|
||||
float topSrc = ((float)srcRect.top) / bitmap.RealDimY;
|
||||
float leftSrc = ((float)srcRect.left) / bitmap.RealDimX;
|
||||
float rightSrc = ((float)srcRect.right) / bitmap.RealDimX;
|
||||
|
||||
Common::Rect viewport = game._renderer->_viewport;
|
||||
float bottomDst = 1.0 - ((dstRect.bottom == 0 ? 0 : ((double)dstRect.bottom) / viewport.height()) * 2.0);
|
||||
float topDst = 1.0 - ((dstRect.top == 0 ? 0 : ((double)dstRect.top) / viewport.height()) * 2.0);
|
||||
float leftDst = ((dstRect.left == 0 ? 0 : ((double)dstRect.left) / viewport.width()) * 2.0) - 1.0;
|
||||
float rightDst = ((dstRect.right == 0 ? 0 : ((double)dstRect.right) / viewport.width()) * 2.0) - 1.0;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
glTexCoord2f(leftSrc, bottomSrc); // Bottom Left
|
||||
glVertex3f(leftDst, bottomDst, 0.0f);
|
||||
|
||||
glTexCoord2f(rightSrc, bottomSrc); // Bottom Right
|
||||
glVertex3f(rightDst, bottomDst, 0.0f);
|
||||
|
||||
glTexCoord2f(rightSrc, topSrc); // Top Right
|
||||
glVertex3f(rightDst, topDst, 0.0f);
|
||||
|
||||
glTexCoord2f(leftSrc, topSrc); // Top Left
|
||||
glVertex3f(leftDst, topDst, 0.0f);
|
||||
|
||||
glEnd();
|
||||
glFlush();
|
||||
checkGlError("Exiting renderTexture");
|
||||
}
|
||||
|
||||
void gTexture::render(WGame &game, Common::Rect src, Common::Rect dst) {
|
||||
// Render self
|
||||
if (_texture) {
|
||||
renderTexture(game, *this, src, dst);
|
||||
}
|
||||
for (uint i = 0; i < _blitsOnTop.size(); i++) {
|
||||
_blitsOnTop[i].texture->render(game, _blitsOnTop[i].src, _blitsOnTop[i].dst);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::blitScreenBuffer() {
|
||||
checkGlError("Entering rBlitScreenBuffer");
|
||||
g_renderer->enter2Dmode();
|
||||
_bitmapList.bitmaps[BACK_BUFFER].render(*_game, _game->_renderer->_viewport, _game->_renderer->_viewport);
|
||||
g_renderer->exit2Dmode();
|
||||
checkGlError("Exiting rBlitScreenBuffer");
|
||||
}
|
||||
|
||||
void Renderer::clearBitmap(int dst, int dposx, int dposy, int sdimx, int sdimy, unsigned char r, unsigned char g, unsigned char b) {
|
||||
warning("STUBBED: rClear(%d, %d, %d, %d, %d", dst, dposx, dposy, sdimx, sdimy);
|
||||
_bitmapList.bitmaps[dst].clear();
|
||||
}
|
||||
|
||||
//************************************************************************************************************************
|
||||
void rBlitter(WGame &game, int dst, int src, int dposx, int dposy,
|
||||
int sposx, int sposy, int sdimx, int sdimy) {
|
||||
auto &bitmapList = game._renderer->_bitmapList.bitmaps;
|
||||
// TODO: This currently gets called a bit too much.
|
||||
warning("TODO: Stubbed rBlitter(%s, %d, %d, %d, %d, %d, %d, %d, %d)", bitmapList[src].name.c_str(), dst, src, dposx, dposy, sposx, sposy, sdimx, sdimy);
|
||||
|
||||
auto &bitmap = bitmapList[src];
|
||||
|
||||
assert(dst == 0);
|
||||
auto &dstBitmap = bitmapList[dst];
|
||||
|
||||
checkGlError("rBlitter Start");
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
int dwWidth, dwHeight;
|
||||
|
||||
dwWidth = game._renderer->_viewport.width();
|
||||
dwHeight = game._renderer->_viewport.height();
|
||||
|
||||
if ((sdimx <= 0)) {
|
||||
sdimx = bitmapList[src].DimX;
|
||||
}
|
||||
if ((sdimy <= 0)) {
|
||||
sdimy = bitmapList[src].DimY;
|
||||
}
|
||||
|
||||
if ((dposx >= dwWidth) || (dposy >= dwHeight) || (sposx >= dwWidth) || (sposy >= dwHeight) ||
|
||||
((dposx + sdimx) <= 0) || ((dposy + sdimy) <= 0) || ((sposx + sdimx) <= 0) || ((sposy + sdimy) <= 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dst == 0) {
|
||||
if (!gClipToBlitterViewport(&sposx, &sposy, &sdimx, &sdimy, &dposx, &dposy)) {
|
||||
error("gClipToBlitterViewport report an error");
|
||||
return;
|
||||
}
|
||||
|
||||
rUpdateExtends(dposx, dposy, dposx + sdimx, dposy + sdimy);
|
||||
}
|
||||
|
||||
if ((sdimx == 0) && (sdimy == 0)) {
|
||||
sdimx = bitmapList[src].DimX;
|
||||
sdimy = bitmapList[src].DimY;
|
||||
}
|
||||
|
||||
{
|
||||
Common::Rect srcRect;
|
||||
// Source rect
|
||||
srcRect.top = sposy;
|
||||
srcRect.left = sposx;
|
||||
srcRect.right = sposx + sdimx;
|
||||
srcRect.bottom = sposy + sdimy;
|
||||
|
||||
Common::Rect dstRect;
|
||||
// Destination rect
|
||||
// Convention in dpos is that 0,0 is upper left hand corner, increasing down the y-axis.
|
||||
dstRect.top = dposy;
|
||||
dstRect.left = dposx;
|
||||
dstRect.right = dposx + sdimx;
|
||||
dstRect.bottom = dposy + sdimy;
|
||||
if (((dstRect.bottom - dstRect.top) <= 0) || ((dstRect.right - dstRect.left) <= 0) || ((srcRect.bottom - srcRect.top) <= 0) || ((srcRect.right - srcRect.left) <= 0) ||
|
||||
(dstRect.right <= 0) || (srcRect.right <= 0) || (dstRect.bottom < 0) || (srcRect.bottom < 0)) {
|
||||
// DebugLogWindow("gBlitter: blit not needed: dimx:%d dimy:%d", ( sr.top-sr.bottom ),( sr.left-sr.right ));
|
||||
return;
|
||||
}
|
||||
dstBitmap.blitInto(&bitmap, srcRect, dstRect);
|
||||
}
|
||||
checkGlError("rBlitter End");
|
||||
|
||||
// DebugLogFile("gBlitter(%d %d)",dst,src);
|
||||
//gBlitter(d, s, sposx, sposy, sdimx, sdimy, dposx, dposy, 0);
|
||||
//#endif
|
||||
}
|
||||
|
||||
// Straight from Wintermute:
|
||||
void applyColorKey(Graphics::Surface &surf, byte ckRed, byte ckGreen, byte ckBlue, bool replaceAlpha) {
|
||||
// this is taken from Graphics::TransparentSurface
|
||||
// only difference is that we set the pixel
|
||||
// color to transparent black, like D3DX,
|
||||
// if it matches the color key
|
||||
for (int y = 0; y < surf.h; y++) {
|
||||
for (int x = 0; x < surf.w; x++) {
|
||||
uint32 pix = ((uint32 *)surf.getPixels())[y * surf.w + x];
|
||||
uint8 r, g, b, a;
|
||||
surf.format.colorToARGB(pix, a, r, g, b);
|
||||
if (r == ckRed && g == ckGreen && b == ckBlue) {
|
||||
a = 0;
|
||||
r = 0;
|
||||
g = 0;
|
||||
b = 0;
|
||||
((uint32 *)surf.getPixels())[y * surf.w + x] = surf.format.ARGBToColor(a, r, g, b);
|
||||
} else if (replaceAlpha) {
|
||||
a = 255;
|
||||
((uint32 *)surf.getPixels())[y * surf.w + x] = surf.format.ARGBToColor(a, r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rLoadBitmapImage(WGame &game, const char *TextName, unsigned char flags) {
|
||||
WorkDirs &workDirs = game.workDirs;
|
||||
if (flags & rTEXTURESURFACE) {
|
||||
warning("TODO: support texture surface loading");
|
||||
// return ((int) gLoadTexture(TextName, flags));
|
||||
}
|
||||
|
||||
assert(TextName);
|
||||
auto stream = workDirs.resolveFile(TextName);
|
||||
if (!stream) {
|
||||
warning("gLoadBitmapImage: Cannot find %s.", TextName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const Graphics::PixelFormat RGBA32 = Graphics::PixelFormat::createFormatRGBA32();
|
||||
|
||||
unsigned int pos = game._renderer->_bitmapList.acquirePosition();
|
||||
if (pos == 0) {
|
||||
warning("rLoadBitmap: Can't create more bitmaps");
|
||||
return -1;
|
||||
}
|
||||
gTexture *Texture = &game._renderer->_bitmapList.bitmaps[pos];
|
||||
*Texture = gTexture();
|
||||
Texture->Flags = CurLoaderFlags;
|
||||
auto surface = ReadTgaImage(TextName, *stream, RGBA32, Texture->Flags);
|
||||
applyColorKey(*surface, 0, 0, 0, false);
|
||||
auto texData = createTextureFromSurface(*surface, GL_RGBA);
|
||||
Texture->_texture = createGLTexture();
|
||||
Texture->_texture->assignData(*texData);
|
||||
Texture->name = TextName;
|
||||
|
||||
if (flags & rSURFACESTRETCH) { // Also rSURFACEFLIP
|
||||
static bool warned = false;
|
||||
if (!warned) {
|
||||
warning("TODO: rSURFACESTRETCH");
|
||||
warned = true;
|
||||
}
|
||||
// HACK: Just set a dimension at all:
|
||||
Texture->DimX = surface->w;
|
||||
Texture->DimY = surface->h;
|
||||
} else {
|
||||
Texture->DimX = surface->w;
|
||||
Texture->DimY = surface->h;
|
||||
}
|
||||
|
||||
Texture->RealDimX = surface->w;
|
||||
Texture->RealDimY = surface->h;
|
||||
// TODO: Colour-keying
|
||||
return pos;
|
||||
}
|
||||
|
||||
void rSetLoaderFlags(unsigned int NewLoaderFlags) {
|
||||
CurLoaderFlags = NewLoaderFlags;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // USE_OPENGL_GAME
|
||||
36
engines/watchmaker/3d/render/opengl_2d.h
Normal file
36
engines/watchmaker/3d/render/opengl_2d.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_OPENGL2D_H
|
||||
#define WATCHMAKER_OPENGL2D_H
|
||||
|
||||
#include "watchmaker/render.h"
|
||||
#include "watchmaker/3d/render/opengl_3d.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
extern int gStencilBitDepth;
|
||||
|
||||
extern unsigned int CurLoaderFlags;
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_OPENGL2D_H
|
||||
840
engines/watchmaker/3d/render/opengl_3d.cpp
Normal file
840
engines/watchmaker/3d/render/opengl_3d.cpp
Normal file
@@ -0,0 +1,840 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_strcat
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_strcpy
|
||||
|
||||
#include "watchmaker/3d/render/opengl_3d.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/3d/math/Matrix4x4.h"
|
||||
#include "watchmaker/3d/render/opengl_renderer.h"
|
||||
#include "watchmaker/ll/ll_system.h"
|
||||
#include "watchmaker/3d/render/opengl_2d.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/work_dirs.h"
|
||||
|
||||
#ifdef USE_OPENGL_GAME
|
||||
|
||||
#include "graphics/opengl/system_headers.h"
|
||||
#include "watchmaker/3d/render/shadows.h"
|
||||
#include "watchmaker/file_utils.h"
|
||||
#include "watchmaker/tga_util.h"
|
||||
|
||||
#define MAXTEXTURES 2000
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
#define T3D_FASTFILE (1<<23) // fastfile
|
||||
|
||||
// Tecture formats
|
||||
int NumAvailableFormats = 0;
|
||||
gAvailFormat AvailableFormats[50];
|
||||
gAvailFormat *gCurrentFormat;
|
||||
|
||||
// Point VB
|
||||
int g_lpD3DPointsBuffer;
|
||||
unsigned int gNumPointsBuffer;
|
||||
|
||||
// Tecture list
|
||||
gTexture gTextureList[MAXTEXTURES];
|
||||
unsigned int gNumTextureList = 0;
|
||||
|
||||
// {ines array
|
||||
uint16 gLinesArray[MAX_LINES];
|
||||
unsigned int gNumLinesArray = 0;
|
||||
|
||||
// screen traingles
|
||||
Vertex gTriangles[100];
|
||||
unsigned int gNumTrianglesArray = 0;
|
||||
|
||||
// camera info
|
||||
Matrix4x4 rWorldMatrix;
|
||||
Matrix4x4 rProjectionMatrix;
|
||||
float gNearPlane, gFarPlane;
|
||||
|
||||
// saved matrix
|
||||
Matrix4x4 rLinesViewMatrix;
|
||||
|
||||
// user matrix
|
||||
#define MAX_USER_VIEW_MATRICES 2000 // TODO: Why do we get so many of them?
|
||||
Matrix4x4 rUserViewMatrix[MAX_USER_VIEW_MATRICES];
|
||||
unsigned int rNumUserViewMatrices = 0;
|
||||
|
||||
// user vertext buffer
|
||||
void *g_lpD3DUserVertexBuffer = nullptr;
|
||||
unsigned int g_dwD3DUserVertexBufferCounter = 0;
|
||||
|
||||
//***********************************************************************************************
|
||||
uint16 *rGetLinesArrayPtr() {
|
||||
return &gLinesArray[gNumLinesArray];
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
void rAddLinesArray() {
|
||||
gNumLinesArray++;
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
void *rLockPointArray() {
|
||||
warning("TODO: Implement rLockPointArray");
|
||||
#if 0
|
||||
HRESULT hResult;
|
||||
LPVOID v;
|
||||
|
||||
if ((hResult = g_lpD3DPointsBuffer->Lock(DDLOCK_SURFACEMEMORYPTR, &v, NULL)) != D3D_OK) {
|
||||
char str[255];
|
||||
GetDDErrorString(hResult, str, 1);
|
||||
DebugLogFile("rLockPointArray: Unable to lock points vertexbuffer:\r\n%s", str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gVertex *gv = (gVertex *)v;
|
||||
return &gv[rGetNumPointArray()];
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void rAddTrianglesArray(float x, float y, int r, int g, int b, int a) {
|
||||
gTriangles[gNumTrianglesArray].sx = x;
|
||||
gTriangles[gNumTrianglesArray].sy = y;
|
||||
gTriangles[gNumTrianglesArray].sz = 1.0f;
|
||||
gTriangles[gNumTrianglesArray].color = RGBA_MAKE(r, g, b, a);
|
||||
gNumTrianglesArray++;
|
||||
}
|
||||
|
||||
|
||||
//***********************************************************************************************
|
||||
void rUnlockPointArray() {
|
||||
warning("TODO: Implement rUnlockPointArray");
|
||||
#if 0
|
||||
g_lpD3DPointsBuffer->Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
unsigned int rGetNumPointArray() {
|
||||
return gNumPointsBuffer;
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
void rAddPointArray() {
|
||||
gNumPointsBuffer++;
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
bool rSetViewMatrix(float _00, float _01, float _02,
|
||||
float _03, float _04, float _05,
|
||||
float _06, float _07, float _08,
|
||||
float _tx, float _ty, float _tz) {
|
||||
Matrix4x4 rViewMatrix;
|
||||
rViewMatrix.setIdentity();
|
||||
|
||||
rViewMatrix.setValue(1, 1, _00);
|
||||
rViewMatrix.setValue(1, 2, _01);
|
||||
rViewMatrix.setValue(1, 3, _02);
|
||||
rViewMatrix.setValue(1, 4, _tx);
|
||||
|
||||
rViewMatrix.setValue(2, 1, _03);
|
||||
rViewMatrix.setValue(2, 2, _04);
|
||||
rViewMatrix.setValue(2, 3, _05);
|
||||
rViewMatrix.setValue(2, 4, _ty);
|
||||
|
||||
rViewMatrix.setValue(3, 1, -_06);
|
||||
rViewMatrix.setValue(3, 2, -_07);
|
||||
rViewMatrix.setValue(3, 3, -_08);
|
||||
rViewMatrix.setValue(3, 4, _tz);
|
||||
|
||||
rViewMatrix.setValue(4, 1, 0.0f);
|
||||
rViewMatrix.setValue(4, 2, 0.0f);
|
||||
rViewMatrix.setValue(4, 3, 0.0f);
|
||||
rViewMatrix.setValue(4, 4, 1.0f);
|
||||
|
||||
g_renderer->setTransformMatrix(TransformMatrix::VIEW, rViewMatrix);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void rSetViewMatrix(const t3dM3X3F &viewMatrix, const t3dV3F &translation) {
|
||||
rSetViewMatrix(viewMatrix.M[0], viewMatrix.M[1], viewMatrix.M[2],
|
||||
viewMatrix.M[3], viewMatrix.M[4], viewMatrix.M[5],
|
||||
viewMatrix.M[6], viewMatrix.M[7], viewMatrix.M[8],
|
||||
translation.x, translation.y, -translation.z);
|
||||
}
|
||||
|
||||
void rSaveViewMatrix() {
|
||||
g_renderer->pushModelView();
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
void rRestoreViewMatrix() {
|
||||
g_renderer->popModelView();
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
bool rBuildLinesViewMatrix(float _00, float _01, float _02,
|
||||
float _03, float _04, float _05,
|
||||
float _06, float _07, float _08,
|
||||
float _tx, float _ty, float _tz) {
|
||||
rLinesViewMatrix.setIdentity();
|
||||
|
||||
rLinesViewMatrix.setValue(1, 1, _00);
|
||||
rLinesViewMatrix.setValue(1, 2, _01);
|
||||
rLinesViewMatrix.setValue(1, 3, _02);
|
||||
rLinesViewMatrix.setValue(1, 4, _tx);
|
||||
|
||||
rLinesViewMatrix.setValue(2, 1, _03);
|
||||
rLinesViewMatrix.setValue(2, 2, _04);
|
||||
rLinesViewMatrix.setValue(2, 3, _05);
|
||||
rLinesViewMatrix.setValue(2, 4, _ty);
|
||||
|
||||
rLinesViewMatrix.setValue(3, 1, -_06);
|
||||
rLinesViewMatrix.setValue(3, 2, -_07);
|
||||
rLinesViewMatrix.setValue(3, 3, -_08);
|
||||
rLinesViewMatrix.setValue(3, 4, -_tz);
|
||||
|
||||
rLinesViewMatrix.setValue(4, 1, 0.0f);
|
||||
rLinesViewMatrix.setValue(4, 2, 0.0f);
|
||||
rLinesViewMatrix.setValue(4, 3, 0.0f);
|
||||
rLinesViewMatrix.setValue(4, 4, 1.0f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int rBuildLinesViewMatrix(const t3dM3X3F &viewMatrix, const t3dV3F &translation) {
|
||||
return rBuildLinesViewMatrix(viewMatrix.M[0], viewMatrix.M[1], viewMatrix.M[2],
|
||||
viewMatrix.M[3], viewMatrix.M[4], viewMatrix.M[5],
|
||||
viewMatrix.M[6], viewMatrix.M[7], viewMatrix.M[8],
|
||||
translation.x, translation.y, translation.z);
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
int rAddUserViewMatrix(float _00, float _01, float _02,
|
||||
float _03, float _04, float _05,
|
||||
float _06, float _07, float _08,
|
||||
float _tx, float _ty, float _tz) {
|
||||
Matrix4x4 rTempViewMatrix;
|
||||
Matrix4x4 *um;
|
||||
unsigned int i;
|
||||
|
||||
rTempViewMatrix.setIdentity();
|
||||
|
||||
rTempViewMatrix.setValue(1, 1, _00);
|
||||
rTempViewMatrix.setValue(1, 2, _01);
|
||||
rTempViewMatrix.setValue(1, 3, _02);
|
||||
rTempViewMatrix.setValue(1, 4, _tx);
|
||||
|
||||
rTempViewMatrix.setValue(2, 1, _03);
|
||||
rTempViewMatrix.setValue(2, 2, _04);
|
||||
rTempViewMatrix.setValue(2, 3, _05);
|
||||
rTempViewMatrix.setValue(2, 4, _ty);
|
||||
|
||||
rTempViewMatrix.setValue(3, 1, -_06);
|
||||
rTempViewMatrix.setValue(3, 2, -_07);
|
||||
rTempViewMatrix.setValue(3, 3, -_08);
|
||||
rTempViewMatrix.setValue(3, 4, -_tz);
|
||||
|
||||
rTempViewMatrix.setValue(4, 1, 0.0f);
|
||||
rTempViewMatrix.setValue(4, 2, 0.0f);
|
||||
rTempViewMatrix.setValue(4, 3, 0.0f);
|
||||
rTempViewMatrix.setValue(4, 4, 1.0f);
|
||||
|
||||
auto &tmp = rTempViewMatrix;
|
||||
//warning("Adding: ");
|
||||
//tmp.print();
|
||||
for (i = 0, um = &rUserViewMatrix[0]; i < rNumUserViewMatrices; i++, um++) {
|
||||
//warning("Comparing %d", i);
|
||||
//um->print();
|
||||
if (*um == tmp) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= MAX_USER_VIEW_MATRICES) {
|
||||
DebugLogFile("Too many UserViewMatrix %d (MAX is %d)\n", i, MAX_USER_VIEW_MATRICES);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*um = tmp;
|
||||
|
||||
rNumUserViewMatrices ++;
|
||||
return rNumUserViewMatrices - 1;
|
||||
}
|
||||
|
||||
int rAddUserViewMatrix(const t3dM3X3F &viewMatrix, const t3dV3F &translation) {
|
||||
return rAddUserViewMatrix(viewMatrix.M[0], viewMatrix.M[1], viewMatrix.M[2],
|
||||
viewMatrix.M[3], viewMatrix.M[4], viewMatrix.M[5],
|
||||
viewMatrix.M[6], viewMatrix.M[7], viewMatrix.M[8],
|
||||
translation.x, translation.y, translation.z);
|
||||
}
|
||||
|
||||
void rResetPipeline() {
|
||||
gNumLinesArray = 0;
|
||||
gNumPointsBuffer = 0;
|
||||
gNumShadowBoxesList = 0;
|
||||
rNumUserViewMatrices = 0;
|
||||
g_dwD3DUserVertexBufferCounter = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
void *rGetUserVertexBuffer() {
|
||||
return g_lpD3DUserVertexBuffer;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
unsigned int rGetUserVertexBufferCounter() {
|
||||
return g_dwD3DUserVertexBufferCounter;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
void rSetUserVertexBufferCounter(unsigned int uvbc) {
|
||||
g_dwD3DUserVertexBufferCounter = uvbc;
|
||||
}
|
||||
|
||||
gVertex *rLockVertexPtr(void *vb, int flags) {
|
||||
warning("TODO: Implement rLockVertexPtr");
|
||||
#if 0
|
||||
LPVOID v;
|
||||
DWORD dim, lock_flags;
|
||||
HRESULT hResult;
|
||||
|
||||
LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuffer1 = (LPDIRECT3DVERTEXBUFFER7)vb;
|
||||
|
||||
lock_flags = DDLOCK_SURFACEMEMORYPTR;
|
||||
if (flags & rVBLOCK_READONLY)
|
||||
lock_flags |= DDLOCK_READONLY;
|
||||
else if (flags & rVBLOCK_WRITEONLY)
|
||||
lock_flags |= DDLOCK_WRITEONLY;
|
||||
if (flags & rVBLOCK_NOSYSLOCK)
|
||||
lock_flags |= DDLOCK_NOSYSLOCK;
|
||||
|
||||
if ((hResult = lpD3DVertexBuffer1->Lock(lock_flags, &v, &dim)) != D3D_OK) {
|
||||
char str[255];
|
||||
GetDDErrorString(hResult, str, 1);
|
||||
DebugLogFile("Unable to lock vertexbuffer:\r\n%s", str);
|
||||
return NULL;
|
||||
}
|
||||
return (gVertex *)v;
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Graphics::Surface *gCreateSurface(int width, int height, void *ptr) {
|
||||
auto surface = new Graphics::Surface();
|
||||
surface->w = width;
|
||||
surface->h = height;
|
||||
surface->pitch = width * 4; // TODO
|
||||
surface->setPixels(ptr);
|
||||
return surface;
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
bool rUnlockVertexPtr(void *vb) {
|
||||
warning("Implement rUnlockVertexPtr");
|
||||
#if 0
|
||||
LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuffer1 = (LPDIRECT3DVERTEXBUFFER7)vb;
|
||||
|
||||
if (lpD3DVertexBuffer1->Unlock() != D3D_OK) {
|
||||
DebugLogFile("VertexBuffer Unlock error");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//***********************************************************************************************
|
||||
void rSetLinesViewMatrix() {
|
||||
g_renderer->setTransformMatrix(TransformMatrix::VIEW, rLinesViewMatrix);
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
void rSetUserViewMatrix(int num) {
|
||||
auto &matrix = rUserViewMatrix[num];
|
||||
|
||||
g_renderer->setTransformMatrix(TransformMatrix::VIEW, matrix);
|
||||
}
|
||||
|
||||
|
||||
//*********************************************************************************************
|
||||
unsigned int gGetTextureListPosition() {
|
||||
unsigned int pos = 1;
|
||||
|
||||
while (!gTextureList[pos].isEmpty()) { // TODO: Do we need the surface?
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (pos > MAXTEXTURES)
|
||||
return 0;
|
||||
|
||||
if (pos > gNumTextureList)
|
||||
gNumTextureList = pos;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
void gBuildAlternateName(char *AltName, const char *Name) {
|
||||
int len, i, j;
|
||||
|
||||
if (!Name || !AltName) return;
|
||||
|
||||
len = strlen(Name);
|
||||
memset(AltName, 0, len + 4);
|
||||
memcpy(AltName, Name, len);
|
||||
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
if ((AltName[i] == '.') && (i < (len - 3))) {
|
||||
AltName[i + 1] = 'd';
|
||||
AltName[i + 2] = 'd';
|
||||
AltName[i + 3] = 's';
|
||||
}
|
||||
if (AltName[i] == '\\' || AltName[i] == '/') {
|
||||
for (j = len; j >= i; j--)
|
||||
AltName[j + 3] = AltName[j];
|
||||
|
||||
AltName[i + 0] = 'D';
|
||||
AltName[i + 1] = 'D';
|
||||
AltName[i + 2] = 'S';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//warning("Build alternate name %s -> %s", Name, AltName);
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
void gBuildAlternateName(char *AltName, char *Name) {
|
||||
int len, i, j;
|
||||
|
||||
if (!Name || !AltName) return;
|
||||
|
||||
len = strlen(Name);
|
||||
memset(AltName, 0, len + 4);
|
||||
memcpy(AltName, Name, len);
|
||||
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
if ((AltName[i] == '.') && (i < (len - 3))) {
|
||||
AltName[i + 1] = 'd';
|
||||
AltName[i + 2] = 'd';
|
||||
AltName[i + 3] = 's';
|
||||
}
|
||||
if (AltName[i] == '\\') {
|
||||
for (j = len; j >= i; j--)
|
||||
AltName[j + 3] = AltName[j];
|
||||
|
||||
AltName[i + 0] = 'D';
|
||||
AltName[i + 1] = 'D';
|
||||
AltName[i + 2] = 'S';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
gTexture *gUserTexture(Texture *texture, unsigned int dimx, unsigned int dimy) {
|
||||
gTexture *Texture;
|
||||
int pos;
|
||||
//DDSURFACEDESC2 DDSurfDesc;
|
||||
|
||||
pos = gGetTextureListPosition();
|
||||
if (pos == 0) {
|
||||
DebugLogFile("gUserTexture: Can't create more textures");
|
||||
return nullptr;
|
||||
}
|
||||
Texture = &gTextureList[pos];
|
||||
*Texture = gTexture();
|
||||
Texture->Flags = CurLoaderFlags;
|
||||
|
||||
{
|
||||
#if 0
|
||||
memset(&DDSurfDesc, 0, sizeof(DDSURFACEDESC2));
|
||||
memcpy(&DDSurfDesc.ddpfPixelFormat, &gCurrentFormat->SurfaceDesc, sizeof(DDPIXELFORMAT));
|
||||
DDSurfDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
|
||||
if (gRenderFlags & gAGPSUPPORTED) {
|
||||
//Alloc texture in AGP
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY |
|
||||
DDSCAPS_TEXTURE;
|
||||
} else {
|
||||
//No AGP support; alloc in sysmem
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
DDSurfDesc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
|
||||
}
|
||||
#endif
|
||||
if (dimx > 8) {
|
||||
if (dimx > 16) {
|
||||
if (dimx > 32) {
|
||||
if (dimx > 64) {
|
||||
if (dimx > 128) {
|
||||
dimx = 256;
|
||||
} else {
|
||||
dimx = 128;
|
||||
}
|
||||
} else {
|
||||
dimx = 64;
|
||||
}
|
||||
} else {
|
||||
dimx = 32;
|
||||
}
|
||||
} else {
|
||||
dimx = 16;
|
||||
}
|
||||
}
|
||||
if (dimy > 8) {
|
||||
if (dimy > 16) {
|
||||
if (dimy > 32) {
|
||||
if (dimy > 64) {
|
||||
if (dimy > 128) {
|
||||
dimy = 256;
|
||||
} else {
|
||||
dimy = 128;
|
||||
}
|
||||
} else {
|
||||
dimy = 64;
|
||||
}
|
||||
} else {
|
||||
dimy = 32;
|
||||
}
|
||||
} else {
|
||||
dimy = 16;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
DDSurfDesc.dwWidth = dimx;
|
||||
DDSurfDesc.dwHeight = dimy;
|
||||
|
||||
if (!(Texture->lpDDSurface = gCreateSurface(&DDSurfDesc, Texture->lpDDSurface))) {
|
||||
DebugLogFile("gCreateSurface FAILED: Can't create surface");
|
||||
return NULL;
|
||||
}
|
||||
strcpy(Texture->Name, "UserTexture");
|
||||
gClear(Texture->lpDDSurface, 0, 0, dimx, dimy, 0, 0, 0);
|
||||
#endif
|
||||
Texture->ID = pos;
|
||||
|
||||
Texture->DimX = dimx;
|
||||
Texture->DimY = dimy;
|
||||
#if 0
|
||||
DDCOLORKEY ddck;
|
||||
ddck.dwColorSpaceLowValue = 0;
|
||||
ddck.dwColorSpaceHighValue = 0;
|
||||
Texture->lpDDSurface->SetColorKey(DDCKEY_SRCBLT, &ddck);
|
||||
#endif
|
||||
}
|
||||
|
||||
Texture->_texture = texture;
|
||||
return Texture;
|
||||
}
|
||||
|
||||
class SurfaceBackedTextureData : public TextureData {
|
||||
bool _owned = true;
|
||||
public:
|
||||
Graphics::Surface *_surface;
|
||||
SurfaceBackedTextureData(Graphics::Surface *surface, bool owned = true) : TextureData(DxtCompression::UNCOMPRESSED), _surface(surface), _owned(owned) {}
|
||||
~SurfaceBackedTextureData() override {
|
||||
if (_owned) {
|
||||
_surface->free();
|
||||
delete _surface;
|
||||
}
|
||||
}
|
||||
int getWidth() const override {
|
||||
return _surface->w;
|
||||
}
|
||||
int getHeight() const override {
|
||||
return _surface->h;
|
||||
}
|
||||
int getDataSize() const override {
|
||||
return _surface->w * _surface->h * _surface->format.bytesPerPixel;
|
||||
}
|
||||
const void *getData() const override {
|
||||
return _surface->getPixels();
|
||||
}
|
||||
};
|
||||
|
||||
Common::SharedPtr<TextureData> createTextureFromSurface(Graphics::Surface &surface, int texFormat) {
|
||||
return Common::SharedPtr<TextureData>(new SurfaceBackedTextureData(&surface, false));
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
gTexture *gLoadTexture(WorkDirs &workDirs, const char *TextName, unsigned int _LoaderFlags) {
|
||||
//bool bAlpha = FALSE
|
||||
bool bUseAlternate = FALSE;
|
||||
gTexture *texture = nullptr;
|
||||
int32 pos = 0;
|
||||
char AlternateName[500] {};
|
||||
uint32 date1 = 0, date2 = 0, time1 = 0, time2 = 0;
|
||||
//uint32 magic,retv;
|
||||
unsigned long dwWidth = 0, dwHeight = 0;
|
||||
//DDSURFACEDESC2 DDSurfDesc;
|
||||
//Graphics::Surface *lpSSource = nullptr;
|
||||
|
||||
if (!TextName) return nullptr;
|
||||
//lpSSource = nullptr;
|
||||
|
||||
//warning("gLoadTexture(%s)", TextName);
|
||||
// Check if already loaded
|
||||
for (uint32 i = 0; i < gNumTextureList; i++) {
|
||||
if (gTextureList[i].name.equalsIgnoreCase(TextName)) {
|
||||
//Texture already loaded; just assign pointers
|
||||
texture = &gTextureList[i];
|
||||
texture->ID = i;
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
/* VERSIONE ORIGINALE by FAB
|
||||
gBuildAlternateName( AlternateName, TextName );
|
||||
if( ( CurLoaderFlags & T3D_FASTFILE ) || ( !t3dGetFileDate( &date1, &time1, TextName ) ) )
|
||||
bUseAlternate = TRUE;
|
||||
if( !t3dGetFileDate( &date2, &time2, AlternateName ) )
|
||||
{
|
||||
if( bUseAlternate == TRUE )
|
||||
{
|
||||
DebugLogFile("gAddMaterial:gLoadTexture: Cannot find %s and alternate %s.\n", TextName, AlternateName );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if( bUseAlternate == FALSE )
|
||||
{
|
||||
if( ( date2 > date1 ) || ( ( date2 == date1 ) && ( time2 >= time1 ) ) )
|
||||
bUseAlternate = TRUE;
|
||||
}
|
||||
*/
|
||||
|
||||
gBuildAlternateName(AlternateName, TextName);
|
||||
|
||||
if (!t3dGetFileDate(&date1, &time1, TextName)) // if it doesn't find the .tga texture, try the dds
|
||||
bUseAlternate = TRUE;
|
||||
|
||||
if (!t3dGetFileDate(&date2, &time2, AlternateName)) { //se non trova la texture .dds
|
||||
if (bUseAlternate == TRUE) { // does not find the .dds texture and furthermore the .tga does not exist
|
||||
DebugLogFile("gAddMaterial:gLoadTexture: Cannot find %s and alternate %s.\n", TextName, AlternateName);
|
||||
return nullptr;
|
||||
}
|
||||
} else if (bUseAlternate == FALSE) { // if there is the .dds and there is also the .tga see which is newer
|
||||
if ((date2 > date1) || ((date2 == date1) && (time2 >= time1)))
|
||||
bUseAlternate = TRUE;
|
||||
}
|
||||
|
||||
|
||||
if ((pos = gGetTextureListPosition()) == 0) {
|
||||
DebugLogFile("gLoadTexture: Can't create more textures");
|
||||
return nullptr;
|
||||
}
|
||||
texture = &gTextureList[pos];
|
||||
*texture = gTexture();
|
||||
texture->_texture = createGLTexture();
|
||||
|
||||
if (bUseAlternate) {
|
||||
auto stream = workDirs.resolveFile(AlternateName);
|
||||
if (!stream) {
|
||||
DebugLogFile("gAddMaterial:gLoadTexture: Cannot find %s.\n", AlternateName);
|
||||
return nullptr;
|
||||
}
|
||||
auto ddsTextureData = loadDdsTexture(*stream);
|
||||
texture->_texture->assignData(*ddsTextureData);
|
||||
dwWidth = ddsTextureData->getWidth();
|
||||
dwHeight = ddsTextureData->getHeight();
|
||||
//lpSSource = nullptr;
|
||||
#if 0
|
||||
if (gRenderFlags & gDXT1SUPPORTED) {
|
||||
/* if( gRenderFlags & gAGPSUPPORTED )
|
||||
{ // Alloc texture in AGP
|
||||
DDSurfDesc.ddsCaps.dwCaps= DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE;
|
||||
}
|
||||
else
|
||||
*/ { //No AGP support; alloc in sysmem
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
DDSurfDesc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
|
||||
}
|
||||
lpSSource = Texture->lpDDSurface;
|
||||
} else
|
||||
DDSurfDesc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
||||
if (!(lpSSource = gCreateSurface(&DDSurfDesc, lpSSource))) {
|
||||
DebugLogFile("gLoadTexture: gCreateSurface FAILED: Can't create surface DDS");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((lpSSource->Lock(NULL, &DDSurfDesc, DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL))) { // Lock and fill with the dds
|
||||
DebugLogFile("gLoadTexture: Can't lock surface DDS");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
t3dReadData(DDSurfDesc.lpSurface, DDSurfDesc.dwLinearSize);
|
||||
|
||||
if ((lpSSource->Unlock(NULL))) {
|
||||
DebugLogFile("gLoadTexture: Can't unlock surface DDS");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
stream = nullptr;
|
||||
} else { // TGA
|
||||
auto stream = workDirs.resolveFile(TextName);
|
||||
auto image = ReadTgaImage(TextName, *stream, Graphics::PixelFormat::createFormatRGBA32(), 0); // TODO Flags
|
||||
SurfaceBackedTextureData texData(image);
|
||||
|
||||
texture->_texture->assignData(texData);
|
||||
#if 0
|
||||
//warning("TODO: Handle TGA");
|
||||
if (!t3dOpenFile(TextName)) {
|
||||
DebugLogFile("gAddMaterial:gLoadTexture: Cannot find %s.\n", TextName);
|
||||
return NULL;
|
||||
}
|
||||
// Parse the PPM header
|
||||
if (!loadTGAHeader(&dwWidth, &dwHeight)) {
|
||||
t3dCloseFile();
|
||||
DebugLogFile("gAddMaterial: gLoadTexture: Could not load or parse TGA header in %s.\n", TextName);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if 0 // Replaced by createTextureFromSurface
|
||||
if (!(gRenderFlags & gDXT1SUPPORTED) || (bUseAlternate == FALSE)) {
|
||||
memset(&DDSurfDesc, 0, sizeof(DDSURFACEDESC2));
|
||||
memcpy(&DDSurfDesc.ddpfPixelFormat, &gCurrentFormat->SurfaceDesc, sizeof(DDPIXELFORMAT));
|
||||
DDSurfDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
|
||||
/* if (gRenderFlags&gAGPSUPPORTED)
|
||||
{ //Alloc texture in AGP
|
||||
DDSurfDesc.ddsCaps.dwCaps= DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY |
|
||||
DDSCAPS_TEXTURE;
|
||||
}
|
||||
else
|
||||
*/ { //No AGP support; alloc in sysmem
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
DDSurfDesc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
|
||||
}
|
||||
DDSurfDesc.dwWidth = dwWidth;
|
||||
DDSurfDesc.dwHeight = dwHeight;
|
||||
if (!(Texture->lpDDSurface = gCreateSurface(&DDSurfDesc, Texture->lpDDSurface))) {
|
||||
DebugLogFile("gLoadTexture: gCreateSurface FAILED: Can't create surface");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
texture->name = TextName;
|
||||
|
||||
if (bUseAlternate) {
|
||||
#if 0
|
||||
// DebugFile( "Carico |%s|", AlternateName );
|
||||
if (!(gRenderFlags & gDXT1SUPPORTED)) {
|
||||
if (Texture->lpDDSurface->Blt(NULL, lpSSource, NULL, DDBLT_WAIT, NULL) != DD_OK) {
|
||||
DebugLogFile("gLoadTexture: Can't Blit DDS texture");
|
||||
return NULL;
|
||||
}
|
||||
lpSSource->Release();
|
||||
} else
|
||||
Texture->lpDDSurface = lpSSource;
|
||||
#endif
|
||||
} else {
|
||||
#if 0
|
||||
// DebugFile( "Carico |%s|", TextName );
|
||||
Texture->lpDDSurface->Lock(NULL, &DDSurfDesc, DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL); //Lock and fill with the tga
|
||||
if (gCurrentFormat->abits)
|
||||
bAlpha = TRUE;
|
||||
|
||||
if (!ReadTgaImage(TextName, &DDSurfDesc, bAlpha)) {
|
||||
DebugLogFile("gLoadTexture: Error reading TGA file");
|
||||
return NULL;
|
||||
}
|
||||
Texture->lpDDSurface->Unlock(NULL);
|
||||
#endif
|
||||
}
|
||||
texture->RealDimX = dwWidth;
|
||||
texture->RealDimY = dwHeight;
|
||||
|
||||
if (_LoaderFlags & rSURFACEHALF) {
|
||||
warning("Half-res loading not implemented");
|
||||
#if 0
|
||||
LPDIRECTDRAWSURFACE7 surf;
|
||||
HRESULT err;
|
||||
|
||||
dwWidth /= 2;
|
||||
dwHeight /= 2;
|
||||
|
||||
memset(&DDSurfDesc, 0, sizeof(DDSURFACEDESC2));
|
||||
memcpy(&DDSurfDesc.ddpfPixelFormat, &gCurrentFormat->SurfaceDesc, sizeof(DDPIXELFORMAT));
|
||||
DDSurfDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
|
||||
/* if (gRenderFlags&gAGPSUPPORTED)
|
||||
{ //Alloc texture in AGP
|
||||
DDSurfDesc.ddsCaps.dwCaps= DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY |
|
||||
DDSCAPS_TEXTURE;
|
||||
}
|
||||
else
|
||||
*/ { //No AGP support; alloc in sysmem
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
DDSurfDesc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
|
||||
}
|
||||
surf = NULL;
|
||||
DDSurfDesc.dwWidth = dwWidth;
|
||||
DDSurfDesc.dwHeight = dwHeight;
|
||||
if (!(surf = gCreateSurface(&DDSurfDesc, surf))) {
|
||||
DebugLogFile("gLoadTexture (rSURFACEHALF) FAILED: Can't create surface");
|
||||
return NULL;
|
||||
}
|
||||
if ((err = surf->Blt(NULL, Texture->lpDDSurface, NULL, 0, NULL)) != DD_OK) {
|
||||
char str[255];
|
||||
GetDDErrorString(err, str, 1);
|
||||
DebugLogFile("gLoadTexture: BltStretch failed.\n%s", str);
|
||||
}
|
||||
|
||||
//Release old texture
|
||||
Texture->lpDDSurface->Release();
|
||||
//Assign the newone
|
||||
Texture->lpDDSurface = surf;
|
||||
#endif
|
||||
}
|
||||
|
||||
texture->ID = pos;
|
||||
|
||||
texture->Flags = CurLoaderFlags;
|
||||
texture->DimX = dwWidth;
|
||||
texture->DimY = dwHeight;
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
bool Renderer::addMaterial(gMaterial &material, const Common::String &name, int NumFaces, unsigned int _LoaderFlags) {
|
||||
//warning("AddMaterial(%s)", name.c_str());
|
||||
if (hasFileExtension(name, "avi")) {
|
||||
auto tex = createGLTexture();
|
||||
if ((material.Movie = gLoadMovie(*_workDirs, name.c_str(), tex)) == nullptr)
|
||||
return false;
|
||||
if ((material.Texture = gUserTexture(tex, 64, 128)) == nullptr)
|
||||
// if( (Material->Texture=gUserTexture( Material->Movie->g_psiStreamInfo.rcFrame.right,
|
||||
// Material->Movie->g_psiStreamInfo.rcFrame.bottom)) == NULL )
|
||||
return false;
|
||||
material.addProperty(T3D_MATERIAL_MOVIE);
|
||||
} else {
|
||||
if ((material.Texture = gLoadTexture(*_workDirs, name.c_str(), _LoaderFlags)) == nullptr)
|
||||
return false;
|
||||
}
|
||||
|
||||
//f
|
||||
material.addProperty(T3D_MATERIAL_NOLIGHTMAP);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // USE_OPENGL_GAME
|
||||
67
engines/watchmaker/3d/render/opengl_3d.h
Normal file
67
engines/watchmaker/3d/render/opengl_3d.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_OPENGL_3D_H
|
||||
#define WATCHMAKER_OPENGL_3D_H
|
||||
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/render.h"
|
||||
|
||||
#define MAXTEXTURES 2000
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
struct gAvailFormat {
|
||||
//DDPIXELFORMAT SurfaceDesc;
|
||||
char rbits;
|
||||
char gbits;
|
||||
char bbits;
|
||||
char abits;
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
float sx, sy, sz, rhw;
|
||||
uint32 color;
|
||||
};
|
||||
|
||||
extern unsigned int gNumTrianglesArray;
|
||||
extern unsigned int gNumLinesArray;
|
||||
|
||||
extern gAvailFormat *gCurrentFormat;
|
||||
extern int NumAvailableFormats;
|
||||
extern gAvailFormat AvailableFormats[];
|
||||
|
||||
extern gTexture gTextureList[];
|
||||
extern unsigned int gNumTextureList;
|
||||
|
||||
extern uint16 gLinesArray[];
|
||||
extern unsigned int gNumLinesArray;
|
||||
extern unsigned int gNumTrianglesArray;
|
||||
extern Vertex gTriangles[];
|
||||
extern int g_lpD3DPointsBuffer;
|
||||
extern void *g_lpD3DUserVertexBuffer;
|
||||
extern unsigned int g_dwD3DUserVertexBufferCounter;
|
||||
extern unsigned int gNumPointsBuffer;
|
||||
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_OPENGL_3D_H
|
||||
239
engines/watchmaker/3d/render/opengl_renderer.cpp
Normal file
239
engines/watchmaker/3d/render/opengl_renderer.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/render/opengl_renderer.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
|
||||
#if defined(USE_OPENGL_GAME)
|
||||
|
||||
#include "graphics/opengl/system_headers.h"
|
||||
#include "math/glmath.h"
|
||||
|
||||
#include "math/glmath.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
OpenGLRenderer *g_renderer = nullptr;
|
||||
|
||||
void OpenGLRenderer::drawIndexedPrimitivesVBO(PrimitiveType primitiveType, Common::SharedPtr<VertexBuffer> VBO, int firstVertex, int numVertices, Common::Array<uint16> faces, uint32 numFaces) {
|
||||
assert(numFaces <= faces.size());
|
||||
|
||||
assert(primitiveType == PrimitiveType::TRIANGLE);
|
||||
|
||||
float fNearPlane = 1.0f;//5000.0f;
|
||||
float fFarPlane = 15000.0f;
|
||||
float width = 1024;
|
||||
float height = 768;
|
||||
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
float fAspect = 60.0f;//curCamera->FovRad;
|
||||
auto perspectiveMatrix = Math::makePerspectiveMatrix(fAspect, width / height, fNearPlane, fFarPlane);
|
||||
glLoadMatrixf(perspectiveMatrix.getData());
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (uint32 i = 0; i < numFaces; i++) {
|
||||
uint16 index = faces[i];
|
||||
assert(index <= VBO->_buffer.size());
|
||||
auto &vertex = VBO->_buffer[index];
|
||||
//warning("%d/%d %d: [%f, %f, %f], [%f, %f], [%f, %f]", i, numFaces, index, vertex.x, vertex.y, vertex.z, vertex.u1, vertex.v1, vertex.u2, vertex.v2);
|
||||
//glColor4f((float)i/numFaces, 1.0f, 0.0f, 1.0f);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glTexCoord2f(vertex.u1, vertex.v1);
|
||||
glVertex3f(vertex.x, vertex.y, -vertex.z);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glFlush();
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::drawPrimitives(PrimitiveType primitiveType, Vertex *vertices, int numPrimitives) {
|
||||
assert(primitiveType == PrimitiveType::TRIANGLE);
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (int i = 0; i < numPrimitives; i++) {
|
||||
auto &vertex = vertices[i];
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glVertex3f(vertex.sx, vertex.sy, -vertex.sz);
|
||||
}
|
||||
glEnd();
|
||||
glFlush();
|
||||
}
|
||||
void OpenGLRenderer::drawIndexedPrimitivesVBO(PrimitiveType primitiveType, int VBO, int firstVertex, int numVertices, uint16 *faces, uint32 numFaces) {
|
||||
//warning("TODO: Implement drawIndexedPrimitivesVBO");
|
||||
}
|
||||
|
||||
|
||||
void OpenGLRenderer::drawIndexedPrimitivesVBO(PrimitiveType primitiveType, gBatchBlock &bb) {
|
||||
drawIndexedPrimitivesVBO(primitiveType,
|
||||
bb.VBO, 0, bb.NumVerts(),
|
||||
bb.FacesList,
|
||||
bb.NumFaces()/*, 0x0*/
|
||||
);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setTransformMatrix(TransformMatrix which, const Matrix4x4 &matrix) {
|
||||
GLint oldMatrixMode;
|
||||
glGetIntegerv(GL_MATRIX_MODE, &oldMatrixMode);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadMatrixf(matrix.data);
|
||||
glScalef(1.0f, 1.0f, -1.0f);
|
||||
glMatrixMode(oldMatrixMode);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::pushModelView() {
|
||||
GLint oldMatrixMode;
|
||||
glGetIntegerv(GL_MATRIX_MODE, &oldMatrixMode);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glMatrixMode(oldMatrixMode);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::popModelView() {
|
||||
GLint oldMatrixMode;
|
||||
glGetIntegerv(GL_MATRIX_MODE, &oldMatrixMode);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(oldMatrixMode);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setTextureWrapMode(int index, TextureWrapMode mode) {
|
||||
GLint openGlWrapMode = 0;
|
||||
switch (mode) {
|
||||
case TextureWrapMode::WRAP:
|
||||
openGlWrapMode = GL_REPEAT;
|
||||
break;
|
||||
case TextureWrapMode::CLAMP:
|
||||
openGlWrapMode = GL_CLAMP;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, openGlWrapMode);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, openGlWrapMode);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setTexture(int stage, void *texture) {
|
||||
if (texture == nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
void OpenGLRenderer::setTexture(int stage, const gTexture &texture) {
|
||||
texture._texture->bind();
|
||||
}
|
||||
|
||||
void setGlFeature(GLint feature, bool state) {
|
||||
if (state) {
|
||||
glEnable(feature);
|
||||
} else {
|
||||
glDisable(feature);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setRenderState(RenderState state, int value) {
|
||||
switch (state) {
|
||||
case RenderState::ZENABLE:
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
setGlFeature(GL_DEPTH_TEST, value);
|
||||
break;
|
||||
case RenderState::ALPHAREF: // ALPHA-func is never changed.
|
||||
glAlphaFunc(GL_ALWAYS, value);
|
||||
// fall through
|
||||
// FIXME: Is this intended?
|
||||
case RenderState::ALPHABLEND:
|
||||
setGlFeature(GL_BLEND, value);
|
||||
break; // TODO
|
||||
|
||||
case RenderState::LIGHT:
|
||||
case RenderState::CLIP:
|
||||
case RenderState::EXTENT:
|
||||
case RenderState::ZWRITE_ENABLE:
|
||||
case RenderState::TEXTUREFACTOR:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//warning("TODO: Implement setRenderState");
|
||||
}
|
||||
|
||||
GLenum translateBlendFactorToGL(BlendFactor factor) {
|
||||
switch (factor) {
|
||||
case BlendFactor::ONE:
|
||||
return GL_ONE;
|
||||
case BlendFactor::ZERO:
|
||||
return GL_ZERO;
|
||||
case BlendFactor::SRCALPHA:
|
||||
return GL_SRC_ALPHA;
|
||||
case BlendFactor::INVSRCALPHA:
|
||||
return GL_ONE_MINUS_SRC_ALPHA;
|
||||
case BlendFactor::INVSRCCOLOR:
|
||||
return GL_ONE_MINUS_SRC_COLOR;
|
||||
case BlendFactor::SRCCOLOR:
|
||||
return GL_SRC_COLOR;
|
||||
case BlendFactor::DESTCOLOR:
|
||||
return GL_DST_COLOR;
|
||||
case BlendFactor::INVDESTCOLOR:
|
||||
return GL_ONE_MINUS_DST_COLOR;
|
||||
default:
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setBlendFunc(BlendFactor src, BlendFactor dst) {
|
||||
glBlendFunc(translateBlendFactorToGL(src), translateBlendFactorToGL(dst));
|
||||
}
|
||||
|
||||
void OpenGLRenderer::enter2Dmode() {
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
checkGlError("Exiting enter2Dmode");
|
||||
}
|
||||
|
||||
void OpenGLRenderer::exit2Dmode() {
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
checkGlError("exit2Dmode");
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // USE_OPENGL_GAME
|
||||
110
engines/watchmaker/3d/render/opengl_renderer.h
Normal file
110
engines/watchmaker/3d/render/opengl_renderer.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_OPENGL_RENDERER_H
|
||||
#define WATCHMAKER_OPENGL_RENDERER_H
|
||||
|
||||
|
||||
#include "watchmaker/3d/math/Matrix4x4.h"
|
||||
#include "watchmaker/utils.h"
|
||||
#include "watchmaker/render.h"
|
||||
#include "watchmaker/3d/render/opengl_3d.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
enum class TransformMatrix {
|
||||
PROJECTION,
|
||||
VIEW
|
||||
};
|
||||
|
||||
enum class RenderState {
|
||||
LIGHT,
|
||||
CLIP,
|
||||
EXTENT,
|
||||
ALPHABLEND,
|
||||
ALPHAREF, // TODO
|
||||
ZENABLE, // TODO
|
||||
ZWRITE_ENABLE, // TODO
|
||||
TEXTUREFACTOR // TODO
|
||||
};
|
||||
|
||||
enum class BlendFactor {
|
||||
ONE,
|
||||
ZERO,
|
||||
SRCALPHA,
|
||||
INVSRCALPHA,
|
||||
INVSRCCOLOR,
|
||||
SRCCOLOR,
|
||||
DESTCOLOR,
|
||||
INVDESTCOLOR
|
||||
};
|
||||
|
||||
enum class TextureWrapMode {
|
||||
WRAP,
|
||||
CLAMP
|
||||
};
|
||||
|
||||
enum class PrimitiveType {
|
||||
LINE,
|
||||
TRIANGLE
|
||||
};
|
||||
|
||||
Common::SharedPtr<TextureData> createTextureFromSurface(Graphics::Surface &surface, int texFormat);
|
||||
Texture *createGLTexture();
|
||||
|
||||
class OpenGLRenderer {
|
||||
public:
|
||||
void enter2Dmode();
|
||||
void exit2Dmode();
|
||||
|
||||
void pushModelView();
|
||||
void popModelView();
|
||||
void setTransformMatrix(TransformMatrix which, const Matrix4x4 &matrix);
|
||||
// TODO: This should be split.
|
||||
void setRenderState(RenderState state, int value);
|
||||
void setBlendFunc(BlendFactor src, BlendFactor dst);
|
||||
bool error() const {
|
||||
//warning("TODO: Implement error");
|
||||
return false;
|
||||
}
|
||||
Common::String getErrorString() {
|
||||
warning("TODO: Implement getErrorString");
|
||||
return "";
|
||||
}
|
||||
// TODO: This just maps to the D3D way to setting textures
|
||||
void setTexture(int stage, void *texture);
|
||||
void setTexture(int stage, const gTexture &texture);
|
||||
void setTextureWrapMode(int index, TextureWrapMode mode);
|
||||
|
||||
void drawPrimitives(PrimitiveType primitiveType, Vertex *vertices, int numPrimitives);
|
||||
void drawIndexedPrimitivesVBO(PrimitiveType primitiveType, int VBO, int firstVertex, int numVertices, uint16 *faces, uint32 numFaces);
|
||||
void drawIndexedPrimitivesVBO(PrimitiveType primitiveType, Common::SharedPtr<VertexBuffer> VBO, int firstVertex, int numVertices, Common::Array<uint16> faces, uint32 numFaces);
|
||||
void drawIndexedPrimitivesVBO(PrimitiveType primitiveType, gBatchBlock &bb);
|
||||
bool supportsMultiTexturing() const { // TODO
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
extern OpenGLRenderer *g_renderer;
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_OPENGL_RENDERER_H
|
||||
96
engines/watchmaker/3d/render/opengl_texture.cpp
Normal file
96
engines/watchmaker/3d/render/opengl_texture.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/render/opengl_texture.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "graphics/opengl/system_headers.h"
|
||||
#include "watchmaker/3d/dds_header.h"
|
||||
#include "watchmaker/render.h"
|
||||
|
||||
#ifdef USE_OPENGL_GAME
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
GLuint dxtCompressionToTextureFormat(DxtCompression compression) {
|
||||
switch (compression) {
|
||||
case DxtCompression::UNCOMPRESSED:
|
||||
default:
|
||||
return GL_RGBA;
|
||||
case DxtCompression::DXT1:
|
||||
return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
case DxtCompression::DXT2:
|
||||
error("DXT2 Support is not implemented");
|
||||
case DxtCompression::DXT3:
|
||||
return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
case DxtCompression::DXT4:
|
||||
error("DXT4 Support is not implemented");
|
||||
case DxtCompression::DXT5:
|
||||
return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
}
|
||||
}
|
||||
|
||||
class OpenGLTexture : public Texture {
|
||||
public:
|
||||
unsigned int _texId;
|
||||
OpenGLTexture() {
|
||||
glGenTextures(1, &_texId);
|
||||
}
|
||||
OpenGLTexture(unsigned int texId) : _texId(texId) {}
|
||||
void assignData(const TextureData &data) override {
|
||||
glBindTexture(GL_TEXTURE_2D, _texId);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
|
||||
// TODO: Check both compiletime and runtime for the existence of EXT_texture_compression_s3tc
|
||||
GLuint texFormat = dxtCompressionToTextureFormat(data._compression);
|
||||
bool compressed = data._compression != DxtCompression::UNCOMPRESSED;
|
||||
|
||||
if (compressed) {
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, // target
|
||||
0, // level
|
||||
texFormat, // internalFormat
|
||||
data.getWidth(), // width
|
||||
data.getHeight(), // height
|
||||
0, // border
|
||||
data.getDataSize(),
|
||||
data.getData()
|
||||
);
|
||||
checkGlError("glCompressedTexImage");
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, texFormat, data.getWidth(), data.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data.getData());
|
||||
checkGlError("glTexImage2D");
|
||||
}
|
||||
}
|
||||
void bind() override {
|
||||
glBindTexture(GL_TEXTURE_2D, _texId);
|
||||
checkGlError("OpenGLTexture::bind");
|
||||
};
|
||||
};
|
||||
|
||||
Texture *createGLTexture() {
|
||||
return new OpenGLTexture();
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // USE_OPENGL_GAME
|
||||
32
engines/watchmaker/3d/render/opengl_texture.h
Normal file
32
engines/watchmaker/3d/render/opengl_texture.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_3D_OPENGL_TEXTURE_H
|
||||
#define WATCHMAKER_3D_OPENGL_TEXTURE_H
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
class Texture;
|
||||
Texture *createGLTexture();
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_3D_OPENGL_TEXTURE_H
|
||||
621
engines/watchmaker/3d/render/render.cpp
Normal file
621
engines/watchmaker/3d/render/render.cpp
Normal file
@@ -0,0 +1,621 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/render.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/3d/render/opengl_3d.h"
|
||||
#include "watchmaker/render.h"
|
||||
#include "watchmaker/3d/render/opengl_renderer.h"
|
||||
#include "watchmaker/3d/render/opengl_2d.h"
|
||||
#include "watchmaker/3d/render/shadows.h"
|
||||
#include "watchmaker/ll/ll_regen.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
unsigned int bLightmaps = FALSE; // if lightmaps are activated
|
||||
unsigned int bDisableShadows = FALSE; // if shadows should be disabled
|
||||
unsigned int bDisableMultiTexturing = FALSE; // if multitexturing should be disabled
|
||||
|
||||
gBatchBlock BatchBlockList[MAX_BATCH_BLOCKS];
|
||||
gBatchBlock BatchBlockListSpecial[MAX_BATCH_BLOCKS_SPECIAL];
|
||||
//gBatchBlock BatchBlockListLightmaps[MAX_BATCH_BLOCKS_LIGHTMAPS];
|
||||
gBatchBlock BatchBlockListSky[MAX_BATCH_BLOCKS_SKY];
|
||||
|
||||
unsigned int NumBatchBlocks = 0;
|
||||
unsigned int NumBatchBlocksSpecial = 0;
|
||||
//unsigned int NumBatchBlocksLightmaps=0;
|
||||
unsigned int NumBatchBlocksSky = 0;
|
||||
|
||||
/* -----------------13/08/99 10.34-------------------
|
||||
* Comparazione per BB
|
||||
* --------------------------------------------------*/
|
||||
int cmpbb(const void *a, const void *b) {
|
||||
const gBatchBlock *v1 = (const gBatchBlock *)a;
|
||||
const gBatchBlock *v2 = (const gBatchBlock *)b;
|
||||
|
||||
if (v1->Texture2 < v2->Texture2) return -1;
|
||||
else if (v1->Texture2 > v2->Texture2) return 1;
|
||||
else if (v1->Texture1 < v2->Texture1) return -1;
|
||||
else if (v1->Texture1 > v2->Texture1) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
/* -----------------31/05/99 10.12-------------------
|
||||
* Attiva o disattiva lo ZBuffer
|
||||
* --------------------------------------------------*/
|
||||
bool rSetZBufferState(bool state) {
|
||||
g_renderer->setRenderState(RenderState::ZENABLE, state);
|
||||
g_renderer->setRenderState(RenderState::ZWRITE_ENABLE, state);
|
||||
|
||||
return !g_renderer->error();
|
||||
}
|
||||
|
||||
|
||||
/* -----------------25/06/99 11.14-------------------
|
||||
* Renderizza il cielo senza considerare lo zbuffer
|
||||
* --------------------------------------------------*/
|
||||
void RenderSky() {
|
||||
unsigned int i;
|
||||
bool hres;
|
||||
gBatchBlock *bb;
|
||||
|
||||
if (!NumBatchBlocksSky)
|
||||
return;
|
||||
|
||||
if (!rSetZBufferState(false)) {
|
||||
DebugLogFile("Can't rSetZBufferState FALSE");
|
||||
return ;
|
||||
}
|
||||
|
||||
g_renderer->setRenderState(RenderState::ALPHABLEND, TRUE);
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x00000055);
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::INVSRCALPHA);
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bb = &BatchBlockListSky[0];
|
||||
for (i = 0; i < NumBatchBlocksSky; i++, bb++) {
|
||||
if (bb->Texture1 < 0) continue;
|
||||
rSetUserViewMatrix(bb->ViewMatrixNum);
|
||||
|
||||
if (bb->Texture1)
|
||||
g_renderer->setTexture(0, gTextureList[bb->Texture1]);
|
||||
else
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::TRIANGLE, *bb);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
bb->Texture1 = -3;
|
||||
bb->Texture2 = -3;
|
||||
}
|
||||
|
||||
if (!rSetZBufferState(true)) {
|
||||
DebugLogFile("Can't rSetZBufferState TRUE");
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -----------------31/05/99 10.19-------------------
|
||||
* Renderizza la Geometria
|
||||
* --------------------------------------------------*/
|
||||
void RenderGeometry() {
|
||||
signed short int LastViewMatrixNum, LastTexture1, LastTexture2;
|
||||
gBatchBlock *bb;
|
||||
bool hres = false;
|
||||
|
||||
RenderSky();
|
||||
//warning("TODO: Texture configuration");
|
||||
#if 0
|
||||
g_renderer->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
#endif
|
||||
g_renderer->setTextureWrapMode(1, TextureWrapMode::CLAMP);
|
||||
|
||||
g_renderer->setRenderState(RenderState::TEXTUREFACTOR, 0xFFFFFFFF);
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x00000000);
|
||||
|
||||
g_renderer->setRenderState(RenderState::ALPHABLEND, FALSE);
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LastViewMatrixNum = LastTexture1 = LastTexture2 = -2;
|
||||
bb = &BatchBlockList[0];
|
||||
qsort(bb, NumBatchBlocks, sizeof(gBatchBlock), cmpbb);
|
||||
for (uint i = 0; i < NumBatchBlocks; i++, bb++) {
|
||||
if (bb->Texture1 < 0) continue;
|
||||
|
||||
if (bb->ViewMatrixNum != LastViewMatrixNum) {
|
||||
rSetUserViewMatrix(bb->ViewMatrixNum);
|
||||
LastViewMatrixNum = bb->ViewMatrixNum;
|
||||
}
|
||||
if (bb->Texture1 != LastTexture1) {
|
||||
if (bb->Texture1)
|
||||
g_renderer->setTexture(0, gTextureList[bb->Texture1]);
|
||||
else
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
LastTexture1 = bb->Texture1;
|
||||
}
|
||||
if ((g_renderer->supportsMultiTexturing()) && (bb->Texture2 != LastTexture2)) {
|
||||
if (bb->Texture2 > 0) {
|
||||
if (LastTexture2 <= 0) {
|
||||
//warning("TODO: Texture configuration");
|
||||
#if 0
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
|
||||
#endif
|
||||
g_renderer->setTextureWrapMode(1, TextureWrapMode::CLAMP);
|
||||
}
|
||||
g_renderer->setTexture(1, gTextureList[bb->Texture2]);
|
||||
} else if (LastTexture2 > 0) {
|
||||
//warning("TODO: Texture configuration");
|
||||
#if 0
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
#endif
|
||||
g_renderer->setTexture(1, nullptr);
|
||||
}
|
||||
LastTexture2 = bb->Texture2;
|
||||
}
|
||||
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::TRIANGLE, *bb);
|
||||
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
bb->Texture1 = -3;
|
||||
}
|
||||
//warning("TODO: Texture configuration");
|
||||
#if 0
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
#endif
|
||||
|
||||
// 2nd pass: lightmaps, if device doesn't support multi-texturing
|
||||
if ((!g_renderer->supportsMultiTexturing()) && (bLightmaps)) {
|
||||
g_renderer->setRenderState(RenderState::ZWRITE_ENABLE, FALSE);
|
||||
|
||||
#if 0 // TODO
|
||||
g_renderer->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 1); // use mapping coordinates set 1
|
||||
#endif
|
||||
g_renderer->setBlendFunc(BlendFactor::ZERO, BlendFactor::SRCCOLOR);
|
||||
g_renderer->setRenderState(RenderState::ALPHABLEND, true);
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LastViewMatrixNum = LastTexture1 = LastTexture2 = -2;
|
||||
bb = &BatchBlockList[0];
|
||||
for (uint i = 0; i < NumBatchBlocks; i++, bb++) {
|
||||
if (bb->Texture2 <= 0) continue;
|
||||
|
||||
if (bb->ViewMatrixNum != LastViewMatrixNum) {
|
||||
rSetUserViewMatrix(bb->ViewMatrixNum);
|
||||
LastViewMatrixNum = bb->ViewMatrixNum;
|
||||
}
|
||||
if (bb->Texture2 != LastTexture2) {
|
||||
g_renderer->setTexture(0, gTextureList[bb->Texture2]);
|
||||
LastTexture2 = bb->Texture2;
|
||||
}
|
||||
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::TRIANGLE, *bb);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
g_renderer->setRenderState(RenderState::ZWRITE_ENABLE, TRUE);
|
||||
#if 0 // TODO
|
||||
g_renderer->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); // mapping coordinates back to set 0
|
||||
#endif
|
||||
}
|
||||
|
||||
// Clipmaps
|
||||
g_renderer->setRenderState(RenderState::ALPHABLEND, TRUE);
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x00000055);
|
||||
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::INVSRCALPHA);
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LastViewMatrixNum = LastTexture1 = LastTexture2 = -2;
|
||||
bb = &BatchBlockListSpecial[0];
|
||||
qsort(bb, NumBatchBlocksSpecial, sizeof(gBatchBlock), cmpbb);
|
||||
for (uint i = 0; i < NumBatchBlocksSpecial; i++, bb++) {
|
||||
if (bb->Texture1 < 0) continue;
|
||||
if (!(bb->Flags1 & T3D_MATERIAL_CLIPMAP) ||
|
||||
(bb->Flags1 & T3D_MATERIAL_FLARE) ||
|
||||
(bb->Flags1 & T3D_MATERIAL_SMOKE))
|
||||
continue;
|
||||
|
||||
if (bb->ViewMatrixNum != LastViewMatrixNum) {
|
||||
rSetUserViewMatrix(bb->ViewMatrixNum);
|
||||
LastViewMatrixNum = bb->ViewMatrixNum;
|
||||
}
|
||||
if (bb->Texture1 != LastTexture1) {
|
||||
if (bb->Texture1)
|
||||
g_renderer->setTexture(0, gTextureList[bb->Texture1]);
|
||||
else
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
LastTexture1 = bb->Texture1;
|
||||
}
|
||||
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::TRIANGLE, *bb);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
bb->Texture1 = -3;
|
||||
bb->Texture2 = -3;
|
||||
}
|
||||
|
||||
// Render Smoke or Flare materials
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x00000055);
|
||||
g_renderer->setRenderState(RenderState::ZWRITE_ENABLE, FALSE);
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LastViewMatrixNum = LastTexture1 = LastTexture2 = -2;
|
||||
bb = &BatchBlockListSpecial[0];
|
||||
for (uint i = 0; i < NumBatchBlocksSpecial; i++, bb++) {
|
||||
if (bb->Texture1 < 0) continue;
|
||||
if (!(bb->Flags1 & T3D_MATERIAL_FLARE) &&
|
||||
!(bb->Flags1 & T3D_MATERIAL_SMOKE))
|
||||
continue;
|
||||
|
||||
if (bb->Flags1 & T3D_MATERIAL_FLARE_SUN) {
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::INVSRCCOLOR);
|
||||
} else if (bb->Flags1 & T3D_MATERIAL_FLARESOFT) {
|
||||
g_renderer->setRenderState(RenderState::ZENABLE, FALSE);
|
||||
g_renderer->setBlendFunc(BlendFactor::DESTCOLOR, BlendFactor::ONE);
|
||||
} else if (bb->Flags1 & T3D_MATERIAL_SMOKE) {
|
||||
g_renderer->setBlendFunc(BlendFactor::SRCALPHA, BlendFactor::ONE);
|
||||
} else {
|
||||
g_renderer->setBlendFunc(BlendFactor::SRCCOLOR, BlendFactor::ONE);
|
||||
}
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bb->ViewMatrixNum != LastViewMatrixNum) {
|
||||
rSetUserViewMatrix(bb->ViewMatrixNum);
|
||||
LastViewMatrixNum = bb->ViewMatrixNum;
|
||||
}
|
||||
if (bb->Texture1 != LastTexture1) {
|
||||
if (bb->Texture1)
|
||||
g_renderer->setTexture(0, gTextureList[bb->Texture1]);
|
||||
else
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
LastTexture1 = bb->Texture1;
|
||||
}
|
||||
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::TRIANGLE, *bb);
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
bb->Texture1 = -3;
|
||||
bb->Texture2 = -3;
|
||||
}
|
||||
g_renderer->setRenderState(RenderState::ZWRITE_ENABLE, TRUE);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Print transparent/translucent materials
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x0000002);
|
||||
|
||||
LastViewMatrixNum = LastTexture1 = LastTexture2 = -2;
|
||||
bb = &BatchBlockListSpecial[0];
|
||||
for (uint i = 0; i < NumBatchBlocksSpecial; i++, bb++) {
|
||||
if (bb->Texture1 < 0) continue;
|
||||
if ((bb->Flags1 & T3D_MATERIAL_FLARE) ||
|
||||
(bb->Flags1 & T3D_MATERIAL_SMOKE))
|
||||
continue;
|
||||
|
||||
if (bb->Flags1 & T3D_MATERIAL_GLASS) {
|
||||
g_renderer->setBlendFunc(BlendFactor::DESTCOLOR, BlendFactor::ZERO);
|
||||
return;
|
||||
} else if (bb->Flags1 & T3D_MATERIAL_OPACITY) {
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::SRCCOLOR);
|
||||
} else if (bb->Flags1 & T3D_MATERIAL_BOTTLE) {
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::INVDESTCOLOR);
|
||||
} else if (bb->Flags1 & T3D_MATERIAL_ADDITIVE) {
|
||||
g_renderer->setBlendFunc(BlendFactor::DESTCOLOR, BlendFactor::ONE);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bb->ViewMatrixNum != LastViewMatrixNum) {
|
||||
rSetUserViewMatrix(bb->ViewMatrixNum);
|
||||
LastViewMatrixNum = bb->ViewMatrixNum;
|
||||
}
|
||||
if (bb->Texture1 != LastTexture1) {
|
||||
if (bb->Texture1)
|
||||
g_renderer->setTexture(0, gTextureList[bb->Texture1]);
|
||||
else
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
LastTexture1 = bb->Texture1;
|
||||
}
|
||||
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::TRIANGLE, *bb);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
bb->Texture1 = -3;
|
||||
bb->Texture2 = -3;
|
||||
}
|
||||
|
||||
// Render blank materials
|
||||
// ???
|
||||
}
|
||||
|
||||
/* -----------------31/05/99 10.55-------------------
|
||||
* Renderizza la scena
|
||||
* --------------------------------------------------*/
|
||||
bool rRenderScene() {
|
||||
unsigned int i, j;
|
||||
bool hres;
|
||||
//static unsigned int dwFrameCount = 0;
|
||||
|
||||
g_renderer->setRenderState(RenderState::LIGHT, false);
|
||||
g_renderer->setRenderState(RenderState::CLIP, true);
|
||||
g_renderer->setRenderState(RenderState::EXTENT, false);
|
||||
|
||||
// Added:
|
||||
ResetScreenBuffer();
|
||||
|
||||
if (!gStencilBitDepth && !bDisableShadows) {
|
||||
//tb
|
||||
//Render Projected shadow into shadow surface
|
||||
for (j = 0; j < gNumShadowBoxesList; j++) {
|
||||
SHADOWBOX *sb = ShadowBoxesList[j];
|
||||
rSetUserViewMatrix(sb->ViewMatrixNum);
|
||||
if (bDisableShadows) break;
|
||||
warning("TODO: Shadows");
|
||||
#if 0
|
||||
for (i = 0; i < sb->NumShadowsList; i++) {
|
||||
if (!(hres = RenderProjectiveShadow(&sb->ShadowsList[i]))) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogFile("Unable to RenderProjectiveShadow into a texture: %s | %d %d | %d", str.c_str(), S_OK, DD_OK, hres);
|
||||
bDisableShadows = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sb->ShadowsList[i].ProjectiveTexture.lpDDSurface) {
|
||||
if (hres = sb->ShadowsList[i].ProjectiveTexture.lpDDSurface->BltFast(0, 0, g_pddsShadowBuffer, NULL, DDBLTFAST_NOCOLORKEY) != S_OK) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("Unable to blitfast Shadowbuffer into a texture: %s", str.c_str());
|
||||
bDisableShadows = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
/* if (g_pddsBackBuffer && !j)
|
||||
{
|
||||
RECT rect;
|
||||
rect.left=rect.top=0;
|
||||
rect.right=rect.bottom=256;
|
||||
|
||||
if (FAILED(hres=g_pddsBackBuffer->BltFast(0,0,sb->ShadowsList[i].ProjectiveTexture.lpDDSurface,&rect,DDBLTFAST_NOCOLORKEY)))
|
||||
{
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("Unable to blit projective texture: %s",str);
|
||||
bDisableShadows=TRUE;
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
}
|
||||
//tb
|
||||
}
|
||||
|
||||
// Begin the scene.
|
||||
#if 0
|
||||
if (FAILED(g_pd3dDevice->BeginScene()))
|
||||
goto closescene;
|
||||
#endif
|
||||
RenderGeometry();
|
||||
|
||||
if (gStencilBitDepth && !bDisableShadows) {
|
||||
//sb
|
||||
rSaveViewMatrix();
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x00000002);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("Unable to SetRenderState for Shadowbuffer: %s", str.c_str());
|
||||
bDisableShadows = TRUE;
|
||||
}
|
||||
|
||||
//Render Shadows volumes
|
||||
for (j = 0; j < gNumShadowBoxesList; j++) {
|
||||
SHADOWBOX *sb = ShadowBoxesList[j];
|
||||
rSetUserViewMatrix(sb->ViewMatrixNum);
|
||||
for (i = 0; i < sb->NumShadowsList; i++)
|
||||
RenderShadow(&sb->ShadowsList[i], sb->ShadowsList[i].VB);
|
||||
|
||||
if (i) {
|
||||
RenderShadowBox(sb, sb->VBO);
|
||||
|
||||
unsigned int width, height, bpp;
|
||||
rGetScreenInfos(&width, &height, &bpp);
|
||||
DrawShadow(0, 0, width, height, sb->Intensity);
|
||||
}
|
||||
}
|
||||
rRestoreViewMatrix();
|
||||
//sb
|
||||
} else if (!bDisableShadows) {
|
||||
//tb
|
||||
for (j = 0; j < gNumShadowBoxesList; j++) {
|
||||
SHADOWBOX *sb = ShadowBoxesList[j];
|
||||
rSetUserViewMatrix(sb->ViewMatrixNum);
|
||||
for (i = 0; i < sb->NumShadowsList; i++)
|
||||
if (!(hres = DrawProjectiveShadow(&sb->ShadowsList[i]))) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogFile("Unable to DrawProjectiveShadow: %s", str.c_str());
|
||||
bDisableShadows = TRUE;
|
||||
}
|
||||
}
|
||||
//tb
|
||||
}
|
||||
|
||||
if (gNumLinesArray && gNumPointsBuffer) {
|
||||
rSaveViewMatrix();
|
||||
rSetLinesViewMatrix();
|
||||
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::ZERO);
|
||||
g_renderer->setRenderState(RenderState::ALPHABLEND, false);
|
||||
if (g_renderer->error()) {
|
||||
goto closescene;
|
||||
}
|
||||
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
/*
|
||||
hres=g_pd3dDevice->DrawIndexedPrimitiveVB( D3DPT_LINELIST,
|
||||
g_lpD3DPointsBuffer,0,gNumPointsBuffer,
|
||||
gLinesArray, gNumLinesArray,0);
|
||||
*/
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::LINE, g_lpD3DPointsBuffer, 0, gNumPointsBuffer, gLinesArray, gNumLinesArray/*, 0*/);
|
||||
hres = g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
rRestoreViewMatrix();
|
||||
gNumLinesArray = 0;
|
||||
}
|
||||
|
||||
|
||||
if (gNumTrianglesArray) {
|
||||
rSetZBufferState(FALSE);
|
||||
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x0000000);
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::SRCALPHA);
|
||||
g_renderer->setRenderState(RenderState::ALPHABLEND, true);
|
||||
if (g_renderer->error()) {
|
||||
goto closescene;
|
||||
}
|
||||
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
g_renderer->drawPrimitives(PrimitiveType::TRIANGLE,
|
||||
/*D3DFVF_TLVERTEX,*/ gTriangles,
|
||||
gNumTrianglesArray/*, 0x0*/);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
gNumTrianglesArray = 0;
|
||||
rSetZBufferState(TRUE);
|
||||
}
|
||||
#if 0
|
||||
g_pd3dDevice->EndScene();
|
||||
#endif
|
||||
NumBatchBlocks = 0;
|
||||
NumBatchBlocksSpecial = 0;
|
||||
// NumBatchBlocksLightmaps=0;
|
||||
NumBatchBlocksSky = 0;
|
||||
|
||||
//dwFrameCount++;
|
||||
|
||||
return TRUE;
|
||||
// End the scene.
|
||||
|
||||
closescene:
|
||||
#if 0
|
||||
g_pd3dDevice->EndScene();
|
||||
#endif
|
||||
DebugLogFile("Error during renderscene");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------13/08/99 10.34-------------------
|
||||
* Aggiunge un nuovo BatchBlock
|
||||
* --------------------------------------------------*/
|
||||
gBatchBlock *rNewBatchBlock(signed short int T1, unsigned int F1, signed short int T2, unsigned int F2) {
|
||||
gBatchBlock *bb;
|
||||
|
||||
bb = nullptr;
|
||||
if ((F1 & T3D_MATERIAL_GLASS) ||
|
||||
(F1 & T3D_MATERIAL_OPACITY) ||
|
||||
(F1 & T3D_MATERIAL_CLIPMAP) ||
|
||||
(F1 & T3D_MATERIAL_SMOKE) ||
|
||||
(F1 & T3D_MATERIAL_BOTTLE) ||
|
||||
(F1 & T3D_MATERIAL_FLARE) ||
|
||||
(F1 & T3D_MATERIAL_ADDITIVE)) {
|
||||
if ((NumBatchBlocksSpecial + 1) < MAX_BATCH_BLOCKS_SPECIAL)
|
||||
bb = &BatchBlockListSpecial[NumBatchBlocksSpecial++];
|
||||
else
|
||||
DebugLogFile("Too many BB Special: %d (MAX is %d)!", NumBatchBlocksSpecial, MAX_BATCH_BLOCKS_SPECIAL);
|
||||
}
|
||||
// else if( (T2>0) )
|
||||
// {
|
||||
// if( (NumBatchBlocksLightmaps+1) < MAX_BATCH_BLOCKS_LIGHTMAPS )
|
||||
// bb=&BatchBlockList[NumBatchBlocksLightmaps++];
|
||||
// else
|
||||
// DebugLogFile("Too many BB LightMaps: %d (MAX is %d)!",NumBatchBlocksLightmaps,MAX_BATCH_BLOCKS_LIGHTMAPS);
|
||||
// }
|
||||
else if ((F1 & T3D_MATERIAL_SKY)) {
|
||||
if ((NumBatchBlocksSky + 1) < MAX_BATCH_BLOCKS_SKY)
|
||||
bb = &BatchBlockListSky[NumBatchBlocksSky++];
|
||||
else
|
||||
DebugLogFile("Too many BB Sky: %d (MAX is %d)!", NumBatchBlocksSky, MAX_BATCH_BLOCKS_SKY);
|
||||
} else {
|
||||
if ((NumBatchBlocks + 1) < MAX_BATCH_BLOCKS)
|
||||
bb = &BatchBlockList[NumBatchBlocks++];
|
||||
else
|
||||
DebugLogFile("Too many BB: %d (MAX is %d)!", NumBatchBlocks, MAX_BATCH_BLOCKS);
|
||||
}
|
||||
|
||||
if (!bb) return nullptr;
|
||||
|
||||
*bb = gBatchBlock(T1, T2, F1, F2);
|
||||
return bb;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
29
engines/watchmaker/3d/render/render.h
Normal file
29
engines/watchmaker/3d/render/render.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_3D_RENDER_H
|
||||
#define WATCHMAKER_3D_RENDER_H
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_3D_RENDER_H
|
||||
945
engines/watchmaker/3d/render/shadows.cpp
Normal file
945
engines/watchmaker/3d/render/shadows.cpp
Normal file
@@ -0,0 +1,945 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/render/shadows.h"
|
||||
#include "watchmaker/3d/math/Matrix4x4.h"
|
||||
|
||||
|
||||
#define MAX_SHADOW_BOXES 20 // max shadows
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
SHADOWBOX *ShadowBoxesList[MAX_SHADOW_BOXES];
|
||||
unsigned int gNumShadowBoxesList = 0;
|
||||
|
||||
unsigned int gGetTextureListPosition();
|
||||
extern unsigned int CurLoaderFlags;
|
||||
#if 0
|
||||
#pragma pack(1)
|
||||
struct COLORVERTEX { // vertex structures
|
||||
D3DVECTOR p;
|
||||
D3DCOLOR c;
|
||||
};
|
||||
|
||||
struct TRANSCOLORVERTEX { // transformed vertex
|
||||
D3DVECTOR p;
|
||||
D3DVALUE rhw;
|
||||
D3DCOLOR c;
|
||||
};
|
||||
#pragma pack()
|
||||
#endif
|
||||
#define MAX_SHADOW_BOXES 20 // max shadows
|
||||
|
||||
bool g_bUseOneBitStencil = FALSE; // if Stencil buffer if 1 bit deep only
|
||||
DWORD g_max_StencilVal = 255; // maximum value the stencil buffer will hold
|
||||
#if 0
|
||||
D3DSTENCILOP g_StencDecOp, g_StencIncOp; // increment e decrement functions
|
||||
|
||||
LPDIRECTDRAWSURFACE7 g_pddsShadowBuffer = NULL;
|
||||
LPDIRECTDRAWSURFACE7 g_pddsShadowZBuffer = NULL;
|
||||
#endif
|
||||
//************************************************************************************************
|
||||
inline void SetIdentityMatrix(Matrix4x4 &m) { // set D3D matrix to identity
|
||||
m.setIdentity();
|
||||
}
|
||||
|
||||
#if 0
|
||||
//************************************************************************************************
|
||||
int ccw(COLORVERTEX *P[], int i, int j, int k) { // for convex-hull
|
||||
double a = P[i]->p.x - P[j]->p.x,
|
||||
b = P[i]->p.y - P[j]->p.y,
|
||||
c = P[k]->p.x - P[j]->p.x,
|
||||
d = P[k]->p.y - P[j]->p.y;
|
||||
return a * d - b * c <= 0; // true if points i, j, k counterclockwise
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int cmpl(const void *a, const void *b) { // for convex-hull
|
||||
float v;
|
||||
COLORVERTEX **av, **bv;
|
||||
|
||||
av = (COLORVERTEX **)a;
|
||||
bv = (COLORVERTEX **)b;
|
||||
|
||||
v = (*av)->p.x - (*bv)->p.x;
|
||||
|
||||
if (v > 0) return 1;
|
||||
if (v < 0) return -1;
|
||||
|
||||
v = (*bv)->p.y - (*av)->p.y;
|
||||
|
||||
if (v > 0) return 1;
|
||||
if (v < 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int cmph(const void *a, const void *b) {
|
||||
return cmpl(b, a); // for convex-hull
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int make_chain(COLORVERTEX *V[], int n, int (*cmp)(const void *, const void *)) { // for convex-hull
|
||||
int i, j, s = 1;
|
||||
COLORVERTEX *t;
|
||||
|
||||
qsort(V, n, sizeof(COLORVERTEX *), cmp);
|
||||
for (i = 2; i < n; i++) {
|
||||
for (j = s; j >= 1 && ccw(V, i, j, j - 1); j--)
|
||||
{}
|
||||
s = j + 1;
|
||||
t = V[s];
|
||||
V[s] = V[i];
|
||||
V[i] = t;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int ch2d(COLORVERTEX *P[], int n) { // for convex-hull
|
||||
int u = make_chain(P, n, cmpl); // make lower hull
|
||||
if (!n) return 0;
|
||||
P[n] = P[0];
|
||||
return u + make_chain(P + u, n - u + 1, cmph); // make upper hull
|
||||
}
|
||||
|
||||
//************************************************************************************************
|
||||
void Find2DConvexHull(DWORD nverts, COLORVERTEX *pntptr, DWORD *cNumOutIdxs, WORD **OutHullIdxs) { // find a convex hull
|
||||
COLORVERTEX **PntPtrs;
|
||||
DWORD i;
|
||||
|
||||
*cNumOutIdxs = 0; //max space needed is n+1 indices
|
||||
*OutHullIdxs = (WORD *)malloc((nverts + 1) * (sizeof(DWORD) + sizeof(COLORVERTEX *)));
|
||||
|
||||
PntPtrs = (COLORVERTEX **) & (*OutHullIdxs)[nverts + 1];
|
||||
|
||||
// alg requires array of ptrs to verts (for qsort) instead of array of verts, so do the conversion
|
||||
for (i = 0; i < nverts; i++) {
|
||||
PntPtrs[i] = &pntptr[i];
|
||||
}
|
||||
|
||||
*cNumOutIdxs = ch2d(PntPtrs, nverts);
|
||||
|
||||
// convert back to array of idxs
|
||||
for (i = 0; i < *cNumOutIdxs; i++) {
|
||||
(*OutHullIdxs)[i] = (WORD)(PntPtrs[i] - &pntptr[0]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* -----------------25/08/1999 16.41-----------------
|
||||
* find 2D convex hull for the object
|
||||
* --------------------------------------------------*/
|
||||
bool rMakeShadowVolume(SHADOWBOX *sb, gVertex *InVerts, DWORD nverts, float lightm[9]) {
|
||||
warning("Stubbed: rMakeShadowVolume");
|
||||
#if 0
|
||||
Matrix4x4 matWorld, matView, matProj, IDmat;
|
||||
DWORD i;
|
||||
HRESULT hr;
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
unsigned int AlphaVal = 98;
|
||||
SHADOW *shad = &sb->ShadowsList[sb->NumShadowsList++];
|
||||
|
||||
// Get a ptr to the ID3D object to create materials and/or lights. Note:
|
||||
// the Release() call just serves to decrease the ref count.
|
||||
LPDIRECT3D7 pD3D;
|
||||
pd3dDevice->GetDirect3D(&pD3D);
|
||||
pD3D->Release();
|
||||
|
||||
LPDIRECT3DVERTEXBUFFER7 VB_Proj;
|
||||
D3DVERTEXBUFFERDESC vbDesc;
|
||||
vbDesc.dwSize = sizeof(D3DVERTEXBUFFERDESC);
|
||||
vbDesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
|
||||
vbDesc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
|
||||
// xyz+color so we can render them in showshadvol mode
|
||||
|
||||
// Create vertex buffer to hold shadow volumes verts
|
||||
if (shad->VB == NULL) {
|
||||
// now form array of indices that will make the tris
|
||||
ZeroMemory(shad, sizeof(SHADOW));
|
||||
shad->num_objverts = nverts;
|
||||
vbDesc.dwNumVertices = nverts * 2; // *2 to hold top of shadvol for infin light source
|
||||
|
||||
if (FAILED(hr = pD3D->CreateVertexBuffer(&vbDesc, &shad->VB, 0)))
|
||||
return hr;
|
||||
|
||||
// alloc enough to hold largest-case shadvol (max # of verts in c-hull is nverts)
|
||||
// (nverts+1)*2 for tri mesh to hold shadvol sides + nverts to hold tri-fan
|
||||
shad->pwShadVolIndices = (WORD *)t3dCalloc(sizeof(WORD) * (nverts + 1) * 2);
|
||||
}
|
||||
|
||||
// create VB_Proj vertex buffer as a target for the vertex-projection operation used to compute
|
||||
// the silhouette
|
||||
vbDesc.dwNumVertices = nverts;
|
||||
vbDesc.dwFVF = D3DFVF_XYZRHW;
|
||||
// even though RHW not used, must specify it or ProcessVerts will not consider this as a valid
|
||||
// target to xform verts into
|
||||
|
||||
if (FAILED(hr = pD3D->CreateVertexBuffer(&vbDesc, &VB_Proj, NULL)))
|
||||
return hr;
|
||||
|
||||
// must lock VB, then copy verts into its space.
|
||||
COLORVERTEX *VBvertptr;
|
||||
|
||||
shad->VB->Lock(DDLOCK_NOSYSLOCK | DDLOCK_WRITEONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
|
||||
(VOID **) &VBvertptr, NULL);
|
||||
|
||||
// have to copy verts into VB memory. I reformat into COLORVERTEX to do this.
|
||||
// could prevent reformat and do a straight memcpy if Find2DConvexHull used D3DVERTEX tho.
|
||||
COLORVERTEX *cvptr = VBvertptr;
|
||||
gVertex *d3dvptr = InVerts;
|
||||
|
||||
// reformat D3DVERTEX array to COLORVERTEX array
|
||||
for (i = 0; i < nverts; i++) {
|
||||
cvptr->p.x = d3dvptr->x;
|
||||
cvptr->p.y = d3dvptr->y;
|
||||
cvptr->p.z = d3dvptr->z;
|
||||
cvptr->c = RGBA_MAKE(0xff, 0x0, 0x0, 0xff); // shadvol is semi-transparent black
|
||||
cvptr++;
|
||||
d3dvptr++;
|
||||
}
|
||||
|
||||
shad->VB->Unlock();
|
||||
|
||||
// save cur matrices so we can use xform pipeln to project verts supafast
|
||||
pd3dDevice->GetTransform(D3DTRANSFORMSTATE_WORLD, &matWorld);
|
||||
pd3dDevice->GetTransform(D3DTRANSFORMSTATE_VIEW, &matView);
|
||||
pd3dDevice->GetTransform(D3DTRANSFORMSTATE_PROJECTION, &matProj);
|
||||
|
||||
SetIdentityMatrix(IDmat);
|
||||
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &IDmat);
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &IDmat);
|
||||
|
||||
// for view matrix, all we want is anything that projects the verts onto a plane
|
||||
// perp to light direction. so any eyepoint is OK (try to make obj near origin though,
|
||||
// so look at one of the verts). dont care what direction is view up vector (y).
|
||||
rSetViewMatrix(lightm[0], lightm[1], lightm[2],
|
||||
lightm[3], lightm[4], lightm[5],
|
||||
lightm[6], lightm[7], lightm[8],
|
||||
0.0f, 0.0f, 0.0f);
|
||||
|
||||
// do the planar projection
|
||||
VB_Proj->ProcessVertices(D3DVOP_TRANSFORM,
|
||||
0, // write new verts at idx 0
|
||||
nverts,
|
||||
shad->VB,
|
||||
0, // read src verts from idx 0
|
||||
pd3dDevice,
|
||||
0x0); // no flags
|
||||
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matWorld);
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &matView);
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &matProj);
|
||||
|
||||
COLORVERTEX *pntptr;
|
||||
|
||||
VB_Proj->Lock(DDLOCK_NOSYSLOCK | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
|
||||
(void **) &pntptr, NULL);
|
||||
|
||||
WORD *OutHullIdxs;
|
||||
DWORD n_idxs;
|
||||
|
||||
Find2DConvexHull(nverts, pntptr, &n_idxs, &OutHullIdxs); // This is the function supplied with dx6
|
||||
|
||||
VB_Proj->Unlock();
|
||||
VB_Proj->Release(); // just needed the indices of hull
|
||||
|
||||
shad->VB->Lock(DDLOCK_NOSYSLOCK | DDLOCK_WRITEONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
|
||||
(void **) &VBvertptr, NULL);
|
||||
|
||||
// make shadow volume by taking hull verts and project them along light dir far enough
|
||||
// to be offscreen
|
||||
|
||||
// add verts to end of VB
|
||||
for (i = 0; i < n_idxs; i++) {
|
||||
VBvertptr[nverts + i].p.x = VBvertptr[OutHullIdxs[i]].p.x - (2000.0f * lightm[6]); // scale factor of 10 should be enough
|
||||
VBvertptr[nverts + i].p.y = VBvertptr[OutHullIdxs[i]].p.y - (2000.0f * lightm[7]); // scale factor of 10 should be enough
|
||||
VBvertptr[nverts + i].p.z = VBvertptr[OutHullIdxs[i]].p.z - (2000.0f * lightm[8]); // scale factor of 10 should be enough
|
||||
VBvertptr[nverts + i].c = RGBA_MAKE(0x0, 0xff, 0x0, 0xff);
|
||||
}
|
||||
|
||||
shad->totalverts = nverts + n_idxs;
|
||||
|
||||
// now form array of indices that will make the tris
|
||||
// shad vol will have n_idxs square sides
|
||||
|
||||
shad->num_side_indices = (n_idxs + 1) * 2;
|
||||
|
||||
// if shadvol is not capped, shadow may be drawn in place where a backfacing cap is missing even
|
||||
// though no geometry is there
|
||||
|
||||
//f shad->num_cap_indices=n_idxs;
|
||||
shad->num_cap_indices = 0;
|
||||
|
||||
WORD *idxptr;
|
||||
|
||||
idxptr = shad->pwShadVolSideIndices = shad->pwShadVolIndices;
|
||||
|
||||
// tris for all facets but final one
|
||||
for (i = 0; i < n_idxs; i++) {
|
||||
// outhullidx[i] is the index of the ith vertex of the n_idx convex hull verts
|
||||
// nverts+i is the index of the projected vert corresponding to the OutHullIdx[i] vertex
|
||||
*idxptr++ = OutHullIdxs[i];
|
||||
*idxptr++ = (WORD)(nverts + i);
|
||||
}
|
||||
// add tris for final facet (i==n_idxs)
|
||||
*idxptr++ = OutHullIdxs[0];
|
||||
*idxptr++ = (WORD)(nverts + 0);
|
||||
|
||||
//m shad->pwShadVolCapIndices=idxptr;
|
||||
|
||||
free(OutHullIdxs); // allocated by Find2DConvexHull
|
||||
shad->VB->Unlock();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 16.41-----------------
|
||||
* makes a shadow box to avoid stenciled shadows over the object
|
||||
* --------------------------------------------------*/
|
||||
bool rMakeShadowBox(SHADOWBOX *sb, float BoxX, float BoxY, float BoxZ, WORD intens) {
|
||||
warning("Stubbed: rMakeShadowBox");
|
||||
#if 0
|
||||
bool hr;
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
|
||||
// Get a ptr to the ID3D object to create materials and/or lights. Note:
|
||||
// the Release() call just serves to decrease the ref count.
|
||||
LPDIRECT3D7 pD3D;
|
||||
pd3dDevice->GetDirect3D(&pD3D);
|
||||
pD3D->Release();
|
||||
|
||||
D3DVERTEXBUFFERDESC vbDesc;
|
||||
vbDesc.dwSize = sizeof(D3DVERTEXBUFFERDESC);
|
||||
vbDesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
|
||||
vbDesc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
|
||||
// xyz+color so we can render them in showshadvol mode
|
||||
|
||||
// Create vertex buffer to hold shadow volumes verts
|
||||
if (sb->VB == NULL) {
|
||||
sb->NumVerts = 16;
|
||||
sb->NumIndices = 12 * 3;
|
||||
vbDesc.dwNumVertices = sb->NumVerts;
|
||||
if (FAILED(hr = pD3D->CreateVertexBuffer(&vbDesc, &sb->VB, 0)))
|
||||
return hr;
|
||||
|
||||
// alloc enough to hold largest-case shadvol (max # of verts in c-hull is nverts)
|
||||
// (nverts+1)*2 for tri mesh to hold shadvol sides + nverts to hold tri-fan
|
||||
sb->pwIndices = (WORD *)t3dCalloc(sizeof(WORD) * sb->NumIndices);
|
||||
|
||||
WORD *curind = sb->pwIndices;
|
||||
*curind++ = 0;
|
||||
*curind++ = 1;
|
||||
*curind++ = 2; // Base scura
|
||||
*curind++ = 2;
|
||||
*curind++ = 1;
|
||||
*curind++ = 3;
|
||||
*curind++ = 0;
|
||||
*curind++ = 4;
|
||||
*curind++ = 1; // Bordo sinistro scuro
|
||||
*curind++ = 1;
|
||||
*curind++ = 4;
|
||||
*curind++ = 5;
|
||||
*curind++ = 2;
|
||||
*curind++ = 6;
|
||||
*curind++ = 0; // Bordo destro scuro
|
||||
*curind++ = 0;
|
||||
*curind++ = 6;
|
||||
*curind++ = 4;
|
||||
*curind++ = 12;
|
||||
*curind++ = 13;
|
||||
*curind++ = 14; // Testa chiara
|
||||
*curind++ = 14;
|
||||
*curind++ = 13;
|
||||
*curind++ = 15;
|
||||
*curind++ = 11;
|
||||
*curind++ = 15;
|
||||
*curind++ = 9; // Bordo sinistro chiaro
|
||||
*curind++ = 9;
|
||||
*curind++ = 15;
|
||||
*curind++ = 13;
|
||||
*curind++ = 10;
|
||||
*curind++ = 14;
|
||||
*curind++ = 11; // Bordo destro chiaro
|
||||
*curind++ = 11;
|
||||
*curind++ = 14;
|
||||
*curind++ = 15;
|
||||
}
|
||||
sb->NumShadowsList = 0;
|
||||
sb->Intensity = intens;
|
||||
|
||||
// must lock VB, then copy verts into its space.
|
||||
COLORVERTEX *VBvertptr;
|
||||
sb->VB->Lock(DDLOCK_NOSYSLOCK | DDLOCK_WRITEONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
|
||||
(VOID **) &VBvertptr, NULL);
|
||||
|
||||
// have to copy verts into VB memory. I reformat into COLORVERTEX to do this.
|
||||
// could prevent reformat and do a straight memcpy if Find2DConvexHull used D3DVERTEX tho.
|
||||
COLORVERTEX *cvptr = VBvertptr;
|
||||
D3DCOLOR cshadow = RGBA_MAKE(0x0, 0x0, 0x0, intens);
|
||||
D3DCOLOR clight = RGBA_MAKE(0x0, 0x0, 0x0, 0);
|
||||
|
||||
// 0: Base Piu' distante scuro
|
||||
cvptr->p.x = BoxX;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = BoxZ;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 1: Base Sinistra scuro
|
||||
cvptr->p.x = -BoxZ;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = BoxX;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 2: Base Destra scuro
|
||||
cvptr->p.x = BoxZ;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = -BoxX;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 3: Base Piu' vicino scuro
|
||||
cvptr->p.x = -BoxX;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = -BoxZ;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 4: Testa Piu' distante scura
|
||||
cvptr->p.x = BoxX;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = BoxZ;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 5: Testa Sinistra scuro
|
||||
cvptr->p.x = -BoxZ;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = BoxX;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 6: Testa Destra scuro
|
||||
cvptr->p.x = BoxZ;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = -BoxX;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 7: Testa Piu' vicino scuro
|
||||
cvptr->p.x = -BoxX;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = -BoxZ;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 8: Base Piu' distante chiaro
|
||||
cvptr->p.x = BoxX;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = BoxZ;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 9: Base Sinistra chiaro
|
||||
cvptr->p.x = -BoxZ;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = BoxX;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 10: Base Destra chiaro
|
||||
cvptr->p.x = BoxZ;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = -BoxX;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 11: Base Piu' vicino chiaro
|
||||
cvptr->p.x = -BoxX;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = -BoxZ;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 12: Testa Piu' distante chiaro
|
||||
cvptr->p.x = BoxX;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = BoxZ;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 13: Testa Sinistra chiaro
|
||||
cvptr->p.x = -BoxZ;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = BoxX;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 14: Testa Destra chiaro
|
||||
cvptr->p.x = BoxZ;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = -BoxX;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 15: Testa Piu' vicino chiaro
|
||||
cvptr->p.x = -BoxX;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = -BoxZ;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
|
||||
sb->VB->Unlock();
|
||||
|
||||
ShadowBoxesList[gNumShadowBoxesList++] = sb;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 17.24-----------------
|
||||
* renders a stenciled convex hull
|
||||
* --------------------------------------------------*/
|
||||
bool RenderShadow(SHADOW *pShad,
|
||||
void *lpVBuf) {
|
||||
warning("TODO: Stubbed RenderShadow");
|
||||
#if 0
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
|
||||
pd3dDevice->SetTexture(0, NULL);
|
||||
|
||||
// Turn depth buffer off, and stencil buffer on
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, FALSE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT); // dont want to bother interpolating color
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW);
|
||||
|
||||
// Set up stencil compare fuction, reference value, and masks
|
||||
// Stencil test passes if ((ref & mask) cmpfn (stencil & mask)) is true
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILFUNC, D3DCMP_ALWAYS);
|
||||
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILZFAIL, D3DSTENCILOP_KEEP);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILFAIL, D3DSTENCILOP_KEEP);
|
||||
|
||||
if (g_bUseOneBitStencil) {
|
||||
// If ztest passes, write !(g_bInvertStencilBufferSense) into stencil buffer
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILREF, 0x1);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILMASK, 0x1);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILWRITEMASK, 0x1);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILPASS, D3DSTENCILOP_REPLACE);
|
||||
} else {
|
||||
// If ztest passes, inc/decrement stencil buffer value
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILREF, 0x1);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILMASK, 0xffffffff);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILWRITEMASK, 0xffffffff);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILPASS, g_StencIncOp);
|
||||
}
|
||||
|
||||
// Since destcolor=SRCBLEND * SRC_COLOR + DESTBLEND * DEST_COLOR,
|
||||
// this should result in the tri color being completely dropped
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ZERO);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
|
||||
|
||||
// draw front-side of shadow volume in stencil/z only
|
||||
pd3dDevice->DrawIndexedPrimitiveVB(D3DPT_TRIANGLESTRIP, lpVBuf, 0, pShad->totalverts,
|
||||
pShad->pwShadVolSideIndices,
|
||||
pShad->num_side_indices, 0x0);
|
||||
|
||||
// Now reverse cull order so back sides of shadow volume are written.
|
||||
if (g_bUseOneBitStencil) {
|
||||
// write 0's/1's into stencil buffer to erase pixels beyond back of shadow
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILREF, 0x0);
|
||||
} else {
|
||||
// increment stencil buffer value
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILPASS, g_StencDecOp);
|
||||
}
|
||||
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CCW);
|
||||
// Draw back-side of shadow volume in stencil/z only
|
||||
pd3dDevice->DrawIndexedPrimitiveVB(D3DPT_TRIANGLESTRIP, lpVBuf, 0, pShad->totalverts,
|
||||
pShad->pwShadVolSideIndices,
|
||||
pShad->num_side_indices, 0x0);
|
||||
|
||||
// Restore render states
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, FALSE);
|
||||
//f pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 17.25-----------------
|
||||
* renders an object stenciled shadows box
|
||||
* --------------------------------------------------*/
|
||||
bool RenderShadowBox(SHADOWBOX *pSB,
|
||||
int lpVBuf) {
|
||||
warning("TODO: RenderShadowBox");
|
||||
#if 0
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
|
||||
pd3dDevice->SetTexture(0, NULL);
|
||||
|
||||
// Turn depth buffer off, and stencil buffer on
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, FALSE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
|
||||
|
||||
// Set up stencil compare fuction, reference value, and masks
|
||||
// Stencil test passes if ((ref & mask) cmpfn (stencil & mask)) is true
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILREF, 0x1);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILFUNC, D3DCMP_LESSEQUAL);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILZFAIL, D3DSTENCILOP_ZERO);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILFAIL, D3DSTENCILOP_ZERO);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILPASS, D3DSTENCILOP_ZERO);
|
||||
|
||||
// Since destcolor=SRCBLEND * SRC_COLOR + DESTBLEND * DEST_COLOR,
|
||||
// this should result in the tri color being completely dropped
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
|
||||
pd3dDevice->DrawIndexedPrimitiveVB(D3DPT_TRIANGLELIST, lpVBuf, 0, pSB->NumVerts,
|
||||
pSB->pwIndices,
|
||||
pSB->NumIndices, 0x0);
|
||||
|
||||
// Restore render states
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, FALSE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 17.25-----------------
|
||||
* Name: DrawShadow()
|
||||
* Desc: Draws a big grey polygon over scene, and blend it with pixels with
|
||||
* stencil 1, which are in shadow. Could optimize this by keeping track
|
||||
* of rendered 2D extent rect of all shadow vols.
|
||||
* --------------------------------------------------*/
|
||||
bool DrawShadow(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, WORD intens) {
|
||||
warning("Stubbed: DrawShadow");
|
||||
#if 0
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, FALSE);
|
||||
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
|
||||
|
||||
// Since destcolor=SRCBLEND * SRC_COLOR + DESTBLEND * DEST_COLOR,
|
||||
// this results in destcolor= (AlphaSrc) * SRC_COLOR + (1-AlphaSrc)*DestColor
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
|
||||
// stencil cmp func is defined as (ref cmpfn stencbufval).
|
||||
|
||||
// Only write where stencil val >= 1. (count indicates # of shadows that overlap that pixel)
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILREF, 0x1);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILFUNC, D3DCMP_LESSEQUAL);
|
||||
|
||||
//f pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILPASS, D3DSTENCILOP_KEEP );
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILPASS, D3DSTENCILOP_ZERO);
|
||||
|
||||
// Set the world matrix to identity to draw the big grey square
|
||||
D3DMATRIX matWorld, matIdentity;
|
||||
pd3dDevice->GetTransform(D3DTRANSFORMSTATE_WORLD, &matWorld);
|
||||
SetIdentityMatrix(matIdentity);
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matIdentity);
|
||||
// pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &matIdentity );
|
||||
// pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matIdentity );
|
||||
|
||||
TRANSCOLORVERTEX sqverts[4];
|
||||
WORD sqindices[6];
|
||||
|
||||
sqverts[0].p.z = sqverts[1].p.z = sqverts[2].p.z = sqverts[3].p.z = 0.0f;
|
||||
sqverts[0].rhw = sqverts[1].rhw = sqverts[3].rhw = sqverts[3].rhw = 0.0f;
|
||||
sqverts[0].c = sqverts[1].c = sqverts[2].c = sqverts[3].c = RGBA_MAKE(0x0, 0x0, 0x0, intens);
|
||||
|
||||
sqindices[0] = 0;
|
||||
sqindices[1] = 2;
|
||||
sqindices[2] = 1;
|
||||
sqindices[3] = 0;
|
||||
sqindices[4] = 3;
|
||||
sqindices[5] = 2;
|
||||
|
||||
sqverts[0].p.x = (float)x1;
|
||||
sqverts[0].p.y = (float)y1;
|
||||
sqverts[1].p.x = (float)x2;
|
||||
sqverts[1].p.y = (float)y1;
|
||||
sqverts[2].p.x = (float)x2;
|
||||
sqverts[2].p.y = (float)y2;
|
||||
sqverts[3].p.x = (float)x1;
|
||||
sqverts[3].p.y = (float)y2;
|
||||
|
||||
pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, (D3DFVF_XYZRHW | D3DFVF_DIFFUSE),
|
||||
sqverts, 4, sqindices, 6, 0x0);
|
||||
|
||||
// Restore render states
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matWorld);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, FALSE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 17.28-----------------
|
||||
* prepare shadow for projection to a texture
|
||||
* --------------------------------------------------*/
|
||||
bool rMakeProjectiveShadow(SHADOWBOX *sb, void *InVerts, DWORD nverts) {
|
||||
warning("Stubbed. rMakeProjectiveShadow");
|
||||
#if 0
|
||||
SHADOW *shad = &sb->ShadowsList[0];
|
||||
D3DVERTEXBUFFERDESC vbDesc;
|
||||
LPDIRECT3D7 pD3D;
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
int pos;
|
||||
|
||||
if (shad->VB == NULL) {
|
||||
pd3dDevice->GetDirect3D(&pD3D);
|
||||
pD3D->Release();
|
||||
vbDesc.dwSize = sizeof(D3DVERTEXBUFFERDESC);
|
||||
vbDesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
|
||||
vbDesc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;
|
||||
|
||||
// now form array of indices that will make the tris
|
||||
shad->num_objverts = nverts;
|
||||
vbDesc.dwNumVertices = nverts; // *2 to hold top of shadvol for infin light source
|
||||
|
||||
if (FAILED(pD3D->CreateVertexBuffer(&vbDesc, &shad->VB, 0))) {
|
||||
DebugLogFile("Unable to create VertexBuffer");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//Alloc indices for triangles
|
||||
shad->pwShadVolSideIndices = (WORD *)t3dCalloc(sizeof(WORD) * (nverts + 1) * 3);
|
||||
}
|
||||
|
||||
if (!g_pddsShadowBuffer) {
|
||||
HRESULT LastError;
|
||||
DDSURFACEDESC2 ddsd;
|
||||
|
||||
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
|
||||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||||
memcpy(&ddsd, &GraphicsModes[gCurrGraphicsMode].SurfDesc, sizeof(DDSURFACEDESC2));
|
||||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE;
|
||||
|
||||
ddsd.dwWidth = 256;
|
||||
ddsd.dwHeight = 256;
|
||||
|
||||
g_pddsShadowBuffer = gCreateSurface(&ddsd, g_pddsShadowBuffer);
|
||||
if (!g_pddsShadowBuffer) {
|
||||
DebugLogFile("Unable to create ShadowBuffer");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
|
||||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||||
g_pddsZBuffer->GetSurfaceDesc(&ddsd);
|
||||
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
|
||||
ddsd.dwWidth = 256;
|
||||
ddsd.dwHeight = 256;
|
||||
|
||||
g_pddsShadowZBuffer = gCreateSurface(&ddsd, g_pddsZBuffer);
|
||||
if (!g_pddsShadowZBuffer) {
|
||||
char str[200];
|
||||
LastError = 0;
|
||||
GetDDErrorString(LastError, str, 1);
|
||||
|
||||
DebugLogFile("CreateSurface for ShadowBuffer Z-buffer failed.\r\n%s", str);
|
||||
return FALSE;
|
||||
}
|
||||
LastError = g_pddsShadowBuffer->AddAttachedSurface(g_pddsShadowZBuffer);
|
||||
if (LastError != DD_OK) {
|
||||
char str[200];
|
||||
GetDDErrorString(LastError, str, 1);
|
||||
DebugLogFile("AddAttachedBuffer To ShadowBuffer failed for Z-Buffer.%s", str);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!shad->ProjectiveTexture.lpDDSurface) {
|
||||
DDSURFACEDESC2 DDSurfDesc;
|
||||
memset(&DDSurfDesc, 0, sizeof(DDSURFACEDESC2));
|
||||
memcpy(&DDSurfDesc.ddpfPixelFormat, &gCurrentFormat->SurfaceDesc, sizeof(DDPIXELFORMAT));
|
||||
memcpy(&DDSurfDesc, &GraphicsModes[gCurrGraphicsMode].SurfDesc, sizeof(DDSURFACEDESC2));
|
||||
DDSurfDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
|
||||
if (gRenderFlags & gAGPSUPPORTED) {
|
||||
//Alloc texture in AGP
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY |
|
||||
DDSCAPS_TEXTURE;
|
||||
} else {
|
||||
//No AGP support; alloc in sysmem
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
DDSurfDesc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
|
||||
}
|
||||
DDSurfDesc.dwWidth = 256;
|
||||
DDSurfDesc.dwHeight = 256;
|
||||
if (!(shad->ProjectiveTexture.lpDDSurface = gCreateSurface(&DDSurfDesc, shad->ProjectiveTexture.lpDDSurface))) {
|
||||
DebugLogFile("rMakeProjectiveShadow: gCreateSurface FAILED: Can't create surface");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pos = gGetTextureListPosition();
|
||||
if (pos == 0) {
|
||||
DebugLogFile("rMakeProjectiveShadow: Can't create more textures");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&gTextureList[pos], 0, sizeof(gTexture));
|
||||
strcpy(gTextureList[pos].Name, "Texture Buffer Shadow");
|
||||
gTextureList[pos].lpDDSurface = shad->ProjectiveTexture.lpDDSurface;
|
||||
gTextureList[pos].RealDimX = 256;
|
||||
gTextureList[pos].RealDimY = 256;
|
||||
gTextureList[pos].DimX = 256;
|
||||
gTextureList[pos].DimY = 256;
|
||||
gTextureList[pos].Flags = CurLoaderFlags;
|
||||
}
|
||||
|
||||
ShadowBoxesList[gNumShadowBoxesList++] = sb;
|
||||
sb->NumShadowsList = 1;
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 17.28-----------------
|
||||
* renders shadow to a specific texture
|
||||
* --------------------------------------------------*/
|
||||
bool RenderProjectiveShadow(SHADOW *pShad) {
|
||||
warning("Stubbed. RenderPojectiveShadow");
|
||||
#if 0
|
||||
HRESULT hres;
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
LPDIRECTDRAWSURFACE7 OldRenderTarget;
|
||||
D3DVIEWPORT7 NewViewport;
|
||||
|
||||
memset(&gOldViewport, 0, sizeof(D3DVIEWPORT7));
|
||||
if (hres = pd3dDevice->GetViewport(&gOldViewport) != D3D_OK) {
|
||||
DebugLogFile("Unable to get ViewPort2");
|
||||
return hres;
|
||||
}
|
||||
memcpy(&NewViewport, &gOldViewport, sizeof(D3DVIEWPORT7));
|
||||
|
||||
if (hres = pd3dDevice->GetRenderTarget(&OldRenderTarget) != D3D_OK) {
|
||||
DebugLogFile("Can't GetRenderTarget for shadow");
|
||||
return hres;
|
||||
}
|
||||
if (hres = pd3dDevice->SetRenderTarget(g_pddsShadowBuffer, 0) != D3D_OK) {
|
||||
DebugLogFile("Can't SetRenderTarget for shadow");
|
||||
return hres;
|
||||
}
|
||||
|
||||
NewViewport.dwHeight = NewViewport.dwWidth = 256;
|
||||
if (hres = pd3dDevice->SetViewport(&NewViewport) != D3D_OK) {
|
||||
DebugLogFile("Unable to set ShadowBuffer viewport");
|
||||
return hres;
|
||||
}
|
||||
|
||||
D3DRECT rect;
|
||||
rect.x1 = rect.y1 = 0;
|
||||
rect.x2 = 256;
|
||||
rect.y2 = 256;
|
||||
if (hres = pd3dDevice->Clear(1, &rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xFFFFFFFF, 1.0f, 0) != D3D_OK) {
|
||||
DebugLogFile("Unable to clear2 ShadowBuffer viewport");
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (hres = g_pd3dDevice->BeginScene() != D3D_OK) {
|
||||
DebugLogFile("Unable to begin Shadow scene");
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (hres = pd3dDevice->SetTexture(0, NULL)) return hres;
|
||||
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, FALSE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, D3DZB_FALSE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT)) return hres; // dont want to bother interpolating color
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, FALSE)) return hres;
|
||||
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO)) return hres;
|
||||
|
||||
if (hres = pd3dDevice->DrawIndexedPrimitiveVB(D3DPT_TRIANGLELIST, pShad->VB, 0, pShad->totalverts,
|
||||
pShad->pwShadVolSideIndices,
|
||||
pShad->num_side_indices, 0x0) != D3D_OK) {
|
||||
DebugLogFile("Unable to DrawIndexedPrimitive for projected shadow");
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (hres = g_pd3dDevice->EndScene() != D3D_OK) {
|
||||
DebugLogFile("Unable to end shadow scene");
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (hres = g_pd3dDevice->SetRenderTarget(OldRenderTarget, 0) != D3D_OK) {
|
||||
DebugLogFile("Can't SetRenderTarget for shadows");
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (hres = pd3dDevice->SetViewport(&gOldViewport) != D3D_OK) {
|
||||
DebugLogFile("Unable to restore viewport");
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, TRUE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, D3DZB_TRUE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, TRUE)) return hres;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 17.31-----------------
|
||||
* draw projected shadow texture to the room
|
||||
* --------------------------------------------------*/
|
||||
bool DrawProjectiveShadow(SHADOW *pShad) {
|
||||
warning("Stubbed: DrawProjectiveShadow");
|
||||
#if 0
|
||||
bool hres;
|
||||
|
||||
if (hres = g_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP) != DD_OK) return hres;
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, FALSE) != DD_OK) return hres;
|
||||
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ZERO) != DD_OK) return hres;
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_SRCCOLOR) != DD_OK) return hres;
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE) != DD_OK) return hres;
|
||||
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW) != DD_OK) return hres;
|
||||
if (hres = g_pd3dDevice->SetTexture(0, pShad->ProjectiveTexture.lpDDSurface) != DD_OK) return hres;
|
||||
|
||||
if (hres = g_pd3dDevice->DrawIndexedPrimitiveVB(D3DPT_TRIANGLELIST,
|
||||
pShad->ProjVertsVB, 0, pShad->totalverts,
|
||||
pShad->pwShadVolCapIndices,
|
||||
pShad->num_cap_indices, 0x0) != DD_OK) {
|
||||
char str[255];
|
||||
GetDDErrorString(hres, str, 1);
|
||||
DebugLogFile("DrawIndexedPrimitiveVB ERROR:\n\r%s", str);
|
||||
}
|
||||
pShad->num_cap_indices = 0;
|
||||
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, TRUE) != DD_OK) return hres;
|
||||
if (hres = g_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP) != DD_OK) return hres;
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE) != DD_OK) return hres;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
44
engines/watchmaker/3d/render/shadows.h
Normal file
44
engines/watchmaker/3d/render/shadows.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_SHADOWS_H
|
||||
#define WATCHMAKER_SHADOWS_H
|
||||
|
||||
#include "watchmaker/render.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
extern SHADOWBOX *ShadowBoxesList[];
|
||||
extern unsigned int gNumShadowBoxesList;
|
||||
extern void *g_pddsShadowBuffer;
|
||||
extern void *g_pddsShadowZBuffer;
|
||||
|
||||
//extern D3DSTENCILOP g_StencDecOp,g_StencIncOp;
|
||||
bool RenderShadow(SHADOW *pShad, void *lpVBuf);
|
||||
bool RenderShadowBox(SHADOWBOX *pSB, int VBO);
|
||||
bool DrawShadow(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, WORD intens);
|
||||
extern DWORD g_max_StencilVal; // maximum value the stencil buffer will hold
|
||||
extern bool RenderProjectiveShadow(SHADOW *pShad);
|
||||
bool DrawProjectiveShadow(SHADOW *pShad);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_SHADOWS_H
|
||||
613
engines/watchmaker/3d/t3d_body.cpp
Normal file
613
engines/watchmaker/3d/t3d_body.cpp
Normal file
@@ -0,0 +1,613 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_strcat
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_strcpy
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_sprintf
|
||||
|
||||
#include "watchmaker/3d/t3d_body.h"
|
||||
#include "common/stream.h"
|
||||
#include "watchmaker/3d/light.h"
|
||||
#include "watchmaker/3d/loader.h"
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/3d/t3d_face.h"
|
||||
#include "watchmaker/3d/t3d_mesh.h"
|
||||
#include "watchmaker/file_utils.h"
|
||||
#include "watchmaker/game.h"
|
||||
#include "watchmaker/ll/ll_system.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
#define CAMFILEVERSION 2
|
||||
#define BNDFILEVERSION 2
|
||||
|
||||
void t3dLoadMaterials(WGame &game, t3dBODY *b, Common::SeekableReadStream &stream, int numMaterials) {
|
||||
int16 loader_numtextures = 0;
|
||||
WorkDirs &workdirs = game.workDirs;
|
||||
for (uint16 material = 0; material < numMaterials; material++) { // Legge Materiali
|
||||
char Name[100] = {}, Appo[100] = {};
|
||||
unsigned int Flags = 0, flag = 0;
|
||||
#ifndef WMGEN
|
||||
int len;
|
||||
#endif
|
||||
|
||||
unsigned char AmbientR = (uint8)(stream.readFloatLE()); // legge Ambient
|
||||
unsigned char AmbientG = (uint8)(stream.readFloatLE());
|
||||
unsigned char AmbientB = (uint8)(stream.readFloatLE());
|
||||
|
||||
for (uint16 kk = 0; kk < T3D_NAMELEN; kk++) // Legge noem della texture
|
||||
Name[kk] = (uint8)stream.readByte();
|
||||
|
||||
Flags = stream.readSint32LE(); // Legge Flags
|
||||
|
||||
#ifndef WMGEN
|
||||
len = strlen(Name);
|
||||
if (((Name[len - 1] == 'i') || (Name[len - 1] == 'I')) &&
|
||||
((Name[len - 2] == 'v') || (Name[len - 2] == 'V')) &&
|
||||
((Name[len - 3] == 'a') || (Name[len - 3] == 'A'))) {
|
||||
strcpy(Appo, workdirs._moviesDir.c_str()); // altrimenti prende quello di default
|
||||
} else {
|
||||
strcpy(Appo, workdirs._mapsDir.c_str()); // altrimenti prende quello di default
|
||||
}
|
||||
strcat(Appo, Name); // Attacca nome Immagine
|
||||
#else
|
||||
strcpy(Appo, WmMapsDir); // altrimenti prende quello di default
|
||||
strcat(Appo, Name); // Attacca nome TGA
|
||||
#endif
|
||||
|
||||
|
||||
// if( LoaderFlags&T3D_HALFTEXTURESIZE ) // Se ho settato texture dimezzate
|
||||
// strcpy(Appo,WmHalfMapsDir); // cambio path
|
||||
// else
|
||||
//f strcat(Appo,"grid.tga");
|
||||
|
||||
if (LoaderFlags & T3D_HALFTEXTURESIZE) flag = rSURFACEHALF; // Se deve scalare le textures
|
||||
else flag = 0;
|
||||
MaterialPtr mat(new gMaterial());
|
||||
assert(b->MatTable.size() == material);
|
||||
b->MatTable.push_back(mat);
|
||||
//warning("Loading material %d", material);
|
||||
#ifndef WMGEN
|
||||
if (!(game._renderer->addMaterial(*mat, Appo,/*f1*/0, flag))) { // Carica e scala texture
|
||||
warning("Material file %s not found, ", Appo); // Se non trova la texture
|
||||
mat->Texture = nullptr;
|
||||
assert(0);
|
||||
//return nullptr;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
mat->addProperty(Flags); // Aggiunge i Flags al materiale
|
||||
// if(LoaderFlags&T3D_NOLIGHTMAPS)
|
||||
mat->addColor(AmbientR, AmbientG, AmbientB); // Sovrascrive Ambient con quello gloable
|
||||
mat->addColor((uint8)b->AmbientLight.x, (uint8)b->AmbientLight.y, (uint8)b->AmbientLight.z);
|
||||
loader_numtextures++;
|
||||
}
|
||||
assert(mat->Texture);
|
||||
}//__for_material
|
||||
(void)loader_numtextures;
|
||||
}
|
||||
|
||||
void t3dLoadMeshes(t3dBODY *b, uint32 numMeshes, t3dMESH *&ReceiveRipples, uint8 &Mirror, Common::SeekableReadStream &stream) {
|
||||
b->MeshTable.clear();
|
||||
b->MeshTable.reserve(numMeshes);
|
||||
for (uint32 mesh = 0; mesh < numMeshes; mesh++) {
|
||||
b->MeshTable.push_back(Common::move(t3dMESH(b, stream, ReceiveRipples, Mirror)));
|
||||
}
|
||||
}
|
||||
|
||||
void t3dBODY::allocateNormals() {
|
||||
int nListSize = this->NumNormals + this->NumVerticesNormals;
|
||||
this->NList.clear();
|
||||
this->NList.reserve(nListSize);
|
||||
for (int i = 0; i < nListSize; i++) { // Alloca Normali globali
|
||||
this->NList.push_back(Common::SharedPtr<t3dNORMAL>(new t3dNORMAL()));
|
||||
}
|
||||
}
|
||||
|
||||
void t3dBODY::initNormals(Common::SeekableReadStream &stream) {
|
||||
uint nListSize = this->NumNormals + this->NumVerticesNormals;
|
||||
assert(this->NList.size() == nListSize);
|
||||
for (uint16 normal = 0; normal < this->NList.size(); normal++) { // Legge normali globali
|
||||
*this->NList[normal] = t3dNORMAL(stream);
|
||||
}
|
||||
|
||||
for (uint16 i = 0; i < this->NumMeshes(); i++) { // Aggiorna normali mesh con normali globali
|
||||
t3dMESH &Mesh = this->MeshTable[i];
|
||||
#ifndef WMGEN
|
||||
Mesh.VBptr = Mesh.VertexBuffer;
|
||||
#endif
|
||||
Mesh.NList.reserve(Mesh.NumVerts); // Alloca normali mesh
|
||||
for (int k = 0; k < Mesh.NumVerts; k++) {
|
||||
Mesh.NList.push_back(Common::SharedPtr<t3dNORMAL>(new t3dNORMAL()));
|
||||
}
|
||||
|
||||
Mesh.NumNormals = 0;
|
||||
Mesh.NumVerticesNormals = Mesh.NumVerts; // Sono tutte normali ai vertici
|
||||
for (uint16 j = 0; j < Mesh.NumVerts; j++) {
|
||||
uint16 n = (uint16)Mesh.VBptr[j].diffuse;
|
||||
*Mesh.NList[j] = *this->NList[n]; // Copia normale globale in normale mesh
|
||||
Mesh.VBptr[j].diffuse = 0;
|
||||
}
|
||||
#ifndef WMGEN
|
||||
Mesh.VBptr = nullptr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void t3dBODY::populatePortalLists() {
|
||||
t3dMESH *Mesh = &this->MeshTable[0];
|
||||
for (uint16 mesh = 0; mesh < this->NumMeshes(); mesh++) { // Cerca portali in tutte le mesh
|
||||
Mesh[mesh].PortalList = nullptr; // Azzera portale
|
||||
if (Mesh[mesh].portalName.empty()) // Se non ha portale
|
||||
continue; // continua
|
||||
if (Mesh[mesh].portalName == "castle") { // Aggiunge mesh che bloccano la vista
|
||||
// DebugFile("%s: %d %d",Mesh[mesh].Name,Mesh[mesh].NumVerts,Mesh[mesh].NumFaces);
|
||||
for (uint16 i = 0; i < T3D_MAX_BLOCK_MESHES; i++) {
|
||||
if (!this->BlockMeshes[i]) {
|
||||
this->BlockMeshes[i] = &Mesh[mesh];
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Common::String Name = Mesh[mesh].portalName + ".t3d"; // Crea nome del nuovo portale
|
||||
|
||||
Mesh[mesh].Flags |= T3D_MESH_PORTAL; // Mesh e' un portale
|
||||
Mesh[mesh].Flags |= T3D_MESH_NOBOUNDBOX; // Mesh non viene vista dal mouse
|
||||
//#ifndef VIEWER
|
||||
// Mesh[mesh].Flags|=T3D_MESH_NOPORTALCHECK; // Spegne portale
|
||||
//#endif
|
||||
// TODO: This should probably be upfactored.
|
||||
t3dBODY *rez = nullptr;
|
||||
if (((rez = _vm->_roomManager->checkIfAlreadyLoaded(Name)) == nullptr) && (!(LoaderFlags & T3D_NORECURSION))) { // Controlla se lo ha gia' caricato
|
||||
if (Name.equalsIgnoreCase("rxt.t3d"))
|
||||
_vm->_roomManager->addToLoadList(&Mesh[mesh], Name, (uint16)((LoaderFlags | T3D_NORECURSION) & ~T3D_RECURSIONLEVEL1)); // aggiunge e leva la ricorsione
|
||||
// Mesh[mesh].Flags|=T3D_MESH_NOPORTALCHECK;
|
||||
else {
|
||||
if (LoaderFlags & T3D_RECURSIONLEVEL1)
|
||||
_vm->_roomManager->addToLoadList(&Mesh[mesh], Name, (uint16)((LoaderFlags | T3D_NORECURSION) & ~T3D_RECURSIONLEVEL1)); // aggiunge e leva la ricorsione
|
||||
else
|
||||
_vm->_roomManager->addToLoadList(&Mesh[mesh], Name, (uint16)(LoaderFlags)); // altrimenti lo agggiunge alla lista
|
||||
}
|
||||
} else
|
||||
Mesh[mesh].PortalList = rez;
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------10/06/99 16.03-------------------
|
||||
* SetupWaterRipples
|
||||
* --------------------------------------------------*/
|
||||
void SetupWaterRipples(t3dMESH *m) {
|
||||
warning("TODO: Stubbed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* -----------------10/06/99 16.02-------------------
|
||||
* LoadCameras
|
||||
* --------------------------------------------------*/
|
||||
void LoadCameras(WorkDirs &workDirs, const char *pname, t3dBODY *b) {
|
||||
uint8 ver;
|
||||
uint16 camera;
|
||||
|
||||
auto stream = workDirs.resolveFile(pname);
|
||||
if (!stream) {
|
||||
warning("File %s not found", pname);
|
||||
return ;
|
||||
}
|
||||
if ((ver = stream->readByte()) != CAMFILEVERSION) {
|
||||
warning("CAM File Version Error: loaded %d.\tRequired %d", ver, CAMFILEVERSION);
|
||||
return ;
|
||||
}
|
||||
|
||||
int numCameras = stream->readSint16LE();
|
||||
int numPaths = stream->readSint16LE();
|
||||
|
||||
b->CameraTable.clear();
|
||||
b->CameraTable.reserve(numCameras);
|
||||
for (camera = 0; camera < numCameras; camera++) {
|
||||
b->CameraTable.push_back(t3dCAMERA(*stream));
|
||||
}//__for_camera
|
||||
|
||||
b->CameraGrid.TopLeft.x = stream->readFloatLE() * SCALEFACTOR;
|
||||
b->CameraGrid.TopLeft.z = stream->readFloatLE() * SCALEFACTOR;
|
||||
b->CameraGrid.BottomRight.x = stream->readFloatLE() * SCALEFACTOR;
|
||||
b->CameraGrid.BottomRight.z = stream->readFloatLE() * SCALEFACTOR;
|
||||
|
||||
b->CameraGrid.Row = stream->readSint16LE();
|
||||
b->CameraGrid.Col = stream->readSint16LE();
|
||||
|
||||
b->CameraGrid.Grid.clear();
|
||||
b->CameraGrid.Grid.reserve(b->CameraGrid.Row * b->CameraGrid.Col);
|
||||
|
||||
for (int i = 0; i < (b->CameraGrid.Row * b->CameraGrid.Col); i++) {
|
||||
b->CameraGrid.Grid.push_back(stream->readByte());
|
||||
}
|
||||
|
||||
b->CameraPath.clear();
|
||||
b->CameraPath.reserve(numPaths);
|
||||
for (int i = 0; i < numPaths; i++) {
|
||||
b->CameraPath.push_back(t3dCAMERAPATH(*stream));
|
||||
}
|
||||
|
||||
b->CameraGrid.CellDim.x = (b->CameraGrid.BottomRight.x - b->CameraGrid.TopLeft.x) / b->CameraGrid.Col;
|
||||
b->CameraGrid.CellDim.z = (b->CameraGrid.BottomRight.z - b->CameraGrid.TopLeft.z) / b->CameraGrid.Row;
|
||||
}
|
||||
|
||||
/* -----------------10/06/99 16.03-------------------
|
||||
* loadBounds
|
||||
* --------------------------------------------------*/
|
||||
void loadBounds(WorkDirs &workDirs, const char *pname, t3dBODY *b) {
|
||||
for (int i = 0; i < T3D_MAX_LEVELS; i++)
|
||||
b->Panel[i] = nullptr;
|
||||
b->CurLevel = 0;
|
||||
|
||||
auto stream = workDirs.resolveFile(pname);
|
||||
if (!stream) {
|
||||
warning("File %s not found", pname);
|
||||
return ;
|
||||
}
|
||||
uint8 ver = stream->readByte();
|
||||
if (ver != BNDFILEVERSION) {
|
||||
warning("BND File Version Error: loaded %d.\tRequired %d", ver, BNDFILEVERSION);
|
||||
return;
|
||||
}
|
||||
uint16 nlev = stream->readSint16LE();
|
||||
b->NumLevels = nlev;
|
||||
if (nlev > T3D_MAX_LEVELS) {
|
||||
warning("Too much Floor Levels in %s: %d instead of %d", pname, b->NumLevels, T3D_MAX_LEVELS);
|
||||
b->NumLevels = nlev = T3D_MAX_LEVELS;
|
||||
}
|
||||
|
||||
for (int j = 0; j < nlev; j++) {
|
||||
uint16 npan = stream->readSint16LE();
|
||||
b->NumPanels[j] = npan;
|
||||
b->PanelHeight[j] = stream->readFloatLE() * SCALEFACTOR;
|
||||
b->Panel[j] = new t3dPAN[npan + 4 * T3D_MAX_CHARACTERS]; // also leave some space for any additions
|
||||
|
||||
for (int i = 0; i < npan; i++) {
|
||||
b->Panel[j][i].a.x = stream->readFloatLE() * SCALEFACTOR;
|
||||
b->Panel[j][i].a.z = stream->readFloatLE() * SCALEFACTOR;
|
||||
b->Panel[j][i].b.x = stream->readFloatLE() * SCALEFACTOR;
|
||||
b->Panel[j][i].b.z = stream->readFloatLE() * SCALEFACTOR;
|
||||
b->Panel[j][i].backA.x = stream->readFloatLE() * SCALEFACTOR;
|
||||
b->Panel[j][i].backA.z = stream->readFloatLE() * SCALEFACTOR;
|
||||
b->Panel[j][i].backB.x = stream->readFloatLE() * SCALEFACTOR;
|
||||
b->Panel[j][i].backB.z = stream->readFloatLE() * SCALEFACTOR;
|
||||
b->Panel[j][i].near1 = stream->readSint16LE();
|
||||
b->Panel[j][i].near2 = stream->readSint16LE();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------10/06/99 16.03-------------------
|
||||
* LoadLightmaps
|
||||
* --------------------------------------------------*/
|
||||
void LoadLightmaps(WGame &game, t3dBODY *b) {
|
||||
uint32 NumLightmaps;//, num;
|
||||
gVertex *gv;
|
||||
uint8 rr, gg, bb;
|
||||
int32 Map, alphaval1, alphaval2, alphaval3;
|
||||
WorkDirs &workDirs = game.workDirs;
|
||||
|
||||
Common::String Appo = setDirectoryAndName(workDirs._lightmapsDir, b->name);
|
||||
Appo = replaceExtension(Appo.c_str(), "map");
|
||||
|
||||
auto stream = workDirs.resolveFile(Appo);
|
||||
if (!stream) {
|
||||
warning("LoadLightmaps warning: File %s not found", Appo.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 lightMapVersion = stream->readSint32LE();
|
||||
if (lightMapVersion != LIGHT_MAPVERSION) {
|
||||
warning("LoadLightmaps error: File version error: found %d, required %d", lightMapVersion, LIGHT_MAPVERSION);
|
||||
return;
|
||||
}
|
||||
|
||||
b->NumLightmaps = NumLightmaps = stream->readSint32LE();
|
||||
b->LightmapTable = rCreateMaterialList(NumLightmaps);
|
||||
for (uint32 i = 0; i < NumLightmaps; i++) {
|
||||
Common::String root = setDirectoryAndName(workDirs._lightmapsDir, b->name);
|
||||
root = root.substr(0, root.size() - 4);
|
||||
Appo = Common::String::format("%s_%d.tga", root.c_str(), i);
|
||||
|
||||
/*num = */stream->readSint32LE();
|
||||
MaterialPtr mat(new gMaterial());
|
||||
assert(b->LightmapTable.size() == i);
|
||||
b->LightmapTable.push_back(mat);
|
||||
if (!game._renderer->addMaterial(*b->LightmapTable[i], Appo, 0, 0))
|
||||
return;
|
||||
|
||||
b->LightmapTable[i]->clear();
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < b->NumNormals; i++) {
|
||||
rr = (uint8)stream->readByte();
|
||||
gg = (uint8)stream->readByte();
|
||||
bb = (uint8)stream->readByte();
|
||||
Map = (int32)stream->readSint32LE();
|
||||
|
||||
Appo = setDirectoryAndName(workDirs._lightmapsDir.c_str(), b->name);
|
||||
Appo = Common::String::format("%s_%d.tga", Appo.c_str(), Map);
|
||||
|
||||
if (Map >= 0) {
|
||||
for (uint32 k = 0; k < b->NumMeshes(); k++) {
|
||||
t3dMESH &m = b->MeshTable[k];
|
||||
//f if (m->Flags&T3D_MESH_HIDDEN)
|
||||
//f continue;
|
||||
m.VBptr = m.VertexBuffer;
|
||||
gv = m.VBptr;
|
||||
|
||||
if (m.Flags & T3D_MESH_NOLIGHTMAP) {
|
||||
t3dFACE &f = m.FList[0];
|
||||
for (uint32 j = 0; j < m.NumFaces(); j++) {
|
||||
if (f.n == b->NList[i]) {
|
||||
f.lightmap = nullptr;
|
||||
}
|
||||
}
|
||||
m.VBptr = nullptr;
|
||||
continue;
|
||||
}
|
||||
t3dFACE &f = m.FList[0];
|
||||
for (uint32 j = 0; j < m.NumFaces(); j++) {
|
||||
// gMaterial *newmat;
|
||||
if (f.n == b->NList[i]) {
|
||||
// f->mat->Texture=f->mat->Lightmap;
|
||||
if ((!(f.hasMaterialFlag(T3D_MATERIAL_OPACITY))) &&
|
||||
(!(f.hasMaterialFlag(T3D_MATERIAL_CLIPMAP))) &&
|
||||
(!(f.hasMaterialFlag(T3D_MATERIAL_BOTTLE))) &&
|
||||
(!(f.hasMaterialFlag(T3D_MATERIAL_ADDITIVE))) &&
|
||||
(!(f.hasMaterialFlag(T3D_MATERIAL_GLASS)))) {
|
||||
alphaval1 = RGBA_GETALPHA(gv[f.VertexIndex[0]].diffuse);
|
||||
alphaval2 = RGBA_GETALPHA(gv[f.VertexIndex[1]].diffuse);
|
||||
alphaval3 = RGBA_GETALPHA(gv[f.VertexIndex[2]].diffuse);
|
||||
gv[f.VertexIndex[0]].diffuse = RGBA_MAKE(254, 254, 254, alphaval1);
|
||||
gv[f.VertexIndex[1]].diffuse = RGBA_MAKE(254, 254, 254, alphaval2);
|
||||
gv[f.VertexIndex[2]].diffuse = RGBA_MAKE(254, 254, 254, alphaval3);
|
||||
f.lightmap = b->LightmapTable[Map];
|
||||
f.getMaterial()->addNumFacesAdditionalMaterial(f.lightmap, 1);
|
||||
} else if (((f.hasMaterialFlag(T3D_MATERIAL_OPACITY))) ||
|
||||
((f.hasMaterialFlag(T3D_MATERIAL_CLIPMAP))) ||
|
||||
((f.hasMaterialFlag(T3D_MATERIAL_BOTTLE))) ||
|
||||
((f.hasMaterialFlag(T3D_MATERIAL_ADDITIVE))) ||
|
||||
((f.hasMaterialFlag(T3D_MATERIAL_GLASS)))) {
|
||||
f.lightmap = nullptr;
|
||||
}
|
||||
|
||||
// if (!f->mat->Lightmap)
|
||||
{
|
||||
//DebugLogWindow("Mesh %s: Face %d has not lightmap",m->Name,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
m.VBptr = nullptr;
|
||||
}
|
||||
} else {
|
||||
for (uint32 k = 0; k < b->NumMeshes(); k++) {
|
||||
t3dMESH &m = b->MeshTable[k];
|
||||
// gMaterial *newmat;
|
||||
m.VBptr = m.VertexBuffer;
|
||||
gv = m.VBptr;
|
||||
|
||||
//f if (m->Flags&T3D_MESH_HIDDEN)
|
||||
//f continue;
|
||||
|
||||
if (m.Flags & T3D_MESH_NOLIGHTMAP) {
|
||||
t3dFACE &f = m.FList[0];
|
||||
for (uint32 j = 0; j < m.NumFaces(); j++) {
|
||||
if (f.n == b->NList[i]) {
|
||||
f.lightmap = nullptr;
|
||||
}
|
||||
}
|
||||
m.VBptr = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
t3dFACE &f = m.FList[0];
|
||||
for (uint32 j = 0; j < m.NumFaces(); j++) {
|
||||
// t3dU32 nr,ng,nb;
|
||||
if (f.n == b->NList[i]) {
|
||||
f.lightmap = nullptr;
|
||||
// if (Map==-1)
|
||||
if ((!(f.hasMaterialFlag(T3D_MATERIAL_OPACITY))) &&
|
||||
(!(f.hasMaterialFlag(T3D_MATERIAL_CLIPMAP))) &&
|
||||
(!(f.hasMaterialFlag(T3D_MATERIAL_BOTTLE))) &&
|
||||
(!(f.hasMaterialFlag(T3D_MATERIAL_ADDITIVE))) &&
|
||||
(!(f.hasMaterialFlag(T3D_MATERIAL_GLASS)))) {
|
||||
alphaval1 = RGBA_GETALPHA(gv[f.VertexIndex[0]].diffuse);
|
||||
alphaval2 = RGBA_GETALPHA(gv[f.VertexIndex[1]].diffuse);
|
||||
alphaval3 = RGBA_GETALPHA(gv[f.VertexIndex[2]].diffuse);
|
||||
gv[f.VertexIndex[0]].diffuse = RGBA_MAKE(rr, gg, bb, alphaval1);
|
||||
gv[f.VertexIndex[1]].diffuse = RGBA_MAKE(rr, gg, bb, alphaval2);
|
||||
gv[f.VertexIndex[2]].diffuse = RGBA_MAKE(rr, gg, bb, alphaval3);
|
||||
}
|
||||
}
|
||||
}
|
||||
// f->mat->Texture= nullptr;
|
||||
|
||||
m.VBptr = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < b->NumMeshes(); i++) {
|
||||
t3dMESH &m = b->MeshTable[i];
|
||||
m.VBptr = m.VertexBuffer;
|
||||
gv = m.VBptr;
|
||||
for (uint32 j = 0; j < m.NumVerts; j++) {
|
||||
t3dF32 u = stream->readFloatLE();
|
||||
t3dF32 v = stream->readFloatLE();
|
||||
|
||||
if ((RGBA_GETRED(gv[j].diffuse) == 254) &&
|
||||
(RGBA_GETGREEN(gv[j].diffuse) == 254) &&
|
||||
(RGBA_GETBLUE(gv[j].diffuse) == 254)) {
|
||||
gv[j].u2 = u;
|
||||
gv[j].v2 = v;
|
||||
gv[j].diffuse = RGBA_MAKE(255, 255, 255, RGBA_GETALPHA(gv[j].diffuse));
|
||||
|
||||
// gv[j].u2=(rand())%2;
|
||||
// gv[j].v2=(rand())%2;
|
||||
} else {
|
||||
gv[j].u2 = gv[j].u1;
|
||||
gv[j].v2 = gv[j].v1;
|
||||
}
|
||||
|
||||
// gv[j].diffuse=0xFFFFFFFF;
|
||||
// DebugLogWindow("%f %f",gv[j].u1,gv[j].v1);
|
||||
}
|
||||
m.VBptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------10/06/99 16.04-------------------
|
||||
* t3dLoadSingleRoom
|
||||
* --------------------------------------------------*/
|
||||
t3dBODY *t3dBODY::loadFromStream(WGame &game, const Common::String &pname, Common::SeekableReadStream &stream, uint32 _LoaderFlags) {
|
||||
//decodeLoaderFlags(_LoaderFlags);
|
||||
//char /*t3dU8*/ Name[255];
|
||||
|
||||
uint16 light;
|
||||
t3dF32 minx, miny, minz, maxx, maxy, maxz;
|
||||
|
||||
WorkDirs &workdirs = game.workDirs;
|
||||
|
||||
this->name = pname;
|
||||
auto _name = constructPath(workdirs._t3dDir, pname);
|
||||
|
||||
this->NumTotVerts = 0;
|
||||
|
||||
this->AmbientLight = t3dV3F::fromStreamAsBytes(stream);
|
||||
int numMeshes = stream.readSint16LE(); // Legge globali del body
|
||||
int numMaterials = stream.readSint16LE();
|
||||
int numLights = stream.readSint16LE();
|
||||
int numPosLights = stream.readSint16LE();
|
||||
|
||||
this->NumNormals = stream.readSint32LE();
|
||||
this->NumVerticesNormals = stream.readSint32LE();
|
||||
this->allocateNormals();
|
||||
this->MatTable = rCreateMaterialList(numMaterials); // Crea Materiali Globali
|
||||
this->LightmapTable.clear();
|
||||
//-------------------LOADING MESHES--------------------------------------
|
||||
t3dMESH *ReceiveRipples = nullptr;
|
||||
uint8 Mirror = 0;
|
||||
t3dLoadMeshes(this, numMeshes, ReceiveRipples, Mirror, stream); // TODO: We probably don't need to pass ReceiveRipples, Mirror
|
||||
//-------------------END OF LOADING MESHES-------------------------------
|
||||
this->initNormals(stream);
|
||||
|
||||
//-------------------LOADING MATERIALS--------------------------------------
|
||||
t3dLoadMaterials(game, this, stream, numMaterials);
|
||||
//-------------------LOADING LIGHTS--------------------------------------
|
||||
this->LightTable.reserve(numLights); // Alloca spazio per le luci globali
|
||||
for (light = 0; light < numLights; light++) {
|
||||
this->LightTable.push_back(t3dLIGHT(game, this, workdirs, stream)); // Azzera luce
|
||||
}//__for_light
|
||||
//-------------------END OF LOADING LIGHTS-------------------------------
|
||||
|
||||
this->PosLightTable.clear();
|
||||
this->PosLightTable.reserve(numPosLights); // Alloca spazio per luci di posizione
|
||||
for (light = 0; light < numPosLights; light++) {
|
||||
this->PosLightTable.push_back(t3dPLIGHT(stream));
|
||||
}//__for_plight
|
||||
|
||||
//-------------------Extra optimization here-------------------------------
|
||||
#ifndef WMGEN
|
||||
if (ReceiveRipples) // Se c'era una mesh con i riples
|
||||
SetupWaterRipples(ReceiveRipples); // crea i buffers
|
||||
#endif
|
||||
|
||||
//-------------------Prelighting body-------------------------------
|
||||
for (uint16 i = 0; i < this->NumMeshes(); i++) { // Cerca in tutte le mesh
|
||||
this->MeshTable[i].preCalcLights(this->AmbientLight);
|
||||
}
|
||||
|
||||
#ifndef WMGEN
|
||||
t3dPrecalcLight(this, nullptr);
|
||||
#endif
|
||||
//----------------END OF VERTEX PRE-LIGHTING---------------------
|
||||
|
||||
populatePortalLists();
|
||||
|
||||
warning("LoaderFlags late = %08X", _LoaderFlags);
|
||||
//decodeLoaderFlags(_LoaderFlags);
|
||||
if (!(_LoaderFlags & T3D_NOBOUNDS)) { // Carica Bounds
|
||||
auto bndName = workdirs.join(workdirs._bndDir, pname, "bnd");
|
||||
loadBounds(game.workDirs, bndName.c_str(), this);
|
||||
}
|
||||
if (!(_LoaderFlags & T3D_NOCAMERAS)) { // Carica Camere
|
||||
auto cameraName = constructPath(workdirs._camDir, pname, "cam");
|
||||
LoadCameras(game.workDirs, cameraName.c_str(), this);
|
||||
}
|
||||
if (!(_LoaderFlags & T3D_NOLIGHTMAPS)) { // Carica le Lightmaps
|
||||
// TODO: This looks odd
|
||||
if (!pname.equalsIgnoreCase("rxt.t3d") || !pname.equalsIgnoreCase("rxt-b.t3d") || !pname.equalsIgnoreCase("rxt-c.t3d") ||
|
||||
!pname.equalsIgnoreCase("rxt-d.t3d") || !pname.equalsIgnoreCase("rxt-e.t3d") || !pname.equalsIgnoreCase("rxt.t3d-f"))
|
||||
LoadLightmaps(game, this);
|
||||
}
|
||||
if ((_LoaderFlags & T3D_OUTDOORLIGHTS)) { // Carica le luci per l'esterno
|
||||
if (pname.equalsIgnoreCase("rxt.t3d")) {
|
||||
auto outdoorLightsPath = constructPath(workdirs._lightmapsDir, pname);
|
||||
t3dLoadOutdoorLights(outdoorLightsPath.c_str(), this, t3dCurTime);
|
||||
}
|
||||
}
|
||||
if (!(_LoaderFlags & T3D_NOVOLUMETRICLIGHTS)) { // Carica le luci volumetriche
|
||||
auto volMapPath = constructPath(workdirs._lightmapsDir, pname, "vol");
|
||||
LoadVolumetricMap(workdirs, volMapPath.c_str(), this);
|
||||
}
|
||||
|
||||
GetBoundaries(this, &minx, &miny, &minz, &maxx, &maxy, &maxz); // Calcola occupazione stanza
|
||||
this->MinPos.x = minx; // Salva il minimo per le luci volumetriche
|
||||
this->MinPos.y = miny;
|
||||
this->MinPos.z = minz;
|
||||
|
||||
#ifndef WMGEN
|
||||
for (uint16 i = 0; i < this->NumMeshes(); i++) { // Scorre le mesh
|
||||
this->MeshTable[i].saveVertexBuffer();
|
||||
}
|
||||
#endif
|
||||
|
||||
t3dOptimizeMaterialList(this); // Ottimizza la lista dei metriali (evitando i doppi)
|
||||
#ifndef WMGEN
|
||||
t3dFinalizeMaterialList(this); // Crea VB e indici per materiali
|
||||
#endif
|
||||
|
||||
if (Mirror) { // Se c'era uno specchio
|
||||
this->MirrorMatTable = rCreateMaterialList(this->NumMaterials());
|
||||
rCopyMaterialList(this->MirrorMatTable, this->MatTable, this->NumMaterials());
|
||||
}
|
||||
|
||||
|
||||
//f
|
||||
#ifndef WMGEN
|
||||
for (uint16 i = 0; i < this->NumMeshes(); i++) { // Cancella le normali
|
||||
if (this->MeshTable[i].ModVertices.empty()) // dalle mesh con Smoothing groups
|
||||
continue;
|
||||
for (uint16 j = 0; j < this->MeshTable[i].NumFaces(); j++) {
|
||||
this->MeshTable[i].FList[j].n = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//f
|
||||
return this;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
108
engines/watchmaker/3d/t3d_body.h
Normal file
108
engines/watchmaker/3d/t3d_body.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef WATCHMAKER_T3D_BODY_H
|
||||
#define WATCHMAKER_T3D_BODY_H
|
||||
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/3d/t3d_mesh.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
struct t3dBODY {
|
||||
Common::String name; // room name
|
||||
uint32 NumMeshes() {
|
||||
return MeshTable.size();
|
||||
}; // num meshes
|
||||
uint32 NumCameras() const {
|
||||
return CameraTable.size(); // num cameras
|
||||
}
|
||||
uint16 NumPaths() const {
|
||||
return CameraPath.size(); // num camera paths
|
||||
}
|
||||
uint32 NumLights() const {
|
||||
return LightTable.size(); // num lights
|
||||
}
|
||||
uint16 NumPanels[T3D_MAX_LEVELS] = {}; // num panels per level
|
||||
uint16 NumNormals = 0; // num face normals
|
||||
uint16 NumVerticesNormals = 0; // num vertex normals
|
||||
uint16 NumPosLights() const {
|
||||
return PosLightTable.size();
|
||||
}; // num positional lights
|
||||
uint16 NumLevels = 0; // num panel levels
|
||||
uint16 CurLevel = 0; // current level
|
||||
uint32 NumTotVerts = 0; // total number of verts in room
|
||||
t3dV3F AmbientLight; // room ambient color
|
||||
Common::Array<t3dMESH> MeshTable; // meshes list
|
||||
MaterialTable MatTable; // materials list
|
||||
uint32 NumMaterials() const {
|
||||
return MatTable.size(); // num materials
|
||||
}
|
||||
MaterialTable LightmapTable; // lightmap material list
|
||||
uint32 NumLightmaps = 0; // num lightmap materials
|
||||
MaterialTable MirrorMatTable; // material list (for mirrors)
|
||||
uint32 NumMirrorMaterials() const {
|
||||
return MirrorMatTable.size();
|
||||
}; // num materials (for mirror)
|
||||
private:
|
||||
Common::Array<Common::SharedPtr<VertexBuffer>> VBTable; // metrial vertex buffers list
|
||||
public:
|
||||
Common::SharedPtr<VertexBuffer> addVertexBuffer() {
|
||||
VBTable.push_back(Common::SharedPtr<VertexBuffer>(new VertexBuffer()));
|
||||
return VBTable.back();
|
||||
}
|
||||
void clearVBTable() {
|
||||
for (uint i = 0; i < VBTable.size(); i++) {
|
||||
rDeleteVertexBuffer(*VBTable[i]);
|
||||
}
|
||||
VBTable.clear();
|
||||
}
|
||||
uint32 NumVB() {
|
||||
return VBTable.size();
|
||||
}; // num vertex buffer
|
||||
public:
|
||||
Common::Array<t3dCAMERA> CameraTable; // camera list
|
||||
Common::Array<t3dLIGHT> LightTable; // light list
|
||||
Common::Array<t3dPLIGHT> PosLightTable; // positional light list
|
||||
NormalList NList; // normal list
|
||||
t3dCAMERAGRID CameraGrid; // camera grid
|
||||
Common::Array<t3dCAMERAPATH> CameraPath; // camer paths list
|
||||
t3dPAN *Panel[T3D_MAX_LEVELS] = {}; // room panels for level
|
||||
t3dF32 PanelHeight[T3D_MAX_LEVELS] = {}; // panel height for levels
|
||||
Common::SharedPtr<t3dVolLights> VolumetricLights; // volumetric lights
|
||||
t3dMESH *BlockMeshes[T3D_MAX_BLOCK_MESHES] = {}; // block mesh (for external rooms)
|
||||
t3dV3F MinPos; // min room position
|
||||
private:
|
||||
void allocateNormals();
|
||||
void initNormals(Common::SeekableReadStream &stream);
|
||||
public:
|
||||
t3dCAMERA *PickCamera(uint8 in);
|
||||
Common::Array<t3dPLIGHT> getPositionalLight(uint8 pos);
|
||||
|
||||
t3dBODY *loadFromStream(WGame &game, const Common::String &pname, Common::SeekableReadStream &stream, uint32 LoaderFlags);
|
||||
void populatePortalLists();
|
||||
};
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_T3D_BODY_H
|
||||
66
engines/watchmaker/3d/t3d_face.cpp
Normal file
66
engines/watchmaker/3d/t3d_face.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "watchmaker/3d/t3d_face.h"
|
||||
#include "watchmaker/3d/t3d_body.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
t3dFACE::t3dFACE(t3dBODY *b, Common::SeekableReadStream &stream) {
|
||||
VertexIndex[0] = stream.readSint16LE(); // Legge VertexIndex0
|
||||
VertexIndex[1] = stream.readSint16LE(); // Legge VertexIndex1
|
||||
VertexIndex[2] = stream.readSint16LE(); // Legge VertexIndex2
|
||||
|
||||
this->n = b->NList[stream.readSint16LE()]; // Legge puntatore a normale
|
||||
|
||||
_materialIndex = stream.readSint16LE(); // Legge indice materiale
|
||||
_body = b;
|
||||
}
|
||||
|
||||
bool t3dFACE::isVisible() const {
|
||||
if (!n)
|
||||
return true;
|
||||
else if (n->flag != T3D_NORMAL_VISIBLE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MaterialPtr t3dFACE::getMaterial() {
|
||||
if (_mat) {
|
||||
return _mat;
|
||||
} else {
|
||||
_mat = _body->MatTable[_materialIndex];
|
||||
return _mat;
|
||||
}
|
||||
}
|
||||
|
||||
const gMaterial *t3dFACE::getMaterial() const {
|
||||
if (_mat) {
|
||||
return _mat.get();
|
||||
} else {
|
||||
error("t3dFACE::getMaterial(): No material loaded");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
78
engines/watchmaker/3d/t3d_face.h
Normal file
78
engines/watchmaker/3d/t3d_face.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_T3D_FACE_H
|
||||
#define WATCHMAKER_T3D_FACE_H
|
||||
|
||||
#include "watchmaker/3d/types3d.h"
|
||||
#include "watchmaker/3d/material.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
struct t3dBODY;
|
||||
struct t3dFACE {
|
||||
uint32 flags = 0; // face status 4
|
||||
NormalPtr n; // pointer to the face normal 4
|
||||
private:
|
||||
int16 MatVertexIndex[3] = {}; // Vertices indices in material 6
|
||||
uint16 _materialIndex = 0;
|
||||
MaterialPtr _mat = nullptr; // pointer to material 4
|
||||
t3dBODY *_body = nullptr;
|
||||
public:
|
||||
int16 VertexIndex[3] = {}; // Vertices indices in mesh 6
|
||||
|
||||
void setMatVertexIndex(int index, int16 value) {
|
||||
MatVertexIndex[index] = value;
|
||||
}
|
||||
uint16 getMatVertexIndex(int index) {
|
||||
return MatVertexIndex[index];
|
||||
}
|
||||
public:
|
||||
MaterialPtr lightmap; // pointer to lightmap (or 2nd material) 4
|
||||
|
||||
t3dFACE(t3dBODY *b, Common::SeekableReadStream &stream);
|
||||
|
||||
bool hasMaterialFlag(uint32 flag) {
|
||||
return getMaterial()->hasFlag(flag);
|
||||
}
|
||||
MaterialPtr getMaterial();
|
||||
const gMaterial *getMaterial() const;
|
||||
uint16 getMaterialIndex() const {
|
||||
return _materialIndex;
|
||||
}
|
||||
void setMaterialIndex(uint32 index) {
|
||||
_materialIndex = index;
|
||||
_mat = nullptr;
|
||||
getMaterial();
|
||||
}
|
||||
|
||||
void checkVertices() {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
assert((int)getMaterial()->VertsList.size() > MatVertexIndex[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool isVisible() const;
|
||||
};
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // SCUMMVM_T3D_FACE_H
|
||||
424
engines/watchmaker/3d/t3d_mesh.cpp
Normal file
424
engines/watchmaker/3d/t3d_mesh.cpp
Normal file
@@ -0,0 +1,424 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/t3d_mesh.h"
|
||||
#include "watchmaker/3d/t3d_body.h"
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/3d/loader.h"
|
||||
#include "watchmaker/ll/ll_system.h"
|
||||
#include "watchmaker/3d/geometry.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void t3dMESH::loadFaces(t3dBODY *b, Common::SeekableReadStream &stream, int numFaces) {
|
||||
//Mesh[mesh].FList = new t3dFACE[Mesh[mesh].NumFaces]{}; // Alloca facce
|
||||
|
||||
this->FList.reserve(numFaces); // Legge numero facce mesh
|
||||
for (uint16 face = 0; face < numFaces; face++) {
|
||||
FList.push_back(t3dFACE(b, stream));
|
||||
}//__for_face
|
||||
}
|
||||
|
||||
t3dMESH::t3dMESH(t3dBODY *b, Common::SeekableReadStream &stream, t3dMESH *&ReceiveRipples, uint8 &Mirror) {
|
||||
t3dMatIdentity(&Matrix); // Setta matrice identica
|
||||
|
||||
this->DefaultAnim.NumBones = this->DefaultAnim.NumFrames = 0;
|
||||
this->Anim.NumBones = this->Anim.NumFrames = 0;
|
||||
|
||||
char stringBuffer[T3D_NAMELEN + 1] = {};
|
||||
stream.read(stringBuffer, T3D_NAMELEN); // Legge nome mesh
|
||||
this->name = stringBuffer;
|
||||
stream.read(stringBuffer, T3D_NAMELEN); // Legge nome portale
|
||||
this->portalName = stringBuffer;
|
||||
|
||||
int numFaces = stream.readSint16LE(); // Legge numero facce mesh
|
||||
|
||||
t3dVectFill(&this->Trasl, 0.0f);
|
||||
this->Pos = t3dV3F(stream) * SCALEFACTOR;
|
||||
this->Radius = stream.readFloatLE() * SCALEFACTOR; // Legge raggio boundsphere
|
||||
|
||||
//this->LightmapDim=(t3dU16)t3dRead8();
|
||||
uint8 SaveMipStatus = stream.readByte(); // Legge dimensione lightmap
|
||||
this->LightmapDim = SaveMipStatus;
|
||||
if (this->LightmapDim == 255)
|
||||
this->LightmapDim = 256;
|
||||
if (this->LightmapDim == 0) { // Se non e' specificata
|
||||
if ((this->name[0] == 'o') || (this->name[0] == 'O')) // decide in base al nome
|
||||
this->LightmapDim = 8;
|
||||
else if ((this->name[0] == 'p') || (this->name[0] == 'P'))
|
||||
this->LightmapDim = 16;
|
||||
}
|
||||
if (this->LightmapDim > 256) { // Se > 256, errore
|
||||
this->LightmapDim = 256;
|
||||
warning("ATTENTION: Lightmap dim >256 on mesh %s!!!", this->name.c_str());
|
||||
warning("Check and verify .t3d");
|
||||
}
|
||||
|
||||
this->Flags = stream.readSint32LE(); // Legge flags
|
||||
// if ( !strcasecmp( "pxt-musoleoBUCO", this->Name ) );
|
||||
if (this->Flags & T3D_MESH_MIRROR) // Incrementa numero mirror
|
||||
Mirror++;
|
||||
// if( this->Flags&T3D_MESH_PORTAL)
|
||||
// this->Flags|=T3D_MESH_PORTAL;
|
||||
if ((this->Flags & T3D_MESH_RECEIVERIPPLES) || // Aggiunge buffer per le onde
|
||||
(this->Flags & T3D_MESH_POOLWATER))
|
||||
ReceiveRipples = this;
|
||||
if (this->Flags & T3D_MESH_WAVESTEXTURE) { // Legge informazioni sulle onde
|
||||
this->WavesSpeed = (t3dF32)stream.readSint32LE() / 10000.0f;
|
||||
this->YSpeed = (t3dF32)stream.readSint32LE() / 100.0f;
|
||||
}
|
||||
if (this->Flags & T3D_MESH_SOLARVARIATION) { // Legge informazioni sulla variazione solare
|
||||
this->SolarRGBVar[0].x = (t3dF32)stream.readSint16LE() / 100.0f;
|
||||
this->SolarRGBVar[0].y = (t3dF32)stream.readSint16LE() / 100.0f;
|
||||
this->SolarRGBVar[0].z = (t3dF32)stream.readSint16LE() / 100.0f;
|
||||
this->SolarRGBVar[1].x = 1.0f;
|
||||
this->SolarRGBVar[1].y = 1.0f;
|
||||
this->SolarRGBVar[1].z = 1.0f;
|
||||
this->SolarRGBVar[2].x = (t3dF32)stream.readSint16LE() / 100.0f;
|
||||
this->SolarRGBVar[2].y = (t3dF32)stream.readSint16LE() / 100.0f;
|
||||
this->SolarRGBVar[2].z = (t3dF32)stream.readSint16LE() / 100.0f;
|
||||
this->SolarRGBVar[3].x = (t3dF32)stream.readSint16LE() / 100.0f;
|
||||
this->SolarRGBVar[3].y = (t3dF32)stream.readSint16LE() / 100.0f;
|
||||
this->SolarRGBVar[3].z = (t3dF32)stream.readSint16LE() / 100.0f;
|
||||
}
|
||||
{
|
||||
uint16 n = stream.readSint32LE();
|
||||
if (n)
|
||||
this->XInc = 1.0f / (t3dF32) n; // Legge info su movimenti texture
|
||||
else this->XInc = 0.0f;
|
||||
n = stream.readSint32LE();
|
||||
if (n) this->YInc = 1.0f / (t3dF32) n;
|
||||
else this->YInc = 0.0f;
|
||||
}
|
||||
this->CurFrame = 0;
|
||||
|
||||
this->loadFaces(b, stream, numFaces);
|
||||
|
||||
this->NumVerts = stream.readSint16LE(); // Rilegge numero vertici
|
||||
b->NumTotVerts += this->NumVerts;
|
||||
|
||||
#ifndef WMGEN
|
||||
this->VertexBuffer = new gVertex[this->NumVerts](); // Crea un VertexBuffer
|
||||
this->VBptr = this->VertexBuffer;
|
||||
#else
|
||||
this->VBptr = (gVertex *)t3dMalloc(sizeof(gVertex) * this->NumVerts);
|
||||
#endif
|
||||
for (uint16 i = 0; i < this->NumVerts; i++) {
|
||||
this->VBptr[i].x = stream.readFloatLE(); // Legge X
|
||||
this->VBptr[i].y = stream.readFloatLE(); // Legge Y
|
||||
this->VBptr[i].z = stream.readFloatLE(); // Legge Z
|
||||
this->VBptr[i].u1 = stream.readFloatLE(); // Legge U
|
||||
this->VBptr[i].v1 = stream.readFloatLE(); // Legge V
|
||||
uint16 n = stream.readSint16LE(); // Legge indice normale
|
||||
this->VBptr[i].diffuse = n; //temporary storage for normal index
|
||||
}
|
||||
#ifndef WMGEN
|
||||
this->VBptr = nullptr;
|
||||
#endif
|
||||
this->NList = b->NList; // Lista di normali e' quella globale
|
||||
|
||||
int numMorphFrames = stream.readSint16LE(); // Legge frame di espressioni
|
||||
if (numMorphFrames) { // Se frame di espressioni
|
||||
this->MorphFrames.reserve(numMorphFrames); // Alloca spazio
|
||||
for (int i = 0; i < numMorphFrames; i++) {
|
||||
this->MorphFrames.push_back(t3dMORPH(stream));
|
||||
}
|
||||
}
|
||||
// Bounding box vertices
|
||||
//
|
||||
// 4 5
|
||||
// *-------*
|
||||
//0*-----1*/|
|
||||
// | 6 | |
|
||||
// |/*----+-*7
|
||||
// *------*/
|
||||
//2 3
|
||||
for (uint16 normal = 0; normal < 8; normal++) { // Legge BoundingBox
|
||||
this->BBox[normal].p = t3dV3F(stream) * SCALEFACTOR;
|
||||
}//__for_normal
|
||||
if ((this->BBox[0].p == this->BBox[4].p) && // Se non ha spessore
|
||||
(this->BBox[1].p == this->BBox[5].p) &&
|
||||
(this->BBox[2].p == this->BBox[6].p) &&
|
||||
(this->BBox[3].p == this->BBox[7].p)) {
|
||||
t3dV3F sub;
|
||||
sub.x = sub.y = sub.z = 5.0f;
|
||||
t3dVectSub(&this->BBox[0].p, &this->BBox[0].p, &sub); // Aggiunge 5 di spessore
|
||||
t3dVectSub(&this->BBox[1].p, &this->BBox[1].p, &sub);
|
||||
t3dVectSub(&this->BBox[2].p, &this->BBox[2].p, &sub);
|
||||
t3dVectSub(&this->BBox[3].p, &this->BBox[3].p, &sub);
|
||||
}
|
||||
|
||||
// Calcs the BBox normals
|
||||
t3dPlaneNormal(&this->BBoxNormal[0], &this->BBox[0].p, &this->BBox[2].p, &this->BBox[1].p); //front
|
||||
t3dPlaneNormal(&this->BBoxNormal[1], &this->BBox[4].p, &this->BBox[5].p, &this->BBox[6].p); //back
|
||||
t3dPlaneNormal(&this->BBoxNormal[2], &this->BBox[4].p, &this->BBox[0].p, &this->BBox[5].p); //Up
|
||||
t3dPlaneNormal(&this->BBoxNormal[3], &this->BBox[6].p, &this->BBox[7].p, &this->BBox[2].p); //Down
|
||||
t3dPlaneNormal(&this->BBoxNormal[4], &this->BBox[4].p, &this->BBox[6].p, &this->BBox[0].p); //Left
|
||||
t3dPlaneNormal(&this->BBoxNormal[5], &this->BBox[5].p, &this->BBox[1].p, &this->BBox[7].p); //Right
|
||||
this->BBoxAverageZ = 0; // Azzera distanza media
|
||||
uint32 numAniVerts = stream.readSint32LE();
|
||||
if (numAniVerts > 0) { // Se ci sono Smoothing Groups
|
||||
this->OldVertexBuffer = new gVertex[this->NumVerts]; // Crea un OldVertexBuffer
|
||||
this->SavedVertexBuffer = new gVertex[this->NumVerts]; // Crea un SavedVertexBuffer
|
||||
this->VertsInterpolants = t3dCalloc<t3dV3F>(this->NumVerts); // Crea spazio per interpolanti
|
||||
|
||||
this->ModVertices.reserve(numAniVerts);
|
||||
for (uint32 i = 0; i < numAniVerts; i++) {
|
||||
this->ModVertices.push_back(t3dMODVERTS(stream));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t3dMESH &t3dMESH::operator=(t3dMESH rhs) {
|
||||
SWAP(name, rhs.name);
|
||||
SWAP(portalName, rhs.portalName);
|
||||
SWAP(NumVerts, rhs.NumVerts);
|
||||
SWAP(NumNormals, rhs.NumNormals);
|
||||
SWAP(NumVerticesNormals, rhs.NumVerticesNormals);
|
||||
SWAP(SavedVertexBuffer, rhs.SavedVertexBuffer);
|
||||
SWAP(VertexBuffer, rhs.VertexBuffer);
|
||||
SWAP(OldVertexBuffer, rhs.OldVertexBuffer);
|
||||
SWAP(VertsInterpolants, rhs.VertsInterpolants);
|
||||
SWAP(VBptr, rhs.VBptr);
|
||||
SWAP(MorphFrames, rhs.MorphFrames);
|
||||
SWAP(FList, rhs.FList);
|
||||
SWAP(NList, rhs.NList);
|
||||
SWAP(Pos, rhs.Pos);
|
||||
SWAP(Trasl, rhs.Trasl);
|
||||
SWAP(Radius, rhs.Radius);
|
||||
SWAP(BBoxAverageZ, rhs.BBoxAverageZ);
|
||||
SWAP(Intersection, rhs.Intersection);
|
||||
SWAP(Matrix, rhs.Matrix);
|
||||
SWAP(LightmapDim, rhs.LightmapDim);
|
||||
SWAP(ModVertices, rhs.ModVertices);
|
||||
SWAP(CurFrame, rhs.CurFrame);
|
||||
SWAP(LastFrame, rhs.LastFrame);
|
||||
SWAP(BlendPercent, rhs.BlendPercent);
|
||||
SWAP(LastBlendPercent, rhs.LastBlendPercent);
|
||||
SWAP(ExpressionFrame, rhs.ExpressionFrame);
|
||||
SWAP(LastExpressionFrame, rhs.LastExpressionFrame);
|
||||
SWAP(DefaultAnim, rhs.DefaultAnim);
|
||||
SWAP(Anim, rhs.Anim);
|
||||
SWAP(WaterBuffer1, rhs.WaterBuffer1);
|
||||
SWAP(WaterBuffer2, rhs.WaterBuffer2);
|
||||
SWAP(WavesSpeed, rhs.WavesSpeed);
|
||||
SWAP(YSpeed, rhs.YSpeed);
|
||||
SWAP(XInc, rhs.XInc);
|
||||
SWAP(YInc, rhs.YInc);
|
||||
SWAP(Flags, rhs.Flags);
|
||||
SWAP(PortalList, rhs.PortalList);
|
||||
SWAP(RejectedMeshes, rhs.RejectedMeshes);
|
||||
|
||||
Common::copy(rhs.BBox, rhs.BBox + 8, BBox);
|
||||
Common::copy(rhs.BBoxNormal, rhs.BBoxNormal + 6, BBoxNormal);
|
||||
Common::copy(rhs.SolarRGBVar, rhs.SolarRGBVar + 4, SolarRGBVar);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
t3dMESH::t3dMESH(const t3dMESH &other) :
|
||||
name(other.name),
|
||||
portalName(other.portalName),
|
||||
NumVerts(other.NumVerts),
|
||||
NumNormals(other.NumNormals),
|
||||
NumVerticesNormals(other.NumVerticesNormals),
|
||||
SavedVertexBuffer(nullptr),
|
||||
VertexBuffer(new gVertex[other.NumVerts]()),
|
||||
OldVertexBuffer(nullptr),
|
||||
VertsInterpolants(nullptr),
|
||||
VBptr(other.VBptr),
|
||||
MorphFrames(other.MorphFrames),
|
||||
FList(other.FList),
|
||||
NList(other.NList),
|
||||
Pos(other.Pos),
|
||||
Trasl(other.Trasl),
|
||||
Radius(other.Radius),
|
||||
BBoxAverageZ(other.BBoxAverageZ),
|
||||
Intersection(other.Intersection),
|
||||
Matrix(other.Matrix),
|
||||
LightmapDim(other.LightmapDim),
|
||||
ModVertices(other.ModVertices),
|
||||
CurFrame(other.CurFrame),
|
||||
LastFrame(other.LastFrame),
|
||||
BlendPercent(other.BlendPercent),
|
||||
LastBlendPercent(other.LastBlendPercent),
|
||||
ExpressionFrame(other.ExpressionFrame),
|
||||
LastExpressionFrame(other.LastExpressionFrame),
|
||||
DefaultAnim(other.DefaultAnim),
|
||||
Anim(other.Anim),
|
||||
WaterBuffer1(other.WaterBuffer1),
|
||||
WaterBuffer2(other.WaterBuffer2),
|
||||
WavesSpeed(other.WavesSpeed),
|
||||
YSpeed(other.YSpeed),
|
||||
XInc(other.XInc),
|
||||
YInc(other.YInc),
|
||||
Flags(other.Flags),
|
||||
PortalList(other.PortalList),
|
||||
RejectedMeshes(other.RejectedMeshes) {
|
||||
|
||||
Common::copy(other.VertexBuffer, other.VertexBuffer + NumVerts, VertexBuffer);
|
||||
if (other.SavedVertexBuffer) {
|
||||
SavedVertexBuffer = new gVertex[other.NumVerts]();
|
||||
Common::copy(other.SavedVertexBuffer, other.SavedVertexBuffer + NumVerts, SavedVertexBuffer);
|
||||
}
|
||||
if (other.OldVertexBuffer) {
|
||||
OldVertexBuffer = new gVertex[other.NumVerts]();
|
||||
Common::copy(other.OldVertexBuffer, other.OldVertexBuffer + NumVerts, OldVertexBuffer);
|
||||
}
|
||||
if (other.VertsInterpolants) {
|
||||
VertsInterpolants = t3dCalloc<t3dV3F>(NumVerts);
|
||||
Common::copy(other.VertsInterpolants, other.VertsInterpolants + NumVerts, VertsInterpolants);
|
||||
}
|
||||
Common::copy(other.BBox, other.BBox + 8, BBox);
|
||||
Common::copy(other.BBoxNormal, other.BBoxNormal + 6, BBoxNormal);
|
||||
Common::copy(other.SolarRGBVar, other.SolarRGBVar + 4, SolarRGBVar);
|
||||
}
|
||||
|
||||
|
||||
t3dMESH::t3dMESH(t3dMESH &&old) :
|
||||
name(Common::move(old.name)),
|
||||
portalName(Common::move(old.portalName)),
|
||||
NumVerts(old.NumVerts),
|
||||
NumNormals(old.NumNormals),
|
||||
NumVerticesNormals(old.NumVerticesNormals),
|
||||
SavedVertexBuffer(old.SavedVertexBuffer),
|
||||
VertexBuffer(old.VertexBuffer),
|
||||
OldVertexBuffer(old.OldVertexBuffer),
|
||||
VertsInterpolants(old.VertsInterpolants),
|
||||
VBptr(old.VBptr),
|
||||
MorphFrames(Common::move(old.MorphFrames)),
|
||||
FList(Common::move(old.FList)),
|
||||
NList(Common::move(old.NList)),
|
||||
Pos(Common::move(old.Pos)),
|
||||
Trasl(Common::move(old.Trasl)),
|
||||
Radius(old.Radius),
|
||||
BBoxAverageZ(old.BBoxAverageZ),
|
||||
Intersection(Common::move(old.Intersection)),
|
||||
Matrix(Common::move(old.Matrix)),
|
||||
LightmapDim(old.LightmapDim),
|
||||
ModVertices(Common::move(old.ModVertices)),
|
||||
CurFrame(old.CurFrame),
|
||||
LastFrame(old.LastFrame),
|
||||
BlendPercent(old.BlendPercent),
|
||||
LastBlendPercent(old.LastBlendPercent),
|
||||
ExpressionFrame(old.ExpressionFrame),
|
||||
LastExpressionFrame(old.LastExpressionFrame),
|
||||
DefaultAnim(Common::move(old.DefaultAnim)),
|
||||
Anim(Common::move(old.Anim)),
|
||||
WaterBuffer1(old.WaterBuffer1),
|
||||
WaterBuffer2(old.WaterBuffer2),
|
||||
WavesSpeed(old.WavesSpeed),
|
||||
YSpeed(old.YSpeed),
|
||||
XInc(old.XInc),
|
||||
YInc(old.YInc),
|
||||
Flags(old.Flags),
|
||||
PortalList(old.PortalList),
|
||||
RejectedMeshes(Common::move(old.RejectedMeshes)) {
|
||||
|
||||
old.SavedVertexBuffer = nullptr;
|
||||
old.VertexBuffer = nullptr;
|
||||
old.OldVertexBuffer = nullptr;
|
||||
old.VertsInterpolants = nullptr;
|
||||
old.VBptr = nullptr;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
BBox[i] = Common::move(old.BBox[i]);
|
||||
}
|
||||
for (int i = 0; i < 6; i++) {
|
||||
BBoxNormal[i] = Common::move(old.BBoxNormal[i]);
|
||||
}
|
||||
old.WaterBuffer1 = nullptr;
|
||||
old.WaterBuffer2 = nullptr;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
SolarRGBVar[i] = Common::move(old.SolarRGBVar[i]);
|
||||
}
|
||||
}
|
||||
|
||||
t3dMESH::~t3dMESH() {
|
||||
release();
|
||||
}
|
||||
|
||||
/* -----------------10/06/99 15.39-------------------
|
||||
* t3dReleaseAnim
|
||||
* --------------------------------------------------*/
|
||||
void t3dMESH::releaseAnim(uint8 flag) {
|
||||
t3dBONEANIM *ba;
|
||||
uint32 i;
|
||||
|
||||
if (flag & T3D_MESH_DEFAULTANIM)
|
||||
ba = &this->DefaultAnim;
|
||||
else
|
||||
ba = &this->Anim;
|
||||
|
||||
if (!ba)
|
||||
return ;
|
||||
|
||||
for (i = 0; i < ba->NumBones; i++) {
|
||||
if (ba->BoneTable && ba->BoneTable[i].Matrix) {
|
||||
t3dFree(ba->BoneTable[i].Matrix);
|
||||
ba->BoneTable[i].Matrix = nullptr;
|
||||
t3dFree(ba->BoneTable[i].Trasl);
|
||||
ba->BoneTable[i].Trasl = nullptr;
|
||||
ba->BoneTable[i].ModVertices.clear();
|
||||
}
|
||||
}
|
||||
|
||||
t3dFree(ba->BoneTable);
|
||||
ba->BoneTable = nullptr;
|
||||
delete[] ba->Dist;
|
||||
ba->Dist = nullptr;
|
||||
}
|
||||
|
||||
void t3dMESH::release() { // Will eventually be a destructor.
|
||||
this->FList.clear();
|
||||
|
||||
this->MorphFrames.clear();
|
||||
this->NList.clear();
|
||||
|
||||
releaseAnim(0);
|
||||
releaseAnim(T3D_MESH_DEFAULTANIM);
|
||||
|
||||
this->RejectedMeshes.clear();
|
||||
this->PortalList = nullptr;
|
||||
|
||||
delete[] this->WaterBuffer1;
|
||||
this->WaterBuffer1 = nullptr;
|
||||
|
||||
delete[] this->WaterBuffer2;
|
||||
this->WaterBuffer2 = nullptr;
|
||||
|
||||
delete[] this->VertexBuffer;
|
||||
this->VertexBuffer = nullptr;
|
||||
|
||||
delete[] this->OldVertexBuffer;
|
||||
this->OldVertexBuffer = nullptr;
|
||||
|
||||
delete[] this->SavedVertexBuffer;
|
||||
this->SavedVertexBuffer = nullptr;
|
||||
|
||||
t3dFree(this->VertsInterpolants);
|
||||
this->VertsInterpolants = nullptr;
|
||||
|
||||
// if(mt->VBptr)
|
||||
// t3dFree(mt->VBptr);
|
||||
this->VBptr = nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
170
engines/watchmaker/3d/t3d_mesh.h
Normal file
170
engines/watchmaker/3d/t3d_mesh.h
Normal file
@@ -0,0 +1,170 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_T3D_MESH_H
|
||||
#define WATCHMAKER_T3D_MESH_H
|
||||
|
||||
#include "watchmaker/3d/t3d_face.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
struct t3dMESH {
|
||||
Common::String name; // mesh name
|
||||
Common::String portalName; // dest room name (if portal)
|
||||
uint16 NumFaces() {
|
||||
return FList.size();
|
||||
}; // faces number
|
||||
uint16 NumVerts = 0; // verts number
|
||||
uint16 NumNormals = 0; // face normals number
|
||||
uint16 NumVerticesNormals = 0; // verts normals number
|
||||
gVertex *SavedVertexBuffer = nullptr; // saved vertices pos (original)
|
||||
gVertex *VertexBuffer = nullptr; // cur vertices pos
|
||||
gVertex *OldVertexBuffer = nullptr; // last vertices pos
|
||||
t3dV3F *VertsInterpolants = nullptr; // verts interpolants (for blending)
|
||||
gVertex *VBptr = nullptr; // temp pointer to vertexbuffer
|
||||
Common::Array<t3dMORPH> MorphFrames; // morph frames list
|
||||
Common::Array<t3dFACE> FList; // faces list
|
||||
NormalList NList; // normals list
|
||||
t3dV3F Pos; // mesh center
|
||||
t3dV3F Trasl; // mesh traslation (world)
|
||||
t3dF32 Radius = 0.0f; // radius for Bounding Sphere culling
|
||||
t3dVERTEX BBox[8] = {}; // Bounding box
|
||||
t3dNORMAL BBoxNormal[6] = {}; // bound box normals
|
||||
t3dF32 BBoxAverageZ = 0.0f; // average distance from eye
|
||||
t3dV3F Intersection; // intersecton form eye
|
||||
t3dM3X3F Matrix; // transformation matrix (useful only for 1st mesh in body)
|
||||
uint16 LightmapDim = 0; // lightmap texture dimensions
|
||||
Common::Array<t3dMODVERTS> ModVertices; // mod vertices list
|
||||
t3dBONEANIM DefaultAnim; // Default Animations
|
||||
t3dBONEANIM Anim; // Animations
|
||||
int16 CurFrame = 0; // current animation frames (0 no anim)
|
||||
int16 LastFrame = 0; // last animation frames
|
||||
uint8 BlendPercent = 0; // blend animation percentage
|
||||
uint8 LastBlendPercent = 0; // last blend animation percentage
|
||||
uint32 ExpressionFrame = 0; // current expression frames
|
||||
uint32 LastExpressionFrame = 0; // last expression frames
|
||||
int32 *WaterBuffer1 = nullptr; // pointers to ripple buffer
|
||||
int32 *WaterBuffer2 = nullptr; // pointers to ripple buffer
|
||||
t3dF32 WavesSpeed; // waves speed
|
||||
t3dF32 YSpeed; // waves y speed
|
||||
t3dF32 XInc, YInc; // waves movements
|
||||
|
||||
t3dV3F SolarRGBVar[4]; // Override ambient color variation for solar movement
|
||||
|
||||
uint32 Flags; // Flags
|
||||
t3dBODY *PortalList = nullptr; // Pointer to portal connected
|
||||
Common::Array<t3dMESH *> RejectedMeshes; // rejected mesh from portal
|
||||
|
||||
void saveVertexBuffer() { // Scorre le mesh
|
||||
this->VBptr = this->VertexBuffer;
|
||||
if (this->OldVertexBuffer)
|
||||
memcpy(this->OldVertexBuffer, this->VBptr, sizeof(gVertex)*this->NumVerts);
|
||||
if (this->SavedVertexBuffer)
|
||||
memcpy(this->SavedVertexBuffer, this->VBptr, sizeof(gVertex)*this->NumVerts);
|
||||
this->VBptr = nullptr;
|
||||
}
|
||||
|
||||
void preCalcLights(const t3dV3F &ambientLight) {
|
||||
#ifndef WMGEN
|
||||
this->VBptr = this->VertexBuffer;
|
||||
#endif
|
||||
for (uint16 j = 0; j < this->NumFaces(); j++) { // Scorre le facce
|
||||
t3dFACE &Face = this->FList[j];
|
||||
MaterialPtr Material = Face.getMaterial();
|
||||
uint32 alphaval = 2;
|
||||
uint32 rr = 0, gg = 0, bb = 0;
|
||||
|
||||
rr = Material->r; // Prende Ambient da materiale
|
||||
gg = Material->g;
|
||||
bb = Material->b;
|
||||
|
||||
if (Material->hasFlag(T3D_MATERIAL_CLIPMAP)) { // Se il materiale e' clipmap
|
||||
alphaval = 0xfe;
|
||||
Face.flags |= T3D_MATERIAL_CLIPMAP; // lo setta sulla faccia
|
||||
/* Face->flags&=~T3D_MATERIAL_OPACITY;
|
||||
Face->flags&=~T3D_MATERIAL_GLASS;
|
||||
Material->Flags&=~T3D_MATERIAL_OPACITY;
|
||||
Material->Flags&=~T3D_MATERIAL_GLASS;*/
|
||||
// r=g=b=0;
|
||||
}
|
||||
if (Material->hasFlag(T3D_MATERIAL_OPACITY)) { // Se il materiale e' opacity
|
||||
Face.flags |= T3D_MATERIAL_OPACITY; // lo setta sulla faccia
|
||||
alphaval = 0x88;
|
||||
rr = gg = bb = 0;
|
||||
}
|
||||
if (Material->hasFlag(T3D_MATERIAL_GLASS)) { // Se e' un glass
|
||||
Face.flags |= T3D_MATERIAL_GLASS; // lo setta sulla faccia
|
||||
alphaval = 0xfe;
|
||||
rr = gg = bb = 255;
|
||||
}
|
||||
if (Material->hasFlag(T3D_MATERIAL_BOTTLE)) { // Se e' un bottle
|
||||
Face.flags |= T3D_MATERIAL_BOTTLE; // sulla faccia
|
||||
alphaval = 0x88;
|
||||
rr = gg = bb = 255;
|
||||
}
|
||||
if (Material->hasFlag(T3D_MATERIAL_ADDITIVE)) { // Se e' un additivo
|
||||
Face.flags |= T3D_MATERIAL_ADDITIVE; // sulla faccia
|
||||
alphaval = 0x88;
|
||||
rr = gg = bb = 255;
|
||||
}
|
||||
if (rr < ambientLight.x) rr = (uint8)ambientLight.x;
|
||||
if (gg < ambientLight.y) gg = (uint8)ambientLight.y;
|
||||
if (bb < ambientLight.z) bb = (uint8)ambientLight.z;
|
||||
this->VBptr[Face.VertexIndex[0]].diffuse = RGBA_MAKE(rr, gg, bb, alphaval); // Cambia diffse dei vertici della mesh
|
||||
this->VBptr[Face.VertexIndex[1]].diffuse = RGBA_MAKE(rr, gg, bb, alphaval);
|
||||
this->VBptr[Face.VertexIndex[2]].diffuse = RGBA_MAKE(rr, gg, bb, alphaval);
|
||||
}
|
||||
#ifndef WMGEN
|
||||
this->VBptr = nullptr;
|
||||
#endif
|
||||
// rOptimizeVertexArray(Mesh->VertexBuffer);
|
||||
}
|
||||
|
||||
t3dMESH() = default;
|
||||
t3dMESH(t3dBODY *b, Common::SeekableReadStream &stream, t3dMESH *&ReceiveRipples, uint8 &Mirror);
|
||||
t3dMESH(const t3dMESH &other);
|
||||
t3dMESH(t3dMESH &&old);
|
||||
t3dMESH& operator=(t3dMESH rhs);
|
||||
~t3dMESH();
|
||||
void loadFaces(t3dBODY *b, Common::SeekableReadStream &stream, int numFaces);
|
||||
void release();
|
||||
void releaseAnim(uint8 flag);
|
||||
|
||||
bool hasFaceMaterial() const {
|
||||
return !this->FList.empty() && (bool)(this->FList[0].getMaterial());
|
||||
}
|
||||
|
||||
void setMovieFrame(uint32 dwCurrFrame) {
|
||||
// TODO: Could just inline rSetMovieFrame?
|
||||
if (!this->FList.empty() && this->FList[0].getMaterial()) {
|
||||
rSetMovieFrame(this->FList[0].getMaterial(), dwCurrFrame);
|
||||
}
|
||||
}
|
||||
uint32 getMovieFrame() {
|
||||
assert(!this->FList.empty() && this->FList[0].getMaterial());
|
||||
return rGetMovieFrame(this->FList[0].getMaterial());
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_T3D_MESH_H
|
||||
26
engines/watchmaker/3d/texture.cpp
Normal file
26
engines/watchmaker/3d/texture.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/texture.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
69
engines/watchmaker/3d/texture.h
Normal file
69
engines/watchmaker/3d/texture.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_TEXTURE_H
|
||||
#define WATCHMAKER_TEXTURE_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/str.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "watchmaker/3d/dds_header.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "watchmaker/rect.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
class WGame;
|
||||
// Texture structs
|
||||
struct gTexture {
|
||||
Common::String name;
|
||||
Texture *_texture = nullptr;
|
||||
int RealDimX = 0; // original dimensions
|
||||
int RealDimY = 0; // original dimensions
|
||||
int DimX = 0; // current dimensions
|
||||
int DimY = 0; // current dimensions
|
||||
int ID = 0; // id
|
||||
int Flags = 0; // Flags
|
||||
|
||||
bool isEmpty() {
|
||||
return _texture == nullptr;
|
||||
}
|
||||
void clear() {
|
||||
// TODO: This will only work for the back-surface
|
||||
warning("Clearing %d", _blitsOnTop.size());
|
||||
_blitsOnTop.clear();
|
||||
}
|
||||
void render(WGame &game, Common::Rect src, Common::Rect dst);
|
||||
void blitInto(gTexture *texture, Common::Rect src, Common::Rect dst) {
|
||||
_blitsOnTop.push_back({texture, src, dst});
|
||||
}
|
||||
private:
|
||||
struct Blit {
|
||||
gTexture *texture;
|
||||
Common::Rect src;
|
||||
Common::Rect dst;
|
||||
};
|
||||
Common::Array<Blit> _blitsOnTop;
|
||||
};
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_TEXTURE_H
|
||||
26
engines/watchmaker/3d/types3d.cpp
Normal file
26
engines/watchmaker/3d/types3d.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/types3d.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
120
engines/watchmaker/3d/types3d.h
Normal file
120
engines/watchmaker/3d/types3d.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_TYPES3D_H
|
||||
#define WATCHMAKER_TYPES3D_H
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "math/vector3d.h"
|
||||
#include "watchmaker/types.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
struct t3dV2F {
|
||||
t3dF32 x = 0.0f, y = 0.0f; // 2d Vector
|
||||
public:
|
||||
constexpr t3dV2F() = default;
|
||||
constexpr t3dV2F(float _x, float _y, float z) : x(_x), y(_y) {}
|
||||
};
|
||||
|
||||
struct t3dV3F {
|
||||
t3dF32 x = 0.0f, y = 0.0f, z = 0.0f; // 3d vector
|
||||
public:
|
||||
constexpr t3dV3F() = default;
|
||||
constexpr t3dV3F(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
|
||||
t3dV3F(const Math::Vector3d &vector) {
|
||||
x = vector.x();
|
||||
y = vector.y();
|
||||
z = vector.z();
|
||||
}
|
||||
t3dV3F(Common::SeekableReadStream &stream) {
|
||||
x = stream.readFloatLE(); // Legge Pos
|
||||
y = stream.readFloatLE();
|
||||
z = stream.readFloatLE();
|
||||
}
|
||||
static t3dV3F fromStreamAsBytes(Common::SeekableReadStream &stream) {
|
||||
t3dF32 x = stream.readByte();
|
||||
t3dF32 y = stream.readByte();
|
||||
t3dF32 z = stream.readByte();
|
||||
return t3dV3F(x, y, z);
|
||||
}
|
||||
t3dV3F operator+(const t3dV3F &rhs) const {
|
||||
return t3dV3F(
|
||||
x + rhs.x,
|
||||
y + rhs.y,
|
||||
z + rhs.z
|
||||
);
|
||||
}
|
||||
t3dV3F operator-(const t3dV3F &rhs) const {
|
||||
return t3dV3F(
|
||||
x + rhs.x,
|
||||
y + rhs.y,
|
||||
z + rhs.z
|
||||
);
|
||||
}
|
||||
t3dV3F operator-() const {
|
||||
return t3dV3F(
|
||||
-x,
|
||||
-y,
|
||||
-z
|
||||
);
|
||||
}
|
||||
t3dV3F operator*(float scalar) const {
|
||||
return t3dV3F(
|
||||
x * scalar,
|
||||
y * scalar,
|
||||
z * scalar
|
||||
);
|
||||
}
|
||||
t3dV3F &operator*=(float scalar) {
|
||||
this->x *= scalar;
|
||||
this->y *= scalar;
|
||||
this->z *= scalar;
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const t3dV3F &rhs) const {
|
||||
return this->x == rhs.x && this->y == rhs.y && this->z == rhs.z;
|
||||
}
|
||||
bool operator!=(const t3dV3F &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
struct t3dNORMAL {
|
||||
t3dV3F n; //normal coords 12
|
||||
t3dF32 tn = 0.0f; //normal coords in light space
|
||||
t3dF32 dist = 0.0f; //dist from plane 4
|
||||
t3dF32 tras_n = 0.0f; //transformed normal 4
|
||||
uint8 flag = 0; //flags 1
|
||||
public:
|
||||
constexpr t3dNORMAL() = default;
|
||||
t3dNORMAL(Common::SeekableReadStream &stream) {
|
||||
n = t3dV3F(stream); // Direzione
|
||||
dist = -stream.readFloatLE(); // Distanza-Dot
|
||||
}
|
||||
};
|
||||
|
||||
typedef Common::SharedPtr<t3dNORMAL> NormalPtr;
|
||||
typedef Common::Array<NormalPtr> NormalList; // TODO: Not necessarily the prettiest solution, but chosen to ensure that changes to copies are shared.
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_TYPES3D_H
|
||||
26
engines/watchmaker/3d/vertex.cpp
Normal file
26
engines/watchmaker/3d/vertex.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/vertex.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
52
engines/watchmaker/3d/vertex.h
Normal file
52
engines/watchmaker/3d/vertex.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_VERTEX_H
|
||||
#define WATCHMAKER_VERTEX_H
|
||||
|
||||
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
// VertexBuffer vertices definition
|
||||
#pragma pack(1)
|
||||
struct gVertex {
|
||||
float x; // untransformed vertex
|
||||
float y;
|
||||
float z;
|
||||
int32 diffuse; // diffuse color
|
||||
float u1; // texture set for primary texture
|
||||
float v1;
|
||||
float u2; // texture set for lightmaps
|
||||
float v2;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
struct pVert {
|
||||
float x, y, z, rhw; // transformed vertex
|
||||
DWORD diffuse; // diffuse color
|
||||
} ;
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_VERTEX_H
|
||||
241
engines/watchmaker/classes/do_action.cpp
Normal file
241
engines/watchmaker/classes/do_action.cpp
Normal file
@@ -0,0 +1,241 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_action.h"
|
||||
#include "watchmaker/game.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/ll/ll_string.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/schedule.h"
|
||||
#include "watchmaker/classes/do_string.h"
|
||||
#include "watchmaker/classes/do_inv.h"
|
||||
#include "watchmaker/ll/ll_diary.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/ll/ll_anim.h"
|
||||
#include "watchmaker/classes/do_operate.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
/* -----------------05/06/00 11.10-------------------
|
||||
* CheckRoomPuzzle
|
||||
* --------------------------------------------------*/
|
||||
bool CheckRoomPuzzle(WGame &game, uint8 ev) {
|
||||
if ((game._gameVars.getCurRoomId() == r2G) && (WhichRoomChar(game.init, ocGIARDINIERE) == r2G) && ((CurObj != o2Gp2H) && (CurObj != ocGIARDINIERE))) {
|
||||
ClearText();
|
||||
ClearUseWith();
|
||||
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dGIARDINIERE_INTERRUPT2, 0, 0, nullptr, nullptr, nullptr);
|
||||
return true;
|
||||
} else if ((game._gameVars.getCurRoomId() == r2G) && (WhichRoomChar(game.init, ocCUSTODE) == r2G) && ((CurObj != o2Gp2H) && (CurObj != ocCUSTODE))) {
|
||||
ClearText();
|
||||
ClearUseWith();
|
||||
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dCUSTODE_INTERRUPT5, 0, 0, nullptr, nullptr, nullptr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -----------------19/05/98 16.40-------------------
|
||||
* doDoor
|
||||
* --------------------------------------------------*/
|
||||
void doDoor(WGame &game, int32 obj) {
|
||||
int32 anim = aNULL;
|
||||
Init &init = game.init;
|
||||
|
||||
if (!obj) return;
|
||||
|
||||
anim = init.Obj[obj].anim[CurPlayer];
|
||||
switch (obj) {
|
||||
case 0: // Quiet VS C4065 warning
|
||||
default:
|
||||
anim = init.Obj[obj].anim[CurPlayer];
|
||||
if (init.Obj[obj].goroom)
|
||||
game._gameVars.setCurRoomId(init.Obj[obj].goroom);
|
||||
break;
|
||||
}
|
||||
|
||||
if (anim != aNULL) StartAnim(game, anim);
|
||||
}
|
||||
|
||||
/* -----------------19/05/98 16.40-------------------
|
||||
* doTake
|
||||
* --------------------------------------------------*/
|
||||
void doTake(WGame &game, int32 obj) {
|
||||
int32 anim = aNULL;
|
||||
//uint8 del = TRUE;
|
||||
|
||||
if (!obj) return;
|
||||
|
||||
anim = game.init.Obj[obj].anim[CurPlayer];
|
||||
switch (obj) {
|
||||
case o25CHIAVI:
|
||||
// if ( Anim[aMOSTRAFOTOACUOCO].active == 0 )
|
||||
// return ;
|
||||
break;
|
||||
|
||||
default:
|
||||
//del = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (anim) StartAnim(game, anim);
|
||||
|
||||
// spegne oggetto che viene preso
|
||||
// if(del) Obj[obj].flags &= ~ON;
|
||||
// aggiunge icona
|
||||
AddIcon(game.init, game.init.Obj[obj].ninv);
|
||||
}
|
||||
|
||||
/* -----------------19/05/98 16.40-------------------
|
||||
* doExamine
|
||||
* --------------------------------------------------*/
|
||||
void doExamine(WGame &game, int32 obj) {
|
||||
int32 anim = aNULL;
|
||||
uint8 sent = FALSE;
|
||||
int32 log_item = lNULL;
|
||||
Init &init = game.init;
|
||||
|
||||
if (!obj) return;
|
||||
|
||||
if (init.Obj[obj].flags & EXAMINEACT)
|
||||
anim = init.Obj[obj].anim2[CurPlayer];
|
||||
switch (obj) {
|
||||
case o1DVALIGETTACH:
|
||||
UpdateSpecial(game, r1D);
|
||||
anim = aTO1PERSON;
|
||||
break;
|
||||
|
||||
case o31BAULECH:
|
||||
UpdateSpecial(game, r31);
|
||||
anim = aTO1PERSON;
|
||||
break;
|
||||
|
||||
case oXT1ETARGHETTA:
|
||||
log_item = lPDA2_MENU5_RAUL_ITEM2;
|
||||
break;
|
||||
|
||||
case o13STATUETTE:
|
||||
log_item = lPDA2_MENU6_CUS_ITEM3;
|
||||
break;
|
||||
|
||||
case o29TARGA1:
|
||||
case o29TARGA2:
|
||||
case o29TARGA3:
|
||||
case o29TARGA4:
|
||||
case o29COPPA:
|
||||
log_item = lPDA2_MENU8_SUP_ITEM2;
|
||||
break;
|
||||
|
||||
case o46PRIMODIAGRAMMA:
|
||||
log_item = lPDA6_MENU31_ITEM1;
|
||||
break;
|
||||
|
||||
case o46SECONDODIAGRAMMA:
|
||||
// se il flag EXTRA non e' settato vuol dire che non si e' ancora entrati nella r45 e non si
|
||||
// puo' conoscere il significato del disegno
|
||||
if (!(init.Obj[o46SECONDODIAGRAMMA].flags & EXTRA)) {
|
||||
PlayerSpeak(game, init.Obj[o13QUADRO1].action[CurPlayer]);
|
||||
return;
|
||||
} else log_item = lPDA6_MENU31_ITEM2;
|
||||
break;
|
||||
|
||||
default:
|
||||
sent = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (log_item != lNULL) {
|
||||
if (!(init.PDALog[log_item].flags & PDA_ON)) {
|
||||
init.PDALog[log_item].flags |= (PDA_ON | PDA_UPDATE);
|
||||
init.PDALog[log_item].time = t3dCurTime;
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_SYSTEM, ME_STARTEFFECT, MP_DEFAULT, FRAME_PER_SECOND * 3, 0, EFFECT_DISPLAY_NEWLOGIMG, nullptr, nullptr, nullptr);
|
||||
}
|
||||
sent = TRUE;
|
||||
}
|
||||
|
||||
if (anim != aNULL) StartAnim(game, anim);
|
||||
else if ((sent) && (init.Obj[obj].examine[CurPlayer])) PlayerSpeak(game, init.Obj[obj].examine[CurPlayer]);
|
||||
}
|
||||
|
||||
/* -----------------19/03/98 16.31-------------------
|
||||
* doAction
|
||||
* --------------------------------------------------*/
|
||||
void doAction(WGame &game) {
|
||||
Init &init = game.init;
|
||||
switch (TheMessage->event) {
|
||||
case ME_MOUSEEXAMINE:
|
||||
CurObj = TheMessage->lparam[0];
|
||||
|
||||
if (CheckRoomPuzzle(game, TheMessage->event))
|
||||
break;
|
||||
|
||||
if (bUseWith & UW_ON) {
|
||||
UseWith[WITH] = CurObj;
|
||||
bUseWith &= ~UW_ON;
|
||||
ClearText();
|
||||
// fa l'usa con
|
||||
doUseWith(game);
|
||||
break;
|
||||
}
|
||||
|
||||
doExamine(game, CurObj);
|
||||
break;
|
||||
|
||||
case ME_MOUSEOPERATE:
|
||||
CurObj = TheMessage->lparam[0];
|
||||
|
||||
if (CheckRoomPuzzle(game, TheMessage->event))
|
||||
break;
|
||||
|
||||
if (bUseWith & UW_ON) {
|
||||
UseWith[WITH] = CurObj;
|
||||
bUseWith &= ~UW_ON;
|
||||
ClearText();
|
||||
// fa l'usa con
|
||||
doUseWith(game);
|
||||
break;
|
||||
}
|
||||
|
||||
if (init.Obj[CurObj].flags & USEWITH) {
|
||||
UseWith[USED] = CurObj;
|
||||
bUseWith = UW_ON;
|
||||
ShowObjName(init, CurObj);
|
||||
CurMousePointer = MousePointerPlus;
|
||||
} else if (init.Obj[CurObj].flags & CHARACTER) {
|
||||
if (bFirstPerson) {
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_CAMERA, ME_CAMERA1TO3, MP_DEFAULT, 0, 0, 0, nullptr, nullptr, nullptr);
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_WAIT_CAMERA, init.Obj[CurObj].goroom, 0, 0, nullptr, nullptr, nullptr);
|
||||
} else
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, init.Obj[CurObj].goroom, 0, 0, nullptr, nullptr, nullptr);
|
||||
} else if (init.Obj[CurObj].flags & TAKE)
|
||||
doTake(game, CurObj);
|
||||
else if (init.Obj[CurObj].flags & ROOM)
|
||||
doDoor(game, CurObj);
|
||||
else
|
||||
doOperate(game, CurObj);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
34
engines/watchmaker/classes/do_action.h
Normal file
34
engines/watchmaker/classes/do_action.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_ACTION_H
|
||||
#define WATCHMAKER_DO_ACTION_H
|
||||
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doAction(WGame &game);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_ACTION_H
|
||||
53
engines/watchmaker/classes/do_anim.cpp
Normal file
53
engines/watchmaker/classes/do_anim.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_anim.h"
|
||||
#include "watchmaker/game.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/ll/ll_anim.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
/* -----------------15/12/98 10.03-------------------
|
||||
* doAnimation
|
||||
* --------------------------------------------------*/
|
||||
void doAnimation(WGame &game) {
|
||||
switch (TheMessage->event) {
|
||||
case ME_STARTANIM:
|
||||
StartAnim(game, TheMessage->wparam1);
|
||||
break;
|
||||
|
||||
case ME_STOPANIM:
|
||||
StopAnim(game, TheMessage->wparam1);
|
||||
break;
|
||||
|
||||
case ME_PAUSEANIM:
|
||||
PauseAnim(game.init, TheMessage->wparam1);
|
||||
break;
|
||||
|
||||
case ME_CONTINUEANIM:
|
||||
ContinueAnim(game.init, TheMessage->wparam1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
33
engines/watchmaker/classes/do_anim.h
Normal file
33
engines/watchmaker/classes/do_anim.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_ANIM_H
|
||||
#define WATCHMAKER_DO_ANIM_H
|
||||
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doAnimation(WGame &game);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_ANIM_H
|
||||
960
engines/watchmaker/classes/do_camera.cpp
Normal file
960
engines/watchmaker/classes/do_camera.cpp
Normal file
@@ -0,0 +1,960 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_camera.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/utils.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/3d/geometry.h"
|
||||
#include "watchmaker/3d/t3d_body.h"
|
||||
#include "watchmaker/ll/ll_util.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/walk/act.h"
|
||||
#include "watchmaker/ll/ll_mouse.h"
|
||||
#include "watchmaker/schedule.h"
|
||||
#include "watchmaker/ll/ll_string.h"
|
||||
#include "watchmaker/classes/do_string.h"
|
||||
#include "watchmaker/3d/animation.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/3d/loader.h"
|
||||
#include "watchmaker/walk/walkutil.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
|
||||
// locals
|
||||
#define FIRST_PERSON_STEPS 8
|
||||
#define CAMERA_CARRELLO_DIST 800.0f
|
||||
#define MAX_CAMERA_MOVE 50.0f
|
||||
#define MAX_CAMERA_ANGLE 2.0f
|
||||
#define CAMERA_SUB_STEPS 3
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
/* -----------------20/10/98 10.40-------------------
|
||||
* PickCamera
|
||||
* --------------------------------------------------*/
|
||||
t3dCAMERA *CameraMan::PickCamera(t3dBODY *b, unsigned char in) {
|
||||
// TODO: This is just here until we know when we can expect a nullptr
|
||||
if (!b) {
|
||||
return nullptr;
|
||||
}
|
||||
return b->PickCamera(in);
|
||||
}
|
||||
|
||||
t3dCAMERA *t3dBODY::PickCamera(uint8 in) {
|
||||
if (NumCameras() == 0) return nullptr;
|
||||
// in = 100;
|
||||
|
||||
for (int i = 0; i < (int32)NumCameras(); i++)
|
||||
if (CameraTable[i].Index == (in + 1))
|
||||
return (&CameraTable[i]);
|
||||
// return( &b->CameraTable[in] );
|
||||
|
||||
warning("Camera %d non trovata in %s", in + 1, name.c_str());
|
||||
return (&CameraTable[0]);
|
||||
}
|
||||
|
||||
|
||||
/* -----------------06/07/98 16.55-------------------
|
||||
* GetRealCharPos
|
||||
* --------------------------------------------------*/
|
||||
void CameraMan::GetRealCharPos(Init &init, t3dV3F *Target, int32 oc, uint8 bn) {
|
||||
t3dCHARACTER *Ch = Character[oc];
|
||||
t3dMESH *mesh = Ch->Mesh, *m;
|
||||
t3dBONE *bone;
|
||||
int32 frame = mesh->CurFrame;
|
||||
t3dV3F tmp;
|
||||
|
||||
if ((Target != nullptr) && (Ch != nullptr)) {
|
||||
// Discesa del garage
|
||||
if (t3dCurRoom->name.equalsIgnoreCase("rxt.t3d")) {
|
||||
if ((m = LinkMeshToStr(init, "oxt-garage")) && (m->BBox[3].p.x - m->BBox[2].p.x) &&
|
||||
(Player->Pos.x > m->BBox[2].p.x) && (Player->Pos.x < m->BBox[3].p.x) &&
|
||||
(Player->Pos.z > m->BBox[2].p.z) && (Player->Pos.z < m->BBox[6].p.z)) {
|
||||
Player->Mesh->Trasl.y = Player->Pos.y = ((Player->Pos.x - m->BBox[2].p.x) / (m->BBox[3].p.x - m->BBox[2].p.x)) * m->BBox[2].p.y;
|
||||
CurFloorY = Player->Pos.y;
|
||||
}
|
||||
}
|
||||
|
||||
t3dVectCopy(Target, &mesh->Trasl);
|
||||
Target->y = CurFloorY + CHEST_HEIGHT;
|
||||
if ((bn) && (frame > 0)) {
|
||||
if (mesh->Flags & T3D_MESH_DEFAULTANIM)
|
||||
bone = &mesh->DefaultAnim.BoneTable[bn];
|
||||
else
|
||||
bone = &mesh->Anim.BoneTable[bn];
|
||||
|
||||
if ((bone) && (bone->Trasl) && (bone->Matrix)) {
|
||||
Target->y = CurFloorY;
|
||||
t3dVectSub(&tmp, &bone->Trasl[frame], &bone->Trasl[1]);
|
||||
t3dVectTransform(&tmp, &tmp, &bone->Matrix[1]);
|
||||
t3dVectTransformInv(&tmp, &tmp, &bone->Matrix[frame]);
|
||||
t3dVectAdd(&tmp, &tmp, &bone->Trasl[frame]);
|
||||
t3dVectAdd(Target, Target, &tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------21/08/98 14.38-------------------
|
||||
* Dist Point C from AB -> Inters in I
|
||||
* --------------------------------------------------*/
|
||||
uint8 DistPointRect(t3dV3F *i, t3dF32 *dist, t3dV3F *a, t3dV3F *b, t3dV3F *c) {
|
||||
t3dF32 d, r;
|
||||
|
||||
d = ((b->x - a->x) * (b->x - a->x) + (b->z - a->z) * (b->z - a->z));
|
||||
r = ((a->z - c->z) * (a->z - b->z) - (a->x - c->x) * (b->x - a->x)) / d;
|
||||
|
||||
if (r <= 0.0f) { // Prima di A
|
||||
t3dVectCopy(i, a);
|
||||
*dist = t3dVectDistance(c, i);
|
||||
return FALSE;
|
||||
} else if (r >= 1.0f) { // Dopo B
|
||||
t3dVectCopy(i, b);
|
||||
*dist = t3dVectDistance(c, i);
|
||||
return FALSE;
|
||||
} else { // Tra A e B
|
||||
i->x = a->x + r * (b->x - a->x);
|
||||
i->y = a->y + r * (b->y - a->y);
|
||||
i->z = a->z + r * (b->z - a->z);
|
||||
*dist = t3dVectDistance(c, i);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -----------------20/08/98 17.16-------------------
|
||||
* HandleCameraCarrello
|
||||
* --------------------------------------------------*/
|
||||
void CameraMan::HandleCameraCarrello(t3dBODY *croom) {
|
||||
t3dCAMERAPATH *cp = nullptr;
|
||||
t3dF32 dist, mindist;
|
||||
t3dV3F pt, i, b;
|
||||
int16 j;
|
||||
uint8 bcc = false;
|
||||
|
||||
if (!Player || !croom || !t3dCurCamera) return;
|
||||
|
||||
// Se e' appena partito il carrello
|
||||
if (!bCameraCarrello) {
|
||||
CameraCarrello = *t3dCurCamera;
|
||||
t3dCurCamera = &CameraCarrello;
|
||||
}
|
||||
|
||||
// Cerca percorso carrello
|
||||
for (j = 0; j < CameraCarrello.NumAvailablePaths(); j++)
|
||||
if (CameraCarrello.CameraPaths[j].PathIndex & 0x80)
|
||||
break;
|
||||
// Puntatore al perscorso carrello, se non lo trova esce
|
||||
if ((j >= CameraCarrello.NumAvailablePaths()) ||
|
||||
((cp = &croom->CameraPath[(CameraCarrello.CameraPaths[j].PathIndex) & 0x7F]) == nullptr))
|
||||
return ;
|
||||
|
||||
// Trova il punto dell'omino che deve seguire il source del carrello
|
||||
t3dVectFill(&b, 0.0f);
|
||||
t3dVectFill(&pt, 0.0f);
|
||||
pt.z = (t3dF32)(cp->CarrelloDist);
|
||||
t3dVectTransform(&pt, &pt, &Player->Mesh->Matrix);
|
||||
t3dVectAdd(&pt, &pt, &t3dCurCamera->Target);
|
||||
|
||||
// Cerca punto ottimale del carrello
|
||||
mindist = 9999999.9f;
|
||||
for (j = 0; j < cp->NumPoints() - 1; j++) {
|
||||
DistPointRect(&i, &dist, &cp->PList[j], &cp->PList[j + 1], &pt);
|
||||
if (dist < mindist) {
|
||||
t3dVectCopy(&b, &i);
|
||||
bcc = true;
|
||||
mindist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
// Se decide di spostare source camera carrello
|
||||
if (bcc) {
|
||||
// Se e' appena partito carrello, puo' fare scatto
|
||||
if (!bCameraCarrello)
|
||||
t3dVectCopy(&t3dCurCamera->Source, &b);
|
||||
else {
|
||||
// Se dorvebbe fare scatto, inizia a smussare
|
||||
if (t3dVectDistance(&t3dCurCamera->Source, &b) > MAX_CAMERA_MOVE) {
|
||||
t3dVectSub(&i, &b, &t3dCurCamera->Source);
|
||||
t3dVectNormalize(&i);
|
||||
i *= MAX_CAMERA_MOVE;
|
||||
t3dVectAdd(&t3dCurCamera->Source, &t3dCurCamera->Source, &i);
|
||||
} else
|
||||
t3dVectCopy(&t3dCurCamera->Source, &b);
|
||||
}
|
||||
bCameraCarrello = bcc;
|
||||
}
|
||||
}
|
||||
|
||||
void CameraMan::MoveHeadAngles(t3dF32 diffx, t3dF32 diffy) {
|
||||
t3dF32 s;
|
||||
|
||||
if (((diffx == 0) && (diffy == 0)) || (bLPressed) || (bRPressed) || (bDialogActive)) return;
|
||||
|
||||
if (diffx < -10) diffx = -10;
|
||||
else if (diffx > 10) diffx = 10;
|
||||
if (diffy < -10) diffy = -10;
|
||||
else if (diffy > 10) diffy = 10;
|
||||
|
||||
s = (t3dF32)bFirstPerson + 1.0f;
|
||||
if (diffx > 0) {
|
||||
if ((HeadAngles.x + diffx) >= MAX_HEAD_ANGLE_X * s) {
|
||||
diffx = MAX_HEAD_ANGLE_X * s - HeadAngles.x;
|
||||
HeadAngles.x = MAX_HEAD_ANGLE_X * s;
|
||||
} else
|
||||
HeadAngles.x += diffx;
|
||||
} else {
|
||||
if ((HeadAngles.x + diffx) < -MAX_HEAD_ANGLE_X * s) {
|
||||
diffx = -MAX_HEAD_ANGLE_X * s - HeadAngles.x;
|
||||
HeadAngles.x = -MAX_HEAD_ANGLE_X * s;
|
||||
} else
|
||||
HeadAngles.x += diffx;
|
||||
}
|
||||
|
||||
if (diffy > 0) {
|
||||
if ((HeadAngles.y + diffy) >= MAX_HEAD_ANGLE_Y * s) {
|
||||
diffy = MAX_HEAD_ANGLE_Y * s - HeadAngles.y;
|
||||
HeadAngles.y = MAX_HEAD_ANGLE_Y * s;
|
||||
} else
|
||||
HeadAngles.y += diffy;
|
||||
} else {
|
||||
if ((HeadAngles.y + diffy) < -MAX_HEAD_ANGLE_Y * s) {
|
||||
diffy = -MAX_HEAD_ANGLE_Y * s - HeadAngles.y;
|
||||
HeadAngles.y = -MAX_HEAD_ANGLE_Y * s;
|
||||
} else
|
||||
HeadAngles.y += diffy;
|
||||
}
|
||||
|
||||
CamAngleX = ((t3dF32)diffy / 180.0f * T3D_PI);
|
||||
CamAngleY = ((t3dF32)diffx / 180.0f * T3D_PI);
|
||||
if (bFirstPerson && !bLockCamera && ((CamAngleX != 0.0f) || (CamAngleY != 0.0f)))
|
||||
t3dRotateMoveCamera(t3dCurCamera, CamAngleX, CamAngleY, 0.0f);
|
||||
}
|
||||
|
||||
void CameraMan::resetAngle() {
|
||||
CamAngleX = 0.0f;
|
||||
CamAngleY = 0.0f;
|
||||
t3dVectFill(&HeadAngles, 0.0f);
|
||||
}
|
||||
|
||||
/* -----------------30/09/98 11.13-------------------
|
||||
* GetCameraTaget
|
||||
* --------------------------------------------------*/
|
||||
void CameraMan::GetCameraTarget(Init &init, t3dV3F *Target) {
|
||||
int32 i;
|
||||
|
||||
if (!Target) return;
|
||||
|
||||
if (bFirstPerson) // Se sono in prima persona e' gia' precalcolato
|
||||
t3dVectCopy(Target, &FirstPersonTarget);
|
||||
else if ((Player) && (!CameraTargetObj)) // Se non e' settato niente oppure e' il giocatore
|
||||
GetRealCharPos(init, Target, ocCURPLAYER, 0);
|
||||
else if ((CameraTargetObj == oCAMERAMAX) && (t3dCurCamera)) {
|
||||
if ((bAllowCalcCamera) && (bMovingCamera) && (CurCameraStep < NumCameraSteps)) { // se li ha gia' precalcolati
|
||||
t3dVectCopy(Target, &CameraStep[CurCameraStep].Target);
|
||||
for (i = 0; i < CurCameraSubStep; i++)
|
||||
t3dVectAdd(Target, Target, &TargetBlend);
|
||||
} else
|
||||
t3dVectCopy(Target, &t3dCurCamera->MaxTarget);
|
||||
} else
|
||||
GetRealCharPos(init, Target, CameraTargetObj, (uint8)CameraTargetBone);
|
||||
}
|
||||
|
||||
/* -----------------05/06/98 15.34-------------------
|
||||
* NextCameraStep
|
||||
* --------------------------------------------------*/
|
||||
void CameraMan::NextCameraStep(WGame &game) {
|
||||
t3dBONE *bone;
|
||||
t3dV3F Target;
|
||||
int16 i;
|
||||
Init &init = game.init;
|
||||
|
||||
if (bMovingCamera == 2) {
|
||||
if ((game.init._globals._invVars.CameraDummy.CurFrame >= 0) && (game.init._globals._invVars.CameraDummy.Anim.BoneTable)) {
|
||||
if ((bone = &game.init._globals._invVars.CameraDummy.Anim.BoneTable[33]) && (bone->Trasl))
|
||||
t3dVectCopy(&t3dCurCamera->Source, &bone->Trasl[game.init._globals._invVars.CameraDummy.CurFrame]);
|
||||
if ((bone = &game.init._globals._invVars.CameraDummy.Anim.BoneTable[34]) && (bone->Trasl))
|
||||
t3dVectCopy(&t3dCurCamera->Target, &bone->Trasl[game.init._globals._invVars.CameraDummy.CurFrame]);
|
||||
} else {
|
||||
t3dCurCamera = DestCamera;
|
||||
CurCameraSubStep = CurCameraStep = NumCameraSteps = 0;
|
||||
bMovingCamera = false;
|
||||
DestCamera = nullptr;
|
||||
t3dVectFill(&OldCameraTarget, 0.0f);
|
||||
// _vm->_messageSystem.addWaitingMsgs( MP_WAIT_CAMERA );
|
||||
|
||||
GetCameraTarget(init, &t3dCurCamera->Target);
|
||||
game._renderer->setCurCameraViewport(t3dCurCamera->Fov, bSuperView);
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
if (!bMovingCamera || !Player) return;
|
||||
|
||||
GetCameraTarget(init, &Target);
|
||||
|
||||
// Se ha finito di muoversi
|
||||
if ((NumCameraSteps != 0) && (CurCameraStep >= NumCameraSteps)) {
|
||||
t3dCurCamera = DestCamera;
|
||||
t3dVectCopy(&t3dCurCamera->Target, &Target);
|
||||
game._renderer->setCurCameraViewport(t3dCurCamera->Fov, bSuperView);
|
||||
|
||||
CurCameraStep = NumCameraSteps = 0;
|
||||
bMovingCamera = false;
|
||||
DestCamera = nullptr;
|
||||
_vm->_messageSystem.addWaitingMsgs(MP_WAIT_CAMERA);
|
||||
|
||||
// if( (bFirstPerson) && ( ( CurRoom == r32 ) && ( PlayerPos[CurPlayer+ocDARRELL] == 6 ) ) )
|
||||
// PlayerSpeak( Obj[o32OROLOGIO].action[CurPlayer+ocDARRELL] );
|
||||
if ((bFirstPerson) && (ToFirstPersonSent)) {
|
||||
PlayerSpeak(game, ToFirstPersonSent);
|
||||
ToFirstPersonSent = 0;
|
||||
}
|
||||
|
||||
// Se ho selezionato un carrello, riposiziona il source
|
||||
for (i = 0; i < t3dCurCamera->NumAvailablePaths(); i++)
|
||||
if (t3dCurCamera->CameraPaths[i].PathIndex & 0x80) {
|
||||
HandleCameraCarrello(t3dCurRoom);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
t3dCurCamera = &CameraStep[CurCameraStep];
|
||||
t3dVectCopy(&t3dCurCamera->Target, &Target);
|
||||
|
||||
if ((!CurCameraSubStep) && (CurCameraStep + 1 < NumCameraSteps)) {
|
||||
t3dVectSub(&SourceBlend, &CameraStep[CurCameraStep + 1].Source, &CameraStep[CurCameraStep].Source);
|
||||
SourceBlend *= (1.0f / (t3dF32)CAMERA_SUB_STEPS);
|
||||
|
||||
t3dVectSub(&TargetBlend, &CameraStep[CurCameraStep + 1].Target, &CameraStep[CurCameraStep].Target);
|
||||
TargetBlend *= (1.0f / (t3dF32)CAMERA_SUB_STEPS);
|
||||
} else if (CurCameraStep + 1 < NumCameraSteps)
|
||||
t3dVectAdd(&t3dCurCamera->Source, &t3dCurCamera->Source, &SourceBlend);
|
||||
|
||||
game._renderer->setCurCameraViewport(t3dCurCamera->Fov, bSuperView);
|
||||
if (++CurCameraSubStep >= CAMERA_SUB_STEPS) {
|
||||
CurCameraStep ++;
|
||||
CurCameraSubStep = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -----------------05/06/98 15.50-------------------
|
||||
* doCamera
|
||||
* --------------------------------------------------*/
|
||||
void CameraMan::doCamera(WGame &game) {
|
||||
t3dV3F Dest, Dir, ct;
|
||||
t3dF32 dist;
|
||||
int16 row, col, i;
|
||||
Init &init = game.init;
|
||||
|
||||
switch (TheMessage->event) {
|
||||
case ME_CAMERA3TO1:
|
||||
if (bMovingCamera) {
|
||||
TheMessage->flags |= MP_WAIT_CAMERA;
|
||||
ReEvent();
|
||||
}
|
||||
if (Player == nullptr) break;
|
||||
|
||||
mHide = true;
|
||||
bFirstPerson = true;
|
||||
|
||||
CharStop(ocCURPLAYER);
|
||||
game._messageSystem.removeEvent(EventClass::MC_PLAYER, ME_ALL);
|
||||
ClearText();
|
||||
|
||||
LastCamera = t3dCurCamera;
|
||||
DestCamera = &FirstPersonCamera;
|
||||
DestCamera->Fov = CAMERA_FOV_1ST;
|
||||
// LastCamera->Fov = CAMERA_FOV;
|
||||
|
||||
// Abilita la modalita' muovi camera
|
||||
bMovingCamera = true;
|
||||
|
||||
// Seleziona il punto di destinazione del Source
|
||||
GetRealCharPos(init, &Dest, ocCURPLAYER, 0);
|
||||
Dest.y = CurFloorY + EYES_HEIGHT;
|
||||
t3dVectCopy(&FirstPersonCamera.Source, &Dest);
|
||||
// Trova il target a cui puntare
|
||||
t3dVectFill(&HeadAngles, 0.0f);
|
||||
CamAngleX = 0.0f;
|
||||
CamAngleY = 0.0f;
|
||||
t3dVectNormalize(&Player->Dir);
|
||||
FirstPersonTarget = Player->Dir * CHEST_HEIGHT;
|
||||
t3dVectAdd(&FirstPersonTarget, &FirstPersonTarget, &Player->Mesh->Trasl);
|
||||
FirstPersonTarget.y = CurFloorY + EYES_HEIGHT;
|
||||
if (TheMessage->bparam) {
|
||||
if (GetFullLightDirection(&FirstPersonTarget, TheMessage->bparam)) {
|
||||
Dest.y = FirstPersonTarget.y;
|
||||
FirstPersonCamera.Source.y = FirstPersonTarget.y;
|
||||
// HeadAngles.y = -(t3dF32)asin( (FirstPersonTarget.y-(CurFloorY+EYES_HEIGHT))/CHEST_HEIGHT )*180.0f/T3D_PI;
|
||||
}
|
||||
}
|
||||
// Calcola quanto deve muovere la camera
|
||||
dist = t3dVectDistance(&LastCamera->Source, &Dest);
|
||||
t3dVectSub(&Dir, &LastCamera->Source, &Dest);
|
||||
t3dVectNormalize(&Dir);
|
||||
Dir *= (dist / FIRST_PERSON_STEPS);
|
||||
|
||||
CurCameraStep = 0;
|
||||
CurCameraSubStep = 0;
|
||||
NumCameraSteps = FIRST_PERSON_STEPS;
|
||||
// Copia tutti i passi del percorso partendo dall'arrivo
|
||||
for (i = NumCameraSteps - 1; i >= 0; i--) {
|
||||
t3dVectCopy(&CameraStep[i].Source, &Dest);
|
||||
t3dVectAdd(&Dest, &Dest, &Dir);
|
||||
CameraStep[i].Fov = LastCamera->Fov + (t3dF32)(((DestCamera->Fov - LastCamera->Fov) * (t3dF32)i) / (t3dF32)NumCameraSteps);
|
||||
}
|
||||
|
||||
// Avanza al primo frame del percorso
|
||||
NextCameraStep(game);
|
||||
game._messageSystem.removeEvent(EventClass::MC_PLAYER, ME_PLAYERIDLE);
|
||||
|
||||
// Sistema posizione del mouse e posizione della testa
|
||||
{
|
||||
auto info = game._renderer->getScreenInfos();
|
||||
mPosx = info.width / 2;
|
||||
mPosy = info.height / 2;
|
||||
}
|
||||
Player->Flags |= T3D_CHARACTER_ENABLEDINMIRROR;
|
||||
break;
|
||||
|
||||
case ME_CAMERA1TO3:
|
||||
if (bMovingCamera) {
|
||||
TheMessage->flags |= MP_WAIT_CAMERA;
|
||||
ReEvent();
|
||||
}
|
||||
if (Player == nullptr) break;
|
||||
|
||||
mHide = true;
|
||||
bFirstPerson = false;
|
||||
|
||||
// CharStop( Player );
|
||||
ClearText();
|
||||
|
||||
if (FromFirstPersonAnim)
|
||||
CharGotoPosition(game, ocCURPLAYER, init.Anim[FromFirstPersonAnim].pos, 0, FromFirstPersonAnim);
|
||||
DestCamera = LastCamera;
|
||||
if (TheMessage->bparam) DestCamera = t3dCurCamera;
|
||||
LastCamera = &FirstPersonCamera;
|
||||
// DestCamera->Fov = CAMERA_FOV;
|
||||
LastCamera->Fov = CAMERA_FOV_1ST;
|
||||
|
||||
// Abilita la modalita' muovi camera
|
||||
bMovingCamera = true;
|
||||
|
||||
// Seleziona il punto di destinazione del Source
|
||||
t3dVectCopy(&Dest, &Player->Mesh->Trasl);
|
||||
Dest.y = CurFloorY + EYES_HEIGHT;
|
||||
t3dVectCopy(&FirstPersonCamera.Source, &Dest);
|
||||
// Calcola quanto deve muovere la camera
|
||||
dist = t3dVectDistance(&DestCamera->Source, &Dest);
|
||||
t3dVectSub(&Dir, &DestCamera->Source, &Dest);
|
||||
t3dVectNormalize(&Dir);
|
||||
Dir *= (dist / FIRST_PERSON_STEPS);
|
||||
|
||||
CurCameraStep = 0;
|
||||
CurCameraSubStep = 0;
|
||||
NumCameraSteps = FIRST_PERSON_STEPS;
|
||||
// Copia tutti i passi del percorso partendo dall'arrivo
|
||||
for (i = 0; i < NumCameraSteps; i++) {
|
||||
t3dVectCopy(&CameraStep[i].Source, &Dest);
|
||||
t3dVectAdd(&Dest, &Dest, &Dir);
|
||||
CameraStep[i].Fov = LastCamera->Fov + (t3dF32)(((DestCamera->Fov - LastCamera->Fov) * (t3dF32)i) / (t3dF32)NumCameraSteps);
|
||||
}
|
||||
// Azzera un po' di variabili
|
||||
t3dVectFill(&HeadAngles, 0.0f);
|
||||
CamAngleX = 0.0f;
|
||||
CamAngleY = 0.0f;
|
||||
// Avanza al primo frame del percorso
|
||||
NextCameraStep(game);
|
||||
|
||||
FromFirstPersonAnim = aNULL;
|
||||
if (Player)
|
||||
Player->Flags &= ~T3D_CHARACTER_HIDE;
|
||||
Player->Flags &= ~T3D_CHARACTER_ENABLEDINMIRROR;
|
||||
break;
|
||||
|
||||
case ME_CAMERAPLAYER:
|
||||
if (bMovingCamera) {
|
||||
TheMessage->flags |= MP_WAIT_CAMERA;
|
||||
ReEvent();
|
||||
}
|
||||
if ((Player == nullptr) || (t3dCurRoom->CameraGrid.Grid.empty())) break;
|
||||
|
||||
GetCameraTarget(init, &ct);
|
||||
col = (int16)((ct.x - t3dCurRoom->CameraGrid.TopLeft.x) / t3dCurRoom->CameraGrid.CellDim.x);
|
||||
row = (int16)((ct.z - t3dCurRoom->CameraGrid.TopLeft.z) / t3dCurRoom->CameraGrid.CellDim.z);
|
||||
if (((col < 0 || row < 0) || (col >= t3dCurRoom->CameraGrid.Col) || (row >= t3dCurRoom->CameraGrid.Row))) return;
|
||||
|
||||
t3dLastCameraIndex = t3dCurCameraIndex;
|
||||
t3dCurCameraIndex = t3dCurRoom->CameraGrid.Grid[col + row * t3dCurRoom->CameraGrid.Col];
|
||||
|
||||
mHide = true;
|
||||
bFirstPerson = false;
|
||||
ClearText();
|
||||
|
||||
LastCamera = t3dCurCamera;
|
||||
DestCamera = PickCamera(t3dCurRoom, t3dCurCameraIndex);
|
||||
// DestCamera->Fov = CAMERA_FOV;
|
||||
// LastCamera->Fov = CAMERA_FOV;
|
||||
|
||||
// Abilita la modalita' muovi camera
|
||||
bMovingCamera = true;
|
||||
|
||||
// Seleziona il punto di destinazione del Source
|
||||
t3dVectCopy(&Dest, &Player->Mesh->Trasl);
|
||||
Dest.y = CurFloorY + EYES_HEIGHT;
|
||||
|
||||
// Calcola quanto deve muovere la camera
|
||||
dist = t3dVectDistance(&DestCamera->Source, &Dest);
|
||||
t3dVectSub(&Dir, &DestCamera->Source, &Dest);
|
||||
t3dVectNormalize(&Dir);
|
||||
Dir *= (dist / FIRST_PERSON_STEPS);
|
||||
|
||||
CurCameraStep = 0;
|
||||
CurCameraSubStep = 0;
|
||||
NumCameraSteps = FIRST_PERSON_STEPS;
|
||||
// Copia tutti i passi del percorso partendo dall'arrivo
|
||||
for (i = 0; i < NumCameraSteps; i++) {
|
||||
t3dVectCopy(&CameraStep[i].Source, &Dest);
|
||||
t3dVectAdd(&Dest, &Dest, &Dir);
|
||||
CameraStep[i].Fov = LastCamera->Fov + (t3dF32)(((DestCamera->Fov - LastCamera->Fov) * (t3dF32)i) / (t3dF32)NumCameraSteps);
|
||||
}
|
||||
// Azzera un po' di variabili
|
||||
t3dVectFill(&HeadAngles, 0.0f);
|
||||
CamAngleX = 0.0f;
|
||||
CamAngleY = 0.0f;
|
||||
// Avanza al primo frame del percorso
|
||||
NextCameraStep(game);
|
||||
|
||||
FromFirstPersonAnim = aNULL;
|
||||
if (Player)
|
||||
Player->Flags &= ~T3D_CHARACTER_HIDE;
|
||||
Player->Flags &= ~T3D_CHARACTER_ENABLEDINMIRROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------09/11/98 10.27-------------------
|
||||
* ResetCameraSource
|
||||
* --------------------------------------------------*/
|
||||
void CameraMan::ResetCameraSource() {
|
||||
resetLastCameraIndex();
|
||||
t3dCurCameraIndex = 255;
|
||||
}
|
||||
|
||||
/* -----------------09/11/98 10.27-------------------
|
||||
* ResetCameraTarget
|
||||
* --------------------------------------------------*/
|
||||
void CameraMan::ResetCameraTarget() {
|
||||
t3dVectFill(&OldCameraTarget, 0.0f);
|
||||
}
|
||||
|
||||
/* -----------------09/11/98 10.32-------------------
|
||||
* ClipCameraMove
|
||||
* --------------------------------------------------*/
|
||||
uint8 ClipCameraMove(t3dV3F *NewT, t3dV3F *OldT, t3dV3F *Source) {
|
||||
t3dV3F n, o;
|
||||
t3dF32 a, d, l;
|
||||
|
||||
t3dVectSub(&n, NewT, Source);
|
||||
t3dVectSub(&o, OldT, Source);
|
||||
t3dVectNormalize(&n);
|
||||
t3dVectNormalize(&o);
|
||||
|
||||
a = t3dVectAngle(&o, &n);
|
||||
|
||||
if (a > MAX_CAMERA_ANGLE) d = (MAX_CAMERA_ANGLE * T3D_PI) / 180.0f;
|
||||
else if (a < -MAX_CAMERA_ANGLE) d = -(MAX_CAMERA_ANGLE * T3D_PI) / 180.0f;
|
||||
else return 0;
|
||||
|
||||
a = (a * T3D_PI) / 180.0f;
|
||||
t3dVectSub(&o, NewT, OldT);
|
||||
t3dVectNormalize(&o);
|
||||
l = (t3dVectDistance(NewT, OldT) * d) / a;
|
||||
o *= l;
|
||||
t3dVectAdd(NewT, OldT, &o);
|
||||
|
||||
/* t3dVectSub( &o, OldT, Source );
|
||||
t3dVectNormalize( &o );
|
||||
l = t3dVectDistance( OldT, Source );
|
||||
// l += ( ( l - t3dVectDistance( NewT, Source ) ) * d ) / a;
|
||||
t3dVectScale( &o, &o, l );
|
||||
|
||||
t3dMatRot( &m, 0.0f, d, 0.0f );
|
||||
t3dVectTransform( NewT, &o, &m );
|
||||
t3dVectAdd( NewT, NewT, Source );
|
||||
|
||||
NewT->y += ( ( NewT->y - OldT->y ) * d ) / a;
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------05/06/98 10.36-------------------
|
||||
* ProcessCamera
|
||||
* --------------------------------------------------*/
|
||||
void CameraMan::ProcessCamera(WGame &game) {
|
||||
t3dCAMERAPATH *cp = nullptr;
|
||||
t3dBODY *croom;
|
||||
int16 row, col, i;
|
||||
t3dV3F Dest, Dir;
|
||||
t3dF32 dist;
|
||||
int32 a, b;
|
||||
t3dV3F ct;
|
||||
int8 cd;
|
||||
uint8 cc;
|
||||
int32 foxOldRoom;
|
||||
Init &init = game.init;
|
||||
|
||||
if (bMovingCamera && !PortalCrossed) { // Se la camera si sta muovendo
|
||||
NextCameraStep(game);
|
||||
return ;
|
||||
}
|
||||
if (bFirstPerson && !PortalCrossed) { // se sono in prima persona non devo cambiare camera
|
||||
return;
|
||||
}
|
||||
|
||||
if (PortalCrossed != nullptr) { // Se ho cambiato stanza
|
||||
croom = PortalCrossed; // Nuova stanza
|
||||
t3dVectFill(&OldCameraTarget, 0.0f);
|
||||
bForceDirectCamera = TRUE;
|
||||
t3dCurCameraIndex = 255;
|
||||
resetLastCameraIndex();
|
||||
_vm->_messageSystem.addWaitingMsgs(MP_WAIT_PORTAL);
|
||||
// DebugLogFile("PortalCrossed %s",PortalCrossed->Name);
|
||||
// PortalCrossed = nullptr;
|
||||
if (bMovingCamera) {
|
||||
CurCameraStep = NumCameraSteps = 0;
|
||||
bMovingCamera = FALSE;
|
||||
DestCamera = nullptr;
|
||||
_vm->_messageSystem.addWaitingMsgs(MP_WAIT_CAMERA);
|
||||
}
|
||||
if (bFirstPerson)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_CAMERA, ME_CAMERA3TO1, MP_DEFAULT, 0, 0, 0, nullptr, nullptr, nullptr);
|
||||
// Fa partire animazione di link portali se l'ho attraversato con i tasti
|
||||
for (i = 0; i < (int16)t3dCurRoom->NumMeshes(); i++) {
|
||||
if (t3dCurRoom->MeshTable[i].PortalList == PortalCrossed) {
|
||||
for (a = 0; a < MAX_ANIMS_IN_ROOM; a++) {
|
||||
b = game.getCurRoom().anims[a];
|
||||
if ((b == aNULL) || !(init.Anim[b].flags & ANIM_PORTAL_LINK)) continue;
|
||||
|
||||
if (t3dCurRoom->MeshTable[i].name.equalsIgnoreCase((char *)init.Anim[b].RoomName.rawArray()) && (PlayerGotoPos[CurPlayer + ocDARRELL] != init.Anim[b].pos)) {
|
||||
if (!(init.Anim[b].flags & ANIM_NULL))
|
||||
CharGotoPosition(game, ocCURPLAYER, init.Anim[b].pos, 10, b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foxOldRoom = game._gameVars.getCurRoomId();
|
||||
game._gameVars.setCurRoomId(getRoomFromStr(init, croom->name));
|
||||
t3dCurRoom = PortalCrossed;
|
||||
PortalCrossed = nullptr;
|
||||
UpdateRoomVisibility(game);
|
||||
|
||||
if (Player && t3dCurRoom) {
|
||||
Player->Walk.Panel = t3dCurRoom->Panel[t3dCurRoom->CurLevel];
|
||||
Player->Walk.PanelNum = t3dCurRoom->NumPanels[t3dCurRoom->CurLevel];
|
||||
Player->Walk.CurPanel = -1;
|
||||
Player->Walk.OldPanel = -1;
|
||||
for (a = 0; a < Player->Walk.NumSteps; a++)
|
||||
Player->Walk.WalkSteps[a].curp = -1;
|
||||
CurFloorY = t3dCurRoom->PanelHeight[t3dCurRoom->CurLevel];
|
||||
}
|
||||
|
||||
|
||||
// Parte Morte Victoria se esce dalla r49 per andare nella r48 prima di aver attivato le leylines
|
||||
if (
|
||||
(game._gameVars.getCurRoomId() == r48) && (foxOldRoom == r49)
|
||||
&& (!(init.Dialog[dR491].flags & DIALOG_DONE))
|
||||
&& (!(LoaderFlags & T3D_DEBUGMODE))
|
||||
&& (!bDialogActive)
|
||||
) {
|
||||
// DebugLogFile("BECCATO222");
|
||||
CharStop(ocCURPLAYER);
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR48KRENNSPARA, 0, 0, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
// per sicurezza faccio sparire la bottiglia
|
||||
if (game._gameVars.getCurRoomId() == r25) {
|
||||
t3dMESH *m = LinkMeshToStr(init, "o25-fiaschetta");
|
||||
if (m) m->Flags |= T3D_MESH_HIDDEN;
|
||||
}
|
||||
|
||||
} else {
|
||||
croom = t3dCurRoom; // Stanza attuale
|
||||
if (ForcedCamera && bCutCamera) // Se ho settato un camera-cut
|
||||
bForceDirectCamera = TRUE;
|
||||
else
|
||||
bForceDirectCamera = FALSE;
|
||||
}
|
||||
|
||||
// Se non c'e' la griglia o non c'e' il personaggio o la camera attuale
|
||||
if ((croom->CameraGrid.Grid.empty()) || (Player == nullptr) || (t3dCurCamera == nullptr)) return;
|
||||
GetCameraTarget(init, &ct); // Si calcola quale sarebbe il Target giusto per la camera
|
||||
|
||||
// Se non devo spostare la camera esco subito
|
||||
if ((ct == OldCameraTarget) && (!ForcedCamera || (t3dCurCameraIndex == ForcedCamera - 1))) {
|
||||
if ((CamAngleX != 0.0f) || (CamAngleY != 0.0f))
|
||||
t3dRotateMoveCamera(t3dCurCamera, CamAngleX, CamAngleY, 0.0f);
|
||||
return ;
|
||||
}
|
||||
if (!bFirstPerson) t3dVectFill(&HeadAngles, 0.0f);
|
||||
// Mi calcolo in che casella sta l'omino
|
||||
col = (int16)((ct.x - croom->CameraGrid.TopLeft.x) / croom->CameraGrid.CellDim.x);
|
||||
row = (int16)((ct.z - croom->CameraGrid.TopLeft.z) / croom->CameraGrid.CellDim.z);
|
||||
// Se la camera si muoverebbe troppo, riduce il movimento
|
||||
if (!bForceDirectCamera) ClipCameraMove(&ct, &t3dCurCamera->Target, &t3dCurCamera->Source);
|
||||
// Se sono in un dialogo elimina la gestione del trova-camera
|
||||
if (!ForcedCamera && bDialogActive) return ;
|
||||
// Aggiorno Camera
|
||||
t3dVectCopy(&t3dCurCamera->Target, &ct);
|
||||
t3dVectCopy(&OldCameraTarget, &ct);
|
||||
// Se e' un carrello, aggiorno carrello
|
||||
if (bCameraCarrello) HandleCameraCarrello(croom); // Se carrello attivo, riposiziona il source
|
||||
// Se non e' valida esco
|
||||
if (!ForcedCamera && ((col < 0 || row < 0) || (col >= croom->CameraGrid.Col) || (row >= croom->CameraGrid.Row))) return;
|
||||
// Prendo l'indice della nuova stanza e se e' in una zona libera esce
|
||||
cc = croom->CameraGrid.Grid[col + row * croom->CameraGrid.Col];
|
||||
// Se e' in zona libera e la vecchia telecamera era in zona libera, ricerca a spirale
|
||||
if ((cc == 255) && (t3dLastCameraIndex == 255)) {
|
||||
for (a = 1; a < 10; a++) {
|
||||
for (b = -a; b <= a; b++) {
|
||||
if ((col + b) >= 0 || (row + a) >= 0 || (col + b) < croom->CameraGrid.Col || (row + a) < croom->CameraGrid.Row)
|
||||
if ((cc = croom->CameraGrid.Grid[col + b + (row + a) * croom->CameraGrid.Col]) != 255) break;
|
||||
if ((col + b) >= 0 || (row - a) >= 0 || (col + b) < croom->CameraGrid.Col || (row - a) < croom->CameraGrid.Row)
|
||||
if ((cc = croom->CameraGrid.Grid[col + b + (row - a) * croom->CameraGrid.Col]) != 255) break;
|
||||
if ((col + a) >= 0 || (row + b) >= 0 || (col + a) < croom->CameraGrid.Col || (row + b) < croom->CameraGrid.Row)
|
||||
if ((cc = croom->CameraGrid.Grid[col + a + (row + b) * croom->CameraGrid.Col]) != 255) break;
|
||||
if ((col - a) >= 0 || (row + b) >= 0 || (col - a) < croom->CameraGrid.Col || (row + b) < croom->CameraGrid.Row)
|
||||
if ((cc = croom->CameraGrid.Grid[col - a + (row + b) * croom->CameraGrid.Col]) != 255) break;
|
||||
}
|
||||
if (cc != 255) break;
|
||||
}
|
||||
}
|
||||
// Se resta sempre in una zona libera esce
|
||||
if (!ForcedCamera && (cc == 255)) return;
|
||||
// Mi salvo l'ultima posizione della camera e la posizione attuale
|
||||
t3dLastCameraIndex = t3dCurCameraIndex;
|
||||
// Se obbligo a prendre una camera particolare per l'animazione
|
||||
if (ForcedCamera) t3dCurCameraIndex = ForcedCamera - 1;
|
||||
else t3dCurCameraIndex = cc;
|
||||
// Se non deve cambiare camera ed e' nella stessa stanza esce
|
||||
if ((t3dCurCameraIndex == t3dLastCameraIndex) && !(bForceDirectCamera && !bCutCamera)) return;
|
||||
bCameraCarrello = FALSE;
|
||||
// Puntatore alla vecchia e alla nuova camera
|
||||
LastCamera = t3dCurCamera;
|
||||
DestCamera = PickCamera(croom, t3dCurCameraIndex);
|
||||
|
||||
// DestCamera->Fov = CAMERA_FOV;
|
||||
// LastCamera->Fov = CAMERA_FOV;
|
||||
|
||||
i = 255;
|
||||
// Cerca il percorso che mi porta la veccia camera nella nuova camera
|
||||
if (LastCamera->NumAvailablePaths() < 255)
|
||||
for (i = 0; i < LastCamera->NumAvailablePaths(); i++)
|
||||
if (LastCamera->CameraPaths[i].NumCamera == t3dCurCameraIndex)
|
||||
break;
|
||||
|
||||
// Se non lo trova o se deve cambiare la camera senza fare il percorso e non puo' calcolarselo
|
||||
if (((i >= LastCamera->NumAvailablePaths()) || (!LastCamera->NumAvailablePaths()) || bForceDirectCamera) && !bAllowCalcCamera) {
|
||||
// Setta la nuova camera ed esce
|
||||
t3dCurCamera = PickCamera(croom, t3dCurCameraIndex);
|
||||
GetCameraTarget(init, &t3dCurCamera->Target);
|
||||
// t3dCurCamera->Fov = CAMERA_FOV;
|
||||
game._renderer->setCurCameraViewport(t3dCurCamera->Fov, bSuperView);
|
||||
DestCamera = nullptr;
|
||||
bMovingCamera = FALSE;
|
||||
bForceDirectCamera = FALSE;
|
||||
// Se ho selezionato un carrello, riposiziona il source
|
||||
for (i = 0; i < t3dCurCamera->NumAvailablePaths(); i++)
|
||||
if (t3dCurCamera->CameraPaths[i].PathIndex & 0x80) {
|
||||
HandleCameraCarrello(croom);
|
||||
break;
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
// Se non trova percorsi e puo' calcolarsi il percorso
|
||||
if ((bAllowCalcCamera) && ((i >= LastCamera->NumAvailablePaths()) || (!LastCamera->NumAvailablePaths()))) {
|
||||
t3dVectCopy(&Dest, &DestCamera->Source);
|
||||
dist = t3dVectDistance(&LastCamera->Source, &Dest); // Calcola quanto deve muovere la camera
|
||||
t3dVectSub(&Dir, &LastCamera->Source, &Dest);
|
||||
t3dVectNormalize(&Dir);
|
||||
|
||||
CurCameraStep = 0;
|
||||
CurCameraSubStep = 0;
|
||||
NumCameraSteps = (int16)(dist / MAX_CAMERA_MOVE) + 1;
|
||||
if (NumCameraSteps > MAX_CAMERA_STEPS) NumCameraSteps = MAX_CAMERA_STEPS - 1;
|
||||
Dir *= (dist / NumCameraSteps);
|
||||
// Copia tutti i passi del percorso partendo dall'arrivo
|
||||
for (i = NumCameraSteps - 1; i >= 0; i--) {
|
||||
t3dVectCopy(&CameraStep[i].Source, &Dest);
|
||||
t3dVectAdd(&Dest, &Dest, &Dir);
|
||||
CameraStep[i].Fov = LastCamera->Fov + (t3dF32)(((DestCamera->Fov - LastCamera->Fov) * (t3dF32)i) / (t3dF32)NumCameraSteps);
|
||||
}
|
||||
|
||||
if (CameraTargetObj == oCAMERAMAX) { // Se deve mantenere il target di max
|
||||
t3dVectCopy(&Dest, &DestCamera->MaxTarget);
|
||||
dist = t3dVectDistance(&LastCamera->Target, &Dest); // Calcola quanto deve muovere il target
|
||||
t3dVectSub(&Dir, &LastCamera->Target, &Dest);
|
||||
t3dVectNormalize(&Dir);
|
||||
Dir *= (dist / NumCameraSteps);
|
||||
for (i = NumCameraSteps - 1; i >= 0; i--) {
|
||||
t3dVectCopy(&CameraStep[i].MaxTarget, &Dest);
|
||||
t3dVectCopy(&CameraStep[i].Target, &Dest);
|
||||
t3dVectAdd(&Dest, &Dest, &Dir);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cp = &croom->CameraPath[(LastCamera->CameraPaths[i].PathIndex) & 0x7F];
|
||||
cd = LastCamera->CameraPaths[i].Direction;
|
||||
|
||||
CurCameraStep = 0;
|
||||
CurCameraSubStep = 0;
|
||||
NumCameraSteps = cp->NumPoints();
|
||||
if (NumCameraSteps > MAX_CAMERA_STEPS) NumCameraSteps = MAX_CAMERA_STEPS - 1;
|
||||
for (i = 0; i < NumCameraSteps; i++) { // Copia tutti i passi del percorso
|
||||
if (cd == 0)
|
||||
t3dVectCopy(&CameraStep[i].Source, &cp->PList[cp->NumPoints() - 1 - i]);
|
||||
else
|
||||
t3dVectCopy(&CameraStep[i].Source, &cp->PList[i]);
|
||||
|
||||
CameraStep[i].Fov = LastCamera->Fov + (t3dF32)(((DestCamera->Fov - LastCamera->Fov) * (t3dF32)i) / (t3dF32)NumCameraSteps);
|
||||
}
|
||||
}
|
||||
bMovingCamera = TRUE; // Abilita la modalita' muovi camera
|
||||
NextCameraStep(game); // Avanza al primo frame del percorso
|
||||
}
|
||||
|
||||
/* -----------------16/12/00 15.20-------------------
|
||||
* GetCameraIndexUnderPlayer
|
||||
* --------------------------------------------------*/
|
||||
uint8 CameraMan::GetCameraIndexUnderPlayer(int32 pl) {
|
||||
t3dBODY *croom;
|
||||
int16 row, col;
|
||||
int32 a, b;
|
||||
t3dV3F ct;
|
||||
uint8 cc;
|
||||
|
||||
croom = t3dCurRoom; // Stanza attuale
|
||||
if ((!croom) || (!Character[pl])) return (255);
|
||||
|
||||
// Se non c'e' la griglia o non c'e' il personaggio o la camera attuale
|
||||
if (croom->CameraGrid.Grid.empty()) return (255);
|
||||
|
||||
t3dVectCopy(&ct, &Character[pl]->Mesh->Trasl);
|
||||
// Mi calcolo in che casella sta l'omino
|
||||
col = (int16)((ct.x - croom->CameraGrid.TopLeft.x) / croom->CameraGrid.CellDim.x);
|
||||
row = (int16)((ct.z - croom->CameraGrid.TopLeft.z) / croom->CameraGrid.CellDim.z);
|
||||
// Aggiorno Camera
|
||||
// Se non e' valida esco
|
||||
if (((col < 0 || row < 0) || (col >= croom->CameraGrid.Col) || (row >= croom->CameraGrid.Row))) return (255);
|
||||
// Prendo l'indice della nuova stanza e se e' in una zona libera esce
|
||||
cc = croom->CameraGrid.Grid[col + row * croom->CameraGrid.Col];
|
||||
// Se e' in zona libera e la vecchia telecamera era in zona libera, ricerca a spirale
|
||||
if (cc == 255) {
|
||||
for (a = 1; a < 10; a++) {
|
||||
for (b = -a; b <= a; b++) {
|
||||
if ((col + b) >= 0 || (row + a) >= 0 || (col + b) < croom->CameraGrid.Col || (row + a) < croom->CameraGrid.Row)
|
||||
if ((cc = croom->CameraGrid.Grid[col + b + (row + a) * croom->CameraGrid.Col]) != 255) break;
|
||||
if ((col + b) >= 0 || (row - a) >= 0 || (col + b) < croom->CameraGrid.Col || (row - a) < croom->CameraGrid.Row)
|
||||
if ((cc = croom->CameraGrid.Grid[col + b + (row - a) * croom->CameraGrid.Col]) != 255) break;
|
||||
if ((col + a) >= 0 || (row + b) >= 0 || (col + a) < croom->CameraGrid.Col || (row + b) < croom->CameraGrid.Row)
|
||||
if ((cc = croom->CameraGrid.Grid[col + a + (row + b) * croom->CameraGrid.Col]) != 255) break;
|
||||
if ((col - a) >= 0 || (row + b) >= 0 || (col - a) < croom->CameraGrid.Col || (row + b) < croom->CameraGrid.Row)
|
||||
if ((cc = croom->CameraGrid.Grid[col - a + (row + b) * croom->CameraGrid.Col]) != 255) break;
|
||||
}
|
||||
if (cc != 255) break;
|
||||
}
|
||||
}
|
||||
|
||||
return (cc);
|
||||
}
|
||||
|
||||
/* -----------------08/10/98 18.08-------------------
|
||||
* StartAnimCamera
|
||||
* --------------------------------------------------*/
|
||||
void CameraMan::StartAnimCamera(WGame &game) {
|
||||
DebugLogFile("StartAnimCamera");
|
||||
t3dLastCameraIndex = t3dCurCameraIndex;
|
||||
if (ForcedCamera) t3dCurCameraIndex = ForcedCamera - 1;
|
||||
|
||||
LastCamera = t3dCurCamera;
|
||||
DestCamera = PickCamera(t3dCurRoom, t3dCurCameraIndex);
|
||||
AnimCamera = *DestCamera;
|
||||
t3dCurCamera = &AnimCamera;
|
||||
|
||||
game._renderer->setCurCameraViewport(t3dCurCamera->Fov, bSuperView);
|
||||
|
||||
bCameraCarrello = FALSE;
|
||||
bCutCamera = FALSE;
|
||||
bAllowCalcCamera = FALSE;
|
||||
bMovingCamera = 2;
|
||||
|
||||
NextCameraStep(game);
|
||||
}
|
||||
|
||||
/* -----------------09/11/98 10.32-------------------
|
||||
* ClipGolfCameraMove
|
||||
* --------------------------------------------------*/
|
||||
uint8 CameraMan::ClipGolfCameraMove(t3dV3F *NewT, t3dV3F *OldT, t3dV3F *Source) {
|
||||
t3dV3F n, o;
|
||||
t3dF32 a, d, l;
|
||||
|
||||
t3dVectSub(&n, NewT, Source);
|
||||
t3dVectSub(&o, OldT, Source);
|
||||
t3dVectNormalize(&n);
|
||||
t3dVectNormalize(&o);
|
||||
|
||||
a = t3dVectAngle(&o, &n);
|
||||
|
||||
if (a > MAX_CAMERA_ANGLE / 3) d = (MAX_CAMERA_ANGLE / 3 * T3D_PI) / 180.0f;
|
||||
else if (a < -MAX_CAMERA_ANGLE / 3) d = -(MAX_CAMERA_ANGLE / 3 * T3D_PI) / 180.0f;
|
||||
else return 0;
|
||||
|
||||
a = (a * T3D_PI) / 180.0f;
|
||||
t3dVectSub(&o, NewT, OldT);
|
||||
t3dVectNormalize(&o);
|
||||
l = (t3dVectDistance(NewT, OldT) * d) / a;
|
||||
o *= l;
|
||||
t3dVectAdd(NewT, OldT, &o);
|
||||
|
||||
/* t3dVectSub( &o, OldT, Source );
|
||||
t3dVectNormalize( &o );
|
||||
l = t3dVectDistance( OldT, Source );
|
||||
// l += ( ( l - t3dVectDistance( NewT, Source ) ) * d ) / a;
|
||||
t3dVectScale( &o, &o, l );
|
||||
|
||||
t3dMatRot( &m, 0.0f, d, 0.0f );
|
||||
t3dVectTransform( NewT, &o, &m );
|
||||
t3dVectAdd( NewT, NewT, Source );
|
||||
|
||||
NewT->y += ( ( NewT->y - OldT->y ) * d ) / a;
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
73
engines/watchmaker/classes/do_camera.h
Normal file
73
engines/watchmaker/classes/do_camera.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_CAMERA_H
|
||||
#define WATCHMAKER_DO_CAMERA_H
|
||||
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
class CameraMan {
|
||||
// Constants:
|
||||
static const int MAX_CAMERA_STEPS = 500;
|
||||
|
||||
t3dCAMERA FirstPersonCamera, *DestCamera, *LastCamera, CameraCarrello;
|
||||
t3dCAMERA CameraStep[MAX_CAMERA_STEPS], AnimCamera;
|
||||
int16 CurCameraSubStep = 0, CurCameraStep = 0, NumCameraSteps = 0;
|
||||
t3dV3F OldCameraTarget, OldPlayerDir, FirstPersonTarget;
|
||||
t3dV3F SourceBlend, TargetBlend;
|
||||
|
||||
|
||||
uint8 bForceDirectCamera = false, bCameraCarrello = false;
|
||||
|
||||
uint8 t3dCurCameraIndex = 255;
|
||||
uint8 t3dLastCameraIndex = 255;
|
||||
|
||||
void NextCameraStep(WGame &game);
|
||||
void HandleCameraCarrello(t3dBODY *croom);
|
||||
public:
|
||||
t3dV3F HeadAngles;
|
||||
t3dF32 CamAngleX, CamAngleY;
|
||||
|
||||
void resetAngle();
|
||||
void resetLastCameraIndex() { t3dLastCameraIndex = 255; }
|
||||
uint8 getCurCameraIndex() { return t3dCurCameraIndex; }
|
||||
|
||||
void MoveHeadAngles(t3dF32 diffx, t3dF32 diffy);
|
||||
void GetCameraTarget(Init &init, t3dV3F *Target);
|
||||
t3dCAMERA *PickCamera(t3dBODY *b, unsigned char in);
|
||||
void doCamera(WGame &game);
|
||||
void GetRealCharPos(Init &init, t3dV3F *Target, int32 oc, uint8 bn);
|
||||
void ResetCameraTarget();
|
||||
void ResetCameraSource();
|
||||
void ProcessCamera(WGame &game);
|
||||
uint8 GetCameraIndexUnderPlayer(int32 pl);
|
||||
void StartAnimCamera(WGame &game);
|
||||
uint8 ClipGolfCameraMove(t3dV3F *NewT, t3dV3F *OldT, t3dV3F *Source);
|
||||
};
|
||||
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_CAMERA_H
|
||||
540
engines/watchmaker/classes/do_dialog.cpp
Normal file
540
engines/watchmaker/classes/do_dialog.cpp
Normal file
@@ -0,0 +1,540 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_dialog.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/3d/loader.h"
|
||||
#include "watchmaker/3d/geometry.h"
|
||||
#include "watchmaker/3d/t3d_body.h"
|
||||
#include "watchmaker/schedule.h"
|
||||
#include "watchmaker/ll/ll_anim.h"
|
||||
#include "watchmaker/walk/act.h"
|
||||
#include "watchmaker/ll/ll_diary.h"
|
||||
#include "watchmaker/ll/ll_util.h"
|
||||
#include "watchmaker/classes/do_player.h"
|
||||
#include "watchmaker/main.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/classes/do_inv.h"
|
||||
#include "watchmaker/ll/ll_string.h"
|
||||
#include "watchmaker/classes/do_system.h"
|
||||
#include "watchmaker/classes/do_camera.h"
|
||||
#include "watchmaker/classes/do_string.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
// locals
|
||||
int32 DebugSent = 0;
|
||||
int16 NextDlg = dNULL;
|
||||
int32 ic1, ic2;
|
||||
|
||||
/* -----------------03/06/98 10.11-------------------
|
||||
* doDialog
|
||||
* --------------------------------------------------*/
|
||||
void doDialog(WGame &game) {
|
||||
Init &init = game.init;
|
||||
struct SItemCommand *ic;
|
||||
uint8 r;
|
||||
|
||||
switch (TheMessage->event) {
|
||||
case ME_DIALOGSTART:
|
||||
if (TheMessage->wparam1 == dR391) {
|
||||
if (Character[ocCHIRURGO]->Mesh)
|
||||
t3dVectFill(&Character[ocCHIRURGO]->Mesh->Trasl, 0.0f);
|
||||
if (Character[ocVECCHIO]->Mesh)
|
||||
t3dVectFill(&Character[ocVECCHIO]->Mesh->Trasl, 0.0f);
|
||||
if (Character[ocOROLOGIAIO]->Mesh)
|
||||
t3dVectFill(&Character[ocOROLOGIAIO]->Mesh->Trasl, 0.0f);
|
||||
if (Character[ocTRADUTTORE]->Mesh)
|
||||
t3dVectFill(&Character[ocTRADUTTORE]->Mesh->Trasl, 0.0f);
|
||||
|
||||
bSuperView = 1;
|
||||
game._renderer->setCurCameraViewport(t3dCurCamera->Fov, bSuperView);
|
||||
}
|
||||
|
||||
//faccio apparire la scritta di descrizione della stanza di Darrell
|
||||
if ((TheMessage->wparam1 == dR000) && bShowRoomDescriptions) {
|
||||
t3dCurTime = 240;
|
||||
RoomInfo.name[0] = '\0';
|
||||
UpdateRoomInfo(game);
|
||||
}
|
||||
|
||||
// I make darrell disappear
|
||||
if ((TheMessage->wparam1 == dRLOGHI) || (TheMessage->wparam1 == dR000)) {
|
||||
Character[ocDARRELL]->Flags |= T3D_CHARACTER_HIDE; //I hide darrell to make sure he doesn't show while he loads the animations
|
||||
}
|
||||
|
||||
if ((init.Dialog[TheMessage->wparam1].flags & DIALOG_ONCE) && (init.Dialog[TheMessage->wparam1].flags & DIALOG_DONE))
|
||||
return ;
|
||||
|
||||
StopDiary(game, game._gameVars.getCurRoomId(), init.Dialog[TheMessage->wparam1].obj, 0);
|
||||
CurDialog = TheMessage->wparam1;
|
||||
bDialogActive = true;
|
||||
bDialogMenuActive = true;
|
||||
|
||||
CurDlgItem = -1;
|
||||
CurMenu = mMAIN;
|
||||
InvStatus = INV_OFF;
|
||||
BigInvObj = iNULL;
|
||||
NextDlg = dNULL;
|
||||
ClearUseWith();
|
||||
ClearText();
|
||||
CharStop(ocCURPLAYER);
|
||||
|
||||
if (bFirstPerson)
|
||||
game._renderer->setCurCameraViewport(74, bSuperView);
|
||||
|
||||
bDialogMenuActive = false;
|
||||
//DebugFile("DLG: StartDialog %d",CurDialog);
|
||||
// Se sono in un fullmotion
|
||||
if ((init.Dialog[CurDialog].flags & DIALOG_RTV2) && (init.Dialog[CurDialog].ItemIndex[mRTV2]))
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGCONTINUE, MP_DEFAULT, (int16)CurDialog, mRTV2, 0, nullptr, nullptr, nullptr);
|
||||
else if ((init.Dialog[CurDialog].flags & DIALOG_RTV3) && (init.Dialog[CurDialog].ItemIndex[mRTV3]))
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGCONTINUE, MP_DEFAULT, (int16)CurDialog, mRTV3, 0, nullptr, nullptr, nullptr);
|
||||
else if ((init.Dialog[CurDialog].flags & DIALOG_RTV) || (init.Dialog[CurDialog].ItemIndex[mRTV]))
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGCONTINUE, MP_DEFAULT, (int16)CurDialog, mRTV, 0, nullptr, nullptr, nullptr);
|
||||
// Se c'e' un predialog attivo
|
||||
else if (init.Dialog[CurDialog].flags & (DIALOG_PRE1 | DIALOG_PRE2 | DIALOG_PRE3 | DIALOG_PRE4)) {
|
||||
if (init.Dialog[CurDialog].flags & DIALOG_PRE_RAND)
|
||||
while (!(init.Dialog[CurDialog].flags & (DIALOG_PRE1 << (r = (game._rnd->getRandomNumber(3))))));
|
||||
else if (init.Dialog[CurDialog].flags & DIALOG_PRE1) r = 0;
|
||||
else if (init.Dialog[CurDialog].flags & DIALOG_PRE2) r = 1;
|
||||
else if (init.Dialog[CurDialog].flags & DIALOG_PRE3) r = 2;
|
||||
else r = 3;
|
||||
|
||||
if (init.Dialog[CurDialog].ItemIndex[mPREDIALOG1 + r])
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGCONTINUE, MP_DEFAULT, (int16)CurDialog, (int16)(mPREDIALOG1 + r), 0, nullptr, nullptr, nullptr);
|
||||
else
|
||||
bDialogMenuActive = true;
|
||||
} else
|
||||
bDialogMenuActive = true;
|
||||
|
||||
break;
|
||||
|
||||
case ME_DIALOGCONTINUE:
|
||||
CurDialog = TheMessage->wparam1;
|
||||
CurDlgItem = TheMessage->wparam2;
|
||||
bDialogMenuActive = false;
|
||||
|
||||
ic = &init.DlgItem[init.Dialog[CurDialog].ItemIndex[CurDlgItem]].item[CurPlayer][TheMessage->lparam[0]];
|
||||
// Finche' non ci sono comandi che deve aspettare tempo, li fa tutti
|
||||
while (ic->com) {
|
||||
TheMessage->lparam[0] ++;
|
||||
// DebugLogFile("IC %d %d %d | %d %d %d",ic->com,ic->param1,ic->param2,CurDialog,CurDlgItem,TheMessage->lparam[0]);
|
||||
switch (ic->com) {
|
||||
case IC_NULL: // Esce dal dialogo
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGEND, MP_DEFAULT, 0, 0, 0, nullptr, nullptr, nullptr);
|
||||
break;
|
||||
case IC_SET_PLAYER: // non fa niente
|
||||
break;
|
||||
case IC_ANIM:
|
||||
//DebugFile("DLG: StartAnim %d",ic->param1);
|
||||
StartAnim(game, GetAlternateAnim(init, ic->param1));
|
||||
break;
|
||||
case IC_SET_CAMERA:
|
||||
ForcedCamera = GetAlternateCamera(init, (uint8)ic->param1);
|
||||
bCutCamera = true;
|
||||
bAllowCalcCamera = false;
|
||||
break;
|
||||
case IC_MOVE_CAMERA_TO:
|
||||
ForcedCamera = GetAlternateCamera(init, (uint8)ic->param1);
|
||||
bCutCamera = false;
|
||||
bAllowCalcCamera = true;
|
||||
break;
|
||||
case IC_SET_TARGET:
|
||||
CameraTargetObj = ic->param1;
|
||||
CameraTargetBone = ic->param2;
|
||||
break;
|
||||
case IC_SET_CHAR:
|
||||
CharSetPosition(ic->param1, GetAlternatePosition(init, (uint8)ic->param2), nullptr);
|
||||
CharStop(ic->param1);
|
||||
break;
|
||||
case IC_WALK_CHAR:
|
||||
case IC_RUN_CHAR:
|
||||
case IC_BACK_CHAR:
|
||||
CharGotoPosition(game, ic->param1, GetAlternatePosition(init, (uint8)ic->param2), (uint8)(ic->com - IC_WALK_CHAR), 0);
|
||||
TimeWalk = 0;
|
||||
break;
|
||||
case IC_HIDE_CHAR:
|
||||
Character[ic->param1]->Flags |= T3D_CHARACTER_HIDE;
|
||||
break;
|
||||
case IC_UNHIDE_CHAR:
|
||||
Character[ic->param1]->Flags &= ~T3D_CHARACTER_HIDE;
|
||||
break;
|
||||
case IC_CHANGE_ROOM:
|
||||
ChangeRoom(game, Common::String::format("%s.t3d", init.Room[ic->param1].name), 0, aNULL);
|
||||
break;
|
||||
case IC_EXPRESSION:
|
||||
if (Character[ic->param1])
|
||||
Character[ic->param1]->CurExpressionSet = ic->param2;
|
||||
break;
|
||||
case IC_CHANGE_PLAYER:
|
||||
UpdatePlayerStand(game, (uint8)(CurPlayer + ocDARRELL));
|
||||
CurPlayer = (ic->param1 == ocDARRELL) ? DARRELL : VICTORIA;
|
||||
Character[ocCURPLAYER] = Character[ic->param1];
|
||||
Player = Character[ocCURPLAYER];
|
||||
Player->Flags &= ~T3D_CHARACTER_HIDE;
|
||||
break;
|
||||
case IC_DEBUG:
|
||||
DebugSent = ic->param1;
|
||||
break;
|
||||
case IC_ITEM:
|
||||
init.DlgMenu[ic->param1].on = (uint8)ic->param2;
|
||||
break;
|
||||
case IC_SET_FLAGS:
|
||||
if (ic->param1 != dNULL)
|
||||
init.Dialog[ic->param1].flags |= ic->param2;
|
||||
else
|
||||
init.Dialog[CurDialog].flags |= ic->param2;
|
||||
break;
|
||||
case IC_CLR_FLAGS:
|
||||
if (ic->param1 != dNULL)
|
||||
init.Dialog[ic->param1].flags &= ~ic->param2;
|
||||
else
|
||||
init.Dialog[CurDialog].flags &= ~ic->param2;
|
||||
break;
|
||||
case IC_ATFRAME:
|
||||
init.Anim[aDUMMY].atframe[0].type = (uint8)ic->param1;
|
||||
init.Anim[aDUMMY].atframe[0].index = ic->param2;
|
||||
init.Anim[aDUMMY].active = 12;
|
||||
ProcessATF(game, aDUMMY, 0);
|
||||
init.Anim[aDUMMY].active = 0;
|
||||
break;
|
||||
case IC_NEXT_DLG:
|
||||
NextDlg = (int16)ic->param1;
|
||||
break;
|
||||
case IC_SET_CHAR2:
|
||||
if (CurAlternate[ic->param1]) break;
|
||||
CharSetPosition(ic->param1, GetAlternatePosition(init, (uint8)ic->param2), nullptr);
|
||||
CharStop(ic->param1);
|
||||
break;
|
||||
case IC_INTRO_TEXT1:
|
||||
ic1 = ic->param1;
|
||||
ic2 = ic->param2;
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_SYSTEM, ME_STARTEFFECT, MP_DEFAULT, FRAME_PER_SECOND, FRAME_PER_SECOND, EFFECT_FADEOUT_T1, &ic1, nullptr, nullptr);
|
||||
if (ic2)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_SYSTEM, ME_STARTEFFECT, MP_WAITA, FRAME_PER_SECOND, FRAME_PER_SECOND, EFFECT_MOVEIN_T1, &ic1, nullptr, &ic2);
|
||||
break;
|
||||
case IC_INTRO_TEXT2:
|
||||
ic1 = ic->param1;
|
||||
ic2 = ic->param2;
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_SYSTEM, ME_STARTEFFECT, MP_DEFAULT, FRAME_PER_SECOND, FRAME_PER_SECOND, EFFECT_FADEOUT_T2, &ic1, nullptr, nullptr);
|
||||
if (ic2)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_SYSTEM, ME_STARTEFFECT, MP_WAITA, FRAME_PER_SECOND, FRAME_PER_SECOND, EFFECT_MOVEIN_T2, &ic1, nullptr, &ic2);
|
||||
break;
|
||||
|
||||
case IC_TIME_ANIM:
|
||||
//DebugFile("DLG: StartTimeAnim %d %d",ic->param1,ic->param2);
|
||||
AnimAutoPush = ic->param2;
|
||||
StartAnim(game, GetAlternateAnim(init, ic->param1));
|
||||
TheMessage->flags |= MP_WAIT_ANIM;
|
||||
TimeAnim = GetAlternateAnim(init, ic->param1);
|
||||
ReEvent();
|
||||
return ;
|
||||
case IC_TIME_ANIM2:
|
||||
//DebugFile("DLG: StartTimeAnim %d %d",ic->param1,ic->param2);
|
||||
StartAnim(game, GetAlternateAnim(init, ic->param1));
|
||||
TheMessage->flags |= MP_WAIT_ANIM;
|
||||
TimeAnim = GetAlternateAnim(init, ic->param1);
|
||||
ReEvent();
|
||||
return ;
|
||||
case IC_TIME_WALK_CHAR:
|
||||
case IC_TIME_RUN_CHAR:
|
||||
case IC_TIME_BACK_CHAR:
|
||||
if (!CharGotoPosition(game, ic->param1, GetAlternatePosition(init, (uint8)ic->param2), (uint8)(ic->com - IC_TIME_WALK_CHAR), 0)) break;
|
||||
TimeWalk = ic->param1;
|
||||
TheMessage->flags |= MP_WAIT_ACT;
|
||||
ReEvent();
|
||||
return ;
|
||||
case IC_TIME_WAIT_CAMERA:
|
||||
TheMessage->flags |= MP_WAIT_CAMERA;
|
||||
ReEvent();
|
||||
return ;
|
||||
case IC_TIME_WAIT:
|
||||
if (TheMessage->lparam[1] == 0) {
|
||||
TheMessage->lparam[1] = ic->param1;
|
||||
if (DebugSent && (LoaderFlags & T3D_DEBUGMODE)) PlayerSpeak(game, DebugSent);
|
||||
}
|
||||
if (TheMessage->lparam[1] > 1) {
|
||||
TheMessage->lparam[0] --;
|
||||
TheMessage->lparam[1] --;
|
||||
TheMessage->flags |= MP_WAIT_RETRACE;
|
||||
ReEvent();
|
||||
return;
|
||||
}
|
||||
TheMessage->lparam[1] = 0;
|
||||
bSkipTalk = false;
|
||||
DebugSent = 0;
|
||||
break;
|
||||
case IC_TIME_FADOUT:
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_SYSTEM, ME_STARTEFFECT, MP_DEFAULT, ic->param1, 1, EFFECT_FADOUT, nullptr, nullptr, nullptr);
|
||||
TheMessage->flags |= MP_WAITA;
|
||||
ReEvent();
|
||||
return ;
|
||||
}
|
||||
ic = &init.DlgItem[init.Dialog[CurDialog].ItemIndex[CurDlgItem]].item[CurPlayer][TheMessage->lparam[0]];
|
||||
}
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGEND, MP_DEFAULT, (int16)CurDialog, (int16)CurDlgItem, 0, nullptr, nullptr, nullptr);
|
||||
break;
|
||||
|
||||
case ME_DIALOGEND:
|
||||
case ME_DIALOGEND_SKIPINTRO:
|
||||
if (TheMessage->wparam1 == dR391) {
|
||||
bSuperView = 0;
|
||||
game._renderer->setCurCameraViewport(t3dCurCamera->Fov, bSuperView);
|
||||
NextDlg = dR391_end;
|
||||
}
|
||||
|
||||
CurDialog = TheMessage->wparam1;
|
||||
CurDlgItem = TheMessage->wparam2;
|
||||
game._messageSystem.removeEvent(EventClass::MC_DIALOG, ME_ALL);
|
||||
// Se c'e' un enddialog attivo
|
||||
if ((CurDlgItem == mQUIT) && (init.Dialog[CurDialog].flags & (DIALOG_END1 | DIALOG_END2 | DIALOG_END3))) {
|
||||
if (init.Dialog[CurDialog].flags & DIALOG_END_RAND)
|
||||
while (!(init.Dialog[CurDialog].flags & (DIALOG_END1 << (r = (game._rnd->getRandomNumber(2))))));
|
||||
else if (init.Dialog[CurDialog].flags & DIALOG_END1) r = 0;
|
||||
else if (init.Dialog[CurDialog].flags & DIALOG_END2) r = 1;
|
||||
else r = 2;
|
||||
|
||||
if (init.Dialog[CurDialog].ItemIndex[mENDDIALOG1 + r]) {
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGCONTINUE, MP_DEFAULT, (int16)(CurDialog), (int16)(mENDDIALOG1 + r), 0, nullptr, nullptr, nullptr);
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
if ((CurDlgItem == mRTV) || (CurDlgItem == mRTV2) || (CurDlgItem == mRTV3) || (CurDlgItem == mQUIT) ||
|
||||
(CurDlgItem == mENDDIALOG1) || (CurDlgItem == mENDDIALOG2) || (CurDlgItem == mENDDIALOG3)) {
|
||||
//DebugFile("DLG: EndDialog %d",CurDialog);
|
||||
StopObjAnim(game, ocCURPLAYER);
|
||||
CharStop(ocCURPLAYER); //evito che negli interrupt (in particolare) rimanga in memoria l'animazione di ascolta
|
||||
game._cameraMan->ResetCameraTarget();
|
||||
init.Dialog[CurDialog].flags |= DIALOG_DONE;
|
||||
CurDialog = dNULL;
|
||||
bDialogActive = false;
|
||||
bDialogMenuActive = false;
|
||||
bAnimWaitText = false;
|
||||
CurDlgItem = -1;
|
||||
CurMenu = mNULL;
|
||||
ForcedCamera = 0;
|
||||
bCutCamera = false;
|
||||
bAllowCalcCamera = false;
|
||||
CameraTargetObj = ocCURPLAYER;
|
||||
CameraTargetBone = 0;
|
||||
TimeWalk = ocCURPLAYER;
|
||||
TimeAnim = aNULL;
|
||||
bPlayerInAnim = false;
|
||||
if (NextDlg != dNULL)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, NextDlg, 0, 0, nullptr, nullptr, nullptr);
|
||||
else {
|
||||
if ((init.Dialog[TheMessage->wparam1].obj) && (Character[init.Dialog[TheMessage->wparam1].obj]))
|
||||
StartDiary(game, game._gameVars.getCurRoomId(), &Character[init.Dialog[TheMessage->wparam1].obj]->Mesh->Trasl);
|
||||
else
|
||||
StartDiary(game, game._gameVars.getCurRoomId(), nullptr);
|
||||
|
||||
DebugLogFile("EndDialog: resetto t3dLastCameraIndex");
|
||||
game._cameraMan->resetLastCameraIndex(); //forzo ProcessCamera() a cercare una nuova camera, in modo finito il dialogo non rimane qualche strana camera
|
||||
}
|
||||
} else
|
||||
bDialogMenuActive = true;
|
||||
|
||||
if (TheMessage->event == ME_DIALOGEND_SKIPINTRO)
|
||||
if (! DataLoad(game, "WmStart.dat", 0)) {
|
||||
DebugLogFile("SkipIntro: DataLoad() Failed. Quitting ...");
|
||||
CloseSys(game);
|
||||
}
|
||||
|
||||
if (TheMessage->wparam1 == dRLOGHI)
|
||||
ProcessATFDO(game, fSTART_MAIN_MENU);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------06/07/00 10.48-------------------
|
||||
* GetAlternatePosition
|
||||
* --------------------------------------------------*/
|
||||
uint8 GetAlternatePosition(Init &init, uint8 pos) {
|
||||
struct SDialog *d = &init.Dialog[CurDialog];
|
||||
int32 alt;
|
||||
|
||||
if (!d || !d->obj || !(alt = CurAlternate[d->obj])) return pos;
|
||||
|
||||
alt --;
|
||||
if (d->AltPosSco[alt]) return pos + d->AltPosSco[alt];
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/* -----------------06/07/00 10.49-------------------
|
||||
* GetAlternateCamera
|
||||
* --------------------------------------------------*/
|
||||
uint8 GetAlternateCamera(Init &init, uint8 cam) {
|
||||
struct SDialog *d = &init.Dialog[CurDialog];
|
||||
int32 alt;
|
||||
|
||||
if (!d || !d->obj || !(alt = CurAlternate[d->obj])) return cam;
|
||||
|
||||
alt --;
|
||||
if (d->AltCamSco[alt]) return cam + d->AltCamSco[alt];
|
||||
|
||||
return cam;
|
||||
}
|
||||
|
||||
/* -----------------06/07/00 10.49-------------------
|
||||
* GetAlternateAnim
|
||||
* --------------------------------------------------*/
|
||||
int32 GetAlternateAnim(Init &init, int32 an) {
|
||||
struct SDialog *d = &init.Dialog[CurDialog];
|
||||
int32 a, alt;
|
||||
|
||||
if (!d || !d->obj || !(alt = CurAlternate[d->obj])) return an;
|
||||
|
||||
alt --;
|
||||
for (a = 0; a < MAX_ALT_ANIMS; a++)
|
||||
if ((d->AltAnims[alt][a][0] == an) && (d->AltAnims[alt][a][1] != aNULL))
|
||||
return d->AltAnims[alt][a][1];
|
||||
|
||||
return an;
|
||||
}
|
||||
|
||||
/* -----------------03/06/98 11.31-------------------
|
||||
* UpdateDialogMenu
|
||||
* --------------------------------------------------*/
|
||||
void UpdateDialogMenu(WGame &game, int16 dmx, int16 dmy, uint8 db) {
|
||||
struct SRect t;
|
||||
int32 a, ca1, ca2;
|
||||
Init &init = game.init;
|
||||
Renderer &renderer = *game._renderer;
|
||||
|
||||
if ((bDialogActive == FALSE) || (CurDialog == dNULL) || (bDialogMenuActive == FALSE))
|
||||
return ;
|
||||
|
||||
if ((db == ME_MLEFT) && (CurDlgItem) && (init.DlgMenu[CurDlgItem].parent == mMAIN)) {
|
||||
CurMenu = CurDlgItem;
|
||||
Diag2Base = 0;
|
||||
} else if ((db == ME_MLEFT) && (CurDlgItem) && (CurDlgItem != -1)) { // TODO: The original didn't have a check for -1 here
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGCONTINUE, MP_DEFAULT, (int16)CurDialog, (int16)CurDlgItem, 0, nullptr, nullptr, nullptr);
|
||||
UsedDlgMenu[CurPlayer][CurObj][CurDlgItem] = 1;
|
||||
} else if ((db == ME_MRIGHT) && (CurMenu == mMAIN))
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGEND, MP_DEFAULT, (int16)CurDialog, (int16)mQUIT, 0, nullptr, nullptr, nullptr);
|
||||
else if (db == ME_MRIGHT) {
|
||||
CurMenu = mMAIN;
|
||||
Diag2Base = 0;
|
||||
}
|
||||
|
||||
//if( ( db == ME_MLEFT ) || ( db == ME_MRIGHT ) ) DebugFile("DLG: Click %d %d",CurMenu,CurDlgItem);
|
||||
|
||||
for (a = 0, ca1 = 0, ca2 = 0; a < MAX_DLG_MENUS; a++) {
|
||||
if (!(init.DlgMenu[a].on)) continue;
|
||||
|
||||
// se la servetta mi ha gia' dato la banconota devo fare in modo che non me la dia ancora
|
||||
if ((a == mCOSEFATTI8) && (CurObj == ocSERVETTA) && (IconInInv(init, i2cBANCONOTA1))) continue;
|
||||
|
||||
CurDlgItem = a;
|
||||
if (init.DlgMenu[a].parent == mMAIN) {
|
||||
t.x1 = DIAG1_MARG_SX;
|
||||
t.x2 = DIAG1_MARG_DX;
|
||||
t.y1 = DIAG1_MARG_UP + DIAG_DY * ca1;
|
||||
t.y2 = DIAG1_MARG_UP + DIAG_DY * (ca1 + 1);
|
||||
|
||||
ca1++;
|
||||
if (CheckRect(renderer, t, dmx, dmy)) return;
|
||||
} else if (init.DlgMenu[a].parent == CurMenu) {
|
||||
t.x1 = DIAG2_MARG_SX;
|
||||
t.x2 = DIAG2_MARG_DX;
|
||||
t.y1 = DIAG2_MARG_UP + DIAG2_DY * (ca2 - Diag2Base);
|
||||
t.y2 = DIAG2_MARG_UP + DIAG2_DY * ((ca2 - Diag2Base) + 1);
|
||||
|
||||
ca2++;
|
||||
if ((ca2 < Diag2Base) || (ca2 > (Diag2Base + MAX_DIAG2_ITEMS))) continue;
|
||||
if (CheckRect(renderer, t, dmx, dmy)) return;
|
||||
}
|
||||
}
|
||||
CurDlgItem = -1;
|
||||
if ((db == ME_MLEFT) || (db == ME_MRIGHT)) {
|
||||
// Se si cambia la logica di incremento variarla anche in PaintDialog() nella gestione delle freccette
|
||||
if (CheckRect(renderer, game._gameRect._diag2Up, dmx, dmy))
|
||||
Diag2Base = ((Diag2Base - 1) < 0) ? 0 : Diag2Base - 1;
|
||||
else if (CheckRect(renderer, game._gameRect._diag2Down, dmx, dmy))
|
||||
if ((Diag2Base + 1 + MAX_DIAG2_ITEMS) <= ca2)
|
||||
Diag2Base ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------03/06/98 10.47-------------------
|
||||
* PaintDialog
|
||||
* --------------------------------------------------*/
|
||||
void PaintDialog(WGame &game) {
|
||||
int32 a, ca1, ca2;
|
||||
int32 tx = 0, ty = 0;
|
||||
FontColor tc;
|
||||
Init &init = game.init;
|
||||
|
||||
if ((bDialogActive == FALSE) || (CurDialog == dNULL) || (bDialogMenuActive == FALSE))
|
||||
return ;
|
||||
|
||||
game._renderer->_2dStuff.displayDDBitmap(ConsoleD1, 7, 366, 0, 0, 0, 0);
|
||||
DisplayD3DRect(*game._renderer, 15, 373, 187, 211, 18, 25, 18, 128);
|
||||
game._renderer->_2dStuff.displayDDBitmap(ConsoleD2, 223, 515, 0, 0, 0, 0);
|
||||
DisplayD3DRect(*game._renderer, 223 + 6, 515 + 6, 536, 62, 18, 25, 18, 128);
|
||||
DisplayD3DRect(*game._renderer, 223 + 546, 515 + 22, 16, 30, 18, 25, 18, 128);
|
||||
DisplayD3DRect(*game._renderer, 223 + 542, 515 + 18, 4, 38, 18, 25, 18, 128);
|
||||
|
||||
for (a = 0, ca1 = 0, ca2 = 0; a < MAX_DLG_MENUS; a++) {
|
||||
if (!(init.DlgMenu[a].on) || ((init.DlgMenu[a].parent != mMAIN) && (init.DlgMenu[a].parent != CurMenu))) continue;
|
||||
|
||||
// se la servetta mi ha gia' dato la banconota devo fare in modo che non me la dia ancora
|
||||
if ((a == mCOSEFATTI8) && (CurObj == ocSERVETTA) && (IconInInv(init, i2cBANCONOTA1))) continue;
|
||||
|
||||
tc = WHITE_FONT;
|
||||
if (init.DlgMenu[a].parent == mMAIN) {
|
||||
tx = DIAG1_MARG_SX;
|
||||
ty = DIAG1_MARG_UP + DIAG_DY * ca1;
|
||||
ca1++;
|
||||
|
||||
if (CurMenu == a) tc = YELLOW_FONT;
|
||||
} else if (init.DlgMenu[a].parent == CurMenu) {
|
||||
tx = DIAG2_MARG_SX;
|
||||
ty = DIAG2_MARG_UP + DIAG2_DY * (ca2 - Diag2Base);
|
||||
ca2++;
|
||||
if ((ca2 <= Diag2Base) || (ca2 > (Diag2Base + MAX_DIAG2_ITEMS))) continue;
|
||||
|
||||
if (UsedDlgMenu[CurPlayer][CurObj][a]) tc = GRAY_FONT;
|
||||
}
|
||||
if (CurDlgItem == a) tc = RED_FONT;
|
||||
|
||||
game._renderer->_2dStuff.displayDDText(Sentence[init.DlgMenu[a].titolo], FontKind::Standard, tc, tx, ty, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
// disegno le frecce
|
||||
if (Diag2Base > 0)
|
||||
game._renderer->_2dStuff.displayDDBitmap(ConsoleFrecciaSu, 223 + 550, 515 + 0, 0, 0, 0, 0);
|
||||
|
||||
if ((Diag2Base + 1 + MAX_DIAG2_ITEMS) <= ca2)
|
||||
game._renderer->_2dStuff.displayDDBitmap(ConsoleFrecciaGiu, 223 + 550, 515 + 56, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
42
engines/watchmaker/classes/do_dialog.h
Normal file
42
engines/watchmaker/classes/do_dialog.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_DIALOG_H
|
||||
#define WATCHMAKER_DO_DIALOG_H
|
||||
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
extern int16 NextDlg;
|
||||
|
||||
void doDialog(WGame &game);
|
||||
void PaintDialog(WGame &game);
|
||||
void UpdateDialogMenu(WGame &game, int16 dmx, int16 dmy, uint8 db);
|
||||
int32 GetAlternateAnim(Init &init, int32 an);
|
||||
uint8 GetAlternateCamera(Init &init, uint8 cam);
|
||||
uint8 GetAlternatePosition(Init &init, uint8 pos);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_DIALOG_H
|
||||
387
engines/watchmaker/classes/do_inv.cpp
Normal file
387
engines/watchmaker/classes/do_inv.cpp
Normal file
@@ -0,0 +1,387 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_inv.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/schedule.h"
|
||||
#include "watchmaker/ll/ll_string.h"
|
||||
#include "watchmaker/classes/do_player.h"
|
||||
#include "watchmaker/ll/ll_mouse.h"
|
||||
#include "watchmaker/3d/geometry.h"
|
||||
#include "watchmaker/ll/ll_anim.h"
|
||||
#include "watchmaker/classes/do_string.h"
|
||||
#include "watchmaker/classes/do_camera.h"
|
||||
#include "watchmaker/classes/do_inv_inv.h"
|
||||
#include "watchmaker/classes/do_inv_scr.h"
|
||||
#include "watchmaker/classes/do_scr_scr.h"
|
||||
#include "watchmaker/classes/do_sound.h"
|
||||
#include "watchmaker/ll/ll_diary.h"
|
||||
#include "watchmaker/walk/act.h"
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/ll/ll_util.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
/* -----------------03/04/98 10.39-------------------
|
||||
* IconInInv
|
||||
* --------------------------------------------------*/
|
||||
uint8 IconInInv(Init &/*init*/, uint8 icon) {
|
||||
uint8 i;
|
||||
|
||||
for (i = 0; i < MAX_ICONS_IN_INV; i++)
|
||||
if ((Inv[CurPlayer][i] == icon) || (Inv[CurPlayer ^ 1][i] == icon))
|
||||
break;
|
||||
if (i == MAX_ICONS_IN_INV)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------03/04/98 10.39-------------------
|
||||
* IconPos
|
||||
* --------------------------------------------------*/
|
||||
uint8 IconPos(uint8 icon) {
|
||||
uint8 i;
|
||||
|
||||
for (i = 0; i < MAX_ICONS_IN_INV; i++)
|
||||
if (Inv[CurPlayer][i] == icon)
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* -----------------03/04/98 10.41-------------------
|
||||
* KillIcon
|
||||
* --------------------------------------------------*/
|
||||
void KillIcon(Init &init, uint8 icon) {
|
||||
uint8 pos = IconPos(icon), op = CurPlayer;
|
||||
if (pos == MAX_ICONS_IN_INV) {
|
||||
CurPlayer ^= 1;
|
||||
if ((pos = IconPos(icon)) == MAX_ICONS_IN_INV) {
|
||||
CurPlayer = op;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
init.InvObj[icon].flags &= ~ON;
|
||||
Inv[CurPlayer][pos] = iNULL;
|
||||
for (; pos < InvLen[CurPlayer]; pos++)
|
||||
Inv[CurPlayer][pos] = Inv[CurPlayer][pos + 1];
|
||||
InvLen[CurPlayer] --;
|
||||
|
||||
if (InvBase[CurPlayer])
|
||||
if ((InvLen[CurPlayer] > MAX_SHOWN_ICONS) && (Inv[CurPlayer][InvBase[CurPlayer] + MAX_SHOWN_ICONS] == iNULL))
|
||||
InvBase[CurPlayer] = InvLen[CurPlayer] - MAX_SHOWN_ICONS;
|
||||
|
||||
if (CurInvObj == icon) CurInvObj = iNULL;
|
||||
if (BigInvObj == icon) BigInvObj = iNULL;
|
||||
|
||||
CurPlayer = op;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------03/04/98 10.50-------------------
|
||||
* AddIcon
|
||||
* --------------------------------------------------*/
|
||||
void AddIcon(Init &init, uint8 icon) {
|
||||
if (IconInInv(init, icon))
|
||||
return;
|
||||
|
||||
init.InvObj[icon].flags |= ON;
|
||||
Inv[CurPlayer][InvLen[CurPlayer]++] = icon;
|
||||
|
||||
if (InvLen[CurPlayer] < MAX_ICONS_IN_INV)
|
||||
if (InvBase[CurPlayer] < InvLen[CurPlayer] - MAX_SHOWN_ICONS)
|
||||
InvBase[CurPlayer] = InvLen[CurPlayer] - MAX_SHOWN_ICONS;
|
||||
}
|
||||
|
||||
/* -----------------04/06/98 16.34-------------------
|
||||
* ClearUseWith
|
||||
* --------------------------------------------------*/
|
||||
void ClearUseWith() {
|
||||
bUseWith = UW_OFF;
|
||||
UseWith[USED] = 0;
|
||||
UseWith[WITH] = 0;
|
||||
CurMousePointer = MousePointerDefault;
|
||||
}
|
||||
|
||||
/* -----------------25/09/00 17.40-------------------
|
||||
* SelectCurBigIcon
|
||||
* --------------------------------------------------*/
|
||||
void SelectCurBigIcon(uint8 icon) {
|
||||
uint8 pos = IconPos(icon);
|
||||
if (pos == MAX_ICONS_IN_INV) {
|
||||
return;
|
||||
}
|
||||
|
||||
CurInvObj = icon;
|
||||
BigInvObj = icon;
|
||||
}
|
||||
|
||||
/* -----------------23/04/98 14.45-------------------
|
||||
* doUseWith
|
||||
* --------------------------------------------------*/
|
||||
void doUseWith(WGame &game) {
|
||||
if (bUseWith & UW_USEDI) {
|
||||
if (bUseWith & UW_WITHI)
|
||||
doInvInvUseWith(game);
|
||||
else
|
||||
doInvScrUseWith(game);
|
||||
//? BigInvObj = UseWith[USED];
|
||||
} else {
|
||||
doScrScrUseWith(game);
|
||||
BigInvObj = iNULL;
|
||||
}
|
||||
|
||||
ClearUseWith();
|
||||
}
|
||||
|
||||
/* -----------------03/04/98 10.53-------------------
|
||||
* ReplaceIcon
|
||||
* --------------------------------------------------*/
|
||||
void ReplaceIcon(Init &init, uint8 oldicon, uint8 newicon) {
|
||||
uint8 pos = IconPos(oldicon), op = CurPlayer;
|
||||
if (pos == MAX_ICONS_IN_INV) {
|
||||
CurPlayer ^= 1;
|
||||
if ((pos = IconPos(oldicon)) == MAX_ICONS_IN_INV) {
|
||||
CurPlayer = op;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
init.InvObj[oldicon].flags &= ~ON;
|
||||
init.InvObj[newicon].flags |= ON;
|
||||
Inv[CurPlayer][pos] = newicon;
|
||||
|
||||
if (CurInvObj == oldicon) CurInvObj = newicon;
|
||||
if (BigInvObj == oldicon) BigInvObj = newicon;
|
||||
|
||||
CurPlayer = op;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------03/04/98 10.16-------------------
|
||||
* doInventory
|
||||
* --------------------------------------------------*/
|
||||
void doInventory(WGame &game) {
|
||||
uint8 ci;
|
||||
Init &init = game.init;
|
||||
|
||||
switch (TheMessage->event) {
|
||||
case ME_EXAMINEICON:
|
||||
CurInvObj = TheMessage->lparam[0];
|
||||
|
||||
if (CurInvObj && (bUseWith & UW_ON)) {
|
||||
UseWith[WITH] = CurInvObj;
|
||||
|
||||
bUseWith &= ~UW_ON;
|
||||
bUseWith |= UW_WITHI;
|
||||
ClearText();
|
||||
// fa l'usa con
|
||||
doUseWith(game);
|
||||
} else if (CurInvObj) {
|
||||
if (InvStatus & INV_MODE4) {
|
||||
BigInvObj = iNULL;
|
||||
if (
|
||||
bSezioneLabirinto
|
||||
|| (CurInvObj == i00TELEFONO) || (CurInvObj == i00TELEFONOVIC)
|
||||
) {
|
||||
PlayerSpeak(game, init.Obj[o2ACOMPUTER].action[CurPlayer]);
|
||||
break;
|
||||
}
|
||||
|
||||
ci = (uint8)CurInvObj;
|
||||
KillIcon(init, ci);
|
||||
CurPlayer ^= 1;
|
||||
AddIcon(init, ci);
|
||||
CurPlayer ^= 1;
|
||||
break;
|
||||
} else if (InvStatus & INV_MODE5) {
|
||||
BigInvObj = CurInvObj;
|
||||
ReplaceSaveLoadTexture(CurInvObj);
|
||||
break;
|
||||
} else if ((InvStatus & INV_MODE2) && ((CurInvObj == i00TELEFONO) || (CurInvObj == i00TELEFONOVIC))) {
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, 0, 0, tPDA, nullptr, nullptr, nullptr);
|
||||
break;
|
||||
}
|
||||
BigInvObj = CurInvObj;
|
||||
|
||||
// Quando schiaccio sul nome dell'icona per aprire l'inventario grande non gli faccio dire la frase
|
||||
if ((InvStatus & INV_ON) && (InvStatus & INV_MODE2))
|
||||
PlayerSpeak(game, init.InvObj[CurInvObj].examine[CurPlayer]);
|
||||
else
|
||||
InvStatus = INV_ON | INV_MODE2;
|
||||
}
|
||||
break;
|
||||
|
||||
case ME_OPERATEICON:
|
||||
CurInvObj = TheMessage->lparam[0];
|
||||
|
||||
if (bUseWith & UW_ON) {
|
||||
UseWith[WITH] = CurInvObj;
|
||||
bUseWith &= ~UW_ON;
|
||||
bUseWith |= UW_WITHI;
|
||||
ClearText();
|
||||
// fa l'usa con
|
||||
doUseWith(game);
|
||||
break;
|
||||
}
|
||||
|
||||
if (InvStatus & INV_MODE4) {
|
||||
InvStatus &= ~INV_MODE4;
|
||||
CurPlayer ^= 1;
|
||||
CurInvObj = BigInvObj = iNULL;
|
||||
} else if (init.InvObj[CurInvObj].flags & USEWITH) {
|
||||
if (!(InvStatus & INV_MODE2))
|
||||
InvStatus = INV_OFF;
|
||||
UseWith[USED] = CurInvObj;
|
||||
bUseWith = UW_ON | UW_USEDI;
|
||||
ShowInvObjName(init, CurInvObj);
|
||||
CurMousePointer = MousePointerPlus;
|
||||
} else if (CurInvObj) {
|
||||
if (init.InvObj[CurInvObj].anim[CurPlayer]) {
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_INVENTORY, ME_INVOFF, MP_DEFAULT, 0, 0, 0, nullptr, nullptr, nullptr);
|
||||
StartAnim(game, init.InvObj[CurInvObj].anim[CurPlayer]);
|
||||
break;
|
||||
} else {
|
||||
int an;
|
||||
if (CurInvObj == i28WALKMANOK) {
|
||||
if (init.InvObj[CurInvObj].flags & EXTRA) an = a289_noinctime;
|
||||
else an = a289;
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_INVENTORY, ME_INVOFF, MP_DEFAULT, 0, 0, 0, nullptr, nullptr, nullptr);
|
||||
StartAnim(game, an);
|
||||
}
|
||||
}
|
||||
InvStatus = INV_ON | INV_MODE2;
|
||||
|
||||
if (CurInvObj == i22LIBROCHIUSODEPLIANT) {
|
||||
StartSound(game, w228);
|
||||
ReplaceIcon(init, i22LIBROCHIUSODEPLIANT, i22LIBROAPERTODEPLIANT);
|
||||
} else if (CurInvObj == i22LIBROAPERTODEPLIANT) {
|
||||
ReplaceIcon(init, i22LIBROAPERTODEPLIANT, i22DEPLIANT);
|
||||
AddIcon(init, i22LIBROAPERTO);
|
||||
IncCurTime(game, 10);
|
||||
} else if (CurInvObj == i22LIBROAPERTO)
|
||||
ReplaceIcon(init, i22LIBROAPERTO, i22LIBROCHIUSO);
|
||||
else if (CurInvObj == i22LIBROCHIUSO)
|
||||
ReplaceIcon(init, i22LIBROCHIUSO, i22LIBROAPERTO);
|
||||
else if (CurInvObj == i3bLASTRA2VOLTI) {
|
||||
StartSound(game, w3B22);
|
||||
ReplaceIcon(init, i3bLASTRA2VOLTI, i3bLASTRABIANCA);
|
||||
AddIcon(init, i3bLASTRANERA);
|
||||
} else
|
||||
PlayerSpeak(game, init.InvObj[CurInvObj].action[CurPlayer]);
|
||||
}
|
||||
break;
|
||||
|
||||
case ME_INVOFF:
|
||||
case ME_INVMODE1:
|
||||
case ME_INVMODE2:
|
||||
case ME_INVMODE3:
|
||||
case ME_INVMODE4:
|
||||
case ME_INVSWITCH:
|
||||
|
||||
ClearText();
|
||||
if (bSomeOneSpeak) bSkipTalk = true;
|
||||
|
||||
PlayerPos[CurPlayer + ocDARRELL] = 0;
|
||||
PlayerGotoPos[CurPlayer + ocDARRELL] = 0;
|
||||
game._messageSystem.removeEvent(EventClass::MC_PLAYER, ME_ALL);
|
||||
CharStop(ocCURPLAYER);
|
||||
|
||||
if (TheMessage->event == ME_INVOFF)
|
||||
InvStatus = INV_OFF;
|
||||
else if (TheMessage->event == ME_INVSWITCH) {
|
||||
if (InvStatus & INV_ON) {
|
||||
if (InvStatus & INV_MODE4) {
|
||||
CurPlayer ^= 1;
|
||||
ChangePlayer(game, (uint8)((CurPlayer ^ 1) + ocDARRELL));
|
||||
}
|
||||
InvStatus = INV_OFF;
|
||||
game._cameraMan->resetAngle();
|
||||
game._cameraMan->GetCameraTarget(init, &t3dCurCamera->Target);
|
||||
} else {
|
||||
rGrabVideo("temp.tmp", 1);
|
||||
InvStatus = INV_ON | INV_MODE1;
|
||||
}
|
||||
} else
|
||||
InvStatus = INV_ON + (INV_MODE1 << (TheMessage->event - ME_INVMODE1));
|
||||
|
||||
if (InvStatus & INV_ON) {
|
||||
if (TheMessage->event == ME_INVSWITCH) InvStatus |= INV_MODE1;
|
||||
ClearUseWith();
|
||||
mHide = false;
|
||||
}
|
||||
|
||||
if (bFirstPerson)
|
||||
game._renderer->setCurCameraViewport(CAMERA_FOV_1ST, bSuperView);
|
||||
else
|
||||
game._renderer->setCurCameraViewport(t3dCurCamera->Fov, bSuperView);
|
||||
BigInvObj = TheMessage->wparam1;
|
||||
if (TheMessage->event == ME_INVMODE3) {
|
||||
bUseWith = UW_ON | (UW_USEDI * TheMessage->bparam);
|
||||
UseWith[USED] = TheMessage->wparam1;
|
||||
CurMousePointer = MousePointerPlus;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------03/04/98 10.29-------------------
|
||||
* InventoryDown
|
||||
* --------------------------------------------------*/
|
||||
void InventoryDown() {
|
||||
// Se si cambia la logica di incremento variarla anche in PaintInventory() nella gestione delle freccette
|
||||
|
||||
if (InvBase[CurPlayer] < (InvLen[CurPlayer] - MAX_SHOWN_ICONS))
|
||||
InvBase[CurPlayer] ++;
|
||||
}
|
||||
|
||||
/* -----------------03/04/98 10.29-------------------
|
||||
* InventoryUp
|
||||
* --------------------------------------------------*/
|
||||
void InventoryUp() {
|
||||
// Se si cambia la logica di incremento variarla anche in PaintInventory() nella gestione delle freccette
|
||||
|
||||
if (InvBase[CurPlayer] > 0)
|
||||
InvBase[CurPlayer] --;
|
||||
}
|
||||
|
||||
/* -----------------03/04/98 10.34-------------------
|
||||
* WhatIcon
|
||||
* --------------------------------------------------*/
|
||||
uint8 WhatIcon(Renderer &renderer, int16 invmx, int16 invmy) {
|
||||
struct SRect t;
|
||||
t.x1 = INV_MARG_SX;
|
||||
t.y1 = INV_MARG_UP;
|
||||
t.x2 = INV_MARG_DX;
|
||||
t.y2 = INV_MARG_DOWN;
|
||||
|
||||
if (CheckRect(renderer, t, invmx, invmy))
|
||||
return Inv[CurPlayer][(InvBase[CurPlayer] + ((invmy - renderer.rFitY(INV_MARG_UP)) / (renderer.rFitY(ICON_DY))))];
|
||||
else
|
||||
return iNULL;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
43
engines/watchmaker/classes/do_inv.h
Normal file
43
engines/watchmaker/classes/do_inv.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_INV_H
|
||||
#define WATCHMAKER_DO_INV_H
|
||||
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void AddIcon(Init &init, uint8 icon);
|
||||
void doInventory(WGame &game);
|
||||
void doUseWith(WGame &game);
|
||||
void KillIcon(Init &init, uint8 icon);
|
||||
uint8 IconInInv(Init &init, uint8 icon);
|
||||
void ReplaceIcon(Init &init, uint8 oldicon, uint8 newicon);
|
||||
void ClearUseWith();
|
||||
void InventoryUp();
|
||||
void InventoryDown();
|
||||
uint8 WhatIcon(Renderer &renderer, int16 invmx, int16 invmy);
|
||||
void SelectCurBigIcon(uint8 icon);
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_INV_H
|
||||
133
engines/watchmaker/classes/do_inv_inv.cpp
Normal file
133
engines/watchmaker/classes/do_inv_inv.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_inv_inv.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/schedule.h"
|
||||
#include "watchmaker/classes/do_inv.h"
|
||||
#include "watchmaker/ll/ll_diary.h"
|
||||
#include "watchmaker/classes/do_sound.h"
|
||||
#include "watchmaker/classes/do_string.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
/* -----------------19/05/98 16.40-------------------
|
||||
* doInvInvUseWith
|
||||
* --------------------------------------------------*/
|
||||
void doInvInvUseWith(WGame &game) {
|
||||
uint8 sent = TRUE;
|
||||
Init &init = game.init;
|
||||
|
||||
switch (UseWith[USED]) {
|
||||
case i00TELEFONO:
|
||||
case i00TELEFONOVIC:
|
||||
if ((UseWith[WITH] == i28WALKMANOK) && (init.InvObj[i28WALKMANOK].flags & EXTRA)) {
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, 0, 0, tPDA, &UseWith[WITH], nullptr, nullptr);
|
||||
sent = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case i1dAUDIOCASSETTA:
|
||||
if (UseWith[WITH] == i28WALKMANVUOTO) {
|
||||
ReplaceIcon(init, i28WALKMANVUOTO, i28WALKMANNASTRO);
|
||||
KillIcon(init, i1dAUDIOCASSETTA);
|
||||
SelectCurBigIcon(i28WALKMANNASTRO);
|
||||
UseWith[USED] = i28WALKMANNASTRO;
|
||||
sent = false;
|
||||
} else if (UseWith[WITH] == i28WALKMANPILE) {
|
||||
ReplaceIcon(init, i28WALKMANPILE, i28WALKMANOK);
|
||||
KillIcon(init, i1dAUDIOCASSETTA);
|
||||
SelectCurBigIcon(i28WALKMANOK);
|
||||
UseWith[USED] = i28WALKMANOK;
|
||||
sent = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case i25FIALEABPIENE:
|
||||
if (UseWith[WITH] == i34STAMPO) {
|
||||
ReplaceIcon(init, i34STAMPO, i25FIALEABUSATE);
|
||||
ReplaceIcon(init, i25FIALEABPIENE, i25MEDAGLIONI4);
|
||||
IncCurTime(game, 10);
|
||||
}
|
||||
break;
|
||||
|
||||
case i27PILE:
|
||||
if (UseWith[WITH] == i28WALKMANVUOTO) {
|
||||
ReplaceIcon(init, i28WALKMANVUOTO, i28WALKMANPILE);
|
||||
KillIcon(init, i27PILE);
|
||||
SelectCurBigIcon(i28WALKMANPILE);
|
||||
UseWith[USED] = i28WALKMANPILE;
|
||||
IncCurTime(game, 5);
|
||||
sent = false;
|
||||
} else if (UseWith[WITH] == i28WALKMANNASTRO) {
|
||||
ReplaceIcon(init, i28WALKMANNASTRO, i28WALKMANOK);
|
||||
KillIcon(init, i27PILE);
|
||||
SelectCurBigIcon(i28WALKMANOK);
|
||||
UseWith[USED] = i28WALKMANOK;
|
||||
IncCurTime(game, 5);
|
||||
sent = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case i36BUSTA1DOSEA:
|
||||
case i36BUSTA2DOSIA:
|
||||
if (UseWith[WITH] == i2bSACCHETTOINCENSO)
|
||||
ReplaceIcon(init, (uint8)UseWith[USED], i2rBUSTAVUOTAA);
|
||||
break;
|
||||
case i36BUSTA1DOSEB:
|
||||
case i36BUSTA2DOSIB:
|
||||
if (UseWith[WITH] == i2bSACCHETTOINCENSO)
|
||||
ReplaceIcon(init, (uint8)UseWith[USED], i2rBUSTAVUOTAB);
|
||||
break;
|
||||
|
||||
case i3bLASTRANERA:
|
||||
if (UseWith[WITH] == i3bLASTRABIANCA) {
|
||||
StartSound(game, w3B22);
|
||||
ReplaceIcon(init, i3bLASTRABIANCA, i3bLASTRA2VOLTI);
|
||||
KillIcon(init, i3bLASTRANERA);
|
||||
SelectCurBigIcon(i3bLASTRA2VOLTI);
|
||||
sent = false;
|
||||
}
|
||||
break;
|
||||
case i3bLASTRABIANCA:
|
||||
if (UseWith[WITH] == i3bLASTRANERA) {
|
||||
StartSound(game, w3B22);
|
||||
ReplaceIcon(init, i3bLASTRABIANCA, i3bLASTRA2VOLTI);
|
||||
KillIcon(init, i3bLASTRANERA);
|
||||
SelectCurBigIcon(i3bLASTRA2VOLTI);
|
||||
sent = false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sent = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sent)
|
||||
if (!((bUseWith & UW_WITHI) && (UseWith[USED] == UseWith[WITH])))
|
||||
PlayerSpeak(game, init.InvObj[UseWith[USED]].action[CurPlayer]);
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
33
engines/watchmaker/classes/do_inv_inv.h
Normal file
33
engines/watchmaker/classes/do_inv_inv.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_INV_INV_H
|
||||
#define WATCHMAKER_DO_INV_INV_H
|
||||
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doInvInvUseWith(WGame &game);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_INV_INV_H
|
||||
608
engines/watchmaker/classes/do_inv_scr.cpp
Normal file
608
engines/watchmaker/classes/do_inv_scr.cpp
Normal file
@@ -0,0 +1,608 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_inv_scr.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/schedule.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/classes/do_string.h"
|
||||
#include "watchmaker/classes/do_inv.h"
|
||||
#include "watchmaker/ll/ll_mesh.h"
|
||||
#include "watchmaker/ll/ll_anim.h"
|
||||
#include "watchmaker/ll/ll_diary.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
/* -----------------19/05/98 16.40-------------------
|
||||
* doInvScrUseWith
|
||||
* --------------------------------------------------*/
|
||||
void doInvScrUseWith(WGame &game) {
|
||||
uint8 sent = FALSE;
|
||||
int32 sa = 0;
|
||||
Init &init = game.init;
|
||||
|
||||
//messo fuori perche' andava in conflitto con l'usacon dell'icona
|
||||
if ((UseWith[USED] == i29FOTOPROGETTO) && (UseWith[WITH] == ocCUSTODE)) {
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR005, 0, 0, nullptr, nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
//messo fuori perche' se non parte l'RTV deve dire la frase
|
||||
if ((UseWith[USED] == i1cMEDAGLIONI2) && (UseWith[WITH] == o1CBOCCA)) {
|
||||
if (init.Dialog[dR1A5].flags & DIALOG_DONE) {
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR1C3, 0, 0, nullptr, nullptr, nullptr);
|
||||
return;
|
||||
} else {
|
||||
PlayerSpeak(game, init.InvObj[i1cMEDAGLIONI2].text[1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//messo fuori perche' nel caso non si verificasse il gioco deve procedere normalmente con frase/azione dell'icona
|
||||
if ((UseWith[WITH] == o17CAVETTO) && ((UseWith[USED] == i00TELEFONO) || (UseWith[USED] == i00TELEFONOVIC))) {
|
||||
// se non ho sentito il numero...
|
||||
if (!(init.InvObj[i28WALKMANOK].flags & EXTRA2)) {
|
||||
PlayerSpeak(game, init.Obj[o17COMPUTER].action[CurPlayer]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//caso delle chiavi del cuoco che aprono due porte: evito che si usino due volte sulla stessa porta
|
||||
if ((UseWith[USED] == i25MAZZODUECHIAVI) && ((UseWith[WITH] == o2Hp2G) || (UseWith[WITH] == o2Gp2H) || (UseWith[WITH] == oXT16p17) || (UseWith[WITH] == o17p16))) {
|
||||
// se ho gia' aperto la porta gli faccio dire una frase
|
||||
if ((init.Obj[o2Hp2G].flags & EXTRA) || (init.Obj[oXT16p17].flags & ON)) {
|
||||
PlayerSpeak(game, init.Obj[oADDTEXTOBJ].text[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (UseWith[USED]) {
|
||||
case i41OGGETTO:
|
||||
if (UseWith[WITH] == ocCUSTODE)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR002, 0, 0, nullptr, nullptr, nullptr);
|
||||
else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i14OCCHIALI:
|
||||
if (UseWith[WITH] == ocCUSTODE)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR003, 0, 0, nullptr, nullptr, nullptr);
|
||||
else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i1cMEDAGLIONE:
|
||||
if (UseWith[WITH] == o1CBOCCA)
|
||||
PlayerSpeak(game, init.InvObj[i1cMEDAGLIONE].text[1]);
|
||||
else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i34FIALAA:
|
||||
if (init.Obj[o25FORNOAP].flags & EXTRA2) {
|
||||
if (UseWith[WITH] == o25FORNOAP)
|
||||
sa = a257;
|
||||
else if (UseWith[WITH] == o25CONGELATORE2AP)
|
||||
sa = a2524;
|
||||
} else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i34FIALAB:
|
||||
if (init.Obj[o25FORNOAP].flags & EXTRA2) {
|
||||
if (UseWith[WITH] == o25FORNOAP)
|
||||
sa = a258;
|
||||
else if (UseWith[WITH] == o25CONGELATORE2AP)
|
||||
sa = a2525;
|
||||
} else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i25MEDAGLIONI4:
|
||||
if (UseWith[WITH] == o1CBOCCA) {
|
||||
sa = a1C2;
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_WAIT_ANIM, dR1C1, 0, 0, nullptr, nullptr, nullptr);
|
||||
} else
|
||||
sent = TRUE;
|
||||
break;
|
||||
case i1cMEDAGLIONI3:
|
||||
if (UseWith[WITH] == o1CBOCCA) {
|
||||
sa = a1C2;
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_WAIT_ANIM, dR1C2, 0, 0, nullptr, nullptr, nullptr);
|
||||
} else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i24COLTELLO:
|
||||
|
||||
if ((UseWith[WITH] == o2GFILTRODXCH) || (UseWith[WITH] == o2GFILTROSXCH)) {
|
||||
switch (UseWith[WITH]) {
|
||||
case o2GFILTRODXCH:
|
||||
if (init.Obj[o2GOFF].flags & ON) {
|
||||
sa = a2G2;
|
||||
init.Obj[o2GOFF].anim[DARRELL] = init.Obj[o2GOFF].anim[VICTORIA] = aNULL;
|
||||
init.Obj[o2GOFF].flags |= EXTRA;
|
||||
} else PlayerSpeak(game, init.InvObj[UseWith[USED]].text[1]);
|
||||
|
||||
break;
|
||||
|
||||
case o2GFILTROSXCH:
|
||||
if (init.Obj[o2GOFF].flags & ON) {
|
||||
sa = a2G3;
|
||||
init.Obj[o2GOFF].anim[DARRELL] = init.Obj[o2GOFF].anim[VICTORIA] = aNULL;
|
||||
init.Obj[o2GOFF].flags |= EXTRA;
|
||||
} else PlayerSpeak(game, init.InvObj[UseWith[USED]].text[1]);
|
||||
break;
|
||||
}//switch
|
||||
} else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i25MAZZODUECHIAVI:
|
||||
if (UseWith[WITH] == o2Hp2G)
|
||||
sa = a2H6;
|
||||
else if (UseWith[WITH] == oXT16PORTA)
|
||||
sa = a162;
|
||||
else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i2iDETERSIVO:
|
||||
if (UseWith[WITH] == o2GFILTRODXAP) {
|
||||
sa = a2G4;
|
||||
init.InvObj[UseWith[USED]].flags &= ~USEWITH;
|
||||
init.InvObj[UseWith[USED]].flags |= USE;
|
||||
init.InvObj[i2iDETERSIVO].flags |= EXTRA;
|
||||
} else if (UseWith[WITH] == o2GFILTROSXAP) {
|
||||
sa = a2G5;
|
||||
init.InvObj[UseWith[USED]].flags &= ~USEWITH;
|
||||
init.InvObj[UseWith[USED]].flags |= USE;
|
||||
init.InvObj[i2iDETERSIVO].flags |= EXTRA;
|
||||
}
|
||||
break;
|
||||
|
||||
case i2lBOTTIGLIAVINO:
|
||||
if (UseWith[WITH] == ocCUOCO) {
|
||||
if (!(init.InvObj[i2lBOTTIGLIAVINO].flags & EXTRA)) {
|
||||
PlayerSpeak(game, init.InvObj[i2lBOTTIGLIAVINO_NOCUOCO].text[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(init.InvObj[i2lBOTTIGLIAVINO].flags & EXTRA2) &&
|
||||
(((CurPlayer == DARRELL) && (PlayerStand[VICTORIA].roomName.equalsIgnoreCase("r25-a.t3d"))) ||
|
||||
((CurPlayer == VICTORIA) && (PlayerStand[DARRELL].roomName.equalsIgnoreCase("r25-a.t3d"))))) {
|
||||
init.Dialog[dR009].flags &= ~(DIALOG_RTV | DIALOG_RTV2 | DIALOG_RTV3);
|
||||
if (init.Dialog[dR009].flags & DIALOG_DONE)
|
||||
init.Dialog[dR009].flags |= DIALOG_RTV2;
|
||||
else
|
||||
init.Dialog[dR009].flags |= DIALOG_RTV3;
|
||||
init.InvObj[i2lBOTTIGLIAVINO].flags |= EXTRA2;
|
||||
}
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR009, 0, 0, nullptr, nullptr, nullptr);
|
||||
}
|
||||
break;
|
||||
|
||||
case i34LASTRE:
|
||||
if (UseWith[WITH] == ocSUPERVISORE)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR007, 0, 0, nullptr, nullptr, nullptr);
|
||||
else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i22BRACCIALE:
|
||||
if (UseWith[WITH] == ocSERVETTA) {
|
||||
if (CurPlayer == VICTORIA) {
|
||||
// PlayerSpeak( init.InvObj[i22BRACCIALE].text[1] );
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR001, 0, 0, nullptr, nullptr, nullptr);
|
||||
} else {
|
||||
PlayerSpeak(game, init.InvObj[i22BRACCIALE].text[0]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case i29FOTOJUDE1:
|
||||
if ((UseWith[WITH] == ocSUPERVISORE) && (init.InvObj[i2aSANGUE].flags & EXTRA)) {
|
||||
if (CurPlayer == DARRELL)
|
||||
PlayerSpeak(game, init.InvObj[i29FOTOJUDE1].text[0]);
|
||||
|
||||
if (CurPlayer == VICTORIA)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR291, 0, 0, nullptr, nullptr, nullptr);
|
||||
} else sent = TRUE;
|
||||
break;
|
||||
|
||||
case i29STAMPAINGRANAGGIO:
|
||||
if (UseWith[WITH] == ocCUSTODE)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR006, 0, 0, nullptr, nullptr, nullptr);
|
||||
else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i31ANELLOBRONZO:
|
||||
if (UseWith[WITH] == ocCUSTODE)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR004, 0, 0, nullptr, nullptr, nullptr);
|
||||
else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i1aLUCCHETTO:
|
||||
if (UseWith[WITH] == oXT1AFINESTRA) {
|
||||
// morte Cacciatore
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR1A5, 0, 0, nullptr, nullptr, nullptr);
|
||||
} else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i48CHIAVIMANETTE:
|
||||
if (UseWith[WITH] == o48MANETTE)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR483, 0, 0, nullptr, nullptr, nullptr);
|
||||
else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i2aSIRINGAVUOTA:
|
||||
if (UseWith[WITH] == o2AACIDO)
|
||||
sa = a2A14;
|
||||
else if (UseWith[WITH] == o2MACIDO)
|
||||
sa = a2M9;
|
||||
else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i19CRISTALLO:
|
||||
if (UseWith[WITH] == o31ALLOGGIAMENTO)
|
||||
sa = a3114;
|
||||
else if (UseWith[WITH] == o39RETTANGOLO)
|
||||
sa = a396;
|
||||
else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i39CRISTALLOATTIVATO:
|
||||
if (UseWith[WITH] == o31ALLOGGIAMENTO)
|
||||
sa = a3116;
|
||||
else if (UseWith[WITH] == o39RETTANGOLO)
|
||||
sa = a3913;
|
||||
else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i2dSESTERZO:
|
||||
if ((UseWith[WITH] == o36PIATTODX) && !(init.Obj[o36INCENSODX].flags & ON)) {
|
||||
if (init.Obj[o36INCENSOSX].flags & ON)
|
||||
sa = a36MSDA;
|
||||
else
|
||||
sa = a36MSDM;
|
||||
} else if ((UseWith[WITH] == o36PIATTOSX) && !(init.Obj[o36INCENSOSX].flags & ON)) {
|
||||
if (init.Obj[o36INCENSODX].flags & ON)
|
||||
sa = a36MSSA;
|
||||
else
|
||||
sa = a36MSSM;
|
||||
} else if (!(init.Obj[o3BCOPPA].flags & EXTRA)) {
|
||||
if (UseWith[WITH] == o3BCOPPABRACCIALI)
|
||||
sa = a3B2;
|
||||
else if (UseWith[WITH] == o3BCOPPA)
|
||||
sa = a3B3;
|
||||
} else
|
||||
sent = TRUE;
|
||||
break;
|
||||
case i36BUSTA1DOSEA:
|
||||
case i36BUSTA1DOSEB:
|
||||
if ((UseWith[WITH] == o36PIATTODX) && (init.Obj[o36INCENSODX].flags & ON)) {
|
||||
if (init.Obj[o36SESTERZOSX].flags & ON)
|
||||
sa = a36PBDM;
|
||||
else
|
||||
sa = a36PBDB;
|
||||
|
||||
if (UseWith[USED] == i36BUSTA1DOSEA)
|
||||
ReplaceIcon(init, i36BUSTA1DOSEA, i36BUSTA2DOSIA);
|
||||
else
|
||||
ReplaceIcon(init, i36BUSTA1DOSEB, i36BUSTA2DOSIB);
|
||||
} else if ((UseWith[WITH] == o36PIATTOSX) && (init.Obj[o36INCENSOSX].flags & ON)) {
|
||||
if (init.Obj[o36SESTERZODX].flags & ON)
|
||||
sa = a36PBSM;
|
||||
else
|
||||
sa = a36PBSB;
|
||||
|
||||
if (UseWith[USED] == i36BUSTA1DOSEA)
|
||||
ReplaceIcon(init, i36BUSTA1DOSEA, i36BUSTA2DOSIA);
|
||||
else
|
||||
ReplaceIcon(init, i36BUSTA1DOSEB, i36BUSTA2DOSIB);
|
||||
} else if (!(init.Obj[o3BCOPPA].flags & EXTRA)) {
|
||||
if ((UseWith[WITH] == o3BCOPPABRACCIALI) && !(init.Obj[o3B2DOSIBRACCIALI].flags & ON)) {
|
||||
if (UseWith[USED] == i36BUSTA1DOSEA) ReplaceIcon(init, i36BUSTA1DOSEA, i2rBUSTAVUOTAA);
|
||||
else ReplaceIcon(init, i36BUSTA1DOSEB, i2rBUSTAVUOTAB);
|
||||
|
||||
if (init.Obj[o3B1DOSEBRACCIALI].flags & ON) {
|
||||
init.Obj[o3B1DOSEBRACCIALI].flags &= ~ON;
|
||||
init.Obj[o3B2DOSIBRACCIALI].flags |= ON;
|
||||
|
||||
init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer] = init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPABRACCIALI].text[4];
|
||||
} else {
|
||||
init.Obj[o3B1DOSEBRACCIALI].flags |= ON;
|
||||
init.Obj[o3B2DOSIBRACCIALI].flags &= ~ON;
|
||||
|
||||
init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer] = init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPABRACCIALI].text[3];
|
||||
}
|
||||
|
||||
UpdateObjMesh(init, o3B1DOSEBRACCIALI);
|
||||
UpdateObjMesh(init, o3B2DOSIBRACCIALI);
|
||||
|
||||
sa = a3B4;
|
||||
} else if ((UseWith[WITH] == o3BCOPPA) && !(init.Obj[o3B2DOSI].flags & ON)) {
|
||||
if (UseWith[USED] == i36BUSTA1DOSEA) ReplaceIcon(init, i36BUSTA1DOSEA, i2rBUSTAVUOTAA);
|
||||
else ReplaceIcon(init, i36BUSTA1DOSEB, i2rBUSTAVUOTAB);
|
||||
|
||||
if (init.Obj[o3B1DOSE].flags & ON) {
|
||||
init.Obj[o3B1DOSE].flags &= ~ON;
|
||||
init.Obj[o3B2DOSI].flags |= ON;
|
||||
|
||||
init.Obj[o3BCOPPA].examine[CurPlayer] = init.Obj[o3BCOPPA].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPA].text[4];
|
||||
} else {
|
||||
init.Obj[o3B1DOSE].flags |= ON;
|
||||
init.Obj[o3B2DOSI].flags &= ~ON;
|
||||
|
||||
init.Obj[o3BCOPPA].examine[CurPlayer] = init.Obj[o3BCOPPA].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPA].text[3];
|
||||
}
|
||||
|
||||
UpdateObjMesh(init, o3B1DOSE);
|
||||
UpdateObjMesh(init, o3B2DOSI);
|
||||
|
||||
sa = a3B5;
|
||||
} else
|
||||
sent = TRUE;
|
||||
} else
|
||||
sent = TRUE;
|
||||
break;
|
||||
case i36BUSTA2DOSIA:
|
||||
case i36BUSTA2DOSIB:
|
||||
if (!(init.Obj[o3BCOPPA].flags & EXTRA)) {
|
||||
if ((UseWith[WITH] == o3BCOPPABRACCIALI) && !(init.Obj[o3B1DOSEBRACCIALI].flags & ON) && !(init.Obj[o3B2DOSIBRACCIALI].flags & ON)) {
|
||||
if (UseWith[USED] == i36BUSTA2DOSIA) ReplaceIcon(init, i36BUSTA2DOSIA, i2rBUSTAVUOTAA);
|
||||
else ReplaceIcon(init, i36BUSTA2DOSIB, i2rBUSTAVUOTAB);
|
||||
|
||||
init.Obj[o3B2DOSIBRACCIALI].flags |= ON;
|
||||
UpdateObjMesh(init, o3B2DOSIBRACCIALI);
|
||||
|
||||
sa = a3B6;
|
||||
} else if ((UseWith[WITH] == o3BCOPPA) && !(init.Obj[o3B1DOSE].flags & ON) && !(init.Obj[o3B2DOSI].flags & ON)) {
|
||||
if (UseWith[USED] == i36BUSTA2DOSIA) ReplaceIcon(init, i36BUSTA2DOSIA, i2rBUSTAVUOTAA);
|
||||
else ReplaceIcon(init, i36BUSTA2DOSIB, i2rBUSTAVUOTAB);
|
||||
|
||||
init.Obj[o3B2DOSI].flags |= ON;
|
||||
UpdateObjMesh(init, o3B2DOSI);
|
||||
sa = a3B7;
|
||||
} else
|
||||
sent = TRUE;
|
||||
} else
|
||||
sent = TRUE;
|
||||
break;
|
||||
case i2bSACCHETTOINCENSO:
|
||||
if (UseWith[WITH] == o36PIATTODX) {
|
||||
if (init.Obj[o36SESTERZOSX].flags & ON) { // se a sx sesterzo
|
||||
if (!(init.Obj[o36INCENSODX].flags & ON)) // ma a dx non incenso
|
||||
sa = a36MIDA; // lo mette
|
||||
else // altrimenti
|
||||
sa = a36PIDM; // lo prende
|
||||
} else if (init.Obj[o36INCENSODX].flags & ON) // se a dx incenso
|
||||
sa = a36PIDB; // lo prende
|
||||
} else if (UseWith[WITH] == o36PIATTOSX) {
|
||||
if (init.Obj[o36SESTERZODX].flags & ON) { // se a dx sesterzo
|
||||
if (!(init.Obj[o36INCENSOSX].flags & ON)) // ma a sx non incenso
|
||||
sa = a36MISA; // lo mette
|
||||
else // altrimenti
|
||||
sa = a36PISM; // lo prende
|
||||
} else if (init.Obj[o36INCENSOSX].flags & ON) // se a sx incenso
|
||||
sa = a36PISB; // lo prende
|
||||
} else if (!(init.Obj[o3BCOPPA].flags & EXTRA)) {
|
||||
if ((UseWith[WITH] == o3BCOPPABRACCIALI) && (init.Obj[o3B2DOSIBRACCIALI].flags & ON))
|
||||
sa = a3B15;
|
||||
else if ((UseWith[WITH] == o3BCOPPABRACCIALI) && (init.Obj[o3B1DOSEBRACCIALI].flags & ON))
|
||||
sa = a3B13;
|
||||
else if ((UseWith[WITH] == o3BCOPPA) && (init.Obj[o3B2DOSI].flags & ON))
|
||||
sa = a3B16;
|
||||
else if ((UseWith[WITH] == o3BCOPPA) && (init.Obj[o3B1DOSE].flags & ON))
|
||||
sa = a3B14;
|
||||
else
|
||||
sent = TRUE;
|
||||
|
||||
if (sa) { //se ha fatto l'azione di raccoglie controllo il testo delle coppe
|
||||
if (UseWith[WITH] == o3BCOPPABRACCIALI) {
|
||||
if (init.Obj[o3BSESTERZOBRACCIALI].flags & ON)
|
||||
init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer] = init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPABRACCIALI].text[2];
|
||||
else
|
||||
init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer] = init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPABRACCIALI].text[0];
|
||||
|
||||
init.Obj[o3BCOPPABRACCIALI].action[CurPlayer] = init.Obj[o3BCOPPABRACCIALI].action[CurPlayer ^ 1] = 0;
|
||||
} else if (UseWith[WITH] == o3BCOPPA) {
|
||||
if (init.Obj[o3BSESTERZO].flags & ON)
|
||||
init.Obj[o3BCOPPA].examine[CurPlayer] = init.Obj[o3BCOPPA].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPA].text[2];
|
||||
else
|
||||
init.Obj[o3BCOPPA].examine[CurPlayer] = init.Obj[o3BCOPPA].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPA].text[0];
|
||||
|
||||
init.Obj[o3BCOPPA].action[CurPlayer] = init.Obj[o3BCOPPA].action[CurPlayer ^ 1] = 0;
|
||||
}
|
||||
}//if sa
|
||||
}
|
||||
|
||||
else
|
||||
sent = TRUE;
|
||||
break;
|
||||
case i2rBUSTAVUOTAA:
|
||||
if ((UseWith[WITH] == o36PIATTODX) && (init.Obj[o36INCENSODX].flags & ON)) {
|
||||
if (init.Obj[o36SESTERZOSX].flags & ON)
|
||||
sa = a36PBDM;
|
||||
else
|
||||
sa = a36PBDB;
|
||||
|
||||
ReplaceIcon(init, i2rBUSTAVUOTAA, i36BUSTA1DOSEA);
|
||||
} else if ((UseWith[WITH] == o36PIATTOSX) && (init.Obj[o36INCENSOSX].flags & ON)) {
|
||||
if (init.Obj[o36SESTERZODX].flags & ON)
|
||||
sa = a36PBSM;
|
||||
else
|
||||
sa = a36PBSB;
|
||||
|
||||
ReplaceIcon(init, i2rBUSTAVUOTAA, i36BUSTA1DOSEA);
|
||||
} else if (!(init.Obj[o3BCOPPA].flags & EXTRA)) {
|
||||
if ((UseWith[WITH] == o3BCOPPABRACCIALI) && (init.Obj[o3B2DOSIBRACCIALI].flags & ON)) {
|
||||
sa = a3B11;
|
||||
ReplaceIcon(init, (uint8)UseWith[USED], i36BUSTA2DOSIA);
|
||||
} else if ((UseWith[WITH] == o3BCOPPABRACCIALI) && (init.Obj[o3B1DOSEBRACCIALI].flags & ON)) {
|
||||
sa = a3B9;
|
||||
ReplaceIcon(init, (uint8)UseWith[USED], i36BUSTA1DOSEA);
|
||||
} else if ((UseWith[WITH] == o3BCOPPA) && (init.Obj[o3B2DOSI].flags & ON)) {
|
||||
sa = a3B12;
|
||||
ReplaceIcon(init, (uint8)UseWith[USED], i36BUSTA2DOSIA);
|
||||
} else if ((UseWith[WITH] == o3BCOPPA) && (init.Obj[o3B1DOSE].flags & ON)) {
|
||||
sa = a3B10;
|
||||
ReplaceIcon(init, (uint8)UseWith[USED], i36BUSTA1DOSEA);
|
||||
} else
|
||||
sent = TRUE;
|
||||
|
||||
if (sa) { //se ha fatto l'azione di raccoglie controllo il testo delle coppe
|
||||
if (UseWith[WITH] == o3BCOPPABRACCIALI) {
|
||||
if (init.Obj[o3BSESTERZOBRACCIALI].flags & ON)
|
||||
init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer] = init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPABRACCIALI].text[2];
|
||||
else
|
||||
init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer] = init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPABRACCIALI].text[0];
|
||||
|
||||
init.Obj[o3BCOPPABRACCIALI].action[CurPlayer] = init.Obj[o3BCOPPABRACCIALI].action[CurPlayer ^ 1] = 0;
|
||||
} else if (UseWith[WITH] == o3BCOPPA) {
|
||||
if (init.Obj[o3BSESTERZO].flags & ON)
|
||||
init.Obj[o3BCOPPA].examine[CurPlayer] = init.Obj[o3BCOPPA].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPA].text[2];
|
||||
else
|
||||
init.Obj[o3BCOPPA].examine[CurPlayer] = init.Obj[o3BCOPPA].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPA].text[0];
|
||||
|
||||
init.Obj[o3BCOPPA].action[CurPlayer] = init.Obj[o3BCOPPA].action[CurPlayer ^ 1] = 0;
|
||||
}
|
||||
}//if sa
|
||||
} else
|
||||
sent = TRUE;
|
||||
break;
|
||||
case i2rBUSTAVUOTAB:
|
||||
if ((UseWith[WITH] == o36PIATTODX) && (init.Obj[o36INCENSODX].flags & ON)) {
|
||||
if (init.Obj[o36SESTERZOSX].flags & ON)
|
||||
sa = a36PBDM;
|
||||
else
|
||||
sa = a36PBDB;
|
||||
|
||||
ReplaceIcon(init, i2rBUSTAVUOTAB, i36BUSTA1DOSEB);
|
||||
} else if ((UseWith[WITH] == o36PIATTOSX) && (init.Obj[o36INCENSOSX].flags & ON)) {
|
||||
if (init.Obj[o36SESTERZODX].flags & ON)
|
||||
sa = a36PBSM;
|
||||
else
|
||||
sa = a36PBSB;
|
||||
|
||||
ReplaceIcon(init, i2rBUSTAVUOTAB, i36BUSTA1DOSEB);
|
||||
} else if (!(init.Obj[o3BCOPPA].flags & EXTRA)) {
|
||||
if ((UseWith[WITH] == o3BCOPPABRACCIALI) && (init.Obj[o3B2DOSIBRACCIALI].flags & ON)) {
|
||||
sa = a3B11;
|
||||
ReplaceIcon(init, (uint8)UseWith[USED], i36BUSTA2DOSIB);
|
||||
} else if ((UseWith[WITH] == o3BCOPPABRACCIALI) && (init.Obj[o3B1DOSEBRACCIALI].flags & ON)) {
|
||||
sa = a3B9;
|
||||
ReplaceIcon(init, (uint8)UseWith[USED], i36BUSTA1DOSEB);
|
||||
} else if ((UseWith[WITH] == o3BCOPPA) && (init.Obj[o3B2DOSI].flags & ON)) {
|
||||
sa = a3B12;
|
||||
ReplaceIcon(init, (uint8)UseWith[USED], i36BUSTA2DOSIB);
|
||||
} else if ((UseWith[WITH] == o3BCOPPA) && (init.Obj[o3B1DOSE].flags & ON)) {
|
||||
sa = a3B10;
|
||||
ReplaceIcon(init, (uint8)UseWith[USED], i36BUSTA1DOSEB);
|
||||
} else
|
||||
sent = TRUE;
|
||||
|
||||
if (sa) { //se ha fatto l'azione di raccoglie controllo il testo delle coppe
|
||||
if (UseWith[WITH] == o3BCOPPABRACCIALI) {
|
||||
if (init.Obj[o3BSESTERZOBRACCIALI].flags & ON)
|
||||
init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer] = init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPABRACCIALI].text[2];
|
||||
else
|
||||
init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer] = init.Obj[o3BCOPPABRACCIALI].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPABRACCIALI].text[0];
|
||||
|
||||
init.Obj[o3BCOPPABRACCIALI].action[CurPlayer] = init.Obj[o3BCOPPABRACCIALI].action[CurPlayer ^ 1] = 0;
|
||||
} else if (UseWith[WITH] == o3BCOPPA) {
|
||||
if (init.Obj[o3BSESTERZO].flags & ON)
|
||||
init.Obj[o3BCOPPA].examine[CurPlayer] = init.Obj[o3BCOPPA].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPA].text[2];
|
||||
else
|
||||
init.Obj[o3BCOPPA].examine[CurPlayer] = init.Obj[o3BCOPPA].examine[CurPlayer ^ 1] = init.Obj[o3BCOPPA].text[0];
|
||||
|
||||
init.Obj[o3BCOPPA].action[CurPlayer] = init.Obj[o3BCOPPA].action[CurPlayer ^ 1] = 0;
|
||||
}
|
||||
}//if sa
|
||||
} else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i46STELLA1:
|
||||
if (UseWith[WITH] == o45ALLOGGIAMENTO) {
|
||||
sa = a454;
|
||||
if (!(init.Obj[o45ALLOGGIAMENTO].flags & EXTRA2)) {
|
||||
IncCurTime(game, 10);
|
||||
init.Obj[o45ALLOGGIAMENTO].flags |= EXTRA2;
|
||||
}
|
||||
} else if (UseWith[WITH] == o46CERABRACERE)
|
||||
sa = a4619;
|
||||
else if ((UseWith[WITH] == o49INCAVODX) && !(init.Obj[o49STELLADXCIA].flags & ON)) {
|
||||
if (init.Obj[o49STELLASXCIA].flags & ON)
|
||||
sa = a493b;
|
||||
else
|
||||
sa = a493a;
|
||||
} else if ((UseWith[WITH] == o49INCAVOSX) && !(init.Obj[o49STELLASXCIA].flags & ON)) {
|
||||
if (init.Obj[o49STELLADXCIA].flags & ON)
|
||||
sa = a494b;
|
||||
else
|
||||
sa = a494a;
|
||||
} else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
case i46STELLA2:
|
||||
if ((UseWith[WITH] == o49INCAVODX) && !(init.Obj[o49STELLADX].flags & ON)) {
|
||||
if (init.Obj[o49STELLASX].flags & ON)
|
||||
sa = a493cb;
|
||||
else
|
||||
sa = a493ca;
|
||||
} else if ((UseWith[WITH] == o49INCAVOSX) && !(init.Obj[o49STELLASX].flags & ON)) {
|
||||
if (init.Obj[o49STELLADX].flags & ON)
|
||||
sa = a494cb;
|
||||
else
|
||||
sa = a494ca;
|
||||
} else
|
||||
sent = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (init.InvObj[UseWith[USED]].uwobj && (init.InvObj[UseWith[USED]].uwobj == UseWith[WITH]) && init.InvObj[UseWith[USED]].anim2[CurPlayer])
|
||||
sa = init.InvObj[UseWith[USED]].anim2[CurPlayer];
|
||||
else
|
||||
sent = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sent)
|
||||
if (!((bUseWith & UW_WITHI) && (UseWith[USED] == UseWith[WITH])))
|
||||
PlayerSpeak(game, init.InvObj[UseWith[USED]].action[CurPlayer]);
|
||||
|
||||
if (sa)
|
||||
StartAnim(game, sa);
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
33
engines/watchmaker/classes/do_inv_scr.h
Normal file
33
engines/watchmaker/classes/do_inv_scr.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_INV_SCR_H
|
||||
#define WATCHMAKER_DO_INV_SCR_H
|
||||
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doInvScrUseWith(WGame &game);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_INV_SCR_H
|
||||
715
engines/watchmaker/classes/do_keyboard.cpp
Normal file
715
engines/watchmaker/classes/do_keyboard.cpp
Normal file
@@ -0,0 +1,715 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_keyboard.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "watchmaker/3d/animation.h"
|
||||
#include "watchmaker/3d/geometry.h"
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/3d/t3d_mesh.h"
|
||||
#include "watchmaker/classes/do_camera.h"
|
||||
#include "watchmaker/classes/do_dialog.h"
|
||||
#include "watchmaker/classes/do_player.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/game.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/ll/ll_anim.h"
|
||||
#include "watchmaker/ll/ll_diary.h"
|
||||
#include "watchmaker/ll/ll_mesh.h"
|
||||
#include "watchmaker/ll/ll_mouse.h"
|
||||
#include "watchmaker/ll/ll_util.h"
|
||||
#include "watchmaker/main.h"
|
||||
#include "watchmaker/schedule.h"
|
||||
#include "watchmaker/t2d/t2d.h"
|
||||
#include "watchmaker/utils.h"
|
||||
#include "watchmaker/walk/act.h"
|
||||
#include "watchmaker/walk/walk.h"
|
||||
#include "watchmaker/walk/walkutil.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
t3dF32 AngleX, AngleY, AngleSpeed;
|
||||
char bFastAnim = 0;
|
||||
int32 PlayAnim = 351;
|
||||
char bBilinear = 1;
|
||||
char bForceDebug = 0;
|
||||
unsigned char KeyTable[Common::KEYCODE_LAST];
|
||||
|
||||
uint16 bnd_lev;
|
||||
|
||||
extern int16 NextDlg; //from doDialog.c
|
||||
extern uint8 tasti_per_sfx1; //from main.c
|
||||
|
||||
void t3dLoadOutdoorLights(const char *pname, t3dBODY *b, int32 ora);
|
||||
|
||||
void ProcessKBInput() {
|
||||
// TODO: Currently we're polling this in the PollEvent flow.
|
||||
return;
|
||||
#if 0
|
||||
int numKeys = 0;
|
||||
SDL_PumpEvents();
|
||||
auto keyState = SDL_GetKeyboardState(&numKeys);
|
||||
for (int i = 0; i < numKeys; i++) {
|
||||
KeyTable[i] = keyState[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < numKeys; i++) {
|
||||
if (keyState[i])
|
||||
KeyTable[i] = 0x80;
|
||||
else if ((KeyTable[i] != 0) && (!keyState[i]))
|
||||
KeyTable[i] = 0x10;
|
||||
else
|
||||
KeyTable[i] = 0x00;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool KeyDown(Common::KeyCode key) {
|
||||
if (KeyTable[key] & 0x80)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool KeyUp(Common::KeyCode key) {
|
||||
if (KeyTable[key] & 0x10) {
|
||||
KeyTable[key] = 0;
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void KeyClear(Common::KeyCode key) {
|
||||
KeyTable[key] = 0;
|
||||
}
|
||||
|
||||
bool DInputExclusiveMouse() {
|
||||
#if 0
|
||||
HWND hwnd = GetForegroundWindow();
|
||||
|
||||
g_pMouse->lpVtbl->Unacquire(g_pMouse);
|
||||
if (FAILED(g_pMouse->lpVtbl->SetCooperativeLevel(g_pMouse, hwnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND)))
|
||||
return FALSE;
|
||||
g_pMouse->lpVtbl->Acquire(g_pMouse);
|
||||
#endif
|
||||
LoaderFlags &= ~T3D_NONEXCLUSIVEMOUSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool DInputNonExclusiveMouse() {
|
||||
#if 0
|
||||
HWND hwnd = GetForegroundWindow();
|
||||
|
||||
g_pMouse->lpVtbl->Unacquire(g_pMouse);
|
||||
if (FAILED(g_pMouse->lpVtbl->SetCooperativeLevel(g_pMouse, hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND)))
|
||||
return FALSE;
|
||||
g_pMouse->lpVtbl->Acquire(g_pMouse);
|
||||
#endif
|
||||
LoaderFlags |= T3D_NONEXCLUSIVEMOUSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* -----------------25/08/98 10.42-------------------
|
||||
* HandleFirstPerson
|
||||
* --------------------------------------------------*/
|
||||
void HandleFirstPersonView(WGame &game) {
|
||||
t3dF32 dist;
|
||||
t3dV3F d, n;
|
||||
|
||||
if ((!Player) || (!t3dCurCamera) || (bLockCamera)) return;
|
||||
|
||||
if (KeyDown(Common::KEYCODE_a)) { // Alza testa
|
||||
if ((dist = CurFloorY + MAX_HEIGHT - (t3dCurCamera->Source.y + 10 * SCALEFACTOR)) > 0) {
|
||||
if (dist > 10 * SCALEFACTOR) dist = 10 * SCALEFACTOR;
|
||||
t3dVectInit(&d, 0.0f, dist, 0.0f);
|
||||
t3dMoveAndCheck1stCamera(t3dCurRoom, t3dCurCamera, &d);
|
||||
}
|
||||
} else if (KeyDown(Common::KEYCODE_z)) { // Abbassa Testa
|
||||
if ((dist = CurFloorY + KNEE_HEIGHT - (t3dCurCamera->Source.y - 10 * SCALEFACTOR)) < 0) {
|
||||
if (dist < -10 * SCALEFACTOR) dist = -10 * SCALEFACTOR;
|
||||
t3dVectInit(&d, 0.0f, dist, 0.0f);
|
||||
t3dMoveAndCheck1stCamera(t3dCurRoom, t3dCurCamera, &d);
|
||||
}
|
||||
}
|
||||
|
||||
// Se tengo premuto lo shift o un tasto del mouse
|
||||
if (KeyDown(Common::KEYCODE_LSHIFT) || KeyDown(Common::KEYCODE_RSHIFT) || ((bLPressed || bRPressed) && (mMove > 10))) {
|
||||
t3dVectSub(&d, &t3dCurCamera->Target, &t3dCurCamera->Source);
|
||||
d.y = 0.0f;
|
||||
t3dVectNormalize(&d);
|
||||
n.x = -d.z;
|
||||
n.y = 0.0f;
|
||||
n.z = d.x;
|
||||
|
||||
dist = (t3dF32)((t3dF32)mMoveY / (t3dF32)(MainDy / 2)) * 100.0f;
|
||||
if (KeyDown(Common::KEYCODE_UP))
|
||||
d *= (5 * SCALEFACTOR);
|
||||
else if (KeyDown(Common::KEYCODE_DOWN))
|
||||
d *= (-5 * SCALEFACTOR);
|
||||
else if (((bLPressed) || (bRPressed)) && (mMoveY) && !bClock33)
|
||||
d *= (-dist * SCALEFACTOR);
|
||||
else
|
||||
t3dVectFill(&d, 0.0f);
|
||||
|
||||
dist = (t3dF32)((t3dF32)mMoveX / (t3dF32)(MainDx / 2)) * 100.0f;
|
||||
if (KeyDown(Common::KEYCODE_LEFT))
|
||||
n *= (5 * SCALEFACTOR);
|
||||
else if (KeyDown(Common::KEYCODE_RIGHT))
|
||||
n *= (-5 * SCALEFACTOR);
|
||||
else if (((bLPressed) || (bRPressed)) && (mMoveX) && !bClock33)
|
||||
n *= (-dist * SCALEFACTOR);
|
||||
else
|
||||
t3dVectFill(&n, 0.0f);
|
||||
|
||||
t3dVectAdd(&d, &d, &n);
|
||||
t3dMoveAndCheck1stCamera(t3dCurRoom, t3dCurCamera, &d);
|
||||
} else {
|
||||
int32 x, y;
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
if (KeyDown(Common::KEYCODE_UP))
|
||||
y = -10;
|
||||
else if (KeyDown(Common::KEYCODE_DOWN))
|
||||
y = MainDy + 10;
|
||||
if (KeyDown(Common::KEYCODE_LEFT))
|
||||
x = -10;
|
||||
else if (KeyDown(Common::KEYCODE_RIGHT))
|
||||
x = MainDx + 10;
|
||||
|
||||
if (x || y) {
|
||||
t3dF32 diffx, diffy;
|
||||
diffx = 0.f;
|
||||
diffy = 0.f;
|
||||
|
||||
if (x > MainDx) diffx = (t3dF32)((t3dF32)(x - MainDx) / 3.0f);
|
||||
else if (x < 0) diffx = (t3dF32)((t3dF32)x / 3.0f);
|
||||
if (y > MainDy) diffy = (t3dF32)((t3dF32)(y - MainDy) / 3.0f);
|
||||
else if (y < 0) diffy = (t3dF32)((t3dF32)y / 3.0f);
|
||||
|
||||
game._cameraMan->MoveHeadAngles(diffx, diffy);
|
||||
}
|
||||
}
|
||||
|
||||
// Corregge Camera
|
||||
t3dVectCopy(&d, &Player->Mesh->Trasl);
|
||||
d.y = t3dCurCamera->Source.y;
|
||||
dist = KNEE_HEIGHT - t3dVectDistance(&t3dCurCamera->Source, &d);
|
||||
if (dist < 0.0f) {
|
||||
t3dVectSub(&d, &t3dCurCamera->Source, &d);
|
||||
d.y = 0.0f;
|
||||
t3dVectNormalize(&d);
|
||||
d *= dist;
|
||||
|
||||
t3dVectAdd(&t3dCurCamera->Source, &t3dCurCamera->Source, &d);
|
||||
t3dVectAdd(&t3dCurCamera->Target, &t3dCurCamera->Target, &d);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -----------------23/04/98 17.24-------------------
|
||||
* ProcessKeyboard
|
||||
* --------------------------------------------------*/
|
||||
|
||||
void ProcessKeyboard(WGame &game) {
|
||||
//warning("STUBBED: ProcessKeyboard");
|
||||
|
||||
t3dF32 TurnSpeed, Speed = 1.0f, dist;
|
||||
t3dV3F cp, cd, ct;
|
||||
int32 a, b;
|
||||
|
||||
AngleX = AngleY = AngleSpeed = 0.0f;
|
||||
TurnSpeed = 3.5f * FrameFactor;
|
||||
|
||||
doT2DKeyboard(game);
|
||||
|
||||
ProcessKBInput();
|
||||
|
||||
if (bIngnoreDIKeyboard)
|
||||
return ;
|
||||
|
||||
if (KeyUp(Common::KEYCODE_ESCAPE)) {
|
||||
if (LoaderFlags & T3D_DEBUGMODE) {
|
||||
CloseSys(game); // Quitta il gioco
|
||||
} else {
|
||||
// Skip Intro
|
||||
if ((CurDialog == dR000) || (CurDialog == dR111) || (CurDialog == dR211)) {
|
||||
NextDlg = dNULL;
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGEND_SKIPINTRO, MP_DEFAULT, (int16)CurDialog, mQUIT, 0, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
// Skip Loghi
|
||||
if (CurDialog == dRLOGHI)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGEND, MP_DEFAULT, (int16)CurDialog, mQUIT, 0, NULL, NULL, NULL);
|
||||
|
||||
// Skip MorteWM
|
||||
if (CurDialog == dR391)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGEND, MP_DEFAULT, (int16)CurDialog, mQUIT, 0, NULL, NULL, NULL);
|
||||
|
||||
// Skip durante i crediti, quitta
|
||||
if (bTitoliCodaScrolling || bTitoliCodaStatic)
|
||||
game.CleanUpAndPostQuit();
|
||||
}
|
||||
}// Common::KEYCODE_ESCAPE
|
||||
|
||||
//se ci sono i crediti ritorna (controlla solo l'ESC)
|
||||
if (bTitoliCodaStatic || bTitoliCodaScrolling) return;
|
||||
|
||||
if (KeyDown(Common::KEYCODE_LSHIFT) && KeyUp(Common::KEYCODE_d))
|
||||
bForceDebug ^= 1;
|
||||
|
||||
/* if( KeyDown(SDL_SCANCODE_LSHIFT) ) // Bomba il gioco
|
||||
if( KeyUp(SDL_SCANCODE_F) )
|
||||
{
|
||||
t3dFree(t3dCurRoom->CameraTable);
|
||||
t3dFree(t3dCurRoom->CameraTable);
|
||||
}
|
||||
*/
|
||||
if (KeyUp(Common::KEYCODE_i)) // Escono Informazioni
|
||||
bShowInfo ^= 1;
|
||||
|
||||
if (KeyUp(Common::KEYCODE_g)) {
|
||||
error("TODO: Screenshot support");
|
||||
#if 0
|
||||
FILE *fh;
|
||||
char str[32];
|
||||
int i;
|
||||
for (i = 1; i < 1000; i++) {
|
||||
sprintf(str, "Wm%#04d.tga", i);
|
||||
if ((fh = fopen(str, "rb")) == NULL)
|
||||
break;
|
||||
else
|
||||
fclose(fh);
|
||||
}
|
||||
rGrabVideo(str, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (KeyUp(Common::KEYCODE_END)) {
|
||||
if (!bFirstPerson)
|
||||
StartAnim(game, aGIRO);
|
||||
}
|
||||
|
||||
if ((LoaderFlags & T3D_DEBUGMODE) || bForceDebug) {
|
||||
if (KeyUp(Common::KEYCODE_F5))
|
||||
DataSave("Prova Save", 0);
|
||||
if (KeyUp(Common::KEYCODE_F6))
|
||||
DataLoad(game, "", 0);
|
||||
|
||||
if (KeyUp(Common::KEYCODE_w)) { // Modalita' wireframe
|
||||
bForceWire ^= 1;
|
||||
if (bForceWire)
|
||||
rSetRenderMode(rWIREFRAMEMODE);
|
||||
else
|
||||
rSetRenderMode(rSOLIDMODE);
|
||||
}
|
||||
|
||||
if (KeyUp(Common::KEYCODE_b)) // Escono BoundingBox
|
||||
bShowBoundingBox ^= 1;
|
||||
|
||||
if (KeyUp(Common::KEYCODE_BACKSPACE)) // Fa andare le animazioni piu' veloci
|
||||
bFastAnim ^= 1;
|
||||
|
||||
if (KeyUp(Common::KEYCODE_s))
|
||||
bSkipTalk = TRUE;
|
||||
|
||||
if (KeyUp(Common::KEYCODE_h))
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dPROVA, 0, 0, NULL, NULL, NULL);
|
||||
|
||||
if (KeyUp(Common::KEYCODE_e))
|
||||
StartAnim(game, aFOX);
|
||||
|
||||
if (KeyUp(Common::KEYCODE_j)) {
|
||||
if (Player && Player->Mesh) {
|
||||
ct = Player->Dir * HALF_STEP * 5.0f;
|
||||
t3dVectAdd(&Player->Mesh->Trasl, &Player->Mesh->Trasl, &ct);
|
||||
t3dVectCopy(&Player->Pos, &Player->Mesh->Trasl);
|
||||
}
|
||||
}
|
||||
|
||||
if (KeyUp(Common::KEYCODE_p)) {
|
||||
if (KeyDown(Common::KEYCODE_LSHIFT) || KeyDown(Common::KEYCODE_RSHIFT)) {
|
||||
if (++bnd_lev > 5) bnd_lev = 0;
|
||||
SetBndLevel(game, NULL, bnd_lev);
|
||||
DebugLogWindow("BndLev %d", bnd_lev);
|
||||
} else
|
||||
bShowPanels ^= 1; // Escono Pannelli
|
||||
|
||||
}
|
||||
|
||||
if (!tasti_per_sfx1) {
|
||||
if (KeyUp(Common::KEYCODE_m)) {
|
||||
if (KeyDown(Common::KEYCODE_LSHIFT))
|
||||
DInputNonExclusiveMouse();
|
||||
else if (KeyDown(Common::KEYCODE_RSHIFT))
|
||||
DInputExclusiveMouse();
|
||||
|
||||
}
|
||||
|
||||
if (KeyUp(Common::KEYCODE_o))
|
||||
bShowExtraLocalizationStrings ^= 1;
|
||||
} else {
|
||||
if (KeyUp(Common::KEYCODE_k)) {
|
||||
PlayAnim --;
|
||||
if (KeyDown(Common::KEYCODE_LCTRL) || KeyDown(Common::KEYCODE_RCTRL))
|
||||
PlayAnim -= 19;
|
||||
if (KeyDown(Common::KEYCODE_LSHIFT) || KeyDown(Common::KEYCODE_RSHIFT))
|
||||
PlayAnim -= 30;
|
||||
warning("PlayAnim %d '%s'\n", PlayAnim, game.init.Anim[PlayAnim].name[0].rawArray()); // TODO DebugString
|
||||
}
|
||||
if (KeyUp(Common::KEYCODE_l)) {
|
||||
PlayAnim ++;
|
||||
if (KeyDown(Common::KEYCODE_LCTRL) || KeyDown(Common::KEYCODE_RCTRL))
|
||||
PlayAnim += 19;
|
||||
if (KeyDown(Common::KEYCODE_LSHIFT) || KeyDown(Common::KEYCODE_RSHIFT))
|
||||
PlayAnim += 30;
|
||||
warning("PlayAnim %d '%s'\n", PlayAnim, game.init.Anim[PlayAnim].name[0].rawArray()); // TODO DebugString
|
||||
}
|
||||
if (KeyUp(Common::KEYCODE_m))
|
||||
StartAnim(game, PlayAnim);
|
||||
}
|
||||
|
||||
|
||||
if (KeyDown(Common::KEYCODE_LSHIFT)) {
|
||||
if (KeyUp(Common::KEYCODE_F1)) t3dLoadOutdoorLights("c:\\wm\\LMaps\\rxt.t3d", t3dRxt, 1030);
|
||||
if (KeyUp(Common::KEYCODE_F2)) t3dLoadOutdoorLights("c:\\wm\\LMaps\\rxt.t3d", t3dRxt, 1530);
|
||||
if (KeyUp(Common::KEYCODE_F3)) t3dLoadOutdoorLights("c:\\wm\\LMaps\\rxt.t3d", t3dRxt, 1930);
|
||||
if (KeyUp(Common::KEYCODE_F4)) t3dLoadOutdoorLights("c:\\wm\\LMaps\\rxt.t3d", t3dRxt, 2230);
|
||||
}
|
||||
|
||||
if (KeyUp(Common::KEYCODE_F11)) IncCurTime(game, 5);
|
||||
if (KeyUp(Common::KEYCODE_F12)) IncCurTime(game, 100);
|
||||
|
||||
if (KeyUp(Common::KEYCODE_1)) CharSetPosition(ocCURPLAYER, 1, NULL);
|
||||
if (KeyUp(Common::KEYCODE_2)) CharSetPosition(ocCURPLAYER, 2, NULL);
|
||||
if (KeyUp(Common::KEYCODE_3)) CharSetPosition(ocCURPLAYER, 3, NULL);
|
||||
if (KeyUp(Common::KEYCODE_4)) CharSetPosition(ocCURPLAYER, 4, NULL);
|
||||
if (KeyUp(Common::KEYCODE_5)) CharSetPosition(ocCURPLAYER, 5, NULL);
|
||||
if (KeyUp(Common::KEYCODE_6)) CharSetPosition(ocCURPLAYER, 6, NULL);
|
||||
if (KeyUp(Common::KEYCODE_7)) CharSetPosition(ocCURPLAYER, 7, NULL);
|
||||
if (KeyUp(Common::KEYCODE_8)) CharSetPosition(ocCURPLAYER, 8, NULL);
|
||||
if (KeyUp(Common::KEYCODE_9)) CharSetPosition(ocCURPLAYER, 9, NULL);
|
||||
if (KeyUp(Common::KEYCODE_KP0)) CharSetPosition(ocCURPLAYER, 10, NULL);
|
||||
if (KeyUp(Common::KEYCODE_KP1)) CharSetPosition(ocCURPLAYER, 11, NULL);
|
||||
if (KeyUp(Common::KEYCODE_KP2)) CharSetPosition(ocCURPLAYER, 12, NULL);
|
||||
if (KeyUp(Common::KEYCODE_KP3)) CharSetPosition(ocCURPLAYER, 13, NULL);
|
||||
if (KeyUp(Common::KEYCODE_KP4)) CharSetPosition(ocCURPLAYER, 14, NULL);
|
||||
if (KeyUp(Common::KEYCODE_KP5)) CharSetPosition(ocCURPLAYER, 15, NULL);
|
||||
if (KeyUp(Common::KEYCODE_KP6)) CharSetPosition(ocCURPLAYER, 16, NULL);
|
||||
if (KeyUp(Common::KEYCODE_KP7)) CharSetPosition(ocCURPLAYER, 17, NULL);
|
||||
if (KeyUp(Common::KEYCODE_KP8)) CharSetPosition(ocCURPLAYER, 18, NULL);
|
||||
if (KeyUp(Common::KEYCODE_KP9)) CharSetPosition(ocCURPLAYER, 19, NULL);
|
||||
|
||||
if (KeyDown(Common::KEYCODE_LSHIFT))
|
||||
if (KeyUp(Common::KEYCODE_x)) {
|
||||
tasti_per_sfx1 ^= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
if( KeyUp(SDL_SCANCODE_D) )
|
||||
Event( EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, 0, 0, tDIARIO, NULL, NULL, NULL );
|
||||
|
||||
if( KeyUp(SDL_SCANCODE_K) )
|
||||
{
|
||||
PlayAnim --;
|
||||
if( KeyDown(SDL_SCANCODE_LCONTROL) || KeyDown(SDL_SCANCODE_RCONTROL) )
|
||||
PlayAnim -= 19;
|
||||
if( KeyDown(SDL_SCANCODE_LSHIFT) || KeyDown(SDL_SCANCODE_RSHIFT) )
|
||||
PlayAnim -= 30;
|
||||
DebugString("PlayAnim %d '%s'",PlayAnim,Anim[PlayAnim].name[0]);
|
||||
}
|
||||
if( KeyUp(SDL_SCANCODE_L) )
|
||||
{
|
||||
PlayAnim ++;
|
||||
if( KeyDown(SDL_SCANCODE_LCONTROL) || KeyDown(SDL_SCANCODE_RCONTROL) )
|
||||
PlayAnim += 19;
|
||||
if( KeyDown(SDL_SCANCODE_LSHIFT) || KeyDown(SDL_SCANCODE_RSHIFT) )
|
||||
PlayAnim += 30;
|
||||
DebugString("PlayAnim %d '%s'",PlayAnim,Anim[PlayAnim].name[0]);
|
||||
}
|
||||
if( KeyUp(SDL_SCANCODE_M) )
|
||||
StartAnim( PlayAnim );
|
||||
|
||||
|
||||
if ( KeyUp(SDL_SCANCODE_X) )
|
||||
rSetBilinearFilterState( bBilinear ^= 1 );
|
||||
if( KeyUp(SDL_SCANCODE_T) ) // Scrive su file nome mesh
|
||||
DebugFile("%s",ObjectUnderCursor);
|
||||
if( KeyUp(SDL_SCANCODE_BACK) ) // Attiva modalita' frame-by-frame per le animazioni
|
||||
bPauseAllAnims ^= 1;
|
||||
if( KeyUp(SDL_SCANCODE_RETURN) ) // Avanza di un frame tutte le animazioni
|
||||
ContinueAnim( -1 );
|
||||
if( KeyUp(SDL_SCANCODE_S) )
|
||||
Event( EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR1a1, 0, 0, NULL, NULL, NULL );
|
||||
if( KeyUp(SDL_SCANCODE_N) )
|
||||
Event( EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, 0, 0, tPDA, NULL, NULL, NULL );
|
||||
if( KeyUp(SDL_SCANCODE_F) )
|
||||
Event( EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, 0, 0, tCOMPUTER, NULL, NULL, NULL );
|
||||
if( ( KeyDown(SDL_SCANCODE_LSHIFT) || KeyDown(SDL_SCANCODE_RSHIFT) ) && ( KeyDown(SDL_SCANCODE_F5) || KeyDown(SDL_SCANCODE_F6) ) )
|
||||
Event( EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, 0, 0, tOPTIONS, NULL, NULL, NULL );
|
||||
|
||||
if( KeyUp(SDL_SCANCODE_C) )
|
||||
{
|
||||
int i,len;
|
||||
char Name[200];
|
||||
if ( t3dCurRoom->CameraGrid.Grid)
|
||||
t3dFree(t3dCurRoom->CameraGrid.Grid);
|
||||
t3dCurRoom->CameraGrid.Grid=NULL;
|
||||
|
||||
for ( i=0; i<t3dCurRoom->NumPaths; i++)
|
||||
{
|
||||
if ( t3dCurRoom->CameraPath[i].PList)
|
||||
{
|
||||
t3dFree(t3dCurRoom->CameraPath[i].PList);
|
||||
t3dCurRoom->CameraPath[i].PList=NULL;
|
||||
}
|
||||
}
|
||||
t3dFree(t3dCurRoom->CameraPath);
|
||||
t3dCurRoom->CameraPath=NULL;
|
||||
|
||||
for ( i=0; i<t3dCurRoom->NumCameras; i++)
|
||||
{
|
||||
if ( t3dCurRoom->CameraTable[i].CameraPaths)
|
||||
{
|
||||
t3dFree(t3dCurRoom->CameraTable[i].CameraPaths);
|
||||
t3dCurRoom->CameraTable[i].CameraPaths=NULL;
|
||||
}
|
||||
}
|
||||
t3dFree(t3dCurRoom->CameraTable);
|
||||
t3dCurRoom->CameraTable=NULL;
|
||||
|
||||
strcpy(Name,WmCamDir);
|
||||
strcat(Name,t3dCurRoom->Name);
|
||||
len=strlen(Name);
|
||||
Name[len-3]='c';
|
||||
Name[len-2]='a';
|
||||
Name[len-1]='m';
|
||||
LoadCameras(Name,t3dCurRoom);
|
||||
t3dCurCamera = &t3dCurRoom->CameraTable[0];
|
||||
BigInvObj ++;
|
||||
// DebugLogFile("%d: %s %s",BigInvObj,ObjName[InvObj[BigInvObj].name],InvObj[BigInvObj].meshlink);
|
||||
}
|
||||
|
||||
if( KeyUp(SDL_SCANCODE_R) )
|
||||
rSetFogMode( RGBA_MAKE( 70, 0, 0, 0), 4000.0f, 8000.0f, 0.1f, D3DFOG_LINEAR );
|
||||
*/
|
||||
}// fine tasti di debug
|
||||
else {
|
||||
if (KeyUp(Common::KEYCODE_d))
|
||||
bShowRoomDescriptions ^= 1;
|
||||
|
||||
if (KeyUp(Common::KEYCODE_e))
|
||||
bShowExtraLocalizationStrings ^= 1;
|
||||
|
||||
if (KeyUp(Common::KEYCODE_p))
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, 0, 0, tPDA, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (KeyUp(Common::KEYCODE_F8) && PlayerCanSwitch(game._gameVars, 1) && !(InvStatus & INV_ON))
|
||||
// && ( (InvStatus & (INV_ON|INV_MODE2)) != (INV_ON|INV_MODE2) ) )
|
||||
{
|
||||
KeyClear(Common::KEYCODE_F8);
|
||||
if (CurPlayer == DARRELL) a = ocVICTORIA;
|
||||
else a = ocDARRELL;
|
||||
if (a == (ocDARRELL + CurPlayer)) return ;
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_SYSTEM, ME_STARTEFFECT, MP_DEFAULT, FRAME_PER_SECOND / 3, 0, EFFECT_FADOUT, NULL, NULL, NULL);
|
||||
if (bMovingCamera)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_SYSTEM, ME_CHANGEPLAYER, MP_WAITA | MP_WAIT_CAMERA, (int16)a, 0, 0, NULL, NULL, NULL);
|
||||
else
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_SYSTEM, ME_CHANGEPLAYER, MP_WAITA, (int16)a, 0, 0, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if ((bPlayerInAnim) || (bNotSkippableWalk) || (bDialogActive)) {
|
||||
KeyClear(Common::KEYCODE_F1);
|
||||
KeyClear(Common::KEYCODE_F2);
|
||||
KeyClear(Common::KEYCODE_F3);
|
||||
KeyClear(Common::KEYCODE_TAB);
|
||||
KeyClear(Common::KEYCODE_SPACE);
|
||||
KeyClear(Common::KEYCODE_LCTRL);
|
||||
KeyClear(Common::KEYCODE_RCTRL);
|
||||
KeyClear(Common::KEYCODE_END);
|
||||
return;
|
||||
}
|
||||
|
||||
if (KeyUp(Common::KEYCODE_F1) && !(InvStatus & INV_ON) && (bT2DActive == tNULL) && PlayerCanSave()) {
|
||||
rGrabVideo("temp.tmp", 1);
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, MPX_START_T2D_SAVE, 0, tOPTIONS, NULL, NULL, NULL);
|
||||
}
|
||||
if (KeyUp(Common::KEYCODE_F2) && !(InvStatus & INV_ON) && (bT2DActive == tNULL)) {
|
||||
rGrabVideo("temp.tmp", 1);
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, MPX_START_T2D_LOAD, 0, tOPTIONS, NULL, NULL, NULL);
|
||||
}
|
||||
if (KeyUp(Common::KEYCODE_F3) && !(InvStatus & INV_ON) && (bT2DActive == tNULL)) {
|
||||
rGrabVideo("temp.tmp", 1);
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, MPX_START_T2D_OPTIONS, 0, tOPTIONS, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
// Se Premo Control e sono vicino ad una porta o ad una scala
|
||||
if ((Player) && ((KeyUp(Common::KEYCODE_LCTRL)) || (KeyUp(Common::KEYCODE_RCTRL)))) {
|
||||
KeyClear(Common::KEYCODE_LCTRL);
|
||||
KeyClear(Common::KEYCODE_RCTRL);
|
||||
if (bSomeOneSpeak) bSkipTalk = TRUE;
|
||||
|
||||
game._cameraMan->GetRealCharPos(game.init, &ct, ocCURPLAYER, 0);
|
||||
ct.y = CurFloorY;
|
||||
for (a = 0; a < MAX_OBJS_IN_ROOM; a++) {
|
||||
b = game.getCurRoom().objects[a];
|
||||
if (((game.init.Obj[b].flags & DOOR) || (bPorteEsternoBloccate && (game.init.Obj[b].flags & DONE))) && (game.init.Obj[b].flags & ON) && !(game.init.Obj[b].flags & HIDE) && (game.init.Obj[b].pos) && (GetLightPosition(&cp, game.init.Obj[b].pos))) {
|
||||
GetLightDirection(&cd, game.init.Obj[b].pos);
|
||||
dist = t3dVectDistance(&ct, &cp);
|
||||
// Se sono abbastanza vicino a luce posizione
|
||||
if (dist < (CHEST_HEIGHT)) {
|
||||
t3dVectSub(&cd, &cd, &cp);
|
||||
dist = t3dVectAngle(&cd, &Player->Dir);
|
||||
if ((dist < 60.0f) && (dist > -60.0f)) {
|
||||
CurObj = b;
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_MOUSE, ME_MRIGHT, MP_DEFAULT, 0, 0, 0, &CurObj, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (KeyUp(Common::KEYCODE_SPACE) && (!IsPlayerInPool())) { // Cambia tra 3a e 1a persona
|
||||
if (bSomeOneSpeak) bSkipTalk = TRUE;
|
||||
|
||||
if ((bFirstPerson == 0) && (!bMovingCamera) && (!bNoFirstPersonSwitch)/* && !( InvStatus & INV_ON )*/)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_CAMERA, ME_CAMERA3TO1, MP_DEFAULT, 0, 0, 0, NULL, NULL, NULL);
|
||||
else if ((!bMovingCamera) && (!bNoFirstPersonSwitch)/* && !( InvStatus & INV_ON )*/)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_CAMERA, ME_CAMERA1TO3, MP_DEFAULT, 0, 0, 0, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (KeyUp(Common::KEYCODE_TAB) && !bLockCamera) // Fa uscire l'inventario
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_INVENTORY, ME_INVSWITCH, MP_DEFAULT, 0, 0, 0, NULL, NULL, NULL);
|
||||
|
||||
if (KeyDown(Common::KEYCODE_LEFT) && !(InvStatus & INV_ON) && !(bFirstPerson)) { // Ruota a Destra
|
||||
AngleY = (-1) * TurnSpeed / 180.0f * T3D_PI;
|
||||
if ((Player->Walk.CurAction <= aSTAND) || (Player->Walk.CurAction == aROT_DX)) {
|
||||
PlayerGotoPos[CurPlayer + ocDARRELL] = 0;
|
||||
PlayerPos[CurPlayer + ocDARRELL] = 0;
|
||||
Player->Walk.CurAction = aROT_SX;
|
||||
Player->Walk.CurFrame = ActionStart[Player->Walk.CurAction];
|
||||
Player->Mesh->CurFrame = Player->Walk.CurFrame;
|
||||
} else if (Player->Walk.CurAction == aROT_SX) {
|
||||
PlayerGotoPos[CurPlayer + ocDARRELL] = 0;
|
||||
PlayerPos[CurPlayer + ocDARRELL] = 0;
|
||||
Player->Walk.CurFrame ++;
|
||||
if (Player->Walk.CurFrame >= ActionStart[Player->Walk.CurAction + 1] - 1)
|
||||
Player->Walk.CurFrame = ActionStart[Player->Walk.CurAction];
|
||||
Player->Mesh->CurFrame = Player->Walk.CurFrame;
|
||||
}
|
||||
} else if (KeyDown(Common::KEYCODE_RIGHT) && !(InvStatus & INV_ON) && !(bFirstPerson)) { // Ruota a Sinistra
|
||||
AngleY = TurnSpeed / 180.0f * T3D_PI;
|
||||
if ((Player->Walk.CurAction <= aSTAND) || (Player->Walk.CurAction == aROT_SX)) {
|
||||
PlayerGotoPos[CurPlayer + ocDARRELL] = 0;
|
||||
PlayerPos[CurPlayer + ocDARRELL] = 0;
|
||||
Player->Walk.CurAction = aROT_DX;
|
||||
Player->Walk.CurFrame = ActionStart[Player->Walk.CurAction];
|
||||
Player->Mesh->CurFrame = Player->Walk.CurFrame;
|
||||
} else if (Player->Walk.CurAction == aROT_DX) {
|
||||
PlayerGotoPos[CurPlayer + ocDARRELL] = 0;
|
||||
PlayerPos[CurPlayer + ocDARRELL] = 0;
|
||||
Player->Walk.CurFrame ++;
|
||||
if (Player->Walk.CurFrame >= ActionStart[Player->Walk.CurAction + 1] - 1)
|
||||
Player->Walk.CurFrame = ActionStart[Player->Walk.CurAction];
|
||||
Player->Mesh->CurFrame = Player->Walk.CurFrame;
|
||||
}
|
||||
}
|
||||
|
||||
if (KeyDown(Common::KEYCODE_UP) && !(InvStatus & INV_ON) && !(bFirstPerson)) {
|
||||
AngleSpeed = 20.0f;
|
||||
} else if (KeyDown(Common::KEYCODE_DOWN) && !(InvStatus & INV_ON) && !(bFirstPerson)) {
|
||||
AngleSpeed = -20.0f;
|
||||
}
|
||||
|
||||
if (KeyDown(Common::KEYCODE_LSHIFT) || KeyDown(Common::KEYCODE_RSHIFT)) // || (GetKeyState(Common::KEYCODE_CAPSLOCK) & 0x1)) TODO: Allow for Caps-lock for fast walk
|
||||
bFastWalk = TRUE;
|
||||
else
|
||||
bFastWalk = FALSE;
|
||||
|
||||
if (!t3dCurCamera) return;
|
||||
|
||||
if ((bFirstPerson) && !(bMovingCamera))
|
||||
HandleFirstPersonView(game);
|
||||
|
||||
if (bFirstPerson) {
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_MOUSE, ME_MOUSEUPDATE, MP_DEFAULT, 0, 0, 0, NULL, NULL, NULL);
|
||||
AngleX = AngleY = AngleSpeed = 0.0f;
|
||||
if (Player)
|
||||
Player->Flags |= T3D_CHARACTER_HIDE;
|
||||
} else if (!(InvStatus & INV_ON) && (Player)) {
|
||||
UpdateChar(game, ocCURPLAYER, AngleSpeed * Speed, AngleY);
|
||||
AngleX = AngleY = AngleSpeed = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------28/09/98 17.18-------------------
|
||||
* doClock32
|
||||
* --------------------------------------------------*/
|
||||
void doClock33(WGame &game, int32 obj, t3dV3F *mp) {
|
||||
t3dMESH *l;
|
||||
t3dV3F tmp, pos;
|
||||
int32 i, r;
|
||||
|
||||
if (!bClock33) {
|
||||
bClock33 = (uint8)(obj - o33LANCETTAHSX + 1);
|
||||
if (game._gameVars.getCurRoomId() == r33)
|
||||
CharSetPosition(ocCURPLAYER, game.init.Obj[o33OROLOGIO].pos, nullptr);
|
||||
}
|
||||
|
||||
obj = (int32)bClock33 + o33LANCETTAHSX - 1;
|
||||
|
||||
// Trova il puntatore alla mesh
|
||||
if (!(l = LinkMeshToStr(game.init, game.init.Obj[obj].getMeshLink(0)))) return;
|
||||
// Trova il punto centrale attorno a cui ruotare
|
||||
pos.x = l->Pos.x;
|
||||
pos.y = 350.0f;
|
||||
pos.z = l->Pos.z;
|
||||
// Trova direzione della lancetta in base al mouse
|
||||
t3dVectSub(&tmp, mp, &pos);
|
||||
tmp.z = 0.0f;
|
||||
r = (int32)(SinCosAngle(-tmp.x, tmp.y) * 180.0f / T3D_PI) / 30;
|
||||
Comb33[bClock33 - 1] = (int32)r;
|
||||
// Azzera Bounding box (tornano in posizione centrale)
|
||||
for (i = 0; i < 8; i++) {
|
||||
t3dVectSub(&tmp, &l->BBox[i].p, &pos);
|
||||
t3dVectTransformInv(&l->BBox[i].p, &tmp, &Lanc33[obj - o33LANCETTAHSX]->Mesh->Matrix);
|
||||
}
|
||||
|
||||
t3dMatRot(&Lanc33[obj - o33LANCETTAHSX]->Mesh->Matrix, 0.0f, 0.0f, T3D_PI * (t3dF32)r / 6.0f);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
t3dVectTransform(&tmp, &l->BBox[i].p, &Lanc33[obj - o33LANCETTAHSX]->Mesh->Matrix);
|
||||
t3dVectAdd(&l->BBox[i].p, &tmp, &pos);
|
||||
}
|
||||
|
||||
t3dPlaneNormal(&l->BBoxNormal[0], &l->BBox[0].p, &l->BBox[2].p, &l->BBox[1].p); //front
|
||||
t3dPlaneNormal(&l->BBoxNormal[1], &l->BBox[4].p, &l->BBox[5].p, &l->BBox[6].p); //back
|
||||
t3dPlaneNormal(&l->BBoxNormal[2], &l->BBox[4].p, &l->BBox[0].p, &l->BBox[5].p); //Up
|
||||
t3dPlaneNormal(&l->BBoxNormal[3], &l->BBox[6].p, &l->BBox[7].p, &l->BBox[2].p); //Down
|
||||
t3dPlaneNormal(&l->BBoxNormal[4], &l->BBox[4].p, &l->BBox[6].p, &l->BBox[0].p); //Left
|
||||
t3dPlaneNormal(&l->BBoxNormal[5], &l->BBox[5].p, &l->BBox[1].p, &l->BBox[7].p); //Right
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
36
engines/watchmaker/classes/do_keyboard.h
Normal file
36
engines/watchmaker/classes/do_keyboard.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_KEYBOARD_H
|
||||
#define WATCHMAKER_DO_KEYBOARD_H
|
||||
|
||||
#include "watchmaker/globvar.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doClock33(WGame &game, int obj, struct t3dV3F *mp);
|
||||
void ProcessKeyboard(WGame &game);
|
||||
void ProcessKBInput();
|
||||
extern unsigned char KeyTable[];
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_KEYBOARD_H
|
||||
341
engines/watchmaker/classes/do_mouse.cpp
Normal file
341
engines/watchmaker/classes/do_mouse.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_mouse.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/ll/ll_mouse.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/3d/geometry.h"
|
||||
#include "watchmaker/classes/do_camera.h"
|
||||
#include "watchmaker/schedule.h"
|
||||
#include "watchmaker/classes/do_player.h"
|
||||
#include "watchmaker/main.h"
|
||||
#include "watchmaker/ll/ll_util.h"
|
||||
#include "watchmaker/classes/do_dialog.h"
|
||||
#include "watchmaker/classes/do_inv.h"
|
||||
#include "watchmaker/walk/act.h"
|
||||
#include "watchmaker/3d/animation.h"
|
||||
#include "watchmaker/classes/do_string.h"
|
||||
#include "watchmaker/classes/do_keyboard.h"
|
||||
#include "watchmaker/ll/ll_diary.h"
|
||||
#include "watchmaker/ll/ll_string.h"
|
||||
#include "watchmaker/t2d/t2d.h"
|
||||
#include "watchmaker/walk/walk.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
// locals
|
||||
t3dV3F LastClickPos;
|
||||
uint8 LastFloorHit;
|
||||
|
||||
void doMouseButton(WGame &game) {
|
||||
uint8 cp;
|
||||
Init &init = game.init;
|
||||
Renderer &renderer = *game._renderer;
|
||||
|
||||
if (bT2DActive) {
|
||||
doT2DMouse(game);
|
||||
return ;
|
||||
}
|
||||
if (bSomeOneSpeak && !bNotSkippableSent) {
|
||||
/*DebugLogWindow("skip");*/bSkipTalk = true;
|
||||
return;
|
||||
}
|
||||
if (bDialogActive) {
|
||||
UpdateDialogMenu(game, TheMessage->wparam1, TheMessage->wparam2, TheMessage->event);
|
||||
return;
|
||||
}
|
||||
if ((bPlayerInAnim) || (bNotSkippableWalk) || (bMovingCamera)) return;
|
||||
if (mHide) mHide = false;
|
||||
if ((bClock33) || (CurObj == o33LANCETTAMSX) || (CurObj == o33LANCETTAHSX) || (CurObj == o33LANCETTAMDX) || (CurObj == o33LANCETTAHDX)) return;
|
||||
CurInvObj = 0;
|
||||
CurObj = 0;
|
||||
|
||||
// se sono su inventario
|
||||
if (InvStatus & INV_ON) {
|
||||
if ((InvStatus & INV_ON) && (InvStatus & INV_MODE1) && PlayerCanCall(game._gameVars)) {
|
||||
if (CheckRect(renderer, game._gameRect._callOtherPlayerRect, TheMessage->wparam1, TheMessage->wparam2)) {
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dRCALLOTHERPLAYER, 0, 0, nullptr, nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CurInvObj = WhatIcon(*game._renderer, TheMessage->wparam1, TheMessage->wparam2);
|
||||
|
||||
if ((CurInvObj == iNULL) && (InvStatus & INV_MODE2) && CheckRect(renderer, game._gameRect._bigIconRect, TheMessage->wparam1, TheMessage->wparam2))
|
||||
CurInvObj = BigInvObj;
|
||||
|
||||
if (CurInvObj == iNULL) {
|
||||
// se ho cliccato su icona grande
|
||||
if (InvStatus & INV_MODE2) {
|
||||
if (CheckRect(renderer, game._gameRect._inv1Up, TheMessage->wparam1, TheMessage->wparam2))
|
||||
InventoryUp();
|
||||
else if (CheckRect(renderer, game._gameRect._inv1Down, TheMessage->wparam1, TheMessage->wparam2))
|
||||
InventoryDown();
|
||||
else if (CheckRect(renderer, game._gameRect._closeInvRect, TheMessage->wparam1, TheMessage->wparam2)) {
|
||||
if (InvStatus & INV_MODE4) {
|
||||
CurPlayer ^= 1;
|
||||
ChangePlayer(game, (uint8)((CurPlayer ^ 1) + ocDARRELL));
|
||||
}
|
||||
|
||||
InvStatus = INV_OFF;
|
||||
game._cameraMan->resetAngle();
|
||||
game._cameraMan->GetCameraTarget(init, &t3dCurCamera->Target);
|
||||
|
||||
if (bFirstPerson)
|
||||
game._renderer->setCurCameraViewport(CAMERA_FOV_1ST, bSuperView);
|
||||
else
|
||||
game._renderer->setCurCameraViewport(t3dCurCamera->Fov, bSuperView);
|
||||
|
||||
BigInvObj = iNULL;
|
||||
} else if (CheckRect(renderer, game._gameRect._quitGameRect, TheMessage->wparam1, TheMessage->wparam2))
|
||||
CloseSys(game);
|
||||
else if (CheckRect(renderer, game._gameRect._invSaveRect, TheMessage->wparam1, TheMessage->wparam2) && !(InvStatus & INV_MODE4) && PlayerCanSave())
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, MPX_START_T2D_SAVE, 0, tOPTIONS, nullptr, nullptr, nullptr);
|
||||
else if (CheckRect(renderer, game._gameRect._invLoadRect, TheMessage->wparam1, TheMessage->wparam2) && !(InvStatus & INV_MODE4))
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, MPX_START_T2D_LOAD, 0, tOPTIONS, nullptr, nullptr, nullptr);
|
||||
else if (CheckRect(renderer, game._gameRect._invOptionsRect, TheMessage->wparam1, TheMessage->wparam2) && !(InvStatus & INV_MODE4))
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, MPX_START_T2D_OPTIONS, 0, tOPTIONS, nullptr, nullptr, nullptr);
|
||||
else {
|
||||
ClearUseWith();
|
||||
if ((CheckRect(renderer, game._gameRect._playerInvRect, TheMessage->wparam1, TheMessage->wparam2)) || (InvStatus & INV_MODE4)) {
|
||||
if (PlayerCanSwitch(game._gameVars, 0)) {
|
||||
InvStatus ^= INV_MODE4;
|
||||
CurPlayer ^= VICTORIA;
|
||||
BigInvObj = iNULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (CheckRect(renderer, game._gameRect._inv1Up, TheMessage->wparam1, TheMessage->wparam2))
|
||||
InventoryUp();
|
||||
else if (CheckRect(renderer, game._gameRect._inv1Down, TheMessage->wparam1, TheMessage->wparam2))
|
||||
InventoryDown();
|
||||
else {
|
||||
|
||||
InvStatus = INV_OFF;
|
||||
ClearUseWith();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ((BigInvObj != CurInvObj) && !(bUseWith & UW_ON)) {
|
||||
t3dMatIdentity(&game.init._globals._invVars.BigIconM);
|
||||
BigInvObj = CurInvObj;
|
||||
}
|
||||
|
||||
if (TheMessage->event == ME_MRIGHT)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_INVENTORY, ME_OPERATEICON, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, 0, &CurInvObj, nullptr, nullptr);
|
||||
else if (bUseWith & UW_ON)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_INVENTORY, ME_OPERATEICON, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, 0, &CurInvObj, nullptr, nullptr);
|
||||
else
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_INVENTORY, ME_EXAMINEICON, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, 0, &CurInvObj, nullptr, nullptr);
|
||||
|
||||
//if( ( InvStatus & INV_MODE2 ) && CheckRect(BigIconRect,TheMessage->wparam1,TheMessage->wparam2) )
|
||||
//CurInvObj = iNULL;
|
||||
|
||||
return;
|
||||
} else if ((bUseWith & UW_ON) && (bUseWith & UW_USEDI) && CheckRect(renderer, game._gameRect._useIconRect, TheMessage->wparam1, TheMessage->wparam2)) {
|
||||
ClearUseWith();
|
||||
ClearText();
|
||||
return;
|
||||
}
|
||||
|
||||
// se sono su area gioco
|
||||
cp = 0;
|
||||
PlayerGotoPos[CurPlayer + ocDARRELL] = 0;
|
||||
NextPortalObj = oNULL;
|
||||
NextPortalAnim = aNULL;
|
||||
// se gli ho gia' passato che oggetto deve trovare
|
||||
if ((CurObj = TheMessage->lparam[0])) {
|
||||
// se era per un passaggio di portale, cancella l'oggetto
|
||||
if (CurObj == oNEXTPORTAL) CurObj = oNULL;
|
||||
// Ripristina informazioni
|
||||
bFastWalk = (uint8)TheMessage->lparam[2];
|
||||
FloorHit = LastFloorHit;
|
||||
t3dVectCopy(&mPos, &LastClickPos);
|
||||
} else {
|
||||
// Cerca l'oggetto su cui ho cliccato
|
||||
CurObj = WhatObj(game, TheMessage->wparam1, TheMessage->wparam2, TheMessage->event);
|
||||
// Se sono su albero e clicco fuori dal nido, simulo un cambio portale
|
||||
if (bPlayerSuBasamento &&
|
||||
(CurObj != oXT14ALBERO) && (CurObj != oXT14BASAMENTO) && (CurObj != oXT14NIDO_da_sopra_il_basamento) && (CurObj != oXT14OCCHIALI)) {
|
||||
NextPortalObj = CurObj;
|
||||
NextPortalAnim = a145;
|
||||
}
|
||||
|
||||
// se non e' stato cliccato nessun oggetto e un oggetto era gia' selezionato dall'inventario il tasto
|
||||
// destro del mouse elimina questa selezione (nd Fox)
|
||||
if ((CurObj == oNULL) && (bUseWith) && (TheMessage->event == ME_MRIGHT)) {
|
||||
ClearUseWith();
|
||||
return;
|
||||
}
|
||||
|
||||
// Salva informazioni
|
||||
LastFloorHit = FloorHit;
|
||||
t3dVectCopy(&LastClickPos, &mPos);
|
||||
}
|
||||
if (bFirstPerson && FromFirstPersonAnim && (!CurObj || (CurObj && (!(init.Obj[CurObj].flags & NOSWITCH))))) {
|
||||
if (CurObj)
|
||||
NextPortalObj = CurObj;
|
||||
else
|
||||
NextPortalObj = oNEXTPORTAL;
|
||||
NextPortalAnim = FromFirstPersonAnim;
|
||||
FromFirstPersonAnim = aNULL;
|
||||
}
|
||||
// Se ha cliccato in un altro portale e c'e' un'animazione di link
|
||||
if ((NextPortalObj) && (NextPortalAnim)) {
|
||||
// Prende luce di posizione dall'animazione
|
||||
cp = init.Anim[NextPortalAnim].pos;
|
||||
PlayerGotoPos[CurPlayer + ocDARRELL] = GetLightPosition(&mPos, cp);
|
||||
// Simula un click per terra
|
||||
CurObj = oNULL;
|
||||
FloorHit = 1;
|
||||
} else if ((CurObj) && !(NextPortalObj) && (init.Obj[CurObj].pos != 0)) {
|
||||
// altrimenti prova a prendere la luce di posizione
|
||||
cp = init.Obj[CurObj].pos;
|
||||
PlayerGotoPos[CurPlayer + ocDARRELL] = GetLightPosition(&mPos, cp);
|
||||
FloorHit = 1;
|
||||
}
|
||||
// Se deve prendere sempre un click col destro
|
||||
if (init.Obj[CurObj].flags & FORCERIGHT) TheMessage->event = ME_MRIGHT;
|
||||
// Cammina solo; nessuno oggetto o nessuna posizione o posizione diversa e non sono in closeup
|
||||
if ((!CurObj) || ((PlayerGotoPos[CurPlayer + ocDARRELL]) && (PlayerGotoPos[CurPlayer + ocDARRELL] != PlayerPos[CurPlayer + ocDARRELL])) || (!PlayerGotoPos[CurPlayer + ocDARRELL])) {
|
||||
CheckCharacterWithBounds(game, ocCURPLAYER, &mPos, cp, 10);
|
||||
|
||||
// Se ho cliccato in un altro portale dice di contiunare la camminata
|
||||
if ((NextPortalObj) && (NextPortalAnim))
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_MOUSE, TheMessage->event, MP_WAIT_ANIM, 0, 0, 0, &NextPortalObj, nullptr, &bFastWalk);
|
||||
else if (NextPortalObj)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_MOUSE, TheMessage->event, MP_WAIT_PORTAL, 0, 0, 0, &NextPortalObj, nullptr, &bFastWalk);
|
||||
|
||||
// Se sono in prima torno in terza, a meno che l'oggetto non mi obblighi a restare in prima
|
||||
if (bFirstPerson && !bNoFirstPersonSwitch && (!CurObj || (CurObj && (!(init.Obj[CurObj].flags & NOSWITCH) || (Player->Walk.Check & LONGPATH)))))
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_CAMERA, ME_CAMERA1TO3, MP_DEFAULT, 0, 0, 0, nullptr, nullptr, nullptr);
|
||||
//? else if( bFirstPerson )
|
||||
//? CharStop( ocCURPLAYER );
|
||||
}
|
||||
// Rimuove tutti gli eventi del personaggio
|
||||
game._messageSystem.removeEvent(EventClass::MC_PLAYER, ME_ALL);
|
||||
if (CurObj) { // se ho cliccato su un oggetto valido
|
||||
if (TheMessage->event == ME_MLEFT) // se ho cliccato con sinistro
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_PLAYER, ME_PLAYERGOTOEXAMINE, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, bFirstPerson, &CurObj, nullptr, nullptr);
|
||||
else if (TheMessage->event == ME_MRIGHT) { // se ho cliccato con destro
|
||||
if ((init.Obj[CurObj].flags & USEWITH) && !(bUseWith)) { // se ho cliccato su un oggetto usacon
|
||||
Player->Walk.NumSteps = 0; // Simula un PlayerStop
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_ACTION, ME_MOUSEOPERATE, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, bFirstPerson, &CurObj, nullptr, nullptr);
|
||||
} else
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_PLAYER, ME_PLAYERGOTOACTION, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, bFirstPerson, &CurObj, nullptr, nullptr);
|
||||
}
|
||||
} else // se non ho cliccato su niente
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_PLAYER, ME_PLAYERGOTO, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, bFirstPerson, nullptr, &NextPortalAnim, nullptr);
|
||||
}
|
||||
|
||||
void doMouseUpdate(WGame &game) {
|
||||
Init &init = game.init;
|
||||
Renderer &renderer = *game._renderer;
|
||||
|
||||
if (bT2DActive) {
|
||||
doT2DMouse(game);
|
||||
return ;
|
||||
}
|
||||
if (bDialogActive) {
|
||||
UpdateDialogMenu(game, TheMessage->wparam1, TheMessage->wparam2, TheMessage->event);
|
||||
return;
|
||||
}
|
||||
if (/*( mHide ) ||*/ (bSomeOneSpeak)) return;
|
||||
if (!TheMessage->wparam1 && !TheMessage->wparam2) return;
|
||||
if ((bPlayerInAnim) || (bNotSkippableWalk) || (mHide) || (bMovingCamera)) return;
|
||||
|
||||
CurObj = 0;
|
||||
CurInvObj = 0;
|
||||
//DebugFile("MM %d %d",TheMessage->wparam1, TheMessage->wparam2 );
|
||||
|
||||
// se sono su inventario
|
||||
if (InvStatus & INV_ON) {
|
||||
if ((bLPressed) && (InvStatus & INV_MODE2)) {
|
||||
t3dM3X3F t;
|
||||
t3dMatRot(&t, ((t3dF32)(TheMessage->lparam[1]) / (t3dF32)(game._gameRect._bigIconRect.y2 - game._gameRect._bigIconRect.y1))*T3D_PI * 2.0f,
|
||||
((t3dF32)(TheMessage->lparam[0]) / (t3dF32)(game._gameRect._bigIconRect.x1 - game._gameRect._bigIconRect.x2))*T3D_PI * 2.0f, 0.0f);
|
||||
t3dMatMul(&game.init._globals._invVars.BigIconM, &t, &game.init._globals._invVars.BigIconM);
|
||||
CurInvObj = BigInvObj;
|
||||
} else {
|
||||
CurInvObj = WhatIcon(*game._renderer, TheMessage->wparam1, TheMessage->wparam2);
|
||||
if ((CurInvObj == iNULL) && CheckRect(renderer, game._gameRect._bigIconRect, TheMessage->wparam1, TheMessage->wparam2))
|
||||
CurInvObj = BigInvObj;
|
||||
ShowInvObjName(init, CurInvObj);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// se sono su area gioco
|
||||
CurObj = WhatObj(game, TheMessage->wparam1, TheMessage->wparam2, TheMessage->event);
|
||||
|
||||
if ((bLPressed || bRPressed) && ((bClock33) || (CurObj == o33LANCETTAMSX) || (CurObj == o33LANCETTAHSX) || (CurObj == o33LANCETTAMDX) || (CurObj == o33LANCETTAHDX)))
|
||||
doClock33(game, CurObj, &mPos);
|
||||
else {
|
||||
if (bClock33) {
|
||||
if ((Comb33[0] == 7) && (Comb33[1] == 2) && (Comb33[2] == 9) && (Comb33[3] == 11) && IconInInv(init, i19FOGLIO1)) {
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_CAMERA, ME_CAMERA1TO3, MP_DEFAULT, 0, 0, 0, nullptr, nullptr, nullptr);
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_ANIM, ME_STARTANIM, MP_WAIT_CAMERA, a336, 0, 0, nullptr, nullptr, nullptr);
|
||||
|
||||
if (!(init.Obj[o33LANCETTAHSX].flags & EXTRA2)) {
|
||||
IncCurTime(game, 15);
|
||||
init.Obj[o33LANCETTAHSX].flags |= EXTRA2;
|
||||
}
|
||||
}
|
||||
bClock33 = false;
|
||||
}
|
||||
ShowObjName(init, CurObj);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------17/03/98 17.16-------------------
|
||||
* doMouse
|
||||
* --------------------------------------------------*/
|
||||
void doMouse(WGame &game) {
|
||||
//se ci sono i crediti ritorna
|
||||
if (bTitoliCodaStatic || bTitoliCodaScrolling) return;
|
||||
|
||||
switch (TheMessage->event) {
|
||||
case ME_MRIGHT:
|
||||
case ME_MLEFT:
|
||||
doMouseButton(game);
|
||||
break;
|
||||
case ME_MOUSEUPDATE :
|
||||
doMouseUpdate(game);
|
||||
break;
|
||||
case ME_MOUSEHIDE :
|
||||
if ((mCounter++ > 20) && !(mHide))
|
||||
mHide = 1;
|
||||
ClearText();
|
||||
break;
|
||||
case ME_MOUSEUNHIDE :
|
||||
mHide = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
34
engines/watchmaker/classes/do_mouse.h
Normal file
34
engines/watchmaker/classes/do_mouse.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_MOUSE_H
|
||||
#define WATCHMAKER_DO_MOUSE_H
|
||||
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doMouse(WGame &game);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_MOUSE_H
|
||||
1039
engines/watchmaker/classes/do_operate.cpp
Normal file
1039
engines/watchmaker/classes/do_operate.cpp
Normal file
File diff suppressed because it is too large
Load Diff
35
engines/watchmaker/classes/do_operate.h
Normal file
35
engines/watchmaker/classes/do_operate.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_OPERATE_H
|
||||
#define WATCHMAKER_DO_OPERATE_H
|
||||
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void UpdateSpecial(WGame &game, int32 room);
|
||||
void doOperate(WGame &game, int32 obj);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_OPERATE_H
|
||||
516
engines/watchmaker/classes/do_player.cpp
Normal file
516
engines/watchmaker/classes/do_player.cpp
Normal file
@@ -0,0 +1,516 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_player.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/walk/act.h"
|
||||
#include "watchmaker/utils.h"
|
||||
#include "watchmaker/3d/t3d_body.h"
|
||||
#include "watchmaker/3d/t3d_mesh.h"
|
||||
#include "watchmaker/3d/geometry.h"
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/3d/animation.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/schedule.h"
|
||||
#include "watchmaker/ll/ll_anim.h"
|
||||
#include "watchmaker/ll/ll_util.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/ll/ll_diary.h"
|
||||
#include "watchmaker/walk/walk.h"
|
||||
#include "watchmaker/classes/do_sound.h"
|
||||
#include "watchmaker/classes/do_string.h"
|
||||
#include "watchmaker/ll/ll_mesh.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
// locals
|
||||
#define BLEND_INC 65
|
||||
t3dV3F SerraRect[2] = { { -6939.0f, 0.0f, -8396.0f }, { 6679.0f, 0.0f, -16561.0f } };
|
||||
t3dV3F KreenRect1[2] = { { -1482.0f, 0.0f, -12162.0f }, { -1207.0f, 0.0f, -12586.0f } };
|
||||
t3dV3F KreenRect2[2] = { { -1042.0f, 0.0f, -12162.0f }, { -766.0f, 0.0f, -12586.0f } };
|
||||
t3dF32 KrennX = -600.0f;
|
||||
t3dF32 KrennZ = -12570.0f;
|
||||
t3dF32 CacciatoreXleft = -7450.0f;
|
||||
t3dF32 CacciatoreXright = 8400.0f;
|
||||
t3dF32 CacciatoreZright = -14701.0f;
|
||||
t3dF32 r47CoordX = -2125.0f;
|
||||
|
||||
/* -----------------08/10/00 11.55-------------------
|
||||
* SetCurPlayerPosTo_9x()
|
||||
* --------------------------------------------------*/
|
||||
void SetCurPlayerPosTo_9x(GameVars &gameVars, Init &init) {
|
||||
// Setto il player nella posizione 91 o 92 (o successive) se esistono
|
||||
t3dV3F dest;
|
||||
uint8 pos, start_pos, found_pos;
|
||||
|
||||
pos = 0;
|
||||
start_pos = 0;
|
||||
found_pos = 0;
|
||||
|
||||
if (CurPlayer == DARRELL) start_pos = 91;
|
||||
if (CurPlayer == VICTORIA) start_pos = 92;
|
||||
|
||||
// caso particolare nella r42, quando i personaggi potrebbero essere al di la' del portone
|
||||
if ((gameVars.getCurRoomId() == r42) && (init.Dialog[dR421_fine].flags & DIALOG_DONE)) {
|
||||
if (CurPlayer == DARRELL) start_pos = 93;
|
||||
}
|
||||
if ((gameVars.getCurRoomId() == r42) && (init.Dialog[dR42_porta].flags & DIALOG_DONE)) {
|
||||
if (CurPlayer == VICTORIA) start_pos = 94;
|
||||
}
|
||||
|
||||
// caso particolare: quando con Victoria non posso entrare nel castello ma devo tirare il lucchetto, faccio
|
||||
// in modo che quando carico lei si posizioni vicino alla finestra e non a cozze
|
||||
if (bPorteEsternoBloccate && (gameVars.getCurRoomId() == rXT)) {
|
||||
if (CurPlayer == VICTORIA) start_pos = 96;
|
||||
}
|
||||
|
||||
for (pos = start_pos; pos <= 98; pos += 2) {
|
||||
if (!GetLightPosition(&dest, pos)) continue;
|
||||
|
||||
found_pos = pos;
|
||||
break;
|
||||
}//for
|
||||
|
||||
if (found_pos) {
|
||||
CharSetPosition(CurPlayer + ocDARRELL, found_pos, nullptr);
|
||||
warning("SETTATA POSITION: %d, %d", CurPlayer, start_pos);
|
||||
} else {
|
||||
t3dVectCopy(&Player->Pos, &t3dCurCamera->Target);
|
||||
t3dVectCopy(&Player->Mesh->Trasl, &t3dCurCamera->Target);
|
||||
warning("SETTATA POSITION SU CAMERATARGET: %d", CurPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------17/03/98 17.16-------------------
|
||||
* doMouse
|
||||
* --------------------------------------------------*/
|
||||
void doPlayer(WGame &game) {
|
||||
switch (TheMessage->event) {
|
||||
case ME_PLAYERIDLE:
|
||||
// Parte animazione di idle
|
||||
if ((int32)TheTime > TheMessage->lparam[0]) {
|
||||
StopObjAnim(game, TheMessage->wparam1);
|
||||
//DebugString("Idle %d at %d",TheMessage->wparam1,TheMessage->lparam[0]);
|
||||
} else {
|
||||
TheMessage->flags |= MP_WAIT_RETRACE;
|
||||
//DebugString("NO %d",TheMessage->lparam[0]-TheTime);
|
||||
ReEvent();
|
||||
}
|
||||
break;
|
||||
|
||||
case ME_PLAYERGOTO:
|
||||
case ME_PLAYERGOTOEXAMINE:
|
||||
case ME_PLAYERGOTOACTION:
|
||||
case ME_PLAYERGOTOEXIT:
|
||||
case ME_PLAYERGOTONOSKIP:
|
||||
if (CharNextFrame(game, ocCURPLAYER)) {
|
||||
TheMessage->flags |= MP_WAIT_RETRACE;
|
||||
ReEvent();
|
||||
} else {
|
||||
// se sono partito dalla prima persona, torna in prima persona
|
||||
// if ( TheMessage->bparam )
|
||||
// Event( EventClass::MC_CAMERA, ME_CAMERA3TO1, MP_DEFAULT, 0, 0, 0, NULL, NULL, NULL );
|
||||
|
||||
if (Player)
|
||||
Player->Walk.NumPathNodes = Player->Walk.CurrentStep = Player->Walk.NumSteps = bNotSkippableWalk = 0;
|
||||
|
||||
if ((!bDialogActive) || (TimeWalk == CurPlayer + ocDARRELL) || (TimeWalk == ocCURPLAYER))
|
||||
_vm->_messageSystem.addWaitingMsgs(MP_WAIT_ACT);
|
||||
|
||||
if (TheMessage->event == ME_PLAYERGOTOEXAMINE)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_ACTION, ME_MOUSEEXAMINE, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, 0, &TheMessage->lparam[0], nullptr, nullptr);
|
||||
else if (TheMessage->event == ME_PLAYERGOTOACTION)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_ACTION, ME_MOUSEOPERATE, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, 0, &TheMessage->lparam[0], nullptr, nullptr);
|
||||
else if ((TheMessage->event == ME_PLAYERGOTO) && (TheMessage->lparam[1]))
|
||||
StartAnim(game, TheMessage->lparam[1]);
|
||||
|
||||
/*?? if( TheMessage->lparam[0] )
|
||||
{
|
||||
if( (bFirstPerson) && (Obj[TheMessage->lparam[0]].flags & HIDEIN1ST) )
|
||||
Event( EventClass::MC_CAMERA, ME_CAMERA1TO3, MP_DEFAULT, 0, 0, 0, NULL, NULL, NULL );
|
||||
else if( !(bFirstPerson) && (Obj[TheMessage->lparam[0]].flags & HIDEIN3RD) )
|
||||
Event( EventClass::MC_CAMERA, ME_CAMERA3TO1, MP_DEFAULT, 0, 0, Obj[TheMessage->lparam[0]].pos, NULL, NULL, NULL );
|
||||
}*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------02/10/98 10.17-------------------
|
||||
* ProcessCharacters
|
||||
* --------------------------------------------------*/
|
||||
void ProcessCharacters(WGame &game) {
|
||||
int32 i, na, nf;
|
||||
uint8 cbi;
|
||||
t3dMESH *m;
|
||||
t3dCHARACTER *c;
|
||||
|
||||
for (i = 0; i < T3D_MAX_CHARACTERS; i++)
|
||||
if (Character[i] && (Character[i] != Player) && (Character[i]->Walk.NumSteps))
|
||||
if (!CharNextFrame(game, i))
|
||||
if ((bDialogActive) && (TimeWalk == i))
|
||||
_vm->_messageSystem.addWaitingMsgs(MP_WAIT_ACT);
|
||||
|
||||
for (i = 0; i < T3D_MAX_CHARACTERS; i++) {
|
||||
c = Character[i];
|
||||
if (c && (i != ocCURPLAYER) && !(c->Flags & T3D_CHARACTER_HIDE)) {
|
||||
nf = c->Walk.CurFrame;
|
||||
na = c->Walk.CurAction;
|
||||
if ((na == aWALK_START) || (na == aWALK_LOOP) || (na == aWALK_END)) {
|
||||
if ((nf == 81) || (nf == 171)) StartStepSound(game, &c->Pos, SOUND_PSX);
|
||||
else if ((nf == 36) || (nf == 126) || (nf == 216)) StartStepSound(game, &c->Pos, SOUND_PDX);
|
||||
} else if ((na == aBACK_START) || (na == aBACK_LOOP) || (na == aBACK_END)) {
|
||||
if ((nf == 37 + ActionStart[aBACK_START] - 3) || (nf == 162 + ActionStart[aBACK_START] - 3)) StartStepSound(game, &c->Pos, SOUND_PSX);
|
||||
else if (nf == 101 + ActionStart[aBACK_START] - 3) StartStepSound(game, &c->Pos, SOUND_PDX);
|
||||
} else if ((na == aRUN_START) || (na == aRUN_LOOP) || (na == aRUN_END)) {
|
||||
if (nf == 74 + ActionStart[aRUN_START] - 4) StartStepSound(game, &c->Pos, SOUND_PSX);
|
||||
else if (nf == 45 + ActionStart[aRUN_START] - 4) StartStepSound(game, &c->Pos, SOUND_PDX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Segue con la testa il mouse
|
||||
UpdateCharHead(ocCURPLAYER, &mPos);
|
||||
|
||||
// Discesa del garage
|
||||
if (t3dCurRoom->name.equalsIgnoreCase("rxt.t3d")) {
|
||||
if ((m = LinkMeshToStr(game.init, "oxt-garage")) && (m->BBox[3].p.x - m->BBox[2].p.x) &&
|
||||
(Player->Pos.x > m->BBox[2].p.x) && (Player->Pos.x < m->BBox[3].p.x) &&
|
||||
(Player->Pos.z > m->BBox[2].p.z) && (Player->Pos.z < m->BBox[6].p.z)) {
|
||||
Player->Pos.y = ((Player->Pos.x - m->BBox[2].p.x) / (m->BBox[3].p.x - m->BBox[2].p.x)) * m->BBox[2].p.y;
|
||||
t3dVectCopy(&Player->Mesh->Trasl, &Player->Pos);
|
||||
}
|
||||
}
|
||||
|
||||
// Parte RTV serra
|
||||
if (!(game.init.Dialog[dR1a1].flags & DIALOG_DONE) && !(bDialogActive) && (game._gameVars.getCurRoomId() == rXT)) {
|
||||
if ((Player->Mesh->Trasl.x > SerraRect[0].x) && (Player->Mesh->Trasl.x < SerraRect[1].x) &&
|
||||
(Player->Mesh->Trasl.z > SerraRect[1].z) && (Player->Mesh->Trasl.z < SerraRect[0].z)) {
|
||||
if (!(LoaderFlags & T3D_DEBUGMODE)) {
|
||||
t3dF32 dist = SerraRect[1].x - Player->Mesh->Trasl.x;
|
||||
|
||||
CharStop(ocCURPLAYER);
|
||||
|
||||
// controllo da che parte far partire l'RTV
|
||||
if ((dist >= 0.0f) && (dist < 30.f))
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dRUN_R1a1_RIGHT, 0, 0, nullptr, nullptr, nullptr);
|
||||
else
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dRUN_R1a1_CENTER, 0, 0, nullptr, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parte Morte Cacciatore se passa l'esterno
|
||||
if ((bCacciatore) && !(LoaderFlags & T3D_DEBUGMODE)) {
|
||||
if (Player->Mesh->Trasl.x < CacciatoreXleft) {
|
||||
bCacciatore = FALSE;
|
||||
CharStop(ocCURPLAYER);
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR0014_left, 0, 0, nullptr, nullptr, nullptr);
|
||||
}
|
||||
if ((Player->Mesh->Trasl.x > CacciatoreXright) && (Player->Mesh->Trasl.z > CacciatoreZright)) {
|
||||
bCacciatore = FALSE;
|
||||
CharStop(ocCURPLAYER);
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR0014_right, 0, 0, nullptr, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Quando Victoria si avvicina per la prima volta alla Room47 parte un RTV che mostra Krenn.
|
||||
if (
|
||||
(game._gameVars.getCurRoomId() == r47)
|
||||
&& (CurPlayer == VICTORIA)
|
||||
&& (!(game.init.Dialog[dR482].flags & DIALOG_DONE))
|
||||
&& (!(LoaderFlags & T3D_DEBUGMODE))
|
||||
&& (!bDialogActive)) {
|
||||
if (Player->Mesh->Trasl.x > r47CoordX) {
|
||||
CharStop(ocCURPLAYER);
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR482, 0, 0, nullptr, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Parte Morte Victoria se Krenn la vede
|
||||
if ((game._gameVars.getCurRoomId() == r48) && (!bDialogActive) && (!(LoaderFlags & T3D_DEBUGMODE))) {
|
||||
int whichanim;
|
||||
int beccato;
|
||||
|
||||
whichanim = WhichAnimChar(game.init, ocKRENN);
|
||||
beccato = 0;
|
||||
|
||||
if ((whichanim == aKRE481) || (whichanim == aKRE482) || (whichanim == aKRE483) || (whichanim == aKRE484)) {
|
||||
if (Player->Mesh->Trasl.z < KrennZ) {
|
||||
//se Krenn e' in movimento basta arrivare sotto la linea verticale delle colonne per beccarti
|
||||
beccato = 1;
|
||||
} else if (whichanim != aKRE481) {
|
||||
if ((Player->Mesh->Trasl.x > KrennX) //oltrepassata l'ultima colonna
|
||||
|| (
|
||||
(Player->Mesh->Trasl.x > KreenRect1[0].x) && (Player->Mesh->Trasl.x < KreenRect1[1].x)
|
||||
&& (Player->Mesh->Trasl.z < KreenRect1[0].z) && (Player->Mesh->Trasl.z > KreenRect1[1].z)
|
||||
)
|
||||
|| (
|
||||
(Player->Mesh->Trasl.x > KreenRect2[0].x) && (Player->Mesh->Trasl.x < KreenRect2[1].x)
|
||||
&& (Player->Mesh->Trasl.z < KreenRect2[0].z) && (Player->Mesh->Trasl.z > KreenRect2[1].z)
|
||||
)
|
||||
)
|
||||
beccato = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (beccato) {
|
||||
// DebugLogFile("BECCATO");
|
||||
CharStop(ocCURPLAYER);
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR48KRENNSPARA, 0, 0, nullptr, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Dice la frase dell'eclisse se non l'ha gi<67> detta
|
||||
if ((game._gameVars.getCurRoomId() == rXT) && (t3dCurTime >= 1300) && (t3dCurTime <= 1310) && (!(game.init.Obj[oADDTEXTOBJ].flags & EXTRA))) {
|
||||
game.init.Obj[oADDTEXTOBJ].flags |= EXTRA;
|
||||
PlayerSpeak(game, game.init.Obj[oADDTEXTOBJ].examine[CurPlayer]);
|
||||
}
|
||||
|
||||
// Porta gradualmente il Blending a zero
|
||||
cbi = (uint8)((t3dF32)BLEND_INC * FrameFactor);
|
||||
if (bDialogActive) cbi /= 5;
|
||||
for (i = 0; i < T3D_MAX_CHARACTERS; i++) {
|
||||
if (Character[i] && (i != ocCURPLAYER) && (Character[i]->Mesh->BlendPercent != 255)) {
|
||||
if ((Character[i]->Mesh->BlendPercent + cbi) < 255)
|
||||
Character[i]->Mesh->BlendPercent += cbi;
|
||||
else
|
||||
Character[i]->Mesh->BlendPercent = 255;
|
||||
// Character[i]->Mesh->BlendPercent = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -----------------17/08/00 17.31-------------------
|
||||
* UpdatePlayerStand
|
||||
* --------------------------------------------------*/
|
||||
void UpdatePlayerStand(WGame &game, uint8 oc) {
|
||||
int32 a, b, panims[MAX_ANIMS_IN_ROOM], pc, na;
|
||||
t3dF32 mindist, dist;
|
||||
t3dV3F pos;
|
||||
Init &init = game.init;
|
||||
auto curRoom = game._gameVars.getCurRoomId();
|
||||
|
||||
na = 0;
|
||||
pc = 0;
|
||||
mindist = 9999999.0f;
|
||||
memset(panims, 0, sizeof(panims));
|
||||
for (a = 0; a < MAX_ANIMS_IN_ROOM; a++) {
|
||||
b = game.getCurRoom().anims[a];
|
||||
if ((b == aNULL) || !(init.Anim[b].flags & ANIM_STAND) || (init.Anim[b].obj != (ocDARRELL + CurPlayer)))
|
||||
continue;
|
||||
|
||||
// caso particolare nel rXT, quando i personaggi potrebbero teletrasportarsi in mezzo all'RTV della serra (dove appunto le luci 93 e 94 sono messe)
|
||||
if ((curRoom == rXT) && (!(init.Dialog[dR1a1].flags & DIALOG_DONE)))
|
||||
if ((init.Anim[b].pos == 93) || (init.Anim[b].pos == 94)) continue;
|
||||
|
||||
if (!(GetLightPosition(&pos, init.Anim[b].pos)))
|
||||
continue;
|
||||
|
||||
if ((dist = t3dVectDistance(&Player->Mesh->Trasl, &pos)) < mindist) {
|
||||
mindist = dist;
|
||||
na = b;
|
||||
}
|
||||
warning("Found %d, dist %f, good %d", b, dist, na);
|
||||
|
||||
panims[pc] = b ;
|
||||
pc ++;
|
||||
}
|
||||
|
||||
// Ferma il primo personaggio e salva le posizioni
|
||||
game._messageSystem.removeEvent(EventClass::MC_PLAYER, ME_ALL);
|
||||
// Salva informazioni
|
||||
{
|
||||
// DebugLogFile("NO");
|
||||
PlayerStand[CurPlayer].pos = init.Anim[na].pos;
|
||||
|
||||
PlayerStand[CurPlayer].cr = curRoom;
|
||||
PlayerStand[CurPlayer].bnd = t3dCurRoom->CurLevel;
|
||||
if ((curRoom == r15) || (curRoom == r1F)) PlayerStand[CurPlayer].bnd = 0;
|
||||
PlayerStand[CurPlayer].roomName = t3dCurRoom->name;
|
||||
|
||||
if (CurPlayer == DARRELL)
|
||||
PlayerStand[CurPlayer].an = aIDLE_DARRELL_1;
|
||||
else
|
||||
PlayerStand[CurPlayer].an = aIDLE_VICTORIA_1;
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------22/10/98 17.29-------------------
|
||||
* ChangePlayer
|
||||
* --------------------------------------------------*/
|
||||
void ChangePlayer(WGame &game, uint8 oc) {
|
||||
int32 a, b,/*panims[MAX_ANIMS_IN_ROOM],pc,*/na;
|
||||
// t3dF32 mindist,dist;
|
||||
t3dV3F pos;
|
||||
Init &init = game.init;
|
||||
|
||||
if ((oc - ocDARRELL) == CurPlayer)
|
||||
return ;
|
||||
|
||||
// caso particolare: sono nella r2a e faccio andare il submusic 1 (ovvero frigo.mid), il problema e' che le altre
|
||||
// stanze non hanno submusic 1 e quindi se cambio personaggio devo resettare submusic a 0 (cosa che generalmente
|
||||
// fa l'animazione di uscita dalla porta, che in questo caso non viene pero' chiamata)
|
||||
if (t3dCurRoom->name.equalsIgnoreCase("r2a.t3d") && CurSubMusic)
|
||||
CurSubMusic = 0;
|
||||
|
||||
bFirstPerson = false;
|
||||
|
||||
// Aggiorna la variabile di cambio personaggio
|
||||
UpdatePlayerStand(game, oc);
|
||||
// ferma sia darrell sia victoria
|
||||
StopObjAnim(game, ocDARRELL);
|
||||
StopObjAnim(game, ocVICTORIA);
|
||||
|
||||
// cerca tutte le possibili posizioni di cambio
|
||||
CharSetPosition(ocCURPLAYER, PlayerStand[CurPlayer].pos, nullptr);
|
||||
StartAnim(game, PlayerStand[CurPlayer].an);
|
||||
// DebugLogFile("---");
|
||||
// Cambia personaggio
|
||||
bPlayerInAnim = false;
|
||||
CurPlayer = oc - ocDARRELL;
|
||||
Character[ocCURPLAYER] = Character[oc];
|
||||
Player = Character[oc];
|
||||
Player->Flags &= ~T3D_CHARACTER_HIDE;
|
||||
// Resetta telecamera
|
||||
CameraTargetObj = ocCURPLAYER;
|
||||
CameraTargetBone = 0;
|
||||
|
||||
auto curRoom = game._gameVars.getCurRoomId();
|
||||
// Se il secondo personaggio non esisteva
|
||||
if (PlayerStand[CurPlayer].cr == rNULL) {
|
||||
// cerca una animazione adatta nella stessa stanza
|
||||
for (a = 0; a < MAX_ANIMS_IN_ROOM; a++) {
|
||||
b = game.getCurRoom().anims[a];
|
||||
if ((b == aNULL) || !(init.Anim[b].flags & ANIM_STAND) || (init.Anim[b].obj != (ocDARRELL + CurPlayer)))
|
||||
continue;
|
||||
|
||||
if (!(GetLightPosition(&pos, init.Anim[b].pos)))
|
||||
continue;
|
||||
|
||||
na = b;
|
||||
PlayerStand[CurPlayer].pos = init.Anim[na].pos;
|
||||
PlayerStand[CurPlayer].cr = curRoom;
|
||||
PlayerStand[CurPlayer].bnd = t3dCurRoom->CurLevel;
|
||||
PlayerStand[CurPlayer].roomName = t3dCurRoom->name.c_str();
|
||||
|
||||
if (CurPlayer == DARRELL)
|
||||
PlayerStand[CurPlayer].an = aIDLE_DARRELL_1;
|
||||
else
|
||||
PlayerStand[CurPlayer].an = aIDLE_VICTORIA_1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Cambia stanza andandosi a leggere la posizione e l'animazione che aveva prima
|
||||
warning("Changing Room to |%s| pos: %d an: %d", PlayerStand[CurPlayer].roomName.c_str(), PlayerStand[CurPlayer].pos, PlayerStand[CurPlayer].an);
|
||||
ChangeRoom(game, PlayerStand[CurPlayer].roomName, PlayerStand[CurPlayer].pos, 0);
|
||||
if ((curRoom == r15) || (curRoom == r1F))
|
||||
SetBndLevel(game, nullptr, PlayerStand[CurPlayer].bnd);
|
||||
CharStop(ocCURPLAYER);
|
||||
Player->Mesh->Flags |= T3D_MESH_DEFAULTANIM;
|
||||
|
||||
if (Player && t3dCurRoom) {
|
||||
Player->Walk.Panel = t3dCurRoom->Panel[t3dCurRoom->CurLevel];
|
||||
Player->Walk.PanelNum = t3dCurRoom->NumPanels[t3dCurRoom->CurLevel];
|
||||
Player->Mesh->Trasl.y = Player->Pos.y = CurFloorY = t3dCurRoom->PanelHeight[t3dCurRoom->CurLevel];
|
||||
}
|
||||
|
||||
// Inizia il Fade
|
||||
// Event( EventClass::MC_SYSTEM, ME_STARTEFFECT, MP_DEFAULT, FRAME_PER_SECOND/3, 0, EFFECT_FADIN, NULL, NULL, NULL );
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_CAMERA, ME_CAMERAPLAYER, MP_DEFAULT, 0, 0, 0, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
/* -----------------30/10/00 18.26-------------------
|
||||
* IsPlayerInPool()
|
||||
* --------------------------------------------------*/
|
||||
int IsPlayerInPool() {
|
||||
if (!t3dCurRoom) return (0);
|
||||
if (!Character[ocCURPLAYER]->CurRoom->name.equalsIgnoreCase("r22.t3d")) return (0);
|
||||
if (!t3dCurRoom->name.equalsIgnoreCase("r22.t3d")) return (0);
|
||||
if (t3dCurRoom->CurLevel != 1) return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* -----------------31/10/00 09.26-------------------
|
||||
* PlayerCanSwitch()
|
||||
* --------------------------------------------------*/
|
||||
int PlayerCanSwitch(GameVars &gameVars, char no_inventory) {
|
||||
auto curRoom = gameVars.getCurRoomId();
|
||||
if (bNoPlayerSwitch) return (0);
|
||||
if (curRoom == r15) return (0);
|
||||
if (curRoom == r31) return (0);
|
||||
if (curRoom == r1F) return (0);
|
||||
if (curRoom == r1D) return (0);
|
||||
if (curRoom == r42) return (0);
|
||||
if (IsPlayerInPool()) return (0);
|
||||
if (bPlayerSuBasamento) return (0);
|
||||
|
||||
// significa che la richiesta viene fatta quando l'inventario "grosso" non e' aperto e quindi bisogna controllare
|
||||
// dei parametri in piu' (parametri che quando l'inventario e' aperto sono sicuramente giusti)
|
||||
if (no_inventory) {
|
||||
if (bPlayerInAnim) return (0);
|
||||
if (bNotSkippableWalk) return (0);
|
||||
if (bDialogActive) return (0);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* -----------------31/10/00 09.26-------------------
|
||||
* PlayerCanCall()
|
||||
* --------------------------------------------------*/
|
||||
int PlayerCanCall(GameVars &gameVars) {
|
||||
auto curRoom = gameVars.getCurRoomId();
|
||||
if (bNoPlayerSwitch) return (0);
|
||||
if (curRoom == r15) return (0);
|
||||
if (curRoom == r31) return (0);
|
||||
if (curRoom == r1F) return (0);
|
||||
if (curRoom == r1D) return (0);
|
||||
if (curRoom == r42) return (0);
|
||||
if (IsPlayerInPool()) return (0);
|
||||
if (bPlayerSuBasamento) return (0);
|
||||
if (bSezioneLabirinto) return (0);
|
||||
|
||||
if (curRoom == rXT) return (0);
|
||||
if (t3dCurRoom->name.equalsIgnoreCase(PlayerStand[CurPlayer ^ 1].roomName)) return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* -----------------31/10/00 09.26-------------------
|
||||
* PlayerCanSave()
|
||||
* --------------------------------------------------*/
|
||||
int PlayerCanSave() {
|
||||
if (bSaveDisabled) return (0);
|
||||
if (bCacciatore) return (0);
|
||||
if (IsPlayerInPool()) return (0);
|
||||
if (bPlayerSuBasamento) return (0);
|
||||
if (bLockCamera) return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
42
engines/watchmaker/classes/do_player.h
Normal file
42
engines/watchmaker/classes/do_player.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_PLAYER_H
|
||||
#define WATCHMAKER_DO_PLAYER_H
|
||||
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void SetCurPlayerPosTo_9x(GameVars &gameVars, Init &init);
|
||||
void doPlayer(WGame &game);
|
||||
void ChangePlayer(WGame &game, uint8 oc);
|
||||
void ProcessCharacters(WGame &game);
|
||||
void UpdatePlayerStand(WGame &game, uint8 oc);
|
||||
int PlayerCanSwitch(GameVars &gameVars, char no_inventory);
|
||||
int PlayerCanCall(GameVars &gameVars);
|
||||
int PlayerCanSave();
|
||||
int IsPlayerInPool();
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_PLAYER_H
|
||||
55
engines/watchmaker/classes/do_scr_scr.cpp
Normal file
55
engines/watchmaker/classes/do_scr_scr.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_scr_scr.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/ll/ll_anim.h"
|
||||
#include "watchmaker/classes/do_string.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
/* -----------------19/05/98 16.40-------------------
|
||||
* doScrScrUseWith
|
||||
* --------------------------------------------------*/
|
||||
void doScrScrUseWith(WGame &game) {
|
||||
uint8 sent = TRUE;
|
||||
|
||||
switch (UseWith[USED]) {
|
||||
case o2DQUADRODIVANO:
|
||||
if (UseWith[WITH] == o2DCASSAFORTECH) {
|
||||
StartAnim(game, a2D6);
|
||||
sent = false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sent = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sent)
|
||||
if (!(!(bUseWith & UW_WITHI) && (UseWith[USED] == UseWith[WITH])))
|
||||
PlayerSpeak(game, game.init.Obj[UseWith[USED]].action[CurPlayer]);
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
34
engines/watchmaker/classes/do_scr_scr.h
Normal file
34
engines/watchmaker/classes/do_scr_scr.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_SCR_SCR_H
|
||||
#define WATCHMAKER_DO_SCR_SCR_H
|
||||
|
||||
#include "watchmaker/saveload.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doScrScrUseWith(WGame &game);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_SCR_SCR_H
|
||||
368
engines/watchmaker/classes/do_sound.cpp
Normal file
368
engines/watchmaker/classes/do_sound.cpp
Normal file
@@ -0,0 +1,368 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_sound.h"
|
||||
#include "watchmaker/utils.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/ll/ll_sound.h"
|
||||
#include "watchmaker/3d/geometry.h"
|
||||
#include "watchmaker/3d/t3d_body.h"
|
||||
#include "watchmaker/3d/t3d_mesh.h"
|
||||
#include "watchmaker/work_dirs.h"
|
||||
#include "watchmaker/ll/ll_util.h"
|
||||
#include "watchmaker/game.h"
|
||||
#include "watchmaker/walk/walkutil.h"
|
||||
|
||||
#define METER2UNIT 256.051971816707218167072181680248f
|
||||
|
||||
#define PG 3.14159265358979323846f
|
||||
#define GradToRad ((2.0f*PG)/360.0f)
|
||||
|
||||
#define gCOS(G) cos(G*GradToRad)
|
||||
#define gSIN(G) sin(G*GradToRad)
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
/* -----------------28/06/00 16.33-------------------
|
||||
* InitMusic
|
||||
* --------------------------------------------------*/
|
||||
bool InitMusic() {
|
||||
warning("STUBBED InitMusic");
|
||||
#if 0
|
||||
if (!mInitMusicSystem())
|
||||
return false;
|
||||
if (!sInitSoundSystem(hWnd))
|
||||
return false;
|
||||
|
||||
sSetDistanceFactor(METER2UNIT);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ListenerUpdate() {
|
||||
sListener CurListener;
|
||||
|
||||
CurListener.flDistanceFactor = 1.0f;
|
||||
CurListener.flRolloff = 0.1f;
|
||||
CurListener.v3flFrontOrientation.x = t3dCurCamera->NormalizedDir.x;
|
||||
CurListener.v3flFrontOrientation.y = t3dCurCamera->NormalizedDir.y;
|
||||
CurListener.v3flFrontOrientation.z = t3dCurCamera->NormalizedDir.z;
|
||||
CurListener.v3flTopOrientation.x = 0.0f;
|
||||
CurListener.v3flTopOrientation.y = 1.0f;
|
||||
CurListener.v3flTopOrientation.z = 0.0f;
|
||||
CurListener.v3flPosition.x = t3dCurCamera->Source.x;
|
||||
CurListener.v3flPosition.y = t3dCurCamera->Source.y;
|
||||
CurListener.v3flPosition.z = t3dCurCamera->Source.z;
|
||||
return sSetListener(&CurListener);
|
||||
}
|
||||
|
||||
/* -----------------06/04/00 11.52-------------------
|
||||
* PlaySound
|
||||
* --------------------------------------------------*/
|
||||
bool StartSpeech(WGame &game, int32 n) {
|
||||
sSound CurSound;
|
||||
|
||||
if (game.gameOptions.speech_on == FALSE) return true;
|
||||
|
||||
snprintf(CurSound.name, SOUND_NAME_LEN, "%ss%04d.wav", game.workDirs._speechDir.c_str(), n);
|
||||
|
||||
CurSound.lIndex = MAX_SOUNDS + n;
|
||||
CurSound.dwLooped = FALSE;
|
||||
CurSound.flMinDistance = 1000 * METER2UNIT;
|
||||
CurSound.flMaxDistance = 1001 * METER2UNIT;
|
||||
//CurSound.flMinDistance = 1*METER2UNIT;
|
||||
//CurSound.flMaxDistance = 1*METER2UNIT;
|
||||
CurSound.v3flPosition.x = 0;
|
||||
CurSound.v3flPosition.y = 0;
|
||||
CurSound.v3flPosition.z = 0;
|
||||
|
||||
/* Queste righe dovrebbero dare spazialita' al suono, ma visto che non funziona lo playamo diffuso
|
||||
if( Anim[TimeAnim].obj )
|
||||
{
|
||||
CurSound.v3flPosition.x = Character[Anim[TimeAnim].obj]->Pos.x;
|
||||
CurSound.v3flPosition.y = Character[Anim[TimeAnim].obj]->Pos.y;
|
||||
CurSound.v3flPosition.z = Character[Anim[TimeAnim].obj]->Pos.z;
|
||||
DebugLogWindow("StartSpeech(%d): %s",n,Character[Anim[TimeAnim].obj]->Body->Name);
|
||||
}else
|
||||
{
|
||||
CurSound.v3flPosition.x = Character[CurPlayer+ocCURPLAYER]->Pos.x;
|
||||
CurSound.v3flPosition.y = Character[CurPlayer+ocCURPLAYER]->Pos.y;
|
||||
CurSound.v3flPosition.z = Character[CurPlayer+ocCURPLAYER]->Pos.z;
|
||||
DebugLogWindow("StartSpeech(%d): %s",n,Character[CurPlayer+ocCURPLAYER]->Body->Name);
|
||||
}*/
|
||||
|
||||
|
||||
// 12 Ore
|
||||
CurSound.v3flConeOrientation.x = 1;
|
||||
CurSound.v3flConeOrientation.y = 0;
|
||||
CurSound.v3flConeOrientation.z = 0;
|
||||
|
||||
CurSound.dwConeInsideAngle = 360;
|
||||
CurSound.dwConeOutsideAngle = 360;
|
||||
CurSound.dwConeOutsideVolume = 0;
|
||||
|
||||
CurSound.dwFlags = SOUND_SPEECH;
|
||||
ListenerUpdate();
|
||||
return (sStartSoundDiffuse(&CurSound));
|
||||
// return( sStartSound( &CurSound, FALSE ) );
|
||||
}
|
||||
|
||||
/* -----------------06/04/00 11.52-------------------
|
||||
* PlaySound
|
||||
* --------------------------------------------------*/
|
||||
bool StartSound(WGame &game, int32 index) {
|
||||
sSound CurSound;
|
||||
t3dMESH *m;
|
||||
Init &init = game.init;
|
||||
|
||||
if (game.gameOptions.sound_on == FALSE) return TRUE;
|
||||
|
||||
snprintf(CurSound.name, SOUND_NAME_LEN, "%s%s", game.workDirs._wavDir.c_str(), init.Sound[index].name);
|
||||
CurSound.lIndex = index;
|
||||
CurSound.dwLooped = (init.Sound[index].flags & SOUND_LOOP);
|
||||
CurSound.flMinDistance = init.Sound[index].MinDist * METER2UNIT;
|
||||
CurSound.flMaxDistance = init.Sound[index].MaxDist * METER2UNIT;
|
||||
|
||||
m = LinkMeshToStr(init, (char *)init.Sound[index].meshlink[0].rawArray());
|
||||
if (m) {
|
||||
CurSound.v3flPosition.x = m->Pos.x;
|
||||
CurSound.v3flPosition.y = m->Pos.y;
|
||||
CurSound.v3flPosition.z = m->Pos.z;
|
||||
} else {
|
||||
CurSound.v3flPosition.x = 0.f;
|
||||
CurSound.v3flPosition.y = 0.f;
|
||||
CurSound.v3flPosition.z = 0.f;
|
||||
}
|
||||
|
||||
// 360 gradi
|
||||
// CurSound.v3flConeOrientation.x = gCOS(Sound[index].Angle);
|
||||
// CurSound.v3flConeOrientation.y = 0;
|
||||
// CurSound.v3flConeOrientation.z = gSIN(Sound[index].Angle);
|
||||
// 12 Ore
|
||||
CurSound.v3flConeOrientation.x = (float) - gCOS((double)(init.Sound[index].Angle * 30.0f));
|
||||
CurSound.v3flConeOrientation.y = 0.0f;
|
||||
CurSound.v3flConeOrientation.z = (float) - gSIN((double)(init.Sound[index].Angle * 30.0f));
|
||||
|
||||
CurSound.dwConeInsideAngle = init.Sound[index].ConeInside;
|
||||
CurSound.dwConeOutsideAngle = init.Sound[index].ConeOutside;
|
||||
CurSound.dwConeOutsideVolume = init.Sound[index].ConeOutsideVolume;
|
||||
|
||||
CurSound.dwFlags = init.Sound[index].flags;
|
||||
|
||||
if (!sStartSound(&CurSound, FALSE)) return FALSE;
|
||||
if (!ListenerUpdate()) return FALSE;
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
/* -----------------06/04/00 11.52-------------------
|
||||
* StopSound
|
||||
* --------------------------------------------------*/
|
||||
bool StopSound(int32 index) {
|
||||
return (sStopSound(index));
|
||||
}
|
||||
|
||||
/* -----------------05/06/00 12.18-------------------
|
||||
* StartStepSound
|
||||
* --------------------------------------------------*/
|
||||
bool StartStepSound(WGame &game, t3dV3F *pos, uint8 side) {
|
||||
double pgon[4][2];
|
||||
int32 cs, ts, index;
|
||||
sSound CurSound;
|
||||
Init &init = game.init;
|
||||
|
||||
if (game.gameOptions.sound_on == FALSE) return TRUE;
|
||||
|
||||
if (!pos) return FALSE;
|
||||
|
||||
double px = (double)pos->x;
|
||||
double pz = (double)pos->z;
|
||||
if ((pos == &Player->Mesh->Trasl) && (side & SOUND_STAIRS)) {
|
||||
px += (double)(Player->Dir.x * HALF_STEP);
|
||||
pz += (double)(Player->Dir.z * HALF_STEP);
|
||||
side &= ~SOUND_STAIRS;
|
||||
}
|
||||
|
||||
index = cs = wNULL;
|
||||
for (int32 i = 0; i < MAX_SOUNDS_IN_ROOM; i++) {
|
||||
if (((cs = game.getCurRoom().sounds[i]) != wNULL) && (init.Sound[cs].flags & side)) {
|
||||
bool found = false;
|
||||
for (int32 j = 0; j < MAX_SOUND_MESHLINKS; j++) {
|
||||
if (init.Sound[cs].meshlink[j][0] == '\0')
|
||||
break;
|
||||
|
||||
auto it = t3dCurRoom->MeshTable.begin();
|
||||
for (; it != t3dCurRoom->MeshTable.end(); ++it)
|
||||
if (it->name.equalsIgnoreCase((const char *)init.Sound[cs].meshlink[j].rawArray())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((init.Sound[cs].meshlink[0][0] == '\0') || (!found)) { // se non ci sono meshlink o tutti i meshlinks sono in un'altra stanza
|
||||
index = cs; // prende questo suono e continua la ricerca
|
||||
continue;
|
||||
}
|
||||
|
||||
ts = wNULL;
|
||||
for (int32 j = 0; j < MAX_SOUND_MESHLINKS; j++) {
|
||||
if (init.Sound[cs].meshlink[j][0] == '\0')
|
||||
break;
|
||||
|
||||
auto it = t3dCurRoom->MeshTable.begin();
|
||||
for (; it != t3dCurRoom->MeshTable.end(); ++it)
|
||||
if (it->name.equalsIgnoreCase((const char *)init.Sound[cs].meshlink[j].rawArray()))
|
||||
break;
|
||||
|
||||
if (it != t3dCurRoom->MeshTable.end()) {
|
||||
auto &m = *it;
|
||||
pgon[0][0] = (double)m.BBox[0].p.x;
|
||||
pgon[0][1] = (double)m.BBox[0].p.z;
|
||||
|
||||
pgon[1][0] = (double)m.BBox[4].p.x;
|
||||
pgon[1][1] = (double)m.BBox[4].p.z;
|
||||
|
||||
pgon[2][0] = (double)m.BBox[5].p.x;
|
||||
pgon[2][1] = (double)m.BBox[5].p.z;
|
||||
|
||||
pgon[3][0] = (double)m.BBox[1].p.x;
|
||||
pgon[3][1] = (double)m.BBox[1].p.z;
|
||||
|
||||
if (PointInside2DRectangle(pgon, px, pz)) {
|
||||
ts = cs;
|
||||
break;
|
||||
} else
|
||||
ts = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ts > wNULL) {
|
||||
index = ts;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index == wNULL)
|
||||
return FALSE;
|
||||
|
||||
snprintf(CurSound.name, SOUND_NAME_LEN, "%s%s", game.workDirs._wavDir.c_str(), init.Sound[index].name);
|
||||
CurSound.lIndex = index;
|
||||
CurSound.dwLooped = (init.Sound[index].flags & SOUND_LOOP);
|
||||
CurSound.flMinDistance = init.Sound[index].MinDist * METER2UNIT;
|
||||
CurSound.flMaxDistance = init.Sound[index].MaxDist * METER2UNIT;
|
||||
if (pos != nullptr) {
|
||||
CurSound.v3flPosition.x = pos->x;
|
||||
CurSound.v3flPosition.y = pos->y;
|
||||
CurSound.v3flPosition.z = pos->z;
|
||||
}
|
||||
|
||||
//12 Ore
|
||||
CurSound.v3flConeOrientation.x = (float) - gCOS((double)(init.Sound[index].Angle * 30));
|
||||
CurSound.v3flConeOrientation.y = 0;
|
||||
CurSound.v3flConeOrientation.z = (float) - gSIN((double)(init.Sound[index].Angle * 30));
|
||||
|
||||
CurSound.dwConeInsideAngle = init.Sound[index].ConeInside;
|
||||
CurSound.dwConeOutsideAngle = init.Sound[index].ConeOutside;
|
||||
CurSound.dwConeOutsideVolume = init.Sound[index].ConeOutsideVolume;
|
||||
|
||||
CurSound.dwFlags = init.Sound[index].flags;
|
||||
|
||||
if (!ListenerUpdate()) return FALSE;
|
||||
if (!bDontPlaySteps) {
|
||||
if (!sStartSound(&CurSound, FALSE)) return FALSE;
|
||||
}
|
||||
//if (!sStartInstantSound( &CurSound ) ) return FALSE;
|
||||
//if (!ListenerUpdate()) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* -----------------28/06/00 16.33-------------------
|
||||
* Ferma tutti i midi in Play
|
||||
* --------------------------------------------------*/
|
||||
bool StopMusic() {
|
||||
if (!mStopMusic()) return FALSE;
|
||||
//if( !sStopAllSounds() ) return FALSE;
|
||||
warning("STUBBED: StopMusic");
|
||||
#if 0
|
||||
CurPlayIndex = -1;
|
||||
CurPlaySubMusic = -1;
|
||||
CurMusicName[0] = 0;
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* -----------------28/06/00 16.33-------------------
|
||||
* Ferma il MIDI con un fade di FadeOutTime ms,
|
||||
* fa partire il MIDI index con un fade di FadeInTime ms.
|
||||
* --------------------------------------------------*/
|
||||
|
||||
bool PlayMusic(int32 index, uint32 FadeOutTime, uint32 FadeInTime) {
|
||||
warning("STUBBED: PlayMusic");
|
||||
#if 0
|
||||
char FileName[MAX_PATH];
|
||||
|
||||
if (GameOptions.music_on == FALSE) return TRUE;
|
||||
|
||||
if ((CurPlayIndex == index) && (CurPlaySubMusic == CurSubMusic)) return TRUE;
|
||||
if (!strcasecmp(CurMusicName, Music[index].name[CurSubMusic])) return TRUE;
|
||||
|
||||
if ((Music[index].vol[CurSubMusic] != 0) &&
|
||||
(Music[index].vol[CurSubMusic] != mGetAllVolume())) {
|
||||
if (!mSetAllVolume((BYTE)Music[index].vol[CurSubMusic])) return FALSE;
|
||||
}
|
||||
snprintf(FileName, MAX_PATH, "%s%s", WmMidiDir, Music[index].name[CurSubMusic]);
|
||||
if (!mLoadMusic(FileName)) {
|
||||
if (CurPlayIndex == -1) return TRUE;
|
||||
mInstantFadeOut(NULL, FadeOutTime);
|
||||
CurPlayIndex = -1;
|
||||
CurPlaySubMusic = -1;
|
||||
CurMusicName[0] = '\0';
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//if (!mPlayMusic(FileName))
|
||||
if (!mCrossFade(FileName, FadeOutTime, FadeInTime)) {
|
||||
CurPlayIndex = -1;
|
||||
CurPlaySubMusic = -1;
|
||||
CurMusicName[0] = '\0';
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DebugLogFile("PM %s", FileName);
|
||||
|
||||
CurPlayIndex = index;
|
||||
CurPlaySubMusic = CurSubMusic;
|
||||
strcpy(CurMusicName, Music[index].name[CurSubMusic]);
|
||||
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool StopSounds() {
|
||||
if (!sStopAllSounds()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
40
engines/watchmaker/classes/do_sound.h
Normal file
40
engines/watchmaker/classes/do_sound.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_SOUND_H
|
||||
#define WATCHMAKER_DO_SOUND_H
|
||||
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
bool InitMusic();
|
||||
bool StartSound(WGame &game, int32 index);
|
||||
bool StartStepSound(WGame &game, t3dV3F *pos, uint8 side);
|
||||
bool StopSound(int32 index);
|
||||
bool StopSounds();
|
||||
bool StopMusic();
|
||||
bool StartSpeech(WGame &game, int32 n);
|
||||
bool PlayMusic(int32 index, uint32 FadeOutTime, uint32 FadeInTime);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_SOUND_H
|
||||
246
engines/watchmaker/classes/do_string.cpp
Normal file
246
engines/watchmaker/classes/do_string.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_string.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/ll/ll_anim.h"
|
||||
#include "watchmaker/schedule.h"
|
||||
#include "watchmaker/ll/ll_string.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/ll/ll_sound.h"
|
||||
#include "watchmaker/t2d/expr.h"
|
||||
#include "watchmaker/classes/do_sound.h"
|
||||
|
||||
// Locals
|
||||
#define DEFAULT_TEXT_X 25
|
||||
#define DEFAULT_TEXT_Y 537
|
||||
#define DEFAULT_TEXT_DX SCREEN_RES_X-DEFAULT_TEXT_X*2
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
char UWStr[100];
|
||||
|
||||
/* -----------------18/03/98 11.11-------------------
|
||||
* PlayerSpeak
|
||||
* --------------------------------------------------*/
|
||||
bool PlayerSpeak(WGame &game, int32 n) {
|
||||
int32 EndSpeakTime, SentTime;
|
||||
uint8 show_text;
|
||||
int32 speechn = 0;
|
||||
Init &init = game.init;
|
||||
|
||||
if (!n) return false;
|
||||
|
||||
if (Sentence[n][0] == '*') {
|
||||
StartAnim(game, aBOH);
|
||||
return false;
|
||||
} else if (Sentence[n][0] == '#') {
|
||||
StartAnim(game, aPENSA);
|
||||
return false;
|
||||
}
|
||||
|
||||
SentTime = VisemaRecon(n);
|
||||
if ((n <= 15) && (bDialogActive)) {
|
||||
switch (n) {
|
||||
case 1:
|
||||
SentTime = 4560;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocOROLOGIAIO;
|
||||
break;
|
||||
case 2:
|
||||
SentTime = 1200;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocVECCHIO;
|
||||
break;
|
||||
case 3:
|
||||
SentTime = 5960;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocVECCHIO;
|
||||
break;
|
||||
case 4:
|
||||
SentTime = 8200;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocCHIRURGO;
|
||||
break;
|
||||
case 5:
|
||||
SentTime = 800;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocCHIRURGO;
|
||||
break;
|
||||
case 6:
|
||||
SentTime = 4560;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocVECCHIO;
|
||||
break;
|
||||
case 7:
|
||||
SentTime = 7200;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocCHIRURGO;
|
||||
break;
|
||||
case 8:
|
||||
SentTime = 7200;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocVECCHIO;
|
||||
break;
|
||||
case 9:
|
||||
SentTime = 5520;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocCHIRURGO;
|
||||
break;
|
||||
case 10:
|
||||
SentTime = 7720;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocVECCHIO;
|
||||
break;
|
||||
case 11:
|
||||
SentTime = 1600;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocCHIRURGO;
|
||||
break;
|
||||
case 12:
|
||||
SentTime = 1200;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocVECCHIO;
|
||||
break;
|
||||
case 13:
|
||||
SentTime = 2560;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocVECCHIO;
|
||||
break;
|
||||
case 14:
|
||||
SentTime = 6720;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocTRADUTTORE;
|
||||
break;
|
||||
case 15:
|
||||
SentTime = 2200;
|
||||
init.Anim[aDUMMY_dR391_A].obj = ocVECCHIO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (game.gameOptions.subtitles_on) show_text = 1;
|
||||
else show_text = 0;
|
||||
|
||||
if (game.gameOptions.speech_on) {
|
||||
if (StartSpeech(game, n)) {
|
||||
speechn = MAX_SOUNDS + n;
|
||||
DebugLogWindow("PP %d, SentTime %d", speechn, SentTime);
|
||||
} else show_text = 1;
|
||||
}
|
||||
|
||||
if (show_text) {
|
||||
if (InvStatus & INV_ON)
|
||||
Text(DEFAULT_TEXT_X, DEFAULT_TEXT_Y, DEFAULT_TEXT_DX, Sentence[n]);
|
||||
else
|
||||
Text(20, DEFAULT_TEXT_Y, DEFAULT_TEXT_DX, Sentence[n]);
|
||||
}
|
||||
|
||||
// DebugLogFile("PLS (%d) %s",SentTime,Sentence[n]);
|
||||
EndSpeakTime = TheTime + SentTime;
|
||||
bSomeOneSpeak = TRUE;
|
||||
bPlayerSpeak = TRUE;
|
||||
bSkipTalk = FALSE;
|
||||
|
||||
if (speechn)
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_STRING, ME_PLAYERCONTINUESPEAK_WAITWAVE, MP_WAIT_RETRACE, 0, 0, 0, &speechn, nullptr, nullptr);
|
||||
else
|
||||
_vm->_messageSystem.doEvent(EventClass::MC_STRING, ME_PLAYERCONTINUESPEAK, MP_WAIT_RETRACE, 0, 0, 0, &EndSpeakTime, nullptr, nullptr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------18/03/98 11.06-------------------
|
||||
* doString
|
||||
* --------------------------------------------------*/
|
||||
void doString(WGame &game) {
|
||||
switch (TheMessage->event) {
|
||||
case ME_PLAYERSPEAK:
|
||||
PlayerSpeak(game, TheMessage->wparam1);
|
||||
break;
|
||||
|
||||
case ME_PLAYERCONTINUESPEAK:
|
||||
if (((int32)TheTime > TheMessage->lparam[0]) || (bSkipTalk)) {
|
||||
bSomeOneSpeak = false;
|
||||
bPlayerSpeak = false;
|
||||
bSkipTalk = false;
|
||||
bAnimWaitText = false;
|
||||
ClearText();
|
||||
if (!bDialogActive) _vm->_messageSystem.addWaitingMsgs(MP_WAIT_LINK);
|
||||
} else {
|
||||
TheMessage->flags |= MP_WAIT_RETRACE;
|
||||
ReEvent();
|
||||
}
|
||||
break;
|
||||
case ME_PLAYERCONTINUESPEAK_WAITWAVE: {
|
||||
bool isp;
|
||||
|
||||
isp = sIsPlaying(TheMessage->lparam[0]);
|
||||
|
||||
if ((!isp) || bSkipTalk) {
|
||||
if (bSkipTalk && isp) {
|
||||
sStopSound(TheMessage->lparam[0]);
|
||||
}
|
||||
|
||||
bSomeOneSpeak = false;
|
||||
bPlayerSpeak = false;
|
||||
bSkipTalk = false;
|
||||
bAnimWaitText = false;
|
||||
ClearText();
|
||||
if (!bDialogActive) _vm->_messageSystem.addWaitingMsgs(MP_WAIT_LINK);
|
||||
} else {
|
||||
TheMessage->flags |= MP_WAIT_RETRACE;
|
||||
ReEvent();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------17/03/98 16.19-------------------
|
||||
* ShowObjName
|
||||
* --------------------------------------------------*/
|
||||
void ShowObjName(Init &init, int32 ob) {
|
||||
if (bUseWith & UW_ON) {
|
||||
if (bUseWith & UW_USEDI)
|
||||
snprintf(UWStr, 100, "Use %s with ", ObjName[init.InvObj[UseWith[USED]].name]);
|
||||
else
|
||||
snprintf(UWStr, 100, "Use %s with ", ObjName[init.Obj[UseWith[USED]].name]);
|
||||
|
||||
if ((UseWith[USED] != ob) || (bUseWith & UW_USEDI))
|
||||
if (ObjName[init.Obj[ob].name] != nullptr)
|
||||
Common::strlcat(UWStr, ObjName[init.Obj[ob].name], 100);
|
||||
Text(DEFAULT_TEXT_X, DEFAULT_TEXT_Y, DEFAULT_TEXT_DX, UWStr);
|
||||
} else if (!ob || !init.Obj[ob].name)
|
||||
ClearText();
|
||||
else
|
||||
Text(DEFAULT_TEXT_X, DEFAULT_TEXT_Y, DEFAULT_TEXT_DX, ObjName[init.Obj[ob].name]);
|
||||
}
|
||||
|
||||
/* -----------------17/03/98 16.19-------------------
|
||||
* ShowInvObjName
|
||||
* --------------------------------------------------*/
|
||||
void ShowInvObjName(Init &init, int32 obj) {
|
||||
if (bUseWith & UW_ON) {
|
||||
if (bUseWith & UW_USEDI)
|
||||
snprintf(UWStr, 100, "Use %s with ", ObjName[init.InvObj[UseWith[USED]].name]);
|
||||
else
|
||||
snprintf(UWStr, 100, "Use %s with ", ObjName[init.Obj[UseWith[USED]].name]);
|
||||
|
||||
if ((UseWith[USED] != obj) || !(bUseWith & UW_USEDI))
|
||||
if (ObjName[init.InvObj[obj].name] != nullptr)
|
||||
Common::strlcat(UWStr, ObjName[init.InvObj[obj].name], 100);
|
||||
Text(DEFAULT_TEXT_X, DEFAULT_TEXT_Y, DEFAULT_TEXT_DX, UWStr);
|
||||
} else //if ( !obj )
|
||||
ClearText();
|
||||
// else
|
||||
// Text( 100, d3dappi.szClient.cy-30, ObjName[InvObj[obj].name] );
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
38
engines/watchmaker/classes/do_string.h
Normal file
38
engines/watchmaker/classes/do_string.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_STRING_H
|
||||
#define WATCHMAKER_DO_STRING_H
|
||||
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doString(WGame &game);
|
||||
bool PlayerSpeak(WGame &game, int32 n);
|
||||
void ShowObjName(Init &init, int32 ob);
|
||||
void ShowInvObjName(Init &init, int32 obj);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_STRING_H
|
||||
1024
engines/watchmaker/classes/do_system.cpp
Normal file
1024
engines/watchmaker/classes/do_system.cpp
Normal file
File diff suppressed because it is too large
Load Diff
40
engines/watchmaker/classes/do_system.h
Normal file
40
engines/watchmaker/classes/do_system.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_SYSTEM_H
|
||||
#define WATCHMAKER_DO_SYSTEM_H
|
||||
|
||||
#include "watchmaker/struct.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void InitMain(WGame &game);
|
||||
|
||||
extern SRoomInfo RoomInfo;
|
||||
void NextMessage(WGame &game);
|
||||
void doSystem(WGame &game);
|
||||
void TitoliCoda_ShowStatic(WGame &game, char initialize);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_SYSTEM_H
|
||||
3
engines/watchmaker/configure.engine
Normal file
3
engines/watchmaker/configure.engine
Normal file
@@ -0,0 +1,3 @@
|
||||
# This file is included from the main "configure" script
|
||||
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
|
||||
add_engine watchmaker "The Watchmaker" no "" "" "highres 16bit 3d opengl_game_classic"
|
||||
29
engines/watchmaker/console.cpp
Normal file
29
engines/watchmaker/console.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/console.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
Console::Console() {
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
37
engines/watchmaker/console.h
Normal file
37
engines/watchmaker/console.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_CONSOLE_H
|
||||
#define WATCHMAKER_CONSOLE_H
|
||||
|
||||
#include "gui/debugger.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
class Console : public GUI::Debugger {
|
||||
public:
|
||||
explicit Console();
|
||||
~Console() override {}
|
||||
};
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif
|
||||
3
engines/watchmaker/credits.pl
Normal file
3
engines/watchmaker/credits.pl
Normal file
@@ -0,0 +1,3 @@
|
||||
begin_section("Watchmaker");
|
||||
add_person("Einar Johan Troan Somaen;", "somaen", "");
|
||||
end_section();
|
||||
4755
engines/watchmaker/define.h
Normal file
4755
engines/watchmaker/define.h
Normal file
File diff suppressed because it is too large
Load Diff
93
engines/watchmaker/detection.cpp
Normal file
93
engines/watchmaker/detection.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "base/plugins.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
#include "engines/game.h"
|
||||
|
||||
#include "watchmaker/watchmaker.h"
|
||||
|
||||
static const PlainGameDescriptor watchmakerGames[] = {
|
||||
{"watchmaker", "The Watchmaker"},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
static const ADGameDescription gameDescriptions[] = {
|
||||
// The Watchmaker English 0.92
|
||||
{
|
||||
"watchmaker",
|
||||
nullptr,
|
||||
AD_ENTRY1s("WmStart.dat", "a0532ab9a2ea33ce1c6953168ed04d7c", 190251),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
|
||||
// The Watchmaker English Retail
|
||||
{
|
||||
"watchmaker",
|
||||
nullptr,
|
||||
AD_ENTRY1s("Data.wm", "a1675e8fd32c2c1eaed88e292a0d153c", 6017156),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
|
||||
// The Watchmaker Italian Retail
|
||||
{
|
||||
"watchmaker",
|
||||
nullptr,
|
||||
AD_ENTRY1s("Data.wm", "3650195f1983363b5676214a7596d85d", 6032308),
|
||||
Common::IT_ITA,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
|
||||
AD_TABLE_END_MARKER
|
||||
};
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
class WatchmakerMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
|
||||
public:
|
||||
WatchmakerMetaEngineDetection() : AdvancedMetaEngineDetection(Watchmaker::gameDescriptions, watchmakerGames) {
|
||||
}
|
||||
|
||||
const char *getName() const override {
|
||||
return "watchmaker";
|
||||
}
|
||||
|
||||
const char *getEngineName() const override {
|
||||
return "The Watchmaker";
|
||||
}
|
||||
|
||||
const char *getOriginalCopyright() const override {
|
||||
return "The Watchmaker (C) 2002 Trecision SpA.";
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_PLUGIN_STATIC(WATCHMAKER_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, WatchmakerMetaEngineDetection);
|
||||
107
engines/watchmaker/extraLS.cpp
Normal file
107
engines/watchmaker/extraLS.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/extraLS.h"
|
||||
#include "watchmaker/struct.h"
|
||||
#include "watchmaker/ll/ll_mouse.h"
|
||||
#include "watchmaker/ll/ll_util.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
char *ExtraLS[MAX_EXTRALS];
|
||||
|
||||
#define EXTRALS_BKG_COLOR_R 50
|
||||
#define EXTRALS_BKG_COLOR_G 0
|
||||
#define EXTRALS_BKG_COLOR_B 224
|
||||
|
||||
int32 extraLS_BMP = 0;
|
||||
uint32 extraLS_currentID = 0;
|
||||
int32 extraLS_bmpPosX = 0;
|
||||
int32 extraLS_bmpPosY = 0;
|
||||
|
||||
void CheckExtraLocalizationStrings(Renderer &renderer, uint32 id) {
|
||||
static constexpr SRect Console3Save = { 228 + 22, 11 + 15, 277 + 22, 30 + 15 };
|
||||
static constexpr SRect Console3Load = { 340 + 22, 11 + 15, 396 + 22, 30 + 15 };
|
||||
static constexpr SRect Console3Options = { 444 + 22, 11 + 15, 527 + 22, 30 + 15 };
|
||||
static constexpr SRect Console3Quit = { 565 + 22, 11 + 15, 613 + 22, 30 + 15 };
|
||||
static constexpr SRect Console3Close = { 665 + 22, 11 + 15, 724 + 22, 30 + 15 };
|
||||
|
||||
uint32 newID = 0;
|
||||
|
||||
if (!bShowExtraLocalizationStrings) {
|
||||
if (extraLS_BMP) {
|
||||
rReleaseBitmap(extraLS_BMP);
|
||||
extraLS_BMP = 0;
|
||||
}
|
||||
extraLS_currentID = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!id) {
|
||||
if (InvStatus & INV_MODE2) {
|
||||
for (;;) {
|
||||
if (CheckRect(renderer, Console3Save, mPosx, mPosy)) {
|
||||
newID = EXTRALS_SAVE;
|
||||
break;
|
||||
}
|
||||
if (CheckRect(renderer, Console3Load, mPosx, mPosy)) {
|
||||
newID = EXTRALS_LOAD;
|
||||
break;
|
||||
}
|
||||
if (CheckRect(renderer, Console3Options, mPosx, mPosy)) {
|
||||
newID = EXTRALS_OPTIONS;
|
||||
break;
|
||||
}
|
||||
if (CheckRect(renderer, Console3Quit, mPosx, mPosy)) {
|
||||
newID = EXTRALS_QUIT;
|
||||
break;
|
||||
}
|
||||
if (CheckRect(renderer, Console3Close, mPosx, mPosy)) {
|
||||
newID = EXTRALS_CLOSE;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else newID = id;
|
||||
|
||||
if (extraLS_currentID != newID) {
|
||||
if (extraLS_BMP) {
|
||||
rReleaseBitmap(extraLS_BMP);
|
||||
extraLS_BMP = 0;
|
||||
}
|
||||
|
||||
if (newID) {
|
||||
int x, y;
|
||||
renderer._fonts->getTextDim(ExtraLS[newID], FontKind::Standard, &x, &y);
|
||||
extraLS_BMP = CreateTooltipBitmap(renderer, ExtraLS[newID], WHITE_FONT, EXTRALS_BKG_COLOR_R, EXTRALS_BKG_COLOR_G, EXTRALS_BKG_COLOR_B);
|
||||
extraLS_bmpPosX = (800 - x) / 2;
|
||||
extraLS_bmpPosY = 600 - (y + 12);
|
||||
}
|
||||
|
||||
extraLS_currentID = newID;
|
||||
}
|
||||
|
||||
if (extraLS_BMP) renderer._2dStuff.displayDDBitmap(extraLS_BMP, extraLS_bmpPosX, extraLS_bmpPosY, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
88
engines/watchmaker/extraLS.h
Normal file
88
engines/watchmaker/extraLS.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_EXTRALS_H
|
||||
#define WATCHMAKER_EXTRALS_H
|
||||
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
|
||||
#define MAX_EXTRALS 55
|
||||
|
||||
#define EXTRALS_SAVE 1
|
||||
#define EXTRALS_LOAD 2
|
||||
#define EXTRALS_OPTIONS 3
|
||||
#define EXTRALS_QUIT 4
|
||||
#define EXTRALS_CLOSE 5
|
||||
#define EXTRALS_NOCONNECTION 6
|
||||
#define EXTRALS_INVALIDNUMBER 7
|
||||
#define EXTRALS_DIAL 8
|
||||
#define EXTRALS_ENTERUSERNUMBER 9
|
||||
#define EXTRALS_DOCUMENTS 10
|
||||
#define EXTRALS_DOCUMENTVIEWER 11
|
||||
#define EXTRALS_EMAILVIEWER 12
|
||||
#define EXTRALS_EMAIL 13
|
||||
#define EXTRALS_AVAILABLEEMAIL 14
|
||||
#define EXTRALS_OK 15
|
||||
#define EXTRALS_CANCEL 16
|
||||
#define EXTRALS_CLEAR 17
|
||||
#define EXTRALS_DIALLING 18
|
||||
#define EXTRALS_SEARCH 19
|
||||
#define EXTRALS_FINDBY 20
|
||||
#define EXTRALS_NAME 21
|
||||
#define EXTRALS_SURNAME 22
|
||||
#define EXTRALS_SUBJECT 23
|
||||
#define EXTRALS_CASENAME 24
|
||||
#define EXTRALS_YEAR 25
|
||||
#define EXTRALS_NODOCUMENTS 26
|
||||
#define EXTRALS_NEWMAIL 27
|
||||
#define EXTRALS_CIAMAINTERMINAL 28
|
||||
#define EXTRALS_GAMEOVER 29
|
||||
#define EXTRALS_EXIT 30
|
||||
#define EXTRALS_PLAYTHEGAME 31
|
||||
#define EXTRALS_LOADAGAME 32
|
||||
#define EXTRALS_MAINMENU 33
|
||||
#define EXTRALS_HELP 34
|
||||
#define EXTRALS_LOGVIEWER 35
|
||||
#define EXTRALS_TONESEQUENCER 36
|
||||
#define EXTRALS_ACQUIRE 37
|
||||
#define EXTRALS_PROCESS 38
|
||||
#define EXTRALS_LOG 39
|
||||
#define EXTRALS_PREVIEW 40
|
||||
#define EXTRALS_SCAN 41
|
||||
#define EXTRALS_SELECTAREA 42
|
||||
#define EXTRALS_SCANPROGRAM 43
|
||||
#define EXTRALS_MUSIC 44
|
||||
#define EXTRALS_SOUND 45
|
||||
#define EXTRALS_SPEECH 46
|
||||
#define EXTRALS_SUBTITLES 47
|
||||
#define EXTRALS_DARRELL 48
|
||||
#define EXTRALS_VICTORIA 49
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
extern char *ExtraLS[MAX_EXTRALS];
|
||||
|
||||
void CheckExtraLocalizationStrings(Renderer &renderer, uint32 id);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_EXTRALS_H
|
||||
54
engines/watchmaker/file_utils.cpp
Normal file
54
engines/watchmaker/file_utils.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/file_utils.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
Common::String readT3dString(Common::SeekableReadStream &stream) {
|
||||
char strbuf[T3D_NAMELEN + 1] = {};
|
||||
for (int i = 0; i < T3D_NAMELEN; i++) {
|
||||
strbuf[i] = stream.readByte();
|
||||
}
|
||||
return Common::String(strbuf);
|
||||
}
|
||||
|
||||
bool hasFileExtension(const Common::String &str, const Common::String &extension) {
|
||||
return str.hasSuffixIgnoreCase("." + extension);
|
||||
}
|
||||
|
||||
bool hasFileExtension(const char *str, Common::String extension) {
|
||||
Common::String string(str);
|
||||
return hasFileExtension(string, extension);
|
||||
}
|
||||
|
||||
Common::String replaceExtension(const char *str, const Common::String &extension) {
|
||||
Common::String baseStr(str);
|
||||
auto separator = baseStr.findLastOf('.');
|
||||
if (separator == Common::String::npos) {
|
||||
return baseStr + "." + extension;
|
||||
} else {
|
||||
return baseStr.substr(0, separator + 1) + extension;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
37
engines/watchmaker/file_utils.h
Normal file
37
engines/watchmaker/file_utils.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_FILE_UTILS_H
|
||||
#define WATCHMAKER_FILE_UTILS_H
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
Common::String readT3dString(Common::SeekableReadStream &stream);
|
||||
// TODO: This can probably just be replaced with .hasSuffixIgnoreCase
|
||||
bool hasFileExtension(const Common::String &str, const Common::String &extension);
|
||||
bool hasFileExtension(const char *str, Common::String extension);
|
||||
Common::String replaceExtension(const char *str, const Common::String &extension);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_FILE_UTILS_H
|
||||
117
engines/watchmaker/fonts.cpp
Normal file
117
engines/watchmaker/fonts.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/fonts.h"
|
||||
#include "watchmaker/main.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
Fonts::~Fonts() {
|
||||
for (auto table : _tables) {
|
||||
delete[] table;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 *Fonts::setupFontTable(Common::SeekableReadStream &stream) {
|
||||
uint32 dim = stream.size();
|
||||
// FIXME: This looks slightly wrong. Should this be:
|
||||
// uint16 *tab = new uint16[dim / sizeof(uint16)] {};
|
||||
// to match the loop iteration?
|
||||
uint16 *tab = new uint16[dim] {};
|
||||
|
||||
for (uint32 i = 0; i < dim / sizeof(uint16); i++) {
|
||||
tab[i] = stream.readUint16LE();
|
||||
}
|
||||
|
||||
_tables.push_back(tab);
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
void Fonts::loadFont(WGame &game, struct SFont *f, const Common::String &n) {
|
||||
Common::String name = constructPath(game.workDirs._miscDir, n, "fnt");
|
||||
auto stream = game.workDirs.resolveFile(name);
|
||||
if ((f->table = setupFontTable(*stream)) == nullptr) {
|
||||
DebugLogFile("Failed to load Font. Quitting ...");
|
||||
CloseSys(game);
|
||||
}
|
||||
|
||||
Common::String basename = n.substr(0, n.findLastOf('.'));
|
||||
for (uint a = 0; a < MAX_FONT_COLORS; a++) {
|
||||
Common::String tgaName = constructPath(game.workDirs._miscDir, basename + (a + '0')) + ".tga";
|
||||
if ((f->color[a] = rLoadBitmapImage(game, tgaName.c_str(), rBITMAPSURFACE | rSURFACEFLIP)) <= 0) {
|
||||
DebugLogFile("Failed to load Font2. Quitting ...");
|
||||
CloseSys(game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Fonts::loadFonts(WGame &game, WindowInfo &windowInfo) {
|
||||
if ((windowInfo.width >= 1024) || (windowInfo.height >= 768)) {
|
||||
loadFont(game, &StandardFont, "1024NlFont.fnt");
|
||||
loadFont(game, &ComputerFont, "1024ComputerFont.fnt");
|
||||
loadFont(game, &PDAFont, "1024PDAFont.fnt");
|
||||
} else if ((windowInfo.width >= 800) || (windowInfo.height >= 600)) {
|
||||
loadFont(game, &StandardFont, "800NlFont.fnt");
|
||||
loadFont(game, &ComputerFont, "800ComputerFont.fnt");
|
||||
loadFont(game, &PDAFont, "800PDAFont.fnt");
|
||||
} else if ((windowInfo.width >= 640) || (windowInfo.height >= 480)) {
|
||||
loadFont(game, &StandardFont, "640NlFont.fnt");
|
||||
loadFont(game, &ComputerFont, "640ComputerFont.fnt");
|
||||
loadFont(game, &PDAFont, "640PDAFont.fnt");
|
||||
}
|
||||
}
|
||||
|
||||
SFont *Fonts::fontForKind(FontKind font) {
|
||||
switch (font) {
|
||||
case FontKind::Standard:
|
||||
return &StandardFont;
|
||||
case FontKind::Computer:
|
||||
return &ComputerFont;
|
||||
case FontKind::PDA:
|
||||
return &PDAFont;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Fonts::getTextDim(const char *s, FontKind font, int *x, int *y) {
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
SFont *fontTable = fontForKind(font);
|
||||
|
||||
int i = 0;
|
||||
int nextx = 0, nexty = 0;
|
||||
byte c = 0;
|
||||
while ((c = s[i]) != 0) {
|
||||
i++;
|
||||
|
||||
nextx += fontTable->table[c * 4 + 2];
|
||||
nexty = fontTable->table[c * 4 + 3];
|
||||
}
|
||||
|
||||
*x = nextx;
|
||||
*y = nexty;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
55
engines/watchmaker/fonts.h
Normal file
55
engines/watchmaker/fonts.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_FONTS_H
|
||||
#define WATCHMAKER_FONTS_H
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
#include "watchmaker/sysdef.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
struct SFont {
|
||||
uint16 *table = nullptr;
|
||||
int32 color[MAX_FONT_COLORS] = {};
|
||||
};
|
||||
|
||||
class WGame;
|
||||
class Fonts {
|
||||
Common::Array<uint16 *> _tables;
|
||||
uint16 *setupFontTable(Common::SeekableReadStream &stream);
|
||||
void loadFont(WGame &game, struct SFont *f, const Common::String &n);
|
||||
public:
|
||||
SFont *fontForKind(FontKind);
|
||||
SFont StandardFont;
|
||||
SFont ComputerFont;
|
||||
SFont PDAFont;
|
||||
~Fonts();
|
||||
|
||||
void loadFonts(WGame &game, WindowInfo &windowInfo);
|
||||
void getTextDim(const char *s, FontKind font, int *x, int *y);
|
||||
};
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_FONTS_H
|
||||
|
||||
704
engines/watchmaker/game.cpp
Normal file
704
engines/watchmaker/game.cpp
Normal file
@@ -0,0 +1,704 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
#include "watchmaker/3d/animation.h"
|
||||
#include "watchmaker/3d/geometry.h"
|
||||
#include "watchmaker/3d/loader.h"
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/classes/do_camera.h"
|
||||
#include "watchmaker/classes/do_keyboard.h"
|
||||
#include "watchmaker/classes/do_player.h"
|
||||
#include "watchmaker/classes/do_system.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/init/nl_init.h"
|
||||
#include "watchmaker/ll/ll_anim.h"
|
||||
#include "watchmaker/ll/ll_diary.h"
|
||||
#include "watchmaker/ll/ll_mesh.h"
|
||||
#include "watchmaker/ll/ll_mouse.h"
|
||||
#include "watchmaker/ll/ll_regen.h"
|
||||
#include "watchmaker/ll/ll_system.h"
|
||||
#include "watchmaker/ll/ll_util.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
#include "watchmaker/sdl_wrapper.h"
|
||||
#include "watchmaker/walk/act.h"
|
||||
#include "watchmaker/walk/ball.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
const char *WATCHMAKER_CFG_NAME = "wm.cfg";
|
||||
|
||||
WGame *_vm = nullptr;
|
||||
|
||||
// TODO: Unglobalize
|
||||
const char *CharName_Strings[] = {
|
||||
"",
|
||||
"Darrell.t3d",
|
||||
"Victoria.t3d",
|
||||
"Cuoco.t3d",
|
||||
"Domestica.t3d",
|
||||
"Giardiniere.t3d",
|
||||
"Custode.t3d",
|
||||
"Servetta.t3d",
|
||||
"Supervisore.t3d",
|
||||
"MoglieSwim.t3d",
|
||||
"MoglieKimono.t3d",
|
||||
"Cacciatore.t3d",
|
||||
"Vecchio.t3d",
|
||||
"Chirurgo.t3d",
|
||||
"Traduttore.t3d",
|
||||
"Orologiaio.t3d",
|
||||
"Krenn.t3d",
|
||||
"Dukes.t3d",
|
||||
"Corona.t3d",
|
||||
"Valencia.t3d",
|
||||
"Notaio.t3d",
|
||||
"Moore.t3d",
|
||||
"DarrellALetto.t3d",
|
||||
"CacciatoreMalpreso.t3d",
|
||||
"MooreBucato.t3d",
|
||||
nullptr
|
||||
};
|
||||
|
||||
const char *CharNameHI_Strings[] = {
|
||||
"",
|
||||
"DarrellHI.t3d",
|
||||
"VictoriaHI.t3d",
|
||||
"CuocoHI.t3d",
|
||||
"DomesticaHI.t3d",
|
||||
"GiardiniereHI.t3d",
|
||||
"CustodeHI.t3d",
|
||||
"ServettaHI.t3d",
|
||||
"SupervisoreHI.t3d",
|
||||
"MoglieSwimHI.t3d",
|
||||
"MoglieKimonoHI.t3d",
|
||||
"CacciatoreHI.t3d",
|
||||
"VecchioHI.t3d",
|
||||
"ChirurgoHI.t3d",
|
||||
"TraduttoreHI.t3d",
|
||||
"OrologiaioHI.t3d",
|
||||
"KrennHI.t3d",
|
||||
"DukesHI.t3d",
|
||||
"CoronaHI.t3d",
|
||||
"ValenciaHI.t3d",
|
||||
"NotaioHI.t3d",
|
||||
"MooreHI.t3d",
|
||||
"DarrellALettoHI.t3d",
|
||||
"CacciatoreMalpresoHI.t3d",
|
||||
"MooreBucatoHI.t3d",
|
||||
nullptr
|
||||
};
|
||||
|
||||
/* -----------------16/11/00 17.45-------------------
|
||||
* CheckAndLoadMoglieSupervisoreModel
|
||||
* --------------------------------------------------*/
|
||||
// Controllo che la giusta MoglieSupervisore sia caricata
|
||||
bool WGame::CheckAndLoadMoglieSupervisoreModel(int32 c) {
|
||||
warning("CheckAndLoadMoglieSupervisoreModel(workDirs, %d)", c);
|
||||
char RemoveName[128] = "";
|
||||
char RemoveNameHI[128] = "";
|
||||
|
||||
if (c == ocMOGLIESUPERVISORE) {
|
||||
if (bMoglieGym && (!Character[c]->Body->name.contains("MoglieGym"))) {
|
||||
CharName_Strings[c] = "MoglieGym.t3d";
|
||||
Common::strlcpy(RemoveName, "MoglieSwim.t3d", 128);
|
||||
CharNameHI_Strings[c] = "MoglieGymHI.t3d";
|
||||
Common::strlcpy(RemoveNameHI, "MoglieSwimHI.t3d", 128);
|
||||
}
|
||||
|
||||
if ((!bMoglieGym) && (!Character[c]->Body->name.contains("MoglieSwim"))) {
|
||||
CharName_Strings[c] = "MoglieSwim.t3d";
|
||||
Common::strlcpy(RemoveName, "MoglieGym.t3d", 128);
|
||||
CharNameHI_Strings[c] = "MoglieSwimHI.t3d";
|
||||
Common::strlcpy(RemoveNameHI, "MoglieGymHI.t3d", 128);
|
||||
}
|
||||
}
|
||||
|
||||
if (c == ocMOGLIE_KIMONO) {
|
||||
if (bMoglieSangue && (!Character[c]->Body->name.contains("MoglieKimonoSangue"))) {
|
||||
CharName_Strings[c] = "MoglieKimonoSangue.t3d";
|
||||
Common::strlcpy(RemoveName, "MoglieKimono.t3d", 128);
|
||||
CharNameHI_Strings[c] = "MoglieKimonoSangueHI.t3d";
|
||||
Common::strlcpy(RemoveNameHI, "MoglieKimonoHI.t3d", 128);
|
||||
}
|
||||
|
||||
if ((!bMoglieSangue) && (!Character[c]->Body->name.contains("MoglieKimono"))) {
|
||||
CharName_Strings[c] = "MoglieKimono.t3d";
|
||||
Common::strlcpy(RemoveName, "MoglieKimonoSangue.t3d", 128);
|
||||
CharNameHI_Strings[c] = "MoglieKimonoHI.t3d";
|
||||
Common::strlcpy(RemoveNameHI, "MoglieKimonoSangueHI.t3d", 128);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (RemoveName[0] || RemoveNameHI[0]) {
|
||||
if (LoaderFlags & T3D_HIPOLYPLAYERS)
|
||||
CharName[c] = CharNameHI_Strings[c];
|
||||
else
|
||||
CharName[c] = CharName_Strings[c];
|
||||
|
||||
t3dReleaseCharacter(Character[c]);
|
||||
Character[c] = nullptr;
|
||||
|
||||
_vm->_roomManager->releaseBody(RemoveName, RemoveNameHI);
|
||||
|
||||
LoaderFlags |= T3D_PRELOADBASE;
|
||||
LoaderFlags |= T3D_STATIC_SET1;
|
||||
LoaderFlags |= T3D_STATIC_SET0;
|
||||
rSetLoaderFlags(LoaderFlags);
|
||||
if (!(Character[c] = t3dLoadCharacter(*this, CharName[c], (uint16)c))) {
|
||||
warning("Error loading %s", CharName[c]);
|
||||
return false;
|
||||
}
|
||||
LoaderFlags &= ~T3D_PRELOADBASE;
|
||||
LoaderFlags &= ~T3D_STATIC_SET1;
|
||||
LoaderFlags &= ~T3D_STATIC_SET0;
|
||||
rSetLoaderFlags(LoaderFlags);
|
||||
|
||||
}//if removename
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
// TODO: This needs some heavy refactoring.
|
||||
WGame::WGame() : workDirs(WATCHMAKER_CFG_NAME) {
|
||||
_vm = this;
|
||||
_meshModifiers = new MeshModifiers();
|
||||
_roomManager = RoomManager::create(this);
|
||||
_cameraMan = new CameraMan();
|
||||
configLoaderFlags(false); // TODO: This should probably happen before the constructor
|
||||
|
||||
// if LoaderFlags & T3D_DEBUGMODE
|
||||
// ...
|
||||
// }
|
||||
|
||||
gameOptions.load(workDirs);
|
||||
|
||||
if (LoaderFlags & T3D_DEBUGMODE) {
|
||||
InitStructures(*this);
|
||||
} else {
|
||||
warning("Currently doing an unnecessary copy here");
|
||||
loadAll(workDirs, init);
|
||||
}
|
||||
|
||||
sdl = new sdl_wrapper();
|
||||
|
||||
_renderer = new Renderer(this, sdl);
|
||||
|
||||
// Don't forget to register your random source
|
||||
_rnd = new Common::RandomSource("Watchmaker");
|
||||
}
|
||||
|
||||
WGame::~WGame() {
|
||||
delete _renderer;
|
||||
delete sdl;
|
||||
delete _meshModifiers;
|
||||
delete _roomManager;
|
||||
delete _rnd;
|
||||
delete _cameraMan;
|
||||
_vm = nullptr;
|
||||
}
|
||||
|
||||
Common::SharedPtr<Common::SeekableReadStream> WGame::resolveFile(const char *path, bool noFastFile) {
|
||||
return workDirs.resolveFile(path, noFastFile);
|
||||
}
|
||||
|
||||
void WGame::initCharNames() {
|
||||
//Init characters names
|
||||
if (LoaderFlags & T3D_HIPOLYPLAYERS) {
|
||||
CharName[ocDARRELL] = CharNameHI_Strings[ocDARRELL];
|
||||
CharName[ocVICTORIA] = CharNameHI_Strings[ocVICTORIA];
|
||||
CharName[ocDARRELLALETTO] = CharNameHI_Strings[ocDARRELLALETTO];
|
||||
} else {
|
||||
CharName[ocDARRELL] = CharName_Strings[ocDARRELL];
|
||||
CharName[ocVICTORIA] = CharName_Strings[ocVICTORIA];
|
||||
CharName[ocDARRELLALETTO] = CharName_Strings[ocDARRELLALETTO];
|
||||
}
|
||||
|
||||
for (int i = ocCUOCO; i <= ocLASTCHAR; i++)
|
||||
if (i != ocDARRELLALETTO) {
|
||||
if (LoaderFlags & T3D_HIPOLYCHARACTERS)
|
||||
CharName[i] = CharNameHI_Strings[i];
|
||||
else
|
||||
CharName[i] = CharName_Strings[i];
|
||||
}
|
||||
|
||||
//l'orologiaio e' sempre hipoly, perche' nell'rtv della sua morte la mesh e' hipoly
|
||||
CharName[ocOROLOGIAIO] = CharNameHI_Strings[ocOROLOGIAIO];
|
||||
}
|
||||
|
||||
/* -----------------04/10/00 15.45-------------------
|
||||
* StartPlayingGame
|
||||
* --------------------------------------------------*/
|
||||
// Serve quando si deve far partire il gioco dall'inizio
|
||||
int WGame::StartPlayingGame(const Common::String &LoaderName_override) {
|
||||
warning("StartPlayingGame");
|
||||
int retv = 0;
|
||||
|
||||
if (!LoaderName_override.empty())
|
||||
retv = LoadAndSetup(LoaderName_override, 0); // Carica T3D e Bitmap
|
||||
else
|
||||
retv = LoadAndSetup(LoaderName, 0); // Carica T3D e Bitmap
|
||||
|
||||
if (!retv) return false;
|
||||
|
||||
UpdateAll();
|
||||
InitMain(*this);
|
||||
|
||||
// resetto alcune variabili che potrebbero rimanere sporche dalla partita prima (uguale per StartPlayingGame(), DataLoad() )
|
||||
bCacciatore = 0;
|
||||
bSaveDisabled = 0;
|
||||
bNotSkippableSent = 0;
|
||||
bPorteEsternoBloccate = 0;
|
||||
bNoPlayerSwitch = 0;
|
||||
bDarkScreen = false;
|
||||
bSuperView = 0;
|
||||
bSezioneLabirinto = 0;
|
||||
bSkipTalk = false;
|
||||
bSomeOneSpeak = false;
|
||||
bPlayerSpeak = false;
|
||||
bWideScreen = 0;
|
||||
bTitoliCodaStatic = 0;
|
||||
bTitoliCodaScrolling = 0;
|
||||
Common::strlcpy(RoomInfo.name, "", 64);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------16/10/98 12.15-------------------
|
||||
* LoadAndSetup
|
||||
* --------------------------------------------------*/
|
||||
bool WGame::LoadAndSetup(const Common::String &name, uint8 lite) {
|
||||
uint16 i = 0;
|
||||
|
||||
warning("--=>> %s <<=--: LoaderFlags: %08X", name.c_str(), LoaderFlags);
|
||||
t3dCurCamera = &init._globals._invVars.t3dIconCamera;
|
||||
|
||||
auto windowInfo = _renderer->getScreenInfos();
|
||||
|
||||
if (LoaderFlags & T3D_STATIC_SET0) {
|
||||
if (LoaderFlags & T3D_PRELOADBASE) {
|
||||
_renderer->setVirtualScreen(SCREEN_RES_X, SCREEN_RES_Y);
|
||||
warning("Window %dx%d", windowInfo.width, windowInfo.height);
|
||||
_renderer->createScreenBuffer();
|
||||
_renderer->initBlitterViewPort();
|
||||
|
||||
LoadMisc();
|
||||
t3dVectInit(&CharCorrection, 0.0f, 0.0f, /*14*/0.0f * 2.55f * SCALEFACTOR);
|
||||
|
||||
// if( lite )
|
||||
// PrintLoading();
|
||||
|
||||
if (!(LoaderFlags & T3D_NOICONS))
|
||||
if (!(init._globals._invVars.t3dIcons = _roomManager->loadRoom("Icons.t3d", init._globals._invVars.t3dIcons, &i, (LoaderFlags | T3D_NORECURSION | T3D_NOLIGHTMAPS | T3D_NOBOUNDS | T3D_NOCAMERAS | T3D_STATIC_SET1)))) {
|
||||
warning("Error loading Icons");
|
||||
return false;
|
||||
}
|
||||
if (!(Lanc33[0] = t3dLoadCharacter(*this, "Lanc33a.t3d", 99)) || !(Lanc33[1] = t3dLoadCharacter(*this, "Lanc33b.t3d", 99)) ||
|
||||
!(Lanc33[2] = t3dLoadCharacter(*this, "Lanc33c.t3d", 99)) || !(Lanc33[3] = t3dLoadCharacter(*this, "Lanc33d.t3d", 99))) {
|
||||
warning("Error loading Lanc33");
|
||||
return false;
|
||||
}
|
||||
|
||||
warning("Reached loop: %02X", LoadChar);
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (i >= ocCURPLAYER) continue;
|
||||
|
||||
if (LoadChar & (1 << i)) {
|
||||
if ((i + 1) == ocMOGLIESUPERVISORE) {
|
||||
if (bMoglieGym) {
|
||||
CharName_Strings[i + 1] = "MoglieGym.t3d";
|
||||
CharNameHI_Strings[i + 1] = "MoglieGymHI.t3d";
|
||||
} else {
|
||||
CharName_Strings[i + 1] = "MoglieSwim.t3d";
|
||||
CharNameHI_Strings[i + 1] = "MoglieSwimHI.t3d";
|
||||
}
|
||||
}
|
||||
if ((i + 1) == ocMOGLIE_KIMONO) {
|
||||
if (bMoglieSangue) {
|
||||
CharName_Strings[i + 1] = "MoglieKimonoSangue.t3d";
|
||||
CharNameHI_Strings[i + 1] = "MoglieKimonoSangueHI.t3d";
|
||||
} else {
|
||||
CharName_Strings[i + 1] = "MoglieKimono.t3d";
|
||||
CharNameHI_Strings[i + 1] = "MoglieKimono.t3d";
|
||||
}
|
||||
}
|
||||
warning("About to load %s", CharName[i + 1]);
|
||||
if (!(Character[i + 1] = t3dLoadCharacter(*this, CharName[i + 1], i))) {
|
||||
warning("Error loading %s", CharName[i + 1]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
LoaderFlags &= ~T3D_PRELOADBASE;
|
||||
LoaderFlags &= ~T3D_STATIC_SET1;
|
||||
rSetLoaderFlags(LoaderFlags);
|
||||
}
|
||||
|
||||
if (!lite) {
|
||||
if (LoaderFlags & T3D_PRELOAD_RXT) {
|
||||
t3dCurOliSet = -1;
|
||||
// TODO: Figure out how this i works out.
|
||||
if (!(t3dRxt = _roomManager->loadRoom("rxt.t3d", t3dCurRoom, &i, LoaderFlags | T3D_NOLIGHTMAPS))) {
|
||||
warning("Error loading room rxt.t3d");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (LoaderFlags & T3D_SKY) {
|
||||
t3dLoadSky(*this, t3dCurRoom);
|
||||
t3dCreateProceduralSky();
|
||||
}
|
||||
|
||||
LoaderFlags &= ~T3D_STATIC_SET0;
|
||||
rSetLoaderFlags(LoaderFlags);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
}
|
||||
|
||||
if (!((LoaderFlags & T3D_PRELOAD_RXT) && name.equalsIgnoreCase("rxt.t3d"))) {
|
||||
if (!(t3dCurRoom = _roomManager->loadRoom(name, t3dCurRoom, &i, LoaderFlags))) {
|
||||
warning("Error loading room %s", name.c_str());
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
t3dCurRoom = t3dRxt;
|
||||
|
||||
if ((!lite) && (!(LoaderFlags & T3D_DEBUGMODE))) {
|
||||
if (!CheckAndLoadMoglieSupervisoreModel(ocMOGLIESUPERVISORE)) return false;
|
||||
if (!CheckAndLoadMoglieSupervisoreModel(ocMOGLIE_KIMONO)) return false;
|
||||
}
|
||||
|
||||
if (bGolfActive) {
|
||||
// extern t3dS32 SkySurface;
|
||||
if (!(Character[1] = t3dLoadCharacter(*this, "Gopher1.t3d", 99))) {
|
||||
warning("Error loading Gopher1");
|
||||
return false;
|
||||
}
|
||||
if (!(Character[2] = t3dLoadCharacter(*this, "Gopher2.t3d", 99))) {
|
||||
warning("Error loading Gopher2");
|
||||
return false;
|
||||
}
|
||||
if (!(Character[3] = t3dLoadCharacter(*this, "Gopher3.t3d", 99))) {
|
||||
warning("Error loading Gopher3");
|
||||
return false;
|
||||
}
|
||||
if (!(GopherMark[0] = t3dLoadCharacter(*this, "Mark1.t3d", 99))) {
|
||||
warning("Error loading Mark1");
|
||||
return false;
|
||||
}
|
||||
if (!(GopherMark[1] = t3dLoadCharacter(*this, "Mark2.t3d", 99))) {
|
||||
warning("Error loading Mark2");
|
||||
return false;
|
||||
}
|
||||
if (!(GopherMark[2] = t3dLoadCharacter(*this, "Mark3.t3d", 99))) {
|
||||
warning("Error loading Mark3");
|
||||
return false;
|
||||
}
|
||||
if (!(Palla50 = t3dLoadCharacter(*this, "Palla.t3d", 99))) {
|
||||
warning("Error loading Palla50");
|
||||
return false;
|
||||
}
|
||||
if (!(Freccia50 = t3dLoadCharacter(*this, "Freccia.t3d", 99))) {
|
||||
warning("Error loading Freccia50");
|
||||
return false;
|
||||
}
|
||||
if (!(Explode50 = t3dLoadCharacter(*this, "Explode.t3d", 99))) {
|
||||
warning("Error loading Explode50");
|
||||
return false;
|
||||
}
|
||||
// t3dLoadSky(t3dCurRoom);
|
||||
// t3dCreateProceduralSky();
|
||||
t3dGolfSky = LinkMeshToStr(init, "p50-cielo");
|
||||
// t3dCurRoom->MatTable[Obj[oNEXTPORTAL].pos].Texture=rGetSurfaceTexture(SkySurface);
|
||||
|
||||
Palla50->Flags &= ~T3D_CHARACTER_HIDE;
|
||||
Palla50->Mesh->Flags &= ~T3D_MESH_HIDDEN;
|
||||
|
||||
Freccia50->Flags |= T3D_CHARACTER_HIDE;
|
||||
Freccia50->Mesh->Flags &= ~T3D_MESH_HIDDEN;
|
||||
|
||||
Explode50->Flags |= T3D_CHARACTER_HIDE;
|
||||
Explode50->Mesh->Flags &= ~T3D_MESH_HIDDEN;
|
||||
|
||||
Character[ocVICTORIA]->Flags &= ~T3D_CHARACTER_HIDE;
|
||||
CharSetPosition(ocVICTORIA, 7, nullptr);
|
||||
t3dClipToSurface(init, &Character[ocVICTORIA]->Mesh->Trasl);
|
||||
t3dLightChar(Character[ocVICTORIA]->Mesh, &Character[ocVICTORIA]->Mesh->Trasl);
|
||||
|
||||
Character[ocCUOCO]->Flags &= ~T3D_CHARACTER_HIDE;
|
||||
CharSetPosition(ocCUOCO, 13, nullptr);
|
||||
t3dClipToSurface(init, &Character[ocCUOCO]->Mesh->Trasl);
|
||||
t3dLightChar(Character[ocCUOCO]->Mesh, &Character[ocCUOCO]->Mesh->Trasl);
|
||||
|
||||
GopherMark[0]->Flags |= T3D_CHARACTER_HIDE;
|
||||
GopherMark[1]->Flags |= T3D_CHARACTER_HIDE;
|
||||
GopherMark[2]->Flags |= T3D_CHARACTER_HIDE;
|
||||
|
||||
CurGopher = -1;
|
||||
NextGopher(*this);
|
||||
InitPhys(&Ball[CurGopher]);
|
||||
}
|
||||
|
||||
t3dCurCharacter = Player = Character[ocCURPLAYER] = Character[ocDARRELL + CurPlayer];
|
||||
if (lite) Player->Flags |= T3D_CHARACTER_HIDE;
|
||||
else Player->Flags &= ~T3D_CHARACTER_HIDE;
|
||||
|
||||
Character[ocDARRELL]->Flags |= (T3D_CHARACTER_CASTREALTIMESHADOWS | T3D_CHARACTER_REALTIMELIGHTING | T3D_CHARACTER_VOLUMETRICLIGHTING);
|
||||
Character[ocVICTORIA]->Flags |= (T3D_CHARACTER_CASTREALTIMESHADOWS | T3D_CHARACTER_REALTIMELIGHTING | T3D_CHARACTER_VOLUMETRICLIGHTING);
|
||||
Player->Flags |= (T3D_CHARACTER_CASTREALTIMESHADOWS | T3D_CHARACTER_REALTIMELIGHTING | T3D_CHARACTER_VOLUMETRICLIGHTING);
|
||||
|
||||
CurFloorY = t3dCurRoom->PanelHeight[t3dCurRoom->CurLevel];
|
||||
|
||||
t3dMatIdentity(&init._globals._invVars.CameraDummy.Matrix);
|
||||
t3dStartTime();
|
||||
|
||||
if (!t3dCurRoom->CameraTable.empty())
|
||||
if (!(t3dCurCamera = _cameraMan->PickCamera(t3dCurRoom, 0)))
|
||||
t3dCurCamera = &t3dCurRoom->CameraTable[0];
|
||||
if (t3dCurCamera)
|
||||
init._globals._invVars.t3dIconCamera = *t3dCurCamera;
|
||||
|
||||
SetCurPlayerPosTo_9x(_gameVars, init);
|
||||
|
||||
Player->Pos.y = Player->Mesh->Trasl.y = CurFloorY;
|
||||
|
||||
_cameraMan->GetCameraTarget(init, &t3dCurCamera->Target);
|
||||
_renderer->setCurCameraViewport(t3dCurCamera->Fov, bSuperView);
|
||||
|
||||
mPosx = windowInfo.width / 2;
|
||||
mPosy = windowInfo.height / 2;
|
||||
|
||||
if (lite) {
|
||||
ResetScreenBuffer(); //resetto in modo che la scritta di loading non faccia casini
|
||||
UpdateAll();
|
||||
InitMain(*this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------13/07/00 15.21-------------------
|
||||
* UpdateAll
|
||||
* --------------------------------------------------*/
|
||||
void WGame::UpdateAll() {
|
||||
UpdateRoomVisibility(*this);
|
||||
auto bodies = _roomManager->getLoadedFiles();
|
||||
for (auto loadedBody : bodies) {
|
||||
HideRoomMeshes(init, loadedBody);
|
||||
_meshModifiers->applyAllMeshModifiers(*this, loadedBody);
|
||||
}
|
||||
|
||||
UpdateAllClocks(*this);
|
||||
|
||||
// Init for Clock33
|
||||
t3dMatIdentity(&Lanc33[0]->Mesh->Matrix);
|
||||
t3dMatIdentity(&Lanc33[1]->Mesh->Matrix);
|
||||
t3dMatIdentity(&Lanc33[2]->Mesh->Matrix);
|
||||
t3dMatIdentity(&Lanc33[3]->Mesh->Matrix);
|
||||
t3dVectInit(&Lanc33[2]->Mesh->Trasl, -2402.881f, 350.092f, -5110.331f);
|
||||
Lanc33[2]->Flags &= ~T3D_CHARACTER_HIDE;
|
||||
t3dVectInit(&Lanc33[3]->Mesh->Trasl, -2402.881f, 350.092f, -5110.331f);
|
||||
Lanc33[3]->Flags &= ~T3D_CHARACTER_HIDE;
|
||||
t3dVectInit(&Lanc33[0]->Mesh->Trasl, -2441.371f, 350.092f, -5110.331f);
|
||||
Lanc33[0]->Flags &= ~T3D_CHARACTER_HIDE;
|
||||
t3dVectInit(&Lanc33[1]->Mesh->Trasl, -2441.371f, 350.092f, -5110.331f);
|
||||
Lanc33[1]->Flags &= ~T3D_CHARACTER_HIDE;
|
||||
t3dVectInit(&mPos, -2484.0f, 381.0f, -5085.0f);
|
||||
bClock33 = 0;
|
||||
doClock33(*this, o33LANCETTAHSX, &mPos);
|
||||
t3dVectInit(&mPos, -2390.0f, 330.0f, -5085.0f);
|
||||
bClock33 = 0;
|
||||
doClock33(*this, o33LANCETTAMSX, &mPos);
|
||||
t3dVectInit(&mPos, -2415.0f, 325.0f, -5085.0f);
|
||||
bClock33 = 0;
|
||||
doClock33(*this, o33LANCETTAHDX, &mPos);
|
||||
t3dVectInit(&mPos, -2476.0f, 397.0f, -5085.0f);
|
||||
bClock33 = 0;
|
||||
doClock33(*this, o33LANCETTAMDX, &mPos);
|
||||
bClock33 = 0;
|
||||
}
|
||||
|
||||
/* -----------------27/10/98 16.27-------------------
|
||||
*
|
||||
* --------------------------------------------------*/
|
||||
void WGame::LoadMisc() {
|
||||
warning("LoadMisc");
|
||||
char str[20];
|
||||
int32 i;
|
||||
|
||||
auto windowInfo = _renderer->getScreenInfos();
|
||||
|
||||
if (bMiscLoaded) return;
|
||||
|
||||
/*
|
||||
rClear( BACK_BUFFER, 0, 0, MainDx, MainDy, 0, 0, 0 );
|
||||
rBlitScreenBuffer();
|
||||
rShowFrame();
|
||||
|
||||
*/
|
||||
_fonts.loadFonts(*this, windowInfo);
|
||||
|
||||
Console1 = LoadDDBitmap(*this, "Console1.tga", rSURFACESTRETCH);
|
||||
ConsoleFrecciaGiu = LoadDDBitmap(*this, "consoleFrecciaGiu.tga", rSURFACESTRETCH);
|
||||
ConsoleFrecciaSu = LoadDDBitmap(*this, "consoleFrecciaSu.tga", rSURFACESTRETCH);
|
||||
Console2 = LoadDDBitmap(*this, "Console2.tga", rSURFACESTRETCH);
|
||||
Console3 = LoadDDBitmap(*this, "Console3.tga", rSURFACESTRETCH);
|
||||
Console4 = LoadDDBitmap(*this, "Console4.tga", rSURFACESTRETCH);
|
||||
ConsoleNoSwitchDar = LoadDDBitmap(*this, "ConsoleNoSwitchDar.tga", rSURFACESTRETCH);
|
||||
ConsoleNoSwitchVic = LoadDDBitmap(*this, "ConsoleNoSwitchVic.tga", rSURFACESTRETCH);
|
||||
ConsoleNoSave = LoadDDBitmap(*this, "ConsoleNoSave.tga", rSURFACESTRETCH);
|
||||
ConsoleD1 = LoadDDBitmap(*this, "ConsoleD1.tga", rSURFACESTRETCH);
|
||||
ConsoleD2 = LoadDDBitmap(*this, "ConsoleD2.tga", rSURFACESTRETCH);
|
||||
Console5 = LoadDDBitmap(*this, "Console5.tga", rSURFACESTRETCH);
|
||||
Console6 = LoadDDBitmap(*this, "Console6.tga", rSURFACESTRETCH);
|
||||
NewLogImage = LoadDDBitmap(*this, "NewLogImage.tga", rSURFACESTRETCH);
|
||||
LoadingImage = LoadDDBitmap(*this, "Loading.tga", rSURFACESTRETCH);
|
||||
MousePointerDefault = LoadDDBitmap(*this, "Pointer.tga", 0);
|
||||
MousePointerPlus = LoadDDBitmap(*this, "PointerPlus.tga", 0);
|
||||
CurMousePointer = MousePointerDefault;
|
||||
if (bGolfActive) {
|
||||
GopherMap = LoadDDBitmap(*this, "GopherMap.tga", rSURFACESTRETCH);
|
||||
GopherPos[0] = LoadDDBitmap(*this, "Gopher1.tga", rSURFACESTRETCH);
|
||||
GopherPos[1] = LoadDDBitmap(*this, "Gopher2.tga", rSURFACESTRETCH);
|
||||
GopherPos[2] = LoadDDBitmap(*this, "Gopher3.tga", rSURFACESTRETCH);
|
||||
GopherBall = LoadDDBitmap(*this, "GopherBall.tga", rSURFACESTRETCH);
|
||||
EndPic = LoadDDBitmap(*this, "TrecLogo.tga", rSURFACESTRETCH);
|
||||
}
|
||||
MousePointerLim.x1 = 0;
|
||||
MousePointerLim.y1 = 0;
|
||||
MousePointerLim.x2 = windowInfo.width;
|
||||
MousePointerLim.y2 = windowInfo.height;
|
||||
//TrecLogo = LoadDDBitmap( "TrecLogo.tga", rSURFACESTRETCH );
|
||||
|
||||
for (i = 1; i < 85; i++) {
|
||||
snprintf(str, 20, "I%03d.tga", i);
|
||||
IconsPics[i] = LoadDDBitmap(*this, str, rSURFACESTRETCH);
|
||||
}
|
||||
|
||||
bMiscLoaded = 1;
|
||||
warning("LoadMisc Done");
|
||||
}
|
||||
|
||||
void WGame::GameLoop() {
|
||||
bool done = false;
|
||||
//bool bGotMsg = false;
|
||||
//MSG msg;
|
||||
|
||||
// TODO: These two should be adjusted if the game loses focus or needs to get a new context.
|
||||
g_bActive = g_bReady = true;
|
||||
|
||||
while (!done) { // MainLoop
|
||||
/* TODO: Throttle the loop
|
||||
if( g_bActive )
|
||||
bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
|
||||
else
|
||||
bGotMsg = GetMessage( &msg, NULL, 0U, 0U );
|
||||
|
||||
if( bGotMsg )
|
||||
{
|
||||
TranslateMessage( &msg );
|
||||
DispatchMessage( &msg );
|
||||
}
|
||||
else
|
||||
{*/
|
||||
//sleep(1);
|
||||
|
||||
// TODO: The SDL polling should go inside ProcessTime to match the expected behaviour wrt keyboard/mouse
|
||||
sdl->pollSDL();
|
||||
done = sdl->shouldQuit;
|
||||
if (g_bActive && g_bReady) {
|
||||
//warning("NextMessage");
|
||||
NextMessage(*this);
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
void WGame::CleanUpAndPostQuit() {
|
||||
gameOptions.save(workDirs);
|
||||
warning("STUBBED CleanupAndPostQuit");
|
||||
#if 0
|
||||
extern char *TextBucket;
|
||||
|
||||
if (CreditsNames) t3dFree(CreditsNames);
|
||||
if (CreditsRoles) t3dFree(CreditsRoles);
|
||||
|
||||
if ((RoomInfo.tnum) && (RoomInfo.tnum != -1)) {
|
||||
rReleaseBitmap(RoomInfo.tnum);
|
||||
RoomInfo.tnum = 0;
|
||||
}
|
||||
|
||||
CheckExtraLocalizationStrings(0);
|
||||
|
||||
for (uint16 i = 0; i < T3D_MAX_CHARACTERS; i++) {
|
||||
if ((i != ocCURPLAYER) && (Character[i]))
|
||||
CharStop(i);
|
||||
|
||||
if (i < (T3D_MAX_CHARACTERS - 1))
|
||||
t3dReleaseCharacter(Character[i]);
|
||||
Character[i] = nullptr;
|
||||
}
|
||||
Player = nullptr;
|
||||
for (uint16 i = 0; i < NumLoadedFiles; i++) {
|
||||
t3dReleaseBody(LoadedFiles[i].b);
|
||||
LoadedFiles[i].b = nullptr;
|
||||
}
|
||||
|
||||
ReleasePreloadedAnims();
|
||||
t3dReleaseParticles();
|
||||
|
||||
rReleaseAllTextures(0);
|
||||
rReleaseAllBitmaps(0);
|
||||
|
||||
if (TextBucket) free(TextBucket);
|
||||
t3dFree(StandardFont.Table);
|
||||
|
||||
t3dDeallocMemoryPool();
|
||||
t3dEndTime();
|
||||
|
||||
DInputTermMouse();
|
||||
DInputTermKbd();
|
||||
CloseMusic();
|
||||
CloseLogWindow();
|
||||
rCleanup3DEnvironment();
|
||||
t3dFastFileFinish();
|
||||
|
||||
PostQuitMessage(0);
|
||||
|
||||
remove("temp.tmp");
|
||||
|
||||
exit(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void WGame::addMeshModifier(const Common::String &name, int16 com, void *p) {
|
||||
_meshModifiers->addMeshModifier(name, com, p);
|
||||
}
|
||||
|
||||
void WGame::loadMeshModifiers(Common::SeekableReadStream &stream) {
|
||||
delete _meshModifiers;
|
||||
_meshModifiers = new MeshModifiers(stream);
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
122
engines/watchmaker/game.h
Normal file
122
engines/watchmaker/game.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_GAME_H
|
||||
#define WATCHMAKER_GAME_H
|
||||
|
||||
#include "common/random.h"
|
||||
#include "watchmaker/3d/loader.h"
|
||||
#include "watchmaker/fonts.h"
|
||||
#include "watchmaker/game_options.h"
|
||||
#include "watchmaker/ll/ll_ffile.h"
|
||||
#include "watchmaker/saveload.h"
|
||||
#include "watchmaker/schedule.h"
|
||||
#include "watchmaker/work_dirs.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
class sdl_wrapper;
|
||||
class Renderer;
|
||||
|
||||
struct GameVars {
|
||||
private:
|
||||
int32 CurRoom = 0;
|
||||
|
||||
public:
|
||||
void setCurRoomId(int32 room) {
|
||||
CurRoom = room;
|
||||
}
|
||||
int32 getCurRoomId() const {
|
||||
return CurRoom;
|
||||
}
|
||||
};
|
||||
|
||||
class MeshModifiers;
|
||||
class RoomManager;
|
||||
class CameraMan;
|
||||
|
||||
class WGame {
|
||||
bool g_bReady = false, g_bActive = false;
|
||||
//bool g_bSkipActive = false;
|
||||
const char *CharName[32] = {};
|
||||
uint32 LoadChar;
|
||||
MeshModifiers *_meshModifiers;
|
||||
|
||||
public:
|
||||
Common::RandomSource *_rnd;
|
||||
Renderer *_renderer;
|
||||
WorkDirs workDirs;
|
||||
GameOptions gameOptions;
|
||||
Init init;
|
||||
sdl_wrapper *sdl;
|
||||
GameVars _gameVars;
|
||||
GameRect _gameRect;
|
||||
Fonts _fonts;
|
||||
MessageSystem _messageSystem;
|
||||
RoomManager *_roomManager;
|
||||
CameraMan *_cameraMan;
|
||||
WGame();
|
||||
~WGame();
|
||||
|
||||
SRoom &getCurRoom() {
|
||||
return init.Room[_gameVars.getCurRoomId()];
|
||||
}
|
||||
|
||||
Common::SharedPtr<Common::SeekableReadStream> resolveFile(const char *path, bool noFastFile = false);
|
||||
|
||||
void configLoaderFlags(bool debugMode) {
|
||||
// TODO: Add back some of the configurability from the argument parsing.
|
||||
LoadChar = 3;
|
||||
LoaderFlags = T3D_STATIC_SET0;
|
||||
LoaderFlags |= T3D_OUTDOORLIGHTS;
|
||||
LoaderFlags |= T3D_PRELOADBASE;
|
||||
LoaderFlags |= T3D_STATIC_SET1;
|
||||
if (debugMode) {
|
||||
LoaderFlags |= T3D_DEBUGMODE;
|
||||
}
|
||||
|
||||
if (!(LoaderFlags & T3D_DEBUGMODE)) {
|
||||
LoadChar = 3;
|
||||
LoadChar |= 16777212;
|
||||
}
|
||||
}
|
||||
|
||||
int StartPlayingGame(const Common::String &LoaderName_override);
|
||||
bool LoadAndSetup(const Common::String &name, uint8 lite);
|
||||
void LoadMisc();
|
||||
void UpdateAll();
|
||||
void initCharNames();
|
||||
void CleanUpAndPostQuit();
|
||||
|
||||
bool CheckAndLoadMoglieSupervisoreModel(int32 c);
|
||||
|
||||
void GameLoop();
|
||||
|
||||
// TODO: These might belong elsewhere after some refactoring:
|
||||
void addMeshModifier(const Common::String &name, int16 com, void *p);
|
||||
void loadMeshModifiers(Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
extern WGame *_vm;
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_GAME_H
|
||||
26
engines/watchmaker/game_options.cpp
Normal file
26
engines/watchmaker/game_options.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/game_options.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
96
engines/watchmaker/game_options.h
Normal file
96
engines/watchmaker/game_options.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_GAME_OPTIONS_H
|
||||
#define WATCHMAKER_GAME_OPTIONS_H
|
||||
#include "common/stream.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/work_dirs.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
class GameOptions {
|
||||
public:
|
||||
uint8 sound_on = 1;
|
||||
uint8 sound_volume = 100;
|
||||
uint8 music_on = 1;
|
||||
uint8 music_volume = 100;
|
||||
uint8 speech_on = 1;
|
||||
uint8 speech_volume = 100;
|
||||
uint8 subtitles_on = 1;
|
||||
bool bShowRoomDescriptions = true;
|
||||
bool bShowExtraLocalizationStrings = false;
|
||||
bool load(WorkDirs &workDirs) {
|
||||
warning("TODO: Game options");
|
||||
#if 0
|
||||
Common::String path = workDirs._gameDir + workDirs._savesDir + "options.dat";
|
||||
|
||||
auto stream = openFile(path);
|
||||
|
||||
sound_on = stream->readByte();
|
||||
sound_volume = stream->readByte();
|
||||
music_on = stream->readByte();
|
||||
music_volume = stream->readByte();
|
||||
speech_on = stream->readByte();
|
||||
speech_volume = stream->readByte();
|
||||
subtitles_on = stream->readByte();
|
||||
bShowRoomDescriptions = stream->readByte();
|
||||
bShowExtraLocalizationStrings = stream->readByte();
|
||||
warning("Done loading options");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool save(WorkDirs &workDirs) {
|
||||
warning("TODO: Game options");
|
||||
#if 0
|
||||
FILE *fp;
|
||||
char str[T3D_NAMELEN];
|
||||
|
||||
sprintf(str, "%sOptions.dat", workDirs._savesDir.c_str());
|
||||
fp = fopen(str, "wb");
|
||||
|
||||
if (!fp) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
fwrite(&sound_on, sizeof(uint8), 1, fp);
|
||||
fwrite(&sound_volume, sizeof(uint8), 1, fp);
|
||||
fwrite(&music_on, sizeof(uint8), 1, fp);
|
||||
fwrite(&music_volume, sizeof(uint8), 1, fp);
|
||||
fwrite(&speech_on, sizeof(uint8), 1, fp);
|
||||
fwrite(&speech_volume, sizeof(uint8), 1, fp);
|
||||
fwrite(&subtitles_on, sizeof(uint8), 1, fp);
|
||||
fwrite(&bShowRoomDescriptions, sizeof(uint8), 1, fp);
|
||||
fwrite(&bShowExtraLocalizationStrings, sizeof(uint8), 1, fp);
|
||||
|
||||
fclose(fp);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_GAME_OPTIONS_H
|
||||
188
engines/watchmaker/globvar.cpp
Normal file
188
engines/watchmaker/globvar.cpp
Normal file
@@ -0,0 +1,188 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/struct.h"
|
||||
#include "watchmaker/sysdef.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/3d/t3d_mesh.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
// GAME RECT
|
||||
GameRect::GameRect() {
|
||||
_bigIconRect = {INV_MARG_DX + 30, INV_MARG_UP - 12, 775, 587 /*INV_MARG_DOWN+10 */};
|
||||
_useIconRect = {720, 517, 787, 587};
|
||||
_closeInvRect = {667, 13, 782, 73};
|
||||
_quitGameRect = {563, 13, 667, 73};
|
||||
_playerInvRect = {22, 13, 200, 73};
|
||||
_invSaveRect = {223, 13, 284, 73};
|
||||
_invLoadRect = {332, 13, 401, 73};
|
||||
_invOptionsRect = {437, 13, 523, 73};
|
||||
_inv1Up = {3 + 16, 67 + 56, 3 + 28, 67 + 96};
|
||||
_inv1Down = {3 + 205, 67 + 411, 3 + 224, 67 + 444};
|
||||
_diag2Up = {768, 510, 797, 537};
|
||||
_diag2Down = {768, 568, 797, 595};
|
||||
_callOtherPlayerRect = {22, 13, 22 + 192, 13 + 60};
|
||||
}
|
||||
struct SD3DRect D3DRectsList[MAX_D3D_RECTS];
|
||||
struct SD3DTriangle D3DTrianglesList[MAX_D3D_TRIANGLES];
|
||||
struct SD3DBitmap D3DBitmapsList[MAX_D3D_BITMAPS];
|
||||
|
||||
// 2D INTERFACE
|
||||
int32 MainDx, MainDy, MainBpp;
|
||||
int32 IconsPics[MAX_ICONS];
|
||||
int32 Console1, ConsoleFrecciaGiu, ConsoleFrecciaSu, Console2, Console3, Console4, Console5, Console6, ConsoleNoSwitchDar, ConsoleNoSwitchVic, ConsoleNoSave;
|
||||
int32 ConsoleD1, ConsoleD2, StartPic, EndPic, NewLogImage, LoadingImage;
|
||||
int32 CurMousePointer, MousePointerDefault, MousePointerPlus, TrecLogo;
|
||||
int32 GopherMap, GopherPos[MAX_GOPHERS], GopherBall;
|
||||
struct SRect MousePointerLim;
|
||||
|
||||
// LOADER VARS
|
||||
char LoaderName[T3D_NAMELEN] = "rxt.t3d";
|
||||
char WmCfgName[T3D_NAMELEN] = "wm.cfg";
|
||||
uint32 LoaderFlags = 0;
|
||||
char WmGameDataPak_FilePath[MAX_PATH] = WM_GAMEDATA_PACK_FILENAME;
|
||||
|
||||
// SENTENCES
|
||||
char *ObjName[MAX_OBJ_NAMES];
|
||||
char *Sentence[MAX_SENTENCES];
|
||||
char *SysSent[MAX_SYS_SENTS];
|
||||
char *TooltipSent[MAX_TOOLTIP_SENTS];
|
||||
struct SString TheString = { "", 0, 0 };
|
||||
char CurDebugString[MAX_STRING_LEN];
|
||||
char TextLines[MAX_TEXT_LINES][MAX_TEXT_CHARS];
|
||||
|
||||
// MESSAGE SYSTEM
|
||||
message *TheMessage;
|
||||
|
||||
// GAME VARS
|
||||
int32 CurObj;
|
||||
int32 NextPortalObj;
|
||||
int32 NextPortalAnim;
|
||||
int32 FromFirstPersonAnim;
|
||||
int32 ToFirstPersonSent;
|
||||
int32 CurInvObj;
|
||||
int32 BigInvObj;
|
||||
int32 CurPlayer = DARRELL;
|
||||
int32 CurDialog, CurMenu, CurDlgItem;
|
||||
int32 CurSubMusic;
|
||||
int32 CurAlternate[T3D_MAX_CHARACTERS];
|
||||
int32 CurGopher;
|
||||
|
||||
// TIME
|
||||
uint32 TheTime;
|
||||
uint32 NextRefresh, PaintTime, LoadTime;
|
||||
t3dF32 CurFps, AvgFps;
|
||||
t3dF32 FrameFactor;
|
||||
|
||||
// INV
|
||||
uint8 Inv[MAX_PLAYERS][MAX_ICONS_IN_INV];
|
||||
uint8 InvLen[MAX_PLAYERS], InvBase[MAX_PLAYERS];
|
||||
uint8 InvStatus = INV_OFF;
|
||||
uint8 Diag2Base;
|
||||
|
||||
// USE WITH
|
||||
int32 UseWith[2];
|
||||
|
||||
// SEMAFORI
|
||||
uint8 bSomeOneSpeak;
|
||||
uint8 bPlayerSpeak;
|
||||
uint8 bUseWith;
|
||||
uint8 bSkipTalk;
|
||||
uint8 bFirstPerson;
|
||||
uint8 bDialogActive;
|
||||
uint8 bDialogMenuActive;
|
||||
uint8 bMovingCamera;
|
||||
uint8 bCutCamera;
|
||||
uint8 bAllowCalcCamera;
|
||||
uint8 bAnimWaitText;
|
||||
uint8 bPlayerInAnim;
|
||||
uint8 bFastWalk;
|
||||
uint8 bNotSkippableWalk;
|
||||
uint8 bNoFirstPersonSwitch;
|
||||
uint8 bClock33;
|
||||
uint8 bShowInfo;
|
||||
uint8 bShowBoundingBox;
|
||||
uint8 bShowPanels;
|
||||
uint8 bForceWire;
|
||||
uint8 bPauseAllAnims;
|
||||
uint8 bT2DActive;
|
||||
uint8 bGolfActive = false; // HACK
|
||||
uint8 bGolfMode;
|
||||
uint8 bIngnoreDIKeyboard;
|
||||
uint8 bDisableDiary;
|
||||
uint8 bNoPlayerSwitch;
|
||||
uint8 bCacciatore;
|
||||
uint8 bDarkScreen;
|
||||
uint8 bSaveDisabled;
|
||||
uint8 bLockCamera;
|
||||
uint8 bMiscLoaded;
|
||||
uint8 bStartMenuActive;
|
||||
uint8 bShowOnlyLoadWindow;
|
||||
uint8 bNotSkippableSent;
|
||||
uint8 bPorteEsternoBloccate;
|
||||
uint8 bSuperView;
|
||||
uint8 bSezioneLabirinto;
|
||||
uint8 bPlayerSuBasamento;
|
||||
uint8 bWideScreen;
|
||||
uint8 bTitoliCodaStatic;
|
||||
uint8 bTitoliCodaScrolling;
|
||||
uint8 bDontPlaySteps;
|
||||
uint8 bShowRoomDescriptions;
|
||||
uint8 bShowExtraLocalizationStrings;
|
||||
|
||||
// 3D INTERFACE
|
||||
uint8 PlayerPos[T3D_MAX_CHARACTERS];
|
||||
uint8 PlayerGotoPos[T3D_MAX_CHARACTERS];
|
||||
uint8 ForcedCamera, FastWalk;
|
||||
uint16 AnimAutoPush;
|
||||
int32 CameraTargetObj, CameraTargetBone;
|
||||
int32 TimeWalk, TimeAnim;
|
||||
|
||||
// MOUSE VARS
|
||||
char ObjectUnderCursor[MAX_STRING_LEN];
|
||||
t3dV3F mPos;
|
||||
|
||||
// 3D MESH MODIFIER
|
||||
struct SPlayerStand PlayerStand[MAX_PLAYERS];
|
||||
|
||||
// CHARACTERS VARS
|
||||
t3dCHARACTER *Player;
|
||||
t3dCHARACTER *Character[T3D_MAX_CHARACTERS];
|
||||
t3dCHARSTOPSTATUS CharStopStatus[T3D_MAX_CHARACTERS];
|
||||
t3dCHARACTER *Lanc33[4];
|
||||
t3dCHARACTER *Palla50;
|
||||
t3dCHARACTER *Freccia50;
|
||||
t3dCHARACTER *GopherMark[MAX_GOPHERS];
|
||||
t3dCHARACTER *Explode50;
|
||||
t3dMESH *t3dGolfSky;
|
||||
int32 Comb2D[5], Comb2Q[5], Comb19[3], Comb1D[5], Forno25, Frigo25, Comb31[5], Comb33[4], Comb42[12], Comb44[3], Comb45[5];
|
||||
uint8 bMoglieGym, bMoglieSangue;
|
||||
|
||||
// DIALOG VARS
|
||||
uint8 UsedDlgMenu[MAX_PLAYERS][T3D_MAX_CHARACTERS][MAX_DLG_MENUS]; //DlgMenu che sono gia' stati utilizzati dal personaggio
|
||||
|
||||
// OPTIONS VARS
|
||||
struct SGameOptions GameOptions;
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
263
engines/watchmaker/globvar.h
Normal file
263
engines/watchmaker/globvar.h
Normal file
@@ -0,0 +1,263 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_GLOBVAR_H
|
||||
#define WATCHMAKER_GLOBVAR_H
|
||||
|
||||
#include "watchmaker/struct.h"
|
||||
#include "watchmaker/3d/t3d_mesh.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
#define MAX_PATH 256
|
||||
|
||||
// GAME RECT
|
||||
struct GameRect {
|
||||
GameRect();
|
||||
SRect _bigIconRect;
|
||||
SRect _useIconRect;
|
||||
SRect _quitGameRect;
|
||||
SRect _closeInvRect;
|
||||
SRect _playerInvRect;
|
||||
SRect _invSaveRect;
|
||||
SRect _invLoadRect;
|
||||
SRect _invOptionsRect;
|
||||
SRect _inv1Up;
|
||||
SRect _inv1Down;
|
||||
SRect _diag2Up;
|
||||
SRect _diag2Down;
|
||||
SRect _callOtherPlayerRect;
|
||||
};
|
||||
extern struct SD3DRect D3DRectsList[];
|
||||
extern struct SD3DTriangle D3DTrianglesList[];
|
||||
extern struct SD3DBitmap D3DBitmapsList[];
|
||||
|
||||
// 2D INTERFACE
|
||||
extern int32 MainDx, MainDy, MainBpp;
|
||||
extern int32 IconsPics[MAX_ICONS];
|
||||
extern int32 Console1, ConsoleFrecciaGiu, ConsoleFrecciaSu, Console2, Console3, Console4, Console5, Console6, ConsoleNoSwitchDar, ConsoleNoSwitchVic, ConsoleNoSave;
|
||||
extern int32 ConsoleD1, ConsoleD2, StartPic, EndPic, NewLogImage, LoadingImage;
|
||||
extern int32 CurMousePointer, MousePointerDefault, MousePointerPlus, TrecLogo;
|
||||
extern int32 GopherMap, GopherPos[], GopherBall;
|
||||
extern struct SRect MousePointerLim;
|
||||
|
||||
// 3D INTERFACE
|
||||
extern t3dF32 CurFloorY;
|
||||
extern uint8 PlayerPos[];
|
||||
extern uint8 PlayerGotoPos[];
|
||||
extern uint8 ForcedCamera, FastWalk;
|
||||
extern uint16 AnimAutoPush;
|
||||
extern int32 CameraTargetObj, CameraTargetBone;
|
||||
extern int32 TimeWalk, TimeAnim;
|
||||
|
||||
// LOADER VARS
|
||||
extern char LoaderName[];
|
||||
extern char WmCfgName[];
|
||||
extern uint32 LoaderFlags;
|
||||
extern char WmGameDataPak_FilePath[];
|
||||
|
||||
// INV VARS
|
||||
struct InvVars {
|
||||
t3dBODY *t3dIcons;
|
||||
t3dMESH CameraDummy;
|
||||
t3dCAMERA t3dIconCamera;
|
||||
t3dM3X3F BigIconM;
|
||||
};
|
||||
|
||||
// MOUSE VARS
|
||||
extern char ObjectUnderCursor[];
|
||||
extern t3dV3F mPos;
|
||||
|
||||
extern struct SPlayerStand PlayerStand[];
|
||||
|
||||
// SENTENCES
|
||||
extern char *ObjName[];
|
||||
extern char *Sentence[];
|
||||
extern char *SysSent[];
|
||||
extern char *TooltipSent[];
|
||||
extern struct SString TheString;
|
||||
extern char CurDebugString[];
|
||||
extern char TextLines[MAX_TEXT_LINES][MAX_TEXT_CHARS];
|
||||
|
||||
extern t3dCHARACTER *Player;
|
||||
extern t3dCHARACTER *Character[];
|
||||
extern t3dCHARSTOPSTATUS CharStopStatus[];
|
||||
extern t3dCHARACTER *Lanc33[];
|
||||
extern t3dCHARACTER *Sfera34;
|
||||
extern t3dCHARACTER *Palla50;
|
||||
extern t3dCHARACTER *Freccia50;
|
||||
extern t3dCHARACTER *GopherMark[];
|
||||
extern t3dCHARACTER *Explode50;
|
||||
extern t3dMESH *t3dGolfSky;
|
||||
extern int32 Comb2D[], Comb2Q[], Comb19[], Comb1D[], Forno25, Frigo25, Comb31[], Comb33[], Comb42[], Comb44[], Comb45[];
|
||||
extern uint8 bMoglieGym, bMoglieSangue, bNoPlayerSwitch;
|
||||
|
||||
// MESSAGE SYSTEM
|
||||
extern message *TheMessage;
|
||||
|
||||
// GAME VARS
|
||||
extern int32 CurObj;
|
||||
extern int32 NextPortalObj;
|
||||
extern int32 NextPortalAnim;
|
||||
extern int32 FromFirstPersonAnim;
|
||||
extern int32 ToFirstPersonSent;
|
||||
extern int32 CurInvObj;
|
||||
extern int32 BigInvObj;
|
||||
extern int32 CurPlayer;
|
||||
extern int32 CurDialog, CurMenu, CurDlgItem;
|
||||
extern int32 CurSubMusic;
|
||||
extern int32 CurAlternate[];
|
||||
extern int32 CurGopher;
|
||||
|
||||
extern uint32 TheTime;
|
||||
extern uint32 NextRefresh, PaintTime, LoadTime;
|
||||
extern t3dF32 CurFps, AvgFps;
|
||||
extern t3dF32 FrameFactor;
|
||||
|
||||
// INV
|
||||
extern uint8 Inv[MAX_PLAYERS][MAX_ICONS_IN_INV];
|
||||
extern uint8 InvLen[], InvBase[];
|
||||
extern uint8 InvStatus;
|
||||
extern uint8 Diag2Base;
|
||||
|
||||
// USE WITH
|
||||
extern int32 UseWith[];
|
||||
|
||||
// SEMAFORI
|
||||
extern uint8 bSomeOneSpeak;
|
||||
extern uint8 bPlayerSpeak;
|
||||
extern uint8 bUseWith;
|
||||
extern uint8 bSkipTalk;
|
||||
extern uint8 bFirstPerson;
|
||||
extern uint8 bDialogActive;
|
||||
extern uint8 bDialogMenuActive;
|
||||
extern uint8 bMovingCamera;
|
||||
extern uint8 bCutCamera;
|
||||
extern uint8 bAllowCalcCamera;
|
||||
extern uint8 bAnimWaitText;
|
||||
extern uint8 bPlayerInAnim;
|
||||
extern uint8 bFastWalk;
|
||||
extern uint8 bNotSkippableWalk;
|
||||
extern uint8 bNoFirstPersonSwitch;
|
||||
extern uint8 bClock33;
|
||||
extern uint8 bShowInfo;
|
||||
extern uint8 bShowBoundingBox;
|
||||
extern uint8 bShowPanels;
|
||||
extern uint8 bForceWire;
|
||||
extern uint8 bPauseAllAnims;
|
||||
extern uint8 bT2DActive;
|
||||
extern uint8 bGolfActive;
|
||||
extern uint8 bGolfMode;
|
||||
extern uint8 bIngnoreDIKeyboard;
|
||||
extern uint8 bDisableDiary;
|
||||
extern uint8 bCacciatore;
|
||||
extern uint8 bDarkScreen;
|
||||
extern uint8 bSaveDisabled;
|
||||
extern uint8 bLockCamera;
|
||||
extern uint8 bMiscLoaded;
|
||||
extern uint8 bStartMenuActive;
|
||||
extern uint8 bShowOnlyLoadWindow;
|
||||
extern uint8 bSbCacciatorehowOnlyLoadWindow;
|
||||
extern uint8 bNotSkippableSent;
|
||||
extern uint8 bPorteEsternoBloccate;
|
||||
extern uint8 bSuperView;
|
||||
extern uint8 bSezioneLabirinto;
|
||||
extern uint8 bPlayerSuBasamento;
|
||||
extern uint8 bWideScreen;
|
||||
extern uint8 bTitoliCodaStatic;
|
||||
extern uint8 bTitoliCodaScrolling;
|
||||
extern uint8 bDontPlaySteps;
|
||||
extern uint8 bShowRoomDescriptions;
|
||||
extern uint8 bShowExtraLocalizationStrings;
|
||||
|
||||
// DIALOG VARS
|
||||
extern uint8 UsedDlgMenu[MAX_PLAYERS][T3D_MAX_CHARACTERS][MAX_DLG_MENUS];
|
||||
|
||||
struct Globals {
|
||||
InvVars _invVars;
|
||||
};
|
||||
|
||||
// INIT
|
||||
struct Init : public SerializableAsset {
|
||||
SerializableArray<SRoom, MAX_ROOMS> Room;
|
||||
SerializableArray<SObject, MAX_OBJS> Obj;
|
||||
SerializableArray<SInvObject, MAX_ICONS> InvObj;
|
||||
SerializableArray<SSound, MAX_SOUNDS> Sound;
|
||||
SerializableArray<SMusic, MAX_MUSICS> Music;
|
||||
SerializableArray<SAnim, MAX_ANIMS> Anim;
|
||||
SerializableArray<SDialog, MAX_DIALOGS> Dialog;
|
||||
SerializableArray<SDiary, MAX_DIARIES> Diary;
|
||||
SerializableArray<SDlgMenu, MAX_DLG_MENUS> DlgMenu;
|
||||
SerializableArray<SDlgItem, MAX_DLG_ITEMS> DlgItem;
|
||||
|
||||
// Sentences?
|
||||
SerializableArray<SPDALog, MAX_PDALOGS> PDALog;
|
||||
|
||||
SerializableDynamicArray<SCreditsName> _creditsNames;
|
||||
SerializableDynamicArray<SCreditsRole> _creditsRoles;
|
||||
|
||||
Globals _globals;
|
||||
|
||||
void loadFromStream(Common::SeekableReadStream &stream) {
|
||||
warning("Init");
|
||||
Room.loadFromStream(stream);
|
||||
Obj.loadFromStream(stream);
|
||||
InvObj.loadFromStream(stream);
|
||||
Sound.loadFromStream(stream);
|
||||
Music.loadFromStream(stream);
|
||||
Anim.loadFromStream(stream);
|
||||
Dialog.loadFromStream(stream);
|
||||
Diary.loadFromStream(stream);
|
||||
DlgMenu.loadFromStream(stream);
|
||||
DlgItem.loadFromStream(stream);
|
||||
|
||||
PDALog.loadFromStream(stream);
|
||||
|
||||
uint16 numNames = stream.readUint16LE();
|
||||
uint16 numRoles = stream.readUint16LE();
|
||||
_creditsNames = SerializableDynamicArray<SCreditsName>(numNames);
|
||||
_creditsRoles = SerializableDynamicArray<SCreditsRole>(numRoles);
|
||||
_creditsNames.loadFromStream(stream);
|
||||
_creditsRoles.loadFromStream(stream);
|
||||
|
||||
treatCredits();
|
||||
}
|
||||
private:
|
||||
void treatCredits() {
|
||||
for (uint32 i = 0; i < _creditsNames.size(); i++) {
|
||||
char *c = _creditsNames[i].name;
|
||||
for (int k = 0; k < 32; k++, c++) {
|
||||
(*c) ^= 0xA0;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < _creditsRoles.size(); i++) {
|
||||
char *c = _creditsRoles[i].role;
|
||||
for (int k = 0; k < 48; k++, c++) {
|
||||
(*c) ^= 0xC4;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_GLOBVAR_H
|
||||
1619
engines/watchmaker/init/nl_init.cpp
Normal file
1619
engines/watchmaker/init/nl_init.cpp
Normal file
File diff suppressed because it is too large
Load Diff
32
engines/watchmaker/init/nl_init.h
Normal file
32
engines/watchmaker/init/nl_init.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_NL_INIT_H
|
||||
#define WATCHMAKER_NL_INIT_H
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
int LoadExternalText(Init *init, char *et);
|
||||
int InitStructures(WGame &game);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_NL_INIT_H
|
||||
226
engines/watchmaker/init/nl_parse.cpp
Normal file
226
engines/watchmaker/init/nl_parse.cpp
Normal file
@@ -0,0 +1,226 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/init/nl_parse.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "watchmaker/ll/ll_system.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
#define JParse_EOF() (_stream->eos())
|
||||
|
||||
int NLParser::MatchWord(const char *token) {
|
||||
const char *str = token;
|
||||
while (!JParse_EOF() && (*str) != 0) {
|
||||
if (JParse_ReadByte() != *str)
|
||||
str = token;
|
||||
else
|
||||
str++;
|
||||
}
|
||||
return (*str);
|
||||
}
|
||||
|
||||
// PELS: supporto per il parsing dei .nl **********************************
|
||||
|
||||
int NLParser::ParseError(const char *ln, ...) {
|
||||
char err[J_MAXSTRLEN];
|
||||
va_list ap;
|
||||
if (ErrorFunc)
|
||||
ErrorFunc();
|
||||
|
||||
va_start(ap, ln);
|
||||
vsnprintf(err, J_MAXSTRLEN, ln, ap);
|
||||
va_end(ap);
|
||||
warning("%s", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NLParser::IfParseErrorDo(void (*func)()) {
|
||||
ErrorFunc = func;
|
||||
}
|
||||
|
||||
Common::SharedPtr<NLParser> NLParser::open(const Common::String &name) {
|
||||
auto stream = openFile(name);
|
||||
if (!stream) {
|
||||
return nullptr;
|
||||
}
|
||||
return Common::SharedPtr<NLParser>(new NLParser(stream));
|
||||
}
|
||||
|
||||
NLParser::NLParser(Common::SharedPtr<Common::SeekableReadStream> stream) : _stream(stream), nlLineCounter(0), jUsingComments(1) {
|
||||
|
||||
}
|
||||
|
||||
static int lastreadeol = 0;
|
||||
int NLParser::ReadArgument_(char *str, int teol) {
|
||||
int a, notstring = 1, t;
|
||||
unsigned long c = 0;
|
||||
if (teol & lastreadeol)
|
||||
return -1;
|
||||
while (!JParse_EOF()) {
|
||||
skipped_comms:
|
||||
a = JParse_ReadByte();
|
||||
if (notstring) {
|
||||
if (jUsingComments)
|
||||
if (a == '/') {
|
||||
t = JParse_ReadByte() & 0xff;
|
||||
switch (t) {
|
||||
case '/':
|
||||
if (MatchWord("\n"))
|
||||
return -1;
|
||||
if (teol) {
|
||||
lastreadeol = 1;
|
||||
return -1;
|
||||
}
|
||||
goto skipped_comms;
|
||||
case '*':
|
||||
if (MatchWord("*/"))
|
||||
return -1;
|
||||
goto skipped_comms;
|
||||
default:
|
||||
if (JParse_PrevByte())
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
switch (a) {
|
||||
case '\"':
|
||||
notstring = 0;
|
||||
break;
|
||||
case '\r':
|
||||
case '\f':
|
||||
case '\n':
|
||||
if (teol && c == 0) {
|
||||
lastreadeol = 1;
|
||||
return -1;
|
||||
}
|
||||
// FIXME: fallthrough intended?
|
||||
// fallthrough
|
||||
|
||||
case '\t':
|
||||
case ' ':
|
||||
case '(':
|
||||
if (c) {
|
||||
lastreadeol = 0;
|
||||
if (a == '\n')lastreadeol = 1;
|
||||
*str = 0;
|
||||
return (c + 1);
|
||||
}
|
||||
break;
|
||||
case ')':
|
||||
case ',':
|
||||
case ';':
|
||||
case '|':
|
||||
|
||||
lastreadeol = 0;
|
||||
*str = 0;
|
||||
return (c + 1);
|
||||
default:
|
||||
if (c++ >= jStringLimit)
|
||||
return -1;
|
||||
*str = a;
|
||||
str++;
|
||||
break;
|
||||
} //end switch
|
||||
} else
|
||||
switch (a) {
|
||||
case '\"':
|
||||
/*while(!JParse_EOF())
|
||||
switch(JParse_ReadByte()) {
|
||||
case '(':
|
||||
case ')':
|
||||
case ',':
|
||||
case ';': */
|
||||
|
||||
*str = 0;
|
||||
return (c + 1);
|
||||
// }
|
||||
// break;
|
||||
// fallthrough
|
||||
case '\\':
|
||||
t = JParse_ReadByte();
|
||||
switch (t) {
|
||||
case '\\':
|
||||
a = '\\';
|
||||
break;
|
||||
case 't':
|
||||
a = '\t';
|
||||
break;
|
||||
case 'n':
|
||||
a = '\n';
|
||||
break;
|
||||
case '\"':
|
||||
a = '\"';
|
||||
break;
|
||||
default:
|
||||
a = ' ';
|
||||
} // senza break....ok
|
||||
// fallthrough
|
||||
default:
|
||||
if (c++ >= jStringLimit)
|
||||
return -1;
|
||||
*str = a;
|
||||
str++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return EOF_PARSED;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int NLParser::ReadNumber(void) {
|
||||
char stri[J_MAXSTRLEN];
|
||||
int res;
|
||||
if (ReadArgument(stri) < 0)
|
||||
return 0;
|
||||
if (stri[1] == 'x' || stri[1] == 'X') {
|
||||
unsigned int ures;
|
||||
sscanf(stri, "%x", &ures);
|
||||
res = ures;
|
||||
} else {
|
||||
sscanf(stri, "%d", &res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int NLParser::SearchArgument(char *t, ...) {
|
||||
va_list args;
|
||||
char *curarg;
|
||||
int c = 0, res;
|
||||
va_start(args, t);
|
||||
if (ReadArgument(t) < 0)
|
||||
return -1;
|
||||
res = -2;
|
||||
curarg = va_arg(args, char *);
|
||||
while (curarg != NULL) {
|
||||
if (!scumm_stricmp(curarg, t))
|
||||
res = c;
|
||||
c++;
|
||||
curarg = va_arg(args, char *);
|
||||
}
|
||||
va_end(args);
|
||||
return res;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
76
engines/watchmaker/init/nl_parse.h
Normal file
76
engines/watchmaker/init/nl_parse.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_NL_PARSE_H
|
||||
#define WATCHMAKER_NL_PARSE_H
|
||||
|
||||
#define J_MAXSTRLEN 512L
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
class NLParser {
|
||||
unsigned int jStringLimit = J_MAXSTRLEN, jTillEOL = 0, jUsingComments = 0;
|
||||
unsigned long nlLineCounter;
|
||||
int ReadArgument_(char *str, int teol);
|
||||
Common::SharedPtr<Common::SeekableReadStream> _stream = nullptr;
|
||||
void (*ErrorFunc)() = nullptr;
|
||||
public:
|
||||
// TODO: Need a static version that allows for failure, as we have fallbacks in the code to use.
|
||||
static Common::SharedPtr<NLParser> open(const Common::String &name);
|
||||
NLParser(Common::SharedPtr<Common::SeekableReadStream> stream);
|
||||
int ParseError(const char *ln, ...);
|
||||
void IfParseErrorDo(void (*func)());
|
||||
int ReadArgumentEOL(char *str) {
|
||||
return ReadArgument_(str, 1);
|
||||
}
|
||||
int ReadArgument(char *str) {
|
||||
return ReadArgument_(str, 0);
|
||||
}
|
||||
int ReadNumber(); //max 80 cifre
|
||||
int SearchArgument(char *t, ...);
|
||||
int getCurLine() {
|
||||
return nlLineCounter;
|
||||
}
|
||||
|
||||
int JParse_ReadByte(void) {
|
||||
int a = _stream->readByte();
|
||||
if (a == '\n')
|
||||
nlLineCounter++;
|
||||
return a;
|
||||
}
|
||||
|
||||
int JParse_PrevByte(void) {
|
||||
|
||||
if (_stream->seek(-1, SEEK_SET))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int MatchWord(const char *token);
|
||||
|
||||
#define EOF_PARSED -2
|
||||
};
|
||||
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_NL_PARSE_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user