WATCHMAKER: Add all files after initial cleanup.

This commit is contained in:
Einar Johan Trøan Sømåen 2022-09-10 00:46:09 +02:00 committed by Eugene Sandulenko
parent 4781fca07a
commit ccf209a001
145 changed files with 46440 additions and 2 deletions

View File

@ -0,0 +1,744 @@
/* 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/t3d.h"
#include "watchmaker/types.h"
#include "watchmaker/3d/t3d_body.h"
#include "watchmaker/3d/t3d_mesh.h"
#include "watchmaker/t3d.h"
#include "watchmaker/types.h"
#include "watchmaker/3d/loader.h"
#include "watchmaker/3d/math/llmath.h"
#include "watchmaker/ll/ll_system.h"
#include "watchmaker/utils.h"
#include "watchmaker/windows_hacks.h"
#include "watchmaker/game.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, NumBones, HiBone, LastTime;
t3dF32 *Dist;
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 (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 (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 (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, j, k, h, older, len, ScaleAnim, CurPreloadedAnim;
t3dLOADANIM *p;
t3dLOADBONE *bone;
t3dBONEANIM *db;
t3dBONE *b;
t3dV3F t;
t3dF32 c;
char name[100];
// 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);
}
t3dFree(PreloadedAnim[j].Dist);
memset(&PreloadedAnim[j], 0, sizeof(t3dLOADANIM));
}
//t else
//t DebugFile( "Precarico animazione %s nello slot libero %d", s, CurPreloadedAnim );
p = &PreloadedAnim[CurPreloadedAnim];
p->name = s;
// Carica la nuova animazione
memset(name, 0, sizeof(name));
strcpy(&name[0], game.workDirs._a3dDir.c_str());
strcat(&name[0], &s[0]);
len = strlen(name);
name[len - 3] = 'a';
name[len - 2] = '3';
name[len - 1] = 'd';
{
auto stream = game.resolveFile(name);
if (!stream) {
warning("File %s not found\n", name);
return -1;
}
if ((i = stream->readByte()) != A3DFILEVERSION) {
warning("%s file incompatible: current version: %d.\tFile version: %d", name, A3DFILEVERSION, i);
return -1;
}
nb = stream->readSint16LE();
nf = stream->readSint16LE();
if (nf == 0) {
warning("%s has N0 frames!", name);
return -1;
}
if (nb >= MAX_BONES) {
warning("%s has too many bones (%d, MAX is %d)!", name, 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].x = stream->readFloatLE();
bone->Euler[k].y = stream->readFloatLE();
bone->Euler[k].z = stream->readFloatLE();
}
for (k = 0; k < nf; k++) {
bone->Trasl[k].x = stream->readFloatLE();
bone->Trasl[k].y = stream->readFloatLE();
bone->Trasl[k].z = stream->readFloatLE();
}
}
if (stream->readByte()) {
p->Dist = (t3dF32 *) t3dMalloc(nf * sizeof(t3dF32));
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 = (t3dF32 *)t3dMalloc(db->NumFrames * sizeof(t3dF32));
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')) {
for (i = 0; i < NumLoadedFiles; i++)
if ((LoadedFiles[i].b != nullptr) && LoadedFiles[i].b->name.equalsIgnoreCase(room))
t3dCurRoom = LoadedFiles[i].b;
}
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 = t3dLoadRoom(game, 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, t3dCHARACTER *b, uint16 num) {
warning("LoadCharacter(%s)\n", pname);
uint8 Mirror = 1;
uint16 n = 0, f, i;
t3dV3F tmp;
// gVertex *v;
b = new t3dCHARACTER[1] {};
b->Body = nullptr;
b->Body = t3dLoadRoom(game, pname, b->Body, &n, (T3D_NOLIGHTMAPS | T3D_NORECURSION | T3D_NOVOLUMETRICLIGHTS | T3D_NOCAMERAS | T3D_STATIC_SET0 | T3D_STATIC_SET1));
if (!b->Body) 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\n", pname);
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 n = 0; n < b->Body->NumMeshes(); n++) {
t3dMESH &mesh = b->Body->MeshTable[n];
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());
for (i = 0; i < b->Body->NumMaterials(); i++) {
rCopyMaterial(b->Body->MirrorMatTable[i], b->Body->MatTable[i]);
}
}
// 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 n = 0; n < b->Body->NumMeshes(); n++) {
b->Body->MeshTable[n].Flags |= T3D_MESH_CHARACTER;
b->Body->MeshTable[n].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) {
uint8 a;
if (!pos) return 0;
auto pLights = t3dCurRoom->getPositionalLight(pos);
for (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);
}
t3dFree(PreloadedAnim[j].Dist);
memset(&PreloadedAnim[j], 0, sizeof(t3dLOADANIM));
}
}
/* -----------------02/05/00 9.30--------------------
* CompareLightPosition
* --------------------------------------------------*/
uint8 CompareLightPosition(char *roomname, uint8 pos1, t3dV3F *pos2, t3dF32 acceptable_dist) {
t3dV3F p1;
uint8 a;
t3dBODY *t;
int32 i;
if ((pos1 <= 0) || (pos2 == nullptr)) return FALSE;
// cerco la stanza
t = nullptr;
if (roomname && (roomname[0] != '\0')) {
for (i = 0; i < NumLoadedFiles; i++)
if ((LoadedFiles[i].b != nullptr) && LoadedFiles[i].b->name.equalsIgnoreCase(roomname))
t = LoadedFiles[i].b;
} 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

View 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, t3dCHARACTER *b, uint16 num);
void ReleasePreloadedAnims();
uint8 CompareLightPosition(char *roomname, uint8 pos1, t3dV3F *pos2, t3dF32 acceptable_dist);
} // End of namespace Watchmaker
#endif // WATCHMAKER_ANIMATION_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
/* 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 {
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 t3dCalc2dTo3dPos(t3dV3F *pos, t3dF32 posx, t3dF32 posy);
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

View File

@ -0,0 +1,466 @@
/* 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/loader.h"
#include "watchmaker/types.h"
#include "watchmaker/t3d.h"
#include "watchmaker/3d/geometry.h"
#include "watchmaker/3d/t3d_body.h"
#include "watchmaker/3d/t3d_mesh.h"
#include "watchmaker/3d/math/llmath.h"
#include "watchmaker/ll/ll_system.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.findFirstOf("\\");
return path + name.substr(backSlashPos + 1, name.size() - (backSlashPos + 1));
}
/* -----------------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\n");
#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(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
char Name[T3D_NAMELEN], Appo[T3D_NAMELEN];
#ifndef WMGEN
int len;
#endif
//f Light[light].Type&=~T3D_LIGHT_LIGHTON; // La spegne
FlareSize = stream.readFloatLE() * SCALEFACTOR; // Legge il size della flare
for (int i = 0; i < T3D_NAMELEN; i++) { // Legge nome dellaq texture
Name[i] = stream.readByte();
}
#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);
strcat(Appo, Name);
#endif
#ifndef WMGEN
if (!(rAddMaterial(Material[0], Appo, 15, 0))) { // Aggiunge il materiale
warning("File %s not found", Appo);
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
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 (int 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

View 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

View File

@ -0,0 +1,566 @@
/* 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 "watchmaker/3d/math/llmath.h"
#include "watchmaker/t3d.h"
#include "watchmaker/3d/t3d_body.h"
#include "watchmaker/3d/t3d_mesh.h"
#include "watchmaker/types.h"
#include "common/stream.h"
#include "watchmaker/utils.h"
#include "watchmaker/ll/ll_system.h"
#include "watchmaker/work_dirs.h"
#include "watchmaker/3d/geometry.h"
#include "watchmaker/3d/light.h"
#include "watchmaker/windows_hacks.h"
#include "watchmaker/game.h"
#include "watchmaker/renderer.h"
#include "watchmaker/work_dirs.h"
namespace Watchmaker {
#define T3DFILEVERSION 11
// TODO: Globals
#define MAX_LOADED_FILES 100
RecStruct LoadedFiles[MAX_LOADED_FILES];
uint16 NumLoadedFiles = 0;
t3dV3F CharCorrection;
t3dF32 CurFloorY;
int32 t3dCurTime = 900, t3dCurOliSet = 0;
// LoadRoom vars
#define MAX_T3D_LOADLIST_ITEMS 50
struct _t3dLOADLIST {
Common::String pname = {};
uint32 LoaderFlags = 0;
t3dMESH *m = nullptr;
} t3dLoadList[MAX_T3D_LOADLIST_ITEMS] = {};
/* -----------------10/06/99 16.03-------------------
* AddToLoadList
* --------------------------------------------------*/
void AddToLoadList(t3dMESH *m, const Common::String &pname, uint32 LoaderFlags) {
int32 a;
if (!pname.empty()) {
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());
}
}
/* -----------------10/06/99 16.04-------------------
* GetFromLoadList
* --------------------------------------------------*/
struct _t3dLOADLIST *GetFromLoadList(void) {
int32 a;
for (a = 0; a < MAX_T3D_LOADLIST_ITEMS; a++) {
if (t3dLoadList[a].pname[0])
return &t3dLoadList[a];
}
return nullptr;
}
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.reserve(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\n", flags & T3D_GENERATESHADOWMAPS);
warning("%d: T3D_NOLIGHTMAPS\n", flags & T3D_NOLIGHTMAPS);
warning("%d: T3D_NORECURSION\n", flags & T3D_NORECURSION);
warning("%d: T3D_HALFTEXTURESIZE\n", flags & T3D_HALFTEXTURESIZE);
warning("%d: T3D_FULLSCREEN\n", flags & T3D_FULLSCREEN);
warning("%d: T3D_FASTRENDERING\n", flags & T3D_FASTRENDERING);
warning("%d: T3D_OUTDOORLIGHTS\n", flags & T3D_OUTDOORLIGHTS);
warning("%d: T3D_NOVOLUMETRICLIGHTS\n", flags & T3D_NOVOLUMETRICLIGHTS);
warning("%d: T3D_NOBOUNDS\n", flags & T3D_NOBOUNDS);
warning("%d: T3D_NOCAMERAS\n", flags & T3D_NOCAMERAS);
warning("%d: T3D_NONEXCLUSIVEMOUSE\n", flags & T3D_NONEXCLUSIVEMOUSE);
warning("%d: T3D_RECURSIONLEVEL1\n", flags & T3D_RECURSIONLEVEL1);
warning("%d: T3D_SKY\n", flags & T3D_SKY);
warning("%d: T3D_PRELOAD_RXT\n", flags & T3D_PRELOAD_RXT);
warning("%d: T3D_STATIC_SET0\n", flags & T3D_STATIC_SET0);
warning("%d: T3D_STATIC_SET1\n", flags & T3D_STATIC_SET1);
warning("%d: T3D_NOSHADOWS\n", flags & T3D_NOSHADOWS);
warning("%d: T3D_NOICONS\n", flags & T3D_NOICONS);
warning("%d: T3D_NOSOUND\n", flags & T3D_NOSOUND);
warning("%d: T3D_PRELOADBASE\n", flags & T3D_PRELOADBASE);
warning("%d: T3D_NOMUSIC\n", flags & T3D_NOMUSIC);
warning("%d: T3D_DEBUGMODE\n", flags & T3D_DEBUGMODE);
warning("%d: T3D_FASTFILE\n", flags & T3D_FASTFILE);
warning("%d: T3D_HIPOLYPLAYERS\n", flags & T3D_HIPOLYPLAYERS);
warning("%d: T3D_HIPOLYCHARACTERS\n", flags & T3D_HIPOLYCHARACTERS);
}
/* -----------------10/06/99 16.04-------------------
* CheckIfAlreadyLoaded
* --------------------------------------------------*/
t3dBODY *CheckIfAlreadyLoaded(const Common::String &Name) {
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;
}
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(Name);
}
/* -----------------10/06/99 16.04-------------------
* t3dLoadSingleRoom
* --------------------------------------------------*/
t3dBODY *t3dLoadSingleRoom(WGame &game, const Common::String &_pname, t3dBODY *b, uint16 *NumBody, uint32 LoaderFlags) {
//warning("t3dLoadSingleRoom(workDirs, %s, b, %d, %d)\n", _pname, *NumBody, LoaderFlags);
//decodeLoaderFlags(LoaderFlags);
Common::String pname(_pname);
uint16 light;
t3dPLIGHT *PLight;
t3dF32 minx, miny, minz, maxx, maxy, maxz;
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)\n", name.c_str());
auto stream = openFile(name);
if (!(stream)) { // Apre file
warning("t3dLoadSingleRoom: Failed to open(%s)\n", name.c_str());
return nullptr;
}
if (*NumBody == 0) { // Se e' il primo body, alloca
b = new t3dBODY;
(*NumBody)++;
} else
b = (t3dBODY *)t3dRealloc((uint32 *)b, sizeof(t3dBODY) * (++(*NumBody))); // Altrimenti, ridimensiona
//warning("Loading %s ...\n", 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);
return nullptr;
}
{
uint16 j = 1;
while (LoadedFiles[j].b != nullptr) j++;
if (j > MAX_LOADED_FILES) {
warning("Too many t3d files loaded!");
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;
}
/* -----------------10/06/99 16.04-------------------
* t3dLoadRoom
* --------------------------------------------------*/
t3dBODY *t3dLoadRoom(WGame &game, const Common::String &pname, t3dBODY *b, uint16 *NumBody, uint32 LoaderFlags) {
warning("t3dLoadRoom(%s, b, %d, %d)\n", pname.c_str(), *NumBody, LoaderFlags);
struct _t3dLOADLIST *l;
t3dBODY *r, *rez;
t3dBODY *body;
uint16 num, i;
// azzera tutto quello che c'era prima nella load list
for (int i = 0; i < MAX_T3D_LOADLIST_ITEMS; i++) {
t3dLoadList[i] = _t3dLOADLIST();
}
// Aggiunge la stanza base alla lista di caricamenti
AddToLoadList(nullptr, pname, LoaderFlags);
while ((l = GetFromLoadList())) {
num = 0;
if (l->m) {
if ((rez = CheckIfAlreadyLoaded(l->pname)))
body = 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
body = l->m->PortalList = t3dLoadSingleRoom(game, l->pname, l->m->PortalList, &num, l->LoaderFlags);
}
} else
body = r = t3dLoadSingleRoom(game, l->pname, b, NumBody, l->LoaderFlags);
memset(l, 0, sizeof(struct _t3dLOADLIST));
}
if (!(LoaderFlags & T3D_NORECURSION)) {
for (i = 0; i < NumLoadedFiles; i++)
if (LoadedFiles[i].b)
t3dCalcRejectedMeshFromPortal(LoadedFiles[i].b);
}
warning("Room loaded\n");
return r;
}
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 = t3dLoadRoom(game, "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]->Flags |= T3D_MATERIAL_SKY | 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 (int 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->Flags & T3D_MATERIAL_MOVIE)) // Se non esiste o non ha texture
continue; // esce
for (int 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");
#if 0
// This is currently broken.
Mat = rMergeMaterial(Mat, CurMat); // Unisce i due materiali
t3dMESH *m = b->MeshTable;
for (int k = 0; k < b->NumMeshes; k++, m++) { // Aggiorna in tutte le mesh id materiale
t3dFACE *f = m->FList;
for (int q = 0; q < m->NumFaces; q++, f++) {
if (f->mat == CurMat)
f->mat = Mat;
}
}
#endif
}
}
}
}
/* -----------------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.mat;
if (Face.lightmap) {
Mat = nullptr;
for (auto material : Face.mat->AddictionalMaterial) {
if (Mat->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.mat->NumAddictionalMaterial, Face.lightmap->Texture->ID);
for (auto material : Face.mat->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 = (gVertex **)t3dRealloc(Mat->VertsList, sizeof(gVertex *));
Mat->VertsList[Mat->NumAllocatedVerts++] = &Mesh.VBptr[Face.VertexIndex[h]];
}
Face.MatVertexIndex[h] = (int16)k;
}
}
#ifndef WMGEN
Mesh.VBptr = nullptr;
#endif
}
warning("Partially stubbed t3dFinalizeMaterialList");
for (int i = 0; i < b->NumMaterials(); i++) {
auto &Mat = b->MatTable[i];
Mat->VBO = b->addVertexBuffer(); // t3dAddVertexBuffer(b, Mat->NumAllocatedVerts);
for (int j = 0; j < (uint32)Mat->NumAddictionalMaterial; j++)
Mat->AddictionalMaterial[j]->VBO = t3dAddVertexBuffer(b, Mat->AddictionalMaterial[j]->NumAllocatedVerts);
}
}
} // End of namespace Watchmaker

View 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_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;
};
extern RecStruct LoadedFiles[];
extern uint16 NumLoadedFiles;
t3dBODY *t3dLoadRoom(WGame &game, const Common::String &pname, t3dBODY *b, unsigned short *NumBody, unsigned int LoaderFlags);
t3dBODY *t3dLoadSingleRoom(WGame &game, const char *_pname, t3dBODY *b, uint16 *NumBody, uint32 LoaderFlags);
void t3dOptimizeMaterialList(t3dBODY *b);
void t3dFinalizeMaterialList(t3dBODY *b);
void t3dPrecalcLight(t3dBODY *b, unsigned char *sun);
void t3dLoadSky(WGame &game, t3dBODY *b);
t3dBODY *CheckIfAlreadyLoaded(const Common::String &Name);
void AddToLoadList(t3dMESH *m, const Common::String &pname, uint32 LoaderFlags);
Common::String constructPath(const Common::String &prefix, const Common::String &filename, const char *suffix = nullptr);
} // End of namespace Watchmaker
#endif // WATCHMAKER_LOADER_H

View File

@ -0,0 +1,322 @@
/* 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/util.h"
#include "watchmaker/3d/material.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\n");
#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;
}
MaterialPtr rAddMaterial(MaterialTable &MList, const Common::String &TextName, int NumFaces, unsigned int LoaderFlags) {
MaterialPtr &Material=MList[0];
rAddMaterial(*Material, TextName, NumFaces, LoaderFlags);
}
void gMaterial::addProperty(int flag) {
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->NumAllocatedFaces=0;
cm->FacesList.clear();
this->NumAddictionalMaterial++;
}
cm->FacesList.resize(cm->FacesList.size() + num*3);
cm->NumAllocatedFaces+=num*3;
return true;
}
bool gMaterial::addNumFaces(unsigned int num) {
if (num == 0)
return false;
FacesList.resize(FacesList.size() + num * 3);
NumAllocatedFaces += num * 3;
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);
}
Mat1->addNumFaces(Mat2->NumAllocatedFaces);
//reset mat2
rRemoveMaterial(Mat2);
*Mat2 = gMaterial();
return Mat1;
}
void rRemoveMaterials(Common::Array<Common::SharedPtr<gMaterial>> &m) {
for (auto &material : m) {
m.clear();
}
}
Common::SharedPtr<gMaterial> rCopyMaterial(Common::SharedPtr<gMaterial> Mat1, Common::SharedPtr<gMaterial> Mat2) {
int i;
if (!Mat1 || !Mat2)
return nullptr;
Mat1->FacesList.clear();
Mat1->AddictionalMaterial.clear();
Mat1->FacesList.clear();
delete[] Mat1->VertsList;
Mat1->VertsList = nullptr;
//t3dFree(Mat1->FlagsList);
*Mat1 = gMaterial();
if (Mat2->NumAllocatedFaces) {
Mat1->addNumFaces(Mat2->NumAllocatedFaces);
for (int i = 0; i < Mat2->NumAllocatedFaces; i++) {
Mat1->FacesList.push_back(Mat2->FacesList[i]);
}
}
if (Mat2->NumAllocatedVerts) {
Mat1->VertsList = new gVertex*[Mat2->NumAllocatedVerts]{};
memcpy(Mat1->VertsList, Mat2->VertsList, sizeof(gVertex *)*Mat2->NumAllocatedVerts);
}
if (Mat2->NumAllocatedMesh) {
Mat1->FlagsList = Mat2->FlagsList;
}
Mat1->Texture = Mat2->Texture;
Mat1->Movie = Mat2->Movie;
Mat1->Flags = Mat2->Flags;
Mat1->NumFaces = Mat2->NumFaces;
Mat1->NumAllocatedFaces = Mat2->NumAllocatedFaces;
Mat1->NumAllocatedVerts = Mat2->NumAllocatedVerts;
Mat1->VBO = Mat2->VBO;
Mat1->NumAllocatedMesh = Mat2->NumAllocatedMesh;
Mat1->r = Mat2->r;
Mat1->g = Mat2->g;
Mat1->b = Mat2->b;
Mat1->NumAddictionalMaterial = Mat2->NumAddictionalMaterial;
if (Mat2->NumAddictionalMaterial)
Mat1->AddictionalMaterial.resize(Mat2->NumAddictionalMaterial); // TODO: Does this mean that we don't copy any extras?
for (i = 0; i < Mat2->NumAddictionalMaterial; i++)
rCopyMaterial(Mat1->AddictionalMaterial[i], Mat2->AddictionalMaterial[i]);
return Mat1;
}
void gMaterial::clear() {
if (Movie)
{
Movie = nullptr;
}
FacesList.clear();
delete[] VertsList;
VertsList=nullptr;
FlagsList.clear();
// rDeleteVertexBuffer(m->VB);
VBO=0;
for ( int j=0; j<NumAddictionalMaterial; j++)
{
Common::SharedPtr<gMaterial> cm = AddictionalMaterial[j];
cm->FacesList.clear();
delete[] cm->VertsList;
cm->VertsList=nullptr;
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) {
//warning("Stubbed: rAddToMaterialList\n");
//D3DVERTEXBUFFERDESC VBDesc;
gMaterial *cm;
gBatchBlock *bb;
int j;
#if 0
if (!mat)
return;
if ((mat.Flags & T3D_MATERIAL_MOVIE))
gUpdateMovie(mat);
#endif
if ((mat.NumFaces >= 3) && (mat.VBO)) {
bb = rNewBatchBlock(mat.Texture->ID, mat.Flags, 0, 0);
bb->ViewMatrixNum = ViewMatrixNum;
bb->NumFaces = (unsigned short int) mat.NumFaces;
bb->FacesList = mat.FacesList;
bb->VBO = mat.VBO;
bb->NumVerts = (unsigned short int) mat.NumAllocatedVerts;
mat.NumFaces = 0;
// if ( bb->VB == g_lpD3DUserVertexBuffer )
// DebugLogFile("User VB %s with %d verts",mat->Texture->Name,bb->NumVerts);
#if 0
if ((bb->NumVerts == 0) && (bb->VBO)) {
if (bb->VB->GetVertexBufferDesc(&VBDesc) != D3D_OK)
DebugLogFile("Can't get VB information for %s", mat->Texture->Name);
else
bb->NumVerts = (unsigned short int) VBDesc.dwNumVertices;
// DebugLogFile("Saving VB %s with %d verts",mat->Texture->Name,bb->NumVerts);
}
#endif
}
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->NumFaces = (unsigned short int) cm->NumFaces;
bb->FacesList = cm->FacesList;
bb->VBO = cm->VBO;
bb->NumVerts = (unsigned short int) cm->NumAllocatedVerts;
cm->NumFaces = 0;
if (bb->NumVerts == 0) {
#if 0
if (bb->VBO->GetVertexBufferDesc(&VBDesc) != D3D_OK)
DebugLogFile("Can't get VB information for %s", mat->Texture->Name);
else
bb->NumVerts = (unsigned short int) VBDesc.dwNumVertices;
// DebugLogFile("Saving VB %s with %d verts",mat->Texture->Name,bb->NumVerts);
#endif
}
}
}
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;
list.reserve(num);
for (int i = 0; i < num; i++) {
list.push_back(Common::SharedPtr<gMaterial>(new gMaterial()));
}
return list;
}
} // End of namespace Watchmaker

View File

@ -0,0 +1,77 @@
/* 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 = 0; // current number of faces to be processed
int NumAllocatedFaces = 0; // maximum number of faces
Common::Array<uint16> FacesList; // list of verts indices
int NumAllocatedVerts = 0; // number of allocated vertex in mat VB
gVertex **VertsList = nullptr; // pointers to pointers to verts
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 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);
MaterialPtr rCopyMaterial(MaterialPtr Mat1, MaterialPtr Mat2);
MaterialPtr rMergeMaterial(MaterialPtr Mat1, MaterialPtr Mat2);
void rAddToMaterialList(gMaterial &mat, signed short int ViewMatrixNum);
} // End of namespace Watchmaker
#endif // WATCHMAKER_MATERIAL_H

View 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

View 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("\n");
}
}
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

View 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\n");
/*
__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 <EFBFBD> -sin <EFBFBD> 0 | y' = (cos <EFBFBD>) * y - (sin <EFBFBD>) * z
| 0 sin <EFBFBD> cos <EFBFBD> 0 | z' = (sin <EFBFBD>) * y + (cos <EFBFBD>) * 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 <EFBFBD> 0 cos <EFBFBD> 0 | z' = -(sin <EFBFBD>) * x + (cos <EFBFBD>) * 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 <EFBFBD> cos <EFBFBD> 0 0 | y' = (sin <EFBFBD>) * x + (cos <EFBFBD>) * 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

View File

@ -0,0 +1,68 @@
/* 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 t3dMatCopy(t3dM3X3F *d, t3dM3X3F *s);
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 t3dVectInit(t3dV3F *d, t3dF32 a1, t3dF32 a2, t3dF32 a3);
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

View 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 Managment
// 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

View 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

View 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/movie.h"
namespace Watchmaker {
} // End of namespace Watchmaker

View 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_MOVIE_H
#define WATCHMAKER_MOVIE_H
#include "watchmaker/types.h"
#include "watchmaker/utils.h"
namespace Watchmaker {
struct gMovie {
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;
// TODO
~gMovie() {
//warning("TODO: Clean up gMovie properly\n");
}
};
} // End of namespace Watchmaker
#endif // WATCHMAKER_MOVIE_H

View 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\n");
return false;
}
} // End of namespace Watchmaker

View 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

View File

@ -0,0 +1,348 @@
/* 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/render/opengl_2d.h"
#include "watchmaker/utils.h"
#include "watchmaker/render.h"
#include "watchmaker/tga_util.h"
#include "watchmaker/rect.h"
#include "watchmaker/work_dirs.h"
#include "watchmaker/game.h"
#include "watchmaker/renderer.h"
#include "watchmaker/sdl_wrapper.h"
#ifdef USE_OPENGL_GAME
#include "graphics/opengl/system_headers.h"
#endif
namespace Watchmaker {
// Bitmap list
unsigned int gNumBitmapList = 0;
uint16 *gFonts[10];
unsigned int gNumFonts = 0;
gTexture gBitmapList[MAX_BITMAP_LIST];
Rect gBlitterExtends;
int gStencilBitDepth;
gLogo Logos[10];
gMaterial LogosMaterials[10];
int NumLogosMaterials = 0, GlobalLogosDelay = 60 * 3;
unsigned int CurLoaderFlags;
//*********************************************************************************************
unsigned int gGetBitmapListPosition() {
unsigned int pos = 1;
while (gBitmapList[pos].surface != nullptr) {
pos++;
}
if (pos > MAX_BITMAP_LIST)
return 0;
if (pos > gNumBitmapList)
gNumBitmapList = pos;
return pos;
}
unsigned int rGetBitmapDimX(unsigned int id) {
return gBitmapList[id].DimX;
}
//************************************************************************************************************************
unsigned int rGetBitmapDimY(unsigned int id) {
return gBitmapList[id].DimY;
}
unsigned int rGetBitmapRealDimX(unsigned int id) {
return gBitmapList[id].RealDimX;
}
unsigned int rGetBitmapRealDimY(unsigned int id) {
return gBitmapList[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(void) {
gBlitterExtends.left = 99999999;
gBlitterExtends.top = 99999999;
gBlitterExtends.right = -99999999;
gBlitterExtends.bottom = -99999999;
}
#ifdef USE_OPENGL_GAME
//************************************************************************************************************************
void rBlitter(WGame &game, int dst, int src, int dposx, int dposy,
int sposx, int sposy, int sdimx, int sdimy) {
// TODO: This currently gets called a bit too much.
//warning("TODO: Stubbed rBlitter(%s, %d, %d, %d, %d, %d, %d, %d, %d)\n", gBitmapList[src].Name, dst, src, dposx, dposy, sposx, sposy, sdimx, sdimy);
auto &bitmap = gBitmapList[src];
checkGlError("rBlitter Start");
glEnable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);
int dwWidth, dwHeight;
dwWidth = game._renderer->_viewport.width();
dwHeight = game._renderer->_viewport.height();;
if ((sdimx <= 0)) {
sdimx = gBitmapList[src].DimX;
}
if ((sdimy <= 0)) {
sdimy = gBitmapList[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 0
if (!gClipToBlitterViewport(&sposx, &sposy, &sdimx, &sdimy, &dposx, &dposy)) {
// DebugLogFile("gClipToBlitterViewport report an error");
return;
}
d = gScreenBuffer.lpDDSurface;
#endif
rUpdateExtends(dposx, dposy, dposx + sdimx, dposy + sdimy);
#if 0
/* //Update extends
if (dposx<gBlitterExtends.left)
gBlitterExtends.left=dposx;
if (dposy<gBlitterExtends.top)
gBlitterExtends.top=dposy;
if ((dposx+sdimx)>gBlitterExtends.right)
gBlitterExtends.right=dposx+sdimx;
if ((dposy+sdimy)>gBlitterExtends.bottom)
gBlitterExtends.bottom=dposy+sdimy;*/
} else
d = gBitmapList[dst].lpDDSurface;
if (src == 0) {
DebugLogFile("rBlitter error: src is an invalid surface");
return;
} else
s = gBitmapList[src].lpDDSurface;
#endif
}
if ((sdimx == 0) && (sdimy == 0)) {
sdimx = gBitmapList[src].DimX;
sdimy = gBitmapList[src].DimY;
}
{
Rect srcRect;
// Source rect
srcRect.top=sposy;
srcRect.left=sposx;
srcRect.right= sposx + sdimx;
srcRect.bottom= sposy + sdimy;
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;
}
glClearColor(0,0,1,0);
glEnable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
error("TODO: Replace SDL textures");
#if 0
SDL_GL_BindTexture(bitmap.texture, nullptr, nullptr);
#endif
//glBindTexture(GL_TEXTURE_2D, bitmap.texId);
glLoadIdentity();
glTranslatef(0, 0, -1.0);
//glTranslatef((2.0 / dposx) - 1.0, (2.0 / dposy) - 1.0, 0.0f);
//glClear(GL_COLOR_BUFFER_BIT);
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;
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);
glColor3f(1.0, 1.0, 1.0);
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("rBlitter End");
// DebugLogFile("gBlitter(%d %d)",dst,src);
//gBlitter(d, s, sposx, sposy, sdimx, sdimy, dposx, dposy, 0);
//#endif
}
// TODO: Deduplicate against the opengl_3d.cpp version
int createTextureFromSurface2(Surface &surface, int texFormat) {
unsigned int texId = 0;
glGenTextures(1, &texId);
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);
bool compressed = false;
switch (texFormat) {
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
compressed = true;
break;
case GL_RGBA:
case GL_RGB:
compressed = false;
break;
default:
warning("Texture format not handled: %d\n", texFormat);
}
if (compressed) {
glCompressedTexImage2D(GL_TEXTURE_2D, 0, texFormat, surface.width, surface.height, 0, surface.dataSize, surface.data);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, texFormat, surface.width, surface.height / 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface.data);
}
return texId;
}
int rLoadBitmapImage(WGame &game, const char *TextName, unsigned char flags) {
WorkDirs &workDirs = game.workDirs;
if (flags & rTEXTURESURFACE) {
warning("TODO: support texture surface loading\n");
// return ((int) gLoadTexture(TextName, flags));
}
assert(TextName);
auto stream = workDirs.resolveFile(TextName);
if (!stream) {
warning("gLoadBitmapImage: Cannot find %s.\n", TextName);
return -1;
}
PixelFormat RGBA8888(4, 8, 8, 8, 8, 24, 16, 8, 0);
unsigned int pos = gGetBitmapListPosition();
if (pos == 0) {
warning("rLoadBitmap: Can't create more bitmaps\n");
return -1;
}
gTexture *Texture = &gBitmapList[pos];
*Texture = gTexture();
Texture->Flags = CurLoaderFlags;
Texture->surface = ReadTgaImage(TextName, stream.get(), RGBA8888, Texture->Flags);
error("TODO: textures in OSystem");
#if 0
Texture->texture = SDL_CreateTextureFromSurface(game.sdl->renderer, Texture->surface->sdl_surface);
#endif
//Texture->texId = createTextureFromSurface2(*Texture->surface, GL_RGBA);
Texture->name = TextName;
if (flags & rSURFACESTRETCH) { // Also rSURFACEFLIP
static bool warned = false;
if (!warned) {
warning("TODO: rSURFACESTRETCH\n");
warned = true;
}
// HACK: Just set a dimension at all:
Texture->DimX = Texture->surface->width;
Texture->DimY = Texture->surface->height;
} else {
Texture->DimX = Texture->surface->width;
Texture->DimY = Texture->surface->height;
}
Texture->RealDimX = Texture->surface->width;
Texture->RealDimY = Texture->surface->height;
// TODO: Colour-keying
return pos;
}
void rSetLoaderFlags(unsigned int NewLoaderFlags) {
CurLoaderFlags = NewLoaderFlags;
}
#endif // USE_OPENGL_GAME
} // End of namespace Watchmaker

