mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-04 17:29:11 +00:00
WATCHMAKER: Add all files after initial cleanup.
This commit is contained in:
parent
4781fca07a
commit
ccf209a001
744
engines/watchmaker/3d/animation.cpp
Normal file
744
engines/watchmaker/3d/animation.cpp
Normal 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
|
44
engines/watchmaker/3d/animation.h
Normal file
44
engines/watchmaker/3d/animation.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_ANIMATION_H
|
||||
#define WATCHMAKER_ANIMATION_H
|
||||
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/3d/t3d_body.h"
|
||||
#include "watchmaker/work_dirs.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
uint8 GetLightDirection(t3dV3F *dest, uint8 pos);
|
||||
unsigned char GetLightPosition(t3dV3F *dest, unsigned char pos);
|
||||
uint8 GetFullLightDirection(t3dV3F *dest, uint8 pos);
|
||||
|
||||
void FixupAnim(t3dMESH *mesh, unsigned char pos, const char *room);
|
||||
t3dBODY *LoadShadowMeshes(WGame &game, const char *pname, t3dBODY *Body);
|
||||
int8 t3dLoadAnimation(WGame &game, const char *s, t3dMESH *mesh, uint16 Flag);
|
||||
t3dCHARACTER *t3dLoadCharacter(WGame &game, const char *pname, 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
|
3512
engines/watchmaker/3d/geometry.cpp
Normal file
3512
engines/watchmaker/3d/geometry.cpp
Normal file
File diff suppressed because it is too large
Load Diff
83
engines/watchmaker/3d/geometry.h
Normal file
83
engines/watchmaker/3d/geometry.h
Normal 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
|
466
engines/watchmaker/3d/light.cpp
Normal file
466
engines/watchmaker/3d/light.cpp
Normal 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
|
46
engines/watchmaker/3d/light.h
Normal file
46
engines/watchmaker/3d/light.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_LIGHT_H
|
||||
#define WATCHMAKER_LIGHT_H
|
||||
|
||||
#include "watchmaker/t3d.h"
|
||||
|
||||
#define LIGHT_MAPVERSION 1
|
||||
#define VOLLIGHTFILEVERSION 1
|
||||
#define OUTDOORLIGHTSFILEVERSION 2
|
||||
|
||||
#define LIGHT_COORDS (1<<0)
|
||||
#define LIGHT_LIGHTMAPS (1<<1)
|
||||
#define LIGHT_SHADOWMAPS (1<<2)
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void GetBoundaries(t3dBODY *b, float *minx, float *miny, float *minz, float *maxx, float *maxy, float *maxz);
|
||||
unsigned char LightgVertex(gVertex *v, t3dLIGHT *light);
|
||||
void t3dLoadOutdoorLights(const char *pname, t3dBODY *b, int32 ora);
|
||||
void LoadVolumetricMap(WorkDirs &workDirs, const char *pname, t3dBODY *b);
|
||||
Common::String setDirectoryAndName(const Common::String &path, const Common::String &name);
|
||||
uint8 LightVertex(t3dVERTEX *vv, t3dV3F *v, t3dLIGHT *light);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_LIGHT_H
|
566
engines/watchmaker/3d/loader.cpp
Normal file
566
engines/watchmaker/3d/loader.cpp
Normal 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
|
88
engines/watchmaker/3d/loader.h
Normal file
88
engines/watchmaker/3d/loader.h
Normal file
@ -0,0 +1,88 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_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
|
322
engines/watchmaker/3d/material.cpp
Normal file
322
engines/watchmaker/3d/material.cpp
Normal 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
|
77
engines/watchmaker/3d/material.h
Normal file
77
engines/watchmaker/3d/material.h
Normal 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
|
26
engines/watchmaker/3d/math/Matrix4x4.cpp
Normal file
26
engines/watchmaker/3d/math/Matrix4x4.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/math/Matrix4x4.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
69
engines/watchmaker/3d/math/Matrix4x4.h
Normal file
69
engines/watchmaker/3d/math/Matrix4x4.h
Normal file
@ -0,0 +1,69 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_MATRIX4X4_H
|
||||
#define WATCHMAKER_MATRIX4X4_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
struct Matrix4x4 {
|
||||
float data[16] = {};
|
||||
|
||||
void setIdentity() {
|
||||
setValue(1, 1, 1.0f);
|
||||
setValue(2, 2, 1.0f);
|
||||
setValue(3, 3, 1.0f);
|
||||
setValue(4, 4, 1.0f);
|
||||
}
|
||||
|
||||
void setValue(int row, int col, float value) {
|
||||
data[(col - 1) * 4 + (row - 1)] = value;
|
||||
}
|
||||
float getValue(int row, int col) const {
|
||||
return data[(col - 1) * 4 + (row - 1)];
|
||||
}
|
||||
void print() const {
|
||||
for (int row = 1; row <= 4; row++) {
|
||||
for (int col = 1; col <= 4; col++) {
|
||||
warning("%f ", getValue(row, col));
|
||||
}
|
||||
warning("\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
|
427
engines/watchmaker/3d/math/llmath.cpp
Normal file
427
engines/watchmaker/3d/math/llmath.cpp
Normal file
@ -0,0 +1,427 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/utils.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
int32 t3dFloatToInt(t3dF32 nfloat) {
|
||||
int32 sint = nfloat;
|
||||
// warning("STUBBED: t3dFloatToInt\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
|
68
engines/watchmaker/3d/math/llmath.h
Normal file
68
engines/watchmaker/3d/math/llmath.h
Normal 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
|
90
engines/watchmaker/3d/mem_management.cpp
Normal file
90
engines/watchmaker/3d/mem_management.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/mem_management.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/ll/ll_system.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
static int8 *MemoryPool = nullptr;
|
||||
static uint32 MemoryPoolPointer = 0;
|
||||
static uint32 MaxAllocatedMem = 0;
|
||||
|
||||
// Memory 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
|
34
engines/watchmaker/3d/mem_management.h
Normal file
34
engines/watchmaker/3d/mem_management.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_MEM_MANAGEMENT_H
|
||||
#define WATCHMAKER_MEM_MANAGEMENT_H
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
unsigned char t3dAllocMemoryPool(unsigned int pool);
|
||||
void t3dDeallocMemoryPool();
|
||||
void *t3dAlloc(unsigned int size);
|
||||
void *t3dDealloc(unsigned int size);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_MEM_MANAGEMENT_H
|
26
engines/watchmaker/3d/movie.cpp
Normal file
26
engines/watchmaker/3d/movie.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/movie.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
52
engines/watchmaker/3d/movie.h
Normal file
52
engines/watchmaker/3d/movie.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_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
|
36
engines/watchmaker/3d/render/opengl.cpp
Normal file
36
engines/watchmaker/3d/render/opengl.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/render/opengl.h"
|
||||
#include "watchmaker/utils.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
//*********************************************************************************************
|
||||
bool rGetStencilBitDepth() {
|
||||
#if 0
|
||||
return gStencilBitDepth;
|
||||
#endif
|
||||
//warning("TODO: Implement rGetStencilBitDepth\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
29
engines/watchmaker/3d/render/opengl.h
Normal file
29
engines/watchmaker/3d/render/opengl.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_OPENGL_H
|
||||
#define WATCHMAKER_OPENGL_H
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_OPENGL_H
|
348
engines/watchmaker/3d/render/opengl_2d.cpp
Normal file
348
engines/watchmaker/3d/render/opengl_2d.cpp
Normal 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
|
48
engines/watchmaker/3d/render/opengl_2d.h
Normal file
48
engines/watchmaker/3d/render/opengl_2d.h
Normal 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
|
967
engines/watchmaker/3d/render/opengl_3d.cpp
Normal file
967
engines/watchmaker/3d/render/opengl_3d.cpp
Normal 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
|
67
engines/watchmaker/3d/render/opengl_3d.h
Normal file
67
engines/watchmaker/3d/render/opengl_3d.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_OPENGL_3D_H
|
||||
#define WATCHMAKER_OPENGL_3D_H
|
||||
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/render.h"
|
||||
|
||||
#define MAXTEXTURES 2000
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
struct gAvailFormat {
|
||||
//DDPIXELFORMAT SurfaceDesc;
|
||||
char rbits;
|
||||
char gbits;
|
||||
char bbits;
|
||||
char abits;
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
float sx, sy, sz, rhw;
|
||||
uint32 color;
|
||||
};
|
||||
|
||||
extern unsigned int gNumTrianglesArray;
|
||||
extern unsigned int gNumLinesArray;
|
||||
|
||||
extern gAvailFormat *gCurrentFormat;
|
||||
extern int NumAvailableFormats;
|
||||
extern gAvailFormat AvailableFormats[];
|
||||
|
||||
extern gTexture gTextureList[];
|
||||
extern unsigned int gNumTextureList;
|
||||
|
||||
extern uint16 gLinesArray[];
|
||||
extern unsigned int gNumLinesArray;
|
||||
extern unsigned int gNumTrianglesArray;
|
||||
extern Vertex gTriangles[];
|
||||
extern int g_lpD3DPointsBuffer;
|
||||
extern void *g_lpD3DUserVertexBuffer;
|
||||
extern unsigned int g_dwD3DUserVertexBufferCounter;
|
||||
extern unsigned int gNumPointsBuffer;
|
||||
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_OPENGL_3D_H
|
201
engines/watchmaker/3d/render/opengl_renderer.cpp
Normal file
201
engines/watchmaker/3d/render/opengl_renderer.cpp
Normal 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
|
104
engines/watchmaker/3d/render/opengl_renderer.h
Normal file
104
engines/watchmaker/3d/render/opengl_renderer.h
Normal 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
|
693
engines/watchmaker/3d/render/render.cpp
Normal file
693
engines/watchmaker/3d/render/render.cpp
Normal 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
|
29
engines/watchmaker/3d/render/render.h
Normal file
29
engines/watchmaker/3d/render/render.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_3D_RENDER_H
|
||||
#define WATCHMAKER_3D_RENDER_H
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_3D_RENDER_H
|
945
engines/watchmaker/3d/render/shadows.cpp
Normal file
945
engines/watchmaker/3d/render/shadows.cpp
Normal file
@ -0,0 +1,945 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/render/shadows.h"
|
||||
#include "watchmaker/3d/math/Matrix4x4.h"
|
||||
|
||||
|
||||
#define MAX_SHADOW_BOXES 20 // max shadows
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
SHADOWBOX *ShadowBoxesList[MAX_SHADOW_BOXES];
|
||||
unsigned int gNumShadowBoxesList = 0;
|
||||
|
||||
unsigned int gGetTextureListPosition();
|
||||
extern unsigned int CurLoaderFlags;
|
||||
#if 0
|
||||
#pragma pack(1)
|
||||
struct COLORVERTEX { // vertex structures
|
||||
D3DVECTOR p;
|
||||
D3DCOLOR c;
|
||||
};
|
||||
|
||||
struct TRANSCOLORVERTEX { // transformed vertex
|
||||
D3DVECTOR p;
|
||||
D3DVALUE rhw;
|
||||
D3DCOLOR c;
|
||||
};
|
||||
#pragma pack()
|
||||
#endif
|
||||
#define MAX_SHADOW_BOXES 20 // max shadows
|
||||
|
||||
bool g_bUseOneBitStencil = FALSE; // if Stencil buffer if 1 bit deep only
|
||||
DWORD g_max_StencilVal = 255; // maximum value the stencil buffer will hold
|
||||
#if 0
|
||||
D3DSTENCILOP g_StencDecOp, g_StencIncOp; // increment e decrement functions
|
||||
|
||||
LPDIRECTDRAWSURFACE7 g_pddsShadowBuffer = NULL;
|
||||
LPDIRECTDRAWSURFACE7 g_pddsShadowZBuffer = NULL;
|
||||
#endif
|
||||
//************************************************************************************************
|
||||
inline void SetIdentityMatrix(Matrix4x4 &m) { // set D3D matrix to identity
|
||||
m.setIdentity();
|
||||
}
|
||||
|
||||
#if 0
|
||||
//************************************************************************************************
|
||||
int ccw(COLORVERTEX *P[], int i, int j, int k) { // for convex-hull
|
||||
double a = P[i]->p.x - P[j]->p.x,
|
||||
b = P[i]->p.y - P[j]->p.y,
|
||||
c = P[k]->p.x - P[j]->p.x,
|
||||
d = P[k]->p.y - P[j]->p.y;
|
||||
return a * d - b * c <= 0; // true if points i, j, k counterclockwise
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int cmpl(const void *a, const void *b) { // for convex-hull
|
||||
float v;
|
||||
COLORVERTEX **av, **bv;
|
||||
|
||||
av = (COLORVERTEX **)a;
|
||||
bv = (COLORVERTEX **)b;
|
||||
|
||||
v = (*av)->p.x - (*bv)->p.x;
|
||||
|
||||
if (v > 0) return 1;
|
||||
if (v < 0) return -1;
|
||||
|
||||
v = (*bv)->p.y - (*av)->p.y;
|
||||
|
||||
if (v > 0) return 1;
|
||||
if (v < 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int cmph(const void *a, const void *b) {
|
||||
return cmpl(b, a); // for convex-hull
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int make_chain(COLORVERTEX *V[], int n, int (*cmp)(const void *, const void *)) { // for convex-hull
|
||||
int i, j, s = 1;
|
||||
COLORVERTEX *t;
|
||||
|
||||
qsort(V, n, sizeof(COLORVERTEX *), cmp);
|
||||
for (i = 2; i < n; i++) {
|
||||
for (j = s; j >= 1 && ccw(V, i, j, j - 1); j--)
|
||||
{}
|
||||
s = j + 1;
|
||||
t = V[s];
|
||||
V[s] = V[i];
|
||||
V[i] = t;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int ch2d(COLORVERTEX *P[], int n) { // for convex-hull
|
||||
int u = make_chain(P, n, cmpl); // make lower hull
|
||||
if (!n) return 0;
|
||||
P[n] = P[0];
|
||||
return u + make_chain(P + u, n - u + 1, cmph); // make upper hull
|
||||
}
|
||||
|
||||
//************************************************************************************************
|
||||
void Find2DConvexHull(DWORD nverts, COLORVERTEX *pntptr, DWORD *cNumOutIdxs, WORD **OutHullIdxs) { // find a convex hull
|
||||
COLORVERTEX **PntPtrs;
|
||||
DWORD i;
|
||||
|
||||
*cNumOutIdxs = 0; //max space needed is n+1 indices
|
||||
*OutHullIdxs = (WORD *)malloc((nverts + 1) * (sizeof(DWORD) + sizeof(COLORVERTEX *)));
|
||||
|
||||
PntPtrs = (COLORVERTEX **) & (*OutHullIdxs)[nverts + 1];
|
||||
|
||||
// alg requires array of ptrs to verts (for qsort) instead of array of verts, so do the conversion
|
||||
for (i = 0; i < nverts; i++) {
|
||||
PntPtrs[i] = &pntptr[i];
|
||||
}
|
||||
|
||||
*cNumOutIdxs = ch2d(PntPtrs, nverts);
|
||||
|
||||
// convert back to array of idxs
|
||||
for (i = 0; i < *cNumOutIdxs; i++) {
|
||||
(*OutHullIdxs)[i] = (WORD)(PntPtrs[i] - &pntptr[0]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* -----------------25/08/1999 16.41-----------------
|
||||
* find 2D convex hull for the object
|
||||
* --------------------------------------------------*/
|
||||
bool rMakeShadowVolume(SHADOWBOX *sb, gVertex *InVerts, DWORD nverts, float lightm[9]) {
|
||||
warning("Stubbed: rMakeShadowVolume\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
|
44
engines/watchmaker/3d/render/shadows.h
Normal file
44
engines/watchmaker/3d/render/shadows.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_SHADOWS_H
|
||||
#define WATCHMAKER_SHADOWS_H
|
||||
|
||||
#include "watchmaker/render.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
extern SHADOWBOX *ShadowBoxesList[];
|
||||
extern unsigned int gNumShadowBoxesList;
|
||||
extern void *g_pddsShadowBuffer;
|
||||
extern void *g_pddsShadowZBuffer;
|
||||
|
||||
//extern D3DSTENCILOP g_StencDecOp,g_StencIncOp;
|
||||
bool RenderShadow(SHADOW *pShad, void *lpVBuf);
|
||||
bool RenderShadowBox(SHADOWBOX *pSB, int VBO);
|
||||
bool DrawShadow(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, WORD intens);
|
||||
extern DWORD g_max_StencilVal; // maximum value the stencil buffer will hold
|
||||
extern bool RenderProjectiveShadow(SHADOW *pShad);
|
||||
bool DrawProjectiveShadow(SHADOW *pShad);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_SHADOWS_H
|
615
engines/watchmaker/3d/t3d_body.cpp
Normal file
615
engines/watchmaker/3d/t3d_body.cpp
Normal 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
|
92
engines/watchmaker/3d/t3d_body.h
Normal file
92
engines/watchmaker/3d/t3d_body.h
Normal 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
|
275
engines/watchmaker/3d/t3d_mesh.cpp
Normal file
275
engines/watchmaker/3d/t3d_mesh.cpp
Normal 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
|
147
engines/watchmaker/3d/t3d_mesh.h
Normal file
147
engines/watchmaker/3d/t3d_mesh.h
Normal 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
|
26
engines/watchmaker/3d/texture.cpp
Normal file
26
engines/watchmaker/3d/texture.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/texture.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
51
engines/watchmaker/3d/texture.h
Normal file
51
engines/watchmaker/3d/texture.h
Normal 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
|
26
engines/watchmaker/3d/types3d.cpp
Normal file
26
engines/watchmaker/3d/types3d.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/types3d.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
114
engines/watchmaker/3d/types3d.h
Normal file
114
engines/watchmaker/3d/types3d.h
Normal 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
|
26
engines/watchmaker/3d/vertex.cpp
Normal file
26
engines/watchmaker/3d/vertex.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/vertex.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
52
engines/watchmaker/3d/vertex.h
Normal file
52
engines/watchmaker/3d/vertex.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_VERTEX_H
|
||||
#define WATCHMAKER_VERTEX_H
|
||||
|
||||
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
// VertexBuffer vertices definition
|
||||
#pragma pack(1)
|
||||
struct gVertex {
|
||||
float x; // untransformed vertex
|
||||
float y;
|
||||
float z;
|
||||
int32 diffuse; // diffuse color
|
||||
float u1; // texture set for primary texture
|
||||
float v1;
|
||||
float u2; // texture set for lightmaps
|
||||
float v2;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
struct pVert {
|
||||
float x, y, z, rhw; // transformed vertex
|
||||
DWORD diffuse; // diffuse color
|
||||
} ;
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_VERTEX_H
|
240
engines/watchmaker/classes/do_action.cpp
Normal file
240
engines/watchmaker/classes/do_action.cpp
Normal 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
|
34
engines/watchmaker/classes/do_action.h
Normal file
34
engines/watchmaker/classes/do_action.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_ACTION_H
|
||||
#define WATCHMAKER_DO_ACTION_H
|
||||
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doAction(WGame &game);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_ACTION_H
|
53
engines/watchmaker/classes/do_anim.cpp
Normal file
53
engines/watchmaker/classes/do_anim.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_anim.h"
|
||||
#include "watchmaker/game.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/ll/ll_anim.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
/* -----------------15/12/98 10.03-------------------
|
||||
* doAnimation
|
||||
* --------------------------------------------------*/
|
||||
void doAnimation(WGame &game) {
|
||||
switch (TheMessage->event) {
|
||||
case ME_STARTANIM:
|
||||
StartAnim(game, TheMessage->wparam1);
|
||||
break;
|
||||
|
||||
case ME_STOPANIM:
|
||||
StopAnim(game, TheMessage->wparam1);
|
||||
break;
|
||||
|
||||
case ME_PAUSEANIM:
|
||||
PauseAnim(game.init, TheMessage->wparam1);
|
||||
break;
|
||||
|
||||
case ME_CONTINUEANIM:
|
||||
ContinueAnim(game.init, TheMessage->wparam1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
33
engines/watchmaker/classes/do_anim.h
Normal file
33
engines/watchmaker/classes/do_anim.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_ANIM_H
|
||||
#define WATCHMAKER_DO_ANIM_H
|
||||
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doAnimation(WGame &game);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_ANIM_H
|
925
engines/watchmaker/classes/do_camera.cpp
Normal file
925
engines/watchmaker/classes/do_camera.cpp
Normal 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
|
47
engines/watchmaker/classes/do_camera.h
Normal file
47
engines/watchmaker/classes/do_camera.h
Normal 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
|
545
engines/watchmaker/classes/do_dialog.cpp
Normal file
545
engines/watchmaker/classes/do_dialog.cpp
Normal 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
|
42
engines/watchmaker/classes/do_dialog.h
Normal file
42
engines/watchmaker/classes/do_dialog.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_DIALOG_H
|
||||
#define WATCHMAKER_DO_DIALOG_H
|
||||
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
extern int16 NextDlg;
|
||||
|
||||
void doDialog(WGame &game);
|
||||
void PaintDialog(WGame &game);
|
||||
void UpdateDialogMenu(WGame &game, int16 dmx, int16 dmy, uint8 db);
|
||||
int32 GetAlternateAnim(Init &init, int32 an);
|
||||
uint8 GetAlternateCamera(Init &init, uint8 cam);
|
||||
uint8 GetAlternatePosition(Init &init, uint8 pos);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_DIALOG_H
|
392
engines/watchmaker/classes/do_inv.cpp
Normal file
392
engines/watchmaker/classes/do_inv.cpp
Normal 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
|
43
engines/watchmaker/classes/do_inv.h
Normal file
43
engines/watchmaker/classes/do_inv.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_INV_H
|
||||
#define WATCHMAKER_DO_INV_H
|
||||
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void AddIcon(Init &init, uint8 icon);
|
||||
void doInventory(WGame &game);
|
||||
void doUseWith(WGame &game);
|
||||
void KillIcon(Init &init, uint8 icon);
|
||||
uint8 IconInInv(Init &init, uint8 icon);
|
||||
void ReplaceIcon(Init &init, uint8 oldicon, uint8 newicon);
|
||||
void ClearUseWith();
|
||||
void InventoryUp();
|
||||
void InventoryDown();
|
||||
uint8 WhatIcon(Renderer &renderer, int16 invmx, int16 invmy);
|
||||
void SelectCurBigIcon(uint8 icon);
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_INV_H
|
133
engines/watchmaker/classes/do_inv_inv.cpp
Normal file
133
engines/watchmaker/classes/do_inv_inv.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_inv_inv.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/schedule.h"
|
||||
#include "watchmaker/classes/do_inv.h"
|
||||
#include "watchmaker/ll/ll_diary.h"
|
||||
#include "watchmaker/classes/do_sound.h"
|
||||
#include "watchmaker/classes/do_string.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
/* -----------------19/05/98 16.40-------------------
|
||||
* doInvInvUseWith
|
||||
* --------------------------------------------------*/
|
||||
void doInvInvUseWith(WGame &game) {
|
||||
uint8 sent = TRUE;
|
||||
Init &init = game.init;
|
||||
|
||||
switch (UseWith[USED]) {
|
||||
case i00TELEFONO:
|
||||
case i00TELEFONOVIC:
|
||||
if ((UseWith[WITH] == i28WALKMANOK) && (init.InvObj[i28WALKMANOK].flags & EXTRA)) {
|
||||
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
|
33
engines/watchmaker/classes/do_inv_inv.h
Normal file
33
engines/watchmaker/classes/do_inv_inv.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_INV_INV_H
|
||||
#define WATCHMAKER_DO_INV_INV_H
|
||||
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doInvInvUseWith(WGame &game);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_INV_INV_H
|
608
engines/watchmaker/classes/do_inv_scr.cpp
Normal file
608
engines/watchmaker/classes/do_inv_scr.cpp
Normal file
@ -0,0 +1,608 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_inv_scr.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/message.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/schedule.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/classes/do_string.h"
|
||||
#include "watchmaker/classes/do_inv.h"
|
||||
#include "watchmaker/ll/ll_mesh.h"
|
||||
#include "watchmaker/ll/ll_anim.h"
|
||||
#include "watchmaker/ll/ll_diary.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
/* -----------------19/05/98 16.40-------------------
|
||||
* doInvScrUseWith
|
||||
* --------------------------------------------------*/
|
||||
void doInvScrUseWith(WGame &game) {
|
||||
uint8 sent = FALSE;
|
||||
int32 sa = 0;
|
||||
Init &init = game.init;
|
||||
|
||||
//messo fuori perche' andava in conflitto con l'usacon dell'icona
|
||||
if ((UseWith[USED] == i29FOTOPROGETTO) && (UseWith[WITH] == ocCUSTODE)) {
|
||||
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
|
33
engines/watchmaker/classes/do_inv_scr.h
Normal file
33
engines/watchmaker/classes/do_inv_scr.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_INV_SCR_H
|
||||
#define WATCHMAKER_DO_INV_SCR_H
|
||||
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doInvScrUseWith(WGame &game);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_INV_SCR_H
|
741
engines/watchmaker/classes/do_keyboard.cpp
Normal file
741
engines/watchmaker/classes/do_keyboard.cpp
Normal 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
|
36
engines/watchmaker/classes/do_keyboard.h
Normal file
36
engines/watchmaker/classes/do_keyboard.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_KEYBOARD_H
|
||||
#define WATCHMAKER_DO_KEYBOARD_H
|
||||
|
||||
#include "watchmaker/globvar.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doClock33(WGame &game, int obj, struct t3dV3F *mp);
|
||||
void ProcessKeyboard(WGame &game);
|
||||
void ProcessKBInput();
|
||||
extern unsigned char KeyTable[256];
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_KEYBOARD_H
|
346
engines/watchmaker/classes/do_mouse.cpp
Normal file
346
engines/watchmaker/classes/do_mouse.cpp
Normal 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
|
34
engines/watchmaker/classes/do_mouse.h
Normal file
34
engines/watchmaker/classes/do_mouse.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_MOUSE_H
|
||||
#define WATCHMAKER_DO_MOUSE_H
|
||||
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doMouse(WGame &game);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_MOUSE_H
|
1029
engines/watchmaker/classes/do_operate.cpp
Normal file
1029
engines/watchmaker/classes/do_operate.cpp
Normal file
File diff suppressed because it is too large
Load Diff
35
engines/watchmaker/classes/do_operate.h
Normal file
35
engines/watchmaker/classes/do_operate.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_OPERATE_H
|
||||
#define WATCHMAKER_DO_OPERATE_H
|
||||
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void UpdateSpecial(WGame &game, int32 room);
|
||||
void doOperate(WGame &game, int32 obj);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_OPERATE_H
|
517
engines/watchmaker/classes/do_player.cpp
Normal file
517
engines/watchmaker/classes/do_player.cpp
Normal 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
|
42
engines/watchmaker/classes/do_player.h
Normal file
42
engines/watchmaker/classes/do_player.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_PLAYER_H
|
||||
#define WATCHMAKER_DO_PLAYER_H
|
||||
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void SetCurPlayerPosTo_9x(GameVars &gameVars, Init &init);
|
||||
void doPlayer(WGame &game);
|
||||
void ChangePlayer(WGame &game, uint8 oc);
|
||||
void ProcessCharacters(WGame &game);
|
||||
void UpdatePlayerStand(WGame &game, uint8 oc);
|
||||
int PlayerCanSwitch(GameVars &gameVars, char no_inventory);
|
||||
int PlayerCanCall(GameVars &gameVars);
|
||||
int PlayerCanSave();
|
||||
int IsPlayerInPool();
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_PLAYER_H
|
55
engines/watchmaker/classes/do_scr_scr.cpp
Normal file
55
engines/watchmaker/classes/do_scr_scr.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/classes/do_scr_scr.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/ll/ll_anim.h"
|
||||
#include "watchmaker/classes/do_string.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
/* -----------------19/05/98 16.40-------------------
|
||||
* doScrScrUseWith
|
||||
* --------------------------------------------------*/
|
||||
void doScrScrUseWith(WGame &game) {
|
||||
uint8 sent = TRUE;
|
||||
|
||||
switch (UseWith[USED]) {
|
||||
case o2DQUADRODIVANO:
|
||||
if (UseWith[WITH] == o2DCASSAFORTECH) {
|
||||
StartAnim(game, a2D6);
|
||||
sent = false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sent = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sent)
|
||||
if (!(!(bUseWith & UW_WITHI) && (UseWith[USED] == UseWith[WITH])))
|
||||
PlayerSpeak(game, game.init.Obj[UseWith[USED]].action[CurPlayer]);
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
34
engines/watchmaker/classes/do_scr_scr.h
Normal file
34
engines/watchmaker/classes/do_scr_scr.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_SCR_SCR_H
|
||||
#define WATCHMAKER_DO_SCR_SCR_H
|
||||
|
||||
#include "watchmaker/saveload.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doScrScrUseWith(WGame &game);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_SCR_SCR_H
|
372
engines/watchmaker/classes/do_sound.cpp
Normal file
372
engines/watchmaker/classes/do_sound.cpp
Normal 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
|
40
engines/watchmaker/classes/do_sound.h
Normal file
40
engines/watchmaker/classes/do_sound.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_SOUND_H
|
||||
#define WATCHMAKER_DO_SOUND_H
|
||||
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
bool InitMusic();
|
||||
bool StartSound(WGame &game, int32 index);
|
||||
bool StartStepSound(WGame &game, t3dV3F *pos, uint8 side);
|
||||
bool StopSound(int32 index);
|
||||
bool StopSounds();
|
||||
bool StopMusic();
|
||||
bool StartSpeech(WGame &game, int32 n);
|
||||
bool PlayMusic(int32 index, uint32 FadeOutTime, uint32 FadeInTime);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_SOUND_H
|
250
engines/watchmaker/classes/do_string.cpp
Normal file
250
engines/watchmaker/classes/do_string.cpp
Normal 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
|
38
engines/watchmaker/classes/do_string.h
Normal file
38
engines/watchmaker/classes/do_string.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_STRING_H
|
||||
#define WATCHMAKER_DO_STRING_H
|
||||
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void doString(WGame &game);
|
||||
bool PlayerSpeak(WGame &game, int32 n);
|
||||
void ShowObjName(Init &init, int32 ob);
|
||||
void ShowInvObjName(Init &init, int32 obj);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_STRING_H
|
1039
engines/watchmaker/classes/do_system.cpp
Normal file
1039
engines/watchmaker/classes/do_system.cpp
Normal file
File diff suppressed because it is too large
Load Diff
40
engines/watchmaker/classes/do_system.h
Normal file
40
engines/watchmaker/classes/do_system.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_DO_SYSTEM_H
|
||||
#define WATCHMAKER_DO_SYSTEM_H
|
||||
|
||||
#include "watchmaker/struct.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
void InitMain(WGame &game);
|
||||
|
||||
extern SRoomInfo RoomInfo;
|
||||
void NextMessage(WGame &game);
|
||||
void doSystem(WGame &game);
|
||||
void TitoliCoda_ShowStatic(WGame &game, char initialize);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_DO_SYSTEM_H
|
4751
engines/watchmaker/define.h
Normal file
4751
engines/watchmaker/define.h
Normal file
File diff suppressed because it is too large
Load Diff
107
engines/watchmaker/extraLS.cpp
Normal file
107
engines/watchmaker/extraLS.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/extraLS.h"
|
||||
#include "watchmaker/struct.h"
|
||||
#include "watchmaker/ll/ll_mouse.h"
|
||||
#include "watchmaker/ll/ll_util.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
char *ExtraLS[MAX_EXTRALS];
|
||||
|
||||
#define EXTRALS_BKG_COLOR_R 50
|
||||
#define EXTRALS_BKG_COLOR_G 0
|
||||
#define EXTRALS_BKG_COLOR_B 224
|
||||
|
||||
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
|
88
engines/watchmaker/extraLS.h
Normal file
88
engines/watchmaker/extraLS.h
Normal file
@ -0,0 +1,88 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_EXTRALS_H
|
||||
#define WATCHMAKER_EXTRALS_H
|
||||
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
|
||||
#define MAX_EXTRALS 55
|
||||
|
||||
#define EXTRALS_SAVE 1
|
||||
#define EXTRALS_LOAD 2
|
||||
#define EXTRALS_OPTIONS 3
|
||||
#define EXTRALS_QUIT 4
|
||||
#define EXTRALS_CLOSE 5
|
||||
#define EXTRALS_NOCONNECTION 6
|
||||
#define EXTRALS_INVALIDNUMBER 7
|
||||
#define EXTRALS_DIAL 8
|
||||
#define EXTRALS_ENTERUSERNUMBER 9
|
||||
#define EXTRALS_DOCUMENTS 10
|
||||
#define EXTRALS_DOCUMENTVIEWER 11
|
||||
#define EXTRALS_EMAILVIEWER 12
|
||||
#define EXTRALS_EMAIL 13
|
||||
#define EXTRALS_AVAILABLEEMAIL 14
|
||||
#define EXTRALS_OK 15
|
||||
#define EXTRALS_CANCEL 16
|
||||
#define EXTRALS_CLEAR 17
|
||||
#define EXTRALS_DIALLING 18
|
||||
#define EXTRALS_SEARCH 19
|
||||
#define EXTRALS_FINDBY 20
|
||||
#define EXTRALS_NAME 21
|
||||
#define EXTRALS_SURNAME 22
|
||||
#define EXTRALS_SUBJECT 23
|
||||
#define EXTRALS_CASENAME 24
|
||||
#define EXTRALS_YEAR 25
|
||||
#define EXTRALS_NODOCUMENTS 26
|
||||
#define EXTRALS_NEWMAIL 27
|
||||
#define EXTRALS_CIAMAINTERMINAL 28
|
||||
#define EXTRALS_GAMEOVER 29
|
||||
#define EXTRALS_EXIT 30
|
||||
#define EXTRALS_PLAYTHEGAME 31
|
||||
#define EXTRALS_LOADAGAME 32
|
||||
#define EXTRALS_MAINMENU 33
|
||||
#define EXTRALS_HELP 34
|
||||
#define EXTRALS_LOGVIEWER 35
|
||||
#define EXTRALS_TONESEQUENCER 36
|
||||
#define EXTRALS_ACQUIRE 37
|
||||
#define EXTRALS_PROCESS 38
|
||||
#define EXTRALS_LOG 39
|
||||
#define EXTRALS_PREVIEW 40
|
||||
#define EXTRALS_SCAN 41
|
||||
#define EXTRALS_SELECTAREA 42
|
||||
#define EXTRALS_SCANPROGRAM 43
|
||||
#define EXTRALS_MUSIC 44
|
||||
#define EXTRALS_SOUND 45
|
||||
#define EXTRALS_SPEECH 46
|
||||
#define EXTRALS_SUBTITLES 47
|
||||
#define EXTRALS_DARRELL 48
|
||||
#define EXTRALS_VICTORIA 49
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
extern char *ExtraLS[MAX_EXTRALS];
|
||||
|
||||
void CheckExtraLocalizationStrings(Renderer &renderer, uint32 id);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_EXTRALS_H
|
705
engines/watchmaker/game.cpp
Normal file
705
engines/watchmaker/game.cpp
Normal 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
101
engines/watchmaker/game.h
Normal 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
|
26
engines/watchmaker/game_options.cpp
Normal file
26
engines/watchmaker/game_options.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/game_options.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
96
engines/watchmaker/game_options.h
Normal file
96
engines/watchmaker/game_options.h
Normal file
@ -0,0 +1,96 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_GAME_OPTIONS_H
|
||||
#define WATCHMAKER_GAME_OPTIONS_H
|
||||
#include "common/stream.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/work_dirs.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
class GameOptions {
|
||||
public:
|
||||
uint8 sound_on = 1;
|
||||
uint8 sound_volume = 100;
|
||||
uint8 music_on = 1;
|
||||
uint8 music_volume = 100;
|
||||
uint8 speech_on = 1;
|
||||
uint8 speech_volume = 100;
|
||||
uint8 subtitles_on = 1;
|
||||
bool bShowRoomDescriptions = true;
|
||||
bool bShowExtraLocalizationStrings = false;
|
||||
bool load(WorkDirs &workDirs) {
|
||||
warning("TODO: Game options");
|
||||
#if 0
|
||||
Common::String path = workDirs._gameDir + workDirs._savesDir + "options.dat";
|
||||
|
||||
auto stream = openFile(path);
|
||||
|
||||
sound_on = stream->readByte();
|
||||
sound_volume = stream->readByte();
|
||||
music_on = stream->readByte();
|
||||
music_volume = stream->readByte();
|
||||
speech_on = stream->readByte();
|
||||
speech_volume = stream->readByte();
|
||||
subtitles_on = stream->readByte();
|
||||
bShowRoomDescriptions = stream->readByte();
|
||||
bShowExtraLocalizationStrings = stream->readByte();
|
||||
warning("Done loading options\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
|
205
engines/watchmaker/globvar.cpp
Normal file
205
engines/watchmaker/globvar.cpp
Normal 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
|
265
engines/watchmaker/globvar.h
Normal file
265
engines/watchmaker/globvar.h
Normal 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
|
127
engines/watchmaker/init/nl_init.cpp
Normal file
127
engines/watchmaker/init/nl_init.cpp
Normal 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
|
31
engines/watchmaker/init/nl_init.h
Normal file
31
engines/watchmaker/init/nl_init.h
Normal 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
|
52
engines/watchmaker/init/nl_parse.cpp
Normal file
52
engines/watchmaker/init/nl_parse.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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
|
33
engines/watchmaker/init/nl_parse.h
Normal file
33
engines/watchmaker/init/nl_parse.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_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
|
1863
engines/watchmaker/ll/ll_anim.cpp
Normal file
1863
engines/watchmaker/ll/ll_anim.cpp
Normal file
File diff suppressed because it is too large
Load Diff
46
engines/watchmaker/ll/ll_anim.h
Normal file
46
engines/watchmaker/ll/ll_anim.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_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
|
521
engines/watchmaker/ll/ll_diary.cpp
Normal file
521
engines/watchmaker/ll/ll_diary.cpp
Normal 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
|
43
engines/watchmaker/ll/ll_diary.h
Normal file
43
engines/watchmaker/ll/ll_diary.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_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
|
93
engines/watchmaker/ll/ll_ffile.cpp
Normal file
93
engines/watchmaker/ll/ll_ffile.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "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
|
46
engines/watchmaker/ll/ll_ffile.h
Normal file
46
engines/watchmaker/ll/ll_ffile.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_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
|
865
engines/watchmaker/ll/ll_mesh.cpp
Normal file
865
engines/watchmaker/ll/ll_mesh.cpp
Normal 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
|
53
engines/watchmaker/ll/ll_mesh.h
Normal file
53
engines/watchmaker/ll/ll_mesh.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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
|
180
engines/watchmaker/ll/ll_mouse.cpp
Normal file
180
engines/watchmaker/ll/ll_mouse.cpp
Normal 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
|
40
engines/watchmaker/ll/ll_mouse.h
Normal file
40
engines/watchmaker/ll/ll_mouse.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_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
|
458
engines/watchmaker/ll/ll_regen.cpp
Normal file
458
engines/watchmaker/ll/ll_regen.cpp
Normal 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
|
36
engines/watchmaker/ll/ll_regen.h
Normal file
36
engines/watchmaker/ll/ll_regen.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_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
|
102
engines/watchmaker/ll/ll_sound.cpp
Normal file
102
engines/watchmaker/ll/ll_sound.cpp
Normal 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
|
102
engines/watchmaker/ll/ll_sound.h
Normal file
102
engines/watchmaker/ll/ll_sound.h
Normal 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
|
310
engines/watchmaker/ll/ll_string.cpp
Normal file
310
engines/watchmaker/ll/ll_string.cpp
Normal 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
|
40
engines/watchmaker/ll/ll_string.h
Normal file
40
engines/watchmaker/ll/ll_string.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_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
|
192
engines/watchmaker/ll/ll_system.cpp
Normal file
192
engines/watchmaker/ll/ll_system.cpp
Normal 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
Loading…
x
Reference in New Issue
Block a user