View File

@ -0,0 +1,48 @@
/* 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"
#define MAX_BITMAP_LIST 1024
namespace Watchmaker {
extern int gStencilBitDepth;
struct gLogo {
gMaterial *Material;
Vertex Verts[4];
int Delay;
};
extern gLogo Logos[];
extern gMaterial LogosMaterials[];
extern int NumLogosMaterials;
extern unsigned int CurLoaderFlags;
} // End of namespace Watchmaker
#endif // WATCHMAKER_OPENGL2D_H

View File

@ -0,0 +1,967 @@
/* 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"
#define MAXTEXTURES 2000
namespace Watchmaker {
// temp pixel format conversion info
struct {
float RedScale;
float GreenScale;
float BlueScale;
float AlphaScale;
unsigned int RedShift;
unsigned int GreenShift;
unsigned int BlueShift;
unsigned int AlphaShift;
unsigned int RedMask;
unsigned int GreenMask;
unsigned int BlueMask;
unsigned int AlphaMask;
} gTexturePixelConversion;
#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\n");
#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\n");
#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: \n");
//tmp.print();
for (i = 0, um = &rUserViewMatrix[0]; i < rNumUserViewMatrices; i++, um++) {
//warning("Comparing %d\n", 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 *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;
}
Surface *gCreateSurface(int width, int height, void *ptr) {
auto surface = new Surface();
surface->data = ptr;
surface->width = width;
surface->height = height;
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\n", 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(unsigned int dimx, unsigned int dimy) {
bool AlreadyLoaded = FALSE, bAlpha = FALSE;
gTexture *Texture;
int pos;
//DDSURFACEDESC2 DDSurfDesc;
pos = gGetTextureListPosition();
if (pos == 0) {
DebugLogFile("gUserTexture: Can't create more textures");
return nullptr;
}
Texture = &gTextureList[pos];
memset(Texture, 0, sizeof(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;
Texture->surface = gCreateSurface(dimx, dimy, nullptr);
#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
}
return Texture;
}
int createTextureFromSurface(Surface &surface, int texFormat) {
unsigned int texId = 0;
glGenTextures(1, &texId);
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);
bool compressed = false;
error("TODO: Compressed textures");
#if 0
switch (texFormat) {
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
compressed = true;
break;
default:
warning("Texture format not handled: %d\n", texFormat);
}
#endif
if (compressed) {
glCompressedTexImage2D(GL_TEXTURE_2D, 0, texFormat, surface.width, surface.height, 0, surface.dataSize, surface.data);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, texFormat, surface.width, surface.height, 0, surface.dataSize, GL_UNSIGNED_BYTE, surface.data);
}
return texId;
}
struct DDSHeader {
int height = 0;
int width = 0;
};
DDSHeader parseDDSHeader(Common::SeekableReadStream &stream) {
DDSHeader header;
//warning("TODO: Implement DDS Header parsing\n");
uint32 retv = ' SDD'; //MAKEFOURCC( 'D','D','S',' ' );
uint32 magic = stream.readUint32LE();
if (magic != retv) {
error("parseDDSHeader: Wrong Magic, expected %08X, got %08X\n", retv, magic);
}
uint32 size = stream.readUint32LE();
uint32 flags = stream.readUint32LE();
header.height = stream.readUint32LE();
header.width = stream.readUint32LE();
stream.seek(SEEK_SET, size + 4);
return header;
}
Surface *parseDDS(Common::SeekableReadStream &stream) {
DDSHeader header = parseDDSHeader(stream);
auto dataSize = stream.size() - stream.pos();
auto data = new unsigned char[dataSize]();
stream.read(data, dataSize);
auto result = gCreateSurface(header.width, header.height, data);
result->dataSize = dataSize;
return result;
}
//*********************************************************************************************
Common::SharedPtr<gMovie> gLoadMovie(WorkDirs &workDirs, const char *TextName) {
bool AlreadyLoaded = FALSE, bAlpha = FALSE;
uint32 i;
char finalName[MAX_PATH];
auto Movie = Common::SharedPtr<gMovie>(new gMovie());
if (!Movie) {
DebugLogFile("gLoadMovie FAILED: Can't alloc Movie struct");
return nullptr;
}
*Movie = gMovie();
//convert .avi name in .wmm
strcpy(finalName, TextName);
{
int i = strlen(finalName) - 1;
while (i > 0) {
if (finalName[i] == '.') {
finalName[i] = '\0';
break;
}
i--;
}
strcat(finalName, ".wmm");
}
//load movie file
Movie->stream = workDirs.resolveFile(finalName);
// Movie->fp=fopen("c:\\wm\\TMaps2DDS\\fiammata.wmm","rb");
// Movie->fp=fopen("c:\\wm\\TMaps2DDS\\medicalshow.wmm","rb");
if (!Movie->stream) {
DebugLogFile("gLoadMovie FAILED: Can't find movie file\n");
return nullptr;
}
Movie->numFrames = Movie->stream->readUint16LE();
Movie->width = Movie->stream->readUint16LE();
Movie->height = Movie->stream->readUint16LE();
Movie->keyFrame = Movie->stream->readByte();
Movie->frameRate = Movie->stream->readByte();
//uint32 readMagic = Movie->stream->readUint32LE();
DDSHeader header = parseDDSHeader(*Movie->stream);
Movie->numBlocks = Movie->width * Movie->height / 16;
Movie->curFrame = 0xFFFF;
Movie->frameOffsets = (uint32 *)t3dMalloc(sizeof(uint32) * Movie->numFrames);
if (!Movie->frameOffsets) {
DebugLogFile("gLoadMovie FAILED: Can't alloc Movie->frameOffsets struct");
return nullptr;
}
uint16 maxlen = (Movie->numBlocks / 8) + 8 * Movie->numBlocks; //bit array + max different blocks
Movie->buffer = (uint8 *)t3dMalloc(maxlen);
if (!Movie->buffer) {
DebugLogFile("gLoadMovie FAILED: Can't alloc Movie->buffer struct");
return nullptr;
}
//read frame offsets
for (i = 0; i < Movie->numFrames; i++) {
Movie->frameOffsets[i] = Movie->stream->readUint32LE();
}
//check if the files are ok
{
//create surface
//warning("TODO: Create compressed surface\n");
#if 0
DDSURFACEDESC2 ddsd2;
//create compressed surface
memcpy(&ddsd2, &Movie->surfDesc, sizeof(DDSURFACEDESC2));
ddsd2.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
if (!(Movie->surf = gCreateSurface(&ddsd2, Movie->surf))) {
DebugLogFile("gLoadMovie: gCreateSurface FAILED: Can't create surface DDS");
return NULL;
}
#endif
}
// Movie->frameRate=240;
return Movie;
}
//*********************************************************************************************
gTexture *gLoadTexture(WorkDirs &workDirs, const char *TextName, unsigned int LoaderFlags) {
bool bAlpha = FALSE, 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;
Surface *lpSSource = nullptr;
if (!TextName) return nullptr;
lpSSource = nullptr;
//warning("gLoadTexture(%s)\n", 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();
if (bUseAlternate) {
auto stream = workDirs.resolveFile(AlternateName);
if (!stream) {
DebugLogFile("gAddMaterial:gLoadTexture: Cannot find %s.\n", AlternateName);
return nullptr;
}
lpSSource = parseDDS(*stream);
dwWidth = lpSSource->width;
dwHeight = lpSSource->height;
error("TODO");
#if 0
Texture->texId = createTextureFromSurface(*lpSSource, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
#endif
delete lpSSource;
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
//warning("TODO: Handle TGA");
#if 0
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;
}
MaterialPtr Renderer::addMaterial(MaterialPtr MList, const Common::String &name, int NumFaces, unsigned int LoaderFlags) {
MaterialPtr Material = MList;
bool AlreadyLoaded = FALSE;
int len = name.size();
//warning("AddMaterial(%s)\n", name.c_str());
if (((name[len - 1 - 0] == 'i') || (name[len - 1 - 0] == 'I')) &&
((name[len - 1 - 1] == 'v') || (name[len - 1 - 1] == 'V')) &&
((name[len - 1 - 2] == 'a') || (name[len - 1 - 2] == 'A'))) {
if ((Material->Movie = gLoadMovie(*_workDirs, name.c_str())) == nullptr)
return nullptr;
if ((Material->Texture = gUserTexture(64,
128)) == nullptr)
// if( (Material->Texture=gUserTexture( Material->Movie->g_psiStreamInfo.rcFrame.right,
// Material->Movie->g_psiStreamInfo.rcFrame.bottom)) == NULL )
return nullptr;
Material->Flags |= T3D_MATERIAL_MOVIE;
} else {
if ((Material->Texture = gLoadTexture(*_workDirs, name.c_str(), LoaderFlags)) == nullptr)
return nullptr;
}
//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;
}
} // End of namespace Watchmaker
#endif // USE_OPENGL_GAME

View 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

View File

@ -0,0 +1,201 @@
/* 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"
#ifdef USE_OPENGL_GAME
#include "graphics/opengl/system_headers.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 (int i = 0; i < numFaces; i++) {
int index = faces[i];
auto &vertex = VBO->_buffer[index];
//warning("%d/%d %d: [%f, %f, %f], [%f, %f], [%f, %f]\n", i, numFaces, index, vertex.x, vertex.y, vertex.z, vertex.u1, vertex.v1, vertex.u2, vertex.v2);
//glColor3f((float)i/numFaces, 1.0, 0.0);
glColor3f(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];
glColor3f(1.0, 1.0, 1.0);
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\n");
}
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) {
glBindTexture(GL_TEXTURE_2D, texture.texId);
}
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);
}
case RenderState::ALPHABLEND: setGlFeature(GL_BLEND, value); break; // TODO
}
//warning("TODO: Implement setRenderState\n");
}
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:
assert(false);
}
}
void OpenGLRenderer::setBlendFunc(BlendFactor src, BlendFactor dst) {
glBlendFunc(translateBlendFactorToGL(src), translateBlendFactorToGL(dst));
}
} // End of namespace Watchmaker
#endif // USE_OPENGL_GAME

View File

@ -0,0 +1,104 @@
/* 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
};
class OpenGLRenderer {
public:
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\n");
return false;
}
Common::String getErrorString() {
warning("TODO: Implement getErrorString\n");
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

View File

@ -0,0 +1,693 @@
/* 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) {
gBatchBlock *v1 = (gBatchBlock *)a;
gBatchBlock *v2 = (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(void) {
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(void) {
signed short int LastViewMatrixNum, LastTexture1, LastTexture2;
gBatchBlock *bb;
bool hres = false;
RenderSky();
//warning("TODO: Texture configuration\n");
#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 (int 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\n");
#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\n");
#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\n");
#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 (int 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 (int 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 (int 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 (int 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(void) {
unsigned int i, j;
bool hres;
static int Logostops = 0;
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\n");
#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
}
// Display logos if exists
if ((NumLogosMaterials) && (NumLogosMaterials != Logostops)) {
gLogo *lpLogos = Logos;
WORD Array[2 * 3];
Logostops = 0;
Array[0] = 0;
Array[1] = 1;
Array[2] = 2;
Array[3] = 3;
Array[4] = 2;
Array[5] = 1;
g_renderer->setTextureWrapMode(0, TextureWrapMode::CLAMP);
g_renderer->setRenderState(RenderState::ALPHABLEND, false);
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::ZERO);
if (g_renderer->error()) {
goto closescene;
}
rSetZBufferState(FALSE);
for (i = 0; i < (unsigned int)NumLogosMaterials; i++, lpLogos++) {
if (lpLogos->Verts[0].sy == lpLogos->Verts[2].sy) {
Logostops++;
continue;
}
if (lpLogos->Material->Texture)
g_renderer->setTexture(0, lpLogos->Material->Texture);
#if 0 // TODO!
hres = g_renderer->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
D3DFVF_TLVERTEX,
lpLogos->Verts, 4,
Array, 6, 0x0);
#endif
lpLogos->Delay--;
if (lpLogos->Delay < 0) {
lpLogos->Verts[0].sx += 0.5f;
lpLogos->Verts[0].sy += 1.0f;
lpLogos->Verts[0].sz += 0.008f;
lpLogos->Verts[0].rhw = 1.0f / lpLogos->Verts[0].sz;
lpLogos->Verts[1].sx -= 0.5f;
lpLogos->Verts[1].sy += 1.0f;
lpLogos->Verts[1].sz += 0.008f;
lpLogos->Verts[1].rhw = 1.0f / lpLogos->Verts[1].sz;
lpLogos->Verts[2].sx -= 0.5f;
lpLogos->Verts[2].sy -= 1.0f;
lpLogos->Verts[2].sz -= 0.008f;
lpLogos->Verts[2].rhw = 1.0f / lpLogos->Verts[2].sz;
lpLogos->Verts[3].sx += 0.5f;
lpLogos->Verts[3].sy -= 1.0f;
lpLogos->Verts[3].sz -= 0.008f;
lpLogos->Verts[3].rhw = 1.0f / lpLogos->Verts[3].sz;
}
}
rSetZBufferState(TRUE);
g_renderer->setTextureWrapMode(0, TextureWrapMode::WRAP);
}
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();
bb->Texture1 = T1;
bb->Texture2 = T2;
bb->Flags1 = F1;
bb->Flags2 = F2;
bb->NumFaces = 0;
bb->NumVerts = 0;
bb->FacesList.clear();
return bb;
}
} // End of namespace Watchmaker

View 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

View 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\n");
#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\n");
#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\n");
#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\n");
#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\n");
#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\n");
#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\n");
#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\n");
#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

View 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

View File

@ -0,0 +1,615 @@
/* 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/t3d_mesh.h"
#include "watchmaker/3d/math/llmath.h"
#include "watchmaker/3d/loader.h"
#include "watchmaker/ll/ll_system.h"
#include "watchmaker/game.h"
#include "watchmaker/renderer.h"
#include "watchmaker/3d/light.h"
namespace Watchmaker {
#define CAMFILEVERSION 2
#define BNDFILEVERSION 2
void t3dLoadMaterials(WGame &game, t3dBODY *b, Common::SeekableReadStream &stream) {
int16 loader_numtextures = 0;
WorkDirs &workdirs = game.workDirs;
for (uint16 material = 0; material < b->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 = b->MatTable[material];
//warning("Loading material %d\n", 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++;
}
}//__for_material
}
void t3dLoadMeshes(t3dBODY *b, uint32 numMeshes, t3dMESH *&ReceiveRipples, uint8 &Mirror, Common::SeekableReadStream &stream) {
b->MeshTable.clear();
for (uint16 mesh = 0; mesh < numMeshes; mesh++) {
b->MeshTable.push_back(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) {
int 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 = CheckIfAlreadyLoaded(Name)) == nullptr) && (!(LoaderFlags & T3D_NORECURSION))) { // Controlla se lo ha gia' caricato
if (Name.equalsIgnoreCase("rxt.t3d"))
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)
AddToLoadList(&Mesh[mesh], Name, (uint16)(LoaderFlags | T3D_NORECURSION & ~T3D_RECURSIONLEVEL1)); // aggiunge e leva la ricorsione
else
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) {
/* FILE *f;*/
uint16 i, j, npan, nlev;
uint8 ver;
for (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 ;
}
if ((ver = stream->readByte()) != BNDFILEVERSION) {
warning("BND File Version Error: loaded %d.\tRequired %d", ver, BNDFILEVERSION);
return ;
}
b->NumLevels = nlev = stream->readSint16LE();
if (nlev > T3D_MAX_LEVELS) {
warning("Too much Floor Levels in %s: %d instead of %d\n", pname, b->NumLevels, T3D_MAX_LEVELS);
b->NumLevels = nlev = T3D_MAX_LEVELS;
}
for (j = 0; j < nlev; j++) {
b->NumPanels[j] = npan = stream->readSint16LE();
b->PanelHeight[j] = stream->readFloatLE() * SCALEFACTOR;
b->Panel[j] = t3dMalloc<t3dPAN>(npan + 4 * T3D_MAX_CHARACTERS); // lascia anche un po' di spazio per eventuali aggiunte
for (i = 0; i < npan; i++) {
b->Panel[j][i].x1 = stream->readFloatLE() * SCALEFACTOR;
b->Panel[j][i].z1 = stream->readFloatLE() * SCALEFACTOR;
b->Panel[j][i].x2 = stream->readFloatLE() * SCALEFACTOR;
b->Panel[j][i].z2 = stream->readFloatLE() * SCALEFACTOR;
b->Panel[j][i].bx1 = stream->readFloatLE() * SCALEFACTOR;
b->Panel[j][i].bz1 = stream->readFloatLE() * SCALEFACTOR;
b->Panel[j][i].bx2 = stream->readFloatLE() * SCALEFACTOR;
b->Panel[j][i].bz2 = 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(WorkDirs &workDirs, t3dBODY *b) {
uint32 NumLightmaps;//, num;
gVertex *gv;
uint8 rr, gg, bb;
int32 Map, alphaval1, alphaval2, alphaval3;
Common::String Appo = setDirectoryAndName(workDirs._lightmapsDir, b->name);
Appo = Appo.substr(0, Appo.size() - 3) + "map"; // TODO: Create util-functions for this lookup
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();
if (rAddMaterial(*b->LightmapTable[i], Appo, 0, 0) == nullptr)
return;
b->LightmapTable[i]->Flags = 0;
b->LightmapTable[i]->NumFaces = 0;
}
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.mat->Flags & T3D_MATERIAL_OPACITY)) &&
(!(f.mat->Flags & T3D_MATERIAL_CLIPMAP)) &&
(!(f.mat->Flags & T3D_MATERIAL_BOTTLE)) &&
(!(f.mat->Flags & T3D_MATERIAL_ADDITIVE)) &&
(!(f.mat->Flags & 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.mat->addNumFacesAdditionalMaterial(f.lightmap, 1);
} else if (((f.mat->Flags & T3D_MATERIAL_OPACITY)) ||
((f.mat->Flags & T3D_MATERIAL_CLIPMAP)) ||
((f.mat->Flags & T3D_MATERIAL_BOTTLE)) ||
((f.mat->Flags & T3D_MATERIAL_ADDITIVE)) ||
((f.mat->Flags & 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.mat->Flags & T3D_MATERIAL_OPACITY)) &&
(!(f.mat->Flags & T3D_MATERIAL_CLIPMAP)) &&
(!(f.mat->Flags & T3D_MATERIAL_BOTTLE)) &&
(!(f.mat->Flags & T3D_MATERIAL_ADDITIVE)) &&
(!(f.mat->Flags & 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;
t3dPLIGHT *PLight;
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);
//-------------------LOADING LIGHTS--------------------------------------
this->LightTable.reserve(numLights); // Alloca spazio per le luci globali
for (light = 0; light < numLights; light++) {
this->LightTable.push_back(t3dLIGHT(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---------------------
warning("LoaderFlags late = %08X\n", LoaderFlags);
//decodeLoaderFlags(LoaderFlags);
if (!(LoaderFlags & T3D_NOBOUNDS)) { // Carica Bounds
auto bndName = workdirs.join(workdirs._bndDir, pname, "bnd");
/*
strcpy(Name, workdirs._bndDir.c_str());
strcat(Name, pname);
len = strlen(Name);
Name[len - 3] = 'b';
Name[len - 2] = 'n';
Name[len - 1] = 'd';
*/
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(workdirs, 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
gMaterial *mat1, *mat2;
this->MirrorMatTable = rCreateMaterialList(this->NumMaterials());
for (uint16 i = 0; i < this->NumMaterials(); i++, mat1++, mat2++) // Per ogni materiale allocato
rCopyMaterial(this->MirrorMatTable[i], this->MatTable[i]);
}
//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

View File

@ -0,0 +1,92 @@
/* 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 (int 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

View File

@ -0,0 +1,275 @@
/* 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) {
//Mesh[mesh].FList = new t3dFACE[Mesh[mesh].NumFaces]{}; // Alloca facce
for (uint16 face = 0; face < NumFaces(); face++) {
FList[face].VertexIndex[0] = stream.readSint16LE(); // Legge VertexIndex0
FList[face].VertexIndex[1] = stream.readSint16LE(); // Legge VertexIndex1
FList[face].VertexIndex[2] = stream.readSint16LE(); // Legge VertexIndex2
FList[face].n = b->NList[stream.readSint16LE()]; // Legge puntatore a normale
uint16 n = stream.readSint16LE(); // Legge indice materiale
if (n >= b->NumMaterials())
warning("Material index wrong: current index: %d; Max material index %d\n", n, b->NumMaterials());
else {
FList[face].mat = b->MatTable[n]; // Make the pointer to the material
if (b->MatTable[n]->addNumFaces(1/*f2*/) == false) // Add face space to the material
warning("Can't realloc material faces");
}
}//__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] = {};
stream.read(stringBuffer, T3D_NAMELEN); // Legge nome mesh
this->name = stringBuffer;
stream.read(stringBuffer, T3D_NAMELEN); // Legge nome portale
this->portalName = stringBuffer;
this->FList.resize(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);
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 (int i = 0; i < numAniVerts; i++) {
this->ModVertices.push_back(t3dMODVERTS(stream));
}
}
}
/* -----------------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;
t3dFree(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;
if (this->WaterBuffer1)
t3dFree(this->WaterBuffer1);
this->WaterBuffer1 = nullptr;
if (this->WaterBuffer2)
t3dFree(this->WaterBuffer2);
this->WaterBuffer2 = nullptr;
if (this->VertexBuffer)
t3dFree(this->VertexBuffer);
this->VertexBuffer = nullptr;
if (this->OldVertexBuffer)
t3dFree(this->OldVertexBuffer);
this->OldVertexBuffer = nullptr;
if (this->SavedVertexBuffer)
t3dFree(this->SavedVertexBuffer);
this->SavedVertexBuffer = nullptr;
if (this->VertsInterpolants)
t3dFree(this->VertsInterpolants);
this->VertsInterpolants = nullptr;
// if(mt->VBptr)
// t3dFree(mt->VBptr);
this->VBptr = nullptr;
}
} // End of namespace Watchmaker

View File

@ -0,0 +1,147 @@
/* 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/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 (usefull 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, *WaterBuffer2; // 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; // 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.mat;
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->Flags & 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->Flags & 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->Flags & T3D_MATERIAL_GLASS) { // Se e' un glass
Face.flags |= T3D_MATERIAL_GLASS; // lo setta sulla faccia
alphaval = 0xfe;
rr = gg = bb = 255;
}
if (Material->Flags & T3D_MATERIAL_BOTTLE) { // Se e' un bottle
Face.flags |= T3D_MATERIAL_BOTTLE; // sulla faccia
alphaval = 0x88;
rr = gg = bb = 255;
}
if (Material->Flags & 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);
void loadFaces(t3dBODY *b, Common::SeekableReadStream &stream);
void release();
void releaseAnim(uint8 flag);
};
} // End of namespace Watchmaker
#endif // WATCHMAKER_T3D_MESH_H

View 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

View File

@ -0,0 +1,51 @@
/* 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/str.h"
#include "watchmaker/surface.h"
namespace Watchmaker {
struct SDL_Texture;
// Texture structs
struct gTexture {
Common::String name;
Surface *surface = nullptr; // 2d surface
int texId = 0; // OpenGL tex id
SDL_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 texId == 0 && texture == nullptr;
}
};
} // End of namespace Watchmaker
#endif // WATCHMAKER_TEXTURE_H

View 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

View File

@ -0,0 +1,114 @@
/* 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 "watchmaker/types.h"
namespace Watchmaker {
struct t3dV2F {
t3dF32 x = 0.0f, y = 0.0f; // 2d Vector
public:
t3dV2F() {}
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:
t3dV3F() {}
t3dV3F(float x, float y, float z) : x(x), y(y), z(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:
t3dNORMAL() {}
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

View 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

View 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

View File

@ -0,0 +1,240 @@
/* 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();
Event(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();
Event(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) {
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;
Event(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) {
Event(EventClass::MC_CAMERA, ME_CAMERA1TO3, MP_DEFAULT, 0, 0, 0, nullptr, nullptr, nullptr);
Event(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_WAIT_CAMERA, init.Obj[CurObj].goroom, 0, 0, nullptr, nullptr, nullptr);
} else
Event(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

View 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

View 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

View 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

View File

@ -0,0 +1,925 @@
/* 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 MAX_CAMERA_STEPS 500
#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 {
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;
t3dV3F HeadAngles;
t3dF32 CamAngleX, CamAngleY;
uint8 bForceDirectCamera = false, bCameraCarrello = false;
uint8 t3dCurCameraIndex = 255;
uint8 t3dLastCameraIndex = 255;
/* -----------------20/10/98 10.40-------------------
* PickCamera
* --------------------------------------------------*/
t3dCAMERA *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 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 HandleCameraCarrello(t3dBODY *croom) {
t3dCAMERAPATH *cp = nullptr;
t3dF32 dist, mindist;
t3dV3F pt, i, b;
int16 j;
uint8 bcc;
if (!Player || !croom || !t3dCurCamera) return;
// Se e' appena partito il carrello
if (!bCameraCarrello) {
memcpy(&CameraCarrello, t3dCurCamera, sizeof(CameraCarrello));
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;
}
}
/* -----------------30/09/98 11.13-------------------
* GetCameraTaget
* --------------------------------------------------*/
void 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 NextCameraStep(WGame &game) {
t3dBONE *bone;
t3dV3F Target;
int16 i;
Init &init = game.init;
if (bMovingCamera == 2) {
if ((CameraDummy.CurFrame >= 0) && (CameraDummy.Anim.BoneTable)) {
if ((bone = &CameraDummy.Anim.BoneTable[33]) && (bone->Trasl))
t3dVectCopy(&t3dCurCamera->Source, &bone->Trasl[CameraDummy.CurFrame]);
if ((bone = &CameraDummy.Anim.BoneTable[34]) && (bone->Trasl))
t3dVectCopy(&t3dCurCamera->Target, &bone->Trasl[CameraDummy.CurFrame]);
} else {
t3dCurCamera = DestCamera;
CurCameraSubStep = CurCameraStep = NumCameraSteps = 0;
bMovingCamera = false;
DestCamera = nullptr;
t3dVectFill(&OldCameraTarget, 0.0f);
// 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;
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 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);
RemoveEvent(&Game, 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);
RemoveEvent(&Game, 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 ResetCameraSource(void) {
t3dLastCameraIndex = 255;
t3dCurCameraIndex = 255;
}
/* -----------------09/11/98 10.27-------------------
* ResetCameraTarget
* --------------------------------------------------*/
void ResetCameraTarget(void) {
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 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;
t3dLastCameraIndex = 255;
AddWaitingMsgs(MP_WAIT_PORTAL);
// DebugLogFile("PortalCrossed %s",PortalCrossed->Name);
// PortalCrossed = nullptr;
if (bMovingCamera) {
CurCameraStep = NumCameraSteps = 0;
bMovingCamera = FALSE;
DestCamera = nullptr;
AddWaitingMsgs(MP_WAIT_CAMERA);
}
if (bFirstPerson)
Event(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(init);
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;
if (&t3dCurRoom->PanelHeight[t3dCurRoom->CurLevel])
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);
Event(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 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 StartAnimCamera(WGame &game) {
DebugLogFile("StartAnimCamera");
t3dLastCameraIndex = t3dCurCameraIndex;
if (ForcedCamera) t3dCurCameraIndex = ForcedCamera - 1;
LastCamera = t3dCurCamera;
DestCamera = PickCamera(t3dCurRoom, t3dCurCameraIndex);
memcpy(&AnimCamera, DestCamera, sizeof(AnimCamera));
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 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

View File

@ -0,0 +1,47 @@
/* 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 {
extern t3dV3F HeadAngles;
extern t3dF32 CamAngleX, CamAngleY;
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);
void ResetCameraSource(void);
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

View File

@ -0,0 +1,545 @@
/* 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_sprintf
#define FORBIDDEN_SYMBOL_EXCEPTION_strcpy
#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;
char str[T3D_NAMELEN];
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;
strcpy(RoomInfo.name, "");
UpdateRoomInfo(init);
}
// 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]))
Event(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]))
Event(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]))
Event(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])
Event(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
Event(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:
sprintf(str, "%s.t3d", init.Room[ic->param1].name);
ChangeRoom(game, str, 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;
Event(EventClass::MC_SYSTEM, ME_STARTEFFECT, MP_DEFAULT, FRAME_PER_SECOND, FRAME_PER_SECOND, EFFECT_FADEOUT_T1, &ic1, nullptr, nullptr);
if (ic2) Event(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;
Event(EventClass::MC_SYSTEM, ME_STARTEFFECT, MP_DEFAULT, FRAME_PER_SECOND, FRAME_PER_SECOND, EFFECT_FADEOUT_T2, &ic1, nullptr, nullptr);
if (ic2) Event(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:
Event(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]];
}
Event(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;
RemoveEvent(&Game, 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]) {
Event(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
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 = ocBOTH;
CameraTargetBone = 0;
TimeWalk = ocBOTH;
TimeAnim = aNULL;
bPlayerInAnim = false;
if (NextDlg != dNULL)
Event(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, NextDlg, 0, 0, nullptr, nullptr, nullptr);
else {
extern uint8 t3dLastCameraIndex;
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");
t3dLastCameraIndex = 255; //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)) {
Event(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))
Event(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, Diag2Up, dmx, dmy))
Diag2Base = ((Diag2Base - 1) < 0) ? 0 : Diag2Base - 1;
else if (CheckRect(renderer, 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, ty;
uint8 tc;
Init &init = game.init;
if ((bDialogActive == FALSE) || (CurDialog == dNULL) || (bDialogMenuActive == FALSE))
return ;
DisplayDDBitmap(*game._renderer, ConsoleD1, 7, 366, 0, 0, 0, 0);
DisplayD3DRect(*game._renderer, 15, 373, 187, 211, 18, 25, 18, 128);
DisplayDDBitmap(*game._renderer, 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;
DisplayDDText(*game._renderer, Sentence[init.DlgMenu[a].titolo], &StandardFont, tc, tx, ty, 0, 0, 0, 0);
}
// disegno le frecce
if (Diag2Base > 0)
DisplayDDBitmap(*game._renderer, ConsoleFrecciaSu, 223 + 550, 515 + 0, 0, 0, 0, 0);
if ((Diag2Base + 1 + MAX_DIAG2_ITEMS) <= ca2)
DisplayDDBitmap(*game._renderer, ConsoleFrecciaGiu, 223 + 550, 515 + 56, 0, 0, 0, 0);
}
} // End of namespace Watchmaker

View 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

View File

@ -0,0 +1,392 @@
/* 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 {
extern t3dV3F HeadAngles;
extern t3dF32 CamAngleX, CamAngleY;
/* -----------------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))) {
Event(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]) {
Event(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;
Event(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;
RemoveEvent(&Game, 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;
CamAngleX = 0.0f;
CamAngleY = 0.0f;
t3dVectFill(&HeadAngles, 0.0f);
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

View 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

View 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)) {
Event(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

View 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

View 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)) {
Event(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) {
Event(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)
Event(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR002, 0, 0, nullptr, nullptr, nullptr);
else
sent = TRUE;
break;
case i14OCCHIALI:
if (UseWith[WITH] == ocCUSTODE)
Event(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;
Event(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;
Event(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;
}
Event(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR009, 0, 0, nullptr, nullptr, nullptr);
}
break;
case i34LASTRE:
if (UseWith[WITH] == ocSUPERVISORE)
Event(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] );
Event(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)
Event(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR291, 0, 0, nullptr, nullptr, nullptr);
} else sent = TRUE;
break;
case i29STAMPAINGRANAGGIO:
if (UseWith[WITH] == ocCUSTODE)
Event(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR006, 0, 0, nullptr, nullptr, nullptr);
else
sent = TRUE;
break;
case i31ANELLOBRONZO:
if (UseWith[WITH] == ocCUSTODE)
Event(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
Event(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dR1A5, 0, 0, nullptr, nullptr, nullptr);
} else
sent = TRUE;
break;
case i48CHIAVIMANETTE:
if (UseWith[WITH] == o48MANETTE)
Event(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

View 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

View File

@ -0,0 +1,741 @@
/* 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/classes/do_keyboard.h"
#include "watchmaker/globvar.h"
#include "watchmaker/define.h"
#include "watchmaker/3d/math/llmath.h"
#include "watchmaker/3d/t3d_mesh.h"
#include "watchmaker/ll/ll_util.h"
#include "watchmaker/walk/act.h"
#include "watchmaker/walk/walkutil.h"
#include "watchmaker/utils.h"
#include "watchmaker/3d/geometry.h"
#include "watchmaker/schedule.h"
#include "watchmaker/classes/do_dialog.h"
#include "watchmaker/t2d/t2d.h"
#include "watchmaker/main.h"
#include "watchmaker/ll/ll_diary.h"
#include "watchmaker/ll/ll_anim.h"
#include "watchmaker/classes/do_player.h"
#include "watchmaker/classes/do_camera.h"
#include "watchmaker/3d/animation.h"
#include "watchmaker/walk/walk.h"
#include "watchmaker/ll/ll_mouse.h"
#include "watchmaker/ll/ll_mesh.h"
namespace Watchmaker {
t3dF32 AngleX,AngleY,AngleSpeed;
char bFastAnim = 0;
int32 PlayAnim=351;
char bBilinear=1;
char bForceDebug=0;
unsigned char KeyTable[256];
uint16 bnd_lev;
extern int16 NextDlg; //from doDialog.c
extern uint8 tasti_per_sfx1; //from main.c
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(unsigned char key)
{
if(KeyTable[(key)] & 0x80)
return TRUE;
else
return FALSE;
}
bool KeyUp(unsigned char key)
{
if(KeyTable[(key)] & 0x10)
{
KeyTable[(key)]=0;
return TRUE;
}
else
return FALSE;
}
void KeyClear(unsigned char 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( void )
{
t3dF32 dist;
t3dV3F d,n;
error("TODO: HandleFirstPersonView");
#if 0
if( ( !Player ) || ( !t3dCurCamera ) || ( bLockCamera ) ) return;
if( KeyDown(SDL_SCANCODE_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(SDL_SCANCODE_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(SDL_SCANCODE_LSHIFT) || KeyDown(SDL_SCANCODE_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(SDL_SCANCODE_UP) )
d *= (5*SCALEFACTOR );
else if( KeyDown(SDL_SCANCODE_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(SDL_SCANCODE_LEFT) )
n *= (5*SCALEFACTOR );
else if( KeyDown(SDL_SCANCODE_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(SDL_SCANCODE_UP) )
y = -10;
else if( KeyDown(SDL_SCANCODE_DOWN) )
y = MainDy+10;
if( KeyDown(SDL_SCANCODE_LEFT) )
x = -10;
else if( KeyDown(SDL_SCANCODE_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 );
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 );
}
#endif
}
/* -----------------23/04/98 17.24-------------------
* ProcessKeyboard
* --------------------------------------------------*/
void ProcessKeyboard(WGame &game) {
//warning("STUBBED: ProcessKeyboard\n");
// Hack: Skip intro:
if ((CurDialog == dR000) || (CurDialog == dR111) || (CurDialog == dR211)) {
NextDlg = dNULL;
Event(EventClass::MC_DIALOG, ME_DIALOGEND_SKIPINTRO, MP_DEFAULT, (int16)CurDialog, mQUIT, 0, NULL, NULL, NULL);
}
// Skip Loghi
if (CurDialog == dRLOGHI)
Event(EventClass::MC_DIALOG, ME_DIALOGEND, MP_DEFAULT, (int16)CurDialog, mQUIT, 0, NULL, NULL, NULL);
// End hack
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 ;
error("TODO: Convert to OSystem");
#if 0
if (KeyUp(SDL_SCANCODE_ESCAPE)) {
if (LoaderFlags & T3D_DEBUGMODE) {
CloseSys(game); // Quitta il gioco
} else {
// Skip Intro
if ((CurDialog == dR000) || (CurDialog == dR111) || (CurDialog == dR211)) {
NextDlg = dNULL;
Event(EventClass::MC_DIALOG, ME_DIALOGEND_SKIPINTRO, MP_DEFAULT, (int16)CurDialog, mQUIT, 0, NULL, NULL, NULL);
}
// Skip Loghi
if (CurDialog == dRLOGHI)
Event(EventClass::MC_DIALOG, ME_DIALOGEND, MP_DEFAULT, (int16)CurDialog, mQUIT, 0, NULL, NULL, NULL);
// Skip MorteWM
if (CurDialog == dR391)
Event(EventClass::MC_DIALOG, ME_DIALOGEND, MP_DEFAULT, (int16)CurDialog, mQUIT, 0, NULL, NULL, NULL);
// Skip durante i crediti, quitta
if (bTitoliCodaScrolling || bTitoliCodaStatic)
game.CleanUpAndPostQuit();
}
}// SDL_SCANCODE_ESCAPE
//se ci sono i crediti ritorna (controlla solo l'ESC)
if (bTitoliCodaStatic || bTitoliCodaScrolling) return;
if (KeyDown(SDL_SCANCODE_LSHIFT) && KeyUp(SDL_SCANCODE_D))
bForceDebug ^= 1;
/* if( KeyDown(SDL_SCANCODE_LSHIFT) ) // Bomba il gioco
if( KeyUp(SDL_SCANCODE_F) )
{
t3dFree(t3dCurRoom->CameraTable);
t3dFree(t3dCurRoom->CameraTable);
}
*/
if (KeyUp(SDL_SCANCODE_I)) // Escono Informazioni
bShowInfo ^= 1;
if (KeyUp(SDL_SCANCODE_G)) {
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);
}
if (KeyUp(SDL_SCANCODE_END)) {
if (!bFirstPerson)
StartAnim(game, aGIRO);
}
if ((LoaderFlags & T3D_DEBUGMODE) || bForceDebug) {
if (KeyUp(SDL_SCANCODE_F5))
DataSave("Prova Save", 0);
if (KeyUp(SDL_SCANCODE_F6))
DataLoad(game, "", 0);
if (KeyUp(SDL_SCANCODE_W)) { // Modalita' wireframe
bForceWire ^= 1;
if (bForceWire)
rSetRenderMode(rWIREFRAMEMODE);
else
rSetRenderMode(rSOLIDMODE);
}
if (KeyUp(SDL_SCANCODE_B)) // Escono BoundingBox
bShowBoundingBox ^= 1;
if (KeyUp(SDL_SCANCODE_BACKSPACE)) // Fa andare le animazioni piu' veloci
bFastAnim ^= 1;
if (KeyUp(SDL_SCANCODE_S))
bSkipTalk = TRUE;
if (KeyUp(SDL_SCANCODE_H))
Event(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dPROVA, 0, 0, NULL, NULL, NULL);
if (KeyUp(SDL_SCANCODE_E))
StartAnim(game, aFOX);
if (KeyUp(SDL_SCANCODE_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(SDL_SCANCODE_P)) {
if (KeyDown(SDL_SCANCODE_LSHIFT) || KeyDown(SDL_SCANCODE_RSHIFT)) {
if (++bnd_lev > 5) bnd_lev = 0;
SetBndLevel(game.init, NULL, bnd_lev);
DebugLogWindow("BndLev %d", bnd_lev);
} else
bShowPanels ^= 1; // Escono Pannelli
}
if (!tasti_per_sfx1) {
if (KeyUp(SDL_SCANCODE_M)) {
if (KeyDown(SDL_SCANCODE_LSHIFT))
DInputNonExclusiveMouse();
else if (KeyDown(SDL_SCANCODE_RSHIFT))
DInputExclusiveMouse();
}
if (KeyUp(SDL_SCANCODE_O))
bShowExtraLocalizationStrings ^= 1;
} else {
if (KeyUp(SDL_SCANCODE_K)) {
PlayAnim --;
if (KeyDown(SDL_SCANCODE_LCTRL) || KeyDown(SDL_SCANCODE_RCTRL))
PlayAnim -= 19;
if (KeyDown(SDL_SCANCODE_LSHIFT) || KeyDown(SDL_SCANCODE_RSHIFT))
PlayAnim -= 30;
printf("PlayAnim %d '%s'\n", PlayAnim, game.init.Anim[PlayAnim].name[0].rawArray()); // TODO DebugString
}
if (KeyUp(SDL_SCANCODE_L)) {
PlayAnim ++;
if (KeyDown(SDL_SCANCODE_LCTRL) || KeyDown(SDL_SCANCODE_RCTRL))
PlayAnim += 19;
if (KeyDown(SDL_SCANCODE_LSHIFT) || KeyDown(SDL_SCANCODE_RSHIFT))
PlayAnim += 30;
printf("PlayAnim %d '%s'\n", PlayAnim, game.init.Anim[PlayAnim].name[0].rawArray()); // TODO DebugString
}
if (KeyUp(SDL_SCANCODE_M))
StartAnim(game, PlayAnim);
}
if (KeyDown(SDL_SCANCODE_LSHIFT)) {
void t3dLoadOutdoorLights(const char *pname, t3dBODY * b, int32 ora);
if (KeyUp(SDL_SCANCODE_F1)) t3dLoadOutdoorLights("c:\\wm\\LMaps\\rxt.t3d", t3dRxt, 1030);
if (KeyUp(SDL_SCANCODE_F2)) t3dLoadOutdoorLights("c:\\wm\\LMaps\\rxt.t3d", t3dRxt, 1530);
if (KeyUp(SDL_SCANCODE_F3)) t3dLoadOutdoorLights("c:\\wm\\LMaps\\rxt.t3d", t3dRxt, 1930);
if (KeyUp(SDL_SCANCODE_F4)) t3dLoadOutdoorLights("c:\\wm\\LMaps\\rxt.t3d", t3dRxt, 2230);
}
if (KeyUp(SDL_SCANCODE_F11)) IncCurTime(game, 5);
if (KeyUp(SDL_SCANCODE_F12)) IncCurTime(game, 100);
if (KeyUp(SDL_SCANCODE_1)) CharSetPosition(ocCURPLAYER, 1, NULL);
if (KeyUp(SDL_SCANCODE_2)) CharSetPosition(ocCURPLAYER, 2, NULL);
if (KeyUp(SDL_SCANCODE_3)) CharSetPosition(ocCURPLAYER, 3, NULL);
if (KeyUp(SDL_SCANCODE_4)) CharSetPosition(ocCURPLAYER, 4, NULL);
if (KeyUp(SDL_SCANCODE_5)) CharSetPosition(ocCURPLAYER, 5, NULL);
if (KeyUp(SDL_SCANCODE_6)) CharSetPosition(ocCURPLAYER, 6, NULL);
if (KeyUp(SDL_SCANCODE_7)) CharSetPosition(ocCURPLAYER, 7, NULL);
if (KeyUp(SDL_SCANCODE_8)) CharSetPosition(ocCURPLAYER, 8, NULL);
if (KeyUp(SDL_SCANCODE_9)) CharSetPosition(ocCURPLAYER, 9, NULL);
if (KeyUp(SDL_SCANCODE_KP_0)) CharSetPosition(ocCURPLAYER, 10, NULL);
if (KeyUp(SDL_SCANCODE_KP_1)) CharSetPosition(ocCURPLAYER, 11, NULL);
if (KeyUp(SDL_SCANCODE_KP_2)) CharSetPosition(ocCURPLAYER, 12, NULL);
if (KeyUp(SDL_SCANCODE_KP_3)) CharSetPosition(ocCURPLAYER, 13, NULL);
if (KeyUp(SDL_SCANCODE_KP_4)) CharSetPosition(ocCURPLAYER, 14, NULL);
if (KeyUp(SDL_SCANCODE_KP_5)) CharSetPosition(ocCURPLAYER, 15, NULL);
if (KeyUp(SDL_SCANCODE_KP_6)) CharSetPosition(ocCURPLAYER, 16, NULL);
if (KeyUp(SDL_SCANCODE_KP_7)) CharSetPosition(ocCURPLAYER, 17, NULL);
if (KeyUp(SDL_SCANCODE_KP_8)) CharSetPosition(ocCURPLAYER, 18, NULL);
if (KeyUp(SDL_SCANCODE_KP_9)) CharSetPosition(ocCURPLAYER, 19, NULL);
if (KeyDown(SDL_SCANCODE_LSHIFT))
if (KeyUp(SDL_SCANCODE_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(SDL_SCANCODE_D))
bShowRoomDescriptions ^= 1;
if (KeyUp(SDL_SCANCODE_E))
bShowExtraLocalizationStrings ^= 1;
if (KeyUp(SDL_SCANCODE_P))
Event(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, 0, 0, tPDA, NULL, NULL, NULL);
}
if (KeyUp(SDL_SCANCODE_F8) && PlayerCanSwitch(game._gameVars, 1) && !(InvStatus & INV_ON))
// && ( (InvStatus & (INV_ON|INV_MODE2)) != (INV_ON|INV_MODE2) ) )
{
KeyClear(SDL_SCANCODE_F8);
if (CurPlayer == DARRELL) a = ocVICTORIA;
else a = ocDARRELL;
if (a == (ocDARRELL + CurPlayer)) return ;
Event(EventClass::MC_SYSTEM, ME_STARTEFFECT, MP_DEFAULT, FRAME_PER_SECOND / 3, 0, EFFECT_FADOUT, NULL, NULL, NULL);
if (bMovingCamera)
Event(EventClass::MC_SYSTEM, ME_CHANGEPLAYER, MP_WAITA | MP_WAIT_CAMERA, (int16)a, 0, 0, NULL, NULL, NULL);
else
Event(EventClass::MC_SYSTEM, ME_CHANGEPLAYER, MP_WAITA, (int16)a, 0, 0, NULL, NULL, NULL);
}
if ((bPlayerInAnim) || (bNotSkippableWalk) || (bDialogActive)) {
KeyClear(SDL_SCANCODE_F1);
KeyClear(SDL_SCANCODE_F2);
KeyClear(SDL_SCANCODE_F3);
KeyClear(SDL_SCANCODE_TAB);
KeyClear(SDL_SCANCODE_SPACE);
KeyClear(SDL_SCANCODE_LCTRL);
KeyClear(SDL_SCANCODE_RCTRL);
KeyClear(SDL_SCANCODE_END);
return;
}
if (KeyUp(SDL_SCANCODE_F1) && !(InvStatus & INV_ON) && (bT2DActive == tNULL) && PlayerCanSave()) {
rGrabVideo("temp.tmp", 1);
Event(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, MPX_START_T2D_SAVE, 0, tOPTIONS, NULL, NULL, NULL);
}
if (KeyUp(SDL_SCANCODE_F2) && !(InvStatus & INV_ON) && (bT2DActive == tNULL)) {
rGrabVideo("temp.tmp", 1);
Event(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, MPX_START_T2D_LOAD, 0, tOPTIONS, NULL, NULL, NULL);
}
if (KeyUp(SDL_SCANCODE_F3) && !(InvStatus & INV_ON) && (bT2DActive == tNULL)) {
rGrabVideo("temp.tmp", 1);
Event(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(SDL_SCANCODE_LCTRL)) || (KeyUp(SDL_SCANCODE_RCTRL)))) {
KeyClear(SDL_SCANCODE_LCTRL);
KeyClear(SDL_SCANCODE_RCTRL);
if (bSomeOneSpeak) bSkipTalk = TRUE;
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;
Event(EventClass::MC_MOUSE, ME_MRIGHT, MP_DEFAULT, 0, 0, 0, &CurObj, NULL, NULL);
}
}
}
}
}
if (KeyUp(SDL_SCANCODE_SPACE) && (!IsPlayerInPool())) { // Cambia tra 3a e 1a persona
if (bSomeOneSpeak) bSkipTalk = TRUE;
if ((bFirstPerson == 0) && (!bMovingCamera) && (!bNoFirstPersonSwitch)/* && !( InvStatus & INV_ON )*/)
Event(EventClass::MC_CAMERA, ME_CAMERA3TO1, MP_DEFAULT, 0, 0, 0, NULL, NULL, NULL);
else if ((!bMovingCamera) && (!bNoFirstPersonSwitch)/* && !( InvStatus & INV_ON )*/)
Event(EventClass::MC_CAMERA, ME_CAMERA1TO3, MP_DEFAULT, 0, 0, 0, NULL, NULL, NULL);
}
if (KeyUp(SDL_SCANCODE_TAB) && !bLockCamera) // Fa uscire l'inventario
Event(EventClass::MC_INVENTORY, ME_INVSWITCH, MP_DEFAULT, 0, 0, 0, NULL, NULL, NULL);
if (KeyDown(SDL_SCANCODE_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(SDL_SCANCODE_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(SDL_SCANCODE_UP) && !(InvStatus & INV_ON) && !(bFirstPerson)) {
AngleSpeed = 20.0f;
} else if (KeyDown(SDL_SCANCODE_DOWN) && !(InvStatus & INV_ON) && !(bFirstPerson)) {
AngleSpeed = -20.0f;
}
if (KeyDown(SDL_SCANCODE_LSHIFT) || KeyDown(SDL_SCANCODE_RSHIFT)) // || (GetKeyState(SDL_SCANCODE_CAPSLOCK) & 0x1)) TODO: Allow for Caps-lock for fast walk
bFastWalk = TRUE;
else
bFastWalk = FALSE;
if (!t3dCurCamera) return;
if ((bFirstPerson) && !(bMovingCamera))
HandleFirstPersonView();
if (bFirstPerson) {
Event(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;
}
#endif
}
/* -----------------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, (char *)game.init.Obj[obj].meshlink[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

View 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[256];
} // End of namespace Watchmaker
#endif // WATCHMAKER_DO_KEYBOARD_H

View File

@ -0,0 +1,346 @@
/* 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;
extern t3dV3F HeadAngles;
extern t3dF32 CamAngleX, CamAngleY;
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, CallOtherPlayerRect, TheMessage->wparam1, TheMessage->wparam2)) {
Event(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, BigIconRect, TheMessage->wparam1, TheMessage->wparam2))
CurInvObj = BigInvObj;
if (CurInvObj == iNULL) {
// se ho cliccato su icona grande
if (InvStatus & INV_MODE2) {
if (CheckRect(renderer, Inv1Up, TheMessage->wparam1, TheMessage->wparam2))
InventoryUp();
else if (CheckRect(renderer, Inv1Down, TheMessage->wparam1, TheMessage->wparam2))
InventoryDown();
else if (CheckRect(renderer, CloseInvRect, TheMessage->wparam1, TheMessage->wparam2)) {
if (InvStatus & INV_MODE4) {
CurPlayer ^= 1;
ChangePlayer(game, (uint8)((CurPlayer ^ 1) + ocDARRELL));
}
InvStatus = INV_OFF;
CamAngleX = 0.0f;
CamAngleY = 0.0f;
t3dVectFill(&HeadAngles, 0.0f);
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, QuitGameRect, TheMessage->wparam1, TheMessage->wparam2))
CloseSys(game);
else if (CheckRect(renderer, InvSaveRect, TheMessage->wparam1, TheMessage->wparam2) && !(InvStatus & INV_MODE4) && PlayerCanSave())
Event(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, MPX_START_T2D_SAVE, 0, tOPTIONS, nullptr, nullptr, nullptr);
else if (CheckRect(renderer, InvLoadRect, TheMessage->wparam1, TheMessage->wparam2) && !(InvStatus & INV_MODE4))
Event(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, MPX_START_T2D_LOAD, 0, tOPTIONS, nullptr, nullptr, nullptr);
else if (CheckRect(renderer, InvOptionsRect, TheMessage->wparam1, TheMessage->wparam2) && !(InvStatus & INV_MODE4))
Event(EventClass::MC_T2D, ME_T2DSTART, MP_DEFAULT, MPX_START_T2D_OPTIONS, 0, tOPTIONS, nullptr, nullptr, nullptr);
else {
ClearUseWith();
if ((CheckRect(renderer, 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, Inv1Up, TheMessage->wparam1, TheMessage->wparam2))
InventoryUp();
else if (CheckRect(renderer, Inv1Down, TheMessage->wparam1, TheMessage->wparam2))
InventoryDown();
else {
InvStatus = INV_OFF;
ClearUseWith();
}
return;
}
if ((BigInvObj != CurInvObj) && !(bUseWith & UW_ON)) {
t3dMatIdentity(&BigIconM);
BigInvObj = CurInvObj;
}
if (TheMessage->event == ME_MRIGHT)
Event(EventClass::MC_INVENTORY, ME_OPERATEICON, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, 0, &CurInvObj, nullptr, nullptr);
else if (bUseWith & UW_ON)
Event(EventClass::MC_INVENTORY, ME_OPERATEICON, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, 0, &CurInvObj, nullptr, nullptr);
else
Event(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, 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))
Event(EventClass::MC_MOUSE, TheMessage->event, MP_WAIT_ANIM, 0, 0, 0, &NextPortalObj, nullptr, &bFastWalk);
else if (NextPortalObj)
Event(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)))))
Event(EventClass::MC_CAMERA, ME_CAMERA1TO3, MP_DEFAULT, 0, 0, 0, nullptr, nullptr, nullptr);
//? else if( bFirstPerson )
//? CharStop( ocCURPLAYER );
}
// Rimuove tutti gli eventi del personaggio
RemoveEvent(&Game, EventClass::MC_PLAYER, ME_ALL);
if (CurObj) { // se ho cliccato su un oggetto valido
if (TheMessage->event == ME_MLEFT) // se ho cliccato con sinistro
Event(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
Event(EventClass::MC_ACTION, ME_MOUSEOPERATE, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, bFirstPerson, &CurObj, nullptr, nullptr);
} else
Event(EventClass::MC_PLAYER, ME_PLAYERGOTOACTION, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, bFirstPerson, &CurObj, nullptr, nullptr);
}
} else // se non ho cliccato su niente
Event(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)(BigIconRect.y2 - BigIconRect.y1))*T3D_PI * 2.0f,
((t3dF32)(TheMessage->lparam[0]) / (t3dF32)(BigIconRect.x1 - BigIconRect.x2))*T3D_PI * 2.0f, 0.0f);
t3dMatMul(&BigIconM, &t, &BigIconM);
CurInvObj = BigInvObj;
} else {
CurInvObj = WhatIcon(*game._renderer, TheMessage->wparam1, TheMessage->wparam2);
if ((CurInvObj == iNULL) && CheckRect(renderer, 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)) {
Event(EventClass::MC_CAMERA, ME_CAMERA1TO3, MP_DEFAULT, 0, 0, 0, nullptr, nullptr, nullptr);
Event(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

View 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

File diff suppressed because it is too large Load Diff

View 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

View File

@ -0,0 +1,517 @@
/* 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 == ocBOTH))
AddWaitingMsgs(MP_WAIT_ACT);
if (TheMessage->event == ME_PLAYERGOTOEXAMINE)
Event(EventClass::MC_ACTION, ME_MOUSEEXAMINE, MP_DEFAULT, TheMessage->wparam1, TheMessage->wparam2, 0, &TheMessage->lparam[0], nullptr, nullptr);
else if (TheMessage->event == ME_PLAYERGOTOACTION)
Event(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))
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))
Event(EventClass::MC_DIALOG, ME_DIALOGSTART, MP_DEFAULT, dRUN_R1a1_RIGHT, 0, 0, nullptr, nullptr, nullptr);
else
Event(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);
Event(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);
Event(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);
Event(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);
Event(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\n", b, dist, na);
panims[pc] = b ;
pc ++;
}
// Ferma il primo personaggio e salva le posizioni
RemoveEvent(&Game, 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\n", 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(init, 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];
if (&t3dCurRoom->PanelHeight[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 );
Event(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

View 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

View 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

View 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

View File

@ -0,0 +1,372 @@
/* 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_sprintf
#include <cmath>
#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\n");
#if 0
if (!mInitMusicSystem())
return false;
if (!sInitSoundSystem(hWnd))
return false;
sSetDistanceFactor(METER2UNIT);
#endif
return true;
}
bool ListenerUpdate(void) {
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;
sprintf(CurSound.name, "%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;
sprintf(CurSound.name, "%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;
sprintf(CurSound.name, "%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;
}
sprintf(FileName, "%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

View 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

View File

@ -0,0 +1,250 @@
/* 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/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)
Event(EventClass::MC_STRING, ME_PLAYERCONTINUESPEAK_WAITWAVE, MP_WAIT_RETRACE, 0, 0, 0, &speechn, nullptr, nullptr);
else
Event(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) 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) 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)
sprintf(UWStr, "Use %s with ", ObjName[init.InvObj[UseWith[USED]].name]);
else
sprintf(UWStr, "Use %s with ", ObjName[init.Obj[UseWith[USED]].name]);
if ((UseWith[USED] != ob) || (bUseWith & UW_USEDI))
if (ObjName[init.Obj[ob].name] != nullptr)
strcat(UWStr, ObjName[init.Obj[ob].name]);
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)
sprintf(UWStr, "Use %s with ", ObjName[init.InvObj[UseWith[USED]].name]);
else
sprintf(UWStr, "Use %s with ", ObjName[init.Obj[UseWith[USED]].name]);
if ((UseWith[USED] != obj) || !(bUseWith & UW_USEDI))
if (ObjName[init.InvObj[obj].name] != nullptr)
strcat(UWStr, ObjName[init.InvObj[obj].name]);
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

View 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

File diff suppressed because it is too large Load Diff

View 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

4751
engines/watchmaker/define.h Normal file

File diff suppressed because it is too large Load Diff

View 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
uint32 extraLS_BMP = 0;
uint32 extraLS_currentID = 0;
int32 extraLS_bmpPosX = 0;
int32 extraLS_bmpPosY = 0;
struct SRect Console3Save = { 228 + 22, 11 + 15, 277 + 22, 30 + 15 };
struct SRect Console3Load = { 340 + 22, 11 + 15, 396 + 22, 30 + 15 };
struct SRect Console3Options = { 444 + 22, 11 + 15, 527 + 22, 30 + 15 };
struct SRect Console3Quit = { 565 + 22, 11 + 15, 613 + 22, 30 + 15 };
struct SRect Console3Close = { 665 + 22, 11 + 15, 724 + 22, 30 + 15 };
void CheckExtraLocalizationStrings(Renderer &renderer, uint32 id) {
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;
rGetTextDim(ExtraLS[newID], StandardFont.Table, &x, &y);
extraLS_BMP = CreateTooltipBitmap(renderer, ExtraLS[newID], &StandardFont, 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) DisplayDDBitmap(renderer, extraLS_BMP, extraLS_bmpPosX, extraLS_bmpPosY, 0, 0, 0, 0);
}
} // End of namespace Watchmaker

View 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

705
engines/watchmaker/game.cpp Normal file
View File

@ -0,0 +1,705 @@
/* 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_strcpy
#define FORBIDDEN_SYMBOL_EXCEPTION_sprintf
#include <unistd.h>
#include "watchmaker/game.h"
#include "watchmaker/windows_hacks.h"
#include "watchmaker/classes/do_system.h"
#include "watchmaker/3d/geometry.h"
#include "watchmaker/3d/loader.h"
#include "watchmaker/3d/math/llmath.h"
#include "watchmaker/3d/animation.h"
#include "watchmaker/define.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/walk/act.h"
#include "watchmaker/classes/do_player.h"
#include "watchmaker/classes/do_keyboard.h"
#include "watchmaker/classes/do_camera.h"
#include "watchmaker/walk/ball.h"
#include "watchmaker/sdl_wrapper.h"
#include "watchmaker/renderer.h"
namespace Watchmaker {
const char *WATCHMAKER_CFG_NAME = "wm.cfg";
// 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)\n", c);
char RemoveName[128] = "";
char RemoveNameHI[128] = "";
int32 j;
if (c == ocMOGLIESUPERVISORE) {
if (bMoglieGym && (!Character[c]->Body->name.contains("MoglieGym"))) {
CharName_Strings[c] = "MoglieGym.t3d";
strcpy(RemoveName, "MoglieSwim.t3d");
CharNameHI_Strings[c] = "MoglieGymHI.t3d";
strcpy(RemoveNameHI, "MoglieSwimHI.t3d");
}
if ((!bMoglieGym) && (!Character[c]->Body->name.contains("MoglieSwim"))) {
CharName_Strings[c] = "MoglieSwim.t3d";
strcpy(RemoveName, "MoglieGym.t3d");
CharNameHI_Strings[c] = "MoglieSwimHI.t3d";
strcpy(RemoveNameHI, "MoglieGymHI.t3d");
}
}
if (c == ocMOGLIE_KIMONO) {
if (bMoglieSangue && (!Character[c]->Body->name.contains("MoglieKimonoSangue"))) {
CharName_Strings[c] = "MoglieKimonoSangue.t3d";
strcpy(RemoveName, "MoglieKimono.t3d");
CharNameHI_Strings[c] = "MoglieKimonoSangueHI.t3d";
strcpy(RemoveNameHI, "MoglieKimonoHI.t3d");
}
if ((!bMoglieSangue) && (!Character[c]->Body->name.contains("MoglieKimono"))) {
CharName_Strings[c] = "MoglieKimono.t3d";
strcpy(RemoveName, "MoglieKimonoSangue.t3d");
CharNameHI_Strings[c] = "MoglieKimonoHI.t3d";
strcpy(RemoveNameHI, "MoglieKimonoSangueHI.t3d");
}
}
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;
for (j = 0; j < NumLoadedFiles; j++) {
if (LoadedFiles[j].name.equalsIgnoreCase(RemoveName) || LoadedFiles[j].name.equalsIgnoreCase(RemoveNameHI)) {
t3dReleaseBody(LoadedFiles[j].b);
LoadedFiles[j].b = nullptr;
break;
}
}
LoaderFlags |= T3D_PRELOADBASE;
LoaderFlags |= T3D_STATIC_SET1;
LoaderFlags |= T3D_STATIC_SET0;
rSetLoaderFlags(LoaderFlags);
if (!(Character[c] = t3dLoadCharacter(*this, CharName[c], Character[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) {
configLoaderFlags(); // TODO: This should probably happen before the constructor
// if LoaderFlags & T3D_DEBUGMODE
// ...
// }
gameOptions.load(workDirs);
// if (LoaderFlags & T3D_DEBUGMODE) {
// ...
// } else
warning("Currently doing an unneccessary copy here");
loadAll(workDirs, init);
sdl = new sdl_wrapper();
_renderer = new Renderer(&workDirs, sdl);
// Don't forget to register your random source
_rnd = new Common::RandomSource("Watchmaker");
}
WGame::~WGame() {
delete _renderer;
delete sdl;
}
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;
strcpy(RoomInfo.name, "");
return true;
}
/* -----------------16/10/98 12.15-------------------
* LoadAndSetup
* --------------------------------------------------*/
bool WGame::LoadAndSetup(const Common::String &name, uint8 lite) {
uint16 i = 0;
warning("--=>> %s <<=--: LoaderFlags: %08X\n", name.c_str(), LoaderFlags);
t3dCurCamera = &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 (!(t3dIcons = t3dLoadRoom(*this, "Icons.t3d", 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", Lanc33[0], 99)) || !(Lanc33[1] = t3dLoadCharacter(*this, "Lanc33b.t3d", Lanc33[1], 99)) ||
!(Lanc33[2] = t3dLoadCharacter(*this, "Lanc33c.t3d", Lanc33[2], 99)) || !(Lanc33[3] = t3dLoadCharacter(*this, "Lanc33d.t3d", Lanc33[3], 99))) {
warning("Error loading Lanc33");
return false;
}
warning("Reached loop: %02X\n", 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\n", CharName[i + 1]);
if (!(Character[i + 1] = t3dLoadCharacter(*this, CharName[i + 1], Character[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;
if (!(t3dRxt = t3dLoadRoom(*this, "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 = t3dLoadRoom(*this, 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", Character[1], 99))) {
warning("Error loading Gopher1");
return false;
}
if (!(Character[2] = t3dLoadCharacter(*this, "Gopher2.t3d", Character[2], 99))) {
warning("Error loading Gopher2");
return false;
}
if (!(Character[3] = t3dLoadCharacter(*this, "Gopher3.t3d", Character[3], 99))) {
warning("Error loading Gopher3");
return false;
}
if (!(GopherMark[0] = t3dLoadCharacter(*this, "Mark1.t3d", GopherMark[0], 99))) {
warning("Error loading Mark1");
return false;
}
if (!(GopherMark[1] = t3dLoadCharacter(*this, "Mark2.t3d", GopherMark[1], 99))) {
warning("Error loading Mark2");
return false;
}
if (!(GopherMark[2] = t3dLoadCharacter(*this, "Mark3.t3d", GopherMark[2], 99))) {
warning("Error loading Mark3");
return false;
}
if (!(Palla50 = t3dLoadCharacter(*this, "Palla.t3d", Palla50, 99))) {
warning("Error loading Palla50");
return false;
}
if (!(Freccia50 = t3dLoadCharacter(*this, "Freccia.t3d", Freccia50, 99))) {
warning("Error loading Freccia50");
return false;
}
if (!(Explode50 = t3dLoadCharacter(*this, "Explode.t3d", Explode50, 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(&CameraDummy.Matrix);
t3dStartTime();
if (!t3dCurRoom->CameraTable.empty())
if (!(t3dCurCamera = PickCamera(t3dCurRoom, 0)))
t3dCurCamera = &t3dCurRoom->CameraTable[0];
if (t3dCurCamera) memcpy(&t3dIconCamera, t3dCurCamera, sizeof(t3dCAMERA));
SetCurPlayerPosTo_9x(_gameVars, init);
Player->Pos.y = Player->Mesh->Trasl.y = CurFloorY;
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() {
int32 i;
UpdateRoomVisibility(init);
for (i = 0; i < NumLoadedFiles; i++) {
if (LoadedFiles[i].b) {
HideRoomMeshes(init, LoadedFiles[i].b);
ApplyAllMeshModifiers(*this, LoadedFiles[i].b);
}
}
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\n");
char str[20];
int32 i;
auto windowInfo = _renderer->getScreenInfos();
if (bMiscLoaded) return;
/*
rClear( BACK_BUFFER, 0, 0, MainDx, MainDy, 0, 0, 0 );
rBlitScreenBuffer();
rShowFrame();
*/
if ((windowInfo.width >= 1024) || (windowInfo.height >= 768)) {
LoadFont(&StandardFont, "1024NlFont.fnt");
LoadFont(&ComputerFont, "1024ComputerFont.fnt");
LoadFont(&PDAFont, "1024PDAFont.fnt");
} else if ((windowInfo.width >= 800) || (windowInfo.height >= 600)) {
LoadFont(&StandardFont, "800NlFont.fnt");
LoadFont(&ComputerFont, "800ComputerFont.fnt");
LoadFont(&PDAFont, "800PDAFont.fnt");
} else if ((windowInfo.width >= 640) || (windowInfo.height >= 480)) {
LoadFont(&StandardFont, "640NlFont.fnt");
LoadFont(&ComputerFont, "640ComputerFont.fnt");
LoadFont(&PDAFont, "640PDAFont.fnt");
}
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++) {
sprintf(str, "I%0#3d.tga", i);
IconsPics[i] = LoadDDBitmap(*this, str, rSURFACESTRETCH);
}
bMiscLoaded = 1;
warning("LoadMisc Done\n");
}
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\n");
NextMessage(*this);
}
//}
}
}
void WGame::CleanUpAndPostQuit() {
uint16 i;
extern char *TextBucket;
gameOptions.save(workDirs);
warning("STUBBED CleanupAndPostQuit\n");
#if 0
if (CreditsNames) t3dFree(CreditsNames);
if (CreditsRoles) t3dFree(CreditsRoles);
if ((RoomInfo.tnum) && (RoomInfo.tnum != -1)) {
rReleaseBitmap(RoomInfo.tnum);
RoomInfo.tnum = 0;
}
CheckExtraLocalizationStrings(0);
for (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 (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
}
} // End of namespace Watchmaker

101
engines/watchmaker/game.h Normal file
View File

@ -0,0 +1,101 @@
/* 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/game_options.h"
#include "watchmaker/ll/ll_ffile.h"
#include "watchmaker/saveload.h"
#include "watchmaker/work_dirs.h"
namespace Watchmaker {
class sdl_wrapper;
class Renderer;
struct GameVars {
private:
int32 CurRoom;
public:
void setCurRoomId(int32 room) {
CurRoom = room;
}
int32 getCurRoomId() const {
return CurRoom;
}
};
class WGame {
bool g_bReady, g_bActive;
bool g_bSkipActive = false;
const char *CharName[32];
uint32 LoadChar;
public:
Common::RandomSource *_rnd;
Renderer *_renderer;
WorkDirs workDirs;
GameOptions gameOptions;
Init init;
sdl_wrapper *sdl;
GameVars _gameVars;
WGame();
~WGame();
SRoom &getCurRoom() {
return init.Room[_gameVars.getCurRoomId()];
}
Common::SharedPtr<Common::SeekableReadStream> resolveFile(const char *path, bool noFastFile = false);
void configLoaderFlags() {
// 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 (!(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();
};
} // End of namespace Watchmaker
#endif // WATCHMAKER_GAME_H

View 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

View 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\n");
#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

View File

@ -0,0 +1,205 @@
/* 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
struct SRect BigIconRect = { INV_MARG_DX + 30, INV_MARG_UP - 12, 775, 587/*INV_MARG_DOWN+10 */};
struct SRect UseIconRect = { 720, 517, 787, 587 };
struct SRect CloseInvRect = { 667, 13, 782, 73 };
struct SRect QuitGameRect = { 563, 13, 667, 73 };
struct SRect PlayerInvRect = { 22, 13, 200, 73 };
struct SRect InvSaveRect = { 223, 13, 284, 73 };
struct SRect InvLoadRect = { 332, 13, 401, 73 };
struct SRect InvOptionsRect = { 437, 13, 523, 73 };
struct SRect Inv1Up = { 3 + 16, 67 + 56, 3 + 28, 67 + 96 };
struct SRect Inv1Down = { 3 + 205, 67 + 411, 3 + 224, 67 + 444 };
struct SRect Diag2Up = { 768, 510, 797, 537 };
struct SRect Diag2Down = { 768, 568, 797, 595 };
struct SRect 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];
struct SDDBitmap DDBitmapsList[MAX_DD_BITMAPS];
struct SDDText DDTextsList[MAX_DD_TEXTS];
struct SDDText RendText[MAX_REND_TEXTS];
// 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;
struct SFont StandardFont;
struct SFont ComputerFont;
struct SFont PDAFont;
// 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 GameMessage[MAX_MESSAGES];
pqueue Game;
message *TheMessage;
message idlemessage = {EventClass::MC_IDLE, 0, MP_DEFAULT};
message quitgamemessage = {EventClass::MC_SYSTEM, ME_QUIT, MP_DEFAULT};
message supereventmessage;
uint8 SuperEventActivate;
// 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;
// INV VARS
t3dBODY *t3dIcons;
t3dMESH CameraDummy;
t3dCAMERA t3dIconCamera;
t3dM3X3F BigIconM;
// MOUSE VARS
char ObjectUnderCursor[MAX_STRING_LEN];
t3dV3F mPos;
// 3D MESH MODIFIER
struct SMeshModifier MMList[MAX_MODIFIED_MESH];
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

View File

@ -0,0 +1,265 @@
/* 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"
namespace Watchmaker {
#define MAX_PATH 256
// 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;
void loadFromStream(Common::SeekableReadStream &stream) {
warning("Init\n");
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 (int i = 0; i < _creditsNames.size(); i++) {
char *c = _creditsNames[i].name;
for (int k = 0; k < 32; k++, c++) {
(*c) ^= 0xA0;
}
}
for (int i = 0; i < _creditsRoles.size(); i++) {
char *c = _creditsRoles[i].role;
for (int k = 0; k < 48; k++, c++) {
(*c) ^= 0xC4;
}
}
}
};
// GAME RECT
extern struct SRect BigIconRect;
extern struct SRect UseIconRect;
extern struct SRect QuitGameRect;
extern struct SRect CloseInvRect;
extern struct SRect PlayerInvRect;
extern struct SRect InvSaveRect;
extern struct SRect InvLoadRect;
extern struct SRect InvOptionsRect;
extern struct SRect Inv1Up;
extern struct SRect Inv1Down;
extern struct SRect Diag2Up;
extern struct SRect Diag2Down;
extern struct SRect CallOtherPlayerRect;
extern struct SD3DRect D3DRectsList[];
extern struct SD3DTriangle D3DTrianglesList[];
extern struct SD3DBitmap D3DBitmapsList[];
extern struct SDDBitmap DDBitmapsList[];
extern struct SDDText DDTextsList[];
extern struct SDDText RendText[];
// 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;
extern struct SFont StandardFont;
extern struct SFont ComputerFont;
extern struct SFont PDAFont;
// 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
extern t3dBODY *t3dIcons;
extern t3dMESH CameraDummy;
extern t3dCAMERA t3dIconCamera;
extern t3dM3X3F BigIconM;
// MOUSE VARS
extern char ObjectUnderCursor[];
extern t3dV3F mPos;
extern struct SMeshModifier MMList[];
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 GameMessage[];
extern pqueue Game;
extern message *TheMessage;
extern message idlemessage;
extern message quitgamemessage;
extern message supereventmessage;
extern uint8 SuperEventActivate;
// 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];
} // End of namespace Watchmaker
#endif // WATCHMAKER_GLOBVAR_H

View File

@ -0,0 +1,127 @@
/* 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 <cstring>
#include <cstdio>
#define FORBIDDEN_SYMBOL_EXCEPTION_strcpy
#include "watchmaker/ll/ll_system.h"
#include "watchmaker/types.h"
#include "watchmaker/globvar.h"
#include "watchmaker/extraLS.h"
#include "watchmaker/init/nl_parse.h"
namespace Watchmaker {
char *TextBucket, cr = 0; //da rimpiazzare con la areatext allocata da fab
static char *CurText;
int SentenceNum = 1, SysSentNum = 1, TooltipSentNum = 1, ObjNameNum = 1, ExtraLSNum = 1;
int DlgItemNum = 1;
uint16 Credits_numRoles = 0;
uint16 Credits_numNames = 0;
/* -----------------24/08/00 9.31--------------------
* LoadExternalText
* --------------------------------------------------*/
int LoadExternalText(Init *init, char *et) {
char line[1000];
int len, num;
error("TODO: LoadExternalText");
#if 0
FILE *ff;
if (!et) return false;
if (et[0] == '\0') return true;
if ((ff = fopen(et, "rt")) == nullptr)
return false;
CurText = TextBucket;
memset(TextBucket, 0, TEXT_BUCKET_SIZE);
SentenceNum = SysSentNum = TooltipSentNum = ObjNameNum = ExtraLSNum = 1;
while ((fgets(line, 1000, ff)) != nullptr) {
if ((line[0] == '/') && (line[1] == '/')) continue;
if ((len = strlen(line)) > 260)
return ParseError("ExternalText: line too long! curlen %d (MAX 250)\n%s", line - 10, line);
if (len < 2) continue;
if (sscanf(&line[5], "%d", &num) < 1)
return ParseError("ExternalText: sentence number not found in line:\n%s", line);
switch (line[4]) {
case 's':
Sentence[num] = CurText;
SentenceNum ++;
break;
case 'y':
SysSent[num] = CurText;
SysSentNum ++;
break;
case 't':
TooltipSent[num] = CurText;
TooltipSentNum ++;
break;
case 'e':
ExtraLS[num] = CurText;
ExtraLSNum ++;
break;
case 'n':
ObjName[num] = CurText;
ObjNameNum ++;
break;
case 'd':
break;
default:
return ParseError("ExternalText: unknown paramenters in line:\n%s", line);
}
if ((len - 10 - 1) > 0) {
memcpy(CurText, &line[10], len - 10 - 1);
switch (line[4]) {
case 'd':
strcpy(init->Room[num].desc, CurText);
break;
}
CurText += (len - 10);
} else {
switch (line[4]) {
case 'd':
strcpy(init->Room[num].desc, "");
break;
}
CurText ++;
}
}
fclose(ff);
#endif
return true;
}
} // End of namespace Watchmaker

View File

@ -0,0 +1,31 @@
/* 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);
} // End of namespace Watchmaker
#endif // WATCHMAKER_NL_INIT_H

View 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/>.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_vsprintf
#include "watchmaker/init/nl_parse.h"
#include "common/stream.h"
#include "common/textconsole.h"
#include <cstdarg>
namespace Watchmaker {
unsigned int jStringLimit = J_MAXSTRLEN, jTillEOL = 0, jUsingComments = 0;
unsigned int nlLineCounter;
char nlCurFileName[200];
static Common::SeekableReadStream *nlCurFile;
// PELS: supporto per il parsing dei .nl **********************************
static void (*ErrorFunc)(void) = nullptr;
int ParseError(const char *ln, ...) {
char err[J_MAXSTRLEN];
va_list ap;
if (ErrorFunc)
ErrorFunc();
va_start(ap, ln);
vsprintf(err, ln, ap);
va_end(ap);
warning("%s,%d: %s", nlCurFileName, nlLineCounter, err);
return 0;
}
} // End of namespace Watchmaker

View 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_NL_PARSE_H
#define WATCHMAKER_NL_PARSE_H
#define J_MAXSTRLEN 512L
namespace Watchmaker {
int ParseError(const char *ln, ...);
} // End of namespace Watchmaker
#endif // WATCHMAKER_NL_PARSE_H

File diff suppressed because it is too large Load Diff

View 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_LL_ANIM_H
#define WATCHMAKER_LL_ANIM_H
#include "watchmaker/types.h"
#include "watchmaker/work_dirs.h"
#include "watchmaker/globvar.h"
#include "watchmaker/game.h"
namespace Watchmaker {
void StopObjAnim(WGame &game, int32 obj);
bool CheckAndLoadMoglieSupervisoreModel(WorkDirs &workDirs, int32 c);
void StartAnim(WGame &game, int32 an);
void StopAnim(WGame &game, int32 an);
void PauseAnim(Init &init, int32 an);
void ContinueAnim(Init &init, int32 an);
void StopAllAnims(Init &init);
void StopPlayingGame(WGame &game);
void ProcessATF(WGame &game, int32 an, int32 atf);
void ProcessATFDO(WGame &game, int32 in);
void ProcessAnims(WGame &game);
} // End of namespace Watchmaker
#endif // WATCHMAKER_LL_ANIM_H

View File

@ -0,0 +1,521 @@
/* 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/game.h"
#include "watchmaker/ll/ll_diary.h"
#include "watchmaker/ll/ll_util.h"
#include "watchmaker/3d/geometry.h"
#include "watchmaker/ll/ll_mesh.h"
#include "watchmaker/windows_hacks.h"
#include "watchmaker/define.h"
#include "watchmaker/ll/ll_system.h"
#include "watchmaker/walk/act.h"
#include "watchmaker/ll/ll_anim.h"
#include "watchmaker/3d/animation.h"
namespace Watchmaker {
char bDiariesStoppedByTimeInc = 0;
/* -----------------26/11/1999 16.19-----------------
* StartDiary
* --------------------------------------------------*/
void StartDiary(WGame &game, int32 room, t3dV3F *pos) {
struct SDiary *d, *l;
int32 tot_rand, cur_rand;
int32 i, j, ca;
t3dF32 acceptable_dist;
char special_flag;
uint8 cr;
Init &init = game.init;
if (t3dCurRoom) cr = (uint8)getRoomFromStr(init, t3dCurRoom->name);
else cr = rNULL;
if (bDisableDiary) return ;
// DebugLogFile( "Parto Diario per room %d", room );
for (i = 0, d = &init.Diary[0]; i < MAX_DIARIES; i++, d++) {
if ((d->room != room) || (t3dCurTime < d->startt) || (d->endt && (t3dCurTime >= d->endt))) continue;
if (d->item[d->cur].on) continue;
if ((Character[d->obj]) && (Character[d->obj]->Flags & T3D_CHARACTER_DIARYDISABLE)) continue;
if (init.Dialog[CurDialog].obj == d->obj) continue; //se e' attivo un dialogo e si cerca di far partire il diario del personaggio che sta' gia' parlando
for (j = 0, l = &init.Diary[0]; j < MAX_DIARIES; j++, l++)
if ((l->obj == d->obj) && (l->item[l->cur].on))
break;
if (j < MAX_DIARIES) continue;
if (cr != rNULL) {
//se un diario e' fuori ma l'omino e' dentro non lo faccio partire
if ((d->room == rXT) && (cr != rXT)) {
DebugLogWindow("Skippato diario %d in rXT: obj %d room %d", i, d->obj, d->room);
continue;
}
//se il diario e' nella r13 ma non siamo nella r13 skippo
if ((d->room == r13) && (cr != r13)) {
DebugLogWindow("Skippato diario %d in r13: obj %d room %d", i, d->obj, d->room);
continue;
}
}
// if( i==36)
// DebugLogFile("START36 d->startt %d, d->endt %d, d->obj %d",d->startt,d->endt,d->obj);
// DebugLogFile( "Diario valido num %d", i );
// da usare per quei personaggi che, tra un diario e il successivo, cambiano posizione (sempre nel caso che un dialogo/rtv abbia incrementato il tempo e fatto cosi' switchare il diario)
special_flag = 0;
if (bDiariesStoppedByTimeInc && (d->obj == ocSERVETTA)) special_flag = 1;
acceptable_dist = 40000.0f;
// la servetta ha bisogno di piu' spazio vista la disposizione delle luci di posizione dei dialoghi e dei background
if (d->obj == ocSERVETTA) acceptable_dist = 200000.0f;
// quando il sup non c'<27> noi possiamo rubare la foto e quindi il portafoto diventa vuoto. Quando lui torna dobbiamo fare in modo che il portafoto sia rovesciato
if ((d->obj == ocSUPERVISORE) && (d->room == r29) && (init.Obj[o29PORTAFOTOVUOTO].flags & ON) && (!(init.Obj[o29PORTAFOTOROVESCIATO].flags & ON))) {
init.Obj[o29PORTAFOTOVUOTO].flags &= ~ON;
UpdateObjMesh(init, o29PORTAFOTOVUOTO);
init.Obj[o29PORTAFOTOROVESCIATO].flags |= ON;
UpdateObjMesh(init, o29PORTAFOTOROVESCIATO);
}
// la domestica ha bisogno di piu' spazio in questa circostanza vista la disposizione delle luci di posizione dei dialoghi e dei background
if ((d->obj == ocDOMESTICA) && ((d->room == r22) || (d->room == r26) || (d->room == r28))) acceptable_dist = 200000.0f;
tot_rand = 0;
for (j = 0; j < MAX_ANIMS_PER_DIARY_ITEM; j++)
if ((special_flag) || (pos == nullptr) || ((d->item[j].anim[0]) && (CompareLightPosition((char *) init.Anim[d->item[j].anim[0]].RoomName.rawArray(), init.Anim[d->item[j].anim[0]].pos, pos, acceptable_dist))))
tot_rand += d->item[j].rand;
if (!tot_rand) continue;
game._rnd->setSeed((unsigned)t3dReadTime());
cur_rand = game._rnd->getRandomNumber(tot_rand - 1);
// DebugLogFile( "Random %d (%d)", cur_rand, tot_rand );
tot_rand = 0;
for (j = 0; j < MAX_ANIMS_PER_DIARY_ITEM; j++) {
if ((special_flag) || (pos == nullptr) || ((d->item[j].anim[0]) && (CompareLightPosition((char *) init.Anim[d->item[j].anim[0]].RoomName.rawArray(), init.Anim[d->item[j].anim[0]].pos, pos, acceptable_dist)))) {
tot_rand += d->item[j].rand;
// DebugLogFile( "%d: %d (%d)", j, cur_rand, tot_rand );
if (cur_rand < tot_rand)
break;
}
}
if (!(ca = d->item[j].anim[0]) || init.Anim[ca].active)
continue;
// DebugLogFile( "Parte anim %d char %d pos %d", ca, d->obj, Anim[ca].pos );
Character[d->obj]->Flags &= ~T3D_CHARACTER_HIDE;
d->cur = j;
d->item[d->cur].on = TRUE;
d->item[d->cur].cur = 0;
d->item[d->cur].loopc = 0;
if (d->end_hideobj) d->end_hideobj |= 0x8000; //se ha un oggetto assegnato setto anche il flag piu' alto
init.Anim[ca].flags |= ANIM_DIARY;
if ((d->item[d->cur].bnd < 255) && !(bPlayerSuBasamento && (d->room == rXT))) {
d->item[d->cur].saved_bnd = GetBndLevel((char *) init.Anim[ca].RoomName.rawArray());
SetBndLevel(init, (char *)init.Anim[ca].RoomName.rawArray(), d->item[d->cur].bnd);
} else d->item[d->cur].saved_bnd = 255;
if (d->obj) CharSetPosition(d->obj, init.Anim[ca].pos, (char *)init.Anim[ca].RoomName.rawArray());
StartAnim(game, ca);
}
bDiariesStoppedByTimeInc = 0;
// Fa partire animazione di stand dell'altro personaggio
i = (CurPlayer ^ 1);
if ((Character[i + ocDARRELL]->Flags & T3D_CHARACTER_HIDE) && (PlayerStand[i].cr == room)) {
Character[i + ocDARRELL]->Flags &= ~T3D_CHARACTER_HIDE;
// CharSetPosition( i+ocDARRELL, Anim[PlayerStand[i].an].pos, PlayerStand[i].RoomName );
CharSetPosition(i + ocDARRELL, PlayerStand[i].pos, PlayerStand[i].roomName.c_str());
StartAnim(game, PlayerStand[i].an);
}
}
/* -----------------26/11/1999 16.39-----------------
* StopDiary
* --------------------------------------------------*/
void StopDiary(WGame &game, int32 room, int32 obj, uint8 only_overtime) {
struct SDiary *d;
int32 i, an;
char is_overtime;
uint8 cr;
Init &init = game.init;
if (t3dCurRoom) cr = (uint8)getRoomFromStr(init, t3dCurRoom->name);
else cr = rNULL;
// DebugLogFile( "Finisco Diario per room %d", room );
for (i = 0, d = &init.Diary[0]; i < MAX_DIARIES; i++, d++) {
if (obj && (obj != d->obj)) continue;
if ((room > 0) && (d->room != room)) continue;
if ((room < 0) && (room == cr)) continue;
is_overtime = (t3dCurTime < d->startt) || ((d->endt != 0) && (t3dCurTime >= d->endt));
if (only_overtime && (!is_overtime)) continue;
if (is_overtime && (d->end_hideobj & 0x8000)) { //se ha il bit settato significa che aveva un oggetto da nascondere e il diario era stato lanciato almeno una volta
d->end_hideobj &= 0x7FFF; //rimuovo l'ultimo bit
DebugLogFile("!! EndAnim !! per obj %d (%s)", d->end_hideobj, Character[d->obj]->Mesh->name.c_str());
init.Obj[d->end_hideobj].flags &= ~ON;
UpdateObjMesh(init, d->end_hideobj);
d->end_hideobj = 0;
//caso particolare dello sportello del bagno
if ((d->room == r2M) && (d->obj == ocCUSTODE)) {
init.Obj[o2MOGGETTICUSTODE_TOHIDE].flags |= ON;
UpdateObjMesh(init, o2MOGGETTICUSTODE_TOHIDE);
}
//casi particolari delle porte dei diari della servetta
if (i == eSERVETTA1) {
init.Obj[o2CMEGABB_2R].flags &= ~ON;
UpdateObjMesh(init, o2CMEGABB_2R);
// stanze in cui la r2C e la r2R sono caricate
if ((cr == r2C) || (cr == r2F) || (cr == r15) || (cr == r2E) || (cr == r2R) || (cr == r2T) || (cr == r2S) || (cr == r31)) {
t3dResetMesh(LinkMeshToStr(init, "o2c-portacamere02"));
t3dResetMesh(LinkMeshToStr(init, "o2r-portacamere2c01"));
}
}
if (i == eSERVETTA2) {
init.Obj[o2CMEGABB_2S].flags &= ~ON;
UpdateObjMesh(init, o2CMEGABB_2S);
// stanze in cui la r2C e la r2R sono caricate
if ((cr == r2C) || (cr == r2F) || (cr == r15) || (cr == r2E) || (cr == r2R) || (cr == r2T) || (cr == r2S) || (cr == r31)) {
t3dResetMesh(LinkMeshToStr(init, "o2c-portacamere06"));
t3dResetMesh(LinkMeshToStr(init, "o2s-portacamere01"));
}
}
if (i == eSERVETTA4) {
init.Obj[o2PMEGABB_2D].flags &= ~ON;
UpdateObjMesh(init, o2PMEGABB_2D);
// stanze in cui la r2P e la r2D sono caricate
if ((cr == r27) || (cr == r2P) || (cr == r2D)) {
t3dResetMesh(LinkMeshToStr(init, "o2p-portasup"));
t3dResetMesh(LinkMeshToStr(init, "o2d-portasup"));
}
}
}//end_hideobj
// da mettere dopo "end_hideobj", perche' anche se il diario non e' attivo gli oggetti li devo spegnere lo stesso
if (!d->item[d->cur].on) continue;
an = d->item[d->cur].anim[d->item[d->cur].cur];
init.Anim[an].flags &= ~ANIM_DIARY;
StopAnim(game, an);
if ((d->item[d->cur].saved_bnd < 255)) {
if (!(bPlayerSuBasamento && (d->room == rXT)))
SetBndLevel(init, (char *)init.Anim[an].RoomName.rawArray(), d->item[d->cur].saved_bnd);
d->item[d->cur].saved_bnd = 255;
}
Character[d->obj]->Flags |= T3D_CHARACTER_HIDE;
// DebugLogWindow("%s HIDEEEEEEEE: Flags %d",Character[d->obj]->Mesh->Name,Character[d->obj]->Flags);
d->item[d->cur].on = FALSE;
d->item[d->cur].loopc = 0;
d->item[d->cur].cur = 0;
d->cur = 0;
}
// Termina animazione di stand dell'altro personaggio
if (!obj) {
i = (CurPlayer ^ 1);
if (!(Character[i + ocDARRELL]->Flags & T3D_CHARACTER_HIDE) && (PlayerStand[i].cr == room)) {
StopObjAnim(game, i + ocDARRELL);
Character[i + ocDARRELL]->Flags |= T3D_CHARACTER_HIDE;
}
}
}
/* -----------------26/11/1999 16.49-----------------
* ContinueDiary
* --------------------------------------------------*/
void ContinueDiary(WGame &game, int32 an) {
struct SDiary *d;
int32 i, ca, pos;
Init &init = game.init;
// DebugLogFile( "Continuo Diario per anim %d", an );
pos = -1;
for (i = 0, d = &init.Diary[0]; i < MAX_DIARIES; i++, d++) {
if ((!d->item[d->cur].on) || (d->item[d->cur].anim[d->item[d->cur].cur] != an)) continue;
pos = init.Anim[an].pos;
d->item[d->cur].cur ++;
if (!(ca = d->item[d->cur].anim[d->item[d->cur].cur]) || init.Anim[ca].active) {
if ((!d->item[d->cur].loop) || !(ca = d->item[d->cur].anim[0]) || init.Anim[ca].active ||
((d->item[d->cur].loop > 0) && ((d->item[d->cur].loopc + 1) >= d->item[d->cur].loop))) {
if (!d->item[d->cur].anim[d->item[d->cur].cur])
d->item[d->cur].cur --; //altrimenti quando stoppo il tutto becca un item vuoto
StopDiary(game, d->room, d->obj, 0);
/* d->item[d->cur].on = FALSE;
d->item[d->cur].cur = 0;
d->item[d->cur].loopc = 0;
d->cur = 0;*/
if (Character[d->obj] && Character[d->obj]->Mesh)
StartDiary(game, d->room, &Character[d->obj]->Mesh->Trasl);
else
StartDiary(game, d->room, nullptr);
break;
} else {
if (d->item[d->cur].loop > 0) d->item[d->cur].loopc ++;
d->item[d->cur].cur = 0;
ca = d->item[d->cur].anim[d->item[d->cur].cur];
}
}
// DebugLogFile( "Parte anim %d char %d pos %d", ca, d->obj, Anim[ca].pos );
init.Anim[an].flags &= ~ANIM_DIARY;
init.Anim[ca].flags |= ANIM_DIARY;
CharSetPosition(d->obj, init.Anim[ca].pos, (char *)init.Anim[ca].RoomName.rawArray());
StartAnim(game, ca);
break;
}
}
/* -----------------29/05/00 16.57-------------------
* UpdateAllClocks
* --------------------------------------------------*/
void UpdateAllClocks(WGame &game) {
void t3dLoadOutdoorLights(const char *pname, t3dBODY * b, int32 ora);
char str[255];
t3dMESH *mesh;
Init &init = game.init;
const char *ClockMeshes[] = {
"o21-a-ore01",
"o21-a-minuti01",
"o24-a-ore01",
"o24-a-minuti01",
"o2p-ore01",
"o2p-minuti01",
"o2s-ore01",
"o2s-minuti01",
nullptr
};
const char *ClockAnims[] = {
"r21-a-orologio-ore.a3d",
"r21-a-orologio-minuti.a3d",
"r24-a-orologio-ore.a3d",
"r24-a-orologio-minuti.a3d",
"r2p-orologio-ore.a3d",
"r2p-orologio-minuti.a3d",
"r2s-orologio-ore.a3d",
"r2s-orologio-minuti.a3d",
nullptr
};
const char *ClockMeshes24[] = {
"o48-lancettaore",
"o48-lancettaore01",
nullptr
};
const char *ClockAnims24[] = {
"r48-ore.a3d",
"r48-minuti.a3d",
nullptr
};
int32 i, l[2];
l[0] = (t3dCurTime / 100) % 12;
l[1] = (t3dCurTime % 100) / 5;
if (!l[0]) l[0] = 12;
if (!l[1]) l[1] = 12;
// DebugLogWindow("%d: %d %d",t3dCurTime,l[0],l[1]);
for (i = 0;; i++) {
if (ClockMeshes[i] == nullptr) break;
if ((mesh = LinkMeshToStr(init, ClockMeshes[i])) == nullptr) continue;
t3dSetSpecialAnimFrame(game, ClockAnims[i], mesh, l[i % 2]);
}
//orologio a 24ore (avanti di un'ora)
l[0] = ((t3dCurTime + 100) / 100) % 24;
l[1] = (t3dCurTime % 100) / 5;
if (!l[0]) l[0] = 24;
if (!l[1]) l[1] = 12;
for (i = 0;; i++) {
if (ClockMeshes24[i] == nullptr) break;
if ((mesh = LinkMeshToStr(init, ClockMeshes24[i])) == nullptr) continue;
t3dSetSpecialAnimFrame(game, ClockAnims24[i], mesh, l[i % 2]);
}
strcpy(str, game.workDirs._lightmapsDir.c_str());
strcat(str, "rxt.t3d");
if (t3dRxt)
t3dLoadOutdoorLights(str, t3dRxt, t3dCurTime);
}
/* -----------------22/05/00 10.03-------------------
* IncCurTime
* --------------------------------------------------*/
void IncCurTime(WGame &game, int32 inc) {
int32 h, m;
Init &init = game.init;
t3dCurTime += inc;
h = (t3dCurTime / 100);
m = (t3dCurTime % 100);
while (m >= 60) {
m -= 60;
h ++;
}
t3dCurTime = h * 100 + m;
UpdateAllClocks(game);
if (bDialogActive && (init.Dialog[CurDialog].obj == ocSERVETTA)) {
StopDiary(game, 0, init.Dialog[CurDialog].obj, 1);
bDiariesStoppedByTimeInc = 1;
}
// stoppo tutti i diari overtime di tutte le stanze esclusa la attuale
StopDiary(game, -1, 0, 1);
//la moglie del supervisore va in camera sua e non ci fa entrare in camera
if ((t3dCurTime >= 1700) && (t3dCurTime < 1720)) {
init.Obj[o2Pp2D].anim[CurPlayer] = a2P7;
init.Obj[o2Pp2D].anim[CurPlayer ^ 1] = a2P7;
init.Obj[o2Pp2D].pos = 2;
}
//il cuoco va a letto e noi non lo disturbiamo
if ((t3dCurTime >= 1430) && (t3dCurTime < 1450)) {
init.Obj[o2Cp2T].anim[CurPlayer] = a2C4_CUOCODORME;
init.Obj[o2Cp2T].anim[CurPlayer ^ 1] = a2C4_CUOCODORME;
}
//il cuoco si alza e ci lascia entrare nella r2t
if ((t3dCurTime >= 1715) && (t3dCurTime < 1735)) {
init.Obj[o2Cp2T].anim[CurPlayer] = a2C4;
init.Obj[o2Cp2T].anim[CurPlayer ^ 1] = a2C4;
}
//il supervisore ci da le foto
if ((t3dCurTime >= 1900) && !(init.Dialog[dR008].flags & DIALOG_DONE)) {
init.Obj[o2Qp29].anim[CurPlayer] = a2Q4b;
init.Obj[o2Qp29].anim[CurPlayer ^ 1] = a2Q4b;
}
//la domestica ci cazzia
if ((t3dCurTime >= 1715) && !(init.Dialog[dR015].flags & DIALOG_DONE)) {
init.Obj[o25p2Q].anim[CurPlayer] = a2513_DOM;
init.Obj[o25p2Q].anim[CurPlayer ^ 1] = a2513_DOM;
init.Obj[o25p24].anim[CurPlayer] = a2512_DOM;
init.Obj[o25p24].anim[CurPlayer ^ 1] = a2512_DOM;
init.Obj[oXT11p21].anim[CurPlayer] = a111_DOM;
init.Obj[oXT11p21].anim[CurPlayer ^ 1] = a111_DOM;
init.Obj[oXT1Ap22].anim[CurPlayer] = a1A4_DOM;
init.Obj[oXT1Ap22].anim[CurPlayer ^ 1] = a1A4_DOM;
}
}
/* -----------------22/05/00 10.03-------------------
* DecCurTime
* --------------------------------------------------*/
void DecCurTime(WGame &game, int32 dec) {
int32 h, m;
t3dCurTime -= dec;
h = (t3dCurTime / 100);
m = (t3dCurTime % 100);
while (m < 0) {
m += 60;
h --;
}
t3dCurTime = h * 100 + m;
UpdateAllClocks(game);
}
/* -----------------29/05/00 15.40-------------------
* SetCurTime
* --------------------------------------------------*/
void SetCurTime(WGame &game, int32 set) {
t3dCurTime = set;
UpdateAllClocks(game);
}
/* -----------------02/06/00 10.10-------------------
* WhichRoomChar
* --------------------------------------------------*/
int32 WhichRoomChar(Init &init, int32 ch) {
struct SDiary *d;
int32 i;
for (i = 0, d = &init.Diary[0]; i < MAX_DIARIES; i++, d++) {
if ((d->obj != ch) || (t3dCurTime < d->startt) || (d->endt && (t3dCurTime >= d->endt))) continue;
return d->room;
}
return rNULL;
}
/* -----------------02/06/00 10.26-------------------
* WhichAnimChar
* --------------------------------------------------*/
int32 WhichAnimChar(Init &init, int32 ch) {
struct SDiary *d;
int32 i;
for (i = 0, d = &init.Diary[0]; i < MAX_DIARIES; i++, d++) {
if ((d->obj != ch) || (t3dCurTime < d->startt) || (d->endt && (t3dCurTime >= d->endt))) continue;
if (!d->item[d->cur].on) continue;
return d->item[d->cur].anim[d->item[d->cur].cur];
}
return 0;
}
/* -----------------02/06/00 10.26-------------------
* WhichPosChar
* --------------------------------------------------*/
uint8 WhichPosChar(Init &init, int32 ch) {
struct SDiary *d;
int32 i;
for (i = 0, d = &init.Diary[0]; i < MAX_DIARIES; i++, d++) {
if ((d->obj != ch) || (t3dCurTime < d->startt) || (d->endt && (t3dCurTime >= d->endt))) continue;
if (!d->item[d->cur].on) continue;
return init.Anim[d->item[d->cur].anim[d->item[d->cur].cur]].pos;
}
return 0;
}
} // End of namespace Watchmaker

View 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_LL_DIARY_H
#define WATCHMAKER_LL_DIARY_H
#include "watchmaker/work_dirs.h"
#include "watchmaker/globvar.h"
#include "watchmaker/game.h"
namespace Watchmaker {
void UpdateAllClocks(WGame &game);
void StopDiary(WGame &game, int32 room, int32 obj, uint8 only_overtime);
void StartDiary(WGame &game, int32 room, t3dV3F *pos);
void IncCurTime(WGame &game, int32 inc);
void DecCurTime(WGame &game, int32 dec);
void SetCurTime(WGame &game, int32 set);
int32 WhichRoomChar(Init &init, int32 ch);
int32 WhichAnimChar(Init &init, int32 ch);
void ContinueDiary(WGame &game, int32 an);
} // End of namespace Watchmaker
#endif // WATCHMAKER_LL_DIARY_H

View 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 "watchmaker/ll/ll_ffile.h"
#include "ll_system.h"
#include <cstring>
namespace Watchmaker {
const int MAX_NAME_LEN = 52;
struct FileEntry {
Common::String name;
int32 offset;
int32 time;
int32 date;
};
FastFile::FastFile(const char *path) : _path(path) {
auto stream = openFile(path);
assert(stream);
_numFiles = stream->readUint32LE();
_files = new FileEntry[_numFiles] {};
_totalSize = stream->size();
for (int i = 0; i < _numFiles; i++) {
char name[MAX_NAME_LEN] = {};
stream->read(name, MAX_NAME_LEN);
_files[i].name = name;
_files[i].offset = stream->readUint32LE();
_files[i].time = stream->readUint32LE();
_files[i].date = stream->readUint32LE();
for (auto it = _files[i].name.begin(); it != _files[i].name.end(); ++it) {
if (*it == '\\') {
*it = '/';
}
}
}
}
Common::SharedPtr<Common::SeekableReadStream> FastFile::resolve(const char *filename) {
int index = -1;
//HACK
if (strlen(filename) >= 2 && filename[0] == '.' && filename[1] == '/') {
filename = filename + 2;
}
for (int i = 0; i < _numFiles; i++) {
if (_files[i].name.equalsIgnoreCase(filename)) {
index = i;
break;
}
}
if (index == -1) {
return nullptr;
}
auto entry = _files[index];
int size = 0;
if (index == _numFiles - 1) {
size = _totalSize - entry.offset;
} else {
size = _files[index + 1].offset - entry.offset;
}
auto stream = openFile(_path);
assert(stream);
stream->seek(SEEK_SET, entry.offset);
error("TODO: Substream-logic");
#if 0
stream->setSize(size);
stream->setStart(entry.offset);
#endif
return Common::SharedPtr<Common::SeekableReadStream>(stream);
}
} // End of namespace Watchmaker

View 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_LL_FFILE_H
#define WATCHMAKER_LL_FFILE_H
#include "common/ptr.h"
#include "common/stream.h"
namespace Watchmaker {
struct FileEntry;
class FastFile {
const char *_path = nullptr;
int _totalSize = 0;
public:
int _numFiles;
FileEntry *_files;
FastFile(const char *path);
Common::SharedPtr<Common::SeekableReadStream> resolve(const char *filename);
};
} // End of namespace Watchmaker
#endif // WATCHMAKER_LL_FFILE_H

View File

@ -0,0 +1,865 @@
/* 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 <cmath>
#include "watchmaker/ll/ll_mesh.h"
#include "watchmaker/types.h"
#include "watchmaker/t3d.h"
#include "watchmaker/3d/math/llmath.h"
#include "watchmaker/3d/geometry.h"
#include "watchmaker/windows_hacks.h"
#include "watchmaker/define.h"
#include "watchmaker/globvar.h"
#include "watchmaker/ll/ll_util.h"
#include "watchmaker/3d/animation.h"
#include "watchmaker/utils.h"
#include "watchmaker/ll/ll_mouse.h"
#include "watchmaker/walk/walkutil.h"
#include "watchmaker/walk/walk.h"
#include "watchmaker/ll/ll_system.h"
namespace Watchmaker {
// locals
struct t3dHEADMOVE {
t3dV3F OldPos, DestAng, CurAng;
};
t3dHEADMOVE HeadMove[T3D_MAX_CHARACTERS];
t3dF32 OldArrowLen, OldExplosionScale;
uint32 **SavedBodyLight;
uint8 LastLightChar, LastLightRoom;
/* -----------------14/04/99 18.24-------------------
* t3dUpdateArrow
* --------------------------------------------------*/
void t3dUpdateArrow(t3dMESH *m, t3dF32 len) {
uint32 i;
if (!m) return;
m->VBptr = m->VertexBuffer;
for (i = 0; i < m->NumVerts; i++)
if (fabs(m->VBptr[i].z) > 1.0f)
m->VBptr[i].z += (-len + OldArrowLen);
m->Flags |= T3D_MESH_UPDATEVB;
m->VBptr = nullptr;
OldArrowLen = len;
}
/* -----------------27/04/99 10.52-------------------
* t3dLightRoom
* --------------------------------------------------*/
void t3dLightRoom(Init &init, t3dBODY *b, t3dV3F *p, t3dF32 NearRange, t3dF32 FarRange, t3dF32 IperRange) {
uint32 i, j, k, rr, gg, bb, aa, cr, cb, cg, *sbl;
uint32 addr = 110;
uint32 addg = 95;
uint32 addb = 80;
t3dMESH *m;
t3dF32 dist;
t3dV3F tmp;
gVertex *gv;
if (!b || !p) return;
FarRange *= FarRange;
NearRange *= NearRange;
IperRange *= IperRange;
if (!SavedBodyLight) {
if (!(SavedBodyLight = (uint32 **)t3dMalloc(sizeof(uint32 *) * b->NumMeshes())))
return ;
m = &b->MeshTable[0];
for (j = 0; j < b->NumMeshes(); j++, m++) {
if (!m) continue;
if (!(SavedBodyLight[j] = (uint32 *)t3dMalloc(sizeof(uint32) * m->NumVerts * 4)))
continue;
gv = m->VBptr = m->VBptr = m->VertexBuffer;
for (i = 0; i < m->NumVerts; i++, gv++) {
SavedBodyLight[j][i * 4 + 0] = RGBA_GETRED(gv->diffuse);
SavedBodyLight[j][i * 4 + 1] = RGBA_GETGREEN(gv->diffuse);
SavedBodyLight[j][i * 4 + 2] = RGBA_GETBLUE(gv->diffuse);
SavedBodyLight[j][i * 4 + 3] = RGBA_GETALPHA(gv->diffuse);
}
m->VBptr = nullptr;
}
}
LastLightRoom = (LastLightRoom + 1) > 3 ? 0 : LastLightRoom + 1;
m = &b->MeshTable[0];
for (j = 0; j < b->NumMeshes(); j++, m++) {
if (!m) continue;
if (m->name.equalsIgnoreCase("p50-cielo") || m->name.equalsIgnoreCase("p50-stelle") || m->name.equalsIgnoreCase("p50-luna")) continue;
if (!(m->Flags & T3D_MESH_VISIBLE) && !(m->Flags & T3D_MESH_HIDDEN)) {
m->Flags &= ~T3D_MESH_HIDDEN;
continue;
}
m->Flags &= ~T3D_MESH_HIDDEN;
// if( (j%4) != LastLightRoom ) continue;
sbl = (uint32 *)&SavedBodyLight[j][0];
for (k = 0; k < MAX_OBJ_MESHLINKS ; k++) {
if (((init.Obj[oNEXTPORTAL].meshlink[k][0] != '\0') && (m->name.equalsIgnoreCase((const char *)init.Obj[oNEXTPORTAL].meshlink[k]))) ||
m->name.equalsIgnoreCase("p50-sentierini01") || m->name.equalsIgnoreCase("p50-sentierini02") || m->name.equalsIgnoreCase("p50-sentierini03") ||
m->name.equalsIgnoreCase("p50-sentierini04") || m->name.equalsIgnoreCase("p50-sentierini05") || m->name.equalsIgnoreCase("p50-sentierini06")) {
tmp.x = m->Pos.x - p->x;
tmp.z = m->Pos.z - p->z;
gv = m->VBptr = m->VBptr = m->VertexBuffer;
if ((dist = tmp.x * tmp.x + tmp.z * tmp.z) > (FarRange + m->Radius * m->Radius * 1.3f)) {
if ((bGolfMode == 0) || (bGolfMode == 1))
if (dist > (FarRange + m->Radius * m->Radius) * 2.5f) m->Flags |= T3D_MESH_HIDDEN;
for (i = 0; i < m->NumVerts; i++, gv++) {
rr = *sbl++;
gg = *sbl++;
bb = *sbl++;
aa = *sbl++;
gv->diffuse = RGBA_MAKE(rr, gg, bb, aa);
}
} else {
for (i = 0; i < m->NumVerts; i++, gv++) {
tmp.x = gv->x - p->x;
tmp.z = gv->z - p->z;
if ((dist = tmp.x * tmp.x + tmp.z * tmp.z) < IperRange) {
rr = *sbl++ + addr * 2;
gg = *sbl++ + addg * 2;
bb = *sbl++ + addb * 2;
} else if (dist < NearRange) {
rr = *sbl++ + addr;
gg = *sbl++ + addg;
bb = *sbl++ + addb;
} else if (dist < FarRange) {
dist = 1.0f - (dist - NearRange) / (FarRange - NearRange);
rr = *sbl++ + (uint32)((t3dF32)(addr) * dist);
gg = *sbl++ + (uint32)((t3dF32)(addg) * dist);
bb = *sbl++ + (uint32)((t3dF32)(addb) * dist);
} else {
rr = *sbl++;
gg = *sbl++;
bb = *sbl++;
}
aa = *sbl++;
if (rr > 255) rr = 255;
if (gg > 255) gg = 255;
if (bb > 255) bb = 255;
gv->diffuse = RGBA_MAKE(rr, gg, bb, aa);
}
}
m->Flags |= T3D_MESH_UPDATEVB;
m->VBptr = nullptr;
break;
}
}
if (k < MAX_OBJ_MESHLINKS) continue;
tmp.x = m->Pos.x - p->x + m->Trasl.x;
tmp.z = m->Pos.z - p->z + m->Trasl.z;
if ((dist = tmp.x * tmp.x + tmp.z * tmp.z) < IperRange) {
cr = addr * 2;
cg = addg * 2;
cb = addb * 2;
} else if (dist < NearRange) {
cr = addr;
cg = addg;
cb = addb;
} else if (dist < FarRange) {
dist = 1.0f - (dist - NearRange) / (FarRange - NearRange);
cr = (uint32)((t3dF32)(addr) * dist);
cg = (uint32)((t3dF32)(addg) * dist);
cb = (uint32)((t3dF32)(addb) * dist);
} else {
if ((bGolfMode == 0) || (bGolfMode == 1))
if (dist > (FarRange + m->Radius * m->Radius) * 2.5f) m->Flags |= T3D_MESH_HIDDEN;
cr = 0;
cg = 0;
cb = 0;
}
gv = m->VBptr = m->VBptr = m->VertexBuffer;
for (i = 0; i < m->NumVerts; i++, gv++) {
rr = cr + *sbl++;
gg = cg + *sbl++;
bb = cb + *sbl++;
aa = *sbl++;
if (rr > 255) rr = 255;
if (gg > 255) gg = 255;
if (bb > 255) bb = 255;
gv->diffuse = RGBA_MAKE(rr, gg, bb, aa);
}
m->Flags |= T3D_MESH_UPDATEVB;
m->VBptr = nullptr;
}
}
/* -----------------27/04/99 15.35-------------------
* t3dLightChar
* --------------------------------------------------*/
void t3dLightChar(t3dMESH *mesh, t3dV3F *p) {
int16 df;
uint32 j, rr, gg, bb, cr, cb, cg;
t3dF32 addr = 110 + 60;
t3dF32 addg = 95 + 75;
t3dF32 addb = 80 + 90;
t3dF32 nlight;
t3dV3F ppos, l, *normal;
gVertex *gv;
if (!mesh || !p) return;
#if 0
t3dVectAdd(&ppos, &mesh->Trasl, &mesh->Pos);
gv = mesh->VBptr = mesh->VertexBuffer;
cr = (t3dU32)t3dCurRoom->AmbientLight.x + 20;
cg = (t3dU32)t3dCurRoom->AmbientLight.y + 20;
cb = (t3dU32)t3dCurRoom->AmbientLight.z + 20;
df = RGBA_MAKE(cr, cg, cb, 255);
for (j = 0; j < mesh->NumVerts; j++, gv++)
gv->diffuse = df;
t3dVectSub(&l, p, &ppos);
t3dVectTransformInv(&l, &l, &mesh->Matrix);
t3dVectNormalize(&l);
gv = mesh->VBptr;
for (j = 0; j < mesh->NumVerts; j++, gv++) {
normal = &mesh->NList[j]->n;
nlight = t3dVectDot(normal, &l);
// if( (nlight=t3dVectDot(normal,&l)) >= 0 )
{
rr = cr + t3dFloatToInt((addr * nlight));
gg = cg + t3dFloatToInt((addg * nlight));
bb = cb + t3dFloatToInt((addb * nlight));
if (rr > 255) rr = 255;
if (gg > 255) gg = 255;
if (bb > 255) bb = 255;
gv->diffuse = RGBA_MAKE(rr, gg, bb, 255);
}
}
mesh->Flags |= T3D_MESH_UPDATEVB;
mesh->VBptr = nullptr;
#endif
}
/* -----------------12/04/99 12.11-------------------
* t3dVectMeshInters
* --------------------------------------------------*/
uint8 t3dVectMeshInters(t3dMESH *m, t3dV3F start, t3dV3F end, t3dV3F *inters) {
t3dV3F v1, v2, v3;
if (!m) return 0;
if (!t3dVectPlaneIntersection(inters, start, end, m->BBoxNormal[3])) return 0;
m->VBptr = m->VertexBuffer;
for (uint32 j = 0; j < m->NumFaces(); j++) {
t3dFACE &f = m->FList[j];
if (!f.n) continue;
v1.x = m->VBptr[f.VertexIndex[0]].x;
v1.y = m->VBptr[f.VertexIndex[0]].y;
v1.z = m->VBptr[f.VertexIndex[0]].z;
v2.x = m->VBptr[f.VertexIndex[1]].x;
v2.y = m->VBptr[f.VertexIndex[1]].y;
v2.z = m->VBptr[f.VertexIndex[1]].z;
v3.x = m->VBptr[f.VertexIndex[2]].x;
v3.y = m->VBptr[f.VertexIndex[2]].y;
v3.z = m->VBptr[f.VertexIndex[2]].z;
if (t3dVectTriangleIntersection(inters, start, end, v1, v2, v3, *f.n)) {
m->VBptr = nullptr;
return 1;
}
}
m->VBptr = nullptr;
return 0;
}
/* -----------------19/05/00 12.43-------------------
* t3dMoveAndCheck1stCamera
* --------------------------------------------------*/
bool t3dMoveAndCheck1stCamera( t3dBODY *rr, t3dCAMERA *cc, t3dV3F *mm )
{
t3dWALK *w;
t3dV3F tmp;
int32 i,j;
if ( !Character[ocCURPLAYER] ) return FALSE;
w=&Character[ocCURPLAYER]->Walk;
t3dVectAdd( &tmp, &cc->Source, mm );
// Controlla che non sia dentro un Bounding Box
for ( i=0; i<(int32)rr->NumMeshes(); i++ )
{
t3dMESH &mesh = rr->MeshTable[i];
if( !( mesh.Flags & T3D_MESH_HIDDEN ) )
{
// Se il punto di destinazione e' dentro il bound box (allargato dell'altezza del ginocchio)
for ( j=0; j<6; j++ )
if( t3dVectPlaneDistance( tmp, mesh.BBoxNormal[j] ) < -KNEE_HEIGHT )
break;
if ( j >= 6 )
{
// Prima controlla che non sia dentro i bounds
for ( j=0; j<w->PanelNum; j++ )
{
if ( PointInside( ocCURPLAYER, j, (double)tmp.x, (double)tmp.z ) != 0 )
{
warning( "Inters %s", mesh.name.c_str() ); // TODO: Debug
return FALSE;
}
}
warning( "Saved by bounds" ); // TODO: Debug
}
}
}
// evito che si entri nell'altro personaggio giocante
i = (CurPlayer ^ 1);
if ( Character[i+ocDARRELL] && Character[i+ocDARRELL]->Mesh && t3dCurRoom->name.equalsIgnoreCase(PlayerStand[i].roomName ) ) // Used to be stricmp
{
t3dF32 d=t3dVectDistance( &tmp, &Character[i+ocDARRELL]->Mesh->Trasl );
if( d < 435.f ) return FALSE;
}
t3dVectAdd( &cc->Source, &cc->Source, mm );
t3dVectAdd( &cc->Target, &cc->Target, mm );
return TRUE;
}
/* -----------------03/05/99 15.24-------------------
* t3dClipToSurface
* --------------------------------------------------*/
uint8 t3dClipToSurface(Init &init, t3dV3F *pt) {
t3dV3F tmp, start, end;
int32 i;
t3dMESH *m;
t3dVectCopy(&start, pt);
start.y = 260000.0f;
t3dVectCopy(&end, pt);
end.y = -130000.0f;
for (i = 0; i < 6; i++) {
if ((m = LinkMeshToStr(init, (char *)init.Obj[oNEXTPORTAL].meshlink[i])) && (t3dVectMeshInters(m, start, end, &tmp))) {
pt->y = tmp.y;
return true;
}
}
return false;
}
/* -----------------03/05/99 16.44-------------------
* t3dUpdateExplosion
* --------------------------------------------------*/
void t3dUpdateExplosion(t3dMESH *m, t3dF32 scale) {
// t3dU32 i;
if (!m) return;
m->Matrix.M[0] = scale;
m->Matrix.M[4] = scale;
m->Matrix.M[8] = scale;
/* m->VBptr=m->VertexBuffer;
for (i=0; i<m->NumVerts; i++ )
{
m->VBptr[i].x *= (scale/OldExplosionScale);
m->VBptr[i].y *= (scale/OldExplosionScale);
m->VBptr[i].z *= (scale/OldExplosionScale);
}
m->Flags |= T3D_MESH_UPDATEVB;
m->VBptr = NULL;
*/
OldExplosionScale = scale;
}
/* -----------------03/09/98 17.42-------------------
* UpdateBoundingBox
* --------------------------------------------------*/
void UpdateBoundingBox(t3dMESH *mesh) {
t3dBONEANIM *db;
t3dBONE *bone;
t3dV3F Appov;
int32 i, frame;
if (!mesh || (mesh->Flags & T3D_MESH_NOBOUNDBOX))return;
// DebugFile("Update Bounding Box %s",mesh->Name);
if (mesh->Flags & T3D_MESH_DEFAULTANIM)
db = &mesh->DefaultAnim;
else
db = &mesh->Anim;
frame = mesh->CurFrame;
bone = db->BoneTable;
for (i = 0; i < db->NumBones; i++, bone++) {
if (!bone || !bone->Trasl || !bone->Matrix || (bone->ModVertices.size() > mesh->NumVerts)) continue;
if ((!bone->ModVertices.empty()) && !(mesh->Flags & T3D_MESH_CHARACTER)) {
for (i = 0; i < 8; i++) {
t3dVectSub(&Appov, &mesh->BBox[i].p, &bone->Trasl[1]);
t3dVectTransform(&Appov, &Appov, &bone->Matrix[1]);
t3dVectTransformInv(&Appov, &Appov, &bone->Matrix[frame]);
t3dVectAdd(&mesh->BBox[i].p, &Appov, &bone->Trasl[frame]);
}
t3dPlaneNormal(&mesh->BBoxNormal[0], &mesh->BBox[0].p, &mesh->BBox[2].p, &mesh->BBox[1].p); //front
t3dPlaneNormal(&mesh->BBoxNormal[1], &mesh->BBox[4].p, &mesh->BBox[5].p, &mesh->BBox[6].p); //back
t3dPlaneNormal(&mesh->BBoxNormal[2], &mesh->BBox[4].p, &mesh->BBox[0].p, &mesh->BBox[5].p); //Up
t3dPlaneNormal(&mesh->BBoxNormal[3], &mesh->BBox[6].p, &mesh->BBox[7].p, &mesh->BBox[2].p); //Down
t3dPlaneNormal(&mesh->BBoxNormal[4], &mesh->BBox[4].p, &mesh->BBox[6].p, &mesh->BBox[0].p); //Left
t3dPlaneNormal(&mesh->BBoxNormal[5], &mesh->BBox[5].p, &mesh->BBox[1].p, &mesh->BBox[7].p); //Right
return ;
}
}
}
/* -----------------08/06/00 14.51-------------------
* t3dSetSpecialAnimFrame
* --------------------------------------------------*/
bool t3dSetSpecialAnimFrame(WGame &game, const char *name, t3dMESH *mesh, int32 nf) {
if (!name || !mesh)
return false;
if (t3dLoadAnimation(game, name, mesh, T3D_MESH_DEFAULTANIM) <= 0)
return false;
mesh->Flags |= (T3D_MESH_ABS_ANIM | T3D_MESH_DEFAULTANIM);
FixupAnim(mesh, 0, "");
if (nf < 0) nf = mesh->DefaultAnim.NumFrames - 1;
mesh->CurFrame = nf;
mesh->LastFrame = -1;
mesh->BlendPercent = 255;
mesh->LastBlendPercent = 0;
return true;
}
/* -----------------15/09/98 12.23-------------------
* ModifyMesh
* --------------------------------------------------*/
void ModifyMesh(WGame &game, t3dMESH *mesh) {
struct SMeshModifier *mm;
int16 i;
if (!mesh || (mesh->Flags & T3D_MESH_CHARACTER)) return;
// Cerca se esite un modificatore per questa mesh
mm = &MMList[0];
for (i = 0; i < MAX_MODIFIED_MESH; i++, mm++)
if ((!mm->meshName.empty()) && (mm->meshName.equalsIgnoreCase(mesh->name)))
break;
// Se non ci sono modificatori per questa mesh o si rifericono a un body
if ((i >= MAX_MODIFIED_MESH) || (mm->Flags & (MM_SET_BND_LEVEL | MM_SET_HALOES)))
return ;
warning("MM %s: addflags %X, removeflags %X, anim |%s|", mesh->name.c_str(), mm->AddFlags, mm->RemoveFlags, mm->animName.c_str());
// Aggiorna Flags
if (mm->Flags & MM_REMOVE_FLAGS)
mesh->Flags &= ~mm->RemoveFlags;
if (mm->Flags & MM_ADD_FLAGS)
mesh->Flags |= mm->AddFlags;
// Aggiorna Materiali
if (mm->Flags & MM_REMOVE_MAT_FLAGS)
mesh->FList[0].mat->Flags &= ~mm->RemoveMatFlags;
if (mm->Flags & MM_ADD_MAT_FLAGS)
mesh->FList[0].mat->Flags |= mm->AddMatFlags;
if (mm->Flags & MM_SET_MAT_FRAME)
rSetMovieFrame(mesh->FList[0].mat, mm->MatFrame);
// Aggiorna Anim
if ((mm->Flags & MM_ANIM_BLOCK) && (!mm->animName.empty()) && (!mesh->CurFrame)) {
t3dSetSpecialAnimFrame(game, mm->animName.c_str(), mesh, -1);
t3dCalcMeshBones(mesh, 1);
UpdateBoundingBox(mesh);
}
}
/* -----------------22/06/00 10.35-------------------
* ApplyAllMeshModifiers
* --------------------------------------------------*/
void ApplyAllMeshModifiers(WGame &game, t3dBODY *b) {
// Cerca se esite un modificatore per questo body
struct SMeshModifier *mm = &MMList[0];
for (int32 j = 0; j < MAX_MODIFIED_MESH; j++, mm++)
if ((!mm->meshName.empty()) && b->name.equalsIgnoreCase(mm->meshName)) {
if (mm->Flags & MM_SET_BND_LEVEL)
b->CurLevel = mm->BndLevel;
if (mm->Flags & MM_SET_HALOES) {
for (auto &l : b->LightTable) {
if (!(l.Type & T3D_LIGHT_FLARE)) continue;
if (mm->HaloesStatus > 0)
l.Type |= T3D_LIGHT_LIGHTON;
else
l.Type &= ~T3D_LIGHT_LIGHTON;
}
}
}
for (int32 i = 0; i < (int32)b->NumMeshes(); i++)
ModifyMesh(game, &b->MeshTable[i]);
}
/* -----------------29/03/99 14.33-------------------
* HideRoomMeshes
* --------------------------------------------------*/
void HideRoomMeshes(Init &init, t3dBODY *body) {
int32 cr, c, a, b, i, j, k, h, skip;
char *str;
t3dMESH *m;
if (!(cr = getRoomFromStr(init, body->name))) return;
// DebugFile("Hiding Room %s (%d)",body->Name,cr);
for (a = 0; a < MAX_OBJS_IN_ROOM; a++) {
if (!(c = init.Room[cr].objects[a])) continue;
if (init.Obj[c].flags & NOUPDATE) continue;
if (!(init.Obj[c].flags & ON) || (init.Obj[c].flags & HIDE)) {
for (b = 0; b < MAX_OBJ_MESHLINKS; b++) {
if (init.Obj[c].meshlink[b][0] == '\0') continue;
m = nullptr;
str = (char *)init.Obj[c].meshlink[b];
for (h = 0; h < (uint16)body->NumMeshes(); h++) {
if (body->MeshTable[h].name.equalsIgnoreCase(str)) {
m = &body->MeshTable[h];
break;
}
}
if (m == nullptr) continue;
// DebugFile("CandidateObj '%s'",Obj[c].meshlink[b]);
skip = 0;
for (i = 0; i < MAX_OBJS_IN_ROOM; i++) {
if (!(k = init.Room[cr].objects[i]) || (k == c)) continue;
if (!(init.Obj[k].flags & ON) || (init.Obj[k].flags & HIDE)) continue;
for (j = 0; j < MAX_OBJ_MESHLINKS; j++) {
if (init.Obj[k].meshlink[j][0] == '\0') continue;
if (!Common::String((char *)init.Obj[c].meshlink[b]).equalsIgnoreCase((char *)init.Obj[k].meshlink[j])) continue;
// DebugFile("Skipped for %d,%d",k,j);
skip ++;
break;
}
}
if (!skip && m) {
// DebugFile("Hiding Mesh %s",Obj[c].meshlink[b]);
m->Flags |= T3D_MESH_HIDDEN;
}
}
}
}
}
/* -----------------28/12/98 17.43-------------------
* UpdateCharHead
* --------------------------------------------------*/
void UpdateCharHead(int32 oc, t3dV3F *dir) {
t3dCHARACTER *Ch = Character[oc];
t3dMESH *mesh;
t3dHEADMOVE *t;
t3dBONE *bone;
t3dV3F tmp;
int32 i, cf;
t3dF32 s;
if (!Ch || !(mesh = Ch->Mesh) || mHide || !dir) return;
if ((bDialogActive) || (bT2DActive) || (InvStatus)) return;
if (oc == ocCURPLAYER) oc = ocDARRELL + CurPlayer;
t = &HeadMove[oc];
if ((Player->Mesh->CurFrame > ActionStart[aSTAND]) || !(Player->Mesh->Flags & T3D_MESH_DEFAULTANIM))
t3dVectFill(&t->DestAng, 0.0f);
else if (t->OldPos != *dir) {
t3dVectCopy(&tmp, &mesh->Trasl);
tmp.y = CurFloorY + EYES_HEIGHT;
t3dVectSub(&tmp, dir, &tmp);
t->DestAng.x = t3dVectAngle(&tmp, &Ch->Dir);
if (t->DestAng.x < -MAX_HEAD_ANGLE_X * 2) t->DestAng.x = -MAX_HEAD_ANGLE_X * 2;
if (t->DestAng.x > MAX_HEAD_ANGLE_X * 2) t->DestAng.x = MAX_HEAD_ANGLE_X * 2;
t->DestAng.y = -(t3dF32)asin((mPos.y - (CurFloorY + EYES_HEIGHT)) / t3dVectMod(&tmp)) * 180.0f / T3D_PI;
if (t->DestAng.y < -MAX_HEAD_ANGLE_Y / 2) t->DestAng.y = -MAX_HEAD_ANGLE_Y / 2;
if (t->DestAng.y > MAX_HEAD_ANGLE_Y / 2) t->DestAng.y = MAX_HEAD_ANGLE_Y / 2;
t->DestAng.z = 0.0f;
t3dVectCopy(&t->OldPos, dir);
}
if (t->DestAng != t->CurAng) {
Player->Mesh->LastFrame = 0;
if (Player->Mesh->Flags & T3D_MESH_DEFAULTANIM) {
if (Player->Mesh->CurFrame < ActionStart[aSTAND])
Player->Mesh->CurFrame = ActionStart[aSTAND];
cf = 1;
for (i = 1; i < Player->Mesh->DefaultAnim.NumBones; i++) {
if (!(bone = &Player->Mesh->DefaultAnim.BoneTable[i]) || !(bone->Trasl) || !(bone->Matrix))
continue;
t3dVectCopy(&bone->Trasl[cf], &bone->Trasl[Player->Mesh->CurFrame]);
t3dMatCopy(&bone->Matrix[cf], &bone->Matrix[Player->Mesh->CurFrame]);
}
bone = &Player->Mesh->DefaultAnim.BoneTable[12];
} else {
cf = Player->Mesh->CurFrame;
bone = &Player->Mesh->Anim.BoneTable[12];
}
if ((bone) && (bone->Trasl) && (bone->Matrix)) {
t3dVectSub(&tmp, &t->DestAng, &t->CurAng);
s = t3dVectMod(&tmp);
if (s > MAX_HEAD_SPEED) {
tmp.x *= (MAX_HEAD_SPEED / s);
tmp.y *= (MAX_HEAD_SPEED / s);
}
t->CurAng.x += tmp.x;
t->CurAng.y += tmp.y;
t->CurAng.z = 0.0f;
t3dMatRot(&bone->Matrix[cf], (t->CurAng.y * T3D_PI) / 180.0f, (t->CurAng.x * T3D_PI) / 180.0f, 0.0f);
bone->Matrix[cf].Flags &= ~T3D_MATRIX_IDENTITY;
// Player->Mesh->BlendPercent = 0;
Player->Mesh->CurFrame = cf;
}
}
// se siamo in un dialogo o RTV non gli faccio muovere la testolina
if (bDialogActive) {
t3dVectFill(&t->CurAng, 0.0f);
t3dVectFill(&t->DestAng, 0.0f);
t3dVectFill(&t->OldPos, 0.0f);
}
}
/* -----------------15/09/98 12.04-------------------
* AddMeshModifier
* --------------------------------------------------*/
void AddMeshModifier(const Common::String &name, int16 com, void *p) {
struct SMeshModifier *mm;
uint32 Flags;
int16 i;
warning("Not sure this is right"); // Used to check for nullptr, not 0 length.
if (name.empty() || !p) return;
// DebugLogFile("AddMM |%s| %d",name,com);
// Cerca se esiste gia' un modificatore per questa mesh
mm = &MMList[0];
for (i = 0; i < MAX_MODIFIED_MESH; i++, mm++)
if ((!mm->meshName.empty()) && mm->meshName.equalsIgnoreCase(name))
break;
// Se e' un nuovo modificatore cerca un posto libero
if (i >= MAX_MODIFIED_MESH) {
mm = &MMList[0];
for (i = 0; i < MAX_MODIFIED_MESH; i++, mm++)
if (mm->meshName.empty())
break;
if (i >= MAX_MODIFIED_MESH) {
warning("Troppi Mesh modifier per %s: MAX %d", name.c_str(), MAX_MODIFIED_MESH);
return ;
}
// memset( mm, 0, sizeof( struct SMeshModifier ) );
mm->meshName = name;
}
mm->Flags |= com;
switch (com) {
case MM_ADD_FLAGS:
Flags = *((uint32 *)p);
mm->RemoveFlags &= ~Flags;
mm->AddFlags |= Flags;
break;
case MM_REMOVE_FLAGS:
Flags = *((uint32 *)p);
mm->AddFlags &= ~Flags;
mm->RemoveFlags |= Flags;
break;
case MM_ADD_MAT_FLAGS:
Flags = *((uint32 *)p);
mm->RemoveMatFlags &= ~Flags;
mm->AddMatFlags |= Flags;
break;
case MM_REMOVE_MAT_FLAGS:
Flags = *((uint32 *)p);
mm->AddMatFlags &= ~Flags;
mm->RemoveMatFlags |= Flags;
break;
case MM_SET_MAT_FRAME:
mm->MatFrame = *((int32 *)p);
break;
case MM_ANIM_BLOCK:
if (mm->animName.empty())
mm->animName = (char*)p;
else
mm->animName.clear();
break;
case MM_SET_BND_LEVEL:
mm->BndLevel = *((uint16 *)p);
break;
case MM_SET_HALOES:
mm->HaloesStatus = *((int8 *)p);
break;
}
}
/* -----------------22/06/00 12.15-------------------
* ChangeMeshFlags
* --------------------------------------------------*/
void ChangeMeshFlags(t3dMESH *m, int8 add, uint32 newflags) {
if (!m) return;
if (add > 0) {
m->Flags |= newflags;
AddMeshModifier(m->name, MM_ADD_FLAGS, &newflags);
} else {
m->Flags &= ~newflags;
AddMeshModifier(m->name, MM_REMOVE_FLAGS, &newflags);
}
}
/* -----------------29/06/00 11.22-------------------
* ChangeHaloesStatus
* --------------------------------------------------*/
void ChangeHaloesStatus(t3dBODY *b, int8 op) {
if (b == nullptr) b = t3dCurRoom;
if (b == nullptr) return;
for (auto &l : b->LightTable) {
if (!(l.Type & T3D_LIGHT_FLARE)) continue;
if (op > 0)
l.Type |= T3D_LIGHT_LIGHTON;
else
l.Type &= ~T3D_LIGHT_LIGHTON;
}
AddMeshModifier(b->name.c_str(), MM_SET_HALOES, &op);
}
/* -----------------01/06/00 11.12-------------------
* UpdateObjMesh
* --------------------------------------------------*/
void UpdateObjMesh(Init &init, int32 in) {
t3dMESH *m;
int32 a;
if (init.Obj[in].flags & NOUPDATE) return;
for (a = 0; a < MAX_OBJ_MESHLINKS; a++) {
m = LinkMeshToStr(init, (char *)init.Obj[in].meshlink[a]);
if (m) {
if ((init.Obj[in].flags & ON) && !(init.Obj[in].flags & HIDE))
// m->Flags &= ~T3D_MESH_HIDDEN;
ChangeMeshFlags(m, -1, T3D_MESH_HIDDEN);
else
// m->Flags |= T3D_MESH_HIDDEN;
ChangeMeshFlags(m, +1, T3D_MESH_HIDDEN);
} else {
//se non la trova in memoria aggiunge solo il modifier alla lista
uint32 newflags;
newflags = T3D_MESH_HIDDEN;
if (init.Obj[in].meshlink[a][0] != '\0') {
if ((init.Obj[in].flags & ON) && !(init.Obj[in].flags & HIDE))
AddMeshModifier((char *)init.Obj[in].meshlink[a], MM_REMOVE_FLAGS, &newflags);
else
AddMeshModifier((char *)init.Obj[in].meshlink[a], MM_ADD_FLAGS, &newflags);
}
}
}//for
}
/* -----------------22/06/00 12.15-------------------
* SetMeshMaterialMovieFrame
* --------------------------------------------------*/
void SetMeshMaterialMovieFrame(t3dMESH *m, int8 op, int32 newframe) {
if (!m || m->FList.empty() || !m->FList[0].mat) return;
if (op == 0)
rSetMovieFrame(m->FList[0].mat, newframe);
else if (op > 0)
rSetMovieFrame(m->FList[0].mat, rGetMovieFrame(m->FList[0].mat) + newframe);
else if (op < 0)
rSetMovieFrame(m->FList[0].mat, rGetMovieFrame(m->FList[0].mat) - newframe);
newframe = rGetMovieFrame(m->FList[0].mat);
AddMeshModifier(m->name, MM_SET_MAT_FRAME, &newframe);
}
/* -----------------22/06/00 12.15-------------------
* ChangeMeshMaterialFlags
* --------------------------------------------------*/
void ChangeMeshMaterialFlags(t3dMESH *m, int8 add, uint32 newflags) {
if (!m || m->FList.empty() || !m->FList[0].mat) return;
if (add > 0) {
m->FList[0].mat->Flags |= newflags;
AddMeshModifier(m->name, MM_ADD_MAT_FLAGS, &newflags);
} else {
m->FList[0].mat->Flags &= ~newflags;
AddMeshModifier(m->name, MM_REMOVE_MAT_FLAGS, &newflags);
}
}
/* -----------------20/04/99 15.29-------------------
* t3dProcessGolfSky
* --------------------------------------------------*/
void t3dProcessGolfSky(t3dMESH *gs) {
uint32 i;
t3dF32 GolfSkySpeed = 0.00009f;
gVertex *gv;
if (!gs) return ;
gv = gs->VertexBuffer;
for (i = 0; i < gs->NumVerts; i++, gv++) {
gv->u1 += GolfSkySpeed;
gv->v1 += GolfSkySpeed;
}
gs->Flags |= T3D_MESH_UPDATEVB;
gs->VBptr = NULL;
}
} // End of namespace Watchmaker

View 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/>.
*
*/
#ifndef WATCHMAKER_LL_MESH_H
#define WATCHMAKER_LL_MESH_H
#include "watchmaker/t3d.h"
#include "watchmaker/globvar.h"
#include "watchmaker/work_dirs.h"
namespace Watchmaker {
uint8 t3dClipToSurface(Init &init, t3dV3F *pt);
void t3dLightChar(t3dMESH *mesh, t3dV3F *p);
void t3dProcessGolfSky(t3dMESH *gs);
void ApplyAllMeshModifiers(WGame &game, t3dBODY *b);
void HideRoomMeshes(Init &init, t3dBODY *body);
void t3dUpdateArrow(t3dMESH *m, t3dF32 len);
bool t3dSetSpecialAnimFrame(WGame &game, const char *name, t3dMESH *mesh, int32 nf);
void ChangeMeshFlags(t3dMESH *m, int8 add, uint32 newflags);
void AddMeshModifier(const Common::String &name, int16 com, void *p);
void UpdateObjMesh(Init &init, int32 in);
void UpdateBoundingBox(t3dMESH *mesh);
void UpdateCharHead(int32 oc, t3dV3F *dir);
void SetMeshMaterialMovieFrame(t3dMESH *m, int8 op, int32 newframe);
void ChangeMeshMaterialFlags(t3dMESH *m, int8 add, uint32 newflags);
void ChangeHaloesStatus(t3dBODY *b, int8 op);
uint8 t3dVectMeshInters(t3dMESH *m, t3dV3F start, t3dV3F end, t3dV3F *inters);
void t3dLightRoom(Init &init, t3dBODY *b, t3dV3F *p, t3dF32 NearRange, t3dF32 FarRange, t3dF32 IperRange);
void t3dUpdateExplosion(t3dMESH *m, t3dF32 scale);
bool t3dMoveAndCheck1stCamera( t3dBODY *rr, t3dCAMERA *cc, t3dV3F *mm );
} // End of namespace Watchmaker
#endif // WATCHMAKER_LL_MESH_H

View File

@ -0,0 +1,180 @@
/* 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 <SDL_mouse.h>
#include "watchmaker/ll/ll_mouse.h"
#include "watchmaker/utils.h"
#include "watchmaker/message.h"
#include "watchmaker/game.h"
#include "watchmaker/schedule.h"
#include "watchmaker/classes/do_camera.h"
#include "watchmaker/3d/geometry.h"
#include "watchmaker/renderer.h"
namespace Watchmaker {
int32 mPosy = 0, mPosx = 0, mMoveX = 0, mMoveY = 0, mMove = 0, mCounter = 0, mHotspotX = 0, mHotspotY = 0;
uint8 bLPressed = 0, bRPressed = 0, mHide = 1, bSkipped = 0;
uint8 bLPressedPrev = 0, bRPressedPrev = 0;
void 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);
}
/* -----------------08/05/98 11.47-------------------
* ProcessMouse
* --------------------------------------------------*/
void ProcessMouse(WGame &game) {
t3dF32 diffx, diffy;
int32 fittedx, fittedy;
if (mMoveX || mMoveY) {
mHide = 0;
mCounter = 0;
RemoveEvent(&Game, EventClass::MC_MOUSE, ME_MOUSEUPDATE);
Event(EventClass::MC_MOUSE, ME_MOUSEUPDATE, MP_DEFAULT, (int16)mPosx, (int16)mPosy, 0, &mMoveX, &mMoveY, NULL);
}
mMoveX = mMoveY = 0;
diffx = 0.0f;
diffy = 0.0f;
CamAngleX = 0.0f;
CamAngleY = 0.0f;
fittedx = 0;
fittedy = 0;
fittedx = game._renderer->rInvFitX(mPosx);
if (fittedx < (SCREEN_RES_X / 2)) {
if (fittedx < 50) {
diffx = - ((50.f - (t3dF32)fittedx) / 50.f);
}
if (fittedx < 5) diffx *= 1.4f;
} else {
if ((SCREEN_RES_X - fittedx) < 50) {
diffx = ((50.f - (t3dF32)(SCREEN_RES_X - fittedx)) / 50.f);
}
if ((SCREEN_RES_X - fittedx) < 5) diffx *= 1.4f;
}
fittedy = game._renderer->rInvFitY(mPosy);
if (fittedy < (SCREEN_RES_Y / 2)) {
if (fittedy < 50) {
diffy = - ((50.f - (t3dF32)fittedy) / 50.f);
}
if (fittedy < 5) diffy *= 1.4f;
} else {
if ((SCREEN_RES_Y - fittedy) < 50) {
diffy = ((50.f - (t3dF32)(SCREEN_RES_Y - fittedy)) / 50.f);
}
if ((SCREEN_RES_Y - fittedy) < 5) diffy *= 1.4f;
}
auto windowInfo = game._renderer->getScreenInfos();
if (mPosx > windowInfo.width) mPosx = windowInfo.width - 1;
else if (mPosx <= 0) mPosx = 1;
if (mPosy > windowInfo.height) mPosy = windowInfo.height - 1;
else if (mPosy <= 0) mPosy = 1;
MoveHeadAngles(diffx, diffy);
}
/* -----------------19/10/98 15.18-------------------
* DInputMouseGetCoords
* --------------------------------------------------*/
void HandleMouseChanges()
{
// Mouse movement will have been accumulated prior to calling this function.
// Button flags may also have been changed, this function then applies the button changes.
int curX, curY;
Uint32 buttonState = SDL_GetMouseState(&curX, &curY);
bLPressed = buttonState & SDL_BUTTON_LMASK;
bRPressed = buttonState & SDL_BUTTON_RMASK;
//warning("L: %d %d R: %d %d\n", bLPressed, bLPressedPrev, bRPressed, bRPressedPrev);
// Button 0 pressed or released
if( bLPressed != bLPressedPrev )
{
// se ha rilasciato e non ha mosso il mouse
if( ( !bLPressed ) && ( !bSkipped ) && ( ( mMove < 10 ) || ( !( InvStatus & INV_MODE2 ) && !bFirstPerson && !bT2DActive ) ) )
{ Event(EventClass::MC_MOUSE, ME_MLEFT, MP_DEFAULT, (int16)mPosx, (int16)mPosy, bRPressed, NULL, NULL, NULL); bSkipped = FALSE; }
else if( bLPressed && ( mMove >= 10 ) && ( InvStatus & INV_MODE2 ) && ( bSomeOneSpeak ) )
{ bSkipTalk = TRUE; bSkipped = TRUE; }
else if( !bLPressed )
bSkipped = FALSE;
mMove = 0;
}
// Button 1 pressed or released
if( bRPressed != bRPressedPrev )
{
if( ( !bRPressed ) && ( ( mMove < 10 ) || ( !bFirstPerson && !bT2DActive ) ) )
Event(EventClass::MC_MOUSE, ME_MRIGHT, MP_DEFAULT, (int16)mPosx, (int16)mPosy, bLPressed, NULL, NULL, NULL);
mMove = 0;
}
bLPressedPrev = bLPressed;
bRPressedPrev = bRPressed;
}
} // End of namespace Watchmaker

View 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_LL_MOUSE_H
#define WATCHMAKER_LL_MOUSE_H
#include "watchmaker/types.h"
namespace Watchmaker {
class WGame;
// MOUSE form (llmouse.c)
extern int32 mPosy, mPosx, mMoveX, mMoveY, mMove, mCounter, mHotspotX, mHotspotY;
extern uint8 bLPressed, bRPressed, mHide;
void ProcessMouse(WGame &game);
void HandleMouseChanges();
void MoveHeadAngles(t3dF32 diffx, t3dF32 diffy);
} // End of namespace Watchmaker
#endif // WATCHMAKER_LL_MOUSE_H

View File

@ -0,0 +1,458 @@
/* 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 <cstring>
#include "watchmaker/ll/ll_regen.h"
#include "watchmaker/render.h"
#include "watchmaker/struct.h"
#include "watchmaker/sysdef.h"
#include "watchmaker/utils.h"
#include "watchmaker/t2d/t2d.h"
#include "watchmaker/extraLS.h"
#include "watchmaker/ll/ll_mouse.h"
#include "watchmaker/define.h"
#include "watchmaker/3d/geometry.h"
#include "watchmaker/3d/t3d_body.h"
#include "watchmaker/ll/ll_system.h"
#include "watchmaker/ll/ll_util.h"
#include "watchmaker/ll/ll_string.h"
#include "watchmaker/renderer.h"
// 2d-regen
#define MAX_PAINT_RECTS MAX_DD_BITMAPS+MAX_REND_TEXTS
#define MAX_UPDATE_RECTS MAX_DD_BITMAPS+MAX_REND_TEXTS
namespace Watchmaker {
struct SDDBitmap PaintRect[MAX_PAINT_RECTS];
struct SDDBitmap OldPaintRect[MAX_PAINT_RECTS];
// frame-rate
t3dF32 hi, lo, ofps;
#define WM_CUR_VERSION "The Watchmaker v0.92"
/* -----------------30/10/98 12.19-------------------
* IntersecateRect
* --------------------------------------------------*/
int32 IntersecateRect(int32 x1, int32 y1, int32 x2, int32 y2, int32 x3, int32 y3, int32 x4, int32 y4, SRect *r) {
if ((x1 <= x4) && (x2 >= x3) && (y1 <= y4) && (y2 >= y3)) {
if (x3 > x1)
r->x1 = 0;
else
r->x1 = x1 - x3;
if (x2 < x4)
r->x2 = x2 - x3;
else
r->x2 = x4 - x3;
if (y3 > y1)
r->y1 = 0;
else
r->y1 = y1 - y3;
if (y2 < y4)
r->y2 = y2 - y3;
else
r->y2 = y4 - y3;
if (!(r->x2 - r->x1) || !(r->y2 - r->y1))
return 0;
return 1;
} else
return 0;
}
/* -----------------30/10/98 11.41-------------------
* Regen
* --------------------------------------------------*/
void Regen(WGame &game) {
struct SRect UpdateRect[MAX_UPDATE_RECTS], *p;
struct SDDBitmap *n, *o;
struct SRect r, ext;
int32 a, b, upn;
uint8 found, refresh[MAX_PAINT_RECTS];
#ifdef DEBUG_REGEN
DebugFile("----- Nuovo Frame -----");
#endif
upn = 0;
memset(refresh, 0, sizeof(refresh));
memset(UpdateRect, 0, sizeof(UpdateRect));
// I take the Extends of what the engine drew
rGetExtends(&ext.x1, &ext.y1, &ext.x2, &ext.y2);
// 1 - Compare each element of PaintRect to all OlPaintRect elements
for (a = 0; a < MAX_PAINT_RECTS; a++) {
n = &PaintRect[a];
if (!(n->dx) || !(n->dy))
continue;
#ifdef DEBUG_REGEN
DebugFile("%d: Controllo rect %d '%s': %d,%d %d,%d", a, n->tnum, rGetBitmapName(n->tnum), n->px + n->ox, n->py + n->oy, n->dx, n->dy);
#endif
found = 0;
for (b = 0; b < MAX_PAINT_RECTS; b++) {
o = &OldPaintRect[b];
if (!(o->dx) || !(o->dy))
continue;
if ((n->tnum == o->tnum) && (n->px == o->px) && (n->py == o->py) && (n->ox == o->ox) && (n->oy == o->oy) && (n->dx == o->dx) && (n->dy == o->dy)) {
#ifdef DEBUG_REGEN
DebugFile("-> Gia' disegnato");
#endif
refresh[b] = 1;
found ++;
}
}
// if it's a new rectangle, compile UpdateRect
if (true || !found) { // HACK: Just always treat everything as new, since we're doing GL
#ifdef DEBUG_REGEN
DebugFile("-> Nuovo rettangolo");
#endif
UpdateRect[upn].x1 = n->px + n->ox;
UpdateRect[upn].y1 = n->py + n->oy;
UpdateRect[upn].x2 = n->px + n->ox + n->dx;
UpdateRect[upn].y2 = n->py + n->oy + n->dy;
upn ++;
}
}
// 2 - If there are any reactangles that need to be deleted, compile UpdateRect
for (a = 0; a < MAX_PAINT_RECTS; a++) {
n = &OldPaintRect[a];
if (!(n->dx) || !(n->dy))
continue;
if ((!refresh[a]) && (n->dx) && (n->dy)) {
#ifdef DEBUG_REGEN
DebugFile("Non viene piu' ridisegnato %d '%s': %d,%d %d,%d", n->tnum, rGetBitmapName(n->tnum), n->px + n->ox, n->py + n->oy, n->dx, n->dy);
#endif
UpdateRect[upn].x1 = n->px + n->ox;
UpdateRect[upn].y1 = n->py + n->oy;
UpdateRect[upn].x2 = n->px + n->ox + n->dx;
UpdateRect[upn].y2 = n->py + n->oy + n->dy;
upn ++;
}
}
// 3 - For all UpdateRects delete the ScreenBuffer and copy what's left
for (a = 0; a < upn; a++) {
p = &UpdateRect[a];
if (!(p->x2 - p->x1) || !(p->y2 - p->y1))
continue;
// Clear ScreenBuffer
rClear(BACK_BUFFER, (p->x1), (p->y1), (p->x2 - p->x1), (p->y2 - p->y1), 0, 0, 0);
}
for (a = 0; a < upn; a++) {
p = &UpdateRect[a];
if (!(p->x2 - p->x1) || !(p->y2 - p->y1))
continue;
#ifdef DEBUG_REGEN
DebugFile("Ridisegno quello che sta sopra a %d,%d %d,%d", p->x1, p->y1, p->x2 - p->x1, p->y2 - p->y1);
#endif
found = 0;
for (b = 0; b < MAX_PAINT_RECTS; b++) {
n = &PaintRect[b];
if (!(n->dx) || !(n->dy))
continue;
// If it intersects, copies intersection only
if ((IntersecateRect(p->x1, p->y1, p->x2, p->y2, n->px + n->ox, n->py + n->oy, n->px + n->ox + n->dx, n->py + n->oy + n->dy, &r)) &&
(n->ox + r.x2 - r.x1) && (n->oy + r.y2 - r.y1)) {
#ifdef DEBUG_REGEN
DebugFile("Copio %d '%s': P %d,%d O %d,%d D %d,%d", n->tnum, rGetBitmapName(n->tnum), (n->px + n->ox + r.x1), (n->py + n->oy + r.y1), (n->ox + r.x1), (n->oy + r.y1), (r.x2 - r.x1), (r.y2 - r.y1));
// DebugLogWindow( "Copio %d '%s': P %d,%d O %d,%d D %d,%d", n->tnum, rGetBitmapName(n->tnum), (n->px+n->ox+r.x1), (n->py+n->oy+r.y1), (n->ox+r.x1), (n->oy+r.y1), (r.x2-r.x1), (r.y2-r.y1) );
#endif
rBlitter(game, BACK_BUFFER, n->tnum, (n->px + n->ox + r.x1), (n->py + n->oy + r.y1), (n->ox + r.x1), (n->oy + r.y1), (r.x2 - r.x1), (r.y2 - r.y1));
found ++;
}
}
if (!found)
memset(p, 0, sizeof(struct SRect));
}
// 4 - Copy on screen only the UpdateRects by stretching them.
for (a = 0; a < MAX_PAINT_RECTS; a++) {
n = &PaintRect[a];
if (!(n->dx) || !(n->dy))
continue;
if ((n->px + n->ox) < ext.x1) ext.x1 = n->px + n->ox;
if ((n->py + n->oy) < ext.y1) ext.y1 = n->py + n->oy;
if ((n->px + n->ox + n->dx) > ext.x2) ext.x2 = n->px + n->ox + n->dx;
if ((n->py + n->oy + n->dy) > ext.y2) ext.y2 = n->py + n->oy + n->dy;
}
for (a = 0; a < upn; a++) {
p = &UpdateRect[a];
if (!(p->x2 - p->x1) || !(p->y2 - p->y1))
continue;
if (p->x1 < ext.x1) ext.x1 = p->x1;
if (p->y1 < ext.y1) ext.y1 = p->y1;
if (p->x2 > ext.x2) ext.x2 = p->x2;
if (p->y2 > ext.y2) ext.y2 = p->y2;
}
auto windowInfo = game._renderer->getScreenInfos();
if (ext.x1 < 0) ext.x1 = 0;
if (ext.y1 < 0) ext.y1 = 0;
if (ext.x2 > windowInfo.width) ext.x2 = windowInfo.width;
if (ext.y2 > windowInfo.height) ext.y2 = windowInfo.height;
#ifdef DEBUG_REGEN
DebugFile("Aggiorna video %d,%d %d,%d", ext.x1, ext.y1, ext.x2 - ext.x1, ext.y2 - ext.y1);
// DebugLogWindow( "Aggiorna video %d,%d %d,%d", ext.x1, ext.y1, ext.x2-ext.x1, ext.y2-ext.y1 );
#endif
rUpdateExtends(ext.x1, ext.y1, ext.x2, ext.y2);
rBlitScreenBuffer();
rResetExtends();
// 5 - Copy PaintRect to OldPaintRect
memcpy(OldPaintRect, PaintRect, sizeof(OldPaintRect));
// memset( OldPaintRect, 0, sizeof( OldPaintRect ) );
}
/* -----------------16/11/98 17.29-------------------
* ResetScreenBuffer
* --------------------------------------------------*/
void ResetScreenBuffer() {
memset(OldPaintRect, 0, sizeof(OldPaintRect));
if (!rClearBuffers(rCLEARSCREENBUFFER | rCLEARZBUFFER))
warning("Unable to clear screenbuffer\n");
}
/* -----------------30/10/98 16.18-------------------
* AfterRender
* --------------------------------------------------*/
void AfterRender(WGame &game) {
PaintT2D(*game._renderer);
PaintInventory(game);
PaintText(game);
}
/* -----------------31/10/98 15.56-------------------
* AddPaintRect
* --------------------------------------------------*/
void AddPaintRect(int32 tnum, int32 px, int32 py, int32 ox, int32 oy, int32 dx, int32 dy) {
int32 a;
for (a = 0; a < MAX_PAINT_RECTS; a++)
if (!PaintRect[a].tnum)
break;
// ce ne sono troppe
if (a >= MAX_PAINT_RECTS) {
warning("Too many PaintRects!\n");
return ;
}
PaintRect[a].tnum = tnum;
PaintRect[a].px = (px);
PaintRect[a].py = (py);
PaintRect[a].ox = (ox);
PaintRect[a].oy = (oy);
PaintRect[a].dx = (dx);
PaintRect[a].dy = (dy);
}
/* -----------------27/10/98 17.14-------------------
* Add2DStuff
* --------------------------------------------------*/
void Add2DStuff(WGame &game) {
struct SDDBitmap *b;
struct SDDText *t, *r;
int32 cmx, cmy;
int32 a, c;
// Reset paint structure
memset(PaintRect, 0, sizeof(PaintRect));
// Insert pre-calculated images and texts
memcpy(PaintRect, DDBitmapsList, sizeof(struct SDDBitmap)*MAX_DD_BITMAPS);
// Destroys pre-rendered writings that are no longer needed
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);
memset(r, 0, sizeof(struct SDDText));
}
}
// Put mouse over everything
if ((!mHide) && (CurDialog <= dSUPERVISORE) && (!bTitoliCodaStatic) && (!bTitoliCodaScrolling)) {
cmx = mPosx - mHotspotX;
cmy = mPosy - mHotspotY;
if (cmx >= MousePointerLim.x2) cmx = MousePointerLim.x2 - 1;
else if (cmx <= MousePointerLim.x1) cmx = MousePointerLim.x1 + 1;
if (cmy >= MousePointerLim.y2) cmy = MousePointerLim.y2 - 1;
else if (cmy <= MousePointerLim.y1) cmy = MousePointerLim.y1 + 1;
// Draw the current mouse pointer
if (CurMousePointer > 0)
AddPaintRect(CurMousePointer, (cmx), (cmy), 0, 0, rGetBitmapDimX(CurMousePointer), rGetBitmapDimY(CurMousePointer));
}
Regen(game);
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;
for (a = 0, t = &DDTextsList[0]; a < MAX_DD_TEXTS; a++, t++) {
memset(t->text, 0, sizeof(t->text));
t->tnum = 0;
}
//check
CheckExtraLocalizationStrings(*game._renderer, 0);
}
/* -----------------27/10/98 17.14-------------------
* Add3DStuff
* --------------------------------------------------*/
void Add3DStuff(WGame &game) {
extern uint32 StatNumTris, StatNumVerts;
struct SD3DRect *p;
struct SD3DTriangle *t;
int32 a, y = 0;
// char *PauseAnimStr[] = { "", "(PAUSE)" };
if (bShowBoundingBox) {
t3dShowBoundingBox(t3dCurRoom);
for (a = ocCUOCO; a < ocCURPLAYER; a++)
if ((Character[a]) && (Character[a]->Body) && !(Character[a]->Flags & T3D_CHARACTER_HIDE))
t3dShowBoundingBox(Character[a]->Body);
}
if (bShowPanels && Player && Player->Walk.Panel)
t3dShowBounds(Player->Walk.Panel, Player->Walk.PanelNum);
else if (bShowPanels)
t3dShowBounds(t3dCurRoom->Panel[t3dCurRoom->CurLevel], t3dCurRoom->NumPanels[t3dCurRoom->CurLevel]);
//DisplayDDBitmap( TrecLogo, 800-10-rGetBitmapRealDimX(TrecLogo),0, 0,0, 0,0 );
if (bShowInfo) {
//display version
uint32 date, time, d, m, yy, h, min;
t3dForceNOFastFile(1);
if (t3dGetFileDate(&date, &time, "wm.exe ")) {
d = date - (date / 100) * 100;
date /= 100;
m = date - (date / 100) * 100;
date /= 100;
yy = date;
time /= 100;
min = time - (time / 100) * 100;
time /= 100;
h = time;
} else {
d = m = yy = h = min = 0;
}
t3dForceNOFastFile(0);
DebugVideo(*game._renderer, 1, 600 - 20, "%s (%02d/%02d/%4d - %d.%d)", WM_CUR_VERSION, d, m, yy, h, min);
if (LoaderFlags & T3D_DEBUGMODE) {
extern uint8 t3dCurCameraIndex;
extern int ci;
auto windowInfo = game._renderer->getScreenInfos();
if (CurFps > 100.0f) CurFps = 100.0f;
if (AvgFps > 100.0f) AvgFps = 100.0f;
if (!AvgFps) AvgFps = CurFps;
if (AvgFps != ofps) {
ofps = AvgFps;
hi = 0.0f;
lo = 999.0f;
}
if (CurFps > hi) hi = CurFps;
if (CurFps < lo) lo = CurFps;
DisplayD3DRect(*game._renderer, 1, 1, (int32)((t3dF32)windowInfo.width * (CurFps / 101.0f)), 13, 78, 78, 78, 228);
DebugVideo(*game._renderer, 1, y += 16, "FPS: ( LOW %2d | AVG %2d | HI %2d ) TRI: %d VERT: %d", (int)lo, (int)AvgFps, (int)hi, StatNumTris, StatNumVerts);
// DebugVideo(1,y+=16,"(%d) CUR %f %s",(int)(1000.0f/CurFps),CurFps,PauseAnimStr[bPauseAllAnims]);
DebugVideo(*game._renderer, 1, y += 16, "%d,%d: %s (%d %d) %X", game._gameVars.getCurRoomId(), CurObj, ObjectUnderCursor, NextPortalObj, NextPortalAnim, game.init.Obj[CurObj].flags);
// DebugVideo(1,y+=16,"Player: %d %d %d %d",Player->Mesh->BlendPercent,Player->Mesh->CurFrame,Player->Mesh->LastFrame,Player->Walk.CurAction);
DebugVideo(*game._renderer, 1, y += 16, "DialogActive: %d AnimWaitText: %d PlayerInAnim: %d | %d", bDialogActive, bAnimWaitText, bPlayerInAnim, Player->Mesh->CurFrame);
DebugVideo(*game._renderer, 1, y += 16, "CurCamera %d CurTime %d (%f %f)", t3dCurCameraIndex + 1, t3dCurTime, t3dCurCamera->Source.x, t3dCurCamera->Source.z);
// DebugVideo(1,y+=16,"xy(%f %f)",Character[1]->Mesh->Trasl.x,Character[1]->Mesh->Trasl.y);
// DebugVideo(1,y+=16,"xy(%f %f)",Character[2]->Dir.x,Character[2]->Dir.y);
DebugVideo(*game._renderer, 1, y += 16, "bPlayerSuBasamento %d", bPlayerSuBasamento);
DebugVideo(*game._renderer, 1, y += 16, "%f %f ", Player->Mesh->Trasl.y, Player->Pos.y);
// DebugVideo(1,y+=16,"CurP %d",CurPlayer);
// DebugVideo(1,y+=16,"InvStatus ON%d (1)%d (2)%d (3)%d (4)%d (5)%d",InvStatus&1,InvStatus&2,InvStatus&4,InvStatus&8,InvStatus&16,InvStatus&32);
DebugVideo(*game._renderer, 1, y += 16, "bMovingCamera%d", bMovingCamera);
// DebugVideo(1,y+=16,"1-%s",PlayerStand[0].RoomName);
// DebugVideo(1,y+=16,"2-%s",PlayerStand[1].RoomName);
/* if( Character[1]->CurRoom )
{
if( Character[1]->CurRoom->Name[0]=='\0' ) DebugVideo(1,y+=16,"1-NULLA");
else DebugVideo(1,y+=16,"1-%s",Character[1]->CurRoom->Name);
}
if( Character[2]->CurRoom )
{
if( Character[2]->CurRoom->Name[0]=='\0' ) DebugVideo(1,y+=16,"2-NULLA");
else DebugVideo(1,y+=16,"2-%s",Character[2]->CurRoom->Name);
}
*/
DebugVideo(*game._renderer, 1, windowInfo.height - 40, "%s", CurDebugString);
} else {
// extern t3dU8 t3dCurCameraIndex;
// DebugVideo(1,y+=16,"CurCamera %d CurTime %d",t3dCurCameraIndex+1,t3dCurTime);
// extern t3dU8 t3dCurCameraIndex;
// if( !AvgFps ) AvgFps = CurFps;
// if( AvgFps != ofps ) { ofps = AvgFps; hi = 0.0f; lo = 999.0f; }
// if( CurFps > hi ) hi = CurFps;
// if( CurFps < lo ) lo = CurFps;
// DebugVideo(1,y+=16,"mHide %d",mHide);
// DebugVideo(1,1,"FPS: %3d TRI: %d VERT: %d",(int)AvgFps,StatNumTris,StatNumVerts);
// DebugVideo(1,y+=16,"CurTime %d CurCamera %d",t3dCurTime,t3dCurCameraIndex+1);
// DebugVideo(1,y+=16,"CurDialog %d, obj %d",CurDialog,Dialog[CurDialog].obj);
// DebugVideo(1,y+=16,"%d,%d: %s (%d %d) %X",CurRoom,CurObj,ObjectUnderCursor,NextPortalObj,NextPortalAnim,Obj[CurObj].flags); //_remove
}
}
// Aggiunge i rettangoli D3D
for (a = 0, p = &D3DRectsList[0]; a < MAX_D3D_RECTS; a++, p++)
if (p->dx || p->dy)
t3dAddQuad((t3dF32)(p->px), (t3dF32)(p->py), (t3dF32)(p->px + p->dx), (t3dF32)(p->py),
(t3dF32)(p->px), (t3dF32)(p->py + p->dy), (t3dF32)(p->px + p->dx), (t3dF32)(p->py + p->dy),
p->r, p->g, p->b, p->a);
for (a = 0, p = &D3DRectsList[0]; a < MAX_D3D_RECTS; a++, p++)
p->dx = p->dy = 0;
// Aggiunge i triangoli D3D
for (a = 0, t = &D3DTrianglesList[0]; a < MAX_D3D_TRIANGLES; a++, t++)
if (t->x1 || t->y1 || t->x2 || t->y2)
t3dAddTriangle((t3dF32)(t->x1), (t3dF32)(t->y1), (t3dF32)(t->x2), (t3dF32)(t->y2),
(t3dF32)(t->x3), (t3dF32)(t->y3), t->r, t->g, t->b, t->a);
for (a = 0, t = &D3DTrianglesList[0]; a < MAX_D3D_TRIANGLES; a++, t++)
t->x1 = t->y1 = t->x2 = t->y2 = t->x3 = t->y3 = 0;
}
} // End of namespace Watchmaker

View 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_LL_REGEN_H
#define WATCHMAKER_LL_REGEN_H
namespace Watchmaker {
class WGame;
void ResetScreenBuffer();
void AfterRender(WGame &game);
void Add2DStuff(WGame &game);
void Add3DStuff(WGame &game);
} // End of namespace Watchmaker
#endif // WATCHMAKER_LL_REGEN_H

View File

@ -0,0 +1,102 @@
/* 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/ll/ll_sound.h"
#include "watchmaker/windows_hacks.h"
namespace Watchmaker {
bool mInitMusicSystem(void) {
warning("STUBBED: mInitMusicSystem\n");
return true;
}
bool mCloseMusicSystem(void) {
warning("STUBBED: mCloseMusicSystem\n");
return true;
}
bool mLoadMusic(const char *FileName) {
warning("STUBBED: mLoadMusic\n");
return true;
}
bool mPlayMusic(const char *FileName) {
warning("STUBBED: mPlayMusic\n");
return true;
}
bool mStopMusic(void) {
warning("STUBBED: mStopMusic\n");
return true;
}
bool mRestoreMixerVolume(void) {
warning("STUBBED: mRestoreMixerVolume\n");
return true;
}
bool sSetListener(sListener *NewListener) {
warning("STUBBED: sSetListener\n");
return true;
}
bool sStartSound(sSound *CurSound, bool Reload) {
warning("STUBBED: sStartSound\n");
return true;
}
bool sStopSound(int32 index) {
warning("STUBBED: sStopSound\n");
return true;
}
bool sStopAllSounds(void) {
warning("STUBBED: sStopAllSounds\n");
return true;
}
bool sIsPlaying(sS32 lIndex) {
warning("STUBBED: sIsPlaying\n");
return true;
}
bool mSetAllVolume(unsigned char Volume) {
warning("STUBBED: mSetAllVolume\n");
return true;
}
bool sSetAllSoundsVolume(unsigned char Vol) {
warning("STUBBED: sSetAllSoundsVolume\n");
return true;
}
bool sSetAllSpeechVolume(unsigned char Vol) {
warning("STUBBED: sSetAllSpeechVolume\n");
return true;
}
bool sStartSoundDiffuse(sSound *CurSound) {
warning("STUBBED: sStartSoundDiffuse\n");
return true;
}
} // End of namespace Watchmaker

View File

@ -0,0 +1,102 @@
/* 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_LL_SOUND_H
#define WATCHMAKER_LL_SOUND_H
#include "watchmaker/types.h"
namespace Watchmaker {
typedef float sF32;
typedef unsigned int sU32;
typedef signed int sS32;
typedef unsigned short sU16;
#define SOUND_NAME_LEN 100
#define SOUND_SPEECH 32
struct sV3F {
sF32 x, y, z;
};
struct sEnvironment {
sS32 lIndex; // room index (for retrieval)
sS32 lRoom; // room effect level at low frequencies
sS32 lRoomHF; // room effect high-frequency level re. low frequency level
sF32 flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect
sF32 flDecayTime; // reverberation decay time at low frequencies
sF32 flDecayHFRatio; // high-frequency to low-frequency decay time ratio
sS32 lReflections; // early reflections level relative to room effect
sF32 flReflectionsDelay; // initial reflection delay time
sS32 lReverb; // late reverberation level relative to room effect
sF32 flReverbDelay; // late reverberation delay time relative to initial reflection
sU32 dwEnvironment; // sets all listener properties ****
sF32 flEnvironmentSize; // environment size in meters
sF32 flEnvironmentDiffusion; // environment diffusion
sF32 flAirAbsorptionHF; // change in level per meter at 5 kHz
sU32 dwFlags; // modifies the behavior of properties
};
struct sSound {
char name[SOUND_NAME_LEN];
sS32 lIndex;
sU32 dwLooped;
sF32 flMaxDistance; // servono fl
sF32 flMinDistance; // servono fl
sV3F v3flPosition; // meshlink
sV3F v3flConeOrientation; // angolo con (0,0,-1)
sU32 dwConeInsideAngle; // servono int
sU32 dwConeOutsideAngle; // servono int
sS32 dwConeOutsideVolume; // servono int (negativo)
sU32 dwFlags; // flags
};
struct sListener {
sF32 flDistanceFactor; // non serve
sV3F v3flFrontOrientation; // vettore front camera
sV3F v3flTopOrientation; // vettore alto camera
sV3F v3flPosition; // quella della telecamera
sF32 flRolloff; // non serve
};
bool sSetListener(sListener *NewListener);
bool sStartSound(sSound *CurSound, bool Reload);
bool sStopSound(int32 index);
bool sStopAllSounds();
bool sIsPlaying(sS32 lIndex);
bool mInitMusicSystem();
bool mCloseMusicSystem();
bool mLoadMusic(const char *FileName);
bool mPlayMusic(const char *FileName);
bool mStopMusic();
bool mRestoreMixerVolume();
bool mSetAllVolume(unsigned char Volume);
bool sSetAllSoundsVolume(unsigned char Vol);
bool sSetAllSpeechVolume(unsigned char Vol);
bool sStartSoundDiffuse(sSound *CurSound);
} // End of namespace Watchmaker
#endif // WATCHMAKER_LL_SOUND_H

View File

@ -0,0 +1,310 @@
/* 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_strcpy
#include "watchmaker/ll/ll_string.h"
#include "watchmaker/globvar.h"
#include "watchmaker/define.h"
#include "watchmaker/ll/ll_util.h"
#include "watchmaker/game.h"
#include "watchmaker/classes/do_player.h"
#include "watchmaker/classes/do_dialog.h"
#include "watchmaker/t2d/expr.h"
#include "watchmaker/renderer.h"
#include "watchmaker/3d/t3d_body.h"
namespace Watchmaker {
// locals
int32 LastTextTime;
int console_3_4_xoffs = 0;
/* -----------------17/03/98 17.48-------------------
* Text
* --------------------------------------------------*/
void Text(uint16 x, uint16 y, uint16 dx, char *text) {
if (!text) return;
LastTextTime = TheTime;
TheString.x = x;
TheString.y = y;
TheString.dx = dx;
strcpy(TheString.text, text);
}
/* -----------------17/03/98 17.48-------------------
* ClearText
* --------------------------------------------------*/
void ClearText(void) {
if (!(bUseWith & UW_ON)) {
TheString.x = 0;
TheString.y = 0;
TheString.dx = 0;
memset(TheString.text, 0, sizeof(TheString.text));
}
}
/*-----------------17/02/95 09.53-------------------
TextLen - calcola lunghezza str dal car 0 a num
--------------------------------------------------*/
uint16 TextLen(char *sign, uint16 num) {
uint16 Len, b, c;
b = 0;
if (sign == nullptr)
return (0);
if (num == 0)
Len = strlen(sign);
else
Len = num;
for (c = 0; c < Len; c++)
b += (StandardFont.Table[(uint16)((uint8)sign[c]) * 4 + 2]);
return (b);
}
/*-----------------14/05/95 12.12-------------------
CheckText - ritorna in quante righe scrivera'
--------------------------------------------------*/
uint16 CheckText(uint16 dx, char *sign) {
uint16 a, b;
uint16 CurInit;
uint16 LastSpace;
uint16 CurLine;
if (sign == NULL) return (0);
// Azzera tutto
memset(TextLines, 0, sizeof(TextLines));
a = 0;
LastSpace = 0;
CurInit = 0;
CurLine = 0;
// Caso piu' semplice: sta tutto su una riga
if (TextLen(sign, 0) <= dx) {
strcpy((char *)TextLines[CurLine], sign);
return (1);
}
while (a < strlen(sign)) {
a++;
if (sign[a] == ' ') {
if (TextLen((char *)(sign + CurInit), (uint16)(a - CurInit)) <= dx)
LastSpace = a;
else if (TextLen((char *)(sign + CurInit), (uint16)(LastSpace - CurInit)) <= dx) {
for (b = CurInit; b < LastSpace; b++)
TextLines[CurLine][b - CurInit] = sign[b];
TextLines[CurLine][b - CurInit] = '\0';
CurInit = LastSpace + 1;
a = CurInit;
CurLine++;
} else
return (0);
} else if (sign[a] == '\0') {
if (TextLen((char *)(sign + CurInit), (uint16)(a - CurInit)) <= dx) {
for (b = CurInit; b < a; b++)
TextLines[CurLine][b - CurInit] = sign[b];
TextLines[CurLine][b - CurInit] = '\0';
CurLine++;
CurInit = a + 1;
return (CurLine);
} else if (TextLen((char *)(sign + CurInit), (uint16)(LastSpace - CurInit)) <= dx) {
for (b = CurInit; b < LastSpace; b++)
TextLines[CurLine][b - CurInit] = sign[b];
TextLines[CurLine][b - CurInit] = '\0';
CurLine++;
CurInit = LastSpace + 1;
if (CurInit < strlen(sign)) {
for (b = CurInit; b < strlen(sign); b++)
TextLines[CurLine][b - CurInit] = sign[b];
TextLines[CurLine][b - CurInit] = '\0';
CurLine++;
}
return (CurLine);
} else
return (0);
}
}
return (0);
}
/* -----------------18/03/98 9.57--------------------
* PaintText
* --------------------------------------------------*/
void PaintText(WGame &game) {
uint16 lines, i;
int32 dx, obj;
uint8 color;
Init &init = game.init;
if (bTitoliCodaStatic || bTitoliCodaScrolling) return;
if (TheString.text) {
if (bDialogActive) {
obj = init.Anim[TimeAnim].obj;
if (obj == ocCURPLAYER)
Player->Mesh->ExpressionFrame = VisemaTimeRecon(TheTime - LastTextTime);
else if ((obj >= ocDARRELL) && (obj <= ocLASTCHAR) && (obj) && (Character[obj]->Mesh))
Character[obj]->Mesh->ExpressionFrame = VisemaTimeRecon(TheTime - LastTextTime);
}
lines = (uint16)CheckText((uint16)game._renderer->rFitY((int32)TheString.dx), TheString.text);
for (i = 0; i < lines; i++) {
dx = (TheString.dx - (TextLen(TextLines[i], 0) * SCREEN_RES_X) / game._renderer->rFitX(SCREEN_RES_X)) / 2;
obj = init.Anim[TimeAnim].obj;
color = WHITE_FONT;
if ((obj >= ocCUOCO) && (obj <= ocCURPLAYER)) {
switch (obj) {
case ocNOTAIO:
case ocSUPERVISORE:
case ocCUOCO:
color = RED_FONT;
break;
case ocVALENCIA:
case ocCHIRURGO:
case ocGIARDINIERE:
color = GREEN_FONT;
break;
case ocKRENN:
case ocOROLOGIAIO:
case ocVICTORIA:
color = CYAN_FONT;
break;
case ocMOORE:
case ocMOOREBUCATO:
case ocDUKES:
case ocTRADUTTORE:
case ocCUSTODE:
color = MAGENTA_FONT;
break;
case ocCORONA:
case ocMOGLIESUPERVISORE:
case ocMOGLIE_KIMONO:
case ocSERVETTA:
color = YELLOW_FONT;
break;
case ocVECCHIO:
case ocCACCIATORE:
case ocCACCIATOREMALPRESO:
case ocDOMESTICA:
color = GRAY_FONT;
break;
case ocDARRELL:
case ocDARRELLALETTO:
case ocCURPLAYER:
default:
color = WHITE_FONT;
break;
}
}
DisplayDDText(*game._renderer, TextLines[i], &StandardFont, color, TheString.x + dx, TheString.y + i * 12, 0, 0, 0, 0);
}
}
}
/* -----------------06/04/98 10.34-------------------
* PaintInventory
* --------------------------------------------------*/
void PaintInventory(WGame &game) {
int32 a, ci;
Init &init = game.init;
Renderer &renderer = *game._renderer;
if ((InvStatus & INV_ON) || ((bT2DActive == tOPTIONS) && !bShowOnlyLoadWindow)) {
if (bT2DActive != tOPTIONS) {
DisplayD3DRect(renderer, 27, 77, 188, 490, 18, 25, 18, 128);
DisplayD3DRect(renderer, 13, 124, 14, 49, 18, 25, 18, 128);
DisplayD3DRect(renderer, 215, 472, 12, 50, 18, 25, 18, 128);
DisplayDDBitmap(renderer, Console1, 3, 73, 0, 0, 0, 0);
if (InvLen[CurPlayer] > MAX_SHOWN_ICONS) {
if (InvBase[CurPlayer] > 0)
DisplayDDBitmap(renderer, ConsoleFrecciaSu, 3 + 14, 73 + 66, 0, 0, 0, 0);
if (InvBase[CurPlayer] < (InvLen[CurPlayer] - MAX_SHOWN_ICONS))
DisplayDDBitmap(renderer, ConsoleFrecciaGiu, 3 + 206, 73 + 416, 0, 0, 0, 0);
}
}
if ((InvStatus & INV_MODE1) && PlayerCanCall(game._gameVars)) {
if (CurPlayer == VICTORIA)
DisplayDDBitmap(renderer, Console5, 22, 13, 0, 0, 0, 0);
else
DisplayDDBitmap(renderer, Console6, 22, 13, 0, 0, 0, 0);
}
if ((InvStatus & INV_MODE2) || (bT2DActive == tOPTIONS)) {
int ox;
if (bT2DActive == tOPTIONS) {
ox = 192;
console_3_4_xoffs = -94;
} else {
ox = 0;
console_3_4_xoffs = 0;
}
if (CurPlayer == DARRELL)
DisplayDDBitmap(renderer, Console3, 22 + console_3_4_xoffs, 13, ox, 0, 0, 0);
else
DisplayDDBitmap(renderer, Console4, 22 + console_3_4_xoffs, 13, ox, 0, 0, 0);
if (!PlayerCanSave())
DisplayDDBitmap(renderer, ConsoleNoSave, 227 + 22 + console_3_4_xoffs, 13, 0, 0, 0, 0);
if ((bT2DActive != tOPTIONS) && (!PlayerCanSwitch(game._gameVars, 0))) {
if (CurPlayer == DARRELL)
DisplayDDBitmap(renderer, ConsoleNoSwitchDar, 61 + 22 + console_3_4_xoffs, 13, 0, 0, 0, 0);
else
DisplayDDBitmap(renderer, ConsoleNoSwitchVic, 61 + 22 + console_3_4_xoffs, 13, 0, 0, 0, 0);
}
}
if (bT2DActive != tOPTIONS) {
for (a = 0; a < MAX_SHOWN_ICONS; a++) {
if (ci = Inv[CurPlayer][InvBase[CurPlayer] + a]) {
if (CurInvObj == ci)
DisplayDDText(renderer, ObjName[init.InvObj[ci].name], &StandardFont, RED_FONT, INV_MARG_SX, INV_MARG_UP + ICON_DY * a, 0, 0, 0, 0);
else
DisplayDDText(renderer, ObjName[init.InvObj[ci].name], &StandardFont, WHITE_FONT, INV_MARG_SX, INV_MARG_UP + ICON_DY * a, 0, 0, 0, 0);
}
}
}
} else if ((bUseWith & UW_ON) && (bUseWith & UW_USEDI)) {
DisplayD3DRect(renderer, UseIconRect.x1 + 3, UseIconRect.y1 + 3, 63, 63, 22, 31, 22, 75);
DisplayDDBitmap(renderer, IconsPics[UseWith[USED]], UseIconRect.x1 + 3, UseIconRect.y1 + 3, 0, 0, 0, 0);
DisplayDDBitmap(renderer, Console2, UseIconRect.x1, UseIconRect.y1, 0, 0, 0, 0);
}
PaintDialog(game);
}
} // End of namespace Watchmaker

View 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_LL_STRING_H
#define WATCHMAKER_LL_STRING_H
#include "watchmaker/types.h"
#include "watchmaker/globvar.h"
namespace Watchmaker {
class WGame;
void ClearText();
void Text(uint16 x, uint16 y, uint16 dx, char *text);
uint16 TextLen(char *sign, uint16 num);
void PaintInventory(WGame &game);
void PaintText(WGame &game);
} // End of namespace Watchmaker
#endif // WATCHMAKER_LL_STRING_H

View File

@ -0,0 +1,192 @@
/* 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/>.
*
*/
#ifdef __APPLE__
#include <malloc/malloc.h>
#define MALLOC_SIZE malloc_size
#else
#include <malloc.h>
#ifdef __linux__
#define MALLOC_SIZE malloc_usable_size
#else
#define MALLOC_SIZE _msize
#endif
#endif
#include "common/archive.h"
#include "watchmaker/ll/ll_system.h"
#include "watchmaker/types.h"
#include "watchmaker/utils.h"
#include "watchmaker/windows_hacks.h"
#include <cstdlib>
namespace Watchmaker {
uint32 t3dAllocatedMemory = 0;
char bUsingFastFile = 0;
char bForceNOFastFile = 0; // forza a non utilizzare il FastFile, nonostante questo sia attivo
char bForceNOFastFile_bUsingFastFile_backup = 0; //valore precedente la chiamata di ForceNOFastFile
//------------------------- Memory Functions -------------------------------
//..........................................................................
void *t3dMalloc(uint32 n) {
uint32 *res;
if (!(res = static_cast<uint32 *>(malloc(n))))
warning("t3dMalloc: Can't alloc %d bytes", n);
t3dAllocatedMemory += n;
return (res);
}
void *t3dCalloc(uint32 n) {
uint32 *res;
if (!(res = static_cast<uint32 *>(calloc(n, 1))))
warning("t3dCalloc: Can't alloc %d bytes", n);
t3dAllocatedMemory += n;
return (res);
}
void *t3dRealloc(void *pp, uint32 additionalBytes) {
uint32 *res = (uint32 *)pp;
uint32 size = 0;
if (pp == nullptr) size = 0;
else
size = (uint32) MALLOC_SIZE(pp);
//Reallocate and show new size:
if ((res = (uint32 *)realloc(pp, (additionalBytes + size))) == nullptr) {
warning("t3dRealloc: Memory allocation error: can't alloc %d bytes", additionalBytes + size);
return res;
}
t3dAllocatedMemory += additionalBytes;
//malloc_size()
pp = res;//realloc(pp, additionalBytes);
//warning("t3dRealloc() size: %d, additionalBytes: %d, newSize = %d\n", size, additionalBytes, malloc_size(pp));
return (pp);
}
void t3dFree(void *p) {
if (!p) return;
t3dAllocatedMemory -= (uint32) MALLOC_SIZE(p);
free(p);
}
//------------------------- Time Functions ---------------------------------
//..........................................................................
void t3dStartTime() {
warning("STUBBED t3dStartTime\n");
#if 0
timeGetDevCaps(&tc, sizeof(tc));
timeBeginPeriod(tc.wPeriodMin);
srand((unsigned)time(NULL));
#endif
}
void t3dEndTime() {
warning("STUBBED t3dEndTime\n");
#if 0
timeEndPeriod(tc.wPeriodMin);
#endif
}
uint32 t3dReadTime() {
return (timeGetTime());
}
//--------------------------------------------------------------------------
//------------------------- File I/O Functions -----------------------------
bool t3dFastFileInit(const char *name) {
warning("STUBBED t3dFastFileInit\n");
#if 0
bUsingFastFile = FastFileInit(name);
return (BOOL)(bUsingFastFile);
#endif
return false;
}
void t3dForceNOFastFile(char valore) {
if (valore) {
bForceNOFastFile_bUsingFastFile_backup = bUsingFastFile;
bUsingFastFile = 0;
} else bUsingFastFile = bForceNOFastFile_bUsingFastFile_backup;
}
int t3dAccessFile(char *name) {
error("STUBBED: t3dAccessFile\n");
#if 0
FILE *tempFile = nullptr;
if (bUsingFastFile) tempFile = (FILE *)FastFileOpen(name);
else tempFile = fopen(name, "rb");
if (tempFile == NULL)
return 0;
if (bUsingFastFile) FastFileClose((LPFILEHANDLE)tempFile);
else fclose(tempFile);
return 1;
#endif
return 0;
}
bool t3dGetFileDate(uint32 *date, uint32 *time, const char *name) {
#if 0
FILE *f = fopen(name, "rb");
//warning("STUBBED: t3dGetFileDate(%s)\n", name);
if (f) {
fclose(f);
return true;
}
#endif
error("TODO: t3dGetFileDate");
return false;
}
Common::SeekableReadStream *openFile(const Common::String &filename) {
Common::SeekableReadStream *file = nullptr;
// Try directly from SearchMan first
Common::ArchiveMemberList files;
SearchMan.listMatchingMembers(files, filename);
for (Common::ArchiveMemberList::iterator it = files.begin(); it != files.end(); ++it) {
if ((*it)->getName().equalsIgnoreCase(lastPathComponent(filename,'/'))) {
file = (*it)->createReadStream();
break;
}
}
return file;
}
} // End of namespace Watchmaker

Some files were not shown because too many files have changed in this diff Show More