Removed GemRB sources - it's now compilable straight from Git
This commit is contained in:
@@ -5,12 +5,12 @@ AppName="GemRB"
|
||||
AppFullName=net.sourceforge.gemrb
|
||||
ScreenOrientation=h
|
||||
InhibitSuspend=n
|
||||
AppDataDownloadUrl="Baldur's gate 2 demo|http://sourceforge.net/projects/libsdl-android/files/gemrb/bg2demo.zip/download^!GemRB data(override)|override4.zip^!GemRB data(scripts)|scripts4.zip"
|
||||
AppDataDownloadUrl="Baldur's Gate 2 demo (800 Mb)|http://sourceforge.net/projects/libsdl-android/files/gemrb/bg2demo.zip/download^!GemRB data(override)|override10.zip^!GemRB data(scripts)|scripts10.zip"
|
||||
VideoDepthBpp=16
|
||||
NeedDepthBuffer=n
|
||||
NeedStencilBuffer=n
|
||||
NeedGles2=n
|
||||
SwVideoMode=n
|
||||
SwVideoMode=y
|
||||
SdlVideoResize=y
|
||||
SdlVideoResizeKeepAspect=y
|
||||
CompatibilityHacks=n
|
||||
@@ -31,9 +31,9 @@ StartupMenuButtonTimeout=2000
|
||||
HiddenMenuOptions=''
|
||||
FirstStartMenuOptions=''
|
||||
MultiABI=y
|
||||
AppVersionCode=0643
|
||||
AppVersionName="0.6.4.3"
|
||||
CompiledLibraries="sdl_mixer ogg vorbis openal png python"
|
||||
AppVersionCode=0700
|
||||
AppVersionName="0.7.0.0"
|
||||
CompiledLibraries="sdl_mixer sdl_ttf ogg vorbis openal png python"
|
||||
CustomBuildScript=n
|
||||
AppCflags='-fexceptions -finline-functions -O3 -DSTATIC_LINK=Yes -DHAVE_SNPRINTF'
|
||||
AppLdflags=''
|
||||
|
||||
BIN
project/jni/application/gemrb/AndroidData/override10.zip
Normal file
BIN
project/jni/application/gemrb/AndroidData/override10.zip
Normal file
Binary file not shown.
Binary file not shown.
BIN
project/jni/application/gemrb/AndroidData/scripts10.zip
Normal file
BIN
project/jni/application/gemrb/AndroidData/scripts10.zip
Normal file
Binary file not shown.
Binary file not shown.
@@ -1,90 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
// GemRB.cpp : Defines the entry point for the application.
|
||||
|
||||
#include "win32def.h" // logging
|
||||
|
||||
#include "Interface.h"
|
||||
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
//this supposed to convince SDL to work on OS/X
|
||||
//WARNING: commenting this out will cause SDL 1.2.x to crash
|
||||
#ifdef __APPLE_CC__ // we need startup SDL here
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <SDL/SDL.h>
|
||||
#include "Audio.h"
|
||||
|
||||
// pause audio playing if app goes in background
|
||||
static void appPutToBackground()
|
||||
{
|
||||
core->GetAudioDrv()->Pause();
|
||||
}
|
||||
// resume audio playing if app return to foreground
|
||||
static void appPutToForeground()
|
||||
{
|
||||
core->GetAudioDrv()->Resume();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#ifdef M_TRIM_THRESHOLD
|
||||
// Prevent fragmentation of the heap by malloc (glibc).
|
||||
//
|
||||
// The default threshold is 128*1024, which can result in a large memory usage
|
||||
// due to fragmentation since we use a lot of small objects. On the other hand
|
||||
// if the threshold is too low, free() starts to permanently ask the kernel
|
||||
// about shrinking the heap.
|
||||
#ifdef HAVE_UNISTD_H
|
||||
int pagesize = sysconf(_SC_PAGESIZE);
|
||||
#else
|
||||
int pagesize = 4*1024;
|
||||
#endif
|
||||
mallopt(M_TRIM_THRESHOLD, 5*pagesize);
|
||||
#endif
|
||||
|
||||
Interface::SanityCheck(VERSION_GEMRB);
|
||||
core = new Interface( argc, argv );
|
||||
if (core->Init() == GEM_ERROR) {
|
||||
delete( core );
|
||||
print("Press enter to continue...");
|
||||
textcolor(DEFAULT);
|
||||
getc(stdin);
|
||||
return -1;
|
||||
}
|
||||
#ifdef ANDROID
|
||||
SDL_ANDROID_SetApplicationPutToBackgroundCallback(&appPutToBackground, &appPutToForeground);
|
||||
#endif
|
||||
core->Main();
|
||||
delete( core );
|
||||
textcolor(DEFAULT);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ActorMgr.h"
|
||||
|
||||
ActorMgr::ActorMgr(void)
|
||||
{
|
||||
}
|
||||
|
||||
ActorMgr::~ActorMgr(void)
|
||||
{
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ACTORMGR_H
|
||||
#define ACTORMGR_H
|
||||
|
||||
#include "Plugin.h"
|
||||
|
||||
class Actor;
|
||||
class DataStream;
|
||||
|
||||
class GEM_EXPORT ActorMgr : public Plugin {
|
||||
public:
|
||||
ActorMgr(void);
|
||||
virtual ~ActorMgr(void);
|
||||
virtual bool Open(DataStream* stream) = 0;
|
||||
virtual Actor* GetActor(unsigned char is_in_party) = 0;
|
||||
|
||||
//returns saved size, updates internal offsets before save
|
||||
virtual int GetStoredFileSize(Actor *ac) = 0;
|
||||
//saves file
|
||||
virtual int PutActor(DataStream *stream, Actor *actor, bool chr=false) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,36 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2004 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Ambient.h"
|
||||
|
||||
Ambient::Ambient()
|
||||
{
|
||||
}
|
||||
|
||||
Ambient::~Ambient()
|
||||
{
|
||||
unsigned int i=sounds.size();
|
||||
while(i--) {
|
||||
free(sounds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Ambient::setActive() { flags |= IE_AMBI_ENABLED; }
|
||||
void Ambient::setInactive() { flags &= ~IE_AMBI_ENABLED; }
|
||||
@@ -1,77 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2004 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AMBIENT_H
|
||||
#define AMBIENT_H
|
||||
|
||||
#include "exports.h"
|
||||
#include "globals.h"
|
||||
#include "ie_types.h"
|
||||
|
||||
#include <bitset>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define IE_AMBI_ENABLED 1
|
||||
#define IE_AMBI_POINT 2
|
||||
#define IE_AMBI_MAIN 4
|
||||
#define IE_AMBI_AREA 8
|
||||
|
||||
class GEM_EXPORT Ambient {
|
||||
public:
|
||||
Ambient();
|
||||
~Ambient();
|
||||
|
||||
/* there is a good reason to have these in the header:
|
||||
* they are automatically inlined, so we have
|
||||
* no roundtrips and no overhead for accessors --Divide */
|
||||
const char *getName() const { return name; }
|
||||
const Point &getOrigin() const { return origin; }
|
||||
ieWord getRadius() const { return radius; }
|
||||
ieWord getHeight() const { return height; }
|
||||
ieWord getGain() const { return gain; }
|
||||
char *getSound(ieDword i) const
|
||||
{
|
||||
if(i<sounds.size()) return sounds[i];
|
||||
return NULL;
|
||||
}
|
||||
ieDword getInterval() const { return interval; }
|
||||
ieDword getPerset() const { return perset; }
|
||||
ieDword getAppearance() const { return appearance; }
|
||||
ieDword getFlags() const { return flags; }
|
||||
|
||||
void setActive();
|
||||
void setInactive();
|
||||
|
||||
public:
|
||||
char name[32];
|
||||
Point origin;
|
||||
ieWord radius;
|
||||
ieWord height;
|
||||
ieWord gain; // percent
|
||||
std::vector<char *> sounds;
|
||||
ieDword interval; // no pauses if zero
|
||||
ieDword perset;
|
||||
ieDword appearance;
|
||||
ieDword flags;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,62 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2004 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "AmbientMgr.h"
|
||||
|
||||
#include "Ambient.h"
|
||||
|
||||
AmbientMgr::AmbientMgr()
|
||||
{
|
||||
}
|
||||
|
||||
AmbientMgr::~AmbientMgr()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void AmbientMgr::activate(const std::string &name)
|
||||
{
|
||||
for (std::vector<Ambient *>::iterator it = ambients.begin(); it != ambients.end(); ++it) {
|
||||
if ((*it) -> getName() == name) {
|
||||
(*it) -> setActive();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AmbientMgr::deactivate(const std::string &name)
|
||||
{
|
||||
for (std::vector<Ambient *>::iterator it = ambients.begin(); it != ambients.end(); ++it) {
|
||||
if ((*it) -> getName() == name) {
|
||||
(*it) -> setInactive();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AmbientMgr::isActive(const std::string &name) const
|
||||
{
|
||||
for (std::vector<Ambient *>::const_iterator it = ambients.begin(); it != ambients.end(); ++it) {
|
||||
if ((*it) -> getName() == name) {
|
||||
return (*it) -> getFlags() & IE_AMBI_ENABLED;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2004 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AMBIENTMGR_H
|
||||
#define AMBIENTMGR_H
|
||||
|
||||
#include "exports.h"
|
||||
#include "win32def.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Ambient;
|
||||
|
||||
class GEM_EXPORT AmbientMgr {
|
||||
public:
|
||||
AmbientMgr();
|
||||
virtual ~AmbientMgr();
|
||||
virtual void reset() { ambients = std::vector<Ambient *> (); }
|
||||
virtual void setAmbients(const std::vector<Ambient *> &a) { reset(); ambients = a; activate(); }
|
||||
virtual void activate(const std::string &name);
|
||||
virtual void activate() { active = true; } // hard play ;-)
|
||||
virtual void deactivate(const std::string &name);
|
||||
virtual void deactivate() { active = false; } // hard stop
|
||||
virtual bool isActive(const std::string &name) const;
|
||||
protected:
|
||||
std::vector<Ambient *> ambients;
|
||||
bool active;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,29 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANIMSTRUCTURES_H
|
||||
#define ANIMSTRUCTURES_H
|
||||
|
||||
struct CycleEntry {
|
||||
ieWord FramesCount;
|
||||
ieWord FirstFrame;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,261 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Animation.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "Game.h"
|
||||
#include "Interface.h"
|
||||
#include "Map.h"
|
||||
#include "Sprite2D.h"
|
||||
#include "Video.h"
|
||||
|
||||
Animation::Animation(int count)
|
||||
{
|
||||
frames = (Sprite2D **) calloc(count, sizeof(Sprite2D *));
|
||||
indicesCount = count;
|
||||
if (count) {
|
||||
pos = rand() % count;
|
||||
}
|
||||
else {
|
||||
pos = 0;
|
||||
}
|
||||
starttime = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
Flags = A_ANI_ACTIVE;
|
||||
fps = 15;
|
||||
endReached = false;
|
||||
//behaviour flags
|
||||
playReversed = false;
|
||||
gameAnimation = false;
|
||||
}
|
||||
|
||||
Animation::~Animation(void)
|
||||
{
|
||||
Video *video = core->GetVideoDriver();
|
||||
|
||||
for (unsigned int i = 0; i < indicesCount; i++) {
|
||||
video->FreeSprite( frames[i] );
|
||||
}
|
||||
free(frames);
|
||||
}
|
||||
|
||||
void Animation::SetPos(unsigned int index)
|
||||
{
|
||||
if (index<indicesCount) {
|
||||
pos=index;
|
||||
}
|
||||
starttime = 0;
|
||||
endReached = false;
|
||||
}
|
||||
|
||||
/* when adding NULL, it means we already added a frame of index */
|
||||
void Animation::AddFrame(Sprite2D* frame, unsigned int index)
|
||||
{
|
||||
if (index>=indicesCount) {
|
||||
error("Animation", "You tried to write past a buffer in animation, BAD!\n");
|
||||
}
|
||||
core->GetVideoDriver()->FreeSprite(frames[index]);
|
||||
frames[index]=frame;
|
||||
|
||||
int x = -frame->XPos;
|
||||
int y = -frame->YPos;
|
||||
int w = frame->Width;
|
||||
int h = frame->Height;
|
||||
if (x < animArea.x) {
|
||||
animArea.w += (animArea.x - x);
|
||||
animArea.x = x;
|
||||
}
|
||||
if (y < animArea.y) {
|
||||
animArea.h += (animArea.y - y);
|
||||
animArea.y = y;
|
||||
}
|
||||
if (x+w > animArea.x+animArea.w) {
|
||||
animArea.w = x+w-animArea.x;
|
||||
}
|
||||
if (y+h > animArea.y+animArea.h) {
|
||||
animArea.h = y+h-animArea.y;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Animation::GetCurrentFrame() const
|
||||
{
|
||||
if (playReversed)
|
||||
return indicesCount-pos-1;
|
||||
return pos;
|
||||
}
|
||||
|
||||
Sprite2D* Animation::LastFrame(void)
|
||||
{
|
||||
if (!Flags&A_ANI_ACTIVE) {
|
||||
print("Frame fetched while animation is inactive!\n");
|
||||
return NULL;
|
||||
}
|
||||
if (gameAnimation) {
|
||||
starttime = core->GetGame()->Ticks;
|
||||
} else {
|
||||
starttime = GetTickCount();
|
||||
}
|
||||
Sprite2D* ret;
|
||||
if (playReversed)
|
||||
ret = frames[indicesCount-pos-1];
|
||||
else
|
||||
ret = frames[pos];
|
||||
return ret;
|
||||
}
|
||||
|
||||
Sprite2D* Animation::NextFrame(void)
|
||||
{
|
||||
if (!Flags&A_ANI_ACTIVE) {
|
||||
print("Frame fetched while animation is inactive!\n");
|
||||
return NULL;
|
||||
}
|
||||
if (starttime == 0) {
|
||||
if (gameAnimation) {
|
||||
starttime = core->GetGame()->Ticks;
|
||||
} else {
|
||||
starttime = GetTickCount();
|
||||
}
|
||||
}
|
||||
Sprite2D* ret;
|
||||
if (playReversed)
|
||||
ret = frames[indicesCount-pos-1];
|
||||
else
|
||||
ret = frames[pos];
|
||||
|
||||
if (endReached && (Flags&A_ANI_PLAYONCE) )
|
||||
return ret;
|
||||
|
||||
unsigned long time;
|
||||
if (gameAnimation) {
|
||||
time = core->GetGame()->Ticks;
|
||||
} else {
|
||||
time = GetTickCount();
|
||||
}
|
||||
|
||||
//it could be that we skip more than one frame in case of slow rendering
|
||||
//large, composite animations (dragons, multi-part area anims) require synchronisation
|
||||
if (( time - starttime ) >= ( unsigned long ) ( 1000 / fps )) {
|
||||
int inc = (time-starttime)*fps/1000;
|
||||
pos += inc;
|
||||
starttime += inc*1000/fps;
|
||||
}
|
||||
if (pos >= indicesCount ) {
|
||||
if (indicesCount) {
|
||||
if (Flags&A_ANI_PLAYONCE) {
|
||||
pos = indicesCount-1;
|
||||
endReached = true;
|
||||
} else {
|
||||
pos = pos%indicesCount;
|
||||
endReached = false; //looping, there is no end
|
||||
}
|
||||
} else {
|
||||
pos = 0;
|
||||
endReached = true;
|
||||
}
|
||||
starttime = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Sprite2D* Animation::GetSyncedNextFrame(Animation* master)
|
||||
{
|
||||
if (!Flags&A_ANI_ACTIVE) {
|
||||
print("Frame fetched while animation is inactive!\n");
|
||||
return NULL;
|
||||
}
|
||||
Sprite2D* ret;
|
||||
if (playReversed)
|
||||
ret = frames[indicesCount-pos-1];
|
||||
else
|
||||
ret = frames[pos];
|
||||
|
||||
starttime = master->starttime;
|
||||
pos = master->pos;
|
||||
endReached = master->endReached;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void Animation::release(void)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
/** Gets the i-th frame */
|
||||
Sprite2D* Animation::GetFrame(unsigned int i)
|
||||
{
|
||||
if (i >= indicesCount) {
|
||||
return NULL;
|
||||
}
|
||||
return frames[i];
|
||||
}
|
||||
|
||||
void Animation::MirrorAnimation()
|
||||
{
|
||||
Video *video = core->GetVideoDriver();
|
||||
|
||||
for (size_t i = 0; i < indicesCount; i++) {
|
||||
Sprite2D * tmp = frames[i];
|
||||
frames[i] = video->MirrorSpriteHorizontal( tmp, true );
|
||||
video->FreeSprite(tmp);
|
||||
}
|
||||
|
||||
// flip animArea horizontally as well
|
||||
animArea.x = -animArea.w - animArea.x;
|
||||
}
|
||||
|
||||
void Animation::MirrorAnimationVert()
|
||||
{
|
||||
Video *video = core->GetVideoDriver();
|
||||
|
||||
for (size_t i = 0; i < indicesCount; i++) {
|
||||
Sprite2D * tmp = frames[i];
|
||||
frames[i] = video->MirrorSpriteVertical( tmp, true );
|
||||
video->FreeSprite(tmp);
|
||||
}
|
||||
|
||||
// flip animArea vertically as well
|
||||
// animArea.y = -animArea.h - animArea.y;
|
||||
}
|
||||
|
||||
void Animation::AddAnimArea(Animation* slave)
|
||||
{
|
||||
int x = slave->animArea.x;
|
||||
int y = slave->animArea.y;
|
||||
int w = slave->animArea.w;
|
||||
int h = slave->animArea.h;
|
||||
if (x < animArea.x) {
|
||||
animArea.w += (animArea.x - x);
|
||||
animArea.x = x;
|
||||
}
|
||||
if (y < animArea.y) {
|
||||
animArea.h += (animArea.y - y);
|
||||
animArea.y = y;
|
||||
}
|
||||
if (x+w > animArea.x+animArea.w) {
|
||||
animArea.w = x+w-animArea.x;
|
||||
}
|
||||
if (y+h > animArea.y+animArea.h) {
|
||||
animArea.h = y+h-animArea.y;
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANIMATION_H
|
||||
#define ANIMATION_H
|
||||
|
||||
#include "RGBAColor.h"
|
||||
#include "exports.h"
|
||||
#include "globals.h"
|
||||
|
||||
#include "Region.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Sprite2D;
|
||||
|
||||
class GEM_EXPORT Animation {
|
||||
private:
|
||||
Sprite2D **frames;
|
||||
unsigned int indicesCount;
|
||||
unsigned long starttime;
|
||||
public:
|
||||
bool endReached;
|
||||
unsigned int pos;
|
||||
int x, y;
|
||||
unsigned char fps;
|
||||
bool playReversed;
|
||||
bool gameAnimation;
|
||||
Region animArea;
|
||||
ieDword Flags;
|
||||
Animation(int count);
|
||||
~Animation(void);
|
||||
void AddFrame(Sprite2D* frame, unsigned int index);
|
||||
Sprite2D* LastFrame(void);
|
||||
Sprite2D* NextFrame(void);
|
||||
Sprite2D* GetSyncedNextFrame(Animation* master);
|
||||
void release(void);
|
||||
/** Gets the i-th frame */
|
||||
Sprite2D* GetFrame(unsigned int i);
|
||||
/** Mirrors all the frames vertically */
|
||||
void MirrorAnimationVert();
|
||||
/** Mirrors all the frames horizontally */
|
||||
void MirrorAnimation();
|
||||
/** sets frame index */
|
||||
void SetPos(unsigned int index);
|
||||
/** Sets ScriptName for area animation */
|
||||
void SetScriptName(const char *name);
|
||||
/** returns the frame count */
|
||||
unsigned int GetFrameCount() const { return indicesCount; }
|
||||
/** returns the current frame's index */
|
||||
unsigned int GetCurrentFrame() const;
|
||||
/** add other animation's animarea to self */
|
||||
void AddAnimArea(Animation* slave);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,169 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "AnimationFactory.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "Interface.h"
|
||||
#include "Sprite2D.h"
|
||||
#include "Video.h"
|
||||
|
||||
AnimationFactory::AnimationFactory(const char* ResRef)
|
||||
: FactoryObject( ResRef, IE_BAM_CLASS_ID )
|
||||
{
|
||||
FLTable = NULL;
|
||||
FrameData = NULL;
|
||||
datarefcount = 0;
|
||||
}
|
||||
|
||||
AnimationFactory::~AnimationFactory(void)
|
||||
{
|
||||
for (unsigned int i = 0; i < frames.size(); i++) {
|
||||
core->GetVideoDriver()->FreeSprite( frames[i] );
|
||||
}
|
||||
if (FLTable)
|
||||
free( FLTable);
|
||||
|
||||
// FIXME: track down where sprites are being leaked
|
||||
if (datarefcount) {
|
||||
fprintf(stderr, "AnimationFactory %s has refcount %d\n", ResRef, datarefcount);
|
||||
//assert(datarefcount == 0);
|
||||
}
|
||||
if (FrameData)
|
||||
free( FrameData);
|
||||
}
|
||||
|
||||
void AnimationFactory::AddFrame(Sprite2D* frame)
|
||||
{
|
||||
frames.push_back( frame );
|
||||
}
|
||||
|
||||
void AnimationFactory::AddCycle(CycleEntry cycle)
|
||||
{
|
||||
cycles.push_back( cycle );
|
||||
}
|
||||
|
||||
void AnimationFactory::LoadFLT(unsigned short* buffer, int count)
|
||||
{
|
||||
if (FLTable) {
|
||||
free( FLTable );
|
||||
}
|
||||
//FLTable = new unsigned short[count];
|
||||
FLTable = (unsigned short *) malloc(count * sizeof( unsigned short ) );
|
||||
memcpy( FLTable, buffer, count * sizeof( unsigned short ) );
|
||||
}
|
||||
|
||||
void AnimationFactory::SetFrameData(unsigned char* FrameData)
|
||||
{
|
||||
this->FrameData = FrameData;
|
||||
}
|
||||
|
||||
|
||||
Animation* AnimationFactory::GetCycle(unsigned char cycle)
|
||||
{
|
||||
if (cycle >= cycles.size()) {
|
||||
return NULL;
|
||||
}
|
||||
int ff = cycles[cycle].FirstFrame;
|
||||
int lf = ff + cycles[cycle].FramesCount;
|
||||
Animation* anim = new Animation( cycles[cycle].FramesCount );
|
||||
int c = 0;
|
||||
for (int i = ff; i < lf; i++) {
|
||||
frames[FLTable[i]]->acquire();
|
||||
anim->AddFrame( frames[FLTable[i]], c++ );
|
||||
}
|
||||
return anim;
|
||||
}
|
||||
|
||||
/* returns the required frame of the named cycle, cycle defaults to 0 */
|
||||
Sprite2D* AnimationFactory::GetFrame(unsigned short index, unsigned char cycle) const
|
||||
{
|
||||
if (cycle >= cycles.size()) {
|
||||
return NULL;
|
||||
}
|
||||
int ff = cycles[cycle]. FirstFrame, fc = cycles[cycle].FramesCount;
|
||||
if(index >= fc) {
|
||||
return NULL;
|
||||
}
|
||||
Sprite2D* spr = frames[FLTable[ff+index]];
|
||||
spr->acquire();
|
||||
return spr;
|
||||
}
|
||||
|
||||
Sprite2D* AnimationFactory::GetFrameWithoutCycle(unsigned short index) const
|
||||
{
|
||||
if(index >= frames.size()) {
|
||||
return NULL;
|
||||
}
|
||||
Sprite2D* spr = frames[index];
|
||||
spr->acquire();
|
||||
return spr;
|
||||
}
|
||||
|
||||
Sprite2D* AnimationFactory::GetPaperdollImage(ieDword *Colors,
|
||||
Sprite2D *&Picture2, unsigned int type) const
|
||||
{
|
||||
if (frames.size()<2) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Video* video = core->GetVideoDriver();
|
||||
Picture2 = video->DuplicateSprite(frames[1]);
|
||||
if (!Picture2) {
|
||||
return NULL;
|
||||
}
|
||||
if (Colors) {
|
||||
Palette* palette = Picture2->GetPalette();
|
||||
palette->SetupPaperdollColours(Colors, type);
|
||||
Picture2->SetPalette(palette);
|
||||
palette->Release();
|
||||
}
|
||||
|
||||
Picture2->XPos = (short)frames[1]->XPos;
|
||||
Picture2->YPos = (short)frames[1]->YPos - 80;
|
||||
|
||||
|
||||
Sprite2D* spr = core->GetVideoDriver()->DuplicateSprite(frames[0]);
|
||||
if (Colors) {
|
||||
Palette* palette = spr->GetPalette();
|
||||
palette->SetupPaperdollColours(Colors, type);
|
||||
spr->SetPalette(palette);
|
||||
palette->Release();
|
||||
}
|
||||
|
||||
spr->XPos = (short)frames[0]->XPos;
|
||||
spr->YPos = (short)frames[0]->YPos;
|
||||
|
||||
//don't free pixels, createsprite stores it in spr
|
||||
|
||||
return spr;
|
||||
}
|
||||
|
||||
void AnimationFactory::IncDataRefCount()
|
||||
{
|
||||
++datarefcount;
|
||||
}
|
||||
|
||||
void AnimationFactory::DecDataRefCount()
|
||||
{
|
||||
assert(datarefcount > 0);
|
||||
--datarefcount;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANIMATIONFACTORY_H
|
||||
#define ANIMATIONFACTORY_H
|
||||
|
||||
#include "exports.h"
|
||||
#include "globals.h"
|
||||
|
||||
#include "Animation.h"
|
||||
#include "AnimStructures.h"
|
||||
#include "FactoryObject.h"
|
||||
|
||||
class GEM_EXPORT AnimationFactory : public FactoryObject {
|
||||
private:
|
||||
std::vector< Sprite2D*> frames;
|
||||
std::vector< CycleEntry> cycles;
|
||||
unsigned short* FLTable; // Frame Lookup Table
|
||||
unsigned char* FrameData;
|
||||
int datarefcount;
|
||||
public:
|
||||
AnimationFactory(const char* ResRef);
|
||||
~AnimationFactory(void);
|
||||
void AddFrame(Sprite2D* frame);
|
||||
void AddCycle(CycleEntry cycle);
|
||||
void LoadFLT(unsigned short* buffer, int count);
|
||||
void SetFrameData(unsigned char* FrameData);
|
||||
Animation* GetCycle(unsigned char cycle);
|
||||
/** No descriptions */
|
||||
Sprite2D* GetFrame(unsigned short index, unsigned char cycle=0) const;
|
||||
Sprite2D* GetFrameWithoutCycle(unsigned short index) const;
|
||||
size_t GetCycleCount() const { return cycles.size(); }
|
||||
size_t GetFrameCount() const { return frames.size(); }
|
||||
int GetCycleSize(int idx) const { return cycles[idx].FramesCount; }
|
||||
Sprite2D* GetPaperdollImage(ieDword *Colors, Sprite2D *&Picture2,
|
||||
unsigned int type) const;
|
||||
|
||||
void IncDataRefCount();
|
||||
void DecDataRefCount();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,29 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "AnimationMgr.h"
|
||||
|
||||
AnimationMgr::AnimationMgr(void)
|
||||
{
|
||||
}
|
||||
|
||||
AnimationMgr::~AnimationMgr(void)
|
||||
{
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANIMATIONMGR_H
|
||||
#define ANIMATIONMGR_H
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
#include "Animation.h"
|
||||
#include "AnimationFactory.h"
|
||||
#include "Plugin.h"
|
||||
|
||||
class Font;
|
||||
|
||||
class GEM_EXPORT AnimationMgr : public Plugin {
|
||||
public:
|
||||
AnimationMgr(void);
|
||||
virtual ~AnimationMgr(void);
|
||||
virtual bool Open(DataStream* stream) = 0;
|
||||
virtual int GetCycleSize(unsigned char Cycle) = 0;
|
||||
virtual AnimationFactory* GetAnimationFactory(const char* ResRef,
|
||||
unsigned char mode = IE_NORMAL) = 0;
|
||||
/** This function will load the Animation as a Font */
|
||||
virtual Font* GetFont() = 0;
|
||||
/** Debug Function: Returns the Global Animation Palette as a Sprite2D Object.
|
||||
If the Global Animation Palette is NULL, returns NULL. */
|
||||
virtual Sprite2D* GetPalette() = 0;
|
||||
virtual int GetCycleCount() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,29 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ArchiveImporter.h"
|
||||
|
||||
ArchiveImporter::ArchiveImporter(void)
|
||||
{
|
||||
}
|
||||
|
||||
ArchiveImporter::~ArchiveImporter(void)
|
||||
{
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ARCHIVEIMPORTER_H
|
||||
#define ARCHIVEIMPORTER_H
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
#include "Plugin.h"
|
||||
|
||||
class GEM_EXPORT ArchiveImporter : public Plugin {
|
||||
public:
|
||||
ArchiveImporter(void);
|
||||
virtual ~ArchiveImporter(void);
|
||||
virtual int CreateArchive(DataStream *stream) = 0;
|
||||
//decompressing a .sav file similar to CBF
|
||||
virtual int DecompressSaveGame(DataStream *compressed) = 0;
|
||||
virtual int AddToSaveGame(DataStream *str, DataStream *uncompressed) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,35 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003-2004 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Audio.h"
|
||||
|
||||
const TypeID Audio::ID = { "Audio" };
|
||||
|
||||
Audio::Audio(void)
|
||||
{
|
||||
}
|
||||
|
||||
Audio::~Audio(void)
|
||||
{
|
||||
}
|
||||
|
||||
SoundHandle::~SoundHandle()
|
||||
{
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003-2004 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_H_INCLUDED
|
||||
#define AUDIO_H_INCLUDED
|
||||
|
||||
#include "globals.h"
|
||||
#include "win32def.h"
|
||||
|
||||
#include "Plugin.h"
|
||||
#include "Holder.h"
|
||||
|
||||
#define GEM_SND_RELATIVE 1
|
||||
#define GEM_SND_LOOPING 2
|
||||
#define GEM_SND_SPEECH IE_STR_SPEECH // 4
|
||||
#define GEM_SND_VOL_MUSIC 1
|
||||
#define GEM_SND_VOL_AMBIENTS 2
|
||||
|
||||
class AmbientMgr;
|
||||
class SoundMgr;
|
||||
|
||||
class GEM_EXPORT SoundHandle : public Held<SoundHandle> {
|
||||
public:
|
||||
virtual bool Playing() = 0;
|
||||
virtual void SetPos(int XPos, int YPos) = 0;
|
||||
virtual void Stop() = 0;
|
||||
virtual void StopLooping() = 0;
|
||||
virtual ~SoundHandle();
|
||||
};
|
||||
|
||||
class GEM_EXPORT Audio : public Plugin {
|
||||
public:
|
||||
static const TypeID ID;
|
||||
public:
|
||||
Audio(void);
|
||||
virtual ~Audio();
|
||||
virtual bool Init(void) = 0;
|
||||
virtual Holder<SoundHandle> Play(const char* ResRef, int XPos, int YPos, unsigned int flags = 0, unsigned int *length = 0) = 0;
|
||||
virtual Holder<SoundHandle> Play(const char* ResRef, unsigned int *length = 0) { return Play(ResRef, 0, 0, GEM_SND_RELATIVE, length); }
|
||||
virtual bool IsSpeaking() = 0;
|
||||
virtual AmbientMgr* GetAmbientMgr() { return ambim; }
|
||||
virtual void UpdateVolume(unsigned int flags = GEM_SND_VOL_MUSIC | GEM_SND_VOL_AMBIENTS) = 0;
|
||||
virtual bool CanPlay() = 0;
|
||||
virtual void ResetMusics() = 0;
|
||||
virtual bool Play() = 0;
|
||||
virtual bool Stop() = 0;
|
||||
virtual bool Pause() = 0;
|
||||
virtual bool Resume() = 0;
|
||||
virtual int CreateStream(Holder<SoundMgr>) = 0;
|
||||
virtual void UpdateListenerPos(int XPos, int YPos ) = 0;
|
||||
virtual void GetListenerPos(int &XPos, int &YPos ) = 0;
|
||||
virtual bool ReleaseStream(int stream, bool HardStop=false ) = 0;
|
||||
virtual int SetupNewStream( ieWord x, ieWord y, ieWord z,
|
||||
ieWord gain, bool point, bool Ambient) = 0;
|
||||
virtual int QueueAmbient(int stream, const char* sound) = 0;
|
||||
virtual void SetAmbientStreamVolume(int stream, int volume) = 0;
|
||||
virtual void QueueBuffer(int stream, unsigned short bits,
|
||||
int channels, short* memory, int size, int samplerate) = 0;
|
||||
|
||||
protected:
|
||||
AmbientMgr* ambim;
|
||||
|
||||
};
|
||||
|
||||
#endif // AUDIO_H_INCLUDED
|
||||
@@ -1,29 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2007 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "Bitmap.h"
|
||||
|
||||
Bitmap::Bitmap(unsigned int w, unsigned int h)
|
||||
: height(h), width(w), data(new unsigned char[height*width])
|
||||
{
|
||||
}
|
||||
|
||||
Bitmap::~Bitmap()
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2007 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef BITMAP_H
|
||||
#define BITMAP_H
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
class GEM_EXPORT Bitmap {
|
||||
public:
|
||||
Bitmap(unsigned int height, unsigned int width);
|
||||
~Bitmap();
|
||||
unsigned char GetAt(unsigned int x, unsigned int y) const
|
||||
{
|
||||
if (x >= width || y >= height)
|
||||
return 0;
|
||||
return data[width*y+x];
|
||||
|
||||
}
|
||||
void SetAt(unsigned int x, unsigned int y, unsigned char idx)
|
||||
{
|
||||
if (x >= width || y >= height)
|
||||
return;
|
||||
data[width*y+x] = idx;
|
||||
|
||||
}
|
||||
unsigned int GetHeight() const
|
||||
{
|
||||
return height;
|
||||
}
|
||||
unsigned int GetWidth() const
|
||||
{
|
||||
return width;
|
||||
}
|
||||
private:
|
||||
unsigned int height, width;
|
||||
unsigned char *data;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,139 +0,0 @@
|
||||
ADD_DEFINITIONS(-DGEM_BUILD_DLL)
|
||||
|
||||
FILE(GLOB gemrb_core_LIB_SRCS
|
||||
ActorMgr.cpp
|
||||
Ambient.cpp
|
||||
AmbientMgr.cpp
|
||||
Animation.cpp
|
||||
AnimationFactory.cpp
|
||||
AnimationMgr.cpp
|
||||
ArchiveImporter.cpp
|
||||
Audio.cpp
|
||||
Bitmap.cpp
|
||||
Cache.cpp
|
||||
Calendar.cpp
|
||||
Callback.cpp
|
||||
CharAnimations.cpp
|
||||
Compressor.cpp
|
||||
ControlAnimation.cpp
|
||||
Core.cpp
|
||||
DataFileMgr.cpp
|
||||
Dialog.cpp
|
||||
DialogHandler.cpp
|
||||
DialogMgr.cpp
|
||||
DisplayMessage.cpp
|
||||
EffectMgr.cpp
|
||||
EffectQueue.cpp
|
||||
Factory.cpp
|
||||
FactoryObject.cpp
|
||||
FileCache.cpp
|
||||
Font.cpp
|
||||
Game.cpp
|
||||
GameData.cpp
|
||||
GlobalTimer.cpp
|
||||
Image.cpp
|
||||
ImageFactory.cpp
|
||||
ImageMgr.cpp
|
||||
ImageWriter.cpp
|
||||
IndexedArchive.cpp
|
||||
IniSpawn.cpp
|
||||
Interface.cpp
|
||||
Inventory.cpp
|
||||
Item.cpp
|
||||
ItemMgr.cpp
|
||||
KeyMap.cpp
|
||||
LRUCache.cpp
|
||||
Map.cpp
|
||||
MapMgr.cpp
|
||||
MoviePlayer.cpp
|
||||
MusicMgr.cpp
|
||||
Palette.cpp
|
||||
PalettedImageMgr.cpp
|
||||
Particles.cpp
|
||||
Plugin.cpp
|
||||
PluginLoader.cpp
|
||||
PluginMgr.cpp
|
||||
Polygon.cpp
|
||||
Projectile.cpp
|
||||
ProjectileMgr.cpp
|
||||
ProjectileServer.cpp
|
||||
Region.cpp
|
||||
Resource.cpp
|
||||
ResourceDesc.cpp
|
||||
ResourceManager.cpp
|
||||
ResourceSource.cpp
|
||||
SaveGameIterator.cpp
|
||||
SaveGameMgr.cpp
|
||||
ScriptEngine.cpp
|
||||
ScriptedAnimation.cpp
|
||||
SoundMgr.cpp
|
||||
Spell.cpp
|
||||
SpellMgr.cpp
|
||||
Spellbook.cpp
|
||||
Sprite2D.cpp
|
||||
SpriteCover.cpp
|
||||
Store.cpp
|
||||
StoreMgr.cpp
|
||||
StringMgr.cpp
|
||||
SymbolMgr.cpp
|
||||
TableMgr.cpp
|
||||
Tile.cpp
|
||||
TileMap.cpp
|
||||
TileMapMgr.cpp
|
||||
TileOverlay.cpp
|
||||
TileSetMgr.cpp
|
||||
Variables.cpp
|
||||
Video.cpp
|
||||
WindowMgr.cpp
|
||||
WorldMap.cpp
|
||||
WorldMapMgr.cpp
|
||||
GameScript/Actions.cpp
|
||||
GameScript/GSUtils.cpp
|
||||
GameScript/GameScript.cpp
|
||||
GameScript/Matching.cpp
|
||||
GameScript/Objects.cpp
|
||||
GameScript/Triggers.cpp
|
||||
GUI/Button.cpp
|
||||
GUI/Console.cpp
|
||||
GUI/Control.cpp
|
||||
GUI/EventMgr.cpp
|
||||
GUI/GameControl.cpp
|
||||
GUI/Label.cpp
|
||||
GUI/MapControl.cpp
|
||||
GUI/Progressbar.cpp
|
||||
GUI/ScrollBar.cpp
|
||||
GUI/Slider.cpp
|
||||
GUI/TextArea.cpp
|
||||
GUI/TextEdit.cpp
|
||||
GUI/Window.cpp
|
||||
GUI/WorldMapControl.cpp
|
||||
Scriptable/Actor.cpp
|
||||
Scriptable/Container.cpp
|
||||
Scriptable/Door.cpp
|
||||
Scriptable/InfoPoint.cpp
|
||||
Scriptable/Scriptable.cpp
|
||||
Scriptable/PCStatStruct.cpp
|
||||
System/DataStream.cpp
|
||||
System/FileStream.cpp
|
||||
System/MemoryStream.cpp
|
||||
System/Logging.cpp
|
||||
System/SlicedStream.cpp
|
||||
System/String.cpp
|
||||
System/VFS.cpp
|
||||
)
|
||||
|
||||
if (STATIC_LINK)
|
||||
ADD_LIBRARY(gemrb_core STATIC ${gemrb_core_LIB_SRCS})
|
||||
else (STATIC_LINK)
|
||||
ADD_LIBRARY(gemrb_core SHARED ${gemrb_core_LIB_SRCS})
|
||||
IF(WIN32)
|
||||
INSTALL(TARGETS gemrb_core RUNTIME DESTINATION ${LIB_DIR})
|
||||
ELSE(WIN32)
|
||||
INSTALL(TARGETS gemrb_core LIBRARY DESTINATION ${LIB_DIR})
|
||||
ENDIF(WIN32)
|
||||
endif (STATIC_LINK)
|
||||
|
||||
SET_TARGET_PROPERTIES(gemrb_core PROPERTIES
|
||||
COMPILE_DEFINITIONS
|
||||
"PLUGINDIR=\"${PLUGIN_DIR}\";DATADIR=\"${DATA_DIR}\";SYSCONFDIR=\"${SYSCONF_DIR}\""
|
||||
)
|
||||
@@ -1,312 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Cache.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <ctype.h>
|
||||
|
||||
// private inlines
|
||||
inline unsigned int Cache::MyHashKey(const char* key) const
|
||||
{
|
||||
int nHash = tolower(key[0]);
|
||||
for (int i=1;(i<KEYSIZE) && key[i];i++) {
|
||||
nHash = (nHash << 5) ^ tolower(key[i]);
|
||||
}
|
||||
return nHash % m_nHashTableSize;
|
||||
}
|
||||
|
||||
Cache::Cache(int nBlockSize, int nHashTableSize)
|
||||
{
|
||||
assert( nBlockSize > 0 );
|
||||
assert( nHashTableSize > 16 );
|
||||
|
||||
m_pHashTable = NULL;
|
||||
m_nHashTableSize = nHashTableSize; // default size
|
||||
m_nCount = 0;
|
||||
m_pFreeList = NULL;
|
||||
m_pBlocks = NULL;
|
||||
m_nBlockSize = nBlockSize;
|
||||
}
|
||||
|
||||
void Cache::InitHashTable(unsigned int nHashSize, bool bAllocNow)
|
||||
//Used to force allocation of a hash table or to override the default
|
||||
//hash table size of (which is fairly small)
|
||||
{
|
||||
assert( m_nCount == 0 );
|
||||
assert( nHashSize > 16 );
|
||||
|
||||
if (m_pHashTable != NULL) {
|
||||
// free hash table
|
||||
free( m_pHashTable);
|
||||
m_pHashTable = NULL;
|
||||
}
|
||||
|
||||
if (bAllocNow) {
|
||||
m_pHashTable = (Cache::MyAssoc **) malloc( sizeof( Cache::MyAssoc * ) * nHashSize );
|
||||
memset( m_pHashTable, 0, sizeof( Cache::MyAssoc * ) * nHashSize );
|
||||
}
|
||||
m_nHashTableSize = nHashSize;
|
||||
}
|
||||
|
||||
void Cache::RemoveAll(ReleaseFun fun)
|
||||
{
|
||||
if (m_pHashTable) {
|
||||
for (unsigned int nHash = 0; nHash < m_nHashTableSize; nHash++)
|
||||
{
|
||||
MyAssoc* pAssoc;
|
||||
for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL;
|
||||
pAssoc = pAssoc->pNext)
|
||||
{
|
||||
if (fun)
|
||||
fun(pAssoc->data);
|
||||
pAssoc->MyAssoc::~MyAssoc();
|
||||
}
|
||||
}
|
||||
// free hash table
|
||||
free( m_pHashTable );
|
||||
m_pHashTable = NULL;
|
||||
}
|
||||
|
||||
m_nCount = 0;
|
||||
m_pFreeList = NULL;
|
||||
|
||||
// free memory blocks
|
||||
MemBlock* p = m_pBlocks;
|
||||
while (p != NULL) {
|
||||
MemBlock* pNext = p->pNext;
|
||||
free( p );
|
||||
p = pNext;
|
||||
}
|
||||
|
||||
m_pBlocks = NULL;
|
||||
}
|
||||
|
||||
Cache::~Cache()
|
||||
{
|
||||
RemoveAll(NULL);
|
||||
}
|
||||
|
||||
Cache::MyAssoc* Cache::NewAssoc()
|
||||
{
|
||||
if (m_pFreeList == NULL) {
|
||||
// add another block
|
||||
Cache::MemBlock* newBlock = ( Cache::MemBlock* ) malloc(m_nBlockSize * sizeof( Cache::MyAssoc ) + sizeof( Cache::MemBlock ));
|
||||
assert( newBlock != NULL ); // we must have something
|
||||
|
||||
newBlock->pNext = m_pBlocks;
|
||||
m_pBlocks = newBlock;
|
||||
|
||||
// chain them into free list
|
||||
Cache::MyAssoc* pAssoc = ( Cache::MyAssoc* )
|
||||
( newBlock + 1 );
|
||||
for (int i = 0; i < m_nBlockSize; i++) {
|
||||
pAssoc->pNext = m_pFreeList;
|
||||
m_pFreeList = pAssoc++;
|
||||
}
|
||||
}
|
||||
|
||||
Cache::MyAssoc* pAssoc = m_pFreeList;
|
||||
m_pFreeList = m_pFreeList->pNext;
|
||||
m_nCount++;
|
||||
assert( m_nCount > 0 ); // make sure we don't overflow
|
||||
#ifdef _DEBUG
|
||||
pAssoc->key[0] = 0;
|
||||
pAssoc->data = 0;
|
||||
#endif
|
||||
pAssoc->nRefCount=1;
|
||||
return pAssoc;
|
||||
}
|
||||
|
||||
void Cache::FreeAssoc(Cache::MyAssoc* pAssoc)
|
||||
{
|
||||
if(pAssoc->pNext) {
|
||||
pAssoc->pNext->pPrev=pAssoc->pPrev;
|
||||
}
|
||||
*pAssoc->pPrev = pAssoc->pNext;
|
||||
pAssoc->pNext = m_pFreeList;
|
||||
m_pFreeList = pAssoc;
|
||||
m_nCount--;
|
||||
assert( m_nCount >= 0 ); // make sure we don't underflow
|
||||
|
||||
// if no more elements, cleanup completely
|
||||
if (m_nCount == 0) {
|
||||
RemoveAll(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
Cache::MyAssoc *Cache::GetNextAssoc(Cache::MyAssoc *Position) const
|
||||
{
|
||||
if (m_pHashTable == NULL || m_nCount==0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Cache::MyAssoc* pAssocRet = (Cache::MyAssoc*)Position;
|
||||
|
||||
if (pAssocRet == NULL)
|
||||
{
|
||||
// find the first association
|
||||
for (unsigned int nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
|
||||
if ((pAssocRet = m_pHashTable[nBucket]) != NULL)
|
||||
break;
|
||||
return pAssocRet;
|
||||
}
|
||||
Cache::MyAssoc* pAssocNext = pAssocRet->pNext;
|
||||
if (pAssocNext == NULL)
|
||||
{
|
||||
// go to next bucket
|
||||
for (unsigned int nBucket = MyHashKey(pAssocRet->key) + 1;
|
||||
nBucket < m_nHashTableSize; nBucket++)
|
||||
if ((pAssocNext = m_pHashTable[nBucket]) != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
return pAssocNext;
|
||||
}
|
||||
|
||||
Cache::MyAssoc* Cache::GetAssocAt(const ieResRef key) const
|
||||
// find association (or return NULL)
|
||||
{
|
||||
if (m_pHashTable == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int nHash = MyHashKey( key );
|
||||
|
||||
// see if it exists
|
||||
Cache::MyAssoc* pAssoc;
|
||||
for (pAssoc = m_pHashTable[nHash];
|
||||
pAssoc != NULL;
|
||||
pAssoc = pAssoc->pNext) {
|
||||
if (!strnicmp( pAssoc->key, key, KEYSIZE )) {
|
||||
return pAssoc;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *Cache::GetResource(const ieResRef key) const
|
||||
{
|
||||
Cache::MyAssoc* pAssoc = GetAssocAt( key );
|
||||
if (pAssoc == NULL) {
|
||||
return NULL;
|
||||
} // not in map
|
||||
|
||||
pAssoc->nRefCount++;
|
||||
return pAssoc->data;
|
||||
}
|
||||
|
||||
//returns true if it was successful
|
||||
bool Cache::SetAt(const ieResRef key, void *rValue)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (m_pHashTable == NULL) {
|
||||
InitHashTable( m_nHashTableSize );
|
||||
}
|
||||
|
||||
Cache::MyAssoc* pAssoc=GetAssocAt( key );
|
||||
|
||||
if (pAssoc) {
|
||||
//already exists, but we return true if it is the same
|
||||
return (pAssoc->data==rValue);
|
||||
}
|
||||
|
||||
// it doesn't exist, add a new Association
|
||||
pAssoc = NewAssoc();
|
||||
for (i=0;i<KEYSIZE && key[i];i++) {
|
||||
pAssoc->key[i]=tolower(key[i]);
|
||||
}
|
||||
for (;i<KEYSIZE;i++) {
|
||||
pAssoc->key[i]=0;
|
||||
}
|
||||
pAssoc->data=rValue;
|
||||
// put into hash table
|
||||
unsigned int nHash = MyHashKey(pAssoc->key);
|
||||
pAssoc->pNext = m_pHashTable[nHash];
|
||||
pAssoc->pPrev = &m_pHashTable[nHash];
|
||||
if (pAssoc->pNext) {
|
||||
pAssoc->pNext->pPrev = &pAssoc->pNext;
|
||||
}
|
||||
m_pHashTable[nHash] = pAssoc;
|
||||
return true;
|
||||
}
|
||||
|
||||
int Cache::RefCount(const ieResRef key) const
|
||||
{
|
||||
Cache::MyAssoc* pAssoc=GetAssocAt( key );
|
||||
if (pAssoc) {
|
||||
return pAssoc->nRefCount;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Cache::DecRef(void *data, const ieResRef key, bool remove)
|
||||
{
|
||||
Cache::MyAssoc* pAssoc;
|
||||
|
||||
if (key) {
|
||||
pAssoc=GetAssocAt( key );
|
||||
if (pAssoc && (pAssoc->data==data) ) {
|
||||
if (!pAssoc->nRefCount) {
|
||||
return -1;
|
||||
}
|
||||
--pAssoc->nRefCount;
|
||||
if (remove && !pAssoc->nRefCount) {
|
||||
FreeAssoc(pAssoc);
|
||||
return 0;
|
||||
}
|
||||
return pAssoc->nRefCount;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
pAssoc=(Cache::MyAssoc *) GetNextAssoc(NULL);
|
||||
|
||||
while (pAssoc) {
|
||||
if (pAssoc->data == data) {
|
||||
if (!pAssoc->nRefCount) {
|
||||
return -1;
|
||||
}
|
||||
--pAssoc->nRefCount;
|
||||
if (remove && !pAssoc->nRefCount) {
|
||||
FreeAssoc(pAssoc);
|
||||
return 0;
|
||||
}
|
||||
return pAssoc->nRefCount;
|
||||
}
|
||||
pAssoc=GetNextAssoc(pAssoc);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Cache::Cleanup()
|
||||
{
|
||||
Cache::MyAssoc* pAssoc=(Cache::MyAssoc *) GetNextAssoc(NULL);
|
||||
|
||||
while (pAssoc)
|
||||
{
|
||||
Cache::MyAssoc* nextAssoc = GetNextAssoc(pAssoc);
|
||||
if (pAssoc->nRefCount == 0) {
|
||||
FreeAssoc(pAssoc);
|
||||
}
|
||||
pAssoc=nextAssoc;
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 |Avenger|
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CACHE_H
|
||||
#define CACHE_H
|
||||
|
||||
#include "globals.h"
|
||||
#include "win32def.h"
|
||||
|
||||
#define KEYSIZE 8
|
||||
|
||||
#ifndef ReleaseFun
|
||||
typedef void (*ReleaseFun)(void *);
|
||||
#endif
|
||||
|
||||
class Cache
|
||||
{
|
||||
protected:
|
||||
// Association
|
||||
struct MyAssoc {
|
||||
MyAssoc* pNext;
|
||||
MyAssoc** pPrev;
|
||||
char key[KEYSIZE]; //not ieResRef!
|
||||
ieDword nRefCount;
|
||||
void* data;
|
||||
};
|
||||
struct MemBlock {
|
||||
MemBlock* pNext;
|
||||
};
|
||||
|
||||
public:
|
||||
// Construction
|
||||
Cache(int nBlockSize = 10, int nHashTableSize = 129);
|
||||
|
||||
// Attributes
|
||||
// number of elements
|
||||
inline int GetCount() const
|
||||
{
|
||||
return m_nCount;
|
||||
}
|
||||
inline bool IsEmpty() const
|
||||
{
|
||||
return m_nCount==0;
|
||||
}
|
||||
// Lookup
|
||||
void *GetResource(const ieResRef key) const;
|
||||
// Operations
|
||||
bool SetAt(const ieResRef key, void *rValue);
|
||||
// decreases refcount or drops data
|
||||
//if name is supplied it is faster, it will use rValue to validate the request
|
||||
int DecRef(void *rValue, const ieResRef name, bool free);
|
||||
int RefCount(const ieResRef key) const;
|
||||
void RemoveAll(ReleaseFun fun);//removes all refcounts
|
||||
void Cleanup(); //removes only zero refcounts
|
||||
void InitHashTable(unsigned int hashSize, bool bAllocNow = true);
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
MyAssoc** m_pHashTable;
|
||||
unsigned int m_nHashTableSize;
|
||||
int m_nCount;
|
||||
MyAssoc* m_pFreeList;
|
||||
MemBlock* m_pBlocks;
|
||||
int m_nBlockSize;
|
||||
|
||||
Cache::MyAssoc* NewAssoc();
|
||||
void FreeAssoc(Cache::MyAssoc*);
|
||||
Cache::MyAssoc* GetAssocAt(const ieResRef) const;
|
||||
Cache::MyAssoc *GetNextAssoc(Cache::MyAssoc * rNextPosition) const;
|
||||
unsigned int MyHashKey(const ieResRef) const;
|
||||
|
||||
public:
|
||||
~Cache();
|
||||
};
|
||||
|
||||
#endif //CACHE_H
|
||||
@@ -1,96 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2009 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Calendar.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "Interface.h"
|
||||
#include "TableMgr.h"
|
||||
#include "Variables.h"
|
||||
|
||||
Calendar::Calendar(void)
|
||||
{
|
||||
int i;
|
||||
AutoTable tab("months");
|
||||
if (!tab) {
|
||||
monthnamecount=-1;
|
||||
monthnames = NULL;
|
||||
days = NULL;
|
||||
return;
|
||||
}
|
||||
monthnamecount = tab->GetRowCount();
|
||||
monthnames = (int *) malloc(sizeof(int) * monthnamecount);
|
||||
days = (int *) malloc(sizeof(int) * monthnamecount);
|
||||
daysinyear=0;
|
||||
for(i=0;i<monthnamecount;i++) {
|
||||
days[i]=atoi(tab->QueryField(i,0));
|
||||
daysinyear+=days[i];
|
||||
monthnames[i]=atoi(tab->QueryField(i,1));
|
||||
}
|
||||
}
|
||||
|
||||
Calendar::~Calendar(void)
|
||||
{
|
||||
if (monthnames) free(monthnames);
|
||||
if (days) free(days);
|
||||
}
|
||||
|
||||
void Calendar::GetMonthName(int dayandmonth) const
|
||||
{
|
||||
int month=1;
|
||||
|
||||
for(int i=0;i<monthnamecount;i++) {
|
||||
if (dayandmonth<days[i]) {
|
||||
char *tmp;
|
||||
|
||||
core->GetTokenDictionary()->SetAtCopy("DAY", dayandmonth+1);
|
||||
|
||||
tmp = core->GetString( monthnames[i] );
|
||||
core->GetTokenDictionary()->SetAt("MONTHNAME",tmp);
|
||||
//must not free tmp, SetAt doesn't copy the pointer!
|
||||
|
||||
core->GetTokenDictionary()->SetAtCopy("MONTH", month);
|
||||
return;
|
||||
}
|
||||
dayandmonth-=days[i];
|
||||
//ignoring single days (they are not months)
|
||||
if (days[i]!=1) month++;
|
||||
}
|
||||
}
|
||||
|
||||
int Calendar::GetCalendarDay(int date) const
|
||||
{
|
||||
int dayandmonth;
|
||||
int month=1;
|
||||
|
||||
if (!daysinyear) return 0;
|
||||
dayandmonth = date%daysinyear;
|
||||
for(int i=0;i<monthnamecount;i++) {
|
||||
if (dayandmonth<days[i]) {
|
||||
break;
|
||||
}
|
||||
dayandmonth-=days[i];
|
||||
//ignoring single days (they are not months)
|
||||
if (days[i]!=1) month++;
|
||||
}
|
||||
return dayandmonth+1;
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2009 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CALENDAR_H
|
||||
#define CALENDAR_H
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
class GEM_EXPORT Calendar {
|
||||
private:
|
||||
int daysinyear;
|
||||
int monthnamecount;
|
||||
int *days;
|
||||
int *monthnames;
|
||||
|
||||
public:
|
||||
Calendar(void);
|
||||
~Calendar(void);
|
||||
void GetMonthName(int dayandmonth) const;
|
||||
int GetCalendarDay(int date) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,33 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "Callback.h"
|
||||
|
||||
Callback::~Callback()
|
||||
{
|
||||
}
|
||||
|
||||
bool Callback::call()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Callback::call(int)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef CALLBACK_H
|
||||
#define CALLBACK_H
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
#include "Holder.h"
|
||||
|
||||
class GEM_EXPORT Callback : public Held<Callback> {
|
||||
public:
|
||||
virtual ~Callback();
|
||||
virtual bool call ();
|
||||
virtual bool call (int);
|
||||
};
|
||||
|
||||
typedef Holder<Callback> EventHandler;
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,233 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CHARANIMATIONS_H
|
||||
#define CHARANIMATIONS_H
|
||||
|
||||
#include "RGBAColor.h"
|
||||
#include "exports.h"
|
||||
|
||||
#include "Animation.h"
|
||||
#include "Palette.h"
|
||||
#include "TableMgr.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define AV_PREFIX1 0
|
||||
#define AV_PREFIX2 1
|
||||
#define AV_PREFIX3 2
|
||||
#define AV_PREFIX4 3
|
||||
#define AV_ANIMTYPE 4
|
||||
#define AV_CIRCLESIZE 5
|
||||
#define AV_USE_PALETTE 6
|
||||
#define AV_SIZE 7
|
||||
|
||||
#define MAX_ANIMS 19
|
||||
|
||||
#define IE_ANI_ATTACK 0
|
||||
#define IE_ANI_AWAKE 1
|
||||
#define IE_ANI_CAST 2
|
||||
#define IE_ANI_CONJURE 3
|
||||
#define IE_ANI_DAMAGE 4
|
||||
#define IE_ANI_DIE 5
|
||||
#define IE_ANI_HEAD_TURN 6
|
||||
#define IE_ANI_READY 7
|
||||
#define IE_ANI_SHOOT 8
|
||||
#define IE_ANI_TWITCH 9
|
||||
#define IE_ANI_WALK 10
|
||||
#define IE_ANI_ATTACK_SLASH 11
|
||||
#define IE_ANI_ATTACK_BACKSLASH 12
|
||||
#define IE_ANI_ATTACK_JAB 13
|
||||
#define IE_ANI_EMERGE 14
|
||||
#define IE_ANI_HIDE 15
|
||||
#define IE_ANI_RUN 15 //pst has no hide, i hope
|
||||
#define IE_ANI_SLEEP 16
|
||||
#define IE_ANI_GET_UP 17
|
||||
#define IE_ANI_PST_START 18
|
||||
|
||||
//BG2, IWD animation types
|
||||
#define IE_ANI_CODE_MIRROR 0
|
||||
#define IE_ANI_ONE_FILE 1
|
||||
#define IE_ANI_FOUR_FILES 2
|
||||
#define IE_ANI_TWO_FILES 3
|
||||
#define IE_ANI_CODE_MIRROR_2 4
|
||||
#define IE_ANI_SIX_FILES_2 5 //MOGR
|
||||
#define IE_ANI_TWENTYTWO 6
|
||||
#define IE_ANI_BIRD 7
|
||||
#define IE_ANI_SIX_FILES 8 //MCAR/MWYV
|
||||
#define IE_ANI_TWO_FILES_3 9 //iwd animations
|
||||
#define IE_ANI_TWO_FILES_2 10 //low res bg1 anim
|
||||
#define IE_ANI_FOUR_FRAMES 11 //wyvern anims
|
||||
#define IE_ANI_NINE_FRAMES 12 //dragon anims
|
||||
#define IE_ANI_FRAGMENT 13 //fragment animation
|
||||
#define IE_ANI_FOUR_FILES_2 14 //METT
|
||||
#define IE_ANI_CODE_MIRROR_3 15 //MSPS
|
||||
#define IE_ANI_TWO_FILES_3B 16 //iwd animations (eg. MBBM)
|
||||
|
||||
//PST animation types
|
||||
#define IE_ANI_PST_ANIMATION_1 56 //full animation
|
||||
#define IE_ANI_PST_GHOST 57 //no orientations
|
||||
#define IE_ANI_PST_STAND 58 //has orientations
|
||||
#define IE_ANI_PST_ANIMATION_2 59 //full animation std-->stc
|
||||
#define IE_ANI_PST_ANIMATION_3 60 //full animation stc-->std
|
||||
|
||||
//armour levels
|
||||
#define IE_ANI_NO_ARMOR 0
|
||||
#define IE_ANI_LIGHT_ARMOR 1
|
||||
#define IE_ANI_MEDIUM_ARMOR 2
|
||||
#define IE_ANI_HEAVY_ARMOR 3
|
||||
|
||||
#define IE_ANI_WEAPON_1H 0
|
||||
#define IE_ANI_WEAPON_2H 1
|
||||
#define IE_ANI_WEAPON_2W 2
|
||||
|
||||
#define IE_ANI_RANGED_BOW 0
|
||||
#define IE_ANI_RANGED_XBOW 1
|
||||
#define IE_ANI_RANGED_THROW 2
|
||||
|
||||
struct AvatarStruct {
|
||||
/* entries from avatars.2da */
|
||||
unsigned int AnimID;
|
||||
unsigned int PaletteType;
|
||||
ieResRef Prefixes[4];
|
||||
unsigned char AnimationType;
|
||||
unsigned char CircleSize;
|
||||
char Size;
|
||||
|
||||
/* comes from bloodclr.2da */
|
||||
char BloodColor;
|
||||
|
||||
/* resdata.ini entries */
|
||||
unsigned int WalkScale; /* 1000 / walkscale */
|
||||
unsigned int RunScale; /* 1000 / runscale */
|
||||
int Bestiary;
|
||||
|
||||
/* comes from walksnd.2da */
|
||||
ieResRef WalkSound;
|
||||
ieByte WalkSoundCount;
|
||||
};
|
||||
|
||||
struct EquipResRefData;
|
||||
|
||||
class GEM_EXPORT CharAnimations {
|
||||
private:
|
||||
Animation** Anims[MAX_ANIMS][MAX_ORIENT];
|
||||
char HelmetRef[2];
|
||||
char WeaponRef[2];
|
||||
char OffhandRef[2];
|
||||
public:
|
||||
const ieDword *Colors; //these are the custom color indices
|
||||
RGBModifier ColorMods[32]; // color modification effects
|
||||
unsigned long lastModUpdate;
|
||||
RGBModifier GlobalColorMod; // global color modification effect
|
||||
|
||||
bool change[4];
|
||||
Palette* palette[4];
|
||||
Palette* modifiedPalette[4];
|
||||
unsigned int AvatarsRowNum;
|
||||
unsigned char ArmorType, WeaponType, RangedType;
|
||||
ieResRef ResRef;
|
||||
ieResRef PaletteResRef;
|
||||
unsigned char nextStanceID, StanceID;
|
||||
bool autoSwitchOnEnd;
|
||||
bool lockPalette;
|
||||
public:
|
||||
CharAnimations(unsigned int AnimID, ieDword ArmourLevel);
|
||||
~CharAnimations(void);
|
||||
static void ReleaseMemory();
|
||||
void SetArmourLevel(int ArmourLevel);
|
||||
void SetRangedType(int Ranged);
|
||||
void SetWeaponType(int WeaponType);
|
||||
void SetHelmetRef(const char* ref);
|
||||
void SetWeaponRef(const char* ref);
|
||||
void SetOffhandRef(const char* ref);
|
||||
void SetColors(const ieDword *Colors);
|
||||
void CheckColorMod();
|
||||
void SetupColors(PaletteType type);
|
||||
void LockPalette(const ieDword *Colors);
|
||||
|
||||
// returns an array of animations of size GetTotalPartCount()
|
||||
Animation** GetAnimation(unsigned char Stance, unsigned char Orient);
|
||||
int GetTotalPartCount() const;
|
||||
const int* GetZOrder(unsigned char Orient);
|
||||
|
||||
// returns Palette for a given part (unlocked)
|
||||
Palette* GetPartPalette(int part); // TODO: clean this up
|
||||
|
||||
public: //attribute functions
|
||||
static int GetAvatarsCount();
|
||||
static AvatarStruct *GetAvatarStruct(int RowNum);
|
||||
unsigned int GetAnimationID() const;
|
||||
int GetCircleSize() const;
|
||||
int NoPalette() const;
|
||||
int GetAnimType() const;
|
||||
int GetSize() const;
|
||||
int GetBloodColor() const;
|
||||
const ieResRef &GetWalkSound() const;
|
||||
int GetWalkSoundCount() const;
|
||||
void PulseRGBModifiers();
|
||||
|
||||
private:
|
||||
void DropAnims();
|
||||
void InitAvatarsTable();
|
||||
int GetActorPartCount() const;
|
||||
void AddPSTSuffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient);
|
||||
void AddFFSuffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient, int Part);
|
||||
void AddNFSuffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient, int Part);
|
||||
void AddVHR2Suffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient);
|
||||
void AddVHRSuffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient, EquipResRefData*& equip);
|
||||
void AddVHR3Suffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient);
|
||||
void GetVHREquipmentRef(char* ResRef, unsigned char& Cycle,
|
||||
const char* equipRef, bool offhand, EquipResRefData* equip);
|
||||
void AddSixSuffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient);
|
||||
void AddMHRSuffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient, EquipResRefData*& equip);
|
||||
void GetMHREquipmentRef(char* ResRef, unsigned char& Cycle,
|
||||
const char* equipRef, bool offhand, EquipResRefData* equip);
|
||||
void AddMMRSuffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient);
|
||||
void AddMMR2Suffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient);
|
||||
void AddTwoFileSuffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient);
|
||||
void AddLRSuffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient, EquipResRefData*& equip);
|
||||
void AddLRSuffix2( char* ResRef, unsigned char StanceID,
|
||||
unsigned char& Cycle, unsigned char Orient, EquipResRefData *&EquipData);
|
||||
void GetLREquipmentRef(char* ResRef, unsigned char& Cycle,
|
||||
const char* equipRef, bool offhand, EquipResRefData* equip);
|
||||
void AddLR2Suffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient);
|
||||
void AddLR3Suffix(char* ResRef, unsigned char AnimID,
|
||||
unsigned char& Cycle, unsigned char Orient);
|
||||
void GetAnimResRef(unsigned char AnimID, unsigned char Orient,
|
||||
char* ResRef, unsigned char& Cycle, int Part, EquipResRefData*& equip);
|
||||
void GetEquipmentResRef(const char* equipRef, bool offhand,
|
||||
char* ResRef, unsigned char& Cycle, EquipResRefData* equip);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,31 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Compressor.h"
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
Compressor::Compressor(void)
|
||||
{
|
||||
}
|
||||
|
||||
Compressor::~Compressor(void)
|
||||
{
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMPRESSOR_H
|
||||
#define COMPRESSOR_H
|
||||
|
||||
#include "Plugin.h"
|
||||
#include "System/DataStream.h"
|
||||
|
||||
class GEM_EXPORT Compressor : public Plugin {
|
||||
public:
|
||||
Compressor(void);
|
||||
virtual ~Compressor(void);
|
||||
/** decompresses a datastream (memory or file) to a FILE * stream */
|
||||
virtual int Decompress(DataStream* dest, DataStream* source, unsigned int size_guess = 0) const = 0;
|
||||
/** compresses a datastream (memory or file) to another DataStream */
|
||||
virtual int Compress(DataStream *dest, DataStream* source) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,156 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ControlAnimation.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "AnimationFactory.h"
|
||||
#include "GameData.h"
|
||||
#include "GlobalTimer.h"
|
||||
#include "Interface.h"
|
||||
#include "Palette.h" /* needed only for paperdoll palettes */
|
||||
#include "Video.h" /* needed only for paperdoll palettes */
|
||||
#include "GUI/Button.h"
|
||||
|
||||
ControlAnimation::ControlAnimation(Control* ctl, const ieResRef ResRef, int Cycle)
|
||||
{
|
||||
control = NULL;
|
||||
bam = NULL;
|
||||
cycle = Cycle;
|
||||
frame = 0;
|
||||
anim_phase = 0;
|
||||
|
||||
bam = ( AnimationFactory* ) gamedata->GetFactoryResource( ResRef,
|
||||
IE_BAM_CLASS_ID, IE_NORMAL );
|
||||
|
||||
if (! bam)
|
||||
return;
|
||||
|
||||
control = ctl;
|
||||
control->animation = this;
|
||||
has_palette = false;
|
||||
is_blended = false;
|
||||
}
|
||||
|
||||
//freeing the bitmaps only once, but using an intelligent algorithm
|
||||
ControlAnimation::~ControlAnimation(void)
|
||||
{
|
||||
//removing from timer first
|
||||
core->timer->RemoveAnimation( this );
|
||||
|
||||
bam = NULL;
|
||||
}
|
||||
|
||||
bool ControlAnimation::SameResource(const ieResRef ResRef, int Cycle)
|
||||
{
|
||||
if (!control ) return false;
|
||||
if (!bam) return false;
|
||||
if (strnicmp(ResRef, bam->ResRef, sizeof(ieResRef) )) return false;
|
||||
int c = cycle;
|
||||
if (control->Flags&IE_GUI_BUTTON_PLAYRANDOM) {
|
||||
c&=~1;
|
||||
}
|
||||
if (Cycle!=c) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ControlAnimation::UpdateAnimation(void)
|
||||
{
|
||||
unsigned long time;
|
||||
int Cycle = cycle;
|
||||
|
||||
if (control->Flags & IE_GUI_BUTTON_PLAYRANDOM) {
|
||||
// simple Finite-State Machine
|
||||
if (anim_phase == 0) {
|
||||
frame = 0;
|
||||
anim_phase = 1;
|
||||
time = 500 + 500 * (rand() % 20);
|
||||
cycle&=~1;
|
||||
Cycle=cycle;
|
||||
} else if (anim_phase == 1) {
|
||||
if (rand() % 30 == 0) {
|
||||
cycle|=1;
|
||||
Cycle=cycle;
|
||||
}
|
||||
anim_phase = 2;
|
||||
time = 100;
|
||||
} else {
|
||||
frame++;
|
||||
time = 100;
|
||||
}
|
||||
} else {
|
||||
frame ++;
|
||||
if (has_palette) {
|
||||
time = 100; //hack for slower movement
|
||||
} else {
|
||||
time = 15;
|
||||
}
|
||||
}
|
||||
|
||||
Sprite2D* pic = bam->GetFrame( (unsigned short) frame, (unsigned char) Cycle );
|
||||
|
||||
if (pic == NULL) {
|
||||
//stopping at end frame
|
||||
if (control->Flags & IE_GUI_BUTTON_PLAYONCE) {
|
||||
core->timer->RemoveAnimation( this );
|
||||
control->SetAnimPicture( NULL );
|
||||
return;
|
||||
}
|
||||
anim_phase = 0;
|
||||
frame = 0;
|
||||
pic = bam->GetFrame( 0, (unsigned char) Cycle );
|
||||
}
|
||||
|
||||
if (pic == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (has_palette) {
|
||||
Palette* palette = pic->GetPalette();
|
||||
palette->SetupPaperdollColours(colors, 0);
|
||||
if (is_blended) {
|
||||
palette->CreateShadedAlphaChannel();
|
||||
}
|
||||
pic->SetPalette(palette);
|
||||
palette->Release();
|
||||
} else {
|
||||
if (is_blended) {
|
||||
Palette* palette = pic->GetPalette();
|
||||
palette->CreateShadedAlphaChannel();
|
||||
pic->SetPalette(palette);
|
||||
palette->Release();
|
||||
}
|
||||
}
|
||||
|
||||
control->SetAnimPicture( pic );
|
||||
core->timer->AddAnimation( this, time );
|
||||
}
|
||||
|
||||
void ControlAnimation::SetPaletteGradients(ieDword *col)
|
||||
{
|
||||
memcpy(colors, col, 8*sizeof(ieDword));
|
||||
has_palette = true;
|
||||
}
|
||||
|
||||
void ControlAnimation::SetBlend(bool b)
|
||||
{
|
||||
is_blended = b;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONTROLANIMATIONS_H
|
||||
#define CONTROLANIMATIONS_H
|
||||
|
||||
#include "RGBAColor.h"
|
||||
#include "exports.h"
|
||||
#include "globals.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class AnimationFactory;
|
||||
class Control;
|
||||
|
||||
class GEM_EXPORT ControlAnimation {
|
||||
private:
|
||||
AnimationFactory* bam;
|
||||
Control* control;
|
||||
unsigned int cycle;
|
||||
unsigned int frame;
|
||||
unsigned int anim_phase;
|
||||
bool has_palette;
|
||||
bool is_blended;
|
||||
ieDword colors[8];
|
||||
public:
|
||||
ControlAnimation(Control* ctl, const ieResRef ResRef, int Cycle = 0);
|
||||
~ControlAnimation(void);
|
||||
void UpdateAnimation();
|
||||
//report if the current resource is the same as descripted by the params
|
||||
bool SameResource(const ieResRef ResRef, int Cycle);
|
||||
void SetPaletteGradients(ieDword *col);
|
||||
void SetBlend(bool b);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,212 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Core.cpp
|
||||
* Some compatibility and utility functions
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
#include "globals.h"
|
||||
#include "exports.h"
|
||||
|
||||
#include "Interface.h"
|
||||
#include "Scriptable/Actor.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <ctype.h>
|
||||
#ifdef WIN32
|
||||
#include "win32def.h"
|
||||
#ifdef _DEBUG
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
BOOL WINAPI DllEntryPoint(HINSTANCE /*hinstDLL*/, DWORD /*fdwReason*/,
|
||||
LPVOID /*lpvReserved*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
//// Globally used functions
|
||||
|
||||
static const unsigned char orientations[25]={
|
||||
6,7,8,9,10,
|
||||
5,6,8,10,11,
|
||||
4,4,0,12,12,
|
||||
3,2,0,14,13,
|
||||
2,1,0,15,14
|
||||
};
|
||||
|
||||
/** Calculates the orientation of a character (or projectile) facing a point */
|
||||
unsigned char GetOrient(const Point &s, const Point &d)
|
||||
{
|
||||
int deltaX = s.x - d.x;
|
||||
int deltaY = s.y - d.y;
|
||||
int div = Distance(s,d);
|
||||
if(!div) return 0; //default
|
||||
if(div>3) div/=2;
|
||||
int aX=deltaX/div;
|
||||
int aY=deltaY/div;
|
||||
return orientations[(aY+2)*5+aX+2];
|
||||
}
|
||||
|
||||
/** Calculates distance between 2 points */
|
||||
unsigned int Distance(Point p, Point q)
|
||||
{
|
||||
long x = ( p.x - q.x );
|
||||
long y = ( p.y - q.y );
|
||||
return (unsigned int) sqrt( ( double ) ( x* x + y* y ) );
|
||||
}
|
||||
|
||||
/** Calculates distance squared from a point to a scriptable */
|
||||
unsigned int SquaredMapDistance(Point p, Scriptable *b)
|
||||
{
|
||||
long x = ( p.x/16 - b->Pos.x/16 );
|
||||
long y = ( p.y/12 - b->Pos.y/12 );
|
||||
return (unsigned int)(x*x + y*y);
|
||||
}
|
||||
|
||||
/** Calculates distance between 2 points */
|
||||
unsigned int Distance(Point p, Scriptable *b)
|
||||
{
|
||||
long x = ( p.x - b->Pos.x );
|
||||
long y = ( p.y - b->Pos.y );
|
||||
return (unsigned int) sqrt( ( double ) ( x* x + y* y ) );
|
||||
}
|
||||
|
||||
unsigned int PersonalDistance(Point p, Scriptable *b)
|
||||
{
|
||||
long x = ( p.x - b->Pos.x );
|
||||
long y = ( p.y - b->Pos.y );
|
||||
int ret = (int) sqrt( ( double ) ( x* x + y* y ) );
|
||||
if (b->Type==ST_ACTOR) {
|
||||
ret-=((Actor *)b)->size*10;
|
||||
}
|
||||
if (ret<0) return (unsigned int) 0;
|
||||
return (unsigned int) ret;
|
||||
}
|
||||
|
||||
unsigned int SquaredPersonalDistance(Point p, Scriptable *b)
|
||||
{
|
||||
long x = ( p.x - b->Pos.x );
|
||||
long y = ( p.y - b->Pos.y );
|
||||
int ret = x*x + y*y;
|
||||
if (b->Type==ST_ACTOR) {
|
||||
ret-=((Actor *)b)->size*100;
|
||||
}
|
||||
if (ret<0) return (unsigned int) 0;
|
||||
return (unsigned int) ret;
|
||||
}
|
||||
|
||||
/** Calculates map distance between 2 scriptables */
|
||||
unsigned int SquaredMapDistance(Scriptable *a, Scriptable *b)
|
||||
{
|
||||
long x = (a->Pos.x/16 - b->Pos.x/16 );
|
||||
long y = (a->Pos.y/12 - b->Pos.y/12 );
|
||||
return (unsigned int)(x*x + y*y);
|
||||
}
|
||||
|
||||
/** Calculates distance between 2 scriptables */
|
||||
unsigned int Distance(Scriptable *a, Scriptable *b)
|
||||
{
|
||||
long x = ( a->Pos.x - b->Pos.x );
|
||||
long y = ( a->Pos.y - b->Pos.y );
|
||||
return (unsigned int) sqrt( ( double ) ( x* x + y* y ) );
|
||||
}
|
||||
|
||||
/** Calculates distance squared between 2 scriptables */
|
||||
unsigned int SquaredDistance(Scriptable *a, Scriptable *b)
|
||||
{
|
||||
long x = ( a->Pos.x - b->Pos.x );
|
||||
long y = ( a->Pos.y - b->Pos.y );
|
||||
return (unsigned int) ( x* x + y* y );
|
||||
}
|
||||
|
||||
/** Calculates distance between 2 scriptables, including feet circle if applicable */
|
||||
unsigned int PersonalDistance(Scriptable *a, Scriptable *b)
|
||||
{
|
||||
long x = ( a->Pos.x - b->Pos.x );
|
||||
long y = ( a->Pos.y - b->Pos.y );
|
||||
int ret = (int) sqrt( ( double ) ( x* x + y* y ) );
|
||||
if (a->Type==ST_ACTOR) {
|
||||
ret-=((Actor *)a)->size*10;
|
||||
}
|
||||
if (b->Type==ST_ACTOR) {
|
||||
ret-=((Actor *)b)->size*10;
|
||||
}
|
||||
if (ret<0) return (unsigned int) 0;
|
||||
return (unsigned int) ret;
|
||||
}
|
||||
|
||||
unsigned int SquaredPersonalDistance(Scriptable *a, Scriptable *b)
|
||||
{
|
||||
long x = ( a->Pos.x - b->Pos.x );
|
||||
long y = ( a->Pos.y - b->Pos.y );
|
||||
int ret = x*x + y*y;
|
||||
if (a->Type==ST_ACTOR) {
|
||||
ret-=((Actor *)a)->size*100;
|
||||
}
|
||||
if (b->Type==ST_ACTOR) {
|
||||
ret-=((Actor *)b)->size*100;
|
||||
}
|
||||
if (ret<0) return (unsigned int) 0;
|
||||
return (unsigned int) ret;
|
||||
}
|
||||
|
||||
// returns EA relation between two scriptables (non actors are always enemies)
|
||||
// it is used for protectile targeting/iwd ids targeting too!
|
||||
int EARelation(Scriptable* Owner, Actor* target)
|
||||
{
|
||||
ieDword eao = EA_ENEMY;
|
||||
|
||||
if (Owner && Owner->Type==ST_ACTOR) {
|
||||
eao = ((Actor *) Owner)->GetStat(IE_EA);
|
||||
}
|
||||
|
||||
ieDword eat = target->GetStat(IE_EA);
|
||||
|
||||
if (eao<=EA_GOODCUTOFF) {
|
||||
|
||||
if (eat<=EA_GOODCUTOFF) {
|
||||
return EAR_FRIEND;
|
||||
}
|
||||
if (eat>=EA_EVILCUTOFF) {
|
||||
return EAR_HOSTILE;
|
||||
}
|
||||
|
||||
return EAR_NEUTRAL;
|
||||
}
|
||||
|
||||
if (eao>=EA_EVILCUTOFF) {
|
||||
|
||||
if (eat<=EA_GOODCUTOFF) {
|
||||
return EAR_HOSTILE;
|
||||
}
|
||||
if (eat>=EA_EVILCUTOFF) {
|
||||
return EAR_FRIEND;
|
||||
}
|
||||
|
||||
return EAR_NEUTRAL;
|
||||
}
|
||||
|
||||
return EAR_NEUTRAL;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "DataFileMgr.h"
|
||||
|
||||
DataFileMgr::DataFileMgr(void)
|
||||
{
|
||||
}
|
||||
|
||||
DataFileMgr::~DataFileMgr(void)
|
||||
{
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file DataFileMgr.h
|
||||
* Declares DataFileMgr class, abstract loader for .INI files
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DATAFILEMGR_H
|
||||
#define DATAFILEMGR_H
|
||||
|
||||
#include "Plugin.h"
|
||||
#include "System/DataStream.h"
|
||||
|
||||
/**
|
||||
* @class DataFileMgr
|
||||
* Abstract loader for .INI files
|
||||
*/
|
||||
|
||||
class GEM_EXPORT DataFileMgr : public Plugin {
|
||||
public:
|
||||
DataFileMgr(void);
|
||||
virtual ~DataFileMgr(void);
|
||||
virtual bool Open(DataStream* stream) = 0;
|
||||
virtual int GetTagsCount() const = 0;
|
||||
virtual const char* GetTagNameByIndex(int index) const = 0;
|
||||
virtual int GetKeysCount(const char* Tag) const = 0;
|
||||
virtual const char* GetKeyNameByIndex(const char* Tag, int index) const = 0;
|
||||
virtual const char* GetKeyAsString(const char* Tag, const char* Key,
|
||||
const char* Default) const = 0;
|
||||
virtual int GetKeyAsInt(const char* Tag, const char* Key,
|
||||
const int Default) const = 0;
|
||||
virtual float GetKeyAsFloat(const char* Tag, const char* Key,
|
||||
const float Default) const = 0;
|
||||
virtual bool GetKeyAsBool(const char* Tag, const char* Key,
|
||||
const bool Default) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,100 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Dialog.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "GameScript/GameScript.h"
|
||||
|
||||
Dialog::Dialog(void)
|
||||
{
|
||||
TopLevelCount = 0;
|
||||
}
|
||||
|
||||
Dialog::~Dialog(void)
|
||||
{
|
||||
if (initialStates) {
|
||||
for (unsigned int i = 0; i < TopLevelCount; i++) {
|
||||
if (initialStates[i]) {
|
||||
FreeDialogState( initialStates[i] );
|
||||
}
|
||||
}
|
||||
free(initialStates);
|
||||
}
|
||||
if (Order) free(Order);
|
||||
}
|
||||
|
||||
DialogState* Dialog::GetState(unsigned int index)
|
||||
{
|
||||
if (index >= TopLevelCount) {
|
||||
return NULL;
|
||||
}
|
||||
return initialStates[index];
|
||||
}
|
||||
|
||||
void Dialog::FreeDialogState(DialogState* ds)
|
||||
{
|
||||
for (unsigned int i = 0; i < ds->transitionsCount; i++) {
|
||||
DialogTransition *trans = ds->transitions[i];
|
||||
for (size_t j = 0; j < trans->actions.size(); ++j)
|
||||
trans->actions[j]->Release();
|
||||
if (trans->condition)
|
||||
delete trans->condition;
|
||||
delete( trans );
|
||||
}
|
||||
free( ds->transitions );
|
||||
if (ds->condition) {
|
||||
delete ds->condition;
|
||||
}
|
||||
delete( ds );
|
||||
}
|
||||
|
||||
int Dialog::FindFirstState(Scriptable* target)
|
||||
{
|
||||
for (unsigned int i = 0; i < TopLevelCount; i++) {
|
||||
Condition *cond = GetState( Order[i] )->condition;
|
||||
if (cond && cond->Evaluate(target)) {
|
||||
return Order[i];
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Dialog::FindRandomState(Scriptable* target)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int max = TopLevelCount;
|
||||
if (!max) return -1;
|
||||
unsigned int pick = rand()%max;
|
||||
for (i=pick; i < max; i++) {
|
||||
Condition *cond = GetState(i)->condition;
|
||||
if (cond && cond->Evaluate(target)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
for (i=0; i < pick; i++) {
|
||||
Condition *cond = GetState(i)->condition;
|
||||
if (cond && cond->Evaluate(target)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DIALOG_H
|
||||
#define DIALOG_H
|
||||
|
||||
#include "exports.h"
|
||||
#include "globals.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define IE_DLG_TR_TEXT 0x01
|
||||
#define IE_DLG_TR_TRIGGER 0x02
|
||||
#define IE_DLG_TR_ACTION 0x04
|
||||
#define IE_DLG_TR_FINAL 0x08
|
||||
#define IE_DLG_TR_JOURNAL 0x10
|
||||
#define IE_DLG_UNSOLVED 0x40
|
||||
#define IE_DLG_SOLVED 0x100
|
||||
#define IE_DLG_QUEST_GROUP 0x4000 // this is a GemRB extension
|
||||
|
||||
class Condition;
|
||||
class Action;
|
||||
|
||||
struct DialogTransition {
|
||||
ieDword Flags;
|
||||
ieStrRef textStrRef;
|
||||
ieStrRef journalStrRef;
|
||||
Condition* condition;
|
||||
std::vector<Action*> actions;
|
||||
ieResRef Dialog;
|
||||
ieDword stateIndex;
|
||||
};
|
||||
|
||||
struct DialogState {
|
||||
ieStrRef StrRef;
|
||||
DialogTransition** transitions;
|
||||
unsigned int transitionsCount;
|
||||
Condition* condition;
|
||||
unsigned int weight;
|
||||
};
|
||||
|
||||
class GEM_EXPORT Dialog {
|
||||
public:
|
||||
Dialog(void);
|
||||
~Dialog(void);
|
||||
private:
|
||||
void FreeDialogState(DialogState* ds);
|
||||
public:
|
||||
void AddState(DialogState* ds);
|
||||
DialogState* GetState(unsigned int index);
|
||||
int FindFirstState(Scriptable* target);
|
||||
int FindRandomState(Scriptable* target);
|
||||
|
||||
void Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
public:
|
||||
ieResRef ResRef;
|
||||
ieDword Flags; //freeze flags (bg2)
|
||||
unsigned int TopLevelCount;
|
||||
ieDword* Order;
|
||||
DialogState** initialStates;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,487 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "DialogHandler.h"
|
||||
|
||||
#include "strrefs.h"
|
||||
|
||||
#include "DialogMgr.h"
|
||||
#include "DisplayMessage.h"
|
||||
#include "Game.h"
|
||||
#include "GameData.h"
|
||||
#include "GlobalTimer.h"
|
||||
#include "PluginMgr.h"
|
||||
#include "ScriptEngine.h"
|
||||
#include "TableMgr.h"
|
||||
#include "Video.h"
|
||||
#include "GameScript/GameScript.h"
|
||||
#include "GUI/GameControl.h"
|
||||
#include "GUI/TextArea.h"
|
||||
|
||||
//translate section values (journal, solved, unsolved, user)
|
||||
static int sectionMap[4]={4,1,2,0};
|
||||
static const int bg2Sections[4]={4,1,2,0};
|
||||
static const int noSections[4]={0,0,0,0};
|
||||
|
||||
DialogHandler::DialogHandler(void)
|
||||
{
|
||||
dlg = NULL;
|
||||
targetID = 0;
|
||||
originalTargetID = 0;
|
||||
speakerID = 0;
|
||||
if (core->HasFeature(GF_JOURNAL_HAS_SECTIONS) ) {
|
||||
memcpy(sectionMap, bg2Sections, sizeof(sectionMap) );
|
||||
} else {
|
||||
memcpy(sectionMap, noSections, sizeof(sectionMap) );
|
||||
}
|
||||
}
|
||||
|
||||
DialogHandler::~DialogHandler(void)
|
||||
{
|
||||
if (dlg) {
|
||||
delete dlg;
|
||||
}
|
||||
}
|
||||
|
||||
//Try to start dialogue between two actors (one of them could be inanimate)
|
||||
bool DialogHandler::InitDialog(Scriptable* spk, Scriptable* tgt, const char* dlgref)
|
||||
{
|
||||
if (dlg) {
|
||||
delete dlg;
|
||||
dlg = NULL;
|
||||
}
|
||||
|
||||
PluginHolder<DialogMgr> dm(IE_DLG_CLASS_ID);
|
||||
dm->Open(gamedata->GetResource(dlgref, IE_DLG_CLASS_ID));
|
||||
dlg = dm->GetDialog();
|
||||
|
||||
if (!dlg) {
|
||||
printMessage("GameControl", "Cannot start dialog: %s\n", LIGHT_RED, dlgref);
|
||||
return false;
|
||||
}
|
||||
|
||||
strnlwrcpy(dlg->ResRef, dlgref, 8); //this isn't handled by GetDialog???
|
||||
|
||||
//target is here because it could be changed when a dialog runs onto
|
||||
//and external link, we need to find the new target (whose dialog was
|
||||
//linked to)
|
||||
|
||||
Actor *oldTarget = GetActorByGlobalID(targetID);
|
||||
speakerID = spk->GetGlobalID();
|
||||
targetID = tgt->GetGlobalID();
|
||||
if (!originalTargetID) originalTargetID = tgt->GetGlobalID();
|
||||
if (tgt->Type==ST_ACTOR) {
|
||||
Actor *tar = (Actor *) tgt;
|
||||
// TODO: verify
|
||||
spk->LastTalker=targetID;
|
||||
tar->LastTalker=speakerID;
|
||||
tar->SetCircleSize();
|
||||
}
|
||||
if (oldTarget) oldTarget->SetCircleSize();
|
||||
|
||||
GameControl *gc = core->GetGameControl();
|
||||
|
||||
if (!gc)
|
||||
return false;
|
||||
|
||||
//check if we are already in dialog
|
||||
if (gc->GetDialogueFlags()&DF_IN_DIALOG) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int si = dlg->FindFirstState( tgt );
|
||||
if (si < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//we need GUI for dialogs
|
||||
//but the guiscript must be in control here
|
||||
//gc->UnhideGUI();
|
||||
|
||||
//no exploring while in dialogue
|
||||
gc->SetScreenFlags(/*SF_GUIENABLED|*/SF_DISABLEMOUSE|SF_LOCKSCROLL, BM_OR);
|
||||
gc->SetDialogueFlags(DF_IN_DIALOG, BM_OR);
|
||||
|
||||
if (tgt->Type==ST_ACTOR) {
|
||||
Actor *tar = (Actor *) tgt;
|
||||
tar->DialogInterrupt();
|
||||
}
|
||||
|
||||
//allow mouse selection from dialog (even though screen is locked)
|
||||
Video *video = core->GetVideoDriver();
|
||||
Region vp = video->GetViewport();
|
||||
video->SetMouseEnabled(true);
|
||||
core->timer->SetMoveViewPort( tgt->Pos.x, tgt->Pos.y, 0, true );
|
||||
video->MoveViewportTo( tgt->Pos.x-vp.w/2, tgt->Pos.y-vp.h/2 );
|
||||
//there are 3 bits, if they are all unset, the dialog freezes scripts
|
||||
if (!(dlg->Flags&7) ) {
|
||||
gc->SetDialogueFlags(DF_FREEZE_SCRIPTS, BM_OR);
|
||||
}
|
||||
//opening control size to maximum, enabling dialog window
|
||||
//but the guiscript must be in control here
|
||||
//core->GetGame()->SetControlStatus(CS_HIDEGUI, BM_NAND);
|
||||
//core->GetGame()->SetControlStatus(CS_DIALOG, BM_OR);
|
||||
//core->SetEventFlag(EF_PORTRAIT);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*try to break will only try to break it, false means unconditional stop*/
|
||||
void DialogHandler::EndDialog(bool try_to_break)
|
||||
{
|
||||
if (try_to_break && (core->GetGameControl()->GetDialogueFlags()&DF_UNBREAKABLE) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Actor *tmp = GetSpeaker();
|
||||
if (tmp) {
|
||||
tmp->LeaveDialog();
|
||||
}
|
||||
speakerID = 0;
|
||||
Scriptable *tmp2 = GetTarget();
|
||||
if (tmp2 && tmp2->Type == ST_ACTOR) {
|
||||
tmp = (Actor *)tmp2;
|
||||
} else {
|
||||
tmp = NULL;
|
||||
}
|
||||
if (tmp) {
|
||||
tmp->LeaveDialog();
|
||||
}
|
||||
targetID = 0;
|
||||
if (tmp) tmp->SetCircleSize();
|
||||
originalTargetID = 0;
|
||||
ds = NULL;
|
||||
if (dlg) {
|
||||
delete dlg;
|
||||
dlg = NULL;
|
||||
}
|
||||
// FIXME: it's not so nice having this here, but things call EndDialog directly :(
|
||||
core->GetGUIScriptEngine()->RunFunction( "GUIWORLD", "DialogEnded" );
|
||||
//restoring original size
|
||||
core->GetGame()->SetControlStatus(CS_DIALOG, BM_NAND);
|
||||
core->GetGameControl()->SetScreenFlags(SF_DISABLEMOUSE|SF_LOCKSCROLL, BM_NAND);
|
||||
core->GetGameControl()->SetDialogueFlags(0, BM_SET);
|
||||
core->SetEventFlag(EF_PORTRAIT);
|
||||
}
|
||||
|
||||
|
||||
void DialogHandler::DialogChoose(unsigned int choose)
|
||||
{
|
||||
TextArea* ta = core->GetMessageTextArea();
|
||||
if (!ta) {
|
||||
printMessage("GameControl","Dialog aborted???",LIGHT_RED);
|
||||
EndDialog();
|
||||
return;
|
||||
}
|
||||
|
||||
Actor *speaker = GetSpeaker();
|
||||
if (!speaker) {
|
||||
printMessage("GameControl","Speaker gone???",LIGHT_RED);
|
||||
EndDialog();
|
||||
return;
|
||||
}
|
||||
|
||||
Scriptable *target = GetTarget();
|
||||
if (!target) {
|
||||
printMessage("GameControl","Target gone???",LIGHT_RED);
|
||||
EndDialog();
|
||||
return;
|
||||
}
|
||||
Actor *tgt = NULL;
|
||||
if (target->Type == ST_ACTOR) {
|
||||
tgt = (Actor *)target;
|
||||
}
|
||||
|
||||
Video *video = core->GetVideoDriver();
|
||||
Region vp = video->GetViewport();
|
||||
video->SetMouseEnabled(true);
|
||||
core->timer->SetMoveViewPort( target->Pos.x, target->Pos.y, 0, true );
|
||||
video->MoveViewportTo( target->Pos.x-vp.w/2, target->Pos.y-vp.h/2 );
|
||||
|
||||
if (choose == (unsigned int) -1) {
|
||||
//increasing talkcount after top level condition was determined
|
||||
|
||||
int si = dlg->FindFirstState( tgt );
|
||||
if (si<0) {
|
||||
EndDialog();
|
||||
return;
|
||||
}
|
||||
|
||||
if (tgt) {
|
||||
if (core->GetGameControl()->GetDialogueFlags()&DF_TALKCOUNT) {
|
||||
core->GetGameControl()->SetDialogueFlags(DF_TALKCOUNT, BM_NAND);
|
||||
tgt->TalkCount++;
|
||||
} else if (core->GetGameControl()->GetDialogueFlags()&DF_INTERACT) {
|
||||
core->GetGameControl()->SetDialogueFlags(DF_INTERACT, BM_NAND);
|
||||
tgt->InteractCount++;
|
||||
}
|
||||
}
|
||||
ds = dlg->GetState( si );
|
||||
} else {
|
||||
if (ds->transitionsCount <= choose) {
|
||||
return;
|
||||
}
|
||||
|
||||
DialogTransition* tr = ds->transitions[choose];
|
||||
|
||||
ta->PopMinRow();
|
||||
|
||||
if (tr->Flags&IE_DLG_TR_JOURNAL) {
|
||||
int Section = 0;
|
||||
if (tr->Flags&IE_DLG_UNSOLVED) {
|
||||
Section |= 1;
|
||||
}
|
||||
if (tr->Flags&IE_DLG_SOLVED) {
|
||||
Section |= 2;
|
||||
}
|
||||
if (core->GetGame()->AddJournalEntry(tr->journalStrRef, sectionMap[Section], tr->Flags>>16) ) {
|
||||
displaymsg->DisplayConstantString(STR_JOURNALCHANGE,0xffff00);
|
||||
char *string = core->GetString( tr->journalStrRef );
|
||||
//cutting off the strings at the first crlf
|
||||
char *poi = strchr(string,'\n');
|
||||
if (poi) {
|
||||
*poi='\0';
|
||||
}
|
||||
displaymsg->DisplayString( string );
|
||||
free( string );
|
||||
}
|
||||
}
|
||||
|
||||
if (tr->textStrRef != 0xffffffff) {
|
||||
//allow_zero is for PST (deionarra's text)
|
||||
displaymsg->DisplayStringName( (int) (tr->textStrRef), 0x8080FF, speaker, IE_STR_SOUND|IE_STR_SPEECH|IE_STR_ALLOW_ZERO);
|
||||
if (core->HasFeature( GF_DIALOGUE_SCROLLS )) {
|
||||
ta->AppendText( "", -1 );
|
||||
}
|
||||
}
|
||||
|
||||
if (tr->actions.size()) {
|
||||
// does this belong here? we must clear actions somewhere before
|
||||
// we start executing them (otherwise queued actions interfere)
|
||||
// executing actions directly does not work, because dialog
|
||||
// needs to end before final actions are executed due to
|
||||
// actions making new dialogs!
|
||||
if (target->Type == ST_ACTOR) ((Movable *)target)->ClearPath(); // fuzzie added this
|
||||
target->ClearActions();
|
||||
|
||||
// do not interrupt during dialog actions (needed for aerie.d polymorph block)
|
||||
char buf[20];
|
||||
strcpy(buf, "SetInterrupt(FALSE)");
|
||||
target->AddAction( GenerateAction( buf ) );
|
||||
for (unsigned int i = 0; i < tr->actions.size(); i++) {
|
||||
target->AddAction(tr->actions[i]);
|
||||
}
|
||||
strcpy(buf, "SetInterrupt(TRUE)");
|
||||
target->AddAction( GenerateAction( buf ) );
|
||||
}
|
||||
|
||||
int final_dialog = tr->Flags & IE_DLG_TR_FINAL;
|
||||
|
||||
if (final_dialog) {
|
||||
ta->SetMinRow( false );
|
||||
EndDialog();
|
||||
}
|
||||
|
||||
if (final_dialog) {
|
||||
return;
|
||||
}
|
||||
|
||||
// avoid problems when dhjollde.dlg tries starting a cutscene in the middle of a dialog
|
||||
// (it seems harmless doing it in non-HoW too, since other versions would just break in such a situation)
|
||||
core->SetCutSceneMode( false );
|
||||
|
||||
//displaying dialog for selected option
|
||||
int si = tr->stateIndex;
|
||||
//follow external linkage, if required
|
||||
if (tr->Dialog[0] && strnicmp( tr->Dialog, dlg->ResRef, 8 )) {
|
||||
//target should be recalculated!
|
||||
tgt = NULL;
|
||||
if (originalTargetID) {
|
||||
// always try original target first (sometimes there are multiple
|
||||
// actors with the same dialog in an area, we want to pick the one
|
||||
// we were talking to)
|
||||
tgt = GetActorByGlobalID(originalTargetID);
|
||||
if (tgt && strnicmp( tgt->GetDialog(GD_NORMAL), tr->Dialog, 8 ) != 0) {
|
||||
tgt = NULL;
|
||||
}
|
||||
}
|
||||
if (!tgt) {
|
||||
// then just search the current area for an actor with the dialog
|
||||
tgt = target->GetCurrentArea()->GetActorByDialog(tr->Dialog);
|
||||
}
|
||||
if (!tgt) {
|
||||
// try searching for banter dialogue: the original engine seems to
|
||||
// happily let you randomly switch between normal and banter dialogs
|
||||
|
||||
// TODO: work out if this should go somewhere more central (such
|
||||
// as GetActorByDialog), or if there's a less awful way to do this
|
||||
// (we could cache the entries, for example)
|
||||
// TODO: fix for ToB (see also the Interact action)
|
||||
AutoTable pdtable("interdia");
|
||||
if (pdtable) {
|
||||
int row = pdtable->FindTableValue( pdtable->GetColumnIndex("FILE"), tr->Dialog );
|
||||
tgt = target->GetCurrentArea()->GetActorByScriptName(pdtable->GetRowName(row));
|
||||
}
|
||||
}
|
||||
target = tgt;
|
||||
if (!target) {
|
||||
printMessage("Dialog","Can't redirect dialog\n",YELLOW);
|
||||
ta->SetMinRow( false );
|
||||
EndDialog();
|
||||
return;
|
||||
}
|
||||
Actor *oldTarget = GetActorByGlobalID(targetID);
|
||||
targetID = tgt->GetGlobalID();
|
||||
tgt->SetCircleSize();
|
||||
if (oldTarget) oldTarget->SetCircleSize();
|
||||
// we have to make a backup, tr->Dialog is freed
|
||||
ieResRef tmpresref;
|
||||
strnlwrcpy(tmpresref,tr->Dialog, 8);
|
||||
/*if (target->GetInternalFlag()&IF_NOINT) {
|
||||
// this whole check moved out of InitDialog by fuzzie, see comments
|
||||
// for the IF_NOINT check in BeginDialog
|
||||
displaymsg->DisplayConstantString(STR_TARGETBUSY,0xff0000);
|
||||
ta->SetMinRow( false );
|
||||
EndDialog();
|
||||
return;
|
||||
}*/
|
||||
if (!InitDialog( speaker, target, tmpresref)) {
|
||||
// error was displayed by InitDialog
|
||||
ta->SetMinRow( false );
|
||||
EndDialog();
|
||||
return;
|
||||
}
|
||||
}
|
||||
ds = dlg->GetState( si );
|
||||
if (!ds) {
|
||||
printMessage("Dialog","Can't find next dialog\n",YELLOW);
|
||||
ta->SetMinRow( false );
|
||||
EndDialog();
|
||||
return;
|
||||
}
|
||||
}
|
||||
//displaying npc text
|
||||
displaymsg->DisplayStringName( ds->StrRef, 0x70FF70, target, IE_STR_SOUND|IE_STR_SPEECH);
|
||||
//adding a gap between options and npc text
|
||||
ta->AppendText("",-1);
|
||||
int i;
|
||||
int idx = 0;
|
||||
ta->SetMinRow( true );
|
||||
//first looking for a 'continue' opportunity, the order is descending (a la IE)
|
||||
unsigned int x = ds->transitionsCount;
|
||||
while(x--) {
|
||||
if (ds->transitions[x]->Flags & IE_DLG_TR_FINAL) {
|
||||
continue;
|
||||
}
|
||||
if (ds->transitions[x]->textStrRef != 0xffffffff) {
|
||||
continue;
|
||||
}
|
||||
if (ds->transitions[x]->Flags & IE_DLG_TR_TRIGGER) {
|
||||
if (ds->transitions[x]->condition &&
|
||||
!ds->transitions[x]->condition->Evaluate(target)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
core->GetDictionary()->SetAt("DialogOption",x);
|
||||
core->GetGameControl()->SetDialogueFlags(DF_OPENCONTINUEWINDOW, BM_OR);
|
||||
goto end_of_choose;
|
||||
}
|
||||
for (x = 0; x < ds->transitionsCount; x++) {
|
||||
if (ds->transitions[x]->Flags & IE_DLG_TR_TRIGGER) {
|
||||
if (ds->transitions[x]->condition &&
|
||||
!ds->transitions[x]->condition->Evaluate(target)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
if (ds->transitions[x]->textStrRef == 0xffffffff) {
|
||||
//dialogchoose should be set to x
|
||||
//it isn't important which END option was chosen, as it ends
|
||||
core->GetDictionary()->SetAt("DialogOption",x);
|
||||
core->GetGameControl()->SetDialogueFlags(DF_OPENENDWINDOW, BM_OR);
|
||||
} else {
|
||||
char *string = ( char * ) malloc( 40 );
|
||||
sprintf( string, "[s=%d,ffffff,ff0000]%d - [p]", x, idx );
|
||||
i = ta->AppendText( string, -1 );
|
||||
free( string );
|
||||
string = core->GetString( ds->transitions[x]->textStrRef );
|
||||
ta->AppendText( string, i );
|
||||
free( string );
|
||||
ta->AppendText( "[/p][/s]", i );
|
||||
}
|
||||
}
|
||||
// this happens if a trigger isn't implemented or the dialog is wrong
|
||||
if (!idx) {
|
||||
printMessage("Dialog", "There were no valid dialog options!\n", YELLOW);
|
||||
core->GetGameControl()->SetDialogueFlags(DF_OPENENDWINDOW, BM_OR);
|
||||
}
|
||||
end_of_choose:
|
||||
//padding the rows so our text will be at the top
|
||||
if (core->HasFeature( GF_DIALOGUE_SCROLLS )) {
|
||||
ta->AppendText( "", -1 );
|
||||
}
|
||||
else {
|
||||
ta->PadMinRow();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: duplicate of the one in GameControl
|
||||
Actor *DialogHandler::GetActorByGlobalID(ieDword ID)
|
||||
{
|
||||
if (!ID)
|
||||
return NULL;
|
||||
Game* game = core->GetGame();
|
||||
if (!game)
|
||||
return NULL;
|
||||
|
||||
Map* area = game->GetCurrentArea( );
|
||||
if (!area)
|
||||
return NULL;
|
||||
return area->GetActorByGlobalID(ID);
|
||||
}
|
||||
|
||||
Scriptable *DialogHandler::GetTarget()
|
||||
{
|
||||
// TODO: area GetScriptableByGlobalID?
|
||||
|
||||
if (!targetID) return NULL;
|
||||
|
||||
Game *game = core->GetGame();
|
||||
if (!game) return NULL;
|
||||
|
||||
Map *area = game->GetCurrentArea();
|
||||
if (!area) return NULL;
|
||||
|
||||
Actor *actor = area->GetActorByGlobalID(targetID);
|
||||
if (actor) return actor;
|
||||
|
||||
Door *door = area->GetDoorByGlobalID(targetID);
|
||||
if (door) return (Scriptable *)door;
|
||||
Container *container = area->GetContainerByGlobalID(targetID);
|
||||
if (container) return (Scriptable *)container;
|
||||
InfoPoint *ip = area->GetInfoPointByGlobalID(targetID);
|
||||
if (ip) return (Scriptable *)ip;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Actor *DialogHandler::GetSpeaker()
|
||||
{
|
||||
return GetActorByGlobalID(speakerID);
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DIALOGHANDLER_H
|
||||
#define DIALOGHANDLER_H
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
#include "Dialog.h"
|
||||
|
||||
class GEM_EXPORT DialogHandler {
|
||||
public:
|
||||
DialogHandler();
|
||||
~DialogHandler();
|
||||
private:
|
||||
/** this function safely retrieves an Actor by ID */
|
||||
Actor *GetActorByGlobalID(ieDword ID);
|
||||
private:
|
||||
DialogState* ds;
|
||||
Dialog* dlg;
|
||||
public:
|
||||
ieDword speakerID;
|
||||
ieDword targetID;
|
||||
ieDword originalTargetID;
|
||||
public:
|
||||
Scriptable *GetTarget();
|
||||
Actor *GetSpeaker();
|
||||
|
||||
bool InitDialog(Scriptable* speaker, Scriptable* target, const char* dlgref);
|
||||
void EndDialog(bool try_to_break=false);
|
||||
void DialogChoose(unsigned int choose);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,29 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "DialogMgr.h"
|
||||
|
||||
DialogMgr::DialogMgr(void)
|
||||
{
|
||||
}
|
||||
|
||||
DialogMgr::~DialogMgr(void)
|
||||
{
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DIALOGMGR_H
|
||||
#define DIALOGMGR_H
|
||||
|
||||
#include "Dialog.h"
|
||||
#include "Plugin.h"
|
||||
#include "System/DataStream.h"
|
||||
|
||||
class GEM_EXPORT DialogMgr : public Plugin {
|
||||
public:
|
||||
DialogMgr(void);
|
||||
virtual ~DialogMgr(void);
|
||||
virtual bool Open(DataStream* stream) = 0;
|
||||
virtual Dialog* GetDialog() const = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,240 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003-2005 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "DisplayMessage.h"
|
||||
|
||||
#include "strrefs.h"
|
||||
|
||||
#include "Interface.h"
|
||||
#include "TableMgr.h"
|
||||
#include "GUI/Label.h"
|
||||
#include "GUI/TextArea.h"
|
||||
#include "Scriptable/Actor.h"
|
||||
|
||||
GEM_EXPORT DisplayMessage * displaymsg;
|
||||
|
||||
static int strref_table[STRREF_COUNT];
|
||||
|
||||
#define PALSIZE 8
|
||||
static Color ActorColor[PALSIZE];
|
||||
static const char* DisplayFormatName = "[color=%06X]%s - [/color][p][color=%06X]%s[/color][/p]";
|
||||
static const char* DisplayFormatAction = "[color=%06X]%s - [/color][p][color=%06X]%s %s[/color][/p]";
|
||||
static const char* DisplayFormat = "[/color][p][color=%06X]%s[/color][/p]";
|
||||
static const char* DisplayFormatValue = "[/color][p][color=%06X]%s: %d[/color][/p]";
|
||||
static const char* DisplayFormatNameString = "[color=%06X]%s - [/color][p][color=%06X]%s: %s[/color][/p]";
|
||||
|
||||
DisplayMessage::DisplayMessage(void) {
|
||||
ReadStrrefs();
|
||||
}
|
||||
|
||||
bool DisplayMessage::ReadStrrefs()
|
||||
{
|
||||
int i;
|
||||
memset(strref_table,-1,sizeof(strref_table) );
|
||||
AutoTable tab("strings");
|
||||
if (!tab) {
|
||||
return false;
|
||||
}
|
||||
for(i=0;i<STRREF_COUNT;i++) {
|
||||
strref_table[i]=atoi(tab->QueryField(i,0));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DisplayMessage::DisplayString(const char* Text, Scriptable *target) const
|
||||
{
|
||||
Label *l = core->GetMessageLabel();
|
||||
if (l) {
|
||||
l->SetText(Text);
|
||||
}
|
||||
TextArea *ta = core->GetMessageTextArea();
|
||||
if (ta) {
|
||||
ta->AppendText( Text, -1 );
|
||||
} else {
|
||||
if(target) {
|
||||
char *tmp = strdup(Text);
|
||||
|
||||
target->DisplayHeadText(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ieStrRef DisplayMessage::GetStringReference(int stridx) const
|
||||
{
|
||||
return strref_table[stridx];
|
||||
}
|
||||
|
||||
bool DisplayMessage::HasStringReference(int stridx) const
|
||||
{
|
||||
return strref_table[stridx] != -1;
|
||||
}
|
||||
|
||||
unsigned int DisplayMessage::GetSpeakerColor(const char *&name, const Scriptable *&speaker) const
|
||||
{
|
||||
unsigned int speaker_color;
|
||||
|
||||
if(!speaker) return 0;
|
||||
switch (speaker->Type) {
|
||||
case ST_ACTOR:
|
||||
name = speaker->GetName(-1);
|
||||
core->GetPalette( ((Actor *) speaker)->GetStat(IE_MAJOR_COLOR) & 0xFF, PALSIZE, ActorColor );
|
||||
speaker_color = (ActorColor[4].r<<16) | (ActorColor[4].g<<8) | ActorColor[4].b;
|
||||
break;
|
||||
case ST_TRIGGER: case ST_PROXIMITY: case ST_TRAVEL:
|
||||
name = core->GetString( speaker->DialogName );
|
||||
speaker_color = 0xc0c0c0;
|
||||
break;
|
||||
default:
|
||||
name = "";
|
||||
speaker_color = 0x800000;
|
||||
break;
|
||||
}
|
||||
return speaker_color;
|
||||
}
|
||||
|
||||
|
||||
//simply displaying a constant string
|
||||
void DisplayMessage::DisplayConstantString(int stridx, unsigned int color, Scriptable *target) const
|
||||
{
|
||||
if (stridx<0) return;
|
||||
char* text = core->GetString( strref_table[stridx], IE_STR_SOUND );
|
||||
DisplayString(text, color, target);
|
||||
core->FreeString(text);
|
||||
}
|
||||
|
||||
void DisplayMessage::DisplayString(int stridx, unsigned int color, ieDword flags) const
|
||||
{
|
||||
if (stridx<0) return;
|
||||
char* text = core->GetString( stridx, flags);
|
||||
DisplayString(text, color, NULL);
|
||||
core->FreeString(text);
|
||||
}
|
||||
|
||||
void DisplayMessage::DisplayString(const char *text, unsigned int color, Scriptable *target) const
|
||||
{
|
||||
if (!text) return;
|
||||
int newlen = (int)(strlen( DisplayFormat) + strlen( text ) + 12);
|
||||
char* newstr = ( char* ) malloc( newlen );
|
||||
snprintf( newstr, newlen, DisplayFormat, color, text );
|
||||
DisplayString( newstr, target );
|
||||
free( newstr );
|
||||
}
|
||||
|
||||
// String format is
|
||||
// blah : whatever
|
||||
void DisplayMessage::DisplayConstantStringValue(int stridx, unsigned int color, ieDword value) const
|
||||
{
|
||||
if (stridx<0) return;
|
||||
char* text = core->GetString( strref_table[stridx], IE_STR_SOUND );
|
||||
int newlen = (int)(strlen( DisplayFormat ) + strlen( text ) + 28);
|
||||
char* newstr = ( char* ) malloc( newlen );
|
||||
snprintf( newstr, newlen, DisplayFormatValue, color, text, (int) value );
|
||||
core->FreeString( text );
|
||||
DisplayString( newstr );
|
||||
free( newstr );
|
||||
}
|
||||
|
||||
// String format is
|
||||
// <charname> - blah blah : whatever
|
||||
void DisplayMessage::DisplayConstantStringNameString(int stridx, unsigned int color, int stridx2, const Scriptable *actor) const
|
||||
{
|
||||
unsigned int actor_color;
|
||||
const char *name = 0;
|
||||
|
||||
if (stridx<0) return;
|
||||
actor_color = GetSpeakerColor(name, actor);
|
||||
char* text = core->GetString( strref_table[stridx], IE_STR_SOUND );
|
||||
char* text2 = core->GetString( strref_table[stridx2], IE_STR_SOUND );
|
||||
int newlen = (int)(strlen( DisplayFormat ) + strlen(name) + strlen( text ) + strlen(text2) + 20);
|
||||
char* newstr = ( char* ) malloc( newlen );
|
||||
if (strlen(text2)) {
|
||||
snprintf( newstr, newlen, DisplayFormatNameString, actor_color, name, color, text, text2 );
|
||||
} else {
|
||||
snprintf( newstr, newlen, DisplayFormatName, color, name, color, text );
|
||||
}
|
||||
core->FreeString( text );
|
||||
core->FreeString( text2 );
|
||||
DisplayString( newstr );
|
||||
free( newstr );
|
||||
}
|
||||
|
||||
// String format is
|
||||
// <charname> - blah blah
|
||||
void DisplayMessage::DisplayConstantStringName(int stridx, unsigned int color, const Scriptable *speaker) const
|
||||
{
|
||||
if (stridx<0) return;
|
||||
if(!speaker) return;
|
||||
|
||||
char* text = core->GetString( strref_table[stridx], IE_STR_SOUND|IE_STR_SPEECH );
|
||||
DisplayStringName(text, color, speaker);
|
||||
core->FreeString(text);
|
||||
}
|
||||
|
||||
// String format is
|
||||
// <charname> - blah blah <someoneelse>
|
||||
void DisplayMessage::DisplayConstantStringAction(int stridx, unsigned int color, const Scriptable *attacker, const Scriptable *target) const
|
||||
{
|
||||
unsigned int attacker_color;
|
||||
const char *name1 = 0;
|
||||
const char *name2 = 0;
|
||||
|
||||
if (stridx<0) return;
|
||||
|
||||
GetSpeakerColor(name2, target);
|
||||
attacker_color = GetSpeakerColor(name1, attacker);
|
||||
|
||||
char* text = core->GetString( strref_table[stridx], IE_STR_SOUND|IE_STR_SPEECH );
|
||||
int newlen = (int)(strlen( DisplayFormatAction ) + strlen( name1 ) +
|
||||
+ strlen( name2 ) + strlen( text ) + 18);
|
||||
char* newstr = ( char* ) malloc( newlen );
|
||||
snprintf( newstr, newlen, DisplayFormatAction, attacker_color, name1, color,
|
||||
text, name2);
|
||||
core->FreeString( text );
|
||||
DisplayString( newstr );
|
||||
free( newstr );
|
||||
}
|
||||
|
||||
void DisplayMessage::DisplayStringName(int stridx, unsigned int color, const Scriptable *speaker, ieDword flags) const
|
||||
{
|
||||
if (stridx<0) return;
|
||||
|
||||
char* text = core->GetString( stridx, flags);
|
||||
DisplayStringName(text, color, speaker);
|
||||
core->FreeString( text );
|
||||
}
|
||||
|
||||
void DisplayMessage::DisplayStringName(const char *text, unsigned int color, const Scriptable *speaker) const
|
||||
{
|
||||
unsigned int speaker_color;
|
||||
const char *name = 0;
|
||||
|
||||
if (!text) return;
|
||||
speaker_color = GetSpeakerColor(name, speaker);
|
||||
|
||||
//FIXME: what happens if there is no name?
|
||||
if (name) {
|
||||
int newlen = (int)(strlen( DisplayFormatName ) + strlen( name ) +
|
||||
+ strlen( text ) + 18);
|
||||
char* newstr = ( char* ) malloc( newlen );
|
||||
snprintf( newstr, newlen, DisplayFormatName, speaker_color, name, color, text );
|
||||
DisplayString( newstr );
|
||||
free( newstr );
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003-2005 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file DisplayMessage.h
|
||||
* Declaration of the DisplayMessage class used for displaying messages in
|
||||
* game message window
|
||||
*/
|
||||
|
||||
#ifndef DISPLAYMESSAGE_H
|
||||
#define DISPLAYMESSAGE_H
|
||||
|
||||
#include "exports.h"
|
||||
#include "ie_types.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
class Scriptable;
|
||||
|
||||
class GEM_EXPORT DisplayMessage
|
||||
{
|
||||
private:
|
||||
bool ReadStrrefs();
|
||||
|
||||
public:
|
||||
DisplayMessage(void);
|
||||
|
||||
/** returns a string reference from a string reference index constant */
|
||||
ieStrRef GetStringReference(int stridx) const;
|
||||
/** returns true if a string reference for a string reference index constant exists */
|
||||
bool HasStringReference(int stridx) const;
|
||||
/** returns the speaker's color and name */
|
||||
unsigned int GetSpeakerColor(const char *&name, const Scriptable *&speaker) const;
|
||||
/** displays any string in the textarea */
|
||||
void DisplayString(const char *txt, Scriptable *speaker=NULL) const;
|
||||
/** displays a string constant in the textarea */
|
||||
void DisplayConstantString(int stridx, unsigned int color, Scriptable *speaker=NULL) const;
|
||||
/** displays actor name - action : parameter */
|
||||
void DisplayConstantStringNameString(int stridx, unsigned int color, int stridx2, const Scriptable *actor) const;
|
||||
/** displays a string constant followed by a number in the textarea */
|
||||
void DisplayConstantStringValue(int stridx, unsigned int color, ieDword value) const;
|
||||
/** displays a string constant in the textarea, starting with speaker's name */
|
||||
void DisplayConstantStringName(int stridx, unsigned int color, const Scriptable *speaker) const;
|
||||
/** displays a string constant in the textarea, starting with actor, and ending with target */
|
||||
void DisplayConstantStringAction(int stridx, unsigned int color, const Scriptable *actor, const Scriptable *target) const;
|
||||
/** displays a string in the textarea */
|
||||
void DisplayString(int stridx, unsigned int color, ieDword flags) const;
|
||||
void DisplayString(const char *text, unsigned int color, Scriptable *target) const;
|
||||
/** displays a string in the textarea, starting with speaker's name */
|
||||
void DisplayStringName(int stridx, unsigned int color, const Scriptable *speaker, ieDword flags) const;
|
||||
void DisplayStringName(const char *text, unsigned int color, const Scriptable *speaker) const;
|
||||
};
|
||||
|
||||
extern GEM_EXPORT DisplayMessage * displaymsg;
|
||||
|
||||
#endif
|
||||
@@ -1,139 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Effect.h
|
||||
* Declares Effect class implementing spell and spell-like effects
|
||||
* and related defines
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_H
|
||||
#define EFFECT_H
|
||||
|
||||
#include "ie_types.h"
|
||||
|
||||
#include "Region.h"
|
||||
|
||||
class Actor;
|
||||
|
||||
//local variables in creatures are stored in fake opcodes
|
||||
#define FAKE_VARIABLE_OPCODE 187
|
||||
#define FAKE_VARIABLE_MARKER 1
|
||||
|
||||
// Effect target types
|
||||
#define FX_TARGET_UNKNOWN 0
|
||||
#define FX_TARGET_SELF 1
|
||||
#define FX_TARGET_PRESET 2
|
||||
#define FX_TARGET_PARTY 3
|
||||
#define FX_TARGET_ALL 4
|
||||
#define FX_TARGET_ALL_BUT_PARTY 5
|
||||
#define FX_TARGET_OWN_SIDE 6
|
||||
#define FX_TARGET_OTHER_SIDE 7
|
||||
#define FX_TARGET_ALL_BUT_SELF 8
|
||||
#define FX_TARGET_ORIGINAL 9
|
||||
|
||||
// Effect duration/timing types
|
||||
#define FX_DURATION_INSTANT_LIMITED 0
|
||||
#define FX_DURATION_INSTANT_PERMANENT 1
|
||||
#define FX_DURATION_INSTANT_WHILE_EQUIPPED 2
|
||||
#define FX_DURATION_DELAY_LIMITED 3 //this contains a relative onset time (delay) also used as duration, transforms to 6 when applied
|
||||
#define FX_DURATION_DELAY_PERMANENT 4 //this transforms to 9 (i guess)
|
||||
#define FX_DURATION_DELAY_UNSAVED 5 //this transforms to 8
|
||||
#define FX_DURATION_DELAY_LIMITED_PENDING 6 //this contains an absolute onset time and a duration
|
||||
#define FX_DURATION_AFTER_EXPIRES 7 //this is a delayed non permanent effect (resolves to JUST_EXPIRED)
|
||||
#define FX_DURATION_PERMANENT_UNSAVED 8
|
||||
#define FX_DURATION_INSTANT_PERMANENT_AFTER_BONUSES 9//this is a special permanent
|
||||
#define FX_DURATION_JUST_EXPIRED 10
|
||||
#define MAX_TIMING_MODE 11
|
||||
#define FX_DURATION_ABSOLUTE 0x1000
|
||||
|
||||
// Effect resistance types
|
||||
#define FX_NO_RESIST_NO_DISPEL 0
|
||||
#define FX_CAN_RESIST_CAN_DISPEL 1
|
||||
//#define FX_CAN_RESIST_NO_DISPEL 2 //same as 0 (not resistable, not dispellable)
|
||||
#define FX_NO_RESIST_CAN_DISPEL 3
|
||||
#define FX_CAN_DISPEL 1
|
||||
#define FX_CAN_RESIST 3
|
||||
|
||||
/**
|
||||
* @class Effect
|
||||
* Structure holding information about single spell or spell-like effect.
|
||||
*/
|
||||
|
||||
// the same as ITMFeature and SPLFeature
|
||||
struct Effect {
|
||||
ieDword Opcode;
|
||||
ieDword Target;
|
||||
ieDword Power;
|
||||
ieDword Parameter1;
|
||||
ieDword Parameter2;
|
||||
ieWord TimingMode; //0x1000 -- no need of conversion
|
||||
ieWord unknown2;
|
||||
ieDword Resistance;
|
||||
ieDword Duration;
|
||||
ieWord Probability1;
|
||||
ieWord Probability2;
|
||||
//keep these four in one bunch, VariableName will
|
||||
//spread across them
|
||||
ieResRef Resource;
|
||||
ieResRef Resource2; //vvc in a lot of effects
|
||||
ieResRef Resource3;
|
||||
ieResRef Resource4;
|
||||
ieDword DiceThrown;
|
||||
ieDword DiceSides;
|
||||
ieDword SavingThrowType;
|
||||
ieDword SavingThrowBonus;
|
||||
ieWord IsVariable;
|
||||
ieWord IsSaveForHalfDamage;
|
||||
|
||||
// EFF V2.0 fields:
|
||||
ieDword PrimaryType; //school
|
||||
ieDword MinAffectedLevel;
|
||||
ieDword MaxAffectedLevel;
|
||||
ieDword Parameter3;
|
||||
ieDword Parameter4;
|
||||
ieDword PosX, PosY;
|
||||
ieDword SourceType; //1-item, 2-spell
|
||||
ieResRef Source;
|
||||
ieDword SourceFlags;
|
||||
ieDword Projectile; //9c
|
||||
ieDwordSigned InventorySlot; //a0
|
||||
//Original engine had a VariableName here, but it is stored in the resource fields
|
||||
ieDword CasterLevel; //c4 in both
|
||||
ieDword FirstApply; //c8 in bg2, cc in iwd2
|
||||
ieDword SecondaryType;
|
||||
ieDword SecondaryDelay; //still not sure about this
|
||||
ieDword CasterID; //10c in bg2 (not saved?)
|
||||
// These are not in the IE files, but are our precomputed values
|
||||
ieDword random_value;
|
||||
public:
|
||||
//don't modify position in case it was already set
|
||||
void SetPosition(const Point &p) {
|
||||
if(PosX==0xffffffff && PosY==0xffffffff) {
|
||||
PosX=p.x;
|
||||
PosY=p.y;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME: what about area spells? They can have map & coordinates as target
|
||||
//void AddEffect(Effect* fx, Actor* self, Actor* pretarget);
|
||||
|
||||
#endif // ! EFFECT_H
|
||||
@@ -1,29 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EffectMgr.h"
|
||||
|
||||
EffectMgr::EffectMgr(void)
|
||||
{
|
||||
}
|
||||
|
||||
EffectMgr::~EffectMgr(void)
|
||||
{
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file EffectMgr.h
|
||||
* Declares EffectMgr class, loader for Effect objects
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef EFFECTMGR_H
|
||||
#define EFFECTMGR_H
|
||||
|
||||
#include "Effect.h"
|
||||
#include "Plugin.h"
|
||||
#include "System/DataStream.h"
|
||||
|
||||
/**
|
||||
* @class EffectMgr
|
||||
* Abstract loader for Effect objects
|
||||
*/
|
||||
|
||||
class GEM_EXPORT EffectMgr : public Plugin {
|
||||
public:
|
||||
EffectMgr(void);
|
||||
virtual ~EffectMgr(void);
|
||||
virtual bool Open(DataStream* stream, bool autoFree = true) = 0;
|
||||
|
||||
/** Fills fx with Effect data loaded from the stream */
|
||||
virtual Effect* GetEffect(Effect *fx) = 0;
|
||||
/** Fills fx with Effect v1 data loaded from the stream*/
|
||||
virtual Effect* GetEffectV1(Effect *fx) = 0;
|
||||
/** Fills fx with Effect v2.0 data loaded from the stream*/
|
||||
virtual Effect* GetEffectV20(Effect *fx) = 0;
|
||||
/** Fills the stream with Effect v2 data loaded from the effect*/
|
||||
virtual void PutEffectV2(DataStream *stream, const Effect *fx) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,314 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file EffectQueue.h
|
||||
* Declares EffectQueue class holding and processing all spell effects
|
||||
* on a single Actor
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
#ifndef EFFECTQUEUE_H
|
||||
#define EFFECTQUEUE_H
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
#include "Effect.h"
|
||||
#include "Region.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <list>
|
||||
|
||||
class Actor;
|
||||
class Map;
|
||||
class Scriptable;
|
||||
|
||||
/** Maximum number of different Effect opcodes */
|
||||
#define MAX_EFFECTS 512
|
||||
|
||||
///** if the effect returns this, stop adding any other effect */
|
||||
#define FX_ABORT 0
|
||||
/** these effects don't stick around if used as permanent,
|
||||
* in that case they modify a base stat like charisma modifier */
|
||||
#define FX_PERMANENT 2
|
||||
/** these effects never stick around, use them for instant effects like damage */
|
||||
#define FX_NOT_APPLIED 3
|
||||
/** these effects always stick around when applied as permanent or duration */
|
||||
#define FX_APPLIED 1
|
||||
///** insert the effect instead of push back */
|
||||
#define FX_INSERT 4
|
||||
|
||||
//remove level effects flags
|
||||
#define RL_DISPELLABLE 1 //only dispellables
|
||||
#define RL_MATCHSCHOOL 2 //match school
|
||||
#define RL_MATCHSECTYPE 4 //match secondary type
|
||||
#define RL_REMOVEFIRST 8 //remove only one spell (could be more effects)
|
||||
|
||||
//bouncing immunities
|
||||
#define BNC_PROJECTILE 1
|
||||
#define BNC_OPCODE 2
|
||||
#define BNC_LEVEL 4
|
||||
#define BNC_SCHOOL 8
|
||||
#define BNC_SECTYPE 0x10
|
||||
#define BNC_RESOURCE 0x20
|
||||
#define BNC_PROJECTILE_DEC 0x100
|
||||
#define BNC_OPCODE_DEC 0x200
|
||||
#define BNC_LEVEL_DEC 0x400
|
||||
#define BNC_SCHOOL_DEC 0x800
|
||||
#define BNC_SECTYPE_DEC 0x1000
|
||||
#define BNC_RESOURCE_DEC 0x2000
|
||||
|
||||
//normal immunities
|
||||
#define IMM_PROJECTILE 1
|
||||
#define IMM_OPCODE 2
|
||||
#define IMM_LEVEL 4
|
||||
#define IMM_SCHOOL 8
|
||||
#define IMM_SECTYPE 16
|
||||
#define IMM_RESOURCE 32
|
||||
#define IMM_PROJECTILE_DEC 0x100
|
||||
#define IMM_OPCODE_DEC 0x200
|
||||
#define IMM_LEVEL_DEC 0x400
|
||||
#define IMM_SCHOOL_DEC 0x800
|
||||
#define IMM_SECTYPE_DEC 0x1000
|
||||
#define IMM_RESOURCE_DEC 0x2000
|
||||
|
||||
// FIXME: Dice roll should be probably done just once, e.g. when equipping
|
||||
// the item, not each time the fx are applied
|
||||
// <avenger> the dice values are actually level limits, except in 3 hp modifier functions
|
||||
// the damage function is an instant (the other 2 functions might be tricky with random values)
|
||||
//#define DICE_ROLL(max_val) ((fx->DiceThrown && fx->DiceSides) ? ((max_val >=0) ? (MIN( core->Roll( fx->DiceThrown, fx->DiceSides, 0 ), max_val )) : (MAX( core->Roll( fx->DiceThrown, fx->DiceSides, 0 ), max_val ))) : max_val)
|
||||
|
||||
//sometimes damage doesn't comply with the calculated value
|
||||
#define DICE_ROLL(adjustment) (core->Roll( fx->DiceThrown, fx->DiceSides, adjustment) )
|
||||
|
||||
// You will need to get GameTime somehow to use this macro
|
||||
#define PrepareDuration(fx) fx->Duration = (fx->Duration*AI_UPDATE_TIME + GameTime)
|
||||
|
||||
//return the caster object
|
||||
#define GetCasterObject() (core->GetGame()->GetActorByGlobalID(fx->CasterID))
|
||||
|
||||
// often used stat modifications, usually Parameter2 types 0, 1 and 2
|
||||
//these macros should work differently in permanent mode (modify base too)
|
||||
#define STAT_GET(stat) (target->Modified[ stat ])
|
||||
#define STAT_ADD(stat, mod) target->SetStat( stat, STAT_GET( stat ) + ( mod ), 0 )
|
||||
#define STAT_SUB(stat, mod) target->SetStat( stat, STAT_GET( stat ) - ( mod ), 0 )
|
||||
#define STAT_BIT_OR(stat, mod) target->SetStat( stat, STAT_GET( stat ) | ( mod ), 0 )
|
||||
#define STAT_SET(stat, mod) target->SetStat( stat, ( mod ), 0 )
|
||||
#define STAT_SET_PCF(stat, mod) target->SetStat( stat, ( mod ), 1 )
|
||||
#define STAT_BIT_OR_PCF(stat, mod) target->SetStat( stat, STAT_GET( stat ) | ( mod ), 1 )
|
||||
#define STAT_MUL(stat, mod) target->SetStat( stat, STAT_GET(stat) * ( mod ) / 100, 0 )
|
||||
//if an effect sticks around
|
||||
#define STATE_CURE( mod ) target->Modified[ IE_STATE_ID ] &= ~(ieDword) ( mod )
|
||||
#define STATE_SET( mod ) target->Modified[ IE_STATE_ID ] |= (ieDword) ( mod )
|
||||
#define EXTSTATE_SET( mod ) target->Modified[ IE_EXTSTATE_ID ] |= (ieDword) ( mod )
|
||||
#define STATE_GET( mod ) (target->Modified[ IE_STATE_ID ] & (ieDword) ( mod ) )
|
||||
#define EXTSTATE_GET( mod ) (target->Modified[ IE_EXTSTATE_ID ] & (ieDword) ( mod ) )
|
||||
#define STAT_MOD( stat ) target->NewStat(stat, fx->Parameter1, fx->Parameter2)
|
||||
#define STAT_MOD_VAR( stat, mod ) target->NewStat(stat, ( mod ) , fx->Parameter2 )
|
||||
#define BASE_GET(stat) (target->BaseStats[ stat ])
|
||||
#define BASE_SET(stat, mod) target->SetBase( stat, ( mod ) )
|
||||
#define BASE_ADD(stat, mod) target->SetBase( stat, BASE_GET(stat)+ ( mod ) )
|
||||
#define BASE_SUB(stat, mod) target->SetBase( stat, BASE_GET(stat)- ( mod ) )
|
||||
#define BASE_MUL(stat, mod) target->SetBase( stat, BASE_GET(stat)* ( mod ) / 100 )
|
||||
#define BASE_MOD(stat) target->NewBase( stat, fx->Parameter1, fx->Parameter2)
|
||||
#define BASE_MOD_VAR(stat, mod) target->NewBase( stat, (mod), fx->Parameter2 )
|
||||
//if an effect doesn't stick (and has permanent until cured effect) then
|
||||
//it has to modify the base stat (which is saved)
|
||||
//also use this one if the effect starts a cure effect automatically
|
||||
#define BASE_STATE_SET( mod ) target->SetBaseBit( IE_STATE_ID, ( mod ), true )
|
||||
#define BASE_STATE_CURE( mod ) target->SetBaseBit( IE_STATE_ID, ( mod ), false )
|
||||
|
||||
/** Prototype of a function implementing a particular Effect opcode */
|
||||
typedef int (* EffectFunction)(Scriptable*, Actor*, Effect*);
|
||||
|
||||
|
||||
/** Cached Effect -> opcode mapping */
|
||||
struct EffectRef {
|
||||
const char* Name;
|
||||
int opcode;
|
||||
};
|
||||
|
||||
/** Links Effect name to a function implementing the effect */
|
||||
struct EffectDesc {
|
||||
const char* Name;
|
||||
EffectFunction Function;
|
||||
int Flags;
|
||||
int opcode;
|
||||
};
|
||||
|
||||
enum EffectFlags {
|
||||
EFFECT_NORMAL = 0,
|
||||
EFFECT_DICED = 1,
|
||||
EFFECT_NO_LEVEL_CHECK = 2,
|
||||
EFFECT_NO_ACTOR = 4
|
||||
};
|
||||
|
||||
/** Initializes table of available spell Effects used by all the queues. */
|
||||
/** The available effects should already be registered by the effect plugins */
|
||||
bool Init_EffectQueue();
|
||||
|
||||
/** Registers opcodes implemented by an effect plugin */
|
||||
void EffectQueue_RegisterOpcodes(int count, const EffectDesc *opcodes);
|
||||
|
||||
/** release effect list when Interface is destroyed */
|
||||
void EffectQueue_ReleaseMemory();
|
||||
|
||||
/** Check if opcode is for an effect that takes a color slot as parameter. */
|
||||
bool IsColorslotEffect(int opcode);
|
||||
|
||||
/**
|
||||
* @class EffectQueue
|
||||
* Class holding and processing spell Effects on a single Actor
|
||||
*/
|
||||
|
||||
class GEM_EXPORT EffectQueue {
|
||||
private:
|
||||
/** List of Effects applied on the Actor */
|
||||
std::list< Effect* > effects;
|
||||
/** Actor which is target of the Effects */
|
||||
Scriptable* Owner;
|
||||
|
||||
public:
|
||||
EffectQueue();
|
||||
virtual ~EffectQueue();
|
||||
|
||||
/** Sets Actor which is affected by these effects */
|
||||
void SetOwner(Scriptable* act) { Owner = act; }
|
||||
/** Returns Actor affected by these effects */
|
||||
Scriptable* GetOwner() const { return Owner; }
|
||||
|
||||
/** adds an effect to the queue, it could also insert it if flagged so
|
||||
* fx should be freed by the caller
|
||||
*/
|
||||
void AddEffect(Effect* fx, bool insert=false);
|
||||
/** Adds an Effect to the queue, subject to level and other checks.
|
||||
* Returns FX_ABORT is unsuccessful. fx is just a reference, AddEffect()
|
||||
* will malloc its own copy */
|
||||
int AddEffect(Effect* fx, Scriptable* self, Actor* pretarget, const Point &dest) const;
|
||||
/** Removes first Effect matching fx from the queue.
|
||||
* Effects are matched based on their contents */
|
||||
bool RemoveEffect(Effect* fx);
|
||||
|
||||
int AddAllEffects(Actor* target, const Point &dest) const;
|
||||
void ApplyAllEffects(Actor* target) const;
|
||||
/** remove effects marked for removal */
|
||||
void Cleanup();
|
||||
|
||||
/* directly removes effects with specified opcode, use effect_reference when you can */
|
||||
void RemoveAllEffects(ieDword opcode) const;
|
||||
void RemoveAllEffectsWithResource(ieDword opcode, const ieResRef resource) const;
|
||||
|
||||
/* removes any effects (delayed or not) which were using projectile */
|
||||
void RemoveAllEffectsWithProjectile(ieDword projectile) const;
|
||||
|
||||
/* removes equipping effects with specified inventory slot code */
|
||||
void RemoveEquippingEffects(ieDwordSigned slotcode) const;
|
||||
|
||||
/* removes all effects of a given spell */
|
||||
void RemoveAllEffects(const ieResRef Removed) const;
|
||||
void RemoveAllEffects(const ieResRef Removed, ieByte timing) const;
|
||||
/* removes all effects of type */
|
||||
void RemoveAllEffects(EffectRef &effect_reference) const;
|
||||
/* removes expired or to be expired effects */
|
||||
void RemoveExpiredEffects(ieDword futuretime) const;
|
||||
/* removes all effects except timing mode 9 */
|
||||
void RemoveAllNonPermanentEffects() const;
|
||||
void RemoveAllDetrimentalEffects(EffectRef &effect_reference, ieDword current) const;
|
||||
void RemoveAllEffectsWithParam(EffectRef &effect_reference, ieDword param2) const;
|
||||
void RemoveAllEffectsWithResource(EffectRef &effect_reference, const ieResRef resource) const;
|
||||
void RemoveLevelEffects(ieResRef &Removed, ieDword level, ieDword flags, ieDword match) const;
|
||||
|
||||
/* returns true if the timing method supports simplified duration */
|
||||
static bool HasDuration(Effect *fx);
|
||||
/* returns true if the effect should be saved */
|
||||
static bool Persistent(Effect* fx);
|
||||
/* returns next saved effect, increases index */
|
||||
std::list< Effect* >::const_iterator GetFirstEffect() const
|
||||
{
|
||||
return effects.begin();
|
||||
}
|
||||
const Effect *GetNextSavedEffect(std::list< Effect* >::const_iterator &f) const;
|
||||
Effect *GetNextEffect(std::list< Effect* >::const_iterator &f) const;
|
||||
ieDword CountEffects(EffectRef &effect_reference, ieDword param1, ieDword param2, const char *ResRef) const;
|
||||
void ModifyEffectPoint(EffectRef &effect_reference, ieDword x, ieDword y) const;
|
||||
/* returns the number of saved effects */
|
||||
ieDword GetSavedEffectsCount() const;
|
||||
size_t GetEffectsCount() const { return effects.size(); }
|
||||
/* this method hacks the offhand weapon color effects */
|
||||
static void HackColorEffects(Actor *Owner, Effect *fx);
|
||||
static Effect *CreateEffect(EffectRef &effect_reference, ieDword param1, ieDword param2, ieWord timing);
|
||||
EffectQueue *CopySelf() const;
|
||||
static Effect *CreateEffectCopy(Effect *oldfx, EffectRef &effect_reference, ieDword param1, ieDword param2);
|
||||
static Effect *CreateUnsummonEffect(Effect *fx);
|
||||
//locating opcodes
|
||||
Effect *HasEffect(EffectRef &effect_reference) const;
|
||||
Effect *HasEffectWithParam(EffectRef &effect_reference, ieDword param2) const;
|
||||
Effect *HasEffectWithParamPair(EffectRef &effect_reference, ieDword param1, ieDword param2) const;
|
||||
Effect *HasEffectWithResource(EffectRef &effect_reference, const ieResRef resource) const;
|
||||
Effect *HasEffectWithSource(EffectRef &effect_reference, const ieResRef source) const;
|
||||
void DecreaseParam1OfEffect(EffectRef &effect_reference, ieDword amount) const;
|
||||
int SpecificDamageBonus(ieDword damage_type) const;
|
||||
bool HasAnyDispellableEffect() const;
|
||||
//transforming timing modes
|
||||
static void TransformToDelay(ieByte &TimingMode);
|
||||
//getting summarised effects
|
||||
int BonusAgainstCreature(EffectRef &effect_reference, Actor *actor) const;
|
||||
//getting weapon immunity flag
|
||||
bool WeaponImmunity(int enchantment, ieDword weapontype) const;
|
||||
//melee and ranged effects
|
||||
void AddWeaponEffects(EffectQueue *fxqueue, EffectRef &fx_ref) const;
|
||||
// checks if spells of type "types" are disabled (usually by armor)
|
||||
// returns a bitfield of disabled spelltypes
|
||||
// it is no longer used
|
||||
//int DisabledSpellcasting(int types) const;
|
||||
|
||||
// returns -1 if bounced, 0 if resisted, 1 if accepted spell
|
||||
int CheckImmunity(Actor *target) const;
|
||||
// apply this effectqueue on all actors matching ids targeting
|
||||
// from pos, in range (no cone size yet)
|
||||
void AffectAllInRange(Map *map, const Point &pos, int idstype, int idsvalue, unsigned int range, Actor *except);
|
||||
/** Lists contents of the queue on a terminal for debugging */
|
||||
void dump() const;
|
||||
//resolve effect
|
||||
static int ResolveEffect(EffectRef &effect_reference);
|
||||
static bool match_ids(Actor *target, int table, ieDword value);
|
||||
/** returns true if the process should abort applying a stack of effects */
|
||||
int ApplyEffect(Actor* target, Effect* fx, ieDword first_apply, ieDword resistance=1) const;
|
||||
private:
|
||||
/** counts effects of specific opcode, parameters and resource */
|
||||
ieDword CountEffects(ieDword opcode, ieDword param1, ieDword param2, const char *ResRef) const;
|
||||
void ModifyEffectPoint(ieDword opcode, ieDword x, ieDword y) const;
|
||||
//use the effect reference style calls from outside
|
||||
static Effect *CreateEffect(ieDword opcode, ieDword param1, ieDword param2, ieWord timing);
|
||||
static Effect *CreateEffectCopy(Effect *oldfx, ieDword opcode, ieDword param1, ieDword param2);
|
||||
void RemoveAllDetrimentalEffects(ieDword opcode, ieDword current) const;
|
||||
void RemoveAllEffectsWithParam(ieDword opcode, ieDword param2) const;
|
||||
Effect *HasOpcode(ieDword opcode) const;
|
||||
Effect *HasOpcodeWithParam(ieDword opcode, ieDword param2) const;
|
||||
Effect *HasOpcodeWithParamPair(ieDword opcode, ieDword param1, ieDword param2) const;
|
||||
Effect *HasOpcodeWithResource(ieDword opcode, const ieResRef resource) const;
|
||||
Effect *HasOpcodeWithSource(ieDword opcode, const ieResRef source) const;
|
||||
void DecreaseParam1OfEffect(ieDword opcode, ieDword amount) const;
|
||||
int SpecificDamageBonus(ieDword opcode, ieDword param2) const;
|
||||
int BonusAgainstCreature(ieDword opcode, Actor *actor) const;
|
||||
bool WeaponImmunity(ieDword opcode, int enchantment, ieDword weapontype) const;
|
||||
};
|
||||
|
||||
#endif // ! EFFECTQUEUE_H
|
||||
@@ -1,65 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Factory.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
Factory::Factory(void)
|
||||
{
|
||||
}
|
||||
|
||||
Factory::~Factory(void)
|
||||
{
|
||||
for (unsigned int i = 0; i < fobjects.size(); i++) {
|
||||
delete( fobjects[i] );
|
||||
}
|
||||
}
|
||||
|
||||
void Factory::AddFactoryObject(FactoryObject* fobject)
|
||||
{
|
||||
fobjects.push_back( fobject );
|
||||
}
|
||||
|
||||
int Factory::IsLoaded(const char* ResRef, SClass_ID type) const
|
||||
{
|
||||
for (unsigned int i = 0; i < fobjects.size(); i++) {
|
||||
if (fobjects[i]->SuperClassID == type) {
|
||||
if (strnicmp( fobjects[i]->ResRef, ResRef, 8 ) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
FactoryObject* Factory::GetFactoryObject(int pos) const
|
||||
{
|
||||
return fobjects[pos];
|
||||
}
|
||||
|
||||
void Factory::FreeObjects(void)
|
||||
{
|
||||
for (unsigned int i = 0; i < fobjects.size(); i++) {
|
||||
delete( fobjects[i] );
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FACTORY_H
|
||||
#define FACTORY_H
|
||||
|
||||
#include "exports.h"
|
||||
#include "globals.h"
|
||||
|
||||
#include "AnimationFactory.h"
|
||||
#include "FactoryObject.h"
|
||||
|
||||
class GEM_EXPORT Factory {
|
||||
private:
|
||||
std::vector< FactoryObject*> fobjects;
|
||||
public:
|
||||
Factory(void);
|
||||
~Factory(void);
|
||||
void AddFactoryObject(FactoryObject* fobject);
|
||||
int IsLoaded(const char* ResRef, SClass_ID type) const;
|
||||
FactoryObject* GetFactoryObject(int pos) const;
|
||||
void FreeObjects(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,33 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "FactoryObject.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
FactoryObject::FactoryObject(const char* name, SClass_ID SuperClassID)
|
||||
{
|
||||
strnlwrcpy( ResRef, name, 8 );
|
||||
this->SuperClassID = SuperClassID;
|
||||
}
|
||||
|
||||
FactoryObject::~FactoryObject(void)
|
||||
{
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FACTORYOBJECT_H
|
||||
#define FACTORYOBJECT_H
|
||||
|
||||
#include "exports.h"
|
||||
#include "globals.h"
|
||||
|
||||
class GEM_EXPORT FactoryObject {
|
||||
public:
|
||||
SClass_ID SuperClassID;
|
||||
ieResRef ResRef;
|
||||
FactoryObject(const char* ResRef, SClass_ID SuperClassID);
|
||||
virtual ~FactoryObject(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,87 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "FileCache.h"
|
||||
|
||||
#include "Compressor.h"
|
||||
#include "Interface.h"
|
||||
#include "PluginMgr.h"
|
||||
#include "System/FileStream.h"
|
||||
#include "System/VFS.h"
|
||||
|
||||
DataStream* CacheCompressedStream(DataStream *stream, const char* filename, int length, bool overwrite)
|
||||
{
|
||||
if (!core->IsAvailable(PLUGIN_COMPRESSION_ZLIB)) {
|
||||
print( "No Compression Manager Available.\nCannot Load Compressed File.\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char fname[_MAX_PATH];
|
||||
ExtractFileFromPath(fname, filename);
|
||||
char path[_MAX_PATH];
|
||||
PathJoin(path, core->CachePath, fname, NULL);
|
||||
|
||||
if (overwrite || !file_exists(path)) {
|
||||
FileStream out;
|
||||
if (!out.Create(path)) {
|
||||
printMessage("FileCache", "Cannot write %s.\n", RED, path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PluginHolder<Compressor> comp(PLUGIN_COMPRESSION_ZLIB);
|
||||
if (comp->Decompress(&out, stream, length) != GEM_OK)
|
||||
return NULL;
|
||||
} else {
|
||||
stream->Seek(length, GEM_CURRENT_POS);
|
||||
}
|
||||
return FileStream::OpenFile(path);
|
||||
}
|
||||
|
||||
DataStream* CacheFile(const char* path)
|
||||
{
|
||||
if (!core->GameOnCD)
|
||||
return FileStream::OpenFile(path);
|
||||
|
||||
char filename[_MAX_PATH];
|
||||
char cachedfile[_MAX_PATH];
|
||||
ExtractFileFromPath(filename, path);
|
||||
PathJoin(cachedfile, core->CachePath, filename, NULL);
|
||||
|
||||
if (!file_exists(cachedfile)) { // File was not found in cache
|
||||
FileStream* src = FileStream::OpenFile(path);
|
||||
FileStream* dest = FileStream::OpenFile(cachedfile);
|
||||
if (!src || !dest) {
|
||||
error("Cache", "CachedFile failed to write to cached file '%s' (from '%s')\n", cachedfile, path);
|
||||
}
|
||||
|
||||
size_t blockSize = 1024 * 1000;
|
||||
char buff[1024 * 1000];
|
||||
do {
|
||||
if (blockSize > src->Remains())
|
||||
blockSize = src->Remains();
|
||||
size_t len = src->Read(buff, blockSize);
|
||||
size_t c = dest->Write(buff, len);
|
||||
if (c != len) {
|
||||
error("Cache", "CacheFile failed to write to cached file '%s' (from '%s')\n", cachedfile, path);
|
||||
}
|
||||
} while (src->Remains());
|
||||
delete src;
|
||||
delete dest;
|
||||
}
|
||||
return FileStream::OpenFile(cachedfile);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef FILECACHE_H
|
||||
#define FILECACHE_H
|
||||
|
||||
#include "System/DataStream.h"
|
||||
|
||||
GEM_EXPORT DataStream* CacheCompressedStream(DataStream *stream, const char* filename, int length = 0, bool overwrite = false);
|
||||
GEM_EXPORT DataStream* CacheFile(const char* path);
|
||||
|
||||
#endif
|
||||
@@ -1,579 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
//This class represents game fonts. Fonts are special .bam files.
|
||||
//Each cycle stands for a letter.
|
||||
|
||||
#include "Font.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "GameData.h"
|
||||
#include "Interface.h"
|
||||
#include "Palette.h"
|
||||
#include "Sprite2D.h"
|
||||
#include "Video.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
unsigned int lastX = 0;
|
||||
|
||||
#define PARAGRAPH_START_X 5;
|
||||
|
||||
static const Color black = {0, 0, 0, 0};
|
||||
|
||||
inline size_t mystrlen(const char* string)
|
||||
{
|
||||
if (!string) {
|
||||
return ( size_t ) 0;
|
||||
}
|
||||
const char* tmp = string;
|
||||
size_t count = 0;
|
||||
while (*tmp != 0) {
|
||||
if (( ( unsigned char ) * tmp ) >= 0xf0) {
|
||||
tmp += 3;
|
||||
count += 3;
|
||||
}
|
||||
count++;
|
||||
tmp++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
Font::Font(int w, int h, Palette* pal)
|
||||
{
|
||||
lastX = 0;
|
||||
count = 0;
|
||||
FirstChar = 0;
|
||||
sprBuffer = 0;
|
||||
|
||||
width = w;
|
||||
height = h;
|
||||
tmpPixels = (unsigned char*)malloc(width*height);
|
||||
|
||||
memset( xPos, 0, sizeof( xPos) );
|
||||
memset( yPos, 0, sizeof( yPos) );
|
||||
|
||||
pal->IncRef();
|
||||
palette = pal;
|
||||
maxHeight = h;
|
||||
}
|
||||
|
||||
Font::~Font(void)
|
||||
{
|
||||
Video *video = core->GetVideoDriver();
|
||||
gamedata->FreePalette( palette );
|
||||
video->FreeSprite( sprBuffer );
|
||||
}
|
||||
|
||||
void Font::FinalizeSprite(bool cK, int index)
|
||||
{
|
||||
sprBuffer = core->GetVideoDriver()->CreateSprite8( width, height, 8, tmpPixels, palette ? palette->col : 0, cK, index );
|
||||
tmpPixels = 0;
|
||||
}
|
||||
|
||||
void Font::AddChar(unsigned char* spr, int w, int h, short xPos, short yPos)
|
||||
{
|
||||
if (!spr) {
|
||||
size[count].x = 0;
|
||||
size[count].y = 0;
|
||||
size[count].w = 0;
|
||||
size[count].h = 0;
|
||||
this->xPos[count] = 0;
|
||||
this->yPos[count] = 0;
|
||||
count++;
|
||||
return;
|
||||
}
|
||||
unsigned char * currPtr = tmpPixels + lastX;
|
||||
unsigned char * srcPtr = ( unsigned char * ) spr;
|
||||
for (int y = 0; y < h; y++) {
|
||||
memcpy( currPtr, srcPtr, w );
|
||||
srcPtr += w;
|
||||
currPtr += width;
|
||||
}
|
||||
size[count].x = lastX;
|
||||
size[count].y = 0;
|
||||
size[count].w = w;
|
||||
size[count].h = h;
|
||||
this->xPos[count] = xPos;
|
||||
this->yPos[count] = yPos;
|
||||
count++;
|
||||
lastX += w;
|
||||
}
|
||||
|
||||
void Font::PrintFromLine(int startrow, Region rgn, const unsigned char* string,
|
||||
Palette* hicolor, unsigned char Alignment, Font* initials,
|
||||
Sprite2D* cursor, unsigned int curpos, bool NoColor) const
|
||||
{
|
||||
bool enablecap=false;
|
||||
int capital = 0;
|
||||
if (initials)
|
||||
{
|
||||
capital=1;
|
||||
enablecap=true;
|
||||
}
|
||||
int initials_rows = 0;
|
||||
int initials_x = 0;
|
||||
|
||||
unsigned int psx = PARAGRAPH_START_X;
|
||||
Palette *pal = hicolor;
|
||||
if (!pal) {
|
||||
pal = palette;
|
||||
}
|
||||
if (startrow) enablecap=false;
|
||||
|
||||
if (initials==this) {
|
||||
enablecap=false;
|
||||
}
|
||||
|
||||
sprBuffer->SetPalette( pal );
|
||||
size_t len = strlen( ( char* ) string );
|
||||
char* tmp = ( char* ) malloc( len + 1 );
|
||||
memcpy( tmp, ( char * ) string, len + 1 );
|
||||
SetupString( tmp, rgn.w, NoColor, initials, enablecap );
|
||||
int ystep = 0;
|
||||
if (Alignment & IE_FONT_SINGLE_LINE) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
int height = yPos[( unsigned char ) tmp[i] - 1];
|
||||
if (ystep < height)
|
||||
ystep = height;
|
||||
}
|
||||
} else {
|
||||
ystep = size[1].h;
|
||||
}
|
||||
if (!ystep) ystep = maxHeight;
|
||||
int x = psx, y = ystep;
|
||||
int w = CalcStringWidth( tmp, NoColor );
|
||||
if (Alignment & IE_FONT_ALIGN_CENTER) {
|
||||
x = ( rgn.w - w) / 2;
|
||||
} else if (Alignment & IE_FONT_ALIGN_RIGHT) {
|
||||
x = ( rgn.w - w );
|
||||
}
|
||||
if (Alignment & IE_FONT_ALIGN_MIDDLE) {
|
||||
int h = 0;
|
||||
for (size_t i = 0; i <= len; i++) {
|
||||
if (( tmp[i] == 0 ) || ( tmp[i] == '\n' ))
|
||||
h++;
|
||||
}
|
||||
h = h * ystep;
|
||||
y += ( rgn.h - h ) / 2;
|
||||
} else if (Alignment & IE_FONT_ALIGN_BOTTOM) {
|
||||
int h = 1;
|
||||
for (size_t i = 0; i <= len; i++) {
|
||||
if (( tmp[i] == 0 ) || ( tmp[i] == '\n' ))
|
||||
h++;
|
||||
}
|
||||
h = h * ystep;
|
||||
y += ( rgn.h - h );
|
||||
} else if (Alignment & IE_FONT_ALIGN_TOP) {
|
||||
y += 5;
|
||||
}
|
||||
|
||||
Video* video = core->GetVideoDriver();
|
||||
int row = 0;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (( ( unsigned char ) tmp[i] ) == '[' && !NoColor) {
|
||||
i++;
|
||||
char tag[256];
|
||||
tag[0]=0;
|
||||
|
||||
for (int k = 0; k < 256 && i<len; k++) {
|
||||
if (tmp[i] == ']') {
|
||||
tag[k] = 0;
|
||||
break;
|
||||
}
|
||||
tag[k] = tmp[i++];
|
||||
}
|
||||
|
||||
if (strnicmp( tag, "capital=",8)==0) {
|
||||
sscanf( tag, "capital=%d", &capital);
|
||||
if (capital && (row>=startrow) ) {
|
||||
enablecap=true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (strnicmp( tag, "color=", 6 ) == 0) {
|
||||
unsigned int r,g,b;
|
||||
if (sscanf( tag, "color=%02X%02X%02X", &r, &g, &b ) != 3)
|
||||
continue;
|
||||
const Color c = {(unsigned char) r,(unsigned char)g, (unsigned char)b, 0};
|
||||
Palette* newPal = core->CreatePalette( c, palette->back );
|
||||
sprBuffer->SetPalette( newPal );
|
||||
gamedata->FreePalette( newPal );
|
||||
continue;
|
||||
}
|
||||
if (stricmp( tag, "/color" ) == 0) {
|
||||
sprBuffer->SetPalette( pal );
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stricmp( "p", tag ) == 0) {
|
||||
psx = x;
|
||||
continue;
|
||||
}
|
||||
if (stricmp( "/p", tag ) == 0) {
|
||||
psx = PARAGRAPH_START_X;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (row < startrow) {
|
||||
if (tmp[i] == 0) {
|
||||
row++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (( tmp[i] == 0 ) || ( tmp[i] == '\n' )) {
|
||||
y += ystep;
|
||||
x = psx;
|
||||
int w = CalcStringWidth( &tmp[i + 1], NoColor );
|
||||
if (initials_rows > 0) {
|
||||
initials_rows--;
|
||||
x += initials_x;
|
||||
w += initials_x;
|
||||
}
|
||||
if (Alignment & IE_FONT_ALIGN_CENTER) {
|
||||
x = ( rgn.w - w ) / 2;
|
||||
} else if (Alignment & IE_FONT_ALIGN_RIGHT) {
|
||||
x = ( rgn.w - w );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
unsigned char currChar = ( unsigned char ) tmp[i] - 1;
|
||||
if (initials && capital && enablecap) {
|
||||
x = initials->PrintInitial( x, y, rgn, currChar );
|
||||
initials_x = x;
|
||||
|
||||
//how many more lines to be indented (one was already indented)
|
||||
initials_rows = (initials->maxHeight-1)/maxHeight;
|
||||
enablecap = false;
|
||||
continue;
|
||||
}
|
||||
video->BlitSpriteRegion( sprBuffer, size[currChar],
|
||||
x + rgn.x, y + rgn.y - yPos[currChar], true, &rgn );
|
||||
if (cursor && ( i == curpos )) {
|
||||
video->BlitSprite( cursor, x + rgn.x,
|
||||
y + rgn.y, true, &rgn );
|
||||
}
|
||||
x += size[currChar].w;
|
||||
}
|
||||
if (cursor && ( curpos == len )) {
|
||||
video->BlitSprite( cursor, x + rgn.x,
|
||||
y + rgn.y, true, &rgn );
|
||||
}
|
||||
free( tmp );
|
||||
}
|
||||
|
||||
void Font::Print(Region rgn, const unsigned char* string, Palette* hicolor,
|
||||
unsigned char Alignment, bool anchor, Font* initials,
|
||||
Sprite2D* cursor, unsigned int curpos, bool NoColor) const
|
||||
{
|
||||
Print(rgn, rgn, string, hicolor, Alignment, anchor, initials, cursor, curpos, NoColor);
|
||||
}
|
||||
|
||||
void Font::Print(Region cliprgn, Region rgn, const unsigned char* string,
|
||||
Palette* hicolor, unsigned char Alignment, bool anchor, Font* initials,
|
||||
Sprite2D* cursor, unsigned int curpos, bool NoColor) const
|
||||
{
|
||||
bool enablecap=false;
|
||||
int capital = 0;
|
||||
if (initials)
|
||||
{
|
||||
capital=1;
|
||||
enablecap=true;
|
||||
}
|
||||
|
||||
unsigned int psx = PARAGRAPH_START_X;
|
||||
Palette* pal = hicolor;
|
||||
if (!pal) {
|
||||
pal = palette;
|
||||
}
|
||||
if (initials==this) {
|
||||
initials = NULL;
|
||||
}
|
||||
|
||||
sprBuffer->SetPalette( pal );
|
||||
size_t len = strlen( ( char* ) string );
|
||||
char* tmp = ( char* ) malloc( len + 1 );
|
||||
memcpy( tmp, ( char * ) string, len + 1 );
|
||||
while (len > 0 && (tmp[len - 1] == '\n' || tmp[len - 1] == '\r')) {
|
||||
// ignore trailing newlines
|
||||
tmp[len - 1] = 0;
|
||||
len--;
|
||||
}
|
||||
|
||||
SetupString( tmp, rgn.w, NoColor, initials, capital );
|
||||
int ystep = 0;
|
||||
if (Alignment & IE_FONT_SINGLE_LINE) {
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (tmp[i] == 0) continue;
|
||||
int height = yPos[( unsigned char ) tmp[i] - 1];
|
||||
if (ystep < height)
|
||||
ystep = height;
|
||||
}
|
||||
} else {
|
||||
ystep = size[1].h;
|
||||
}
|
||||
if (!ystep) ystep = maxHeight;
|
||||
int x = psx, y = ystep;
|
||||
Video* video = core->GetVideoDriver();
|
||||
|
||||
if (Alignment & IE_FONT_ALIGN_CENTER) {
|
||||
int w = CalcStringWidth( tmp, NoColor );
|
||||
x = ( rgn.w - w ) / 2;
|
||||
} else if (Alignment & IE_FONT_ALIGN_RIGHT) {
|
||||
int w = CalcStringWidth( tmp, NoColor );
|
||||
x = ( rgn.w - w );
|
||||
}
|
||||
|
||||
if (Alignment & IE_FONT_ALIGN_MIDDLE) {
|
||||
int h = 0;
|
||||
for (size_t i = 0; i <= len; i++) {
|
||||
if (tmp[i] == 0)
|
||||
h++;
|
||||
}
|
||||
h = h * ystep;
|
||||
y += ( rgn.h - h ) / 2;
|
||||
} else if (Alignment & IE_FONT_ALIGN_BOTTOM) {
|
||||
int h = 1;
|
||||
for (size_t i = 0; i <= len; i++) {
|
||||
if (tmp[i] == 0)
|
||||
h++;
|
||||
}
|
||||
h = h * ystep;
|
||||
y += ( rgn.h - h );
|
||||
} else if (Alignment & IE_FONT_ALIGN_TOP) {
|
||||
y += 5;
|
||||
}
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (( ( unsigned char ) tmp[i] ) == '[' && !NoColor) {
|
||||
i++;
|
||||
char tag[256];
|
||||
tag[0]=0;
|
||||
for (int k = 0; k < 256 && i<len; k++) {
|
||||
if (tmp[i] == ']') {
|
||||
tag[k] = 0;
|
||||
break;
|
||||
}
|
||||
tag[k] = tmp[i++];
|
||||
}
|
||||
|
||||
if (strnicmp( tag, "capital=",8)==0) {
|
||||
sscanf( tag, "capital=%d", &capital);
|
||||
if (capital) {
|
||||
enablecap=true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strnicmp( tag, "color=", 6 ) == 0) {
|
||||
unsigned int r,g,b;
|
||||
if (sscanf( tag, "color=%02X%02X%02X", &r, &g, &b ) != 3)
|
||||
continue;
|
||||
const Color c = {(unsigned char) r,(unsigned char) g,(unsigned char) b, 0};
|
||||
Palette* newPal = core->CreatePalette( c, palette->back );
|
||||
sprBuffer->SetPalette( newPal );
|
||||
gamedata->FreePalette( newPal );
|
||||
continue;
|
||||
}
|
||||
if (stricmp( tag, "/color" ) == 0) {
|
||||
sprBuffer->SetPalette( pal );
|
||||
continue;
|
||||
}
|
||||
if (stricmp( "p", tag ) == 0) {
|
||||
psx = x;
|
||||
continue;
|
||||
}
|
||||
if (stricmp( "/p", tag ) == 0) {
|
||||
psx = PARAGRAPH_START_X;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmp[i] == 0) {
|
||||
y += ystep;
|
||||
x = psx;
|
||||
int w = CalcStringWidth( &tmp[i + 1], NoColor );
|
||||
if (Alignment & IE_FONT_ALIGN_CENTER) {
|
||||
x = ( rgn.w - w ) / 2;
|
||||
} else if (Alignment & IE_FONT_ALIGN_RIGHT) {
|
||||
x = ( rgn.w - w );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
unsigned char currChar = ( unsigned char ) tmp[i] - 1;
|
||||
if (initials && capital) {
|
||||
x = initials->PrintInitial( x, y, rgn, currChar );
|
||||
enablecap=false;
|
||||
continue;
|
||||
}
|
||||
video->BlitSpriteRegion( sprBuffer, size[currChar],
|
||||
x + rgn.x, y + rgn.y - yPos[currChar],
|
||||
anchor, &cliprgn );
|
||||
if (cursor && ( curpos == i ))
|
||||
video->BlitSprite( cursor, x + rgn.x, y + rgn.y, anchor, &cliprgn );
|
||||
x += size[currChar].w;
|
||||
}
|
||||
if (cursor && ( curpos == len )) {
|
||||
video->BlitSprite( cursor, x + rgn.x, y + rgn.y, anchor, &cliprgn );
|
||||
}
|
||||
free( tmp );
|
||||
}
|
||||
|
||||
int Font::PrintInitial(int x, int y, const Region &rgn, unsigned char currChar) const
|
||||
{
|
||||
Video *video = core->GetVideoDriver();
|
||||
video->BlitSpriteRegion( sprBuffer, size[currChar],
|
||||
x + rgn.x, y + rgn.y - yPos[currChar], true, &rgn );
|
||||
x += size[currChar].w;
|
||||
return x;
|
||||
}
|
||||
|
||||
int Font::CalcStringWidth(const char* string, bool NoColor) const
|
||||
{
|
||||
size_t ret = 0, len = strlen( string );
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (( ( unsigned char ) string[i] ) == '[' && !NoColor) {
|
||||
while(i<len && ((unsigned char) string[i]) != ']') {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
ret += size[( unsigned char ) string[i] - 1].w;
|
||||
}
|
||||
return ( int ) ret;
|
||||
}
|
||||
|
||||
void Font::SetupString(char* string, unsigned int width, bool NoColor, Font *initials, bool enablecap) const
|
||||
{
|
||||
size_t len = strlen( string );
|
||||
unsigned int psx = PARAGRAPH_START_X;
|
||||
int lastpos = 0;
|
||||
unsigned int x = psx, wx = 0;
|
||||
bool endword = false;
|
||||
int initials_rows = 0;
|
||||
int initials_x = 0;
|
||||
for (size_t pos = 0; pos < len; pos++) {
|
||||
if (x + wx > width) {
|
||||
// we wrapped, force a new line somewhere
|
||||
if (!endword && ( x == psx ))
|
||||
lastpos = ( int ) pos;
|
||||
else
|
||||
string[lastpos] = 0;
|
||||
x = psx;
|
||||
if (initials_rows > 0) {
|
||||
initials_rows--;
|
||||
x += initials_x;
|
||||
}
|
||||
}
|
||||
if (string[pos] == 0) {
|
||||
continue;
|
||||
}
|
||||
endword = false;
|
||||
if (string[pos] == '\r')
|
||||
string[pos] = ' ';
|
||||
if (string[pos] == '\n') {
|
||||
// force a new line here
|
||||
string[pos] = 0;
|
||||
x = psx;
|
||||
wx = 0;
|
||||
if (initials_rows > 0) {
|
||||
initials_rows--;
|
||||
x += initials_x;
|
||||
}
|
||||
lastpos = ( int ) pos;
|
||||
endword = true;
|
||||
continue;
|
||||
}
|
||||
if (( ( unsigned char ) string[pos] ) == '[' && !NoColor) {
|
||||
pos++;
|
||||
if (pos>=len)
|
||||
break;
|
||||
char tag[256];
|
||||
int k = 0;
|
||||
for (k = 0; k < 256; k++) {
|
||||
if (string[pos] == ']') {
|
||||
tag[k] = 0;
|
||||
break;
|
||||
}
|
||||
tag[k] = string[pos++];
|
||||
}
|
||||
if (strnicmp( tag, "capital=",8)==0) {
|
||||
int capital = 0;
|
||||
sscanf( tag, "capital=%d", &capital);
|
||||
if (capital) {
|
||||
enablecap=true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (stricmp( "p", tag ) == 0) {
|
||||
psx = x;
|
||||
continue;
|
||||
}
|
||||
if (stricmp( "/p", tag ) == 0) {
|
||||
psx = PARAGRAPH_START_X;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (string[pos] && string[pos] != ' ') {
|
||||
string[pos] = ( unsigned char ) (string[pos] - FirstChar);
|
||||
}
|
||||
|
||||
wx += size[( unsigned char ) string[pos] - 1].w;
|
||||
if (initials && enablecap) {
|
||||
wx += initials->size[(unsigned char) string[pos] - 1].w;
|
||||
enablecap=false;
|
||||
initials_x = wx;
|
||||
//how many more lines to be indented (one was already indented)
|
||||
initials_rows = (initials->maxHeight-1)/maxHeight;
|
||||
continue;
|
||||
}
|
||||
if (( string[pos] == ' ' ) || ( string[pos] == '-' )) {
|
||||
x += wx;
|
||||
wx = 0;
|
||||
lastpos = ( int ) pos;
|
||||
endword = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Palette* Font::GetPalette() const
|
||||
{
|
||||
assert(palette);
|
||||
palette->IncRef();
|
||||
return palette;
|
||||
}
|
||||
|
||||
void Font::SetPalette(Palette* pal)
|
||||
{
|
||||
if (palette) palette->Release();
|
||||
pal->IncRef();
|
||||
palette = pal;
|
||||
}
|
||||
|
||||
void Font::SetFirstChar( unsigned char first)
|
||||
{
|
||||
FirstChar = first;
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Font.h
|
||||
* Declares Font, class for manipulating images serving as fonts
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
#ifndef FONT_H
|
||||
#define FONT_H
|
||||
|
||||
#include "globals.h"
|
||||
#include "exports.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Palette;
|
||||
class Sprite2D;
|
||||
|
||||
struct StringList {
|
||||
Sprite2D*** strings;
|
||||
unsigned int* heights;
|
||||
unsigned int* lengths;
|
||||
int StringCount;
|
||||
int starty;
|
||||
int curx;
|
||||
int cury;
|
||||
};
|
||||
|
||||
#define IE_FONT_ALIGN_LEFT 0x00
|
||||
#define IE_FONT_ALIGN_CENTER 0x01
|
||||
#define IE_FONT_ALIGN_RIGHT 0x02
|
||||
#define IE_FONT_ALIGN_BOTTOM 0x04
|
||||
#define IE_FONT_ALIGN_TOP 0x10 //Single-Line and Multi-Line Text
|
||||
#define IE_FONT_ALIGN_MIDDLE 0x20 //Only for single line Text
|
||||
#define IE_FONT_SINGLE_LINE 0x40
|
||||
|
||||
/**
|
||||
* @class Font
|
||||
* Class for using and manipulating images serving as fonts
|
||||
*/
|
||||
|
||||
class GEM_EXPORT Font {
|
||||
private:
|
||||
int count;
|
||||
Palette* palette;
|
||||
Sprite2D* sprBuffer;
|
||||
unsigned char FirstChar;
|
||||
|
||||
short xPos[256];
|
||||
short yPos[256];
|
||||
|
||||
// For the temporary bitmap
|
||||
unsigned char* tmpPixels;
|
||||
unsigned int width, height;
|
||||
public:
|
||||
/** ResRef of the Font image */
|
||||
ieResRef ResRef;
|
||||
int maxHeight;
|
||||
Region size[256];
|
||||
public:
|
||||
Font(int w, int h, Palette* palette);
|
||||
~Font(void);
|
||||
void AddChar(unsigned char* spr, int w, int h, short xPos, short yPos);
|
||||
/** Call this after adding all characters */
|
||||
void FinalizeSprite(bool cK, int index);
|
||||
|
||||
void Print(Region cliprgn, Region rgn, const unsigned char* string,
|
||||
Palette* color, unsigned char Alignment, bool anchor = false,
|
||||
Font* initials = NULL, Sprite2D* cursor = NULL,
|
||||
unsigned int curpos = 0, bool NoColor = false) const;
|
||||
void Print(Region rgn, const unsigned char* string, Palette* color,
|
||||
unsigned char Alignment, bool anchor = false,
|
||||
Font* initials = NULL, Sprite2D* cursor = NULL,
|
||||
unsigned int curpos = 0, bool NoColor = false) const;
|
||||
void PrintFromLine(int startrow, Region rgn, const unsigned char* string,
|
||||
Palette* color, unsigned char Alignment,
|
||||
Font* initials = NULL, Sprite2D* cursor = NULL,
|
||||
unsigned int curpos = 0, bool NoColor = false) const;
|
||||
|
||||
Palette* GetPalette() const;
|
||||
void SetPalette(Palette* pal);
|
||||
/** Returns width of the string rendered in this font in pixels */
|
||||
int CalcStringWidth(const char* string, bool NoColor = false) const;
|
||||
void SetupString(char* string, unsigned int width, bool NoColor = false, Font *initials = NULL, bool enablecap = false) const;
|
||||
/** Sets ASCII code of the first character in the font.
|
||||
* (it allows remapping numeric fonts from \000 to '0') */
|
||||
void SetFirstChar(unsigned char first);
|
||||
|
||||
private:
|
||||
int PrintInitial(int x, int y, const Region &rgn, unsigned char currChar) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,728 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GUI/Button.h"
|
||||
|
||||
#include "GUI/GameControl.h"
|
||||
#include "GUI/EventMgr.h"
|
||||
#include "GUI/ScrollBar.h"
|
||||
#include "GUI/Window.h"
|
||||
|
||||
#include "defsounds.h"
|
||||
#include "win32def.h"
|
||||
|
||||
#include "GameData.h"
|
||||
#include "Interface.h"
|
||||
#include "Palette.h"
|
||||
#include "Variables.h"
|
||||
#include "Video.h"
|
||||
|
||||
Button::Button()
|
||||
{
|
||||
Unpressed = Pressed = Selected = Disabled = NULL;
|
||||
State = IE_GUI_BUTTON_UNPRESSED;
|
||||
ResetEventHandler( ButtonOnPress );
|
||||
ResetEventHandler( ButtonOnDoublePress );
|
||||
ResetEventHandler( ButtonOnShiftPress );
|
||||
ResetEventHandler( ButtonOnRightPress );
|
||||
ResetEventHandler( ButtonOnDragDrop );
|
||||
ResetEventHandler( ButtonOnDrag );
|
||||
ResetEventHandler( MouseEnterButton );
|
||||
ResetEventHandler( MouseLeaveButton );
|
||||
ResetEventHandler( MouseOverButton );
|
||||
//Text = ( char * ) calloc( 64, sizeof(char) );
|
||||
Text = NULL;
|
||||
hasText = false;
|
||||
font = core->GetButtonFont();
|
||||
normal_palette = NULL;
|
||||
disabled_palette = font->GetPalette()->Copy();
|
||||
for (int i = 0; i < 256; i++) {
|
||||
disabled_palette->col[i].r = ( disabled_palette->col[i].r * 2 ) / 3;
|
||||
disabled_palette->col[i].g = ( disabled_palette->col[i].g * 2 ) / 3;
|
||||
disabled_palette->col[i].b = ( disabled_palette->col[i].b * 2 ) / 3;
|
||||
}
|
||||
Flags = IE_GUI_BUTTON_NORMAL;
|
||||
ToggleState = false;
|
||||
Picture = NULL;
|
||||
Clipping = 1.0;
|
||||
memset(&SourceRGB,0,sizeof(SourceRGB));
|
||||
memset(&DestRGB,0,sizeof(DestRGB));
|
||||
memset( borders, 0, sizeof( borders ));
|
||||
starttime = 0;
|
||||
Anchor.null();
|
||||
}
|
||||
Button::~Button()
|
||||
{
|
||||
Video* video = core->GetVideoDriver();
|
||||
video->FreeSprite( Disabled );
|
||||
video->FreeSprite( Selected );
|
||||
video->FreeSprite( Pressed );
|
||||
video->FreeSprite( Unpressed );
|
||||
video->FreeSprite( Picture );
|
||||
ClearPictureList();
|
||||
if (Text) {
|
||||
free( Text );
|
||||
}
|
||||
gamedata->FreePalette( normal_palette);
|
||||
gamedata->FreePalette( disabled_palette);
|
||||
}
|
||||
/** Sets the 'type' Image of the Button to 'img'.
|
||||
'type' may assume the following values:
|
||||
- IE_GUI_BUTTON_UNPRESSED
|
||||
- IE_GUI_BUTTON_PRESSED
|
||||
- IE_GUI_BUTTON_SELECTED
|
||||
- IE_GUI_BUTTON_DISABLED */
|
||||
void Button::SetImage(unsigned char type, Sprite2D* img)
|
||||
{
|
||||
switch (type) {
|
||||
case IE_GUI_BUTTON_UNPRESSED:
|
||||
case IE_GUI_BUTTON_LOCKED:
|
||||
case IE_GUI_BUTTON_LOCKED_PRESSED:
|
||||
core->GetVideoDriver()->FreeSprite( Unpressed );
|
||||
Unpressed = img;
|
||||
break;
|
||||
|
||||
case IE_GUI_BUTTON_SECOND:
|
||||
case IE_GUI_BUTTON_PRESSED:
|
||||
core->GetVideoDriver()->FreeSprite( Pressed );
|
||||
Pressed = img;
|
||||
break;
|
||||
|
||||
case IE_GUI_BUTTON_SELECTED:
|
||||
core->GetVideoDriver()->FreeSprite( Selected );
|
||||
Selected = img;
|
||||
break;
|
||||
|
||||
case IE_GUI_BUTTON_DISABLED:
|
||||
case IE_GUI_BUTTON_THIRD:
|
||||
core->GetVideoDriver()->FreeSprite( Disabled );
|
||||
Disabled = img;
|
||||
break;
|
||||
}
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
/** make SourceRGB go closer to DestRGB */
|
||||
void Button::CloseUpColor()
|
||||
{
|
||||
if (!starttime) return;
|
||||
//using the realtime timer, because i don't want to
|
||||
//handle Game at this point
|
||||
unsigned long newtime;
|
||||
|
||||
Changed = true;
|
||||
newtime = GetTickCount();
|
||||
if (newtime<starttime) {
|
||||
return;
|
||||
}
|
||||
SourceRGB.r = (SourceRGB.r + DestRGB.r) / 2;
|
||||
SourceRGB.g = (SourceRGB.g + DestRGB.g) / 2;
|
||||
SourceRGB.b = (SourceRGB.b + DestRGB.b) / 2;
|
||||
SourceRGB.a = (SourceRGB.a + DestRGB.a) / 2;
|
||||
if (SourceRGB.r == DestRGB.r &&
|
||||
SourceRGB.g == DestRGB.g &&
|
||||
SourceRGB.b == DestRGB.b &&
|
||||
SourceRGB.a == DestRGB.a) {
|
||||
starttime = 0;
|
||||
return;
|
||||
}
|
||||
starttime = newtime + 40;
|
||||
}
|
||||
|
||||
/** Draws the Control on the Output Display */
|
||||
void Button::Draw(unsigned short x, unsigned short y)
|
||||
{
|
||||
if (!Changed && !(Owner->Flags&WF_FLOAT) ) {
|
||||
return;
|
||||
}
|
||||
Changed = false;
|
||||
if (XPos == 65535 || Width == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Video * video = core->GetVideoDriver();
|
||||
|
||||
// Button image
|
||||
if (!( Flags & IE_GUI_BUTTON_NO_IMAGE )) {
|
||||
Sprite2D* Image = NULL;
|
||||
|
||||
switch (State) {
|
||||
case IE_GUI_BUTTON_UNPRESSED:
|
||||
case IE_GUI_BUTTON_LOCKED:
|
||||
case IE_GUI_BUTTON_LOCKED_PRESSED:
|
||||
Image = Unpressed;
|
||||
break;
|
||||
|
||||
case IE_GUI_BUTTON_SECOND:
|
||||
case IE_GUI_BUTTON_PRESSED:
|
||||
Image = Pressed;
|
||||
if (! Image)
|
||||
Image = Unpressed;
|
||||
break;
|
||||
|
||||
case IE_GUI_BUTTON_SELECTED:
|
||||
Image = Selected;
|
||||
if (! Image)
|
||||
Image = Unpressed;
|
||||
break;
|
||||
|
||||
case IE_GUI_BUTTON_DISABLED:
|
||||
case IE_GUI_BUTTON_THIRD:
|
||||
Image = Disabled;
|
||||
if (! Image)
|
||||
Image = Unpressed;
|
||||
break;
|
||||
}
|
||||
if (Image) {
|
||||
// FIXME: maybe it's useless...
|
||||
int xOffs = ( Width / 2 ) - ( Image->Width / 2 );
|
||||
int yOffs = ( Height / 2 ) - ( Image->Height / 2 );
|
||||
|
||||
video->BlitSprite( Image, x + XPos + xOffs, y + YPos + yOffs, true );
|
||||
}
|
||||
}
|
||||
|
||||
if (State == IE_GUI_BUTTON_PRESSED) {
|
||||
//shift the writing/border a bit
|
||||
x+= 2;
|
||||
y+= 2;
|
||||
}
|
||||
|
||||
// Button picture
|
||||
if (Picture && (Flags & IE_GUI_BUTTON_PICTURE) ) {
|
||||
// Picture is drawn centered
|
||||
int xOffs = ( Width / 2 ) - ( Picture->Width / 2 );
|
||||
int yOffs = ( Height / 2 ) - ( Picture->Height / 2 );
|
||||
if (Flags & IE_GUI_BUTTON_HORIZONTAL) {
|
||||
xOffs += x + XPos + Picture->XPos;
|
||||
yOffs += y + YPos + Picture->YPos;
|
||||
video->BlitSprite( Picture, xOffs, yOffs, true );
|
||||
Region r = Region( xOffs, yOffs + (int) (Picture->Height * Clipping), Picture->Width, (int) (Picture->Height*(1.0 - Clipping)) );
|
||||
video->DrawRect( r, SourceRGB, true );
|
||||
// do NOT uncomment this, you can't change Changed or invalidate things from
|
||||
// the middle of Window::DrawWindow() -- it needs moving to somewhere else
|
||||
//CloseUpColor();
|
||||
}
|
||||
else {
|
||||
Region r( x + XPos + xOffs, y + YPos + yOffs, (int)(Picture->Width * Clipping), Picture->Height );
|
||||
video->BlitSprite( Picture, x + XPos + xOffs + Picture->XPos, y + YPos + yOffs + Picture->YPos, true, &r );
|
||||
}
|
||||
}
|
||||
|
||||
// Composite pictures (paperdolls/description icons)
|
||||
if (!PictureList.empty() && (Flags & IE_GUI_BUTTON_PICTURE) ) {
|
||||
std::list<Sprite2D*>::iterator iter = PictureList.begin();
|
||||
int xOffs = 0, yOffs = 0;
|
||||
if (Flags & IE_GUI_BUTTON_CENTER_PICTURES) {
|
||||
// Center the hotspots of all pictures
|
||||
xOffs = Width/2;
|
||||
yOffs = Height/2;
|
||||
} else if (Flags & IE_GUI_BUTTON_BG1_PAPERDOLL) {
|
||||
// Display as-is
|
||||
xOffs = 0;
|
||||
yOffs = 0;
|
||||
} else {
|
||||
// Center the first picture, and align the rest to that
|
||||
xOffs = Width/2 - (*iter)->Width/2 + (*iter)->XPos;
|
||||
yOffs = Height/2 - (*iter)->Height/2 + (*iter)->YPos;
|
||||
}
|
||||
|
||||
for (; iter != PictureList.end(); ++iter) {
|
||||
video->BlitSprite( *iter, x + XPos + xOffs, y + YPos + yOffs, true );
|
||||
}
|
||||
}
|
||||
|
||||
// Button picture
|
||||
if (AnimPicture) {
|
||||
int xOffs = ( Width / 2 ) - ( AnimPicture->Width / 2 );
|
||||
int yOffs = ( Height / 2 ) - ( AnimPicture->Height / 2 );
|
||||
Region r( x + XPos + xOffs, y + YPos + yOffs, (int)(AnimPicture->Width * Clipping), AnimPicture->Height );
|
||||
|
||||
if (Flags & IE_GUI_BUTTON_CENTER_PICTURES) {
|
||||
video->BlitSprite( AnimPicture, x + XPos + xOffs + AnimPicture->XPos, y + YPos + yOffs + AnimPicture->YPos, true, &r );
|
||||
} else {
|
||||
video->BlitSprite( AnimPicture, x + XPos + xOffs, y + YPos + yOffs, true, &r );
|
||||
}
|
||||
}
|
||||
|
||||
// Button label
|
||||
if (hasText && ! ( Flags & IE_GUI_BUTTON_NO_TEXT )) {
|
||||
Palette* ppoi = normal_palette;
|
||||
int align = 0;
|
||||
|
||||
if (State == IE_GUI_BUTTON_DISABLED)
|
||||
ppoi = disabled_palette;
|
||||
// FIXME: hopefully there's no button which sinks when selected
|
||||
// AND has text label
|
||||
//else if (State == IE_GUI_BUTTON_PRESSED || State == IE_GUI_BUTTON_SELECTED) {
|
||||
|
||||
if (Flags & IE_GUI_BUTTON_ALIGN_LEFT)
|
||||
align |= IE_FONT_ALIGN_LEFT;
|
||||
else if (Flags & IE_GUI_BUTTON_ALIGN_RIGHT)
|
||||
align |= IE_FONT_ALIGN_RIGHT;
|
||||
else
|
||||
align |= IE_FONT_ALIGN_CENTER;
|
||||
|
||||
if (Flags & IE_GUI_BUTTON_ALIGN_TOP)
|
||||
align |= IE_FONT_ALIGN_TOP;
|
||||
else if (Flags & IE_GUI_BUTTON_ALIGN_BOTTOM)
|
||||
align |= IE_FONT_ALIGN_BOTTOM;
|
||||
else
|
||||
align |= IE_FONT_ALIGN_MIDDLE;
|
||||
|
||||
if (! (Flags & IE_GUI_BUTTON_MULTILINE)) {
|
||||
align |= IE_FONT_SINGLE_LINE;
|
||||
}
|
||||
font->Print( Region( x + XPos, y + YPos, Width - 2, Height - 2),
|
||||
( unsigned char * ) Text, ppoi,
|
||||
(ieByte) align, true );
|
||||
}
|
||||
|
||||
if (! (Flags&IE_GUI_BUTTON_NO_IMAGE)) {
|
||||
for (int i = 0; i < MAX_NUM_BORDERS; i++) {
|
||||
ButtonBorder *fr = &borders[i];
|
||||
if (! fr->enabled) continue;
|
||||
|
||||
Region r = Region( x + XPos + fr->dx1, y + YPos + fr->dy1, Width - (fr->dx1 + fr->dx2 + 1), Height - (fr->dy1 + fr->dy2 + 1) );
|
||||
video->DrawRect( r, fr->color, fr->filled );
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Sets the Button State */
|
||||
void Button::SetState(unsigned char state)
|
||||
{
|
||||
if (state > IE_GUI_BUTTON_LOCKED_PRESSED) {// If wrong value inserted
|
||||
return;
|
||||
}
|
||||
if (State != state) {
|
||||
Changed = true;
|
||||
State = state;
|
||||
}
|
||||
}
|
||||
void Button::SetBorder(int index, int dx1, int dy1, int dx2, int dy2, const Color &color, bool enabled, bool filled)
|
||||
{
|
||||
if (index >= MAX_NUM_BORDERS)
|
||||
return;
|
||||
|
||||
ButtonBorder *fr = &borders[index];
|
||||
fr->dx1 = dx1;
|
||||
fr->dy1 = dy1;
|
||||
fr->dx2 = dx2;
|
||||
fr->dy2 = dy2;
|
||||
fr->color = color;
|
||||
fr->enabled = enabled;
|
||||
fr->filled = filled;
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
void Button::EnableBorder(int index, bool enabled)
|
||||
{
|
||||
if (index >= MAX_NUM_BORDERS)
|
||||
return;
|
||||
|
||||
if (borders[index].enabled != enabled) {
|
||||
borders[index].enabled = enabled;
|
||||
Changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Button::SetFont(Font* newfont)
|
||||
{
|
||||
font = newfont;
|
||||
}
|
||||
/** Handling The default button (enter) */
|
||||
void Button::OnSpecialKeyPress(unsigned char Key)
|
||||
{
|
||||
if (State != IE_GUI_BUTTON_DISABLED && State != IE_GUI_BUTTON_LOCKED) {
|
||||
if (Key == GEM_RETURN) {
|
||||
if (Flags & IE_GUI_BUTTON_DEFAULT ) {
|
||||
RunEventHandler( ButtonOnPress );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (Key == GEM_ESCAPE) {
|
||||
if (Flags & IE_GUI_BUTTON_CANCEL ) {
|
||||
RunEventHandler( ButtonOnPress );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Control::OnSpecialKeyPress(Key);
|
||||
}
|
||||
|
||||
/** Mouse Button Down */
|
||||
void Button::OnMouseDown(unsigned short x, unsigned short y,
|
||||
unsigned short Button, unsigned short Mod)
|
||||
{
|
||||
if (State == IE_GUI_BUTTON_DISABLED) {
|
||||
Control::OnMouseDown(x,y,Button,Mod);
|
||||
return;
|
||||
}
|
||||
|
||||
if (core->GetDraggedItem () && !ButtonOnDragDrop) {
|
||||
Control::OnMouseDown(x,y,Button,Mod);
|
||||
return;
|
||||
}
|
||||
|
||||
ScrollBar* scrlbr = (ScrollBar*) sb;
|
||||
if (!scrlbr) {
|
||||
Control *ctrl = Owner->GetScrollControl();
|
||||
if (ctrl && (ctrl->ControlType == IE_GUI_SCROLLBAR)) {
|
||||
scrlbr = (ScrollBar *) ctrl;
|
||||
}
|
||||
}
|
||||
|
||||
//Button == 1 means Left Mouse Button
|
||||
switch(Button&GEM_MB_NORMAL) {
|
||||
case GEM_MB_ACTION:
|
||||
// We use absolute screen position here, so drag_start
|
||||
// remains valid even after window/control is moved
|
||||
drag_start.x = Owner->XPos + XPos + x;
|
||||
drag_start.y = Owner->YPos + YPos + y;
|
||||
|
||||
if (State == IE_GUI_BUTTON_LOCKED) {
|
||||
SetState( IE_GUI_BUTTON_LOCKED_PRESSED );
|
||||
return;
|
||||
}
|
||||
SetState( IE_GUI_BUTTON_PRESSED );
|
||||
if (Flags & IE_GUI_BUTTON_SOUND) {
|
||||
core->PlaySound( DS_BUTTON_PRESSED );
|
||||
}
|
||||
if ((Button & GEM_MB_DOUBLECLICK) && ButtonOnDoublePress) {
|
||||
RunEventHandler( ButtonOnDoublePress );
|
||||
printMessage("Button","Doubleclick detected\n",GREEN);
|
||||
}
|
||||
break;
|
||||
case GEM_MB_SCRLUP:
|
||||
if (scrlbr) {
|
||||
scrlbr->ScrollUp();
|
||||
core->RedrawAll();
|
||||
}
|
||||
break;
|
||||
case GEM_MB_SCRLDOWN:
|
||||
if (scrlbr) {
|
||||
scrlbr->ScrollDown();
|
||||
core->RedrawAll();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/** Mouse Button Up */
|
||||
void Button::OnMouseUp(unsigned short x, unsigned short y,
|
||||
unsigned short Button, unsigned short Mod)
|
||||
{
|
||||
if (State == IE_GUI_BUTTON_DISABLED) {
|
||||
return;
|
||||
}
|
||||
|
||||
//what was just dropped?
|
||||
int dragtype = 0;
|
||||
if (core->GetDraggedItem ()) dragtype=1;
|
||||
if (core->GetDraggedPortrait ()) dragtype=2;
|
||||
|
||||
//if something was dropped, but it isn't handled here: it didn't happen
|
||||
if (dragtype && !ButtonOnDragDrop)
|
||||
return;
|
||||
|
||||
switch (State) {
|
||||
case IE_GUI_BUTTON_PRESSED:
|
||||
if (ToggleState) {
|
||||
SetState( IE_GUI_BUTTON_SELECTED );
|
||||
} else {
|
||||
SetState( IE_GUI_BUTTON_UNPRESSED );
|
||||
}
|
||||
break;
|
||||
case IE_GUI_BUTTON_LOCKED_PRESSED:
|
||||
SetState( IE_GUI_BUTTON_LOCKED );
|
||||
break;
|
||||
}
|
||||
|
||||
//in case of dragged/dropped portraits, allow the event to happen even
|
||||
//when we are out of bound
|
||||
if (dragtype!=2) {
|
||||
if (( x >= Width ) || ( y >= Height )) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Flags & IE_GUI_BUTTON_CHECKBOX) {
|
||||
//checkbox
|
||||
ToggleState = !ToggleState;
|
||||
if (ToggleState)
|
||||
SetState( IE_GUI_BUTTON_SELECTED );
|
||||
else
|
||||
SetState( IE_GUI_BUTTON_UNPRESSED );
|
||||
if (VarName[0] != 0) {
|
||||
ieDword tmp = 0;
|
||||
core->GetDictionary()->Lookup( VarName, tmp );
|
||||
tmp ^= Value;
|
||||
core->GetDictionary()->SetAt( VarName, tmp );
|
||||
Owner->RedrawControls( VarName, tmp );
|
||||
}
|
||||
} else {
|
||||
if (Flags & IE_GUI_BUTTON_RADIOBUTTON) {
|
||||
//radio button
|
||||
ToggleState = true;
|
||||
SetState( IE_GUI_BUTTON_SELECTED );
|
||||
}
|
||||
if (VarName[0] != 0) {
|
||||
core->GetDictionary()->SetAt( VarName, Value );
|
||||
Owner->RedrawControls( VarName, Value );
|
||||
}
|
||||
}
|
||||
|
||||
switch (dragtype) {
|
||||
case 1:
|
||||
RunEventHandler( ButtonOnDragDrop );
|
||||
return;
|
||||
case 2:
|
||||
RunEventHandler( ButtonOnDragDropPortrait );
|
||||
return;
|
||||
}
|
||||
|
||||
if ((Button&GEM_MB_NORMAL) == GEM_MB_ACTION) {
|
||||
if ((Mod & GEM_MOD_SHIFT) && ButtonOnShiftPress)
|
||||
RunEventHandler( ButtonOnShiftPress );
|
||||
else
|
||||
RunEventHandler( ButtonOnPress );
|
||||
} else {
|
||||
if (Button == GEM_MB_MENU && ButtonOnRightPress)
|
||||
RunEventHandler( ButtonOnRightPress );
|
||||
}
|
||||
}
|
||||
|
||||
void Button::OnMouseOver(unsigned short x, unsigned short y)
|
||||
{
|
||||
Owner->Cursor = IE_CURSOR_NORMAL;
|
||||
if (State == IE_GUI_BUTTON_DISABLED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( RunEventHandler( MouseOverButton )) {
|
||||
//event handler destructed this object
|
||||
return;
|
||||
}
|
||||
|
||||
//well, no more flags for buttons, and the portraits we can perform action on
|
||||
//are in fact 'draggable multiline pictures' (with image)
|
||||
if ((Flags & IE_GUI_BUTTON_DISABLED_P) == IE_GUI_BUTTON_PORTRAIT) {
|
||||
GameControl *gc = core->GetGameControl();
|
||||
if (gc) {
|
||||
Owner->Cursor = gc->GetDefaultCursor();
|
||||
}
|
||||
}
|
||||
|
||||
if (State == IE_GUI_BUTTON_LOCKED) {
|
||||
return;
|
||||
}
|
||||
|
||||
//portrait buttons are draggable and locked
|
||||
if ((Flags & IE_GUI_BUTTON_DRAGGABLE) &&
|
||||
(State == IE_GUI_BUTTON_PRESSED || State ==IE_GUI_BUTTON_LOCKED_PRESSED)) {
|
||||
// We use absolute screen position here, so drag_start
|
||||
// remains valid even after window/control is moved
|
||||
int dx = Owner->XPos + XPos + x - drag_start.x;
|
||||
int dy = Owner->YPos + YPos + y - drag_start.y;
|
||||
core->GetDictionary()->SetAt( "DragX", dx );
|
||||
core->GetDictionary()->SetAt( "DragY", dy );
|
||||
drag_start.x = (ieWord) (drag_start.x + dx);
|
||||
drag_start.y = (ieWord) (drag_start.y + dy);
|
||||
RunEventHandler( ButtonOnDrag );
|
||||
}
|
||||
}
|
||||
|
||||
void Button::OnMouseEnter(unsigned short /*x*/, unsigned short /*y*/)
|
||||
{
|
||||
if (State == IE_GUI_BUTTON_DISABLED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (MouseEnterButton !=0 && VarName[0] != 0) {
|
||||
core->GetDictionary()->SetAt( VarName, Value );
|
||||
}
|
||||
|
||||
RunEventHandler( MouseEnterButton );
|
||||
}
|
||||
|
||||
void Button::OnMouseLeave(unsigned short /*x*/, unsigned short /*y*/)
|
||||
{
|
||||
if (State == IE_GUI_BUTTON_DISABLED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (MouseLeaveButton !=0 && VarName[0] != 0) {
|
||||
core->GetDictionary()->SetAt( VarName, Value );
|
||||
}
|
||||
|
||||
RunEventHandler( MouseLeaveButton );
|
||||
}
|
||||
|
||||
|
||||
/** Sets the Text of the current control */
|
||||
void Button::SetText(const char* string)
|
||||
{
|
||||
free(Text);
|
||||
Text = NULL;
|
||||
if (string == NULL) {
|
||||
hasText = false;
|
||||
} else if (string[0] == 0) {
|
||||
hasText = false;
|
||||
} else {
|
||||
Text = strndup( string, 255 );
|
||||
if (Flags&IE_GUI_BUTTON_LOWERCASE)
|
||||
strlwr( Text );
|
||||
else if (Flags&IE_GUI_BUTTON_CAPS)
|
||||
strupr( Text );
|
||||
hasText = true;
|
||||
}
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
/** Set Event Handler */
|
||||
bool Button::SetEvent(int eventType, EventHandler handler)
|
||||
{
|
||||
Changed = true;
|
||||
|
||||
switch (eventType) {
|
||||
case IE_GUI_BUTTON_ON_PRESS:
|
||||
ButtonOnPress = handler;
|
||||
break;
|
||||
case IE_GUI_MOUSE_OVER_BUTTON:
|
||||
MouseOverButton = handler;
|
||||
break;
|
||||
case IE_GUI_MOUSE_ENTER_BUTTON:
|
||||
MouseEnterButton = handler;
|
||||
break;
|
||||
case IE_GUI_MOUSE_LEAVE_BUTTON:
|
||||
MouseLeaveButton = handler;
|
||||
break;
|
||||
case IE_GUI_BUTTON_ON_SHIFT_PRESS:
|
||||
ButtonOnShiftPress = handler;
|
||||
break;
|
||||
case IE_GUI_BUTTON_ON_RIGHT_PRESS:
|
||||
ButtonOnRightPress = handler;
|
||||
break;
|
||||
case IE_GUI_BUTTON_ON_DRAG_DROP:
|
||||
ButtonOnDragDrop = handler;
|
||||
break;
|
||||
case IE_GUI_BUTTON_ON_DRAG_DROP_PORTRAIT:
|
||||
ButtonOnDragDropPortrait = handler;
|
||||
break;
|
||||
case IE_GUI_BUTTON_ON_DRAG:
|
||||
ButtonOnDrag = handler;
|
||||
break;
|
||||
case IE_GUI_BUTTON_ON_DOUBLE_PRESS:
|
||||
ButtonOnDoublePress = handler;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Redraws a button from a given radio button group */
|
||||
void Button::RedrawButton(const char* VariableName, unsigned int Sum)
|
||||
{
|
||||
if (strnicmp( VarName, VariableName, MAX_VARIABLE_LENGTH )) {
|
||||
return;
|
||||
}
|
||||
if (State == IE_GUI_BUTTON_DISABLED) {
|
||||
return;
|
||||
}
|
||||
if (Flags & IE_GUI_BUTTON_RADIOBUTTON) {
|
||||
ToggleState = ( Sum == Value );
|
||||
} //radio button, exact value
|
||||
else if (Flags & IE_GUI_BUTTON_CHECKBOX) {
|
||||
ToggleState = !!( Sum & Value );
|
||||
} //checkbox, bitvalue
|
||||
else {
|
||||
return;
|
||||
} //other buttons, nothing to redraw
|
||||
if (ToggleState) {
|
||||
SetState(IE_GUI_BUTTON_SELECTED);
|
||||
} else {
|
||||
SetState(IE_GUI_BUTTON_UNPRESSED);
|
||||
}
|
||||
}
|
||||
/** Sets the Picture */
|
||||
void Button::SetPicture(Sprite2D* newpic)
|
||||
{
|
||||
core->GetVideoDriver()->FreeSprite( Picture );
|
||||
ClearPictureList();
|
||||
Picture = newpic;
|
||||
Changed = true;
|
||||
Flags |= IE_GUI_BUTTON_PICTURE;
|
||||
Owner->Invalidate();
|
||||
}
|
||||
|
||||
/** Clears the list of Pictures */
|
||||
void Button::ClearPictureList()
|
||||
{
|
||||
Video* video = core->GetVideoDriver();
|
||||
for (std::list<Sprite2D*>::iterator iter = PictureList.begin();
|
||||
iter != PictureList.end(); ++iter)
|
||||
video->FreeSprite( *iter );
|
||||
PictureList.clear();
|
||||
Changed = true;
|
||||
Owner->Invalidate();
|
||||
}
|
||||
|
||||
/** Add picture to the end of the list of Pictures */
|
||||
void Button::StackPicture(Sprite2D* Picture)
|
||||
{
|
||||
PictureList.push_back(Picture);
|
||||
Changed = true;
|
||||
Flags |= IE_GUI_BUTTON_PICTURE;
|
||||
Owner->Invalidate();
|
||||
}
|
||||
|
||||
bool Button::IsPixelTransparent(unsigned short x, unsigned short y)
|
||||
{
|
||||
// some buttons have hollow Image frame filled w/ Picture
|
||||
// some buttons in BG2 are text only (if BAM == 'GUICTRL')
|
||||
if (Picture || PictureList.size() || ! Unpressed) return false;
|
||||
return Unpressed->IsPixelTransparent(x, y);
|
||||
}
|
||||
|
||||
// Set palette used for drawing button label in normal state
|
||||
void Button::SetTextColor(const Color &fore, const Color &back)
|
||||
{
|
||||
gamedata->FreePalette( normal_palette );
|
||||
normal_palette = core->CreatePalette( fore, back );
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
void Button::SetHorizontalOverlay(double clip, const Color &src, const Color &dest)
|
||||
{
|
||||
if ((Clipping>clip) || !(Flags&IE_GUI_BUTTON_HORIZONTAL) ) {
|
||||
Flags |= IE_GUI_BUTTON_HORIZONTAL;
|
||||
SourceRGB=src;
|
||||
DestRGB=dest;
|
||||
starttime = GetTickCount();
|
||||
starttime += 40;
|
||||
}
|
||||
Clipping = clip;
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
void Button::SetAnchor(ieWord x, ieWord y)
|
||||
{
|
||||
Anchor = Point(x,y);
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Button.h
|
||||
* Declares Button widget, for displaying buttons in the GUI
|
||||
* @author GemRB Development Team
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BUTTON_H
|
||||
#define BUTTON_H
|
||||
|
||||
#include "GUI/Control.h"
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
#include "Font.h"
|
||||
#include "Sprite2D.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
class Palette;
|
||||
|
||||
// NOTE: keep these synchronized with GUIDefines.py!!!
|
||||
#define IE_GUI_BUTTON_UNPRESSED 0
|
||||
#define IE_GUI_BUTTON_PRESSED 1
|
||||
#define IE_GUI_BUTTON_SELECTED 2
|
||||
#define IE_GUI_BUTTON_DISABLED 3
|
||||
// Like DISABLED, but processes MouseOver events and draws UNPRESSED bitmap
|
||||
#define IE_GUI_BUTTON_LOCKED 4
|
||||
// Draws the disabled bitmap, but otherwise works like unpressed
|
||||
#define IE_GUI_BUTTON_THIRD 5
|
||||
#define IE_GUI_BUTTON_SECOND 6
|
||||
#define IE_GUI_BUTTON_LOCKED_PRESSED 7 //all the same as LOCKED
|
||||
|
||||
#define IE_GUI_BUTTON_NO_IMAGE 0x00000001 // don't draw image (BAM)
|
||||
#define IE_GUI_BUTTON_PICTURE 0x00000002 // draw picture (BMP, MOS, ...)
|
||||
#define IE_GUI_BUTTON_SOUND 0x00000004
|
||||
#define IE_GUI_BUTTON_ALT_SOUND 0x00000008
|
||||
#define IE_GUI_BUTTON_CHECKBOX 0x00000010 // or radio button
|
||||
#define IE_GUI_BUTTON_RADIOBUTTON 0x00000020 // sticks in a state
|
||||
#define IE_GUI_BUTTON_DEFAULT 0x00000040 // enter key triggers it
|
||||
#define IE_GUI_BUTTON_ANIMATED 0x00000080
|
||||
|
||||
//these bits are hardcoded in the .chu structure
|
||||
#define IE_GUI_BUTTON_ALIGN_LEFT 0x00000100
|
||||
#define IE_GUI_BUTTON_ALIGN_RIGHT 0x00000200
|
||||
#define IE_GUI_BUTTON_ALIGN_TOP 0x00000400
|
||||
#define IE_GUI_BUTTON_ALIGN_BOTTOM 0x00000800
|
||||
#define IE_GUI_BUTTON_ANCHOR 0x00001000 //not implemented yet
|
||||
#define IE_GUI_BUTTON_LOWERCASE 0x00002000
|
||||
#define IE_GUI_BUTTON_MULTILINE 0x00004000 // don't set the single line flag
|
||||
//end of hardcoded part
|
||||
#define IE_GUI_BUTTON_DRAGGABLE 0x00008000
|
||||
#define IE_GUI_BUTTON_NO_TEXT 0x00010000 // don't draw button label
|
||||
#define IE_GUI_BUTTON_PLAYRANDOM 0x00020000
|
||||
#define IE_GUI_BUTTON_PLAYONCE 0x00040000
|
||||
|
||||
#define IE_GUI_BUTTON_CENTER_PICTURES 0x00080000 // center button's PictureList
|
||||
#define IE_GUI_BUTTON_BG1_PAPERDOLL 0x00100000 // BG1-style paperdoll PictureList
|
||||
#define IE_GUI_BUTTON_HORIZONTAL 0x00200000 // horizontal clipping of overlay
|
||||
#define IE_GUI_BUTTON_CANCEL 0x00400000 // cancel key triggers it
|
||||
#define IE_GUI_BUTTON_CAPS 0x00800000 // convert text to uppercase
|
||||
|
||||
//composite button flags
|
||||
#define IE_GUI_BUTTON_NORMAL 0x00000004 // default button, doesn't stick
|
||||
#define IE_GUI_BUTTON_PORTRAIT 0x0000c002 // portrait
|
||||
#define IE_GUI_BUTTON_DISABLED_P 0x0000c003 // disabled portrait
|
||||
|
||||
// !!! Keep these synchronized with GUIDefines.py !!!
|
||||
#define IE_GUI_BUTTON_ON_PRESS 0x00000000
|
||||
#define IE_GUI_MOUSE_OVER_BUTTON 0x00000001
|
||||
#define IE_GUI_MOUSE_ENTER_BUTTON 0x00000002
|
||||
#define IE_GUI_MOUSE_LEAVE_BUTTON 0x00000003
|
||||
#define IE_GUI_BUTTON_ON_SHIFT_PRESS 0x00000004
|
||||
#define IE_GUI_BUTTON_ON_RIGHT_PRESS 0x00000005
|
||||
#define IE_GUI_BUTTON_ON_DRAG_DROP 0x00000006
|
||||
#define IE_GUI_BUTTON_ON_DRAG_DROP_PORTRAIT 0x00000007
|
||||
#define IE_GUI_BUTTON_ON_DRAG 0x00000008
|
||||
#define IE_GUI_BUTTON_ON_DOUBLE_PRESS 0x00000009
|
||||
|
||||
/** Border/frame settings for a button */
|
||||
struct ButtonBorder {
|
||||
int dx1;
|
||||
int dy1;
|
||||
int dx2;
|
||||
int dy2;
|
||||
Color color;
|
||||
bool filled;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
#define MAX_NUM_BORDERS 3
|
||||
|
||||
|
||||
/**
|
||||
* @class Button
|
||||
* Button widget, used mainly for buttons, but also for PixMaps (static images)
|
||||
* or for Toggle Buttons.
|
||||
*/
|
||||
|
||||
class GEM_EXPORT Button : public Control {
|
||||
public:
|
||||
Button();
|
||||
~Button();
|
||||
/** Sets the 'type' Image of the Button to 'img'.
|
||||
'type' may assume the following values:
|
||||
- IE_GUI_BUTTON_UNPRESSED
|
||||
- IE_GUI_BUTTON_PRESSED
|
||||
- IE_GUI_BUTTON_SELECTED
|
||||
- IE_GUI_BUTTON_DISABLED */
|
||||
void SetImage(unsigned char type, Sprite2D* img);
|
||||
/** Draws the Control on the Output Display */
|
||||
void Draw(unsigned short x, unsigned short y);
|
||||
/** Sets the Button State */
|
||||
void SetState(unsigned char state);
|
||||
/** Sets the Text of the current control */
|
||||
void SetText(const char* string);
|
||||
/** Sets the Picture */
|
||||
void SetPicture(Sprite2D* Picture);
|
||||
/** Clears the list of Pictures */
|
||||
void ClearPictureList();
|
||||
/** Add picture to the end of the list of Pictures */
|
||||
void StackPicture(Sprite2D* Picture);
|
||||
/** Sets border/frame parameters */
|
||||
void SetBorder(int index, int dx1, int dy1, int dx2, int dy2, const Color &color, bool enabled = false, bool filled = false);
|
||||
/** Sets horizontal overlay, used in portrait hp overlay */
|
||||
void SetHorizontalOverlay(double clip, const Color &src, const Color &dest);
|
||||
/** Sets font used for drawing button label */
|
||||
void SetFont(Font* newfont);
|
||||
/** Enables or disables specified border/frame */
|
||||
void EnableBorder(int index, bool enabled);
|
||||
public: // Public Events
|
||||
/** Mouse Enter */
|
||||
void OnMouseEnter(unsigned short x, unsigned short y);
|
||||
/** Mouse Leave */
|
||||
void OnMouseLeave(unsigned short x, unsigned short y);
|
||||
/** Mouse Over */
|
||||
void OnMouseOver(unsigned short x, unsigned short y);
|
||||
/** Mouse Button Down */
|
||||
void OnMouseDown(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Mouse Button Up */
|
||||
void OnMouseUp(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** A special key has been pressed */
|
||||
void OnSpecialKeyPress(unsigned char Key);
|
||||
/** Set handler for specified event */
|
||||
bool SetEvent(int eventType, EventHandler handler);
|
||||
/** Button Pressed Event Script Function Name */
|
||||
EventHandler ButtonOnPress;
|
||||
EventHandler ButtonOnShiftPress;
|
||||
EventHandler ButtonOnRightPress;
|
||||
EventHandler ButtonOnDoublePress;
|
||||
EventHandler ButtonOnDragDrop;
|
||||
EventHandler ButtonOnDragDropPortrait;
|
||||
EventHandler ButtonOnDrag;
|
||||
EventHandler MouseEnterButton;
|
||||
EventHandler MouseLeaveButton;
|
||||
EventHandler MouseOverButton;
|
||||
/** Refreshes the button from a radio group */
|
||||
void RedrawButton(const char* VariableName, unsigned int Sum);
|
||||
/** Set palette used for drawing button label in normal state. */
|
||||
void SetTextColor(const Color &fore, const Color &back);
|
||||
/** Sets percent (0-1.0) of width for clipping picture */
|
||||
void SetPictureClipping(double clip) { Clipping = clip; }
|
||||
void SetAnchor(ieWord x, ieWord y);
|
||||
private: // Private attributes
|
||||
char* Text;
|
||||
bool hasText;
|
||||
Font* font;
|
||||
bool ToggleState;
|
||||
Palette* normal_palette;
|
||||
Palette* disabled_palette;
|
||||
/** Button Unpressed Image */
|
||||
Sprite2D* Unpressed;
|
||||
/** Button Pressed Image */
|
||||
Sprite2D* Pressed;
|
||||
/** Button Selected Image */
|
||||
Sprite2D* Selected;
|
||||
/** Button Disabled Image */
|
||||
Sprite2D* Disabled;
|
||||
/** Pictures to Apply when the hasPicture flag is set */
|
||||
Sprite2D* Picture;
|
||||
/** If non-empty, list of Pictures to draw when hasPicture is set */
|
||||
std::list<Sprite2D*> PictureList;
|
||||
/** The current state of the Button */
|
||||
unsigned char State;
|
||||
double Clipping;
|
||||
Point drag_start;
|
||||
/** HP Bar over portraits */
|
||||
unsigned long starttime;
|
||||
Color SourceRGB, DestRGB;
|
||||
Point Anchor;
|
||||
/** frame settings */
|
||||
ButtonBorder borders[MAX_NUM_BORDERS];
|
||||
bool IsPixelTransparent (unsigned short x, unsigned short y);
|
||||
void CloseUpColor();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,221 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GUI/Console.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "GameData.h"
|
||||
#include "Interface.h"
|
||||
#include "Palette.h"
|
||||
#include "ScriptEngine.h"
|
||||
#include "Video.h"
|
||||
#include "GUI/EventMgr.h"
|
||||
|
||||
Console::Console(void)
|
||||
{
|
||||
Cursor = NULL;
|
||||
Back = NULL;
|
||||
max = 128;
|
||||
Buffer = ( unsigned char * ) malloc( max );
|
||||
Buffer[0] = 0;
|
||||
for(size_t i=0;i<HISTORY_SIZE;i++) {
|
||||
History[i] = ( unsigned char * ) malloc( max );
|
||||
History[i][0] = 0;
|
||||
}
|
||||
CurPos = 0;
|
||||
HistPos = 0;
|
||||
HistMax = 0;
|
||||
palette = NULL;
|
||||
}
|
||||
|
||||
Console::~Console(void)
|
||||
{
|
||||
free( Buffer );
|
||||
for (size_t i=0;i<HISTORY_SIZE;i++) {
|
||||
free( History[i] );
|
||||
}
|
||||
Video *video = core->GetVideoDriver();
|
||||
|
||||
gamedata->FreePalette( palette );
|
||||
video->FreeSprite( Cursor );
|
||||
}
|
||||
|
||||
/** Draws the Console on the Output Display */
|
||||
void Console::Draw(unsigned short x, unsigned short y)
|
||||
{
|
||||
if (Back) {
|
||||
core->GetVideoDriver()->BlitSprite( Back, 0, y, true );
|
||||
}
|
||||
Color black = {
|
||||
0x00, 0x00, 0x00, 0xff
|
||||
};
|
||||
Region r( x + XPos, y + YPos, Width, Height );
|
||||
core->GetVideoDriver()->DrawRect( r, black );
|
||||
font->Print( r, Buffer, palette,
|
||||
IE_FONT_ALIGN_LEFT | IE_FONT_ALIGN_MIDDLE, true, NULL,
|
||||
Cursor, CurPos, true );
|
||||
}
|
||||
/** Set Font */
|
||||
void Console::SetFont(Font* f)
|
||||
{
|
||||
if (f != NULL) {
|
||||
font = f;
|
||||
}
|
||||
}
|
||||
/** Set Cursor */
|
||||
void Console::SetCursor(Sprite2D* cur)
|
||||
{
|
||||
if (cur != NULL) {
|
||||
Cursor = cur;
|
||||
}
|
||||
}
|
||||
/** Set BackGround */
|
||||
void Console::SetBackGround(Sprite2D* back)
|
||||
{
|
||||
//if 'back' is NULL then no BackGround will be drawn
|
||||
Back = back;
|
||||
}
|
||||
/** Sets the Text of the current control */
|
||||
void Console::SetText(const char* string)
|
||||
{
|
||||
strncpy( ( char * ) Buffer, string, max );
|
||||
}
|
||||
/** Key Press Event */
|
||||
void Console::OnKeyPress(unsigned char Key, unsigned short /*Mod*/)
|
||||
{
|
||||
if (Key >= 0x20) {
|
||||
size_t len = strlen( ( char* ) Buffer );
|
||||
if (len + 1 < max) {
|
||||
for (size_t i = len; i > CurPos; i--) {
|
||||
Buffer[i] = Buffer[i - 1];
|
||||
}
|
||||
Buffer[CurPos++] = Key;
|
||||
Buffer[len + 1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Special Key Press */
|
||||
void Console::OnSpecialKeyPress(unsigned char Key)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
switch (Key) {
|
||||
case GEM_BACKSP:
|
||||
if (CurPos != 0) {
|
||||
size_t len = strlen( ( const char * ) Buffer );
|
||||
for (size_t i = CurPos; i < len; i++) {
|
||||
Buffer[i - 1] = Buffer[i];
|
||||
}
|
||||
Buffer[len - 1] = 0;
|
||||
CurPos--;
|
||||
}
|
||||
break;
|
||||
case GEM_HOME:
|
||||
CurPos = 0;
|
||||
break;
|
||||
case GEM_END:
|
||||
CurPos = (unsigned short) strlen( (const char * ) Buffer);
|
||||
break;
|
||||
case GEM_UP:
|
||||
HistoryBack();
|
||||
break;
|
||||
case GEM_DOWN:
|
||||
HistoryForward();
|
||||
break;
|
||||
case GEM_LEFT:
|
||||
if (CurPos > 0)
|
||||
CurPos--;
|
||||
break;
|
||||
case GEM_RIGHT:
|
||||
len = strlen( ( const char * ) Buffer );
|
||||
if (CurPos < len) {
|
||||
CurPos++;
|
||||
}
|
||||
break;
|
||||
case GEM_DELETE:
|
||||
len = strlen( ( const char * ) Buffer );
|
||||
if (CurPos < len) {
|
||||
for (size_t i = CurPos; i < len; i++) {
|
||||
Buffer[i] = Buffer[i + 1];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GEM_RETURN:
|
||||
core->GetGUIScriptEngine()->ExecString( ( char* ) Buffer );
|
||||
HistoryAdd(false);
|
||||
Buffer[0] = 0;
|
||||
CurPos = 0;
|
||||
HistPos = 0;
|
||||
Changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//ctrl-up
|
||||
void Console::HistoryBack()
|
||||
{
|
||||
HistoryAdd(false);
|
||||
if (HistPos < HistMax-1 && Buffer[0]) {
|
||||
HistPos++;
|
||||
}
|
||||
memcpy(Buffer, History[HistPos], max);
|
||||
CurPos = (unsigned short) strlen ((const char *) Buffer);
|
||||
}
|
||||
|
||||
//ctrl-down
|
||||
void Console::HistoryForward()
|
||||
{
|
||||
HistoryAdd(false);
|
||||
if (HistPos == 0) {
|
||||
Buffer[0]=0;
|
||||
CurPos=0;
|
||||
return;
|
||||
}
|
||||
HistPos--;
|
||||
memcpy(Buffer, History[HistPos], max);
|
||||
CurPos = (unsigned short) strlen ((const char *) Buffer);
|
||||
}
|
||||
|
||||
void Console::HistoryAdd(bool force)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!force && !Buffer[0])
|
||||
return;
|
||||
for (i=0;i<HistMax;i++) {
|
||||
if (!strnicmp((const char *) History[i],(const char *) Buffer,max) )
|
||||
return;
|
||||
}
|
||||
if (History[0][0]) {
|
||||
for (i=HISTORY_SIZE-1; i>0; i--) {
|
||||
memcpy(History[i], History[i-1], max);
|
||||
}
|
||||
}
|
||||
memcpy(History[0], Buffer, max);
|
||||
if (HistMax<HISTORY_SIZE) {
|
||||
HistMax++;
|
||||
}
|
||||
}
|
||||
|
||||
bool Console::SetEvent(int /*eventType*/, EventHandler /*handler*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Console.h
|
||||
* Declares Console widget, input field for direct poking into GemRB innards.
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
#ifndef CONSOLE_H
|
||||
#define CONSOLE_H
|
||||
|
||||
#include "GUI/Control.h"
|
||||
#include "GUI/TextArea.h"
|
||||
|
||||
class Palette;
|
||||
|
||||
/**
|
||||
* @class Console
|
||||
* Widget displaying debugging console, input field for direct poking
|
||||
* into GemRB innards.
|
||||
* The console accepts and executes python statements and has already
|
||||
* GemRB python module loaded, so almost any command
|
||||
* from GUIScripts can be used.
|
||||
*/
|
||||
|
||||
/** the number of remembered lines in the cheat console*/
|
||||
#define HISTORY_SIZE 5
|
||||
|
||||
class Console : public Control {
|
||||
public:
|
||||
Console(void);
|
||||
~Console(void);
|
||||
/** Draws the Console on the Output Display */
|
||||
void Draw(unsigned short x, unsigned short y);
|
||||
/** Set Font */
|
||||
void SetFont(Font* f);
|
||||
/** Set Cursor */
|
||||
void SetCursor(Sprite2D* cur);
|
||||
/** Set BackGround */
|
||||
void SetBackGround(Sprite2D* back);
|
||||
/** Sets the Text of the current control */
|
||||
void SetText(const char* string);
|
||||
private:
|
||||
/** Text Editing Cursor Sprite */
|
||||
Sprite2D* Cursor;
|
||||
/** Text Font */
|
||||
Font* font;
|
||||
/** Background */
|
||||
Sprite2D* Back;
|
||||
/** Max Edit Text Length */
|
||||
unsigned short max;
|
||||
/** Text Buffer */
|
||||
unsigned char* Buffer;
|
||||
/** History Buffer */
|
||||
unsigned char* History[HISTORY_SIZE];
|
||||
/** Cursor Position */
|
||||
unsigned short CurPos;
|
||||
/** History Position and size */
|
||||
unsigned short HistPos, HistMax;
|
||||
/** Color Palette */
|
||||
Palette* palette;
|
||||
|
||||
public: //Events
|
||||
/** Key Press Event */
|
||||
void OnKeyPress(unsigned char Key, unsigned short Mod);
|
||||
/** Special Key Press */
|
||||
void OnSpecialKeyPress(unsigned char Key);
|
||||
bool SetEvent(int eventType, EventHandler handler);
|
||||
private:
|
||||
void HistoryBack();
|
||||
void HistoryForward();
|
||||
void HistoryAdd(bool force);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,245 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GUI/Control.h"
|
||||
|
||||
#include "GUI/EventMgr.h"
|
||||
#include "GUI/Window.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "ControlAnimation.h"
|
||||
#include "Interface.h"
|
||||
#include "ScriptEngine.h"
|
||||
#include "Video.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include "Variables.h"
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
Control::Control()
|
||||
{
|
||||
hasFocus = false;
|
||||
Changed = true;
|
||||
InHandler = false;
|
||||
VarName[0] = 0;
|
||||
Value = 0;
|
||||
Flags = 0;
|
||||
Tooltip = NULL;
|
||||
Owner = NULL;
|
||||
XPos = 0;
|
||||
YPos = 0;
|
||||
|
||||
sb = NULL;
|
||||
animation = NULL;
|
||||
AnimPicture = NULL;
|
||||
ControlType = IE_GUI_INVALID;
|
||||
}
|
||||
|
||||
Control::~Control()
|
||||
{
|
||||
if (InHandler) {
|
||||
printMessage("Control","Destroying control inside event handler, crash may occur!\n", LIGHT_RED);
|
||||
}
|
||||
core->DisplayTooltip( 0, 0, NULL );
|
||||
free (Tooltip);
|
||||
|
||||
delete animation;
|
||||
|
||||
core->GetVideoDriver()->FreeSprite(AnimPicture);
|
||||
}
|
||||
|
||||
/** Sets the Tooltip text of the current control */
|
||||
int Control::SetTooltip(const char* string)
|
||||
{
|
||||
free(Tooltip);
|
||||
|
||||
if ((string == NULL) || (string[0] == 0)) {
|
||||
Tooltip = NULL;
|
||||
} else {
|
||||
Tooltip = strdup (string);
|
||||
}
|
||||
Changed = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Sets the tooltip to be displayed on the screen now */
|
||||
void Control::DisplayTooltip()
|
||||
{
|
||||
if (Tooltip)
|
||||
core->DisplayTooltip( Owner->XPos + XPos + Width / 2, Owner->YPos + YPos + Height / 2, this );
|
||||
else
|
||||
core->DisplayTooltip( 0, 0, NULL );
|
||||
}
|
||||
|
||||
void Control::ResetEventHandler(EventHandler handler)
|
||||
{
|
||||
handler = NULL;
|
||||
}
|
||||
|
||||
void Control::SetText(const char* /*string*/)
|
||||
{
|
||||
}
|
||||
|
||||
int Control::RunEventHandler(EventHandler handler)
|
||||
{
|
||||
if (InHandler) {
|
||||
printMessage("Control","Nested event handlers are not supported!\n", YELLOW);
|
||||
return -1;
|
||||
}
|
||||
if (handler) {
|
||||
Window *wnd = Owner;
|
||||
if (!wnd) {
|
||||
return -1;
|
||||
}
|
||||
unsigned short WID = wnd->WindowID;
|
||||
unsigned short ID = (unsigned short) ControlID;
|
||||
InHandler = true;
|
||||
handler->call();
|
||||
if (!core->IsValidWindow(WID,wnd) ) {
|
||||
printMessage ("Control","Owner window destructed!\n", LIGHT_RED);
|
||||
return -1;
|
||||
}
|
||||
if (!wnd->IsValidControl(ID,this) ) {
|
||||
printMessage ("Control","Control destructed!\n", LIGHT_RED);
|
||||
return -1;
|
||||
}
|
||||
InHandler = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Key Press Event */
|
||||
void Control::OnKeyPress(unsigned char /*Key*/, unsigned short /*Mod*/)
|
||||
{
|
||||
//print("OnKeyPress: CtrlID = 0x%08X, Key = %c (0x%02hX)\n", (unsigned int) ControlID, Key, Key);
|
||||
}
|
||||
|
||||
/** Key Release Event */
|
||||
void Control::OnKeyRelease(unsigned char /*Key*/, unsigned short /*Mod*/)
|
||||
{
|
||||
//print( "OnKeyRelease: CtrlID = 0x%08X, Key = %c (0x%02hX)\n", (unsigned int) ControlID, Key, Key );
|
||||
}
|
||||
|
||||
/** Mouse Enter Event */
|
||||
void Control::OnMouseEnter(unsigned short /*x*/, unsigned short /*y*/)
|
||||
{
|
||||
// print("OnMouseEnter: CtrlID = 0x%08X, x = %hd, y = %hd\n", (unsigned int) ControlID, x, y);
|
||||
}
|
||||
|
||||
/** Mouse Leave Event */
|
||||
void Control::OnMouseLeave(unsigned short /*x*/, unsigned short /*y*/)
|
||||
{
|
||||
// print("OnMouseLeave: CtrlID = 0x%08X, x = %hd, y = %hd\n", (unsigned int) ControlID, x, y);
|
||||
}
|
||||
|
||||
/** Mouse Over Event */
|
||||
void Control::OnMouseOver(unsigned short /*x*/, unsigned short /*y*/)
|
||||
{
|
||||
//print("OnMouseOver: CtrlID = 0x%08X, x = %hd, y = %hd\n", (unsigned int) ControlID, x, y);
|
||||
}
|
||||
|
||||
/** Mouse Button Down */
|
||||
void Control::OnMouseDown(unsigned short x, unsigned short y,
|
||||
unsigned short Button, unsigned short Mod)
|
||||
{
|
||||
if (Button == GEM_MB_SCRLUP || Button == GEM_MB_SCRLDOWN) {
|
||||
Control *ctrl = Owner->GetScrollControl();
|
||||
if (ctrl && (ctrl!=this)) {
|
||||
ctrl->OnMouseDown(x,y,Button,Mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Mouse Button Up */
|
||||
void Control::OnMouseUp(unsigned short /*x*/, unsigned short /*y*/,
|
||||
unsigned short /*Button*/, unsigned short /*Mod*/)
|
||||
{
|
||||
//print("OnMouseUp: CtrlID = 0x%08X, x = %hd, y = %hd, Button = %d, Mos = %hd\n", (unsigned int) ControlID, x, y, Button, Mod);
|
||||
}
|
||||
|
||||
/** Special Key Press */
|
||||
void Control::OnSpecialKeyPress(unsigned char Key)
|
||||
{
|
||||
if (Key == GEM_UP || Key == GEM_DOWN) {
|
||||
Control *ctrl = Owner->GetScrollControl();
|
||||
if (ctrl && (ctrl!=this)) {
|
||||
ctrl->OnSpecialKeyPress(Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the Display Flags */
|
||||
int Control::SetFlags(int arg_flags, int opcode)
|
||||
{
|
||||
if ((arg_flags >>24) != ControlType)
|
||||
return -2;
|
||||
switch (opcode) {
|
||||
case BM_SET:
|
||||
Flags = arg_flags; //set
|
||||
break;
|
||||
case BM_AND:
|
||||
Flags &= arg_flags;
|
||||
break;
|
||||
case BM_OR:
|
||||
Flags |= arg_flags; //turn on
|
||||
break;
|
||||
case BM_XOR:
|
||||
Flags ^= arg_flags;
|
||||
break;
|
||||
case BM_NAND:
|
||||
Flags &= ~arg_flags;//turn off
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
Changed = true;
|
||||
Owner->Invalidate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Control::SetAnimPicture(Sprite2D* newpic)
|
||||
{
|
||||
core->GetVideoDriver()->FreeSprite(AnimPicture);
|
||||
AnimPicture = newpic;
|
||||
//apparently this is needed too, so the artifacts are not visible
|
||||
if (Owner->Visible==WINDOW_VISIBLE) {
|
||||
Changed = true;
|
||||
Owner->InvalidateForControl(this);
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the Scroll Bar Pointer. If 'ptr' is NULL no Scroll Bar will be linked
|
||||
to this Control. */
|
||||
int Control::SetScrollBar(Control* ptr)
|
||||
{
|
||||
if (ptr && (ptr->ControlType!=IE_GUI_SCROLLBAR)) {
|
||||
ptr = NULL;
|
||||
printMessage("Control","Attached control is not a ScrollBar!\n",YELLOW);
|
||||
return -1;
|
||||
}
|
||||
sb = ptr;
|
||||
Changed = true;
|
||||
if (ptr) return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Control.h
|
||||
* Declares Control, root class for all widgets except of windows
|
||||
*/
|
||||
|
||||
#ifndef CONTROL_H
|
||||
#define CONTROL_H
|
||||
|
||||
#define IE_GUI_BUTTON 0
|
||||
#define IE_GUI_PROGRESSBAR 1 //gemrb extension
|
||||
#define IE_GUI_SLIDER 2
|
||||
#define IE_GUI_EDIT 3
|
||||
#define IE_GUI_TEXTAREA 5
|
||||
#define IE_GUI_LABEL 6
|
||||
#define IE_GUI_SCROLLBAR 7
|
||||
#define IE_GUI_WORLDMAP 8 // gemrb extension
|
||||
#define IE_GUI_MAP 9 // gemrb extension
|
||||
#define IE_GUI_GAMECONTROL 128
|
||||
#define IE_GUI_INVALID 255
|
||||
|
||||
#define IE_GUI_CONTROL_FOCUSED 0x80
|
||||
|
||||
//this is in the control ID
|
||||
#define IGNORE_CONTROL 0x10000000
|
||||
|
||||
#include "RGBAColor.h"
|
||||
#include "exports.h"
|
||||
#include "ie_types.h"
|
||||
#include "win32def.h"
|
||||
|
||||
#include "Callback.h"
|
||||
|
||||
class ControlAnimation;
|
||||
class Sprite2D;
|
||||
class Window;
|
||||
|
||||
/**
|
||||
* @class Control
|
||||
* Basic Control Object, also called widget or GUI element. Parent class for Labels, Buttons, etc.
|
||||
* Every GUI element except of a Window is a descendant of this class.
|
||||
*/
|
||||
|
||||
class GEM_EXPORT Control {
|
||||
public:
|
||||
Control();
|
||||
virtual ~Control();
|
||||
/** Draws the Control on the Output Display */
|
||||
virtual void Draw(unsigned short x, unsigned short y) = 0;
|
||||
/** Sets the Text of the current control */
|
||||
virtual void SetText(const char* string);
|
||||
/** Sets the Tooltip text of the current control */
|
||||
int SetTooltip(const char* string);
|
||||
/** Displays the tooltip text, Worldmap handles this differently */
|
||||
virtual void DisplayTooltip();
|
||||
/** Variable length is 40-1 (zero terminator) */
|
||||
char VarName[MAX_VARIABLE_LENGTH];
|
||||
/** the value of the control to add to the variable */
|
||||
ieDword Value;
|
||||
/** various flags based on the control type */
|
||||
ieDword Flags;
|
||||
ControlAnimation* animation;
|
||||
Sprite2D* AnimPicture;
|
||||
|
||||
public: // Public attributes
|
||||
/** Defines the Control ID Number used for GUI Scripting */
|
||||
ieDword ControlID;
|
||||
/** X position of control relative to containing window */
|
||||
ieWord XPos;
|
||||
/** Y position of control relative to containing window */
|
||||
ieWord YPos;
|
||||
/** Width of control */
|
||||
ieWord Width;
|
||||
/** Height of control */
|
||||
ieWord Height;
|
||||
/** Type of control */
|
||||
ieByte ControlType;
|
||||
/** Text to display as a tooltip when the mouse cursor hovers
|
||||
* for some time over the control */
|
||||
char* Tooltip;
|
||||
/** Focused Control */
|
||||
bool hasFocus;
|
||||
/** If true, control is redrawn during next call to gc->DrawWindows.
|
||||
* Then it's set back to false. */
|
||||
bool Changed;
|
||||
/** True if we are currently in an event handler */
|
||||
bool InHandler;
|
||||
/** Owner Window */
|
||||
Window* Owner;
|
||||
/** Attached Scroll Bar Pointer*/
|
||||
Control* sb;
|
||||
public: //Events
|
||||
/** Reset/init event handler */
|
||||
void ResetEventHandler(EventHandler handler);
|
||||
/** Returns the Owner */
|
||||
Window *GetOwner() const { return Owner; }
|
||||
/** Set the Flags */
|
||||
int SetFlags(int arg_flags, int opcode);
|
||||
/** Set handler for specified event. Override in child classes */
|
||||
virtual bool SetEvent(int eventType, EventHandler handler) = 0;
|
||||
/** Run specified handler, it may return error code */
|
||||
int RunEventHandler(EventHandler handler);
|
||||
/** Key Press Event */
|
||||
virtual void OnKeyPress(unsigned char Key, unsigned short Mod);
|
||||
/** Key Release Event */
|
||||
virtual void OnKeyRelease(unsigned char Key, unsigned short Mod);
|
||||
/** Mouse Enter Event */
|
||||
virtual void OnMouseEnter(unsigned short x, unsigned short y);
|
||||
/** Mouse Leave Event */
|
||||
virtual void OnMouseLeave(unsigned short x, unsigned short y);
|
||||
/** Mouse Over Event */
|
||||
virtual void OnMouseOver(unsigned short x, unsigned short y);
|
||||
/** Mouse Button Down */
|
||||
virtual void OnMouseDown(unsigned short x, unsigned short y,
|
||||
unsigned short Button, unsigned short Mod);
|
||||
/** Mouse Button Up */
|
||||
virtual void OnMouseUp(unsigned short x, unsigned short y,
|
||||
unsigned short Button, unsigned short Mod);
|
||||
/** Special Key Press */
|
||||
virtual void OnSpecialKeyPress(unsigned char Key);
|
||||
virtual bool IsPixelTransparent(unsigned short /*x*/, unsigned short /*y*/) {
|
||||
return false;
|
||||
}
|
||||
/** Sets the animation picture ref */
|
||||
void SetAnimPicture(Sprite2D* Picture);
|
||||
/** Sets the Scroll Bar Pointer */
|
||||
int SetScrollBar(Control* ptr);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,440 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GUI/EventMgr.h"
|
||||
|
||||
#include "GUI/GameControl.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "Interface.h"
|
||||
#include "Video.h"
|
||||
#include "GUI/Window.h"
|
||||
|
||||
EventMgr::EventMgr(void)
|
||||
{
|
||||
last_win_focused = NULL;
|
||||
// Last window focused for mouse events (eg, with a click). Used to determine MouseUp events
|
||||
last_win_mousefocused = NULL;
|
||||
// Last window we were over. Used to determine MouseEnter and MouseLeave events
|
||||
last_win_over = NULL;
|
||||
MButtons = 0;
|
||||
dc_x = 0;
|
||||
dc_y = 0;
|
||||
dc_time = 0;
|
||||
dc_delay = 250;
|
||||
rk_delay = 250;
|
||||
rk_flags = GEM_RK_DISABLE;
|
||||
}
|
||||
|
||||
EventMgr::~EventMgr(void)
|
||||
{
|
||||
}
|
||||
|
||||
void EventMgr::SetOnTop(int Index)
|
||||
{
|
||||
std::vector< int>::iterator t;
|
||||
for (t = topwin.begin(); t != topwin.end(); ++t) {
|
||||
if (( *t ) == Index) {
|
||||
topwin.erase( t );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (topwin.size() != 0) {
|
||||
topwin.insert( topwin.begin(), Index );
|
||||
} else {
|
||||
topwin.push_back( Index );
|
||||
}
|
||||
}
|
||||
|
||||
void EventMgr::SetDefaultFocus(Window *win)
|
||||
{
|
||||
if (!last_win_focused) {
|
||||
last_win_focused = win;
|
||||
last_win_focused->SetFocused(last_win_focused->GetControl(0));
|
||||
}
|
||||
last_win_over = NULL;
|
||||
}
|
||||
|
||||
/** Adds a Window to the Event Manager */
|
||||
void EventMgr::AddWindow(Window* win)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (win == NULL) {
|
||||
return;
|
||||
}
|
||||
bool found = false;
|
||||
for (i = 0; i < windows.size(); i++) {
|
||||
if (windows[i] == win) {
|
||||
goto ok;
|
||||
}
|
||||
if(windows[i]==NULL) {
|
||||
windows[i] = win;
|
||||
ok:
|
||||
SetOnTop( i );
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
windows.push_back( win );
|
||||
if (windows.size() == 1)
|
||||
topwin.push_back( 0 );
|
||||
else
|
||||
SetOnTop( ( int ) windows.size() - 1 );
|
||||
}
|
||||
SetDefaultFocus(win);
|
||||
}
|
||||
/** Frees and Removes all the Windows in the Array */
|
||||
void EventMgr::Clear()
|
||||
{
|
||||
topwin.clear();
|
||||
windows.clear();
|
||||
last_win_focused = NULL;
|
||||
last_win_mousefocused = NULL;
|
||||
last_win_over = NULL;
|
||||
}
|
||||
|
||||
/** Remove a Window from the array */
|
||||
void EventMgr::DelWindow(Window *win)
|
||||
//unsigned short WindowID, const char *WindowPack)
|
||||
{
|
||||
if (last_win_focused == win) {
|
||||
last_win_focused = NULL;
|
||||
}
|
||||
if (last_win_mousefocused == win) {
|
||||
last_win_mousefocused = NULL;
|
||||
}
|
||||
if (last_win_over == win) {
|
||||
last_win_over = NULL;
|
||||
}
|
||||
|
||||
if (windows.size() == 0) {
|
||||
return;
|
||||
}
|
||||
int pos = -1;
|
||||
std::vector< Window*>::iterator m;
|
||||
for (m = windows.begin(); m != windows.end(); ++m) {
|
||||
pos++;
|
||||
if ( (*m) == win) {
|
||||
(*m) = NULL;
|
||||
std::vector< int>::iterator t;
|
||||
for (t = topwin.begin(); t != topwin.end(); ++t) {
|
||||
if ( (*t) == pos) {
|
||||
topwin.erase( t );
|
||||
return;
|
||||
}
|
||||
}
|
||||
printMessage("EventManager","Couldn't find window",YELLOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** BroadCast Mouse Move Event */
|
||||
void EventMgr::MouseMove(unsigned short x, unsigned short y)
|
||||
{
|
||||
if (windows.size() == 0) {
|
||||
return;
|
||||
}
|
||||
if (!last_win_focused) {
|
||||
return;
|
||||
}
|
||||
GameControl *gc = core->GetGameControl();
|
||||
if (gc) {
|
||||
// for scrolling
|
||||
gc->OnGlobalMouseMove(x, y);
|
||||
}
|
||||
std::vector< int>::iterator t;
|
||||
std::vector< Window*>::iterator m;
|
||||
for (t = topwin.begin(); t != topwin.end(); ++t) {
|
||||
m = windows.begin();
|
||||
m += ( *t );
|
||||
Window *win = *m;
|
||||
if (win == NULL)
|
||||
continue;
|
||||
if (!win->Visible)
|
||||
continue;
|
||||
if (( win->XPos <= x ) && ( win->YPos <= y )) {
|
||||
//Maybe we are on the window, let's check
|
||||
if (( win->XPos + win->Width >= x ) &&
|
||||
( win->YPos + win->Height >= y )) {
|
||||
//Yes, we are on the Window
|
||||
//Let's check if we have a Control under the Mouse Pointer
|
||||
Control* ctrl = win->GetControl( x, y, true );
|
||||
//look for the low priority flagged controls (mostly static labels)
|
||||
if (ctrl == NULL) {
|
||||
ctrl = win->GetControl( x, y, false );
|
||||
}
|
||||
if (win != last_win_over || ctrl != win->GetOver()) {
|
||||
// Remove tooltip if mouse moved to different control
|
||||
core->DisplayTooltip( 0, 0, NULL );
|
||||
if (last_win_over) {
|
||||
last_win_over->OnMouseLeave( x, y );
|
||||
}
|
||||
last_win_over = win;
|
||||
win->OnMouseEnter( x, y, ctrl );
|
||||
}
|
||||
if (ctrl != NULL) {
|
||||
win->OnMouseOver( x, y );
|
||||
}
|
||||
RefreshCursor(win->Cursor);
|
||||
return;
|
||||
}
|
||||
}
|
||||
//stop going further
|
||||
if (( *m )->Visible == WINDOW_FRONT)
|
||||
break;
|
||||
}
|
||||
core->DisplayTooltip( 0, 0, NULL );
|
||||
}
|
||||
|
||||
void EventMgr::RefreshCursor(int idx)
|
||||
{
|
||||
Video *video = core->GetVideoDriver();
|
||||
if (idx&IE_CURSOR_GRAY) {
|
||||
video->SetMouseGrayed(true);
|
||||
} else {
|
||||
video->SetMouseGrayed(false);
|
||||
}
|
||||
idx &= IE_CURSOR_MASK;
|
||||
video->SetCursor( core->Cursors[idx], core->Cursors[idx ^ 1] );
|
||||
}
|
||||
|
||||
bool EventMgr::ClickMatch(unsigned short x, unsigned short y, unsigned long thisTime)
|
||||
{
|
||||
if (dc_x+10<x) return false;
|
||||
if (dc_x>x+10) return false;
|
||||
if (dc_y+10<y) return false;
|
||||
if (dc_y>y+10) return false;
|
||||
if (dc_time<thisTime) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** BroadCast Mouse Move Event */
|
||||
void EventMgr::MouseDown(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod)
|
||||
{
|
||||
std::vector< int>::iterator t;
|
||||
std::vector< Window*>::iterator m;
|
||||
Control *ctrl;
|
||||
unsigned long thisTime;
|
||||
|
||||
thisTime = GetTickCount();
|
||||
if (ClickMatch(x, y, thisTime)) {
|
||||
Button |= GEM_MB_DOUBLECLICK;
|
||||
dc_x = 0;
|
||||
dc_y = 0;
|
||||
dc_time = 0;
|
||||
} else {
|
||||
dc_x = x;
|
||||
dc_y = y;
|
||||
dc_time = thisTime+dc_delay;
|
||||
}
|
||||
MButtons |= Button;
|
||||
for (t = topwin.begin(); t != topwin.end(); ++t) {
|
||||
m = windows.begin();
|
||||
m += ( *t );
|
||||
if (( *m ) == NULL)
|
||||
continue;
|
||||
if (!( *m )->Visible)
|
||||
continue;
|
||||
if (( ( *m )->XPos <= x ) && ( ( *m )->YPos <= y )) {
|
||||
//Maybe we are on the window, let's check
|
||||
if (( ( *m )->XPos + ( *m )->Width >= x ) &&
|
||||
( ( *m )->YPos + ( *m )->Height >= y )) {
|
||||
//Yes, we are on the Window
|
||||
//Let's check if we have a Control under the Mouse Pointer
|
||||
ctrl = ( *m )->GetControl( x, y, true );
|
||||
if (!ctrl) {
|
||||
ctrl = ( *m )->GetControl( x, y, false);
|
||||
}
|
||||
last_win_mousefocused = *m;
|
||||
if (ctrl != NULL) {
|
||||
last_win_mousefocused->SetMouseFocused( ctrl );
|
||||
ctrl->OnMouseDown( x - last_win_mousefocused->XPos - ctrl->XPos, y - last_win_mousefocused->YPos - ctrl->YPos, Button, Mod );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (( *m )->Visible == WINDOW_FRONT) //stop looking further
|
||||
break;
|
||||
}
|
||||
|
||||
if ((Button == GEM_MB_SCRLUP || Button == GEM_MB_SCRLDOWN) && last_win_mousefocused) {
|
||||
ctrl = last_win_mousefocused->GetScrollControl();
|
||||
if (ctrl) {
|
||||
ctrl->OnMouseDown( x - last_win_mousefocused->XPos - ctrl->XPos, y - last_win_mousefocused->YPos - ctrl->YPos, Button, Mod );
|
||||
}
|
||||
}
|
||||
|
||||
if (last_win_mousefocused) {
|
||||
last_win_mousefocused->SetMouseFocused(NULL);
|
||||
}
|
||||
}
|
||||
/** BroadCast Mouse Up Event */
|
||||
void EventMgr::MouseUp(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod)
|
||||
{
|
||||
MButtons &= ~Button;
|
||||
if (last_win_mousefocused == NULL) return;
|
||||
Control *last_ctrl_mousefocused = last_win_mousefocused->GetMouseFocus();
|
||||
if (last_ctrl_mousefocused == NULL) return;
|
||||
last_ctrl_mousefocused->OnMouseUp( x - last_win_mousefocused->XPos - last_ctrl_mousefocused->XPos,
|
||||
y - last_win_mousefocused->YPos - last_ctrl_mousefocused->YPos, Button, Mod );
|
||||
}
|
||||
|
||||
/** BroadCast Mouse Idle Event */
|
||||
void EventMgr::MouseIdle(unsigned long /*time*/)
|
||||
{
|
||||
if (last_win_over == NULL) return;
|
||||
Control *ctrl = last_win_over->GetOver();
|
||||
if (ctrl == NULL) return;
|
||||
ctrl->DisplayTooltip();
|
||||
}
|
||||
|
||||
/** BroadCast Key Press Event */
|
||||
void EventMgr::KeyPress(unsigned char Key, unsigned short Mod)
|
||||
{
|
||||
if (last_win_focused == NULL) return;
|
||||
Control *ctrl = last_win_focused->GetFocus();
|
||||
if (ctrl == NULL) return;
|
||||
ctrl->OnKeyPress( Key, Mod );
|
||||
}
|
||||
/** BroadCast Key Release Event */
|
||||
void EventMgr::KeyRelease(unsigned char Key, unsigned short Mod)
|
||||
{
|
||||
if (last_win_focused == NULL) return;
|
||||
Control *ctrl = last_win_focused->GetFocus();
|
||||
if (Key == GEM_GRAB) {
|
||||
core->GetVideoDriver()->ToggleGrabInput();
|
||||
return;
|
||||
}
|
||||
if (ctrl == NULL) return;
|
||||
ctrl->OnKeyRelease( Key, Mod );
|
||||
}
|
||||
|
||||
/** Special Key Press Event */
|
||||
void EventMgr::OnSpecialKeyPress(unsigned char Key)
|
||||
{
|
||||
if (!last_win_focused) {
|
||||
return;
|
||||
}
|
||||
Control *ctrl = NULL;
|
||||
|
||||
// tab shows tooltips
|
||||
if (Key == GEM_TAB) {
|
||||
if (last_win_over != NULL) {
|
||||
Control *ctrl = last_win_over->GetOver();
|
||||
if (ctrl != NULL) {
|
||||
ctrl->DisplayTooltip();
|
||||
}
|
||||
}
|
||||
}
|
||||
//the default control will get only GEM_RETURN
|
||||
else if (Key == GEM_RETURN) {
|
||||
ctrl = last_win_focused->GetDefaultControl(0);
|
||||
}
|
||||
//the default cancel control will get only GEM_ESCAPE
|
||||
else if (Key == GEM_ESCAPE) {
|
||||
ctrl = last_win_focused->GetDefaultControl(1);
|
||||
}
|
||||
|
||||
//if there was no default button set, then the current focus will get it
|
||||
if (!ctrl) {
|
||||
ctrl = last_win_focused->GetFocus();
|
||||
}
|
||||
//if one is under focus, use the default scroll focus
|
||||
if (!ctrl) {
|
||||
if (Key == GEM_UP || Key == GEM_DOWN) {
|
||||
ctrl = last_win_focused->GetScrollControl();
|
||||
}
|
||||
}
|
||||
if (ctrl) {
|
||||
switch (ctrl->ControlType) {
|
||||
//scrollbars will receive only mousewheel events
|
||||
case IE_GUI_SCROLLBAR:
|
||||
if (Key != GEM_UP && Key != GEM_DOWN) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
//buttons will receive only GEM_RETURN
|
||||
case IE_GUI_BUTTON:
|
||||
if (Key != GEM_RETURN && Key!=GEM_ESCAPE) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case IE_GUI_GAMECONTROL:
|
||||
//gamecontrols will receive all special keys
|
||||
break;
|
||||
case IE_GUI_EDIT:
|
||||
case IE_GUI_TEXTAREA:
|
||||
//editboxes and textareas will receive all special keys
|
||||
break;
|
||||
default:
|
||||
//other controls don't receive any
|
||||
return;
|
||||
}
|
||||
ctrl->OnSpecialKeyPress( Key );
|
||||
}
|
||||
}
|
||||
|
||||
void EventMgr::SetFocused(Window *win, Control *ctrl)
|
||||
{
|
||||
last_win_focused = win;
|
||||
last_win_focused->SetFocused(ctrl);
|
||||
//this is to refresh changing mouse cursors should the focus change)
|
||||
int x,y;
|
||||
core->GetVideoDriver()->GetMousePos(x,y);
|
||||
MouseMove((unsigned short) x, (unsigned short) y);
|
||||
}
|
||||
|
||||
void EventMgr::SetDCDelay(unsigned long t)
|
||||
{
|
||||
dc_delay = t;
|
||||
}
|
||||
|
||||
void EventMgr::SetRKDelay(unsigned long t)
|
||||
{
|
||||
rk_delay = t;
|
||||
}
|
||||
|
||||
unsigned long EventMgr::GetRKDelay()
|
||||
{
|
||||
if (rk_flags&GEM_RK_DISABLE) return (unsigned long) ~0;
|
||||
if (rk_flags&GEM_RK_DOUBLESPEED) return rk_delay/2;
|
||||
if (rk_flags&GEM_RK_QUADRUPLESPEED) return rk_delay/4;
|
||||
return rk_delay;
|
||||
}
|
||||
|
||||
unsigned long EventMgr::SetRKFlags(unsigned long arg, unsigned int op)
|
||||
{
|
||||
unsigned long tmp = rk_flags;
|
||||
switch (op) {
|
||||
case BM_SET: tmp = arg; break;
|
||||
case BM_OR: tmp |= arg; break;
|
||||
case BM_NAND: tmp &= ~arg; break;
|
||||
case BM_XOR: tmp ^= arg; break;
|
||||
case BM_AND: tmp &= arg; break;
|
||||
default: tmp = 0; break;
|
||||
}
|
||||
rk_flags=tmp;
|
||||
return rk_flags;
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file EventMgr.h
|
||||
* Declares EventMgr, class distributing events from input devices to GUI windows
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef EVENTMGR_H
|
||||
#define EVENTMGR_H
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Control;
|
||||
class Window;
|
||||
|
||||
#define GEM_LEFT 0x81
|
||||
#define GEM_RIGHT 0x82
|
||||
#define GEM_UP 0x83
|
||||
#define GEM_DOWN 0x84
|
||||
#define GEM_DELETE 0x85
|
||||
#define GEM_RETURN 0x86
|
||||
#define GEM_BACKSP 0x87
|
||||
#define GEM_TAB 0x88
|
||||
#define GEM_ALT 0x89
|
||||
#define GEM_HOME 0x8a
|
||||
#define GEM_END 0x8b
|
||||
#define GEM_ESCAPE 0x8c
|
||||
#define GEM_PGUP 0x8d
|
||||
#define GEM_PGDOWN 0x8e
|
||||
#define GEM_GRAB 0x8f
|
||||
|
||||
|
||||
#define GEM_MOD_SHIFT 1
|
||||
#define GEM_MOD_CTRL 2
|
||||
#define GEM_MOD_ALT 4
|
||||
|
||||
#define GEM_MOUSEOUT 128
|
||||
|
||||
// Mouse buttons
|
||||
#define GEM_MB_ACTION 1
|
||||
#define GEM_MB_MENU 4
|
||||
#define GEM_MB_SCRLUP 8
|
||||
#define GEM_MB_SCRLDOWN 16
|
||||
|
||||
#define GEM_MB_NORMAL 255
|
||||
#define GEM_MB_DOUBLECLICK 256
|
||||
|
||||
#define GEM_RK_DOUBLESPEED 1
|
||||
#define GEM_RK_DISABLE 2
|
||||
#define GEM_RK_QUADRUPLESPEED 4
|
||||
|
||||
/**
|
||||
* @class EventMgr
|
||||
* Class distributing events from input devices to GUI windows.
|
||||
* The events are pumped into instance of this class from a Video driver plugin
|
||||
*/
|
||||
|
||||
class GEM_EXPORT EventMgr {
|
||||
private:
|
||||
std::vector< Window*> windows;
|
||||
std::vector< int> topwin;
|
||||
|
||||
unsigned short dc_x, dc_y;
|
||||
unsigned long dc_time, dc_delay;
|
||||
unsigned long rk_delay, rk_flags;
|
||||
public:
|
||||
EventMgr(void);
|
||||
~EventMgr(void);
|
||||
/** Adds a Window to the Event Manager */
|
||||
void AddWindow(Window* win);
|
||||
/** Removes a Window from the Event chain */
|
||||
//void DelWindow(unsigned short WindowID, const char *WindowPack);
|
||||
void DelWindow(Window* win);
|
||||
/** Frees and Removes all the Windows in the Array */
|
||||
void Clear();
|
||||
/** Call this to change the cursor (moving over windows will change it back) */
|
||||
void RefreshCursor(int idx);
|
||||
/** BroadCast Mouse Move Event */
|
||||
void MouseMove(unsigned short x, unsigned short y);
|
||||
/** BroadCast Mouse Move Event */
|
||||
void MouseDown(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** BroadCast Mouse Move Event */
|
||||
void MouseUp(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** BroadCast Mouse Idle Event */
|
||||
void MouseIdle(unsigned long time);
|
||||
/** BroadCast Key Press Event */
|
||||
void KeyPress(unsigned char Key, unsigned short Mod);
|
||||
/** BroadCast Key Release Event */
|
||||
void KeyRelease(unsigned char Key, unsigned short Mod);
|
||||
/** Special Ket Press Event */
|
||||
void OnSpecialKeyPress(unsigned char Key);
|
||||
/** Sets focus to the control of the window */
|
||||
void SetFocused(Window *win, Control *ctrl);
|
||||
/** Sets mouse event focus to the control of the window */
|
||||
void SetMouseFocused(Window *win, Control *ctrl);
|
||||
/** Sets the maximum accepted doubleclick delay */
|
||||
void SetDCDelay(unsigned long t);
|
||||
void SetRKDelay(unsigned long t);
|
||||
unsigned long GetRKDelay();
|
||||
unsigned long SetRKFlags(unsigned long arg, unsigned int op);
|
||||
|
||||
/** Mask of which Mouse Buttons are pressed */
|
||||
unsigned char MButtons;
|
||||
private:
|
||||
/** Last Window focused */
|
||||
Window* last_win_focused;
|
||||
/** Last Window mouse event focused */
|
||||
Window* last_win_mousefocused;
|
||||
/** Last Window under Mouse Pointer*/
|
||||
Window* last_win_over;
|
||||
/** Sets a Window on the Top of the Window Queue */
|
||||
void SetDefaultFocus(Window *win);
|
||||
void SetOnTop(int Index);
|
||||
bool ClickMatch(unsigned short x, unsigned short y, unsigned long thisTime);
|
||||
};
|
||||
|
||||
#endif // ! EVENTMGR_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,258 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file GameControl.h
|
||||
* Declares GameControl widget which is responsible for displaying areas,
|
||||
* interacting with PCs, NPCs and the rest of the game world.
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
#ifndef GAMECONTROL_H
|
||||
#define GAMECONTROL_H
|
||||
|
||||
#include "GUI/Control.h"
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
#include "Dialog.h"
|
||||
#include "Interface.h"
|
||||
#include "Map.h"
|
||||
|
||||
class GameControl;
|
||||
class Window;
|
||||
class DialogHandler;
|
||||
|
||||
//dialog flags
|
||||
#define DF_IN_DIALOG 1
|
||||
#define DF_TALKCOUNT 2
|
||||
#define DF_UNBREAKABLE 4
|
||||
#define DF_FREEZE_SCRIPTS 8
|
||||
#define DF_INTERACT 16
|
||||
#define DF_IN_CONTAINER 32
|
||||
#define DF_OPENCONTINUEWINDOW 64
|
||||
#define DF_OPENENDWINDOW 128
|
||||
|
||||
//screen flags
|
||||
// !!! Keep these synchronized with GUIDefines.py !!!
|
||||
#define SF_DISABLEMOUSE 1 //no mouse cursor
|
||||
#define SF_CENTERONACTOR 2 //
|
||||
#define SF_ALWAYSCENTER 4
|
||||
#define SF_GUIENABLED 8 //
|
||||
#define SF_LOCKSCROLL 16 //don't scroll
|
||||
#define SF_CUTSCENE 32 //don't push new actions onto the action queue
|
||||
#define SF_TRACKING 64 //draw blue arrows on the edge for creatures
|
||||
|
||||
// target modes and types
|
||||
// !!! Keep these synchronized with GUIDefines.py !!!
|
||||
#define TARGET_MODE_NONE 0
|
||||
#define TARGET_MODE_TALK 1
|
||||
#define TARGET_MODE_ATTACK 2
|
||||
#define TARGET_MODE_CAST 3
|
||||
#define TARGET_MODE_DEFEND 4
|
||||
#define TARGET_MODE_PICK 5
|
||||
|
||||
/*
|
||||
#define TARGET_SELECT 16
|
||||
#define TARGET_NO_DEAD 32
|
||||
#define TARGET_POINT 64
|
||||
#define TARGET_NO_HIDDEN 128
|
||||
#define TARGET_TYPE_NONE 0x000
|
||||
#define TARGET_NO_ALLY 0x100 //0x100
|
||||
#define TARGET_NO_ENEMY 0x200 //0x200
|
||||
#define TARGET_NO_NEUTRAL 0x400
|
||||
#define TARGET_NO_SELF 0x800
|
||||
#define TARGET_TYPE_ALL 0 //(TARGET_TYPE_ALLY | TARGET_TYPE_ENEMY | TARGET_TYPE_NEUTRAL)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @class GameControl
|
||||
* Widget displaying areas, where most of the game 'happens'.
|
||||
* It allows for interacting with PCs, NPCs and the rest of the world.
|
||||
* It's also a very core part of GemRB, as some processes are driven from it.
|
||||
* It's always assigned Control index 0.
|
||||
*/
|
||||
|
||||
class GEM_EXPORT GameControl : public Control {
|
||||
public:
|
||||
GameControl(void);
|
||||
~GameControl(void);
|
||||
public:
|
||||
/** Draws the Control on the Output Display */
|
||||
void Draw(unsigned short x, unsigned short y);
|
||||
/** Sets multiple quicksaves flag*/
|
||||
static void MultipleQuickSaves(int arg);
|
||||
void SetTracker(Actor *actor, ieDword dist);
|
||||
private:
|
||||
ieDword lastActorID;
|
||||
ieDword trackerID;
|
||||
ieDword distance; //tracking distance
|
||||
std::vector< Actor*> highlighted;
|
||||
bool DrawSelectionRect;
|
||||
bool MouseIsDown;
|
||||
bool DoubleClick;
|
||||
Region SelectionRect;
|
||||
short StartX, StartY;
|
||||
//int action;
|
||||
|
||||
// following variables used for touch scroll areas
|
||||
bool touchScrollAreasEnabled; // true, if scroll areas enabled
|
||||
bool touched; // true, if player touched screen (left button down and hold)
|
||||
unsigned int scrollAreasWidth; // scroll areas width
|
||||
|
||||
public:
|
||||
Door* overDoor;
|
||||
Container* overContainer;
|
||||
InfoPoint* overInfoPoint;
|
||||
|
||||
// allow targetting allies, enemies and/or neutrals (bitmask)
|
||||
int target_types;
|
||||
private:
|
||||
// currently selected targetting type, such as talk, attack, cast, ...
|
||||
// private to enforce proper cursor changes
|
||||
int target_mode;
|
||||
unsigned char lastCursor;
|
||||
short moveX, moveY;
|
||||
int numScrollCursor;
|
||||
bool scrolling;
|
||||
unsigned short lastMouseX, lastMouseY;
|
||||
int DebugFlags;
|
||||
Point pfs;
|
||||
PathNode* drawPath;
|
||||
unsigned long AIUpdateCounter;
|
||||
int ScreenFlags;
|
||||
int DialogueFlags;
|
||||
char *DisplayText;
|
||||
unsigned int DisplayTextTime;
|
||||
bool EnableRunning;
|
||||
public: //Events
|
||||
/** Key Press Event */
|
||||
void OnKeyPress(unsigned char Key, unsigned short Mod);
|
||||
/** Key Release Event */
|
||||
void OnKeyRelease(unsigned char Key, unsigned short Mod);
|
||||
/** Mouse Over Event */
|
||||
void OnMouseOver(unsigned short x, unsigned short y);
|
||||
/** Global Mouse Move Event */
|
||||
void OnGlobalMouseMove(unsigned short x, unsigned short y);
|
||||
/** Mouse Button Down */
|
||||
void OnMouseDown(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Mouse Button Up */
|
||||
void OnMouseUp(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Special Key Press */
|
||||
void OnSpecialKeyPress(unsigned char Key);
|
||||
void DisplayTooltip();
|
||||
void UpdateScrolling();
|
||||
void SetTargetMode(int mode);
|
||||
int GetTargetMode() { return target_mode; }
|
||||
void SetScreenFlags(int value, int mode);
|
||||
void SetDialogueFlags(int value, int mode);
|
||||
int GetScreenFlags() { return ScreenFlags; }
|
||||
int GetDialogueFlags() { return DialogueFlags; }
|
||||
/** this function is called from the area when autosave is needed */
|
||||
void AutoSave();
|
||||
void SetDisplayText(char *text, unsigned int time);
|
||||
void SetDisplayText(ieStrRef text, unsigned int time);
|
||||
/* centers viewport to the points specified */
|
||||
void Center(unsigned short x, unsigned short y);
|
||||
private:
|
||||
/** this function is called when the user presses 'q' (or equivalent) */
|
||||
void QuickSave();
|
||||
/** this function safely retrieves an Actor by ID */
|
||||
Actor *GetActorByGlobalID(ieDword ID);
|
||||
void CalculateSelection(const Point &p);
|
||||
void ResizeDel(Window* win, int type);
|
||||
void ResizeAdd(Window* win, int type);
|
||||
void HandleWindowHide(const char *WindowName, const char *WindowPosition);
|
||||
void HandleWindowReveal(const char *WindowName, const char *WindowPosition);
|
||||
void ReadFormations();
|
||||
/** Draws an arrow on the edge of the screen based on the point (points at offscreen actors) */
|
||||
void DrawArrowMarker(const Region &screen, Point p, const Region &viewport);
|
||||
|
||||
private:
|
||||
unsigned char LeftCount, BottomCount, RightCount, TopCount;
|
||||
Actor *user; //the user of item or spell
|
||||
public:
|
||||
DialogHandler *dialoghandler;
|
||||
//the name of the spell to cast
|
||||
ieResRef spellName;
|
||||
//using spell or item
|
||||
int spellOrItem; // -1 = item, otherwise the spell type
|
||||
//the user of spell or item
|
||||
Actor *spellUser;
|
||||
int spellSlot, spellIndex; //or inventorySlot/itemHeader
|
||||
int spellCount; //multiple targeting
|
||||
public:
|
||||
/** Selects one or all PC */
|
||||
void SelectActor(int whom, int type = -1);
|
||||
void SetLastActor(Actor *actor, Actor *prevActor);
|
||||
void SetCutSceneMode(bool active);
|
||||
int HideGUI();
|
||||
int UnhideGUI();
|
||||
void TryToAttack(Actor *source, Actor *target);
|
||||
void TryToCast(Actor *source, const Point &p);
|
||||
void TryToCast(Actor *source, Actor *target);
|
||||
void TryToDefend(Actor *source, Actor *target);
|
||||
void TryToTalk(Actor *source, Actor *target);
|
||||
void TryToPick(Actor *source, Actor *tgt);
|
||||
void TryToPick(Actor *source, Door *tgt);
|
||||
void TryToPick(Actor *source, Container *tgt);
|
||||
void TryToDisarm(Actor *source, InfoPoint *tgt);
|
||||
void PerformActionOn(Actor *actor);
|
||||
void ResetTargetMode();
|
||||
void UpdateTargetMode();
|
||||
|
||||
// returns the default cursor fitting the targeting mode
|
||||
int GetDefaultCursor() const;
|
||||
//containers
|
||||
int GetCursorOverContainer(Container *overContainer) const;
|
||||
void HandleContainer(Container *container, Actor *actor);
|
||||
//doors
|
||||
int GetCursorOverDoor(Door *overDoor) const;
|
||||
void HandleDoor(Door *door, Actor *actor);
|
||||
//infopoints
|
||||
int GetCursorOverInfoPoint(InfoPoint *overInfoPoint) const;
|
||||
bool HandleActiveRegion(InfoPoint *trap, Actor *actor, Point &p);
|
||||
|
||||
Point GetFormationOffset(ieDword formation, ieDword pos);
|
||||
void MoveToPointFormation(Actor *actor, unsigned int pos, Point src, Point p);
|
||||
/** calls MoveToPoint or RunToPoint */
|
||||
void CreateMovement(Actor *actor, const Point &p);
|
||||
/** Displays a string over an object */
|
||||
void DisplayString(Scriptable* target);
|
||||
/** Displays a string on screen */
|
||||
void DisplayString(const Point &p, const char *Text);
|
||||
Actor *GetLastActor();
|
||||
/** changes map to the current PC */
|
||||
void ChangeMap(Actor *pc, bool forced);
|
||||
/** Returns game screenshot, with or without GUI controls */
|
||||
Sprite2D* GetScreenshot( bool show_gui = 0 );
|
||||
/** Returns current area preview for saving a game */
|
||||
Sprite2D* GetPreview();
|
||||
/** Returns PC portrait for a currently running game */
|
||||
Sprite2D* GetPortraitPreview(int pcslot);
|
||||
/** Sets up targeting with spells or items */
|
||||
void SetupItemUse(int slot, int header, Actor *actor, int targettype, int cnt);
|
||||
/** Page is the spell type + spell level info */
|
||||
void SetupCasting(ieResRef spellname, int type, int level, int slot, Actor *actor, int targettype, int cnt);
|
||||
bool SetEvent(int eventType, EventHandler handler);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,153 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GUI/Label.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "GameData.h"
|
||||
#include "Interface.h"
|
||||
#include "Palette.h"
|
||||
#include "Sprite2D.h"
|
||||
#include "Variables.h"
|
||||
#include "Video.h"
|
||||
#include "GUI/Window.h"
|
||||
|
||||
Label::Label(Font* font)
|
||||
{
|
||||
this->font = font;
|
||||
Buffer = NULL;
|
||||
useRGB = false;
|
||||
ResetEventHandler( LabelOnPress );
|
||||
|
||||
Alignment = IE_FONT_ALIGN_CENTER|IE_FONT_ALIGN_MIDDLE;
|
||||
palette = NULL;
|
||||
}
|
||||
Label::~Label()
|
||||
{
|
||||
gamedata->FreePalette( palette );
|
||||
if (Buffer) {
|
||||
free( Buffer );
|
||||
}
|
||||
}
|
||||
/** Draws the Control on the Output Display */
|
||||
void Label::Draw(unsigned short x, unsigned short y)
|
||||
{
|
||||
if (!Changed && !(Owner->Flags&WF_FLOAT)) {
|
||||
return;
|
||||
}
|
||||
Changed = false;
|
||||
if (XPos == 65535) {
|
||||
return;
|
||||
}
|
||||
if (font && Buffer) {
|
||||
font->Print( Region( this->XPos + x, this->YPos + y,
|
||||
this->Width, this->Height ), ( unsigned char * ) Buffer,
|
||||
useRGB?palette:NULL,
|
||||
Alignment | IE_FONT_SINGLE_LINE, true );
|
||||
}
|
||||
|
||||
if (AnimPicture) {
|
||||
int xOffs = ( Width / 2 ) - ( AnimPicture->Width / 2 );
|
||||
int yOffs = ( Height / 2 ) - ( AnimPicture->Height / 2 );
|
||||
Region r( x + XPos + xOffs, y + YPos + yOffs, (int)(AnimPicture->Width), AnimPicture->Height );
|
||||
core->GetVideoDriver()->BlitSprite( AnimPicture, x + XPos + xOffs, y + YPos + yOffs, true, &r );
|
||||
}
|
||||
|
||||
}
|
||||
/** This function sets the actual Label Text */
|
||||
void Label::SetText(const char* string)
|
||||
{
|
||||
if (Buffer )
|
||||
free( Buffer );
|
||||
if (Alignment == IE_FONT_ALIGN_CENTER) {
|
||||
if (core->HasFeature( GF_LOWER_LABEL_TEXT )) {
|
||||
int len = strlen(string);
|
||||
Buffer = (char *) malloc( len+1 );
|
||||
strnlwrcpy( Buffer, string, len );
|
||||
}
|
||||
else {
|
||||
Buffer = strdup( string );
|
||||
}
|
||||
}
|
||||
else {
|
||||
Buffer = strdup( string );
|
||||
}
|
||||
if (!palette) {
|
||||
Color white = {0xff, 0xff, 0xff, 0x00}, black = {0x00, 0x00, 0x00, 0x00};
|
||||
SetColor(white, black);
|
||||
}
|
||||
if (Owner) {
|
||||
Owner->Invalidate();
|
||||
}
|
||||
}
|
||||
/** Sets the Foreground Font Color */
|
||||
void Label::SetColor(Color col, Color bac)
|
||||
{
|
||||
gamedata->FreePalette( palette );
|
||||
palette = core->CreatePalette( col, bac );
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
void Label::SetAlignment(unsigned char Alignment)
|
||||
{
|
||||
this->Alignment = Alignment;
|
||||
if (Alignment == IE_FONT_ALIGN_CENTER) {
|
||||
if (core->HasFeature( GF_LOWER_LABEL_TEXT )) {
|
||||
strlwr( Buffer );
|
||||
}
|
||||
}
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
void Label::OnMouseUp(unsigned short x, unsigned short y,
|
||||
unsigned short /*Button*/, unsigned short /*Mod*/)
|
||||
{
|
||||
//print( "Label::OnMouseUp\n" );
|
||||
if (( x <= Width ) && ( y <= Height )) {
|
||||
if (VarName[0] != 0) {
|
||||
core->GetDictionary()->SetAt( VarName, Value );
|
||||
}
|
||||
if (LabelOnPress) {
|
||||
RunEventHandler( LabelOnPress );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Label::SetEvent(int eventType, EventHandler handler)
|
||||
{
|
||||
Changed = true;
|
||||
|
||||
switch (eventType) {
|
||||
case IE_GUI_LABEL_ON_PRESS:
|
||||
LabelOnPress = handler;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Simply returns the pointer to the text, don't modify it! */
|
||||
const char* Label::QueryText() const
|
||||
{
|
||||
return ( const char * ) Buffer;
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Label.h
|
||||
* Declares Label widget for displaying static texts
|
||||
* @author GemRB Developement Team
|
||||
*/
|
||||
|
||||
#ifndef LABEL_H
|
||||
#define LABEL_H
|
||||
|
||||
#include "GUI/Control.h"
|
||||
|
||||
#include "RGBAColor.h"
|
||||
#include "exports.h"
|
||||
|
||||
#include "Font.h"
|
||||
|
||||
class Palette;
|
||||
|
||||
// !!! Keep these synchronized with GUIDefines.py !!!
|
||||
#define IE_GUI_LABEL_ON_PRESS 0x06000000
|
||||
|
||||
/**
|
||||
* @class Label
|
||||
* Label widget for displaying static texts in the GUI
|
||||
*/
|
||||
|
||||
class GEM_EXPORT Label : public Control {
|
||||
public:
|
||||
Label(Font* font);
|
||||
~Label();
|
||||
/** Draws the Control on the Output Display */
|
||||
void Draw(unsigned short x, unsigned short y);
|
||||
/** This function sets the actual Label Text */
|
||||
void SetText(const char* string);
|
||||
/** Sets the Foreground Font Color */
|
||||
void SetColor(Color col, Color bac);
|
||||
/** Sets the Alignment of Text */
|
||||
void SetAlignment(unsigned char Alignment);
|
||||
/** Simply returns the pointer to the text, don't modify it! */
|
||||
const char* QueryText() const;
|
||||
|
||||
/** Mouse Button Down */
|
||||
void OnMouseUp(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Set handler for specified event */
|
||||
bool SetEvent(int eventType, EventHandler handler);
|
||||
/** Use the RGB Color for the Font */
|
||||
bool useRGB;
|
||||
/** OnPress Scripted Event Function Name */
|
||||
EventHandler LabelOnPress;
|
||||
private: // Private attributes
|
||||
/** Text String Buffer */
|
||||
char* Buffer;
|
||||
/** Font for Text Writing */
|
||||
Font* font;
|
||||
/** Foreground & Background Colors */
|
||||
Palette* palette;
|
||||
|
||||
/** Alignment Variable */
|
||||
unsigned char Alignment;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,540 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GUI/MapControl.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "Game.h"
|
||||
#include "GlobalTimer.h"
|
||||
#include "Interface.h"
|
||||
#include "Map.h"
|
||||
#include "Sprite2D.h"
|
||||
#include "Video.h"
|
||||
#include "GUI/EventMgr.h"
|
||||
#include "GUI/Window.h"
|
||||
#include "Scriptable/Actor.h"
|
||||
|
||||
#define MAP_NO_NOTES 0
|
||||
#define MAP_VIEW_NOTES 1
|
||||
#define MAP_SET_NOTE 2
|
||||
#define MAP_REVEAL 3
|
||||
|
||||
// Ratio between pixel sizes of an Area (Big map) and a Small map
|
||||
|
||||
static int MAP_DIV = 3;
|
||||
static int MAP_MULT = 32;
|
||||
|
||||
typedef enum {black=0, gray, violet, green, orange, red, blue, darkblue, darkgreen} colorcode;
|
||||
|
||||
Color colors[]={
|
||||
{ 0x00, 0x00, 0x00, 0xff }, //black
|
||||
{ 0x60, 0x60, 0x60, 0xff }, //gray
|
||||
{ 0xa0, 0x00, 0xa0, 0xff }, //violet
|
||||
{ 0x00, 0xff, 0x00, 0xff }, //green
|
||||
{ 0xff, 0xff, 0x00, 0xff }, //orange
|
||||
{ 0xff, 0x00, 0x00, 0xff }, //red
|
||||
{ 0x00, 0x00, 0xff, 0xff }, //blue
|
||||
{ 0x00, 0x00, 0x80, 0xff }, //darkblue
|
||||
{ 0x00, 0x80, 0x00, 0xff } //darkgreen
|
||||
};
|
||||
|
||||
#define MAP_TO_SCREENX(x) (XWin + XPos + XCenter - ScrollX + (x))
|
||||
#define MAP_TO_SCREENY(y) (YWin + YPos + YCenter - ScrollY + (y))
|
||||
// Omit [XY]Pos, since these macros are used in OnMouseDown(x, y), and x, y is
|
||||
// already relative to control [XY]Pos there
|
||||
#define SCREEN_TO_MAPX(x) ((x) - XCenter + ScrollX)
|
||||
#define SCREEN_TO_MAPY(y) ((y) - YCenter + ScrollY)
|
||||
|
||||
#define GAME_TO_SCREENX(x) MAP_TO_SCREENX((int)((x) * MAP_DIV / MAP_MULT))
|
||||
#define GAME_TO_SCREENY(y) MAP_TO_SCREENY((int)((y) * MAP_DIV / MAP_MULT))
|
||||
|
||||
#define SCREEN_TO_GAMEX(x) (SCREEN_TO_MAPX(x) * MAP_MULT / MAP_DIV)
|
||||
#define SCREEN_TO_GAMEY(y) (SCREEN_TO_MAPY(y) * MAP_MULT / MAP_DIV)
|
||||
|
||||
MapControl::MapControl(void)
|
||||
{
|
||||
if (core->HasFeature(GF_IWD_MAP_DIMENSIONS) ) {
|
||||
MAP_DIV=4;
|
||||
MAP_MULT=32;
|
||||
} else {
|
||||
MAP_DIV=3;
|
||||
MAP_MULT=32;
|
||||
}
|
||||
|
||||
LinkedLabel = NULL;
|
||||
ScrollX = 0;
|
||||
ScrollY = 0;
|
||||
NotePosX = 0;
|
||||
NotePosY = 0;
|
||||
mouseIsDown = false;
|
||||
mouseIsDragging = false;
|
||||
Changed = true;
|
||||
convertToGame = true;
|
||||
memset(Flag,0,sizeof(Flag) );
|
||||
|
||||
// initialize var and event callback to no-ops
|
||||
VarName[0] = 0;
|
||||
ResetEventHandler( MapControlOnPress );
|
||||
ResetEventHandler( MapControlOnRightPress );
|
||||
ResetEventHandler( MapControlOnDoublePress );
|
||||
|
||||
MyMap = core->GetGame()->GetCurrentArea();
|
||||
if (MyMap->SmallMap) {
|
||||
MapMOS = MyMap->SmallMap;
|
||||
MapMOS->acquire();
|
||||
} else
|
||||
MapMOS = NULL;
|
||||
}
|
||||
|
||||
MapControl::~MapControl(void)
|
||||
{
|
||||
Video *video = core->GetVideoDriver();
|
||||
|
||||
if (MapMOS) {
|
||||
video->FreeSprite(MapMOS);
|
||||
}
|
||||
for(int i=0;i<8;i++) {
|
||||
if (Flag[i]) {
|
||||
video->FreeSprite(Flag[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw fog on the small bitmap
|
||||
void MapControl::DrawFog(unsigned short XWin, unsigned short YWin)
|
||||
{
|
||||
Video *video = core->GetVideoDriver();
|
||||
|
||||
Region old_clip;
|
||||
video->GetClipRect(old_clip);
|
||||
|
||||
Region r( XWin + XPos, YWin + YPos, Width, Height );
|
||||
video->SetClipRect(&r);
|
||||
|
||||
// FIXME: this is ugly, the knowledge of Map and ExploredMask
|
||||
// sizes should be in Map.cpp
|
||||
int w = MyMap->GetWidth() / 2;
|
||||
int h = MyMap->GetHeight() / 2;
|
||||
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
Point p( (short) (MAP_MULT * x), (short) (MAP_MULT * y) );
|
||||
bool visible = MyMap->IsVisible( p, true );
|
||||
if (! visible) {
|
||||
Region rgn = Region ( MAP_TO_SCREENX(MAP_DIV * x), MAP_TO_SCREENY(MAP_DIV * y), MAP_DIV, MAP_DIV );
|
||||
video->DrawRect( rgn, colors[black] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
video->SetClipRect(&old_clip);
|
||||
}
|
||||
|
||||
// To be called after changes in control's or screen geometry
|
||||
void MapControl::Realize()
|
||||
{
|
||||
// FIXME: ugly!! How to get area size in pixels?
|
||||
//Map *map = core->GetGame()->GetCurrentMap();
|
||||
//MapWidth = map->GetWidth();
|
||||
//MapHeight = map->GetHeight();
|
||||
|
||||
if (MapMOS) {
|
||||
MapWidth = (short) MapMOS->Width;
|
||||
MapHeight = (short) MapMOS->Height;
|
||||
} else {
|
||||
MapWidth = 0;
|
||||
MapHeight = 0;
|
||||
}
|
||||
|
||||
// FIXME: ugly hack! What is the actual viewport size?
|
||||
ViewWidth = (short) (core->Width * MAP_DIV / MAP_MULT);
|
||||
ViewHeight = (short) (core->Height * MAP_DIV / MAP_MULT);
|
||||
|
||||
XCenter = (short) (Width - MapWidth ) / 2;
|
||||
YCenter = (short) (Height - MapHeight ) / 2;
|
||||
if (XCenter < 0) XCenter = 0;
|
||||
if (YCenter < 0) YCenter = 0;
|
||||
}
|
||||
|
||||
void MapControl::RedrawMapControl(const char *VariableName, unsigned int Sum)
|
||||
{
|
||||
if (strnicmp( VarName, VariableName, MAX_VARIABLE_LENGTH )) {
|
||||
return;
|
||||
}
|
||||
Value = Sum;
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
/** Draws the Control on the Output Display */
|
||||
void MapControl::Draw(unsigned short XWin, unsigned short YWin)
|
||||
{
|
||||
if (!Width || !Height) {
|
||||
return;
|
||||
}
|
||||
if (Owner->Visible!=WINDOW_VISIBLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Changed) {
|
||||
Realize();
|
||||
Changed = false;
|
||||
}
|
||||
|
||||
// we're going to paint over labels/etc, so they need to repaint!
|
||||
bool seen_this = false;
|
||||
unsigned int i;
|
||||
for (i = 0; i < Owner->GetControlCount(); i++) {
|
||||
Control *ctrl = Owner->GetControl(i);
|
||||
if (!ctrl) continue;
|
||||
|
||||
// we could try working out which controls overlap,
|
||||
// but the later controls are cheap to paint..
|
||||
if (ctrl == this) { seen_this = true; continue; }
|
||||
if (!seen_this) continue;
|
||||
|
||||
ctrl->Changed = true;
|
||||
}
|
||||
|
||||
Video* video = core->GetVideoDriver();
|
||||
Region r( XWin + XPos, YWin + YPos, Width, Height );
|
||||
|
||||
if (MapMOS) {
|
||||
video->BlitSprite( MapMOS, MAP_TO_SCREENX(0), MAP_TO_SCREENY(0), true, &r );
|
||||
}
|
||||
|
||||
if (core->FogOfWar&FOG_DRAWFOG)
|
||||
DrawFog(XWin, YWin);
|
||||
|
||||
Region vp = video->GetViewport();
|
||||
|
||||
vp.x = GAME_TO_SCREENX(vp.x);
|
||||
vp.y = GAME_TO_SCREENY(vp.y);
|
||||
vp.w = ViewWidth;
|
||||
vp.h = ViewHeight;
|
||||
|
||||
if ((vp.x + vp.w) >= MAP_TO_SCREENX( Width ))
|
||||
vp.w = MAP_TO_SCREENX( Width ) - vp.x;
|
||||
if ((vp.y + vp.h) >= MAP_TO_SCREENY( Height ))
|
||||
vp.h = MAP_TO_SCREENY( Height ) - vp.y;
|
||||
|
||||
video->DrawRect( vp, colors[green], false, false );
|
||||
|
||||
// Draw PCs' ellipses
|
||||
Game *game = core->GetGame();
|
||||
i = game->GetPartySize(true);
|
||||
while (i--) {
|
||||
Actor* actor = game->GetPC( i, true );
|
||||
if (MyMap->HasActor(actor) ) {
|
||||
video->DrawEllipse( (short) GAME_TO_SCREENX(actor->Pos.x), (short) GAME_TO_SCREENY(actor->Pos.y), 3, 2, actor->Selected ? colors[green] : colors[darkgreen], false );
|
||||
}
|
||||
}
|
||||
// Draw Map notes, could be turned off in bg2
|
||||
// we use the common control value to handle it, because then we
|
||||
// don't need another interface
|
||||
if (Value!=MAP_NO_NOTES) {
|
||||
i = MyMap -> GetMapNoteCount();
|
||||
while (i--) {
|
||||
MapNote * mn = MyMap -> GetMapNote(i);
|
||||
Sprite2D *anim = Flag[mn->color&7];
|
||||
Point pos = mn->Pos;
|
||||
if (convertToGame) {
|
||||
vp.x = GAME_TO_SCREENX(mn->Pos.x);
|
||||
vp.y = GAME_TO_SCREENY(mn->Pos.y);
|
||||
} else { //pst style
|
||||
vp.x = MAP_TO_SCREENX(mn->Pos.x);
|
||||
vp.y = MAP_TO_SCREENY(mn->Pos.y);
|
||||
pos.x = pos.x * MAP_MULT / MAP_DIV;
|
||||
pos.y = pos.y * MAP_MULT / MAP_DIV;
|
||||
}
|
||||
|
||||
//Skip unexplored map notes
|
||||
bool visible = MyMap->IsVisible( pos, true );
|
||||
if (!visible)
|
||||
continue;
|
||||
|
||||
if (anim) {
|
||||
video->BlitSprite( anim, vp.x - anim->Width/2, vp.y - anim->Height/2, true, &r );
|
||||
} else {
|
||||
video->DrawEllipse( (short) vp.x, (short) vp.y, 6, 5, colors[mn->color&7], false );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Key Press Event */
|
||||
void MapControl::OnKeyPress(unsigned char /*Key*/, unsigned short /*Mod*/)
|
||||
{
|
||||
}
|
||||
|
||||
/** Key Release Event */
|
||||
void MapControl::OnKeyRelease(unsigned char Key, unsigned short Mod)
|
||||
{
|
||||
switch (Key) {
|
||||
case '\t':
|
||||
//not GEM_TAB
|
||||
print( "TAB released\n" );
|
||||
return;
|
||||
case 'f':
|
||||
if (Mod & GEM_MOD_CTRL)
|
||||
core->GetVideoDriver()->ToggleFullscreenMode();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!core->CheatEnabled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
/** Mouse Over Event */
|
||||
void MapControl::OnMouseOver(unsigned short x, unsigned short y)
|
||||
{
|
||||
if (mouseIsDown) {
|
||||
ScrollX -= x - lastMouseX;
|
||||
ScrollY -= y - lastMouseY;
|
||||
|
||||
if (ScrollX > MapWidth - Width)
|
||||
ScrollX = MapWidth - Width;
|
||||
if (ScrollY > MapHeight - Height)
|
||||
ScrollY = MapHeight - Height;
|
||||
if (ScrollX < 0)
|
||||
ScrollX = 0;
|
||||
if (ScrollY < 0)
|
||||
ScrollY = 0;
|
||||
}
|
||||
|
||||
if (mouseIsDragging) {
|
||||
ViewHandle(x,y);
|
||||
}
|
||||
|
||||
lastMouseX = x;
|
||||
lastMouseY = y;
|
||||
|
||||
switch (Value) {
|
||||
case MAP_REVEAL: //for farsee effect
|
||||
Owner->Cursor = IE_CURSOR_CAST;
|
||||
break;
|
||||
case MAP_SET_NOTE:
|
||||
Owner->Cursor = IE_CURSOR_GRAB;
|
||||
break;
|
||||
default:
|
||||
Owner->Cursor = IE_CURSOR_NORMAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Value == MAP_VIEW_NOTES || Value == MAP_SET_NOTE || Value == MAP_REVEAL) {
|
||||
Point mp;
|
||||
unsigned int dist;
|
||||
|
||||
if (convertToGame) {
|
||||
mp.x = (short) SCREEN_TO_GAMEX(x);
|
||||
mp.y = (short) SCREEN_TO_GAMEY(y);
|
||||
dist = 100;
|
||||
} else {
|
||||
mp.x = (short) SCREEN_TO_MAPX(x);
|
||||
mp.y = (short) SCREEN_TO_MAPY(y);
|
||||
dist = 16;
|
||||
}
|
||||
int i = MyMap -> GetMapNoteCount();
|
||||
while (i--) {
|
||||
MapNote * mn = MyMap -> GetMapNote(i);
|
||||
if (Distance(mp, mn->Pos)<dist) {
|
||||
if (LinkedLabel) {
|
||||
LinkedLabel->SetText( mn->text );
|
||||
}
|
||||
NotePosX = mn->Pos.x;
|
||||
NotePosY = mn->Pos.y;
|
||||
return;
|
||||
}
|
||||
}
|
||||
NotePosX = mp.x;
|
||||
NotePosY = mp.y;
|
||||
}
|
||||
if (LinkedLabel) {
|
||||
LinkedLabel->SetText( "" );
|
||||
}
|
||||
}
|
||||
|
||||
/** Mouse Leave Event */
|
||||
void MapControl::OnMouseLeave(unsigned short /*x*/, unsigned short /*y*/)
|
||||
{
|
||||
Owner->Cursor = IE_CURSOR_NORMAL;
|
||||
}
|
||||
|
||||
void MapControl::ClickHandle(unsigned short Button)
|
||||
{
|
||||
core->GetDictionary()->SetAt( "MapControlX", NotePosX );
|
||||
core->GetDictionary()->SetAt( "MapControlY", NotePosY );
|
||||
switch(Button&GEM_MB_NORMAL) {
|
||||
case GEM_MB_ACTION:
|
||||
if (Button&GEM_MB_DOUBLECLICK) {
|
||||
RunEventHandler( MapControlOnDoublePress );
|
||||
} else {
|
||||
RunEventHandler( MapControlOnPress );
|
||||
}
|
||||
break;
|
||||
case GEM_MB_MENU:
|
||||
RunEventHandler( MapControlOnRightPress );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MapControl::ViewHandle(unsigned short x, unsigned short y)
|
||||
{
|
||||
short xp = (short) (SCREEN_TO_MAPX(x) - ViewWidth / 2);
|
||||
short yp = (short) (SCREEN_TO_MAPY(y) - ViewHeight / 2);
|
||||
|
||||
if (xp + ViewWidth > MapWidth) xp = MapWidth - ViewWidth;
|
||||
if (yp + ViewHeight > MapHeight) yp = MapHeight - ViewHeight;
|
||||
if (xp < 0) xp = 0;
|
||||
if (yp < 0) yp = 0;
|
||||
|
||||
// clear any previously scheduled moves and then do it asap, so it works while paused
|
||||
unsigned int vpx = xp * MAP_MULT / MAP_DIV;
|
||||
unsigned int vpy = yp * MAP_MULT / MAP_DIV;
|
||||
core->timer->SetMoveViewPort( vpx, vpy, 0, false );
|
||||
core->GetVideoDriver()->MoveViewportTo( vpx, vpy );
|
||||
}
|
||||
|
||||
/** Mouse Button Down */
|
||||
void MapControl::OnMouseDown(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short /*Mod*/)
|
||||
{
|
||||
switch((unsigned char) Button) {
|
||||
case GEM_MB_SCRLUP:
|
||||
OnSpecialKeyPress(GEM_UP);
|
||||
return;
|
||||
case GEM_MB_SCRLDOWN:
|
||||
OnSpecialKeyPress(GEM_DOWN);
|
||||
return;
|
||||
case GEM_MB_ACTION:
|
||||
if (Button & GEM_MB_DOUBLECLICK) {
|
||||
ClickHandle(Button);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mouseIsDown = true;
|
||||
short xp = (short) (SCREEN_TO_GAMEX(x));
|
||||
short yp = (short) (SCREEN_TO_GAMEY(y));
|
||||
Region vp = core->GetVideoDriver()->GetViewport();
|
||||
vp.w = vp.x+ViewWidth*MAP_MULT/MAP_DIV;
|
||||
vp.h = vp.y+ViewHeight*MAP_MULT/MAP_DIV;
|
||||
if ((xp>vp.x) && (xp<vp.w) && (yp>vp.y) && (yp<vp.h)) {
|
||||
mouseIsDragging = true;
|
||||
} else {
|
||||
mouseIsDragging = false;
|
||||
}
|
||||
lastMouseX = x;
|
||||
lastMouseY = y;
|
||||
}
|
||||
|
||||
/** Mouse Button Up */
|
||||
void MapControl::OnMouseUp(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short /*Mod*/)
|
||||
{
|
||||
if (!mouseIsDown) {
|
||||
return;
|
||||
}
|
||||
|
||||
mouseIsDown = false;
|
||||
mouseIsDragging = false;
|
||||
switch(Value) {
|
||||
case MAP_REVEAL:
|
||||
ViewHandle(x,y);
|
||||
NotePosX = (short) SCREEN_TO_MAPX(x) * MAP_MULT / MAP_DIV;
|
||||
NotePosY = (short) SCREEN_TO_MAPY(y) * MAP_MULT / MAP_DIV;
|
||||
ClickHandle(Button);
|
||||
return;
|
||||
case MAP_NO_NOTES:
|
||||
ViewHandle(x,y);
|
||||
return;
|
||||
case MAP_VIEW_NOTES:
|
||||
//left click allows setting only when in MAP_SET_NOTE mode
|
||||
if (Button == GEM_MB_ACTION) {
|
||||
ViewHandle(x,y);
|
||||
}
|
||||
ClickHandle(Button);
|
||||
return;
|
||||
default:
|
||||
ClickHandle(Button);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/** Special Key Press */
|
||||
void MapControl::OnSpecialKeyPress(unsigned char Key)
|
||||
{
|
||||
switch (Key) {
|
||||
case GEM_LEFT:
|
||||
ScrollX -= 64;
|
||||
break;
|
||||
case GEM_UP:
|
||||
ScrollY -= 64;
|
||||
break;
|
||||
case GEM_RIGHT:
|
||||
ScrollX += 64;
|
||||
break;
|
||||
case GEM_DOWN:
|
||||
ScrollY += 64;
|
||||
break;
|
||||
case GEM_ALT:
|
||||
print( "ALT pressed\n" );
|
||||
break;
|
||||
case GEM_TAB:
|
||||
print( "TAB pressed\n" );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (ScrollX > MapWidth - Width)
|
||||
ScrollX = MapWidth - Width;
|
||||
if (ScrollY > MapHeight - Height)
|
||||
ScrollY = MapHeight - Height;
|
||||
if (ScrollX < 0)
|
||||
ScrollX = 0;
|
||||
if (ScrollY < 0)
|
||||
ScrollY = 0;
|
||||
}
|
||||
|
||||
bool MapControl::SetEvent(int eventType, EventHandler handler)
|
||||
{
|
||||
Changed = true;
|
||||
|
||||
switch (eventType) {
|
||||
case IE_GUI_MAP_ON_PRESS:
|
||||
MapControlOnPress = handler;
|
||||
break;
|
||||
case IE_GUI_MAP_ON_RIGHT_PRESS:
|
||||
MapControlOnRightPress = handler;
|
||||
break;
|
||||
case IE_GUI_MAP_ON_DOUBLE_PRESS:
|
||||
MapControlOnDoublePress = handler;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file MapControl.h
|
||||
* Declares MapControl, widget for displaying current area map
|
||||
*/
|
||||
|
||||
class MapControl;
|
||||
|
||||
#ifndef MAPCONTROL_H
|
||||
#define MAPCONTROL_H
|
||||
|
||||
#include "GUI/Control.h"
|
||||
|
||||
#include "exports.h"
|
||||
#include "Interface.h"
|
||||
|
||||
// !!! Keep these synchronized with GUIDefines.py !!!
|
||||
#define IE_GUI_MAP_ON_PRESS 0x09000000
|
||||
#define IE_GUI_MAP_ON_RIGHT_PRESS 0x09000005
|
||||
#define IE_GUI_MAP_ON_DOUBLE_PRESS 0x09000008
|
||||
|
||||
|
||||
/**
|
||||
* @class MapControl
|
||||
* Widget displaying current area map, with a viewport rectangle
|
||||
* and PCs' ground circles
|
||||
*/
|
||||
|
||||
class GEM_EXPORT MapControl : public Control {
|
||||
public:
|
||||
int ScrollX, ScrollY;
|
||||
int NotePosX, NotePosY;
|
||||
unsigned short lastMouseX, lastMouseY;
|
||||
bool mouseIsDown;
|
||||
bool mouseIsDragging;
|
||||
bool convertToGame;
|
||||
// Small map bitmap
|
||||
Sprite2D* MapMOS;
|
||||
// current map
|
||||
Map *MyMap;
|
||||
// map flags
|
||||
Sprite2D *Flag[8];
|
||||
// The MapControl can set the text of this label directly
|
||||
Control *LinkedLabel;
|
||||
// Size of big map (area) in pixels
|
||||
short MapWidth, MapHeight;
|
||||
// Size of area viewport. FIXME: hack!
|
||||
short ViewWidth, ViewHeight;
|
||||
short XCenter, YCenter;
|
||||
EventHandler MapControlOnPress;
|
||||
EventHandler MapControlOnRightPress;
|
||||
EventHandler MapControlOnDoublePress;
|
||||
|
||||
MapControl(void);
|
||||
~MapControl(void);
|
||||
/** redraws the control after its associated variable has changed */
|
||||
void RedrawMapControl(const char *VariableName, unsigned int Sum);
|
||||
/** Draws the Control on the Output Display */
|
||||
void Draw(unsigned short XWin, unsigned short YWin);
|
||||
void DrawFog(unsigned short XWin, unsigned short YWin);
|
||||
/** Compute parameters after changes in control's or screen geometry */
|
||||
void Realize();
|
||||
|
||||
/** Key Press Event */
|
||||
void OnKeyPress(unsigned char Key, unsigned short Mod);
|
||||
/** Mouse Over Event */
|
||||
void OnMouseOver(unsigned short x, unsigned short y);
|
||||
/** Mouse Leave Event */
|
||||
void OnMouseLeave(unsigned short x, unsigned short y);
|
||||
/** Mouse Button Down */
|
||||
void OnMouseDown(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Mouse Button Up */
|
||||
void OnMouseUp(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Key Release Event */
|
||||
void OnKeyRelease(unsigned char Key, unsigned short Mod);
|
||||
/** Special Key Press */
|
||||
void OnSpecialKeyPress(unsigned char Key);
|
||||
/** Set handler for specified event */
|
||||
bool SetEvent(int eventType, EventHandler handler);
|
||||
private:
|
||||
/** Call event handler on click */
|
||||
void ClickHandle(unsigned short Button);
|
||||
/** Move viewport */
|
||||
void ViewHandle(unsigned short x, unsigned short y);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,179 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GUI/Progressbar.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "Interface.h"
|
||||
#include "Video.h"
|
||||
#include "GUI/Window.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
Progressbar::Progressbar( unsigned short KnobStepsCount, bool Clear)
|
||||
{
|
||||
BackGround = NULL;
|
||||
BackGround2 = NULL;
|
||||
this->Clear = Clear;
|
||||
this->KnobStepsCount = KnobStepsCount;
|
||||
PBarAnim = NULL;
|
||||
PBarCap = NULL;
|
||||
KnobXPos = KnobYPos = 0;
|
||||
CapXPos = CapYPos = 0;
|
||||
ResetEventHandler( EndReached );
|
||||
}
|
||||
|
||||
Progressbar::~Progressbar()
|
||||
{
|
||||
if (!Clear) {
|
||||
return;
|
||||
}
|
||||
core->GetVideoDriver()->FreeSprite( BackGround );
|
||||
core->GetVideoDriver()->FreeSprite( BackGround2 );
|
||||
delete PBarAnim;
|
||||
core->GetVideoDriver()->FreeSprite( PBarCap );
|
||||
}
|
||||
|
||||
/** Draws the Control on the Output Display */
|
||||
void Progressbar::Draw(unsigned short x, unsigned short y)
|
||||
{
|
||||
//it is unlikely that a floating window is above us, but...
|
||||
if (!Changed && !(Owner->Flags&WF_FLOAT) ) {
|
||||
return;
|
||||
}
|
||||
Changed = false;
|
||||
if (XPos == 65535) {
|
||||
return;
|
||||
}
|
||||
Sprite2D *bcksprite;
|
||||
|
||||
if((Value >= 100) && KnobStepsCount && BackGround2) {
|
||||
bcksprite=BackGround2; //animated progbar end stage
|
||||
}
|
||||
else {
|
||||
bcksprite=BackGround;
|
||||
}
|
||||
if (bcksprite) {
|
||||
Region r( x + XPos, y + YPos, Width, Height );
|
||||
core->GetVideoDriver()->BlitSprite( bcksprite,
|
||||
x + XPos, y + YPos, true, &r );
|
||||
if( bcksprite==BackGround2) {
|
||||
return; //done for animated progbar
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Count;
|
||||
|
||||
if(!KnobStepsCount) {
|
||||
//linear progressbar (pst, iwd)
|
||||
int w = BackGround2->Width;
|
||||
int h = BackGround2->Height;
|
||||
//this is the PST/IWD specific part
|
||||
Count = Value*w/100;
|
||||
Region r( x + XPos + KnobXPos, y + YPos + KnobYPos, Count, h );
|
||||
core->GetVideoDriver()->BlitSprite( BackGround2,
|
||||
r.x, r.y, true, &r );
|
||||
|
||||
core->GetVideoDriver()->BlitSprite( PBarCap,
|
||||
x+XPos+CapXPos+Count-PBarCap->Width, y+YPos+CapYPos, true );
|
||||
return;
|
||||
}
|
||||
|
||||
//animated progressbar (bg2)
|
||||
Count=Value*KnobStepsCount/100;
|
||||
for(unsigned int i=0; i<Count ;i++ ) {
|
||||
Sprite2D *Knob = PBarAnim->GetFrame(i);
|
||||
core->GetVideoDriver()->BlitSprite( Knob, x , y , true );
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the actual Progressbar Position */
|
||||
unsigned int Progressbar::GetPosition()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
/** Sets the actual Progressbar Position trimming to the Max and Min Values */
|
||||
void Progressbar::SetPosition(unsigned int pos)
|
||||
{
|
||||
if(pos>100) pos=100;
|
||||
if (Value == pos)
|
||||
return;
|
||||
Value = pos;
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
void Progressbar::RedrawProgressbar(const char* VariableName, int Sum)
|
||||
{
|
||||
if (strnicmp( VarName, VariableName, MAX_VARIABLE_LENGTH )) {
|
||||
return;
|
||||
}
|
||||
SetPosition((unsigned int) Sum);
|
||||
if((Value==100) && Changed)
|
||||
RunEventHandler( EndReached );
|
||||
}
|
||||
|
||||
/** Sets the selected image */
|
||||
void Progressbar::SetImage(Sprite2D* img, Sprite2D* img2)
|
||||
{
|
||||
if (BackGround && Clear)
|
||||
core->GetVideoDriver()->FreeSprite( BackGround );
|
||||
BackGround = img;
|
||||
if (BackGround2 && Clear)
|
||||
core->GetVideoDriver()->FreeSprite( BackGround2 );
|
||||
BackGround2 = img2;
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
void Progressbar::SetBarCap(Sprite2D* img3)
|
||||
{
|
||||
core->GetVideoDriver()->FreeSprite( PBarCap );
|
||||
PBarCap = img3;
|
||||
}
|
||||
|
||||
void Progressbar::SetAnimation(Animation *arg)
|
||||
{
|
||||
delete PBarAnim;
|
||||
PBarAnim = arg;
|
||||
}
|
||||
|
||||
void Progressbar::SetSliderPos(int x, int y, int x2, int y2)
|
||||
{
|
||||
KnobXPos=x;
|
||||
KnobYPos=y;
|
||||
CapXPos=x2;
|
||||
CapYPos=y2;
|
||||
}
|
||||
|
||||
bool Progressbar::SetEvent(int eventType, EventHandler handler)
|
||||
{
|
||||
Changed = true;
|
||||
|
||||
switch (eventType) {
|
||||
case IE_GUI_PROGRESS_END_REACHED:
|
||||
EndReached = handler;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003-2005 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Progressbar.h
|
||||
* Declares Progressbar widget for displaying progress of loading and saving games
|
||||
*/
|
||||
|
||||
#ifndef PROGRESSBAR_H
|
||||
#define PROGRESSBAR_H
|
||||
|
||||
#include "GUI/Control.h"
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
#include "Animation.h"
|
||||
#include "Sprite2D.h"
|
||||
|
||||
// !!! Keep in sync with GUIDefines.py !!!
|
||||
#define IE_GUI_PROGRESS_END_REACHED 0x01000000
|
||||
|
||||
|
||||
/**
|
||||
* @class Progressbar
|
||||
* Widget for displaying progressbars, mainly on loading/saving screens
|
||||
*/
|
||||
|
||||
class GEM_EXPORT Progressbar : public Control {
|
||||
public:
|
||||
Progressbar(unsigned short KnobStepsCount, bool Clear = false);
|
||||
~Progressbar();
|
||||
/** Draws the Control on the Output Display */
|
||||
void Draw(unsigned short x, unsigned short y);
|
||||
/** Returns the actual Progressbar Position */
|
||||
unsigned int GetPosition();
|
||||
/** Sets the actual Progressbar Position trimming to the Max and Min Values */
|
||||
void SetPosition(unsigned int pos);
|
||||
/** Sets the background images */
|
||||
void SetImage(Sprite2D * img, Sprite2D * img2);
|
||||
/** Sets a bam resource for progressbar */
|
||||
void SetAnimation(Animation *arg);
|
||||
/** Sets a mos resource for progressbar cap */
|
||||
void SetBarCap(Sprite2D *img3);
|
||||
/** Sets the mos coordinates for the progressbar filler mos/cap */
|
||||
void SetSliderPos(int x, int y, int x2, int y2);
|
||||
/** Redraws a progressbar which is associated with VariableName */
|
||||
void RedrawProgressbar(const char *VariableName, int Sum);
|
||||
/** Set handler for specified event */
|
||||
bool SetEvent(int eventType, EventHandler handler);
|
||||
|
||||
private: // Private attributes
|
||||
/** BackGround Images. If smaller than the Control Size, the image will be tiled. */
|
||||
Sprite2D * BackGround;
|
||||
Sprite2D * BackGround2; //mos resource for the filling of the bar
|
||||
/** Knob Steps Count */
|
||||
unsigned int KnobStepsCount;
|
||||
int KnobXPos, KnobYPos; //relative coordinates for Background2
|
||||
int CapXPos, CapYPos; //relative coordinates for PBarCap
|
||||
/** If true, on deletion the Progressbar will destroy the associated images */
|
||||
bool Clear;
|
||||
/** The bam cycle whose frames work as a progressbar (animated progressbar) */
|
||||
Animation *PBarAnim;
|
||||
/** The most for the progressbar cap (linear progressbar) */
|
||||
Sprite2D *PBarCap;
|
||||
public:
|
||||
/** EndReached Scripted Event Function Name */
|
||||
EventHandler EndReached;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,293 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GUI/ScrollBar.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "Interface.h"
|
||||
#include "Variables.h"
|
||||
#include "Video.h"
|
||||
#include "GUI/EventMgr.h"
|
||||
#include "GUI/Window.h"
|
||||
|
||||
ScrollBar::ScrollBar(void)
|
||||
{
|
||||
Pos = 0;
|
||||
Value = 10;
|
||||
State = 0;
|
||||
ResetEventHandler( ScrollBarOnChange );
|
||||
ta = NULL;
|
||||
for(int i=0;i<SB_RES_COUNT;i++) {
|
||||
Frames[i]=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar::~ScrollBar(void)
|
||||
{
|
||||
Video *video=core->GetVideoDriver();
|
||||
for(int i=0;i<SB_RES_COUNT;i++) {
|
||||
if(Frames[i]) {
|
||||
video->FreeSprite(Frames[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets a new position, relays the change to an associated textarea and calls
|
||||
any existing GUI OnChange callback */
|
||||
void ScrollBar::SetPos(int NewPos)
|
||||
{
|
||||
if (Pos && ( Pos == NewPos )) {
|
||||
return;
|
||||
}
|
||||
Changed = true;
|
||||
Pos = (ieWord) NewPos;
|
||||
if (ta) {
|
||||
TextArea* t = ( TextArea* ) ta;
|
||||
t->SetRow( Pos );
|
||||
}
|
||||
if (VarName[0] != 0) {
|
||||
core->GetDictionary()->SetAt( VarName, Pos );
|
||||
}
|
||||
RunEventHandler( ScrollBarOnChange );
|
||||
}
|
||||
|
||||
/** Refreshes the ScrollBar according to a guiscript variable */
|
||||
void ScrollBar::RedrawScrollBar(const char* Variable, int Sum)
|
||||
{
|
||||
if (strnicmp( VarName, Variable, MAX_VARIABLE_LENGTH )) {
|
||||
return;
|
||||
}
|
||||
SetPos( Sum );
|
||||
}
|
||||
|
||||
/** Mousewheel support */
|
||||
void ScrollBar::ScrollUp()
|
||||
{
|
||||
if (Pos > 0) {
|
||||
SetPos( Pos - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/** Mousewheel support */
|
||||
void ScrollBar::ScrollDown()
|
||||
{
|
||||
if ( (ieDword) Pos + 1 < Value ) {
|
||||
SetPos( Pos + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/** Draws the ScrollBar control */
|
||||
void ScrollBar::Draw(unsigned short x, unsigned short y)
|
||||
{
|
||||
if (!Changed && !(Owner->Flags&WF_FLOAT) ) {
|
||||
return;
|
||||
}
|
||||
Changed = false;
|
||||
if (XPos == 65535) {
|
||||
return;
|
||||
}
|
||||
int upMy = Frames[IE_GUI_SCROLLBAR_UP_UNPRESSED]->Height;
|
||||
int doMy = Frames[IE_GUI_SCROLLBAR_DOWN_UNPRESSED]->Height;
|
||||
unsigned int domy = (Height - doMy);
|
||||
|
||||
unsigned short slmy = ( unsigned short )
|
||||
( upMy +
|
||||
( Pos * ( ( domy - Frames[IE_GUI_SCROLLBAR_SLIDER]->Height - upMy ) /
|
||||
( double ) ( Value < 2 ? 1 : Value - 1 ) ) ) );
|
||||
unsigned short slx = ( unsigned short ) ((Width - Frames[IE_GUI_SCROLLBAR_SLIDER]->Width) / 2 );
|
||||
|
||||
if (( State & UP_PRESS ) != 0) {
|
||||
core->GetVideoDriver()->BlitSprite( Frames[IE_GUI_SCROLLBAR_UP_PRESSED],
|
||||
x + XPos, y + YPos, true );
|
||||
} else {
|
||||
core->GetVideoDriver()->BlitSprite( Frames[IE_GUI_SCROLLBAR_UP_UNPRESSED],
|
||||
x + XPos, y + YPos, true );
|
||||
}
|
||||
int maxy = y + YPos + Height -
|
||||
Frames[IE_GUI_SCROLLBAR_DOWN_UNPRESSED]->Height;
|
||||
int stepy = Frames[IE_GUI_SCROLLBAR_TROUGH]->Height;
|
||||
Region rgn( x + XPos, y + YPos + upMy, Width, domy - upMy);
|
||||
for (int dy = y + YPos + upMy; dy < maxy; dy += stepy) {
|
||||
core->GetVideoDriver()->BlitSprite( Frames[IE_GUI_SCROLLBAR_TROUGH],
|
||||
x + XPos + ( ( Width / 2 ) -
|
||||
Frames[IE_GUI_SCROLLBAR_TROUGH]->Width / 2 ),
|
||||
dy, true, &rgn );
|
||||
}
|
||||
if (( State & DOWN_PRESS ) != 0) {
|
||||
core->GetVideoDriver()->BlitSprite( Frames[IE_GUI_SCROLLBAR_DOWN_PRESSED],
|
||||
x + XPos, maxy, true );
|
||||
} else {
|
||||
core->GetVideoDriver()->BlitSprite( Frames[IE_GUI_SCROLLBAR_DOWN_UNPRESSED],
|
||||
x + XPos, maxy, true );
|
||||
}
|
||||
core->GetVideoDriver()->BlitSprite( Frames[IE_GUI_SCROLLBAR_SLIDER],
|
||||
x + XPos + slx + Frames[IE_GUI_SCROLLBAR_SLIDER]->XPos,
|
||||
y + YPos + slmy + Frames[IE_GUI_SCROLLBAR_SLIDER]->YPos,
|
||||
true );
|
||||
}
|
||||
|
||||
/** Sets a ScrollBar GUI resource */
|
||||
void ScrollBar::SetImage(unsigned char type, Sprite2D* img)
|
||||
{
|
||||
if (type >= SB_RES_COUNT) {
|
||||
return;
|
||||
}
|
||||
if (Frames[type]) {
|
||||
core->GetVideoDriver()->FreeSprite(Frames[type]);
|
||||
}
|
||||
Frames[type] = img;
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
/** Mouse Button Down */
|
||||
void ScrollBar::OnMouseDown(unsigned short x, unsigned short y,
|
||||
unsigned short Button, unsigned short /*Mod*/)
|
||||
{
|
||||
//removing the double click flag, use a more sophisticated method
|
||||
//if it is needed later
|
||||
Button&=GEM_MB_NORMAL;
|
||||
if (Button==GEM_MB_SCRLUP) {
|
||||
ScrollUp();
|
||||
return;
|
||||
}
|
||||
if (Button==GEM_MB_SCRLDOWN) {
|
||||
ScrollDown();
|
||||
return;
|
||||
}
|
||||
|
||||
core->RedrawAll();
|
||||
|
||||
unsigned short upMx = (unsigned short) Frames[IE_GUI_SCROLLBAR_UP_UNPRESSED]->Width;
|
||||
unsigned short upMy = (unsigned short) Frames[IE_GUI_SCROLLBAR_UP_UNPRESSED]->Height;
|
||||
unsigned short domy = (unsigned short) (Height - Frames[IE_GUI_SCROLLBAR_DOWN_UNPRESSED]->Height);
|
||||
unsigned short slheight = domy - upMy;
|
||||
unsigned short refheight = (unsigned short) (slheight - Frames[IE_GUI_SCROLLBAR_SLIDER]->Height);
|
||||
double step = refheight / (double) ( Value < 2 ? 1 : Value - 1 );
|
||||
unsigned short ymax = upMy + refheight;
|
||||
unsigned short ymy = y - upMy;
|
||||
unsigned short doMx = (unsigned short) Frames[IE_GUI_SCROLLBAR_DOWN_UNPRESSED]->Width;
|
||||
unsigned short slMx = (unsigned short) Frames[IE_GUI_SCROLLBAR_SLIDER]->Width;
|
||||
unsigned short slmy = (unsigned short) (upMy + Pos * step);
|
||||
unsigned short slMy = (unsigned short) (slmy + Frames[IE_GUI_SCROLLBAR_SLIDER]->Height);
|
||||
if (( x <= upMx ) && ( y <= upMy )) {
|
||||
if (Pos > 0)
|
||||
SetPos( Pos - 1 );
|
||||
State |= UP_PRESS;
|
||||
return;
|
||||
}
|
||||
if (y >= domy) {
|
||||
if (( x <= doMx ) && ( y <= Height )) {
|
||||
if ( (ieDword) Pos + 1 < Value )
|
||||
SetPos( Pos + 1 );
|
||||
State |= DOWN_PRESS;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (y >= slmy) {
|
||||
if (( x <= slMx ) && ( y <= slMy )) {
|
||||
State |= SLIDER_GRAB;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (y <= upMy) {
|
||||
SetPos( 0 );
|
||||
return;
|
||||
}
|
||||
if (y >= ymax) {
|
||||
SetPos( Value - 1 );
|
||||
return;
|
||||
}
|
||||
unsigned short befst = ( unsigned short ) ( ymy / step );
|
||||
unsigned short aftst = befst + 1;
|
||||
if (( ymy - ( befst * step ) ) < ( ( aftst * step ) - ymy )) {
|
||||
SetPos( befst );
|
||||
} else {
|
||||
SetPos( aftst );
|
||||
}
|
||||
}
|
||||
|
||||
/** Mouse Button Up */
|
||||
void ScrollBar::OnMouseUp(unsigned short /*x*/, unsigned short /*y*/,
|
||||
unsigned short /*Button*/, unsigned short /*Mod*/)
|
||||
{
|
||||
Changed = true;
|
||||
State = 0;
|
||||
}
|
||||
|
||||
/** Mouse Over Event */
|
||||
void ScrollBar::OnMouseOver(unsigned short /*x*/, unsigned short y)
|
||||
{
|
||||
if (( State & SLIDER_GRAB ) != 0) {
|
||||
core->RedrawAll();
|
||||
unsigned short upMy =(unsigned short) Frames[IE_GUI_SCROLLBAR_UP_UNPRESSED]->Height;
|
||||
unsigned short domy = (unsigned short) (Height - Frames[IE_GUI_SCROLLBAR_DOWN_UNPRESSED]->Height);
|
||||
unsigned short slheight = domy - upMy;
|
||||
unsigned short refheight = (unsigned short) (slheight - Frames[IE_GUI_SCROLLBAR_SLIDER]->Height);
|
||||
double step = refheight / ( double ) ( Value < 2 ? 1 : Value - 1 );
|
||||
unsigned short yzero = (unsigned short) (upMy + Frames[IE_GUI_SCROLLBAR_SLIDER]->Height / 2 );
|
||||
unsigned short ymax = yzero + refheight;
|
||||
unsigned short ymy = y - yzero;
|
||||
if (y <= yzero) {
|
||||
SetPos( 0 );
|
||||
return;
|
||||
}
|
||||
if (y >= ymax) {
|
||||
SetPos( Value - 1 );
|
||||
return;
|
||||
}
|
||||
unsigned short befst = ( unsigned short ) ( ymy / step );
|
||||
unsigned short aftst = befst + 1;
|
||||
if (( ymy - ( befst * step ) ) < ( ( aftst * step ) - ymy )) {
|
||||
if (befst > Value )
|
||||
SetPos( befst );
|
||||
} else {
|
||||
if (aftst < Value )
|
||||
SetPos( aftst );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the Maximum Value of the ScrollBar */
|
||||
void ScrollBar::SetMax(unsigned short Max)
|
||||
{
|
||||
Value = Max;
|
||||
if (Max == 0) {
|
||||
SetPos( 0 );
|
||||
} else if (Pos >= Max) {
|
||||
SetPos( Max - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the ScrollBarOnChange event (guiscript callback) */
|
||||
bool ScrollBar::SetEvent(int eventType, EventHandler handler)
|
||||
{
|
||||
Changed = true;
|
||||
|
||||
switch (eventType) {
|
||||
case IE_GUI_SCROLLBAR_ON_CHANGE:
|
||||
ScrollBarOnChange = handler;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ScrollBar.h
|
||||
* Declares ScrollBar widget for paging in long text windows.
|
||||
* This does not include scales and sliders, which are of Slider class.
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
#ifndef SCROLLBAR_H
|
||||
#define SCROLLBAR_H
|
||||
|
||||
#include "GUI/Control.h"
|
||||
#include "GUI/TextArea.h"
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
#include "Sprite2D.h"
|
||||
|
||||
// !!! Keep these synchronized with GUIDefines.py !!!
|
||||
#define IE_GUI_SCROLLBAR_ON_CHANGE 0x07000000
|
||||
|
||||
#define IE_GUI_SCROLLBAR_DEFAULT 0x00000040 // mousewheel triggers it
|
||||
|
||||
#define IE_GUI_SCROLLBAR_UP_UNPRESSED 0
|
||||
#define IE_GUI_SCROLLBAR_UP_PRESSED 1
|
||||
#define IE_GUI_SCROLLBAR_DOWN_UNPRESSED 2
|
||||
#define IE_GUI_SCROLLBAR_DOWN_PRESSED 3
|
||||
#define IE_GUI_SCROLLBAR_TROUGH 4
|
||||
#define IE_GUI_SCROLLBAR_SLIDER 5
|
||||
|
||||
#define UP_PRESS 0x0001
|
||||
#define DOWN_PRESS 0x0010
|
||||
#define SLIDER_GRAB 0x0100
|
||||
|
||||
/**
|
||||
* @class ScrollBar
|
||||
* Widget displaying scrollbars for paging in long text windows
|
||||
*/
|
||||
|
||||
#define SB_RES_COUNT 6
|
||||
|
||||
class GEM_EXPORT ScrollBar : public Control {
|
||||
public:
|
||||
ScrollBar(void);
|
||||
~ScrollBar(void);
|
||||
/**sets position, updates associated stuff */
|
||||
void SetPos(int NewPos);
|
||||
void ScrollUp();
|
||||
void ScrollDown();
|
||||
/**redraws scrollbar if associated with VarName */
|
||||
void RedrawScrollBar(const char* VarName, int Sum);
|
||||
/**/
|
||||
void Draw(unsigned short x, unsigned short y);
|
||||
private: //Private attributes
|
||||
/** Images for drawing the Scroll Bar */
|
||||
Sprite2D* Frames[SB_RES_COUNT];
|
||||
/** Cursor Position */
|
||||
unsigned short Pos;
|
||||
/** Scroll Bar Status */
|
||||
unsigned short State;
|
||||
public:
|
||||
void SetImage(unsigned char type, Sprite2D* img);
|
||||
/** Sets the Maximum Value of the ScrollBar */
|
||||
void SetMax(unsigned short Max);
|
||||
/** TextArea Associated Control */
|
||||
Control* ta;
|
||||
public: // Public Events
|
||||
/** Mouse Button Down */
|
||||
void OnMouseDown(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Mouse Button Up */
|
||||
void OnMouseUp(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Mouse Over Event */
|
||||
void OnMouseOver(unsigned short x, unsigned short y);
|
||||
/** Set handler for specified event */
|
||||
bool SetEvent(int eventType, EventHandler handler);
|
||||
/** OnChange Scripted Event Function Name */
|
||||
EventHandler ScrollBarOnChange;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,291 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GUI/Slider.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "Interface.h"
|
||||
#include "Variables.h"
|
||||
#include "Video.h"
|
||||
#include "GUI/Window.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
Slider::Slider(short KnobXPos, short KnobYPos, short KnobStep,
|
||||
unsigned short KnobStepsCount, bool Clear)
|
||||
{
|
||||
this->KnobXPos = KnobXPos;
|
||||
this->KnobYPos = KnobYPos;
|
||||
this->KnobStep = KnobStep;
|
||||
this->KnobStepsCount = KnobStepsCount;
|
||||
Knob = NULL;
|
||||
GrabbedKnob = NULL;
|
||||
BackGround = NULL;
|
||||
this->Clear = Clear;
|
||||
ResetEventHandler( SliderOnChange );
|
||||
State = IE_GUI_SLIDER_KNOB;
|
||||
Pos = 0;
|
||||
Value = 1;
|
||||
}
|
||||
|
||||
Slider::~Slider()
|
||||
{
|
||||
if (!Clear) {
|
||||
return;
|
||||
}
|
||||
if (Knob) {
|
||||
core->GetVideoDriver()->FreeSprite( Knob );
|
||||
}
|
||||
if (GrabbedKnob) {
|
||||
core->GetVideoDriver()->FreeSprite( GrabbedKnob );
|
||||
}
|
||||
if (BackGround) {
|
||||
core->GetVideoDriver()->FreeSprite( BackGround );
|
||||
}
|
||||
}
|
||||
|
||||
/** Draws the Control on the Output Display */
|
||||
void Slider::Draw(unsigned short x, unsigned short y)
|
||||
{
|
||||
if (!Changed && !(Owner->Flags&WF_FLOAT) ) {
|
||||
return;
|
||||
}
|
||||
Changed = false;
|
||||
if (XPos == 65535) {
|
||||
return;
|
||||
}
|
||||
Region r( x + XPos, y + YPos, Width, Height );
|
||||
if (BackGround) {
|
||||
if (( BackGround->Width < Width ) || ( BackGround->Height < Height )) {
|
||||
core->GetVideoDriver()->BlitTiled( r, BackGround, true );
|
||||
} else {
|
||||
core->GetVideoDriver()->BlitSprite( BackGround, x + XPos, y + YPos, true, &r );
|
||||
}
|
||||
}
|
||||
switch (State) {
|
||||
case IE_GUI_SLIDER_KNOB:
|
||||
core->GetVideoDriver()->BlitSprite( Knob,
|
||||
x + XPos + KnobXPos + ( Pos * KnobStep ),
|
||||
y + YPos + KnobYPos, true );
|
||||
break;
|
||||
|
||||
case IE_GUI_SLIDER_GRABBEDKNOB:
|
||||
core->GetVideoDriver()->BlitSprite( GrabbedKnob,
|
||||
x + XPos + KnobXPos + ( Pos * KnobStep ),
|
||||
y + YPos + KnobYPos, true );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the actual Slider Position */
|
||||
unsigned int Slider::GetPosition()
|
||||
{
|
||||
return Pos;
|
||||
}
|
||||
|
||||
/** Sets the actual Slider Position trimming to the Max and Min Values */
|
||||
void Slider::SetPosition(unsigned int pos)
|
||||
{
|
||||
if (pos <= KnobStepsCount) {
|
||||
Pos = pos;
|
||||
}
|
||||
if (VarName[0] != 0) {
|
||||
if (!Value)
|
||||
Value = 1;
|
||||
core->GetDictionary()->SetAt( VarName, pos * Value );
|
||||
}
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
/** Redraws a slider which is associated with VariableName */
|
||||
void Slider::RedrawSlider(const char* VariableName, int Sum)
|
||||
{
|
||||
if (strnicmp( VarName, VariableName, MAX_VARIABLE_LENGTH )) {
|
||||
return;
|
||||
}
|
||||
if (!Value) {
|
||||
Value = 1;
|
||||
}
|
||||
Sum /= Value;
|
||||
if (Sum <= KnobStepsCount) {
|
||||
Pos = Sum;
|
||||
}
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
/** Sets the selected image */
|
||||
void Slider::SetImage(unsigned char type, Sprite2D* img)
|
||||
{
|
||||
switch (type) {
|
||||
case IE_GUI_SLIDER_KNOB:
|
||||
if (Knob && Clear)
|
||||
core->GetVideoDriver()->FreeSprite( Knob );
|
||||
Knob = img;
|
||||
break;
|
||||
|
||||
case IE_GUI_SLIDER_GRABBEDKNOB:
|
||||
if (GrabbedKnob && Clear)
|
||||
core->GetVideoDriver()->FreeSprite( GrabbedKnob );
|
||||
GrabbedKnob = img;
|
||||
break;
|
||||
|
||||
case IE_GUI_SLIDER_BACKGROUND:
|
||||
if (BackGround && Clear)
|
||||
core->GetVideoDriver()->FreeSprite( BackGround );
|
||||
BackGround = img;
|
||||
break;
|
||||
}
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
/** Mouse Button Down */
|
||||
void Slider::OnMouseDown(unsigned short x, unsigned short y, unsigned short /*Button*/,
|
||||
unsigned short /*Mod*/)
|
||||
{
|
||||
Changed = true;
|
||||
unsigned int oldPos = Pos;
|
||||
int mx = (KnobXPos + ( Pos * KnobStep ) - Knob->XPos);
|
||||
int my = (KnobYPos - Knob->YPos);
|
||||
int Mx = (mx + Knob->Width);
|
||||
int My = (my + Knob->Height);
|
||||
|
||||
if (( x >= mx ) && ( y >= my )) {
|
||||
if (( x <= Mx ) && ( y <= My )) {
|
||||
State = IE_GUI_SLIDER_GRABBEDKNOB;
|
||||
} else {
|
||||
int mx = KnobXPos;
|
||||
int xmx = x - mx;
|
||||
if (x < mx) {
|
||||
SetPosition( 0 );
|
||||
if (oldPos != Pos) {
|
||||
RunEventHandler( SliderOnChange );
|
||||
}
|
||||
return;
|
||||
}
|
||||
int befst = xmx / KnobStep;
|
||||
if (befst >= KnobStepsCount) {
|
||||
SetPosition( KnobStepsCount - 1 );
|
||||
if (oldPos != Pos) {
|
||||
RunEventHandler( SliderOnChange );
|
||||
}
|
||||
return;
|
||||
}
|
||||
int aftst = befst + KnobStep;
|
||||
if (( xmx - ( befst * KnobStep ) ) <
|
||||
( ( aftst * KnobStep ) - xmx )) {
|
||||
SetPosition( befst );
|
||||
} else {
|
||||
SetPosition( aftst );
|
||||
}
|
||||
if (oldPos != Pos) {
|
||||
RunEventHandler( SliderOnChange );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int mx = KnobXPos;
|
||||
int xmx = x - mx;
|
||||
if (x < mx) {
|
||||
SetPosition( 0 );
|
||||
if (oldPos != Pos) {
|
||||
RunEventHandler( SliderOnChange );
|
||||
}
|
||||
return;
|
||||
}
|
||||
int befst = xmx / KnobStep;
|
||||
if (befst >= KnobStepsCount) {
|
||||
SetPosition( KnobStepsCount - 1 );
|
||||
if (oldPos != Pos) {
|
||||
RunEventHandler( SliderOnChange );
|
||||
}
|
||||
return;
|
||||
}
|
||||
int aftst = befst + KnobStep;
|
||||
if (( xmx - ( befst * KnobStep ) ) < ( ( aftst * KnobStep ) - xmx )) {
|
||||
SetPosition( befst );
|
||||
} else {
|
||||
SetPosition( aftst );
|
||||
}
|
||||
if (oldPos != Pos) {
|
||||
RunEventHandler( SliderOnChange );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Mouse Button Up */
|
||||
void Slider::OnMouseUp(unsigned short /*x*/, unsigned short /*y*/, unsigned short /*Button*/,
|
||||
unsigned short /*Mod*/)
|
||||
{
|
||||
if (State != IE_GUI_SLIDER_KNOB) {
|
||||
Changed = true;
|
||||
}
|
||||
State = IE_GUI_SLIDER_KNOB;
|
||||
}
|
||||
|
||||
/** Mouse Over Event */
|
||||
void Slider::OnMouseOver(unsigned short x, unsigned short /*y*/)
|
||||
{
|
||||
Changed = true;
|
||||
unsigned int oldPos = Pos;
|
||||
if (State == IE_GUI_SLIDER_GRABBEDKNOB) {
|
||||
int mx = KnobXPos;
|
||||
int xmx = x - mx;
|
||||
if (x < mx) {
|
||||
SetPosition( 0 );
|
||||
if (oldPos != Pos) {
|
||||
RunEventHandler( SliderOnChange );
|
||||
}
|
||||
return;
|
||||
}
|
||||
int befst = xmx / KnobStep;
|
||||
if (befst >= KnobStepsCount) {
|
||||
SetPosition( KnobStepsCount - 1 );
|
||||
if (oldPos != Pos) {
|
||||
RunEventHandler( SliderOnChange );
|
||||
}
|
||||
return;
|
||||
}
|
||||
short aftst = befst + KnobStep;
|
||||
if (( xmx - ( befst * KnobStep ) ) < ( ( aftst * KnobStep ) - xmx )) {
|
||||
SetPosition( befst );
|
||||
} else {
|
||||
SetPosition( aftst );
|
||||
}
|
||||
if (oldPos != Pos) {
|
||||
RunEventHandler( SliderOnChange );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the slider change event */
|
||||
bool Slider::SetEvent(int eventType, EventHandler handler)
|
||||
{
|
||||
Changed = true;
|
||||
|
||||
switch (eventType) {
|
||||
case IE_GUI_SLIDER_ON_CHANGE:
|
||||
SliderOnChange = handler;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Slider.h
|
||||
* Declares Slider widget for displaying scales and sliders for setting
|
||||
* numerical values
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
#ifndef SLIDER_H
|
||||
#define SLIDER_H
|
||||
|
||||
#include "GUI/Control.h"
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
#include "Sprite2D.h"
|
||||
|
||||
// !!! Keep these synchronized with GUIDefines.py !!!
|
||||
#define IE_GUI_SLIDER_ON_CHANGE 0x02000000
|
||||
|
||||
|
||||
#define IE_GUI_SLIDER_KNOB 0
|
||||
#define IE_GUI_SLIDER_GRABBEDKNOB 1
|
||||
#define IE_GUI_SLIDER_BACKGROUND 2
|
||||
|
||||
/**
|
||||
* @class Slider
|
||||
* Widget displaying sliders or scales for inputting numerical values
|
||||
* with a limited range
|
||||
*/
|
||||
|
||||
class GEM_EXPORT Slider : public Control {
|
||||
public:
|
||||
Slider(short KnobXPos, short KnobYPos, short KnobStep, unsigned short KnobStepsCount, bool Clear = false);
|
||||
~Slider();
|
||||
/** Draws the Control on the Output Display */
|
||||
void Draw(unsigned short x, unsigned short y);
|
||||
/** Returns the actual Slider Position */
|
||||
unsigned int GetPosition();
|
||||
/** Sets the actual Slider Position trimming to the Max and Min Values */
|
||||
void SetPosition(unsigned int pos);
|
||||
/** Sets the selected image */
|
||||
void SetImage(unsigned char type, Sprite2D * img);
|
||||
/** Sets the State of the Slider */
|
||||
void SetState(int arg) { State=(unsigned char) arg; }
|
||||
/** Redraws a slider which is associated with VariableName */
|
||||
void RedrawSlider(const char *VariableName, int Sum);
|
||||
|
||||
private: // Private attributes
|
||||
/** BackGround Image. If smaller than the Control Size, the image will be tiled. */
|
||||
Sprite2D * BackGround;
|
||||
/** Knob Image */
|
||||
Sprite2D * Knob;
|
||||
/** Grabbed Knob Image */
|
||||
Sprite2D * GrabbedKnob;
|
||||
/** Knob Starting X Position */
|
||||
short KnobXPos;
|
||||
/** Knob Starting Y Position */
|
||||
short KnobYPos;
|
||||
/** Knob Step Size */
|
||||
short KnobStep;
|
||||
/** Knob Steps Count */
|
||||
unsigned short KnobStepsCount;
|
||||
/** If true, on deletion the Slider will destroy the associated images */
|
||||
bool Clear;
|
||||
/** Actual Knob Status */
|
||||
unsigned char State;
|
||||
/** Slider Position Value */
|
||||
unsigned int Pos;
|
||||
public: // Public Events
|
||||
/** Mouse Button Down */
|
||||
void OnMouseDown(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Mouse Button Up */
|
||||
void OnMouseUp(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Mouse Over Event */
|
||||
void OnMouseOver(unsigned short x, unsigned short y);
|
||||
/** Set handler for specified event */
|
||||
bool SetEvent(int eventType, EventHandler handler);
|
||||
/** OnChange Scripted Event Function Name */
|
||||
EventHandler SliderOnChange;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,983 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GUI/TextArea.h"
|
||||
|
||||
#include "GUI/GameControl.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "Audio.h"
|
||||
#include "DialogHandler.h"
|
||||
#include "GameData.h"
|
||||
#include "ImageMgr.h"
|
||||
#include "Interface.h"
|
||||
#include "Palette.h"
|
||||
#include "Variables.h"
|
||||
#include "Video.h"
|
||||
#include "GUI/EventMgr.h"
|
||||
#include "GUI/Window.h"
|
||||
#include "Scriptable/Actor.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
TextArea::TextArea(Color hitextcolor, Color initcolor, Color lowtextcolor)
|
||||
{
|
||||
keeplines = 100;
|
||||
rows = 0;
|
||||
startrow = 0;
|
||||
minrow = 0;
|
||||
Cursor = NULL;
|
||||
CurPos = 0;
|
||||
CurLine = 0;
|
||||
seltext = -1;
|
||||
Value = 0xffffffff;
|
||||
ResetEventHandler( TextAreaOnChange );
|
||||
ResetEventHandler( TextAreaOutOfText );
|
||||
PortraitResRef[0]=0;
|
||||
palette = core->CreatePalette( hitextcolor, lowtextcolor );
|
||||
initpalette = core->CreatePalette( initcolor, lowtextcolor );
|
||||
Color tmp = {
|
||||
hitextcolor.b, hitextcolor.g, hitextcolor.r, 0
|
||||
};
|
||||
selected = core->CreatePalette( tmp, lowtextcolor );
|
||||
tmp.r = 255;
|
||||
tmp.g = 152;
|
||||
tmp.b = 102;
|
||||
lineselpal = core->CreatePalette( tmp, lowtextcolor );
|
||||
InternalFlags = 1;
|
||||
//Drop Capitals means initials on!
|
||||
core->GetDictionary()->Lookup("Drop Capitals", InternalFlags);
|
||||
if (InternalFlags) {
|
||||
InternalFlags = TA_INITIALS;
|
||||
}
|
||||
}
|
||||
|
||||
TextArea::~TextArea(void)
|
||||
{
|
||||
gamedata->FreePalette( palette );
|
||||
gamedata->FreePalette( initpalette );
|
||||
gamedata->FreePalette( selected );
|
||||
gamedata->FreePalette( lineselpal );
|
||||
core->GetVideoDriver()->FreeSprite( Cursor );
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
free( lines[i] );
|
||||
}
|
||||
}
|
||||
|
||||
void TextArea::RefreshSprite(const char *portrait)
|
||||
{
|
||||
if (AnimPicture) {
|
||||
if (!strnicmp(PortraitResRef, portrait, 8) ) {
|
||||
return;
|
||||
}
|
||||
SetAnimPicture(NULL);
|
||||
}
|
||||
strnlwrcpy(PortraitResRef, portrait, 8);
|
||||
if (!strnicmp(PortraitResRef, "none", 8) ) {
|
||||
return;
|
||||
}
|
||||
ResourceHolder<ImageMgr> im(PortraitResRef);
|
||||
if (im == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetAnimPicture ( im->GetSprite2D() );
|
||||
}
|
||||
|
||||
void TextArea::Draw(unsigned short x, unsigned short y)
|
||||
{
|
||||
/** Don't come back recursively */
|
||||
if (InternalFlags&TA_BITEMYTAIL) {
|
||||
return;
|
||||
}
|
||||
int tx=x+XPos;
|
||||
int ty=y+YPos;
|
||||
Region clip( tx, ty, Width, Height );
|
||||
Video *video = core->GetVideoDriver();
|
||||
|
||||
if (Flags&IE_GUI_TEXTAREA_SPEAKER) {
|
||||
if (AnimPicture) {
|
||||
video->BlitSprite(AnimPicture, tx,ty, true, &clip);
|
||||
clip.x+=AnimPicture->Width;
|
||||
clip.w-=AnimPicture->Width;
|
||||
}
|
||||
}
|
||||
|
||||
//this might look better in GlobalTimer
|
||||
//or you might want to change the animated button to work like this
|
||||
if (Flags &IE_GUI_TEXTAREA_SMOOTHSCROLL)
|
||||
{
|
||||
unsigned long thisTime;
|
||||
|
||||
thisTime = GetTickCount();
|
||||
if (thisTime>starttime) {
|
||||
starttime = thisTime+ticks;
|
||||
smooth--;
|
||||
while (smooth<=0) {
|
||||
smooth+=ftext->maxHeight;
|
||||
if (startrow<rows) {
|
||||
startrow++;
|
||||
}
|
||||
}
|
||||
|
||||
/** Forcing redraw of whole screen before drawing text*/
|
||||
Owner->Invalidate();
|
||||
InternalFlags |= TA_BITEMYTAIL;
|
||||
Owner->DrawWindow();
|
||||
InternalFlags &= ~TA_BITEMYTAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Changed && !(Owner->Flags&WF_FLOAT) ) {
|
||||
return;
|
||||
}
|
||||
Changed = false;
|
||||
|
||||
if (XPos == 65535) {
|
||||
return;
|
||||
}
|
||||
size_t linesize = lines.size();
|
||||
if (linesize == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//smooth vertical scrolling up
|
||||
if (Flags & IE_GUI_TEXTAREA_SMOOTHSCROLL) {
|
||||
clip.y+=smooth;
|
||||
clip.h-=smooth;
|
||||
}
|
||||
|
||||
//if textarea is 'selectable' it actually means, it is a listbox
|
||||
//in this case the selected value equals the line number
|
||||
//if it is 'not selectable' it can still have selectable lines
|
||||
//but then it is like the dialog window in the main game screen:
|
||||
//the selected value is encoded into the line
|
||||
if (!(Flags & IE_GUI_TEXTAREA_SELECTABLE) ) {
|
||||
char* Buffer = (char *) malloc( 1 );
|
||||
Buffer[0] = 0;
|
||||
int len = 0;
|
||||
int lastlen = 0;
|
||||
for (size_t i = 0; i < linesize; i++) {
|
||||
if (strnicmp( "[s=", lines[i], 3 ) == 0) {
|
||||
int tlen;
|
||||
unsigned long idx, acolor, bcolor;
|
||||
char* rest;
|
||||
idx = strtoul( lines[i] + 3, &rest, 0 );
|
||||
if (*rest != ',')
|
||||
goto notmatched;
|
||||
acolor = strtoul( rest + 1, &rest, 16 );
|
||||
if (*rest != ',')
|
||||
goto notmatched;
|
||||
bcolor = strtoul( rest + 1, &rest, 16 );
|
||||
if (*rest != ']')
|
||||
goto notmatched;
|
||||
tlen = (int)(strstr( rest + 1, "[/s]" ) - rest - 1);
|
||||
if (tlen < 0)
|
||||
goto notmatched;
|
||||
len += tlen + 23;
|
||||
Buffer = (char *) realloc( Buffer, len + 2 );
|
||||
if (seltext == (int) i) {
|
||||
sprintf( Buffer + lastlen, "[color=%6.6lX]%.*s[/color]",
|
||||
acolor, tlen, rest + 1 );
|
||||
} else {
|
||||
sprintf( Buffer + lastlen, "[color=%6.6lX]%.*s[/color]",
|
||||
bcolor, tlen, rest + 1 );
|
||||
}
|
||||
} else {
|
||||
notmatched:
|
||||
len += ( int ) strlen( lines[i] ) + 1;
|
||||
Buffer = (char *) realloc( Buffer, len + 2 );
|
||||
memcpy( &Buffer[lastlen], lines[i], len - lastlen );
|
||||
}
|
||||
lastlen = len;
|
||||
if (i != linesize - 1) {
|
||||
Buffer[lastlen - 1] = '\n';
|
||||
Buffer[lastlen] = 0;
|
||||
}
|
||||
}
|
||||
video->SetClipRect( &clip );
|
||||
|
||||
int pos;
|
||||
|
||||
if (startrow==CurLine) {
|
||||
pos = CurPos;
|
||||
} else {
|
||||
pos = -1;
|
||||
}
|
||||
ftext->PrintFromLine( startrow, clip,
|
||||
( unsigned char * ) Buffer, palette,
|
||||
IE_FONT_ALIGN_LEFT, finit, Cursor, pos );
|
||||
free( Buffer );
|
||||
video->SetClipRect( NULL );
|
||||
//streaming text
|
||||
if (linesize>50) {
|
||||
//the buffer is filled enough
|
||||
return;
|
||||
}
|
||||
if (core->GetAudioDrv()->IsSpeaking() ) {
|
||||
//the narrator is still talking
|
||||
return;
|
||||
}
|
||||
if (RunEventHandler( TextAreaOutOfText )) {
|
||||
return;
|
||||
}
|
||||
if (linesize==lines.size()) {
|
||||
ResetEventHandler( TextAreaOutOfText );
|
||||
return;
|
||||
}
|
||||
AppendText("\n",-1);
|
||||
return;
|
||||
}
|
||||
// normal scrolling textarea
|
||||
int rc = 0;
|
||||
int sr = startrow;
|
||||
unsigned int i;
|
||||
int yl;
|
||||
for (i = 0; i < linesize; i++) {
|
||||
if (rc + lrows[i] <= sr) {
|
||||
rc += lrows[i];
|
||||
continue;
|
||||
}
|
||||
sr -= rc;
|
||||
Palette* pal = NULL;
|
||||
if (seltext == (int) i)
|
||||
pal = selected;
|
||||
else if (Value == i)
|
||||
pal = lineselpal;
|
||||
else
|
||||
pal = palette;
|
||||
ftext->PrintFromLine( sr, clip,
|
||||
( unsigned char * ) lines[i], pal,
|
||||
IE_FONT_ALIGN_LEFT, finit, NULL );
|
||||
yl = ftext->size[1].h*(lrows[i]-sr);
|
||||
clip.y+=yl;
|
||||
clip.h-=yl;
|
||||
break;
|
||||
}
|
||||
for (i++; i < linesize; i++) {
|
||||
Palette* pal = NULL;
|
||||
if (seltext == (int) i)
|
||||
pal = selected;
|
||||
else if (Value == i)
|
||||
pal = lineselpal;
|
||||
else
|
||||
pal = palette;
|
||||
ftext->Print( clip, ( unsigned char * ) lines[i], pal,
|
||||
IE_FONT_ALIGN_LEFT, true );
|
||||
yl = ftext->size[1].h*lrows[i];
|
||||
clip.y+=yl;
|
||||
clip.h-=yl;
|
||||
|
||||
}
|
||||
}
|
||||
/** Sets the Scroll Bar Pointer. If 'ptr' is NULL no Scroll Bar will be linked
|
||||
to this Text Area Control. */
|
||||
int TextArea::SetScrollBar(Control* ptr)
|
||||
{
|
||||
int ret = Control::SetScrollBar(ptr);
|
||||
CalcRowCount();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Sets the Actual Text */
|
||||
void TextArea::SetText(const char* text)
|
||||
{
|
||||
if (!text[0]) {
|
||||
Clear();
|
||||
}
|
||||
|
||||
int newlen = ( int ) strlen( text );
|
||||
|
||||
if (lines.size() == 0) {
|
||||
char* str = (char *) malloc( newlen + 1 );
|
||||
memcpy( str, text, newlen + 1 );
|
||||
lines.push_back( str );
|
||||
lrows.push_back( 0 );
|
||||
} else {
|
||||
lines[0] = (char *) realloc( lines[0], newlen + 1 );
|
||||
memcpy( lines[0], text, newlen + 1 );
|
||||
}
|
||||
CurPos = newlen;
|
||||
CurLine = lines.size()-1;
|
||||
UpdateControls();
|
||||
}
|
||||
|
||||
void TextArea::SetMinRow(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
minrow = (int) lines.size();
|
||||
} else {
|
||||
minrow = 0;
|
||||
}
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
//drop lines scrolled out at the top.
|
||||
//keeplines is the number of lines that should still be
|
||||
//preserved (for scrollback history)
|
||||
void TextArea::DiscardLines()
|
||||
{
|
||||
if (rows<=keeplines) {
|
||||
return;
|
||||
}
|
||||
int drop = rows-keeplines;
|
||||
PopLines(drop, true);
|
||||
}
|
||||
|
||||
static char *note_const = NULL;
|
||||
static const char inserted_crap[]="[/color][color=ffffff]";
|
||||
#define CRAPLENGTH sizeof(inserted_crap)-1
|
||||
|
||||
void TextArea::SetNoteString(const char *s)
|
||||
{
|
||||
free(note_const);
|
||||
if (s) {
|
||||
note_const = (char *) malloc(strlen(s)+5);
|
||||
sprintf(note_const, "\r\n\r\n%s", s);
|
||||
}
|
||||
}
|
||||
|
||||
/** Appends a String to the current Text */
|
||||
int TextArea::AppendText(const char* text, int pos)
|
||||
{
|
||||
int ret = 0;
|
||||
if (pos >= ( int ) lines.size()) {
|
||||
return -1;
|
||||
}
|
||||
int newlen = ( int ) strlen( text );
|
||||
|
||||
if (pos == -1) {
|
||||
const char *note = NULL;
|
||||
if (note_const) {
|
||||
note = strstr(text,note_const);
|
||||
}
|
||||
char *str;
|
||||
if (NULL == note) {
|
||||
str = (char *) malloc( newlen +1 );
|
||||
memcpy(str, text, newlen+1);
|
||||
}
|
||||
else {
|
||||
unsigned int notepos = (unsigned int) (note - text);
|
||||
str = (char *) malloc( newlen + CRAPLENGTH+1 );
|
||||
memcpy(str,text,notepos);
|
||||
memcpy(str+notepos,inserted_crap,CRAPLENGTH);
|
||||
memcpy(str+notepos+CRAPLENGTH, text+notepos, newlen-notepos+1);
|
||||
}
|
||||
lines.push_back( str );
|
||||
lrows.push_back( 0 );
|
||||
ret =(int) (lines.size() - 1);
|
||||
} else {
|
||||
int mylen = ( int ) strlen( lines[pos] );
|
||||
|
||||
lines[pos] = (char *) realloc( lines[pos], mylen + newlen + 1 );
|
||||
memcpy( lines[pos]+mylen, text, newlen + 1 );
|
||||
ret = pos;
|
||||
}
|
||||
|
||||
//if the textarea is not a listbox, then discard scrolled out
|
||||
//lines
|
||||
if (Flags&IE_GUI_TEXTAREA_HISTORY) {
|
||||
DiscardLines();
|
||||
}
|
||||
|
||||
UpdateControls();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Deletes last or first `count' lines */
|
||||
/** Probably not too optimal for many lines, but it isn't used */
|
||||
/** for many lines */
|
||||
void TextArea::PopLines(unsigned int count, bool top)
|
||||
{
|
||||
if (count > lines.size()) {
|
||||
count = (unsigned int) lines.size();
|
||||
}
|
||||
|
||||
while (count > 0 ) {
|
||||
if (top) {
|
||||
int tmp = lrows.front();
|
||||
if (minrow || (startrow<tmp) )
|
||||
break;
|
||||
startrow -= tmp;
|
||||
free(lines.front() );
|
||||
lines.erase(lines.begin());
|
||||
lrows.erase(lrows.begin());
|
||||
} else {
|
||||
free(lines.back() );
|
||||
lines.pop_back();
|
||||
lrows.pop_back();
|
||||
}
|
||||
count--;
|
||||
}
|
||||
UpdateControls();
|
||||
}
|
||||
|
||||
void TextArea::UpdateControls()
|
||||
{
|
||||
int pos;
|
||||
|
||||
CalcRowCount();
|
||||
Changed = true;
|
||||
if (sb) {
|
||||
ScrollBar* bar = ( ScrollBar* ) sb;
|
||||
if (Flags & IE_GUI_TEXTAREA_AUTOSCROLL)
|
||||
pos = rows - ( ( Height - 5 ) / ftext->maxHeight );
|
||||
else
|
||||
pos = 0;
|
||||
if (pos < 0)
|
||||
pos = 0;
|
||||
bar->SetPos( pos );
|
||||
} else {
|
||||
if (Flags & IE_GUI_TEXTAREA_AUTOSCROLL) {
|
||||
pos = rows - ( ( Height - 5 ) / ftext->maxHeight );
|
||||
SetRow(pos);
|
||||
}
|
||||
}
|
||||
core->RedrawAll();
|
||||
}
|
||||
|
||||
/** Sets the Fonts */
|
||||
void TextArea::SetFonts(Font* init, Font* text)
|
||||
{
|
||||
finit = init;
|
||||
ftext = text;
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
/** Key Press Event */
|
||||
void TextArea::OnKeyPress(unsigned char Key, unsigned short /*Mod*/)
|
||||
{
|
||||
if (Flags & IE_GUI_TEXTAREA_EDITABLE) {
|
||||
if (Key >= 0x20) {
|
||||
Owner->Invalidate();
|
||||
Changed = true;
|
||||
int len = GetRowLength(CurLine);
|
||||
//print("len: %d Before: %s\n",len, lines[CurLine]);
|
||||
lines[CurLine] = (char *) realloc( lines[CurLine], len + 2 );
|
||||
for (int i = len; i > CurPos; i--) {
|
||||
lines[CurLine][i] = lines[CurLine][i - 1];
|
||||
}
|
||||
lines[CurLine][CurPos] = Key;
|
||||
lines[CurLine][len + 1] = 0;
|
||||
CurPos++;
|
||||
//print("pos: %d After: %s\n",CurPos, lines[CurLine]);
|
||||
CalcRowCount();
|
||||
RunEventHandler( TextAreaOnChange );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//Selectable=false for dialogs, rather unintuitive, but fact
|
||||
if ((Flags & IE_GUI_TEXTAREA_SELECTABLE) || ( Key < '1' ) || ( Key > '9' ))
|
||||
return;
|
||||
GameControl *gc = core->GetGameControl();
|
||||
if (gc && (gc->GetDialogueFlags()&DF_IN_DIALOG) ) {
|
||||
Changed = true;
|
||||
seltext=minrow-1;
|
||||
if ((unsigned int) seltext>=lines.size()) {
|
||||
return;
|
||||
}
|
||||
for(int i=0;i<Key-'0';i++) {
|
||||
do {
|
||||
seltext++;
|
||||
if ((unsigned int) seltext>=lines.size()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (strnicmp( lines[seltext], "[s=", 3 ) != 0 );
|
||||
}
|
||||
int idx=-1;
|
||||
sscanf( lines[seltext], "[s=%d,", &idx);
|
||||
if (idx==-1) {
|
||||
//this kills this object, don't use any more data!
|
||||
gc->dialoghandler->EndDialog();
|
||||
return;
|
||||
}
|
||||
gc->dialoghandler->DialogChoose( idx );
|
||||
}
|
||||
}
|
||||
|
||||
/** Special Key Press */
|
||||
void TextArea::OnSpecialKeyPress(unsigned char Key)
|
||||
{
|
||||
int len;
|
||||
int i;
|
||||
|
||||
if (!(Flags&IE_GUI_TEXTAREA_EDITABLE)) {
|
||||
return;
|
||||
}
|
||||
Owner->Invalidate();
|
||||
Changed = true;
|
||||
switch (Key) {
|
||||
case GEM_HOME:
|
||||
CurPos = 0;
|
||||
CurLine = 0;
|
||||
break;
|
||||
case GEM_UP:
|
||||
if (CurLine) {
|
||||
CurLine--;
|
||||
}
|
||||
break;
|
||||
case GEM_DOWN:
|
||||
if (CurLine<lines.size()) {
|
||||
CurLine++;
|
||||
}
|
||||
break;
|
||||
case GEM_END:
|
||||
CurLine=lines.size()-1;
|
||||
CurPos = GetRowLength((unsigned int) CurLine);
|
||||
break;
|
||||
case GEM_LEFT:
|
||||
if (CurPos > 0) {
|
||||
CurPos--;
|
||||
} else {
|
||||
if (CurLine) {
|
||||
CurLine--;
|
||||
CurPos = GetRowLength(CurLine);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GEM_RIGHT:
|
||||
len = GetRowLength(CurLine);
|
||||
if (CurPos < len) {
|
||||
CurPos++;
|
||||
} else {
|
||||
if(CurLine<lines.size()) {
|
||||
CurPos=0;
|
||||
CurLine++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GEM_DELETE:
|
||||
len = GetRowLength(CurLine);
|
||||
//print("len: %d Before: %s\n",len, lines[CurLine]);
|
||||
if (CurPos>=len) {
|
||||
//TODO: merge next line
|
||||
break;
|
||||
}
|
||||
lines[CurLine] = (char *) realloc( lines[CurLine], len );
|
||||
for (i = CurPos; i < len; i++) {
|
||||
lines[CurLine][i] = lines[CurLine][i + 1];
|
||||
}
|
||||
//print("pos: %d After: %s\n",CurPos, lines[CurLine]);
|
||||
break;
|
||||
case GEM_BACKSP:
|
||||
len = GetRowLength(CurLine);
|
||||
if (CurPos != 0) {
|
||||
//print("len: %d Before: %s\n",len, lines[CurLine]);
|
||||
if (len<1) {
|
||||
break;
|
||||
}
|
||||
lines[CurLine] = (char *) realloc( lines[CurLine], len );
|
||||
for (i = CurPos; i < len; i++) {
|
||||
lines[CurLine][i - 1] = lines[CurLine][i];
|
||||
}
|
||||
lines[CurLine][len - 1] = 0;
|
||||
CurPos--;
|
||||
//print("pos: %d After: %s\n",CurPos, lines[CurLine]);
|
||||
} else {
|
||||
if (CurLine) {
|
||||
//TODO: merge lines
|
||||
int oldline = CurLine;
|
||||
CurLine--;
|
||||
int old = GetRowLength(CurLine);
|
||||
//print("len: %d Before: %s\n",old, lines[CurLine]);
|
||||
//print("len: %d Before: %s\n",len, lines[oldline]);
|
||||
lines[CurLine] = (char *) realloc (lines[CurLine], len+old);
|
||||
memcpy(lines[CurLine]+old, lines[oldline],len);
|
||||
free(lines[oldline]);
|
||||
lines[CurLine][old+len]=0;
|
||||
lines.erase(lines.begin()+oldline);
|
||||
lrows.erase(lrows.begin()+oldline);
|
||||
CurPos = old;
|
||||
//print("pos: %d len: %d After: %s\n",CurPos, GetRowLength(CurLine), lines[CurLine]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GEM_RETURN:
|
||||
//add an empty line after CurLine
|
||||
//print("pos: %d Before: %s\n",CurPos, lines[CurLine]);
|
||||
lrows.insert(lrows.begin()+CurLine, 0);
|
||||
len = GetRowLength(CurLine);
|
||||
//copy the text after the cursor into the new line
|
||||
char *str = (char *) malloc(len-CurPos+2);
|
||||
memcpy(str, lines[CurLine]+CurPos, len-CurPos+1);
|
||||
str[len-CurPos+1] = 0;
|
||||
lines.insert(lines.begin()+CurLine+1, str);
|
||||
//truncate the current line
|
||||
lines[CurLine] = (char *) realloc (lines[CurLine], CurPos+1);
|
||||
lines[CurLine][CurPos]=0;
|
||||
//move cursor to next line beginning
|
||||
CurLine++;
|
||||
CurPos=0;
|
||||
//print("len: %d After: %s\n",GetRowLength(CurLine-1), lines[CurLine-1]);
|
||||
//print("len: %d After: %s\n",GetRowLength(CurLine), lines[CurLine]);
|
||||
break;
|
||||
}
|
||||
CalcRowCount();
|
||||
RunEventHandler( TextAreaOnChange );
|
||||
}
|
||||
|
||||
/** Returns Row count */
|
||||
int TextArea::GetRowCount()
|
||||
{
|
||||
return ( int ) lines.size();
|
||||
}
|
||||
|
||||
int TextArea::GetRowLength(unsigned int row)
|
||||
{
|
||||
if (lines.size()<=row) {
|
||||
return 0;
|
||||
}
|
||||
//this is just roughly the line size, escape sequences need to be removed
|
||||
return strlen( lines[row] );
|
||||
}
|
||||
|
||||
int TextArea::GetVisibleRowCount()
|
||||
{
|
||||
return (Height-5) / ftext->maxHeight;
|
||||
}
|
||||
|
||||
/** Returns top index */
|
||||
int TextArea::GetTopIndex()
|
||||
{
|
||||
return startrow;
|
||||
}
|
||||
|
||||
/** Set Starting Row */
|
||||
void TextArea::SetRow(int row)
|
||||
{
|
||||
if (row < rows) {
|
||||
startrow = row;
|
||||
}
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
void TextArea::CalcRowCount()
|
||||
{
|
||||
int tr;
|
||||
int w = Width;
|
||||
|
||||
if (Flags&IE_GUI_TEXTAREA_SPEAKER) {
|
||||
const char *portrait = NULL;
|
||||
Actor *actor = NULL;
|
||||
GameControl *gc = core->GetGameControl();
|
||||
if (gc) {
|
||||
Scriptable *target = gc->dialoghandler->GetTarget();
|
||||
if (target && target->Type == ST_ACTOR) {
|
||||
actor = (Actor *)target;
|
||||
}
|
||||
}
|
||||
if (actor) {
|
||||
portrait = actor->GetPortrait(1);
|
||||
}
|
||||
if (portrait) {
|
||||
RefreshSprite(portrait);
|
||||
}
|
||||
if (AnimPicture) {
|
||||
w-=AnimPicture->Width;
|
||||
}
|
||||
}
|
||||
|
||||
rows = 0;
|
||||
if (lines.size() != 0) {
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
// rows++;
|
||||
tr = 0;
|
||||
int len = ( int ) strlen( lines[i] );
|
||||
char* tmp = (char *) malloc( len + 1 );
|
||||
memcpy( tmp, lines[i], len + 1 );
|
||||
ftext->SetupString( tmp, w );
|
||||
for (int p = 0; p <= len; p++) {
|
||||
if (( ( unsigned char ) tmp[p] ) == '[') {
|
||||
p++;
|
||||
//char tag[256];
|
||||
int k = 0;
|
||||
for (k = 0; k < 256; k++) {
|
||||
if (tmp[p] == ']') {
|
||||
//tag[k] = 0;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
//tag[k] = tmp[p++];
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
if (tmp[p] == 0) {
|
||||
// if (p != len)
|
||||
// rows++;
|
||||
tr++;
|
||||
}
|
||||
}
|
||||
lrows[i] = tr;
|
||||
rows += tr;
|
||||
free( tmp );
|
||||
}
|
||||
}
|
||||
|
||||
if (lines.size())
|
||||
{
|
||||
if (CurLine>=lines.size()) {
|
||||
CurLine=lines.size()-1;
|
||||
}
|
||||
w = strlen(lines[CurLine]);
|
||||
if (CurPos>w) {
|
||||
CurPos = w;
|
||||
}
|
||||
} else {
|
||||
CurLine=0;
|
||||
CurPos=0;
|
||||
}
|
||||
|
||||
if (!sb) {
|
||||
return;
|
||||
}
|
||||
ScrollBar* bar = ( ScrollBar* ) sb;
|
||||
tr = rows - Height/ftext->size[1].h + 1;
|
||||
if (tr<0) {
|
||||
tr = 0;
|
||||
}
|
||||
bar->SetMax( (ieWord) tr );
|
||||
}
|
||||
/** Mouse Over Event */
|
||||
void TextArea::OnMouseOver(unsigned short /*x*/, unsigned short y)
|
||||
{
|
||||
int height = ftext->maxHeight; //size[1].h;
|
||||
int r = y / height;
|
||||
int row = 0;
|
||||
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
row += lrows[i];
|
||||
if (r < ( row - startrow )) {
|
||||
if (seltext != (int) i)
|
||||
core->RedrawAll();
|
||||
seltext = ( int ) i;
|
||||
//print("CtrlId = 0x%08lx, seltext = %d, rows = %d, row = %d, r = %d\n", ControlID, i, rows, row, r);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (seltext != -1) {
|
||||
core->RedrawAll();
|
||||
}
|
||||
seltext = -1;
|
||||
//print("CtrlId = 0x%08lx, seltext = %d, rows %d, row %d, r = %d\n", ControlID, seltext, rows, row, r);
|
||||
}
|
||||
|
||||
/** Mouse Button Up */
|
||||
void TextArea::OnMouseUp(unsigned short x, unsigned short y, unsigned short /*Button*/,
|
||||
unsigned short /*Mod*/)
|
||||
{
|
||||
if (( x <= Width ) && ( y <= ( Height - 5 ) ) && ( seltext != -1 )) {
|
||||
Value = (unsigned int) seltext;
|
||||
Changed = true;
|
||||
if (strnicmp( lines[seltext], "[s=", 3 ) == 0) {
|
||||
if (minrow > seltext)
|
||||
return;
|
||||
int idx;
|
||||
sscanf( lines[seltext], "[s=%d,", &idx );
|
||||
GameControl* gc = core->GetGameControl();
|
||||
if (gc && (gc->GetDialogueFlags()&DF_IN_DIALOG) ) {
|
||||
if (idx==-1) {
|
||||
//this kills this object, don't use any more data!
|
||||
gc->dialoghandler->EndDialog();
|
||||
return;
|
||||
}
|
||||
gc->dialoghandler->DialogChoose( idx );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (VarName[0] != 0) {
|
||||
core->GetDictionary()->SetAt( VarName, Value );
|
||||
}
|
||||
RunEventHandler( TextAreaOnChange );
|
||||
}
|
||||
|
||||
void TextArea::SetText(const std::vector<char*>& text)
|
||||
{
|
||||
Clear();
|
||||
for (size_t i = 0; i < text.size(); i++) {
|
||||
int newlen = strlen(text[i]);
|
||||
char* str = (char *) malloc(newlen + 1);
|
||||
memcpy(str, text[i], newlen + 1);
|
||||
lines.push_back(str);
|
||||
lrows.push_back(0);
|
||||
CurPos = newlen;
|
||||
}
|
||||
CurLine = lines.size() - 1;
|
||||
UpdateControls();
|
||||
}
|
||||
|
||||
/** Copies the current TextArea content to another TextArea control */
|
||||
void TextArea::CopyTo(TextArea *ta)
|
||||
{
|
||||
ta->SetText(lines);
|
||||
}
|
||||
|
||||
void TextArea::RedrawTextArea(const char* VariableName, unsigned int Sum)
|
||||
{
|
||||
if (strnicmp( VarName, VariableName, MAX_VARIABLE_LENGTH )) {
|
||||
return;
|
||||
}
|
||||
Value = Sum;
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
void TextArea::SelectText(const char *select)
|
||||
{
|
||||
int i = lines.size();
|
||||
while(i--) {
|
||||
if (!stricmp(lines[i], select) ) {
|
||||
CurLine = i;
|
||||
if (sb) {
|
||||
ScrollBar* bar = ( ScrollBar* ) sb;
|
||||
bar->SetPos( i );
|
||||
} else {
|
||||
SetRow( i );
|
||||
}
|
||||
RedrawTextArea( VarName, i);
|
||||
CalcRowCount();
|
||||
Owner->Invalidate();
|
||||
core->RedrawAll();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* TextArea::QueryText()
|
||||
{
|
||||
if ( Value<lines.size() ) {
|
||||
return ( const char * ) lines[Value];
|
||||
}
|
||||
return ( const char *) "";
|
||||
}
|
||||
|
||||
bool TextArea::SetEvent(int eventType, EventHandler handler)
|
||||
{
|
||||
Changed = true;
|
||||
|
||||
switch (eventType) {
|
||||
case IE_GUI_TEXTAREA_ON_CHANGE:
|
||||
TextAreaOnChange = handler;
|
||||
break;
|
||||
case IE_GUI_TEXTAREA_OUT_OF_TEXT:
|
||||
TextAreaOutOfText = handler;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextArea::PadMinRow()
|
||||
{
|
||||
int row = 0;
|
||||
int i=(int) (lines.size()-1);
|
||||
//minrow -1 ->gap
|
||||
//minrow -2 ->npc text
|
||||
while (i>=minrow-2 && i>=0) {
|
||||
row+=lrows[i];
|
||||
i--;
|
||||
}
|
||||
row = GetVisibleRowCount()-row;
|
||||
while (row>0) {
|
||||
AppendText("",-1);
|
||||
row--;
|
||||
}
|
||||
}
|
||||
|
||||
void TextArea::SetPreservedRow(int arg)
|
||||
{
|
||||
keeplines=arg;
|
||||
Flags |= IE_GUI_TEXTAREA_HISTORY;
|
||||
}
|
||||
|
||||
void TextArea::Clear()
|
||||
{
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
free( lines[i] );
|
||||
}
|
||||
lines.clear();
|
||||
lrows.clear();
|
||||
rows = 0;
|
||||
}
|
||||
|
||||
//setting up the textarea for smooth scrolling, the first
|
||||
//TEXTAREA_OUTOFTEXT callback is called automatically
|
||||
void TextArea::SetupScroll(unsigned long tck)
|
||||
{
|
||||
SetPreservedRow(0);
|
||||
smooth = ftext->maxHeight;
|
||||
startrow = 0;
|
||||
ticks = tck;
|
||||
//clearing the textarea
|
||||
Clear();
|
||||
unsigned int i = (unsigned int) (Height/smooth);
|
||||
while (i--) {
|
||||
char *str = (char *) malloc(1);
|
||||
str[0]=0;
|
||||
lines.push_back(str);
|
||||
lrows.push_back(0);
|
||||
}
|
||||
i = (unsigned int) lines.size();
|
||||
Flags |= IE_GUI_TEXTAREA_SMOOTHSCROLL;
|
||||
starttime = GetTickCount();
|
||||
if (RunEventHandler( TextAreaOutOfText )) {
|
||||
//event handler destructed this object?
|
||||
return;
|
||||
}
|
||||
if (i==lines.size()) {
|
||||
ResetEventHandler( TextAreaOutOfText );
|
||||
return;
|
||||
}
|
||||
//recalculates rows
|
||||
AppendText("\n",-1);
|
||||
}
|
||||
|
||||
void TextArea::OnMouseDown(unsigned short /*x*/, unsigned short /*y*/, unsigned short Button,
|
||||
unsigned short /*Mod*/)
|
||||
{
|
||||
|
||||
ScrollBar* scrlbr = (ScrollBar*) sb;
|
||||
|
||||
if (!scrlbr) {
|
||||
Control *ctrl = Owner->GetScrollControl();
|
||||
if (ctrl && (ctrl->ControlType == IE_GUI_SCROLLBAR)) {
|
||||
scrlbr = (ScrollBar *) ctrl;
|
||||
}
|
||||
}
|
||||
if (scrlbr) {
|
||||
switch(Button) {
|
||||
case GEM_MB_SCRLUP:
|
||||
scrlbr->ScrollUp();
|
||||
core->RedrawAll();
|
||||
break;
|
||||
case GEM_MB_SCRLDOWN:
|
||||
scrlbr->ScrollDown();
|
||||
core->RedrawAll();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file TextArea.h
|
||||
* Declares TextArea widget for displaying long paragraphs of text
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
#ifndef TEXTAREA_H
|
||||
#define TEXTAREA_H
|
||||
|
||||
#include "GUI/Control.h"
|
||||
#include "GUI/ScrollBar.h"
|
||||
|
||||
#include "RGBAColor.h"
|
||||
#include "exports.h"
|
||||
|
||||
#include "Font.h"
|
||||
|
||||
// Keep these synchronized with GUIDefines.py
|
||||
// 0x05 is the control type of TextArea
|
||||
#define IE_GUI_TEXTAREA_ON_CHANGE 0x05000000
|
||||
#define IE_GUI_TEXTAREA_OUT_OF_TEXT 0x05000001
|
||||
|
||||
// TextArea flags, keep these in sync too
|
||||
// the control type is intentionally left out
|
||||
#define IE_GUI_TEXTAREA_SELECTABLE 1
|
||||
#define IE_GUI_TEXTAREA_AUTOSCROLL 2
|
||||
#define IE_GUI_TEXTAREA_SMOOTHSCROLL 4
|
||||
#define IE_GUI_TEXTAREA_HISTORY 8
|
||||
#define IE_GUI_TEXTAREA_SPEAKER 16
|
||||
#define IE_GUI_TEXTAREA_ALT_FONT 32 //this one disables drop capitals
|
||||
#define IE_GUI_TEXTAREA_EDITABLE 64
|
||||
|
||||
// internal flags
|
||||
#define TA_INITIALS 1
|
||||
#define TA_BITEMYTAIL 2
|
||||
|
||||
/**
|
||||
* @class TextArea
|
||||
* Widget capable of displaying long paragraphs of text.
|
||||
* It is usually scrolled with a ScrollBar widget
|
||||
*/
|
||||
|
||||
class GEM_EXPORT TextArea : public Control {
|
||||
public:
|
||||
TextArea(Color hitextcolor, Color initcolor, Color lowtextcolor);
|
||||
~TextArea(void);
|
||||
/** global configuration */
|
||||
static void SetNoteString(const char *s);
|
||||
/** Draws the Control on the Output Display */
|
||||
void Draw(unsigned short x, unsigned short y);
|
||||
/** Set the TextArea value to the line number containing the string parameter */
|
||||
void SelectText(const char *select);
|
||||
/** Sets the Actual Text */
|
||||
void SetText(const char* text);
|
||||
/** Sets text */
|
||||
void SetText(const std::vector<char*>& text);
|
||||
/** Clears the textarea */
|
||||
void Clear();
|
||||
/** Discards scrolled out lines from the textarea */
|
||||
/** preserving 'keeplines' lines for scroll back history */
|
||||
void DiscardLines();
|
||||
/** Appends a String to the current Text */
|
||||
int AppendText(const char* text, int pos = 0);
|
||||
/** Deletes `count' lines (either last or top lines)*/
|
||||
void PopLines(unsigned int count, bool top = false);
|
||||
/** Deletes last lines up to current 'minrow' */
|
||||
void PopMinRow()
|
||||
{
|
||||
PopLines((unsigned int) (lines.size()-minrow));
|
||||
}
|
||||
/** adds empty lines so minrow will be the uppermost visible row */
|
||||
void PadMinRow();
|
||||
/** Sets up scrolling, tck is the scrolling speed */
|
||||
void SetupScroll(unsigned long tck);
|
||||
/** Sets the Fonts */
|
||||
void SetFonts(Font* init, Font* text);
|
||||
/** Returns Number of Rows */
|
||||
int GetRowCount();
|
||||
/** Returns the length of a Row */
|
||||
int GetRowLength(unsigned int row);
|
||||
/** Returns Number of Visible Rows */
|
||||
int GetVisibleRowCount();
|
||||
/** Returns Starting Row */
|
||||
int GetTopIndex();
|
||||
/** Set Starting Row */
|
||||
void SetRow(int row);
|
||||
/** Sets preserved lines */
|
||||
void SetPreservedRow(int arg);
|
||||
/** Set Selectable */
|
||||
void SetSelectable(bool val);
|
||||
/** Set Minimum Selectable Row (to the current ceiling) */
|
||||
void SetMinRow(bool enable);
|
||||
/** Copies the current TextArea content to another TextArea control */
|
||||
void CopyTo(TextArea* ta);
|
||||
/** Returns the selected text */
|
||||
const char* QueryText();
|
||||
/** Marks textarea for redraw with a new value */
|
||||
void RedrawTextArea(const char* VariableName, unsigned int Sum);
|
||||
int SetScrollBar(Control *ptr);
|
||||
private: // Private attributes
|
||||
std::vector< char*> lines;
|
||||
std::vector< int> lrows;
|
||||
int seltext;
|
||||
/** minimum selectable row */
|
||||
int minrow;
|
||||
/** lines to be kept even if scrolled out */
|
||||
int keeplines;
|
||||
/** vertical offset for smooth scrolling */
|
||||
int smooth;
|
||||
/** timer for scrolling */
|
||||
unsigned long starttime;
|
||||
/** timer ticks for scrolling (speed) */
|
||||
unsigned long ticks;
|
||||
/** Number of Text Rows */
|
||||
int rows;
|
||||
/** Starting Row */
|
||||
int startrow;
|
||||
/** Text Colors */
|
||||
Palette* palette;
|
||||
Palette* initpalette;
|
||||
Palette* selected;
|
||||
Palette* lineselpal;
|
||||
/** a hack for smooth windows, drop capitals */
|
||||
ieDword InternalFlags;
|
||||
/** Fonts */
|
||||
Font* finit, * ftext;
|
||||
ieResRef PortraitResRef;
|
||||
|
||||
/** Text Editing Cursor Sprite */
|
||||
Sprite2D* Cursor;
|
||||
unsigned short CurPos, CurLine;
|
||||
|
||||
private: //internal functions
|
||||
void CalcRowCount();
|
||||
void UpdateControls();
|
||||
void RefreshSprite(const char *portrait);
|
||||
|
||||
public: //Events
|
||||
/** Key Press Event */
|
||||
void OnKeyPress(unsigned char Key, unsigned short Mod);
|
||||
/** Special Key Press */
|
||||
void OnSpecialKeyPress(unsigned char Key);
|
||||
/** Mouse Over Event */
|
||||
void OnMouseOver(unsigned short x, unsigned short y);
|
||||
/** Mouse Button Up */
|
||||
void OnMouseUp(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Mouse button down*/
|
||||
void OnMouseDown(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Set handler for specified event */
|
||||
bool SetEvent(int eventType, EventHandler handler);
|
||||
/** OnChange Scripted Event Function Name */
|
||||
EventHandler TextAreaOnChange;
|
||||
/** OutOfText Scripted Event Function Name */
|
||||
EventHandler TextAreaOutOfText;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,241 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "GUI/TextEdit.h"
|
||||
|
||||
#include "GameData.h"
|
||||
#include "Interface.h"
|
||||
#include "Palette.h"
|
||||
#include "Video.h"
|
||||
#include "GUI/EventMgr.h"
|
||||
#include "GUI/Window.h"
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
# include "SDL_uikitkeyboard.h"
|
||||
#endif
|
||||
|
||||
TextEdit::TextEdit(unsigned short maxLength, unsigned short px, unsigned short py)
|
||||
{
|
||||
max = maxLength;
|
||||
FontPosX = px;
|
||||
FontPosY = py;
|
||||
Buffer = ( unsigned char * ) malloc( max + 1 );
|
||||
font = NULL;
|
||||
Cursor = NULL;
|
||||
Back = NULL;
|
||||
CurPos = 0;
|
||||
Buffer[0] = 0;
|
||||
ResetEventHandler( EditOnChange );
|
||||
ResetEventHandler( EditOnDone );
|
||||
ResetEventHandler( EditOnCancel );
|
||||
Color white = {0xff, 0xff, 0xff, 0x00}, black = {0x00, 0x00, 0x00, 0x00};
|
||||
//Original engine values
|
||||
//Color white = {0xc8, 0xc8, 0xc8, 0x00}, black = {0x3c, 0x3c, 0x3c, 0x00};
|
||||
palette = core->CreatePalette( white, black );
|
||||
}
|
||||
|
||||
TextEdit::~TextEdit(void)
|
||||
{
|
||||
Video *video = core->GetVideoDriver();
|
||||
gamedata->FreePalette( palette );
|
||||
free( Buffer );
|
||||
video->FreeSprite( Back );
|
||||
video->FreeSprite( Cursor );
|
||||
}
|
||||
|
||||
/** Draws the Control on the Output Display */
|
||||
void TextEdit::Draw(unsigned short x, unsigned short y)
|
||||
{
|
||||
if (!Changed && !(Owner->Flags&WF_FLOAT)) {
|
||||
return;
|
||||
}
|
||||
Changed = false;
|
||||
if (Back) {
|
||||
core->GetVideoDriver()->BlitSprite( Back, x + XPos, y + YPos, true );
|
||||
|
||||
}
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
//The aligning of textedit fields is done by absolute positioning (FontPosX, FontPosY)
|
||||
if (hasFocus) {
|
||||
#if TARGET_OS_IPHONE
|
||||
SDL_iPhoneKeyboardShow(SDL_GetWindowFromID(1));
|
||||
#endif
|
||||
font->Print( Region( x + XPos + FontPosX, y + YPos + FontPosY, Width, Height ), Buffer,
|
||||
palette, IE_FONT_ALIGN_LEFT | IE_FONT_ALIGN_TOP,
|
||||
true, NULL, Cursor, CurPos );
|
||||
} else {
|
||||
font->Print( Region( x + XPos + FontPosX, y + YPos + FontPosY, Width, Height ), Buffer,
|
||||
palette, IE_FONT_ALIGN_LEFT | IE_FONT_ALIGN_TOP, true );
|
||||
}
|
||||
}
|
||||
|
||||
/** Set Font */
|
||||
void TextEdit::SetFont(Font* f)
|
||||
{
|
||||
if (f != NULL) {
|
||||
font = f;
|
||||
Changed = true;
|
||||
return;
|
||||
}
|
||||
printMessage("TextEdit","Invalid font set!\n", LIGHT_RED);
|
||||
}
|
||||
|
||||
Font *TextEdit::GetFont() { return font; }
|
||||
|
||||
/** Set Cursor */
|
||||
void TextEdit::SetCursor(Sprite2D* cur)
|
||||
{
|
||||
core->GetVideoDriver()->FreeSprite( Cursor );
|
||||
if (cur != NULL) {
|
||||
Cursor = cur;
|
||||
}
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
/** Set BackGround */
|
||||
void TextEdit::SetBackGround(Sprite2D* back)
|
||||
{
|
||||
//if 'back' is NULL then no BackGround will be drawn
|
||||
if (Back)
|
||||
core->GetVideoDriver()->FreeSprite(Back);
|
||||
Back = back;
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
/** Key Press Event */
|
||||
void TextEdit::OnKeyPress(unsigned char Key, unsigned short /*Mod*/)
|
||||
{
|
||||
if (Key >= 0x20) {
|
||||
if (Value && ( (Key<'0') || (Key>'9') ) )
|
||||
return;
|
||||
Owner->Invalidate();
|
||||
Changed = true;
|
||||
int len = ( int ) strlen( ( char* ) Buffer );
|
||||
if (len + 1 < max) {
|
||||
for (int i = len; i > CurPos; i--) {
|
||||
Buffer[i] = Buffer[i - 1];
|
||||
}
|
||||
Buffer[CurPos] = Key;
|
||||
Buffer[len + 1] = 0;
|
||||
CurPos++;
|
||||
}
|
||||
RunEventHandler( EditOnChange );
|
||||
}
|
||||
}
|
||||
/** Special Key Press */
|
||||
void TextEdit::OnSpecialKeyPress(unsigned char Key)
|
||||
{
|
||||
int len;
|
||||
|
||||
Owner->Invalidate();
|
||||
Changed = true;
|
||||
switch (Key) {
|
||||
case GEM_HOME:
|
||||
CurPos = 0;
|
||||
break;
|
||||
case GEM_END:
|
||||
CurPos = (ieWord) strlen( (char * ) Buffer);
|
||||
break;
|
||||
case GEM_LEFT:
|
||||
if (CurPos > 0)
|
||||
CurPos--;
|
||||
break;
|
||||
case GEM_RIGHT:
|
||||
len = ( int ) strlen( ( char * ) Buffer );
|
||||
if (CurPos < len) {
|
||||
CurPos++;
|
||||
}
|
||||
break;
|
||||
case GEM_DELETE:
|
||||
len = ( int ) strlen( ( char * ) Buffer );
|
||||
if (CurPos < len) {
|
||||
for (int i = CurPos; i < len; i++) {
|
||||
Buffer[i] = Buffer[i + 1];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GEM_BACKSP:
|
||||
if (CurPos != 0) {
|
||||
int len = ( int ) strlen( ( char* ) Buffer );
|
||||
for (int i = CurPos; i < len; i++) {
|
||||
Buffer[i - 1] = Buffer[i];
|
||||
}
|
||||
Buffer[len - 1] = 0;
|
||||
CurPos--;
|
||||
}
|
||||
break;
|
||||
case GEM_RETURN:
|
||||
RunEventHandler( EditOnDone );
|
||||
return;
|
||||
|
||||
}
|
||||
RunEventHandler( EditOnChange );
|
||||
}
|
||||
|
||||
/** Sets the Text of the current control */
|
||||
void TextEdit::SetText(const char* string)
|
||||
{
|
||||
strncpy( ( char * ) Buffer, string, max );
|
||||
Buffer[max]=0;
|
||||
CurPos = (ieWord) strlen((char *) Buffer);
|
||||
if (Owner) {
|
||||
Owner->Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void TextEdit::SetBufferLength(ieWord buflen)
|
||||
{
|
||||
if(buflen<1) return;
|
||||
if(buflen!=max) {
|
||||
Buffer = (unsigned char *) realloc(Buffer, buflen+1);
|
||||
max=(ieWord) buflen;
|
||||
Buffer[max]=0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Simply returns the pointer to the text, don't modify it! */
|
||||
const char* TextEdit::QueryText()
|
||||
{
|
||||
return ( const char * ) Buffer;
|
||||
}
|
||||
|
||||
bool TextEdit::SetEvent(int eventType, EventHandler handler)
|
||||
{
|
||||
Changed = true;
|
||||
|
||||
switch (eventType) {
|
||||
case IE_GUI_EDIT_ON_CHANGE:
|
||||
EditOnChange = handler;
|
||||
break;
|
||||
case IE_GUI_EDIT_ON_DONE:
|
||||
EditOnDone = handler;
|
||||
break;
|
||||
case IE_GUI_EDIT_ON_CANCEL:
|
||||
EditOnCancel = handler;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file TextEdit.h
|
||||
* Declares TextEdit widget for displaying single line text input field
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
#ifndef TEXTEDIT_H
|
||||
#define TEXTEDIT_H
|
||||
|
||||
#include "GUI/Control.h"
|
||||
|
||||
#include "RGBAColor.h"
|
||||
#include "exports.h"
|
||||
|
||||
#include "Font.h"
|
||||
|
||||
class Palette;
|
||||
|
||||
// !!! Keep these synchronized with GUIDefines.py
|
||||
#define IE_GUI_EDIT_ON_CHANGE 0x03000000
|
||||
#define IE_GUI_EDIT_ON_DONE 0x03000001
|
||||
#define IE_GUI_EDIT_ON_CANCEL 0x03000002
|
||||
|
||||
//this is stored in 'Value' of Control class
|
||||
#define IE_GUI_EDIT_NUMBER 1
|
||||
|
||||
/**
|
||||
* @class TextEdit
|
||||
* Widget displaying single line text input field
|
||||
*/
|
||||
|
||||
class GEM_EXPORT TextEdit : public Control {
|
||||
public:
|
||||
TextEdit(unsigned short maxLength, unsigned short x, unsigned short y);
|
||||
~TextEdit(void);
|
||||
/** Draws the Control on the Output Display */
|
||||
void Draw(unsigned short x, unsigned short y);
|
||||
/** Set Font */
|
||||
void SetFont(Font* f);
|
||||
Font *GetFont();
|
||||
/** Set Cursor */
|
||||
void SetCursor(Sprite2D* cur);
|
||||
/** Set BackGround */
|
||||
void SetBackGround(Sprite2D* back);
|
||||
/** Sets the Text of the current control */
|
||||
void SetText(const char* string);
|
||||
/** Sets the Text of the current control */
|
||||
const char* QueryText();
|
||||
/** Sets the buffer length */
|
||||
void SetBufferLength(ieWord buflen);
|
||||
private:
|
||||
/** Text Editing Cursor Sprite */
|
||||
Sprite2D* Cursor;
|
||||
/** Text Font */
|
||||
Font* font;
|
||||
/** Background */
|
||||
Sprite2D* Back;
|
||||
/** Max Edit Text Length */
|
||||
unsigned short max;
|
||||
/** Client area position */
|
||||
unsigned short FontPosX, FontPosY;
|
||||
/** Text Buffer */
|
||||
unsigned char* Buffer;
|
||||
/** Cursor Position */
|
||||
unsigned short CurPos;
|
||||
/** Color Palette */
|
||||
Palette* palette;
|
||||
public: //Events
|
||||
/** Key Press Event */
|
||||
void OnKeyPress(unsigned char Key, unsigned short Mod);
|
||||
/** Special Key Press */
|
||||
void OnSpecialKeyPress(unsigned char Key);
|
||||
/** Set handler for specified event */
|
||||
bool SetEvent(int eventType, EventHandler handler);
|
||||
/** OnChange Scripted Event Function Name */
|
||||
EventHandler EditOnChange;
|
||||
EventHandler EditOnDone;
|
||||
EventHandler EditOnCancel;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,443 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GUI/Window.h"
|
||||
|
||||
#include "GUI/Button.h"
|
||||
#include "GUI/Control.h"
|
||||
#include "GUI/MapControl.h"
|
||||
#include "GUI/Progressbar.h"
|
||||
#include "GUI/ScrollBar.h"
|
||||
#include "GUI/Slider.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "Interface.h"
|
||||
#include "Video.h"
|
||||
|
||||
Window::Window(unsigned short WindowID, unsigned short XPos,
|
||||
unsigned short YPos, unsigned short Width, unsigned short Height)
|
||||
{
|
||||
this->WindowID = WindowID;
|
||||
this->XPos = XPos;
|
||||
this->YPos = YPos;
|
||||
this->Width = Width;
|
||||
this->Height = Height;
|
||||
this->BackGround = NULL;
|
||||
lastC = NULL;
|
||||
lastFocus = NULL;
|
||||
lastMouseFocus = NULL;
|
||||
lastOver = NULL;
|
||||
Visible = WINDOW_INVISIBLE;
|
||||
Flags = WF_CHANGED;
|
||||
Cursor = IE_CURSOR_NORMAL;
|
||||
DefaultControl[0] = -1;
|
||||
DefaultControl[1] = -1;
|
||||
ScrollControl = -1;
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
{
|
||||
std::vector< Control*>::iterator m = Controls.begin();
|
||||
while (Controls.size() != 0) {
|
||||
Control* ctrl = ( *m );
|
||||
delete ctrl;
|
||||
Controls.erase( m );
|
||||
m = Controls.begin();
|
||||
}
|
||||
core->GetVideoDriver()->FreeSprite( BackGround );
|
||||
BackGround = NULL;
|
||||
}
|
||||
/** Add a Control in the Window */
|
||||
void Window::AddControl(Control* ctrl)
|
||||
{
|
||||
if (ctrl == NULL) {
|
||||
return;
|
||||
}
|
||||
ctrl->Owner = this;
|
||||
for (size_t i = 0; i < Controls.size(); i++) {
|
||||
if (Controls[i]->ControlID == ctrl->ControlID) {
|
||||
delete( Controls[i] );
|
||||
Controls[i] = ctrl;
|
||||
Invalidate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
Controls.push_back( ctrl );
|
||||
Invalidate();
|
||||
}
|
||||
/** Set the Window's BackGround Image. If 'img' is NULL, no background will be set. If the 'clean' parameter is true (default is false) the old background image will be deleted. */
|
||||
void Window::SetBackGround(Sprite2D* img, bool clean)
|
||||
{
|
||||
if (clean && BackGround) {
|
||||
core->GetVideoDriver()->FreeSprite( this->BackGround );
|
||||
}
|
||||
BackGround = img;
|
||||
Invalidate();
|
||||
}
|
||||
/** This function Draws the Window on the Output Screen */
|
||||
void Window::DrawWindow()
|
||||
{
|
||||
Video* video = core->GetVideoDriver();
|
||||
Region clip( XPos, YPos, Width, Height );
|
||||
//Frame && Changed
|
||||
if ( (Flags & (WF_FRAME|WF_CHANGED) )== (WF_FRAME|WF_CHANGED) ) {
|
||||
Region screen( 0, 0, core->Width, core->Height );
|
||||
video->SetClipRect( NULL );
|
||||
//removed this?
|
||||
Color black = { 0, 0, 0, 255 };
|
||||
video->DrawRect( screen, black );
|
||||
if (core->WindowFrames[0])
|
||||
video->BlitSprite( core->WindowFrames[0], 0, 0, true );
|
||||
if (core->WindowFrames[1])
|
||||
video->BlitSprite( core->WindowFrames[1], core->Width - core->WindowFrames[1]->Width, 0, true );
|
||||
if (core->WindowFrames[2])
|
||||
video->BlitSprite( core->WindowFrames[2], (core->Width - core->WindowFrames[2]->Width) / 2, 0, true );
|
||||
if (core->WindowFrames[3])
|
||||
video->BlitSprite( core->WindowFrames[3], (core->Width - core->WindowFrames[3]->Width) / 2, core->Height - core->WindowFrames[3]->Height, true );
|
||||
} else if (clip_regions.size()) {
|
||||
// clip drawing (we only do Background right now) for InvalidateForControl
|
||||
for (unsigned int i = 0; i < clip_regions.size(); i++) {
|
||||
Region to_clip = clip_regions[i];
|
||||
to_clip.x += XPos;
|
||||
to_clip.y += YPos;
|
||||
video->SetClipRect(&to_clip);
|
||||
if (BackGround) {
|
||||
video->BlitSprite( BackGround, XPos, YPos, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
clip_regions.clear();
|
||||
video->SetClipRect( &clip );
|
||||
//Float || Changed
|
||||
if (BackGround && (Flags & (WF_FLOAT|WF_CHANGED) ) ) {
|
||||
video->BlitSprite( BackGround, XPos, YPos, true );
|
||||
}
|
||||
std::vector< Control*>::iterator m;
|
||||
for (m = Controls.begin(); m != Controls.end(); ++m) {
|
||||
( *m )->Draw( XPos, YPos );
|
||||
}
|
||||
if ( (Flags&WF_CHANGED) && (Visible == WINDOW_GRAYED) ) {
|
||||
Color black = { 0, 0, 0, 128 };
|
||||
video->DrawRect(clip, black);
|
||||
}
|
||||
video->SetClipRect( NULL );
|
||||
Flags &= ~WF_CHANGED;
|
||||
}
|
||||
|
||||
/** Set window frame used to fill screen on higher resolutions*/
|
||||
void Window::SetFrame()
|
||||
{
|
||||
if ( (Width < core->Width) || (Height < core->Height) ) {
|
||||
Flags|=WF_FRAME;
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
/** Returns the Control at X,Y Coordinates */
|
||||
Control* Window::GetControl(unsigned short x, unsigned short y, bool ignore)
|
||||
{
|
||||
Control* ctrl = NULL;
|
||||
|
||||
//Check if we are still on the last control
|
||||
if (( lastC != NULL )) {
|
||||
if (( XPos + lastC->XPos <= x )
|
||||
&& ( YPos + lastC->YPos <= y )
|
||||
&& ( XPos + lastC->XPos + lastC->Width >= x )
|
||||
&& ( YPos + lastC->YPos + lastC->Height >= y )
|
||||
&& ! lastC->IsPixelTransparent (x - XPos - lastC->XPos, y - YPos - lastC->YPos)) {
|
||||
//Yes, we are on the last returned Control
|
||||
return lastC;
|
||||
}
|
||||
}
|
||||
std::vector< Control*>::const_iterator m;
|
||||
for (m = Controls.begin(); m != Controls.end(); m++) {
|
||||
if (ignore && (*m)->ControlID&IGNORE_CONTROL) {
|
||||
continue;
|
||||
}
|
||||
if (( XPos + ( *m )->XPos <= x )
|
||||
&& ( YPos + ( *m )->YPos <= y )
|
||||
&& ( XPos + ( *m )->XPos + ( *m )->Width >= x )
|
||||
&& ( YPos + ( *m )->YPos + ( *m )->Height >= y )
|
||||
&& ! ( *m )->IsPixelTransparent (x - XPos - ( *m )->XPos, y - YPos - ( *m )->YPos)) {
|
||||
ctrl = *m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
lastC = ctrl;
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
Control* Window::GetOver() const
|
||||
{
|
||||
return lastOver;
|
||||
}
|
||||
|
||||
Control* Window::GetFocus() const
|
||||
{
|
||||
return lastFocus;
|
||||
}
|
||||
|
||||
Control* Window::GetMouseFocus() const
|
||||
{
|
||||
return lastMouseFocus;
|
||||
}
|
||||
|
||||
/** Sets 'ctrl' as Focused */
|
||||
void Window::SetFocused(Control* ctrl)
|
||||
{
|
||||
if (lastFocus != NULL) {
|
||||
lastFocus->hasFocus = false;
|
||||
lastFocus->Changed = true;
|
||||
}
|
||||
lastFocus = ctrl;
|
||||
if (ctrl != NULL) {
|
||||
lastFocus->hasFocus = true;
|
||||
lastFocus->Changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets 'ctrl' as Mouse Focused */
|
||||
void Window::SetMouseFocused(Control* ctrl)
|
||||
{
|
||||
if (lastMouseFocus != NULL) {
|
||||
lastMouseFocus->Changed = true;
|
||||
}
|
||||
lastMouseFocus = ctrl;
|
||||
if (ctrl != NULL) {
|
||||
lastMouseFocus->Changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Window::GetControlCount() const
|
||||
{
|
||||
return Controls.size();
|
||||
}
|
||||
|
||||
Control* Window::GetControl(unsigned short i) const
|
||||
{
|
||||
if (i < Controls.size()) {
|
||||
return Controls[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Window::IsValidControl(unsigned short ID, Control *ctrl) const
|
||||
{
|
||||
size_t i = Controls.size();
|
||||
while (i--) {
|
||||
if (Controls[i]==ctrl) {
|
||||
return ctrl->ControlID==ID;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Window::DelControl(unsigned short i)
|
||||
{
|
||||
if (i < Controls.size() ) {
|
||||
Control *ctrl = Controls[i];
|
||||
if (ctrl==lastC) {
|
||||
lastC=NULL;
|
||||
}
|
||||
if (ctrl==lastOver) {
|
||||
lastOver=NULL;
|
||||
}
|
||||
if (ctrl==lastFocus) {
|
||||
lastFocus=NULL;
|
||||
}
|
||||
if (ctrl==lastMouseFocus) {
|
||||
lastMouseFocus=NULL;
|
||||
}
|
||||
delete ctrl;
|
||||
Controls.erase(Controls.begin()+i);
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
Control* Window::GetDefaultControl(unsigned int ctrltype) const
|
||||
{
|
||||
if (!Controls.size()) {
|
||||
return NULL;
|
||||
}
|
||||
if (ctrltype>=2) {
|
||||
return NULL;
|
||||
}
|
||||
return GetControl( (ieWord) DefaultControl[ctrltype] );
|
||||
}
|
||||
|
||||
Control* Window::GetScrollControl() const
|
||||
{
|
||||
if (!Controls.size()) {
|
||||
return NULL;
|
||||
}
|
||||
return GetControl( (ieWord) ScrollControl );
|
||||
}
|
||||
|
||||
void Window::release(void)
|
||||
{
|
||||
Visible = WINDOW_INVALID;
|
||||
lastC = NULL;
|
||||
lastFocus = NULL;
|
||||
lastMouseFocus = NULL;
|
||||
lastOver = NULL;
|
||||
}
|
||||
|
||||
/** Redraw all the Window */
|
||||
void Window::Invalidate()
|
||||
{
|
||||
DefaultControl[0] = -1;
|
||||
DefaultControl[1] = -1;
|
||||
ScrollControl = -1;
|
||||
for (unsigned int i = 0; i < Controls.size(); i++) {
|
||||
if (!Controls[i]) {
|
||||
continue;
|
||||
}
|
||||
Controls[i]->Changed = true;
|
||||
switch (Controls[i]->ControlType) {
|
||||
case IE_GUI_SCROLLBAR:
|
||||
if ((ScrollControl == -1) || (Controls[i]->Flags & IE_GUI_SCROLLBAR_DEFAULT))
|
||||
ScrollControl = i;
|
||||
break;
|
||||
case IE_GUI_BUTTON:
|
||||
if (( Controls[i]->Flags & IE_GUI_BUTTON_DEFAULT )) {
|
||||
DefaultControl[0] = i;
|
||||
}
|
||||
if (( Controls[i]->Flags & IE_GUI_BUTTON_CANCEL )) {
|
||||
DefaultControl[1] = i;
|
||||
}
|
||||
break;
|
||||
//falling through
|
||||
case IE_GUI_GAMECONTROL:
|
||||
DefaultControl[0] = i;
|
||||
DefaultControl[1] = i;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
Flags |= WF_CHANGED;
|
||||
}
|
||||
|
||||
/** Redraw enough to update the specified Control */
|
||||
void Window::InvalidateForControl(Control *ctrl) {
|
||||
// TODO: for this to be general-purpose, we should mark anything inside this
|
||||
// region with Changed, and also do mass Invalidate() if we overlap with
|
||||
// another window, but for now this just clips the *background*, see DrawWindow()
|
||||
clip_regions.push_back( Region(ctrl->XPos, ctrl->YPos, ctrl->Width, ctrl->Height) );
|
||||
}
|
||||
|
||||
void Window::RedrawControls(const char* VarName, unsigned int Sum)
|
||||
{
|
||||
for (unsigned int i = 0; i < Controls.size(); i++) {
|
||||
switch (Controls[i]->ControlType) {
|
||||
case IE_GUI_MAP:
|
||||
{
|
||||
MapControl *mc = ( MapControl* ) (Controls[i]);
|
||||
mc->RedrawMapControl( VarName, Sum );
|
||||
break;
|
||||
}
|
||||
case IE_GUI_BUTTON:
|
||||
{
|
||||
Button* bt = ( Button* ) ( Controls[i] );
|
||||
bt->RedrawButton( VarName, Sum );
|
||||
break;
|
||||
}
|
||||
case IE_GUI_TEXTAREA:
|
||||
{
|
||||
TextArea* pb = ( TextArea* ) ( Controls[i] );
|
||||
pb->RedrawTextArea( VarName, Sum );
|
||||
break;
|
||||
}
|
||||
case IE_GUI_PROGRESSBAR:
|
||||
{
|
||||
Progressbar* pb = ( Progressbar* ) ( Controls[i] );
|
||||
pb->RedrawProgressbar( VarName, Sum );
|
||||
break;
|
||||
}
|
||||
case IE_GUI_SLIDER:
|
||||
{
|
||||
Slider* sl = ( Slider* ) ( Controls[i] );
|
||||
sl->RedrawSlider( VarName, Sum );
|
||||
break;
|
||||
}
|
||||
case IE_GUI_SCROLLBAR:
|
||||
{
|
||||
ScrollBar* sb = ( ScrollBar* ) ( Controls[i] );
|
||||
sb->RedrawScrollBar( VarName, Sum );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Searches for a ScrollBar and a TextArea to link them */
|
||||
void Window::Link(unsigned short SBID, unsigned short TAID)
|
||||
{
|
||||
ScrollBar* sb = NULL;
|
||||
TextArea* ta = NULL;
|
||||
std::vector< Control*>::iterator m;
|
||||
for (m = Controls.begin(); m != Controls.end(); m++) {
|
||||
if (( *m )->Owner != this)
|
||||
continue;
|
||||
if (( *m )->ControlType == IE_GUI_SCROLLBAR) {
|
||||
if (( *m )->ControlID == SBID) {
|
||||
sb = ( ScrollBar * ) ( *m );
|
||||
if (ta != NULL)
|
||||
break;
|
||||
}
|
||||
} else if (( *m )->ControlType == IE_GUI_TEXTAREA) {
|
||||
if (( *m )->ControlID == TAID) {
|
||||
ta = ( TextArea * ) ( *m );
|
||||
if (sb != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sb && ta) {
|
||||
sb->ta = ta;
|
||||
ta->SetScrollBar( sb );
|
||||
}
|
||||
}
|
||||
|
||||
void Window::OnMouseEnter(unsigned short x, unsigned short y, Control *ctrl)
|
||||
{
|
||||
lastOver = ctrl;
|
||||
if (!lastOver) {
|
||||
return;
|
||||
}
|
||||
lastOver->OnMouseEnter( x - XPos - lastOver->XPos, y - YPos - lastOver->YPos );
|
||||
}
|
||||
|
||||
void Window::OnMouseLeave(unsigned short x, unsigned short y)
|
||||
{
|
||||
if (!lastOver) {
|
||||
return;
|
||||
}
|
||||
lastOver->OnMouseLeave( x - XPos - lastOver->XPos, y - YPos - lastOver->YPos );
|
||||
lastOver = NULL;
|
||||
}
|
||||
|
||||
void Window::OnMouseOver(unsigned short x, unsigned short y)
|
||||
{
|
||||
if (!lastOver) {
|
||||
return;
|
||||
}
|
||||
lastOver->OnMouseOver( x - XPos - lastOver->XPos, y - YPos - lastOver->YPos );
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Window.h
|
||||
* Declares Window, class serving as a container for Control/widget objects
|
||||
* and displaying windows in GUI
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
#ifndef WINDOW_H
|
||||
#define WINDOW_H
|
||||
|
||||
#include "GUI/Control.h"
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Sprite2D;
|
||||
|
||||
// Window Flags
|
||||
#define WF_CHANGED 1 //window changed
|
||||
#define WF_FRAME 2 //window has frame
|
||||
#define WF_FLOAT 4 //floating window
|
||||
#define WF_CHILD 8 //if invalidated, it invalidates all windows on top of it
|
||||
|
||||
// Window position anchors (actually flags for WindowSetPos())
|
||||
// !!! Keep these synchronized with GUIDefines.py !!!
|
||||
#define WINDOW_TOPLEFT 0x00
|
||||
#define WINDOW_CENTER 0x01
|
||||
#define WINDOW_ABSCENTER 0x02
|
||||
#define WINDOW_RELATIVE 0x04
|
||||
#define WINDOW_SCALE 0x08
|
||||
#define WINDOW_BOUNDED 0x10
|
||||
|
||||
// IE specific cursor types
|
||||
|
||||
#define IE_CURSOR_INVALID -1
|
||||
#define IE_CURSOR_NORMAL 0
|
||||
#define IE_CURSOR_TAKE 2 //over pile type containers
|
||||
#define IE_CURSOR_WALK 4
|
||||
#define IE_CURSOR_BLOCKED 6
|
||||
#define IE_CURSOR_USE 8 //never hardcoded
|
||||
#define IE_CURSOR_WAIT 10 //hourglass
|
||||
#define IE_CURSOR_ATTACK 12
|
||||
#define IE_CURSOR_SWAP 14 //dragging portraits
|
||||
#define IE_CURSOR_DEFEND 16
|
||||
#define IE_CURSOR_TALK 18
|
||||
#define IE_CURSOR_CAST 20 //targeting with non weapon
|
||||
#define IE_CURSOR_INFO 22 //never hardcoded
|
||||
#define IE_CURSOR_LOCK 24 //locked door
|
||||
#define IE_CURSOR_LOCK2 26 //locked container
|
||||
#define IE_CURSOR_STAIR 28 //never hardcoded
|
||||
#define IE_CURSOR_DOOR 30 //doors
|
||||
#define IE_CURSOR_CHEST 32
|
||||
#define IE_CURSOR_TRAVEL 34
|
||||
#define IE_CURSOR_STEALTH 36
|
||||
#define IE_CURSOR_TRAP 38
|
||||
#define IE_CURSOR_PICK 40 //pickpocket
|
||||
#define IE_CURSOR_PASS 42 //never hardcoded
|
||||
#define IE_CURSOR_GRAB 44
|
||||
#define IE_CURSOR_WAY 46 //waypoint (not in PST)
|
||||
#define IE_CURSOR_INFO2 46 //PST
|
||||
#define IE_CURSOR_PORTAL 48 //PST
|
||||
#define IE_CURSOR_STAIR2 50 //PST
|
||||
#define IE_CURSOR_EXTRA 52 //PST
|
||||
|
||||
#define IE_CURSOR_MASK 127
|
||||
#define IE_CURSOR_GRAY 128
|
||||
/**
|
||||
* @class Window
|
||||
* Class serving as a container for Control/widget objects
|
||||
* and displaying windows in GUI.
|
||||
*/
|
||||
|
||||
class GEM_EXPORT Window {
|
||||
public:
|
||||
Window(unsigned short WindowID, unsigned short XPos, unsigned short YPos,
|
||||
unsigned short Width, unsigned short Height);
|
||||
~Window();
|
||||
/** Set the Window's BackGround Image.
|
||||
* If 'img' is NULL, no background will be set. If the 'clean' parameter is true (default is false) the old background image will be deleted. */
|
||||
void SetBackGround(Sprite2D* img, bool clean = false);
|
||||
/** Add a Control in the Window */
|
||||
void AddControl(Control* ctrl);
|
||||
/** This function Draws the Window on the Output Screen */
|
||||
void DrawWindow();
|
||||
/** Set window frame used to fill screen on higher resolutions*/
|
||||
void SetFrame();
|
||||
/** Returns the Control at X,Y Coordinates */
|
||||
Control* GetControl(unsigned short x, unsigned short y, bool ignore=0);
|
||||
/** Returns the Control by Index */
|
||||
Control* GetControl(unsigned short i) const;
|
||||
/** Returns the number of Controls */
|
||||
unsigned int GetControlCount() const;
|
||||
/** Returns true if ctrl is valid and ctrl->ControlID is ID */
|
||||
bool IsValidControl(unsigned short ID, Control *ctrl) const;
|
||||
/** Deletes the xth. Control */
|
||||
void DelControl(unsigned short i);
|
||||
/** Returns the Default Control which may be a button/gamecontrol atm */
|
||||
Control* GetDefaultControl(unsigned int ctrltype) const;
|
||||
/** Returns the Control which should get mouse scroll events */
|
||||
Control* GetScrollControl() const;
|
||||
/** Sets 'ctrl' as currently under mouse */
|
||||
void SetOver(Control* ctrl);
|
||||
/** Returns last control under mouse */
|
||||
Control* GetOver() const;
|
||||
/** Sets 'ctrl' as Focused */
|
||||
void SetFocused(Control* ctrl);
|
||||
/** Sets 'ctrl' as mouse event Focused */
|
||||
void SetMouseFocused(Control* ctrl);
|
||||
/** Returns last focused control */
|
||||
Control* GetFocus() const;
|
||||
/** Returns last mouse event focused control */
|
||||
Control* GetMouseFocus() const;
|
||||
/** Redraw all the Window */
|
||||
void Invalidate();
|
||||
/** Redraw enough to update the specified Control */
|
||||
void InvalidateForControl(Control *ctrl);
|
||||
/** Redraw controls of the same group */
|
||||
void RedrawControls(const char* VarName, unsigned int Sum);
|
||||
/** Links a scrollbar to a text area */
|
||||
void Link(unsigned short SBID, unsigned short TAID);
|
||||
/** Mouse entered a new control's rectangle */
|
||||
void OnMouseEnter(unsigned short x, unsigned short y, Control *ctrl);
|
||||
/** Mouse left the current control */
|
||||
void OnMouseLeave(unsigned short x, unsigned short y);
|
||||
/** Mouse is over the current control */
|
||||
void OnMouseOver(unsigned short x, unsigned short y);
|
||||
public: //Public attributes
|
||||
/** WinPack */
|
||||
char WindowPack[10];
|
||||
/** Window ID */
|
||||
unsigned short WindowID;
|
||||
/** X Position */
|
||||
unsigned short XPos;
|
||||
/** Y Position */
|
||||
unsigned short YPos;
|
||||
/** Width */
|
||||
unsigned short Width;
|
||||
/** Height */
|
||||
unsigned short Height;
|
||||
/** Visible value: deleted, invisible, visible, grayed */
|
||||
signed char Visible; //-1,0,1,2
|
||||
/** Window flags: Changed, Floating, Framed, Child */
|
||||
int Flags;
|
||||
int Cursor;
|
||||
int DefaultControl[2]; //default enter and cancel
|
||||
int ScrollControl;
|
||||
private: // Private attributes
|
||||
/** BackGround Image. No BackGround if this variable is NULL. */
|
||||
Sprite2D* BackGround;
|
||||
/** Controls Array */
|
||||
std::vector< Control*> Controls;
|
||||
/** Last Control returned by GetControl */
|
||||
Control* lastC;
|
||||
/** Last Focused Control */
|
||||
Control* lastFocus;
|
||||
/** Last mouse event Focused Control */
|
||||
Control* lastMouseFocus;
|
||||
/** Last Control under mouse */
|
||||
Control* lastOver;
|
||||
/** Regions which need to be redrawn */
|
||||
std::vector< Region> clip_regions;
|
||||
|
||||
public:
|
||||
void release(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,420 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GUI/WorldMapControl.h"
|
||||
|
||||
#include "win32def.h"
|
||||
|
||||
#include "Font.h"
|
||||
#include "Game.h"
|
||||
#include "GameData.h"
|
||||
#include "Interface.h"
|
||||
#include "Video.h"
|
||||
#include "WorldMap.h"
|
||||
#include "GUI/EventMgr.h"
|
||||
#include "GUI/Window.h"
|
||||
|
||||
#define MAP_TO_SCREENX(x) XWin + XPos - ScrollX + (x)
|
||||
#define MAP_TO_SCREENY(y) YWin + YPos - ScrollY + (y)
|
||||
|
||||
WorldMapControl::WorldMapControl(const char *font, int direction)
|
||||
{
|
||||
ScrollX = 0;
|
||||
ScrollY = 0;
|
||||
MouseIsDown = false;
|
||||
Changed = true;
|
||||
Area = NULL;
|
||||
Value = direction;
|
||||
Game* game = core->GetGame();
|
||||
WorldMap* worldmap = core->GetWorldMap();
|
||||
strncpy(currentArea, game->CurrentArea, 8);
|
||||
int entry = core->GetAreaAlias(currentArea);
|
||||
if (entry >= 0) {
|
||||
WMPAreaEntry *m = worldmap->GetEntry(entry);
|
||||
strncpy(currentArea, m->AreaResRef, 8);
|
||||
}
|
||||
|
||||
//if there is no trivial area, look harder
|
||||
if (!worldmap->GetArea(currentArea, (unsigned int &) entry) &&
|
||||
core->HasFeature(GF_FLEXIBLE_WMAP) ) {
|
||||
WMPAreaEntry *m = worldmap->FindNearestEntry(currentArea, (unsigned int &) entry);
|
||||
if (m) {
|
||||
strncpy(currentArea, m->AreaResRef, 8);
|
||||
}
|
||||
}
|
||||
|
||||
//this also updates visible locations
|
||||
worldmap->CalculateDistances(currentArea, Value);
|
||||
|
||||
// alpha bit is unfortunately ignored
|
||||
if (font[0]) {
|
||||
ftext = core->GetFont(font);
|
||||
} else {
|
||||
ftext = NULL;
|
||||
}
|
||||
|
||||
// initialize label colors
|
||||
// NOTE: it would be better to initialize these colors from
|
||||
// some 2da file
|
||||
Color normal = { 0xf0, 0xf0, 0xf0, 0xff };
|
||||
Color selected = { 0xf0, 0x80, 0x80, 0xff };
|
||||
Color notvisited = { 0x80, 0x80, 0xf0, 0xff };
|
||||
Color black = { 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
pal_normal = core->CreatePalette ( normal, black );
|
||||
pal_selected = core->CreatePalette ( selected, black );
|
||||
pal_notvisited = core->CreatePalette ( notvisited, black );
|
||||
|
||||
|
||||
ResetEventHandler( WorldMapControlOnPress );
|
||||
ResetEventHandler( WorldMapControlOnEnter );
|
||||
}
|
||||
|
||||
WorldMapControl::~WorldMapControl(void)
|
||||
{
|
||||
//Video *video = core->GetVideoDriver();
|
||||
|
||||
gamedata->FreePalette( pal_normal );
|
||||
gamedata->FreePalette( pal_selected );
|
||||
gamedata->FreePalette( pal_notvisited );
|
||||
}
|
||||
|
||||
/** Draws the Control on the Output Display */
|
||||
void WorldMapControl::Draw(unsigned short XWin, unsigned short YWin)
|
||||
{
|
||||
WorldMap* worldmap = core->GetWorldMap();
|
||||
if (!Width || !Height) {
|
||||
return;
|
||||
}
|
||||
if(!Changed)
|
||||
return;
|
||||
Changed = false;
|
||||
Video* video = core->GetVideoDriver();
|
||||
Region r( XWin+XPos, YWin+YPos, Width, Height );
|
||||
Region clipbackup;
|
||||
video->GetClipRect(clipbackup);
|
||||
video->SetClipRect(&r);
|
||||
video->BlitSprite( worldmap->GetMapMOS(), MAP_TO_SCREENX(0), MAP_TO_SCREENY(0), true, &r );
|
||||
|
||||
unsigned int i;
|
||||
unsigned int ec = worldmap->GetEntryCount();
|
||||
for(i=0;i<ec;i++) {
|
||||
WMPAreaEntry *m = worldmap->GetEntry(i);
|
||||
if (! (m->GetAreaStatus() & WMP_ENTRY_VISIBLE)) continue;
|
||||
|
||||
int xOffs = MAP_TO_SCREENX(m->X);
|
||||
int yOffs = MAP_TO_SCREENY(m->Y);
|
||||
Sprite2D* icon = m->GetMapIcon(worldmap->bam);
|
||||
if( icon ) {
|
||||
video->BlitSprite( icon, xOffs, yOffs, true, &r );
|
||||
video->FreeSprite( icon );
|
||||
}
|
||||
|
||||
if (AnimPicture && !strnicmp(m->AreaResRef, currentArea, 8) ) {
|
||||
core->GetVideoDriver()->BlitSprite( AnimPicture, xOffs, yOffs, true, &r );
|
||||
}
|
||||
}
|
||||
|
||||
// Draw WMP entry labels
|
||||
if (ftext==NULL) {
|
||||
video->SetClipRect(&clipbackup);
|
||||
return;
|
||||
}
|
||||
for(i=0;i<ec;i++) {
|
||||
WMPAreaEntry *m = worldmap->GetEntry(i);
|
||||
if (! (m->GetAreaStatus() & WMP_ENTRY_VISIBLE)) continue;
|
||||
Sprite2D *icon=m->GetMapIcon(worldmap->bam);
|
||||
int h=0,w=0,xpos=0,ypos=0;
|
||||
if (icon) {
|
||||
h=icon->Height;
|
||||
w=icon->Width;
|
||||
xpos=icon->XPos;
|
||||
ypos=icon->YPos;
|
||||
video->FreeSprite( icon );
|
||||
}
|
||||
|
||||
Region r2 = Region( MAP_TO_SCREENX(m->X-xpos), MAP_TO_SCREENY(m->Y-ypos), w, h );
|
||||
if (!m->GetCaption())
|
||||
continue;
|
||||
|
||||
int tw = ftext->CalcStringWidth( m->GetCaption() ) + 5;
|
||||
int th = ftext->maxHeight;
|
||||
|
||||
Palette* text_pal = pal_normal;
|
||||
|
||||
if (Area == m) {
|
||||
text_pal = pal_selected;
|
||||
} else {
|
||||
if (! (m->GetAreaStatus() & WMP_ENTRY_VISITED)) {
|
||||
text_pal = pal_notvisited;
|
||||
}
|
||||
}
|
||||
|
||||
ftext->Print( Region( r2.x + (r2.w - tw)/2, r2.y + r2.h, tw, th ),
|
||||
( const unsigned char * ) m->GetCaption(), text_pal, 0, true );
|
||||
}
|
||||
video->SetClipRect(&clipbackup);
|
||||
}
|
||||
|
||||
/** Key Release Event */
|
||||
void WorldMapControl::OnKeyRelease(unsigned char Key, unsigned short Mod)
|
||||
{
|
||||
switch (Key) {
|
||||
case 'f':
|
||||
if (Mod & GEM_MOD_CTRL)
|
||||
core->GetVideoDriver()->ToggleFullscreenMode();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void WorldMapControl::AdjustScrolling(short x, short y)
|
||||
{
|
||||
WorldMap* worldmap = core->GetWorldMap();
|
||||
if (x || y) {
|
||||
ScrollX += x;
|
||||
ScrollY += y;
|
||||
} else {
|
||||
//center worldmap on current area
|
||||
unsigned entry;
|
||||
|
||||
WMPAreaEntry *m = worldmap->GetArea(currentArea,entry);
|
||||
if (m) {
|
||||
ScrollX = m->X - Width/2;
|
||||
ScrollY = m->Y - Height/2;
|
||||
}
|
||||
}
|
||||
Sprite2D *MapMOS = worldmap->GetMapMOS();
|
||||
if (ScrollX > MapMOS->Width - Width)
|
||||
ScrollX = MapMOS->Width - Width;
|
||||
if (ScrollY > MapMOS->Height - Height)
|
||||
ScrollY = MapMOS->Height - Height;
|
||||
if (ScrollX < 0)
|
||||
ScrollX = 0;
|
||||
if (ScrollY < 0)
|
||||
ScrollY = 0;
|
||||
Changed = true;
|
||||
Area = NULL;
|
||||
}
|
||||
|
||||
/** Mouse Over Event */
|
||||
void WorldMapControl::OnMouseOver(unsigned short x, unsigned short y)
|
||||
{
|
||||
WorldMap* worldmap = core->GetWorldMap();
|
||||
lastCursor = IE_CURSOR_GRAB;
|
||||
|
||||
if (MouseIsDown) {
|
||||
AdjustScrolling(lastMouseX-x, lastMouseY-y);
|
||||
}
|
||||
|
||||
lastMouseX = x;
|
||||
lastMouseY = y;
|
||||
|
||||
if (Value!=(ieDword) -1) {
|
||||
x =(ieWord) (x + ScrollX);
|
||||
y =(ieWord) (y + ScrollY);
|
||||
|
||||
WMPAreaEntry *oldArea = Area;
|
||||
Area = NULL;
|
||||
|
||||
unsigned int i;
|
||||
unsigned int ec = worldmap->GetEntryCount();
|
||||
for (i=0;i<ec;i++) {
|
||||
WMPAreaEntry *ae = worldmap->GetEntry(i);
|
||||
|
||||
if ( (ae->GetAreaStatus() & WMP_ENTRY_WALKABLE)!=WMP_ENTRY_WALKABLE) {
|
||||
continue; //invisible or inaccessible
|
||||
}
|
||||
if (!strnicmp(ae->AreaResRef, currentArea, 8) ) {
|
||||
continue; //current area
|
||||
}
|
||||
|
||||
Sprite2D *icon=ae->GetMapIcon(worldmap->bam);
|
||||
int h=0,w=0;
|
||||
if (icon) {
|
||||
h=icon->Height;
|
||||
w=icon->Width;
|
||||
core->GetVideoDriver()->FreeSprite( icon );
|
||||
}
|
||||
if (ftext && ae->GetCaption()) {
|
||||
int tw = ftext->CalcStringWidth( ae->GetCaption() ) + 5;
|
||||
int th = ftext->maxHeight;
|
||||
if(h<th)
|
||||
h=th;
|
||||
if(w<tw)
|
||||
w=tw;
|
||||
}
|
||||
if (ae->X > x) continue;
|
||||
if (ae->X + w < x) continue;
|
||||
if (ae->Y > y) continue;
|
||||
if (ae->Y + h < y) continue;
|
||||
lastCursor = IE_CURSOR_NORMAL;
|
||||
Area=ae;
|
||||
if(oldArea!=ae) {
|
||||
RunEventHandler(WorldMapControlOnEnter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Owner->Cursor = lastCursor;
|
||||
}
|
||||
|
||||
/** Sets the tooltip to be displayed on the screen now */
|
||||
void WorldMapControl::DisplayTooltip()
|
||||
{
|
||||
if (Area) {
|
||||
int x = Owner->XPos+XPos+lastMouseX;
|
||||
int y = Owner->YPos+YPos+lastMouseY-50;
|
||||
core->DisplayTooltip( x, y, this );
|
||||
} else {
|
||||
core->DisplayTooltip( 0, 0, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
/** Mouse Leave Event */
|
||||
void WorldMapControl::OnMouseLeave(unsigned short /*x*/, unsigned short /*y*/)
|
||||
{
|
||||
Owner->Cursor = IE_CURSOR_NORMAL;
|
||||
Area = NULL;
|
||||
}
|
||||
|
||||
/** Mouse Button Down */
|
||||
void WorldMapControl::OnMouseDown(unsigned short x, unsigned short y,
|
||||
unsigned short Button, unsigned short /*Mod*/)
|
||||
{
|
||||
switch(Button) {
|
||||
case GEM_MB_ACTION:
|
||||
MouseIsDown = true;
|
||||
lastMouseX = x;
|
||||
lastMouseY = y;
|
||||
break;
|
||||
case GEM_MB_SCRLUP:
|
||||
OnSpecialKeyPress(GEM_UP);
|
||||
break;
|
||||
case GEM_MB_SCRLDOWN:
|
||||
OnSpecialKeyPress(GEM_DOWN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/** Mouse Button Up */
|
||||
void WorldMapControl::OnMouseUp(unsigned short /*x*/, unsigned short /*y*/,
|
||||
unsigned short Button, unsigned short /*Mod*/)
|
||||
{
|
||||
if (Button != GEM_MB_ACTION) {
|
||||
return;
|
||||
}
|
||||
MouseIsDown = false;
|
||||
if (lastCursor==IE_CURSOR_NORMAL) {
|
||||
RunEventHandler( WorldMapControlOnPress );
|
||||
}
|
||||
}
|
||||
|
||||
/** Special Key Press */
|
||||
void WorldMapControl::OnSpecialKeyPress(unsigned char Key)
|
||||
{
|
||||
WorldMap* worldmap = core->GetWorldMap();
|
||||
switch (Key) {
|
||||
case GEM_LEFT:
|
||||
ScrollX -= 64;
|
||||
break;
|
||||
case GEM_UP:
|
||||
ScrollY -= 64;
|
||||
break;
|
||||
case GEM_RIGHT:
|
||||
ScrollX += 64;
|
||||
break;
|
||||
case GEM_DOWN:
|
||||
ScrollY += 64;
|
||||
break;
|
||||
case GEM_ALT:
|
||||
print( "ALT pressed\n" );
|
||||
break;
|
||||
case GEM_TAB:
|
||||
print( "TAB pressed\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
Sprite2D *MapMOS = worldmap->GetMapMOS();
|
||||
if (ScrollX > MapMOS->Width - Width)
|
||||
ScrollX = MapMOS->Width - Width;
|
||||
if (ScrollY > MapMOS->Height - Height)
|
||||
ScrollY = MapMOS->Height - Height;
|
||||
if (ScrollX < 0)
|
||||
ScrollX = 0;
|
||||
if (ScrollY < 0)
|
||||
ScrollY = 0;
|
||||
}
|
||||
|
||||
bool WorldMapControl::SetEvent(int eventType, EventHandler handler)
|
||||
{
|
||||
Changed = true;
|
||||
|
||||
switch (eventType) {
|
||||
case IE_GUI_WORLDMAP_ON_PRESS:
|
||||
WorldMapControlOnPress = handler;
|
||||
break;
|
||||
case IE_GUI_MOUSE_ENTER_WORLDMAP:
|
||||
WorldMapControlOnEnter = handler;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WorldMapControl::SetColor(int which, Color color)
|
||||
{
|
||||
Palette* pal;
|
||||
// FIXME: clearly it can cause palettes to be re-created several times,
|
||||
// because setting background color creates all palettes anew.
|
||||
switch (which) {
|
||||
case IE_GUI_WMAP_COLOR_BACKGROUND:
|
||||
pal = core->CreatePalette( pal_normal->front, color );
|
||||
gamedata->FreePalette( pal_normal );
|
||||
pal_normal = pal;
|
||||
pal = core->CreatePalette( pal_selected->front, color );
|
||||
gamedata->FreePalette( pal_selected );
|
||||
pal_selected = pal;
|
||||
pal = core->CreatePalette( pal_notvisited->front, color );
|
||||
gamedata->FreePalette( pal_notvisited );
|
||||
pal_notvisited = pal;
|
||||
break;
|
||||
case IE_GUI_WMAP_COLOR_NORMAL:
|
||||
pal = core->CreatePalette( color, pal_normal->back );
|
||||
gamedata->FreePalette( pal_normal );
|
||||
pal_normal = pal;
|
||||
break;
|
||||
case IE_GUI_WMAP_COLOR_SELECTED:
|
||||
pal = core->CreatePalette( color, pal_selected->back );
|
||||
gamedata->FreePalette( pal_selected );
|
||||
pal_selected = pal;
|
||||
break;
|
||||
case IE_GUI_WMAP_COLOR_NOTVISITED:
|
||||
pal = core->CreatePalette( color, pal_notvisited->back );
|
||||
gamedata->FreePalette( pal_notvisited );
|
||||
pal_notvisited = pal;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Changed = true;
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file WorldMapControl.h
|
||||
* Declares WorldMapControl, widget for displaying world map
|
||||
*/
|
||||
|
||||
|
||||
#ifndef WORLDMAPCONTROL_H
|
||||
#define WORLDMAPCONTROL_H
|
||||
|
||||
#include "GUI/Control.h"
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
#include "Dialog.h"
|
||||
#include "Interface.h"
|
||||
|
||||
class Palette;
|
||||
class WMPAreaEntry;
|
||||
class WorldMapControl;
|
||||
|
||||
// !!! Keep these synchronized with GUIDefines.py !!!
|
||||
/** Which label color is set with SetColor() */
|
||||
#define IE_GUI_WMAP_COLOR_BACKGROUND 0
|
||||
#define IE_GUI_WMAP_COLOR_NORMAL 1
|
||||
#define IE_GUI_WMAP_COLOR_SELECTED 2
|
||||
#define IE_GUI_WMAP_COLOR_NOTVISITED 3
|
||||
|
||||
|
||||
/**
|
||||
* @class WorldMapControl
|
||||
* Widget displaying "world" map, with particular locations and possibly
|
||||
* allowing travelling between areas.
|
||||
*/
|
||||
|
||||
#define IE_GUI_WORLDMAP_ON_PRESS 0x08000000
|
||||
#define IE_GUI_MOUSE_ENTER_WORLDMAP 0x08000002
|
||||
|
||||
class GEM_EXPORT WorldMapControl : public Control {
|
||||
public:
|
||||
WorldMapControl(const char *fontname, int direction);
|
||||
~WorldMapControl(void);
|
||||
|
||||
/** Allows modification of the scrolling factor from outside */
|
||||
void AdjustScrolling(short x, short y);
|
||||
/** Draws the Control on the Output Display */
|
||||
void Draw(unsigned short x, unsigned short y);
|
||||
/** Sets the exit direction (we need this to calculate distances) */
|
||||
void SetDirection(int direction);
|
||||
/** Set color for one type of area labels */
|
||||
void SetColor(int which, Color color);
|
||||
int ScrollX, ScrollY;
|
||||
unsigned short lastMouseX, lastMouseY;
|
||||
bool MouseIsDown;
|
||||
/** pointer to last pointed area */
|
||||
WMPAreaEntry *Area;
|
||||
/** Set handler for specified event */
|
||||
bool SetEvent(int eventType, EventHandler handler);
|
||||
private:
|
||||
//font for printing area names
|
||||
Font* ftext;
|
||||
//mouse cursor
|
||||
unsigned char lastCursor;
|
||||
//current area
|
||||
ieResRef currentArea;
|
||||
/** Label color of a visited area */
|
||||
Palette *pal_normal;
|
||||
/** Label color of a currently selected area */
|
||||
Palette *pal_selected;
|
||||
/** Label color of a not yet visited area */
|
||||
Palette *pal_notvisited;
|
||||
/** guiscript Event when button pressed */
|
||||
EventHandler WorldMapControlOnPress;
|
||||
/** guiscript Event when mouse is over a reachable area */
|
||||
EventHandler WorldMapControlOnEnter;
|
||||
|
||||
/** Mouse Over Event */
|
||||
void OnMouseOver(unsigned short x, unsigned short y);
|
||||
/** Mouse Leave Event */
|
||||
void OnMouseLeave(unsigned short x, unsigned short y);
|
||||
/** Mouse Button Down */
|
||||
void OnMouseDown(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Mouse Button Up */
|
||||
void OnMouseUp(unsigned short x, unsigned short y, unsigned short Button,
|
||||
unsigned short Mod);
|
||||
/** Key Release Event */
|
||||
void OnKeyRelease(unsigned char Key, unsigned short Mod);
|
||||
/** Special Key Press */
|
||||
void OnSpecialKeyPress(unsigned char Key);
|
||||
/** DisplayTooltip */
|
||||
void DisplayTooltip();
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,482 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Game.h
|
||||
* Declares Game class, object representing current game state.
|
||||
* @author The GemRB Project
|
||||
*/
|
||||
|
||||
|
||||
class Game;
|
||||
|
||||
#ifndef GAME_H
|
||||
#define GAME_H
|
||||
|
||||
#include "exports.h"
|
||||
#include "ie_types.h"
|
||||
|
||||
#include "Callback.h"
|
||||
#include "Scriptable/Scriptable.h"
|
||||
#include "Scriptable/PCStatStruct.h"
|
||||
#include "Variables.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Actor;
|
||||
class Map;
|
||||
class Particles;
|
||||
class TableMgr;
|
||||
|
||||
//the size of the bestiary register
|
||||
#define BESTIARY_SIZE 260
|
||||
|
||||
//ShareXP flags
|
||||
#define SX_DIVIDE 1 //divide XP among team members
|
||||
#define SX_CR 2 //use challenge rating resolution
|
||||
|
||||
//joinparty flags
|
||||
#define JP_JOIN 1 //refresh join time
|
||||
#define JP_INITPOS 2 //init startpos
|
||||
#define JP_SELECT 4 //select the actor after joining
|
||||
|
||||
//protagonist mode
|
||||
#define PM_NO 0 //no death checks
|
||||
#define PM_YES 1 //if protagonist dies, game over
|
||||
#define PM_TEAM 2 //if team dies, game over
|
||||
|
||||
// Flags bits for SelectActor()
|
||||
// !!! Keep these synchronized with GUIDefines.py !!!
|
||||
#define SELECT_NORMAL 0x00
|
||||
#define SELECT_REPLACE 0x01 // when selecting actor, deselect all others
|
||||
#define SELECT_QUIET 0x02 // do not run handler when changing selection
|
||||
|
||||
// Flags bits for EveryoneNearPoint()
|
||||
#define ENP_CANMOVE 1 // also check if the PC can move
|
||||
#define ENP_ONLYSELECT 2 // check only selected PC
|
||||
|
||||
// GUI Control Status flags (saved in game)
|
||||
#define CS_PARTY_AI 1 //enable party AI
|
||||
#define CS_MEDIUM 2 //medium dialog
|
||||
#define CS_LARGE 6 //large dialog, both bits set
|
||||
#define CS_DIALOGSIZEMASK 6
|
||||
#define CS_DIALOG 8 //dialog is running
|
||||
#define CS_HIDEGUI 16 //hide all gui
|
||||
#define CS_ACTION 32 //hide action pane
|
||||
#define CS_PORTRAIT 64 //hide portrait pane
|
||||
#define CS_MAPNOTES 128 //hide mapnotes
|
||||
|
||||
//Weather bits
|
||||
#define WB_NORMAL 0
|
||||
#define WB_RAIN 1
|
||||
#define WB_SNOW 2
|
||||
#define WB_FOG 3
|
||||
#define WB_MASK 7
|
||||
#define WB_LIGHTNING 8
|
||||
#define WB_HASWEATHER 0x40
|
||||
#define WB_START 0x80
|
||||
|
||||
//Rest flags
|
||||
#define REST_NOAREA 1 //no area check
|
||||
#define REST_NOSCATTER 2 //no scatter check
|
||||
#define REST_NOMOVE 4 //no movement check
|
||||
#define REST_NOCRITTER 8 //no hostiles check
|
||||
|
||||
//Song types (hardcoded)
|
||||
#define SONG_DAY 0
|
||||
#define SONG_NIGHT 1
|
||||
#define SONG_BATTLE 3
|
||||
|
||||
/**
|
||||
* @struct PCStruct
|
||||
* Information about party member.
|
||||
*/
|
||||
|
||||
struct PCStruct {
|
||||
ieWord Selected;
|
||||
ieWord PartyOrder;
|
||||
ieDword OffsetToCRE;
|
||||
ieDword CRESize;
|
||||
ieResRef CREResRef;
|
||||
ieDword Orientation;
|
||||
ieResRef Area;
|
||||
ieWord XPos;
|
||||
ieWord YPos;
|
||||
ieWord ViewXPos;
|
||||
ieWord ViewYPos;
|
||||
ieWord ModalState;
|
||||
ieWord Happiness;
|
||||
ieDword Interact[MAX_INTERACT];
|
||||
ieWord QuickWeaponSlot[MAX_QUICKWEAPONSLOT];
|
||||
ieWord QuickWeaponHeader[MAX_QUICKWEAPONSLOT];
|
||||
ieResRef QuickSpellResRef[MAX_QSLOTS];
|
||||
ieWord QuickItemSlot[MAX_QUICKITEMSLOT];
|
||||
ieWord QuickItemHeader[MAX_QUICKITEMSLOT];
|
||||
char Name[32];
|
||||
ieDword TalkCount;
|
||||
ieByte QSlots[GUIBT_COUNT];
|
||||
ieByte QuickSpellClass[MAX_QSLOTS];
|
||||
};
|
||||
|
||||
#define IE_GAM_JOURNAL 0
|
||||
#define IE_GAM_QUEST_UNSOLVED 1
|
||||
#define IE_GAM_QUEST_DONE 2
|
||||
#define IE_GAM_JOURNAL_USER 3
|
||||
|
||||
/**
|
||||
* @struct GAMJournalEntry
|
||||
* Single entry in a journal
|
||||
*/
|
||||
|
||||
struct GAMJournalEntry {
|
||||
ieStrRef Text;
|
||||
ieDword GameTime; // in game time seconds
|
||||
ieByte Chapter;
|
||||
ieByte unknown09;
|
||||
ieByte Section;
|
||||
ieByte Group; // this is a GemRB extension
|
||||
};
|
||||
|
||||
// Saved location of party member.
|
||||
struct GAMLocationEntry {
|
||||
ieResRef AreaResRef;
|
||||
Point Pos;
|
||||
};
|
||||
|
||||
//pst maze data structures (TODO: create a separate class?)
|
||||
struct maze_entry {
|
||||
ieDword override;
|
||||
ieDword accessible;
|
||||
ieDword valid;
|
||||
ieDword trapped;
|
||||
ieDword traptype;
|
||||
ieWord walls;
|
||||
ieDword visited;
|
||||
};
|
||||
|
||||
struct maze_header {
|
||||
ieDword maze_sizex, maze_sizey;
|
||||
ieDword pos1x, pos1y; //nordom's position
|
||||
ieDword pos2x, pos2y; //main hall position
|
||||
ieDword pos3x, pos3y; //foyer entrance
|
||||
ieDword pos4x, pos4y; //unknown
|
||||
ieDword trapcount; //based on map size
|
||||
ieDword initialized; //set to 1
|
||||
ieDword unknown2c; //unknown
|
||||
ieDword unknown30; //unknown
|
||||
};
|
||||
|
||||
#define MAZE_ENTRY_SIZE sizeof(maze_entry)
|
||||
#define MAZE_HEADER_SIZE sizeof(maze_header)
|
||||
#define MAZE_MAX_DIM 8
|
||||
#define MAZE_ENTRY_COUNT (MAZE_MAX_DIM*MAZE_MAX_DIM)
|
||||
#define MAZE_DATA_SIZE (MAZE_ENTRY_COUNT*MAZE_ENTRY_SIZE+MAZE_HEADER_SIZE)
|
||||
#define MAZE_DATA_SIZE_HARDCODED 1720
|
||||
|
||||
//maze header indices
|
||||
#define MH_POS1X 0
|
||||
#define MH_POS1Y 1
|
||||
#define MH_POS2X 2
|
||||
#define MH_POS2Y 3
|
||||
#define MH_POS3X 4
|
||||
#define MH_POS3Y 5
|
||||
#define MH_POS4X 6
|
||||
#define MH_POS4Y 7
|
||||
#define MH_TRAPCOUNT 8
|
||||
#define MH_INITED 9
|
||||
#define MH_UNKNOWN2C 10
|
||||
#define MH_UNKNOWN30 11
|
||||
|
||||
//maze entry indices
|
||||
#define ME_OVERRIDE 0
|
||||
#define ME_VALID 1
|
||||
#define ME_ACCESSIBLE 2
|
||||
#define ME_TRAP 3
|
||||
#define ME_WALLS 4
|
||||
#define ME_VISITED 5
|
||||
|
||||
//ME_WALL bitfields
|
||||
#define WALL_SOUTH 1
|
||||
#define WALL_NORTH 2
|
||||
#define WALL_EAST 4
|
||||
#define WALL_WEST 8
|
||||
|
||||
#define MAX_CRLEVEL 32
|
||||
|
||||
typedef int CRRow[MAX_CRLEVEL];
|
||||
|
||||
/**
|
||||
* @class Game
|
||||
* Object representing current game state, mostly party.
|
||||
*/
|
||||
|
||||
class GEM_EXPORT Game : public Scriptable {
|
||||
public:
|
||||
Game(void);
|
||||
~Game(void);
|
||||
private:
|
||||
std::vector< Actor*> PCs;
|
||||
std::vector< Actor*> NPCs;
|
||||
std::vector< Map*> Maps;
|
||||
std::vector< GAMJournalEntry*> Journals;
|
||||
std::vector< GAMLocationEntry*> savedpositions;
|
||||
std::vector< GAMLocationEntry*> planepositions;
|
||||
std::vector< char*> mastarea;
|
||||
CRRow *crtable;
|
||||
ieResRef restmovies[8];
|
||||
ieResRef daymovies[8];
|
||||
ieResRef nightmovies[8];
|
||||
int MapIndex;
|
||||
public:
|
||||
std::vector< Actor*> selected;
|
||||
int version;
|
||||
Variables* kaputz;
|
||||
ieByte* beasts;
|
||||
ieByte* mazedata; //only in PST
|
||||
ieResRef Familiars[9];
|
||||
ieDword CombatCounter;
|
||||
ieDword StateOverrideFlag, StateOverrideTime;
|
||||
ieDword BanterBlockFlag, BanterBlockTime;
|
||||
|
||||
/** Index of PC selected in non-walking environment (shops, inventory...) */
|
||||
int SelectedSingle;
|
||||
/** 0 if the protagonist's death doesn't cause game over */
|
||||
/** 1 if the protagonist's death causes game over */
|
||||
/** 2 if no check is needed (pst) */
|
||||
int protagonist;
|
||||
/** if party size exceeds this amount, a callback will be called */
|
||||
size_t partysize;
|
||||
ieDword Ticks;
|
||||
ieDword interval; // 1000/AI_UPDATE (a tenth of a round in ms)
|
||||
ieDword GameTime;
|
||||
ieDword LastScriptUpdate; // GameTime at which UpdateScripts last ran
|
||||
ieDword RealTime;
|
||||
ieWord WhichFormation;
|
||||
ieWord Formations[5];
|
||||
ieDword PartyGold;
|
||||
ieWord NpcInParty;
|
||||
ieWord WeatherBits;
|
||||
ieDword Unknown48; //still unknown
|
||||
ieDword Reputation;
|
||||
ieDword ControlStatus; // used in bg2, iwd (where you can switch panes off)
|
||||
ieDword Expansion; // mostly used by BG2. IWD games set it to 3 on newgame
|
||||
ieResRef AnotherArea;
|
||||
ieResRef CurrentArea;
|
||||
ieResRef PreviousArea; //move here if the worldmap exit is illegal?
|
||||
ieResRef LoadMos;
|
||||
Actor *timestop_owner;
|
||||
ieDword timestop_end;
|
||||
Particles *weather;
|
||||
int event_timer;
|
||||
EventHandler event_handler; //like in Control
|
||||
bool hasInfra;
|
||||
bool familiarBlock;
|
||||
bool PartyAttack;
|
||||
private:
|
||||
/** reads the challenge rating table */
|
||||
void LoadCRTable();
|
||||
public:
|
||||
/** Returns the PC's slot count for partyID */
|
||||
int FindPlayer(unsigned int partyID);
|
||||
/** Returns actor by slot */
|
||||
Actor* GetPC(unsigned int slot, bool onlyalive);
|
||||
/** Finds an actor in party by party ID, returns Actor, if not there, returns NULL*/
|
||||
Actor* FindPC(unsigned int partyID);
|
||||
Actor* FindNPC(unsigned int partyID);
|
||||
/** Finds a global actor by global ID */
|
||||
Actor* GetGlobalActorByGlobalID(ieDword globalID);
|
||||
/** Finds an actor in party, returns slot, if not there, returns -1*/
|
||||
int InParty(Actor* pc) const;
|
||||
/** Finds an actor in store, returns slot, if not there, returns -1*/
|
||||
int InStore(Actor* pc) const;
|
||||
/** Finds an actor in party by scripting name*/
|
||||
Actor* FindPC(const char *deathvar);
|
||||
/** Finds an actor in store by scripting name*/
|
||||
Actor* FindNPC(const char *deathvar);
|
||||
/** Sets the area and position of the actor to the starting position */
|
||||
void InitActorPos(Actor *actor);
|
||||
/** Joins party */
|
||||
int JoinParty(Actor* pc, int join=JP_JOIN);
|
||||
/** Return current party size */
|
||||
int GetPartySize(bool onlyalive) const;
|
||||
/** Returns the npcs count */
|
||||
int GetNPCCount() const { return (int)NPCs.size(); }
|
||||
/** Sends the hotkey trigger to all selected pcs */
|
||||
void SetHotKey(unsigned long Key);
|
||||
/** Select PC for non-walking environment (shops, inventory, ...) */
|
||||
bool SelectPCSingle(int index);
|
||||
/** Get index of selected PC for non-walking env (shops, inventory, ...) */
|
||||
int GetSelectedPCSingle() const;
|
||||
/** (De)selects actor. */
|
||||
bool SelectActor( Actor* actor, bool select, unsigned flags );
|
||||
|
||||
/** Return current party level count for xp calculations */
|
||||
int GetPartyLevel(bool onlyalive) const;
|
||||
/** Reassigns inparty numbers, call it after party creation */
|
||||
void ConsolidateParty();
|
||||
/** Removes actor from party (if in there) */
|
||||
int LeaveParty(Actor* pc);
|
||||
/** Returns slot*/
|
||||
int DelPC(unsigned int slot, bool autoFree = false);
|
||||
int DelNPC(unsigned int slot, bool autoFree = false);
|
||||
/** Returns map in index */
|
||||
Map* GetMap(unsigned int index) const;
|
||||
/** Returns a map from area name, loads it if needed
|
||||
* use it for the biggest safety, change = true will change the current map */
|
||||
Map* GetMap(const char *areaname, bool change);
|
||||
/** Returns slot of the map if found */
|
||||
int FindMap(const char *ResRef);
|
||||
int AddMap(Map* map);
|
||||
/** Determine if area is master area*/
|
||||
bool MasterArea(const char *area);
|
||||
/** Dynamically adding an area to master areas*/
|
||||
void SetMasterArea(const char *area);
|
||||
/** Returns slot of the map, if it was already loaded,
|
||||
* don't load it again, set changepf == true,
|
||||
* if you want to change the pathfinder too. */
|
||||
int LoadMap(const char* ResRef, bool loadscreen);
|
||||
int DelMap(unsigned int index, int forced = 0);
|
||||
int AddNPC(Actor* npc);
|
||||
Actor* GetNPC(unsigned int Index);
|
||||
void SwapPCs(unsigned int Index1, unsigned int Index2);
|
||||
bool IsDay();
|
||||
|
||||
//journal entries
|
||||
/** Deletes one or all journal entries if strref is -1 */
|
||||
void DeleteJournalEntry(ieStrRef strref);
|
||||
/** Delete entries of the same group */
|
||||
void DeleteJournalGroup(int Group);
|
||||
/** Adds a journal entry from dialog data.
|
||||
* Time and chapter are calculated on the fly
|
||||
* Returns false if the entry already exists */
|
||||
bool AddJournalEntry(ieStrRef strref, int section, int group);
|
||||
/** Adds a journal entry while loading the .gam structure */
|
||||
void AddJournalEntry(GAMJournalEntry* entry);
|
||||
unsigned int GetJournalCount() const;
|
||||
GAMJournalEntry* FindJournalEntry(ieStrRef strref);
|
||||
GAMJournalEntry* GetJournalEntry(unsigned int Index);
|
||||
|
||||
//saved locations
|
||||
unsigned int GetSavedLocationCount() const;
|
||||
void ClearSavedLocations();
|
||||
GAMLocationEntry* GetSavedLocationEntry(unsigned int Index);
|
||||
|
||||
//plane locations
|
||||
unsigned int GetPlaneLocationCount() const;
|
||||
void ClearPlaneLocations();
|
||||
GAMLocationEntry* GetPlaneLocationEntry(unsigned int Index);
|
||||
|
||||
char *GetFamiliar(unsigned int Index);
|
||||
|
||||
bool IsBeastKnown(unsigned int Index) const {
|
||||
if (!beasts) {
|
||||
return false;
|
||||
}
|
||||
if (Index>=BESTIARY_SIZE) {
|
||||
return false;
|
||||
}
|
||||
return beasts[Index] != 0;
|
||||
}
|
||||
void SetBeastKnown(unsigned int Index) {
|
||||
if (!beasts) {
|
||||
return;
|
||||
}
|
||||
if (Index>=BESTIARY_SIZE) {
|
||||
return;
|
||||
}
|
||||
beasts[Index] = 1;
|
||||
}
|
||||
ieWord GetFormation() const {
|
||||
if (WhichFormation>4) {
|
||||
return 0;
|
||||
}
|
||||
return Formations[WhichFormation];
|
||||
}
|
||||
|
||||
/** converts challenge rating to xp */
|
||||
int GetXPFromCR(int cr);
|
||||
/** shares XP among all party members */
|
||||
void ShareXP(int XP, int flags);
|
||||
/** returns true if we should start the party overflow window */
|
||||
bool PartyOverflow() const;
|
||||
/** returns true if any pc is attacker or being attacked */
|
||||
bool AnyPCInCombat() const;
|
||||
/** returns true if the party death condition is true */
|
||||
bool EveryoneDead() const;
|
||||
/** returns true if no one moves */
|
||||
bool EveryoneStopped() const;
|
||||
bool EveryoneNearPoint(Map *map, const Point &p, int flags) const;
|
||||
/** a party member just died now */
|
||||
void PartyMemberDied(Actor *);
|
||||
/** Increments chapter variable and refreshes kill stats */
|
||||
void IncrementChapter();
|
||||
/** Sets party reputation */
|
||||
void SetReputation(ieDword r);
|
||||
/** Sets the gamescreen control status (pane states, dialog textarea size) */
|
||||
void SetControlStatus(int value, int operation);
|
||||
/** Sets party size (1-32000) */
|
||||
void SetPartySize(int value);
|
||||
/** Sets a guiscript function to happen after x AI cycles have elapsed */
|
||||
void SetTimedEvent(EventHandler func, int count);
|
||||
/** Sets protagonist mode to 0-none,1-protagonist,2-team */
|
||||
void SetProtagonistMode(int value);
|
||||
void StartRainOrSnow(bool conditional, int weather);
|
||||
size_t GetLoadedMapCount() const { return Maps.size(); }
|
||||
/** Adds or removes gold */
|
||||
void AddGold(ieDword add);
|
||||
/** Adds ticks to game time */
|
||||
void AdvanceTime(ieDword add);
|
||||
/** Runs the script engine on the global script and the area scripts
|
||||
areas run scripts on door, infopoint, container, actors too */
|
||||
void UpdateScripts();
|
||||
/** runs area functionality, sets partyrested trigger */
|
||||
void RestParty(int checks, int dream, int hp);
|
||||
/** timestop effect initiated by actor */
|
||||
void TimeStop(Actor *actor, ieDword end);
|
||||
/** check if the passed actor is a victim of timestop */
|
||||
bool TimeStoppedFor(const Actor* target=NULL);
|
||||
/** updates the infravision info */
|
||||
void Infravision();
|
||||
/** gets the colour which should be applied over the game area,
|
||||
may return NULL */
|
||||
const Color *GetGlobalTint() const;
|
||||
/** returns true if party has infravision */
|
||||
bool PartyHasInfravision() const { return hasInfra; }
|
||||
/** draw weather */
|
||||
void DrawWeather(const Region &screen, bool update);
|
||||
/** updates current area music */
|
||||
void ChangeSong(bool always = true, bool force = true);
|
||||
/** sets expansion mode */
|
||||
void SetExpansion(ieDword value);
|
||||
/** Dumps information about the object */
|
||||
void DebugDump();
|
||||
/** Finds an actor by global ID */
|
||||
Actor *GetActorByGlobalID(ieDword objectID);
|
||||
/** Allocates maze data */
|
||||
ieByte *AllocateMazeData();
|
||||
/** Checks if any timestop effects are active */
|
||||
bool IsTimestopActive();
|
||||
private:
|
||||
bool DetermineStartPosType(const TableMgr *strta);
|
||||
ieResRef *GetDream(Map *area);
|
||||
void PlayerDream();
|
||||
};
|
||||
|
||||
#endif // ! GAME_H
|
||||
@@ -1,549 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003-2005 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GameData.h"
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
#include "ActorMgr.h"
|
||||
#include "AnimationMgr.h"
|
||||
#include "Cache.h"
|
||||
#include "CharAnimations.h"
|
||||
#include "Effect.h"
|
||||
#include "EffectMgr.h"
|
||||
#include "Factory.h"
|
||||
#include "Game.h"
|
||||
#include "ImageFactory.h"
|
||||
#include "ImageMgr.h"
|
||||
#include "Interface.h"
|
||||
#include "Item.h"
|
||||
#include "ItemMgr.h"
|
||||
#include "PluginMgr.h"
|
||||
#include "ResourceDesc.h"
|
||||
#include "ScriptedAnimation.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "StoreMgr.h"
|
||||
#include "Scriptable/Actor.h"
|
||||
#include "System/FileStream.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
static void ReleaseItem(void *poi)
|
||||
{
|
||||
delete ((Item *) poi);
|
||||
}
|
||||
|
||||
static void ReleaseSpell(void *poi)
|
||||
{
|
||||
delete ((Spell *) poi);
|
||||
}
|
||||
|
||||
static void ReleaseEffect(void *poi)
|
||||
{
|
||||
delete ((Effect *) poi);
|
||||
}
|
||||
|
||||
static void ReleasePalette(void *poi)
|
||||
{
|
||||
//we allow nulls, but we shouldn't release them
|
||||
if (!poi) return;
|
||||
//as long as palette has its own refcount, this should be Release
|
||||
((Palette *) poi)->Release();
|
||||
}
|
||||
|
||||
GEM_EXPORT GameData* gamedata;
|
||||
|
||||
GameData::GameData()
|
||||
{
|
||||
factory = new Factory();
|
||||
}
|
||||
|
||||
GameData::~GameData()
|
||||
{
|
||||
delete factory;
|
||||
}
|
||||
|
||||
void GameData::ClearCaches()
|
||||
{
|
||||
ItemCache.RemoveAll(ReleaseItem);
|
||||
SpellCache.RemoveAll(ReleaseSpell);
|
||||
EffectCache.RemoveAll(ReleaseEffect);
|
||||
PaletteCache.RemoveAll(ReleasePalette);
|
||||
}
|
||||
|
||||
Actor *GameData::GetCreature(const char* ResRef, unsigned int PartySlot)
|
||||
{
|
||||
DataStream* ds = GetResource( ResRef, IE_CRE_CLASS_ID );
|
||||
if (!ds)
|
||||
return 0;
|
||||
|
||||
PluginHolder<ActorMgr> actormgr(IE_CRE_CLASS_ID);
|
||||
if (!actormgr->Open(ds)) {
|
||||
return 0;
|
||||
}
|
||||
Actor* actor = actormgr->GetActor(PartySlot);
|
||||
return actor;
|
||||
}
|
||||
|
||||
int GameData::LoadCreature(const char* ResRef, unsigned int PartySlot, bool character, int VersionOverride)
|
||||
{
|
||||
DataStream *stream;
|
||||
|
||||
Actor* actor;
|
||||
if (character) {
|
||||
char nPath[_MAX_PATH], fName[16];
|
||||
snprintf( fName, sizeof(fName), "%s.chr", ResRef);
|
||||
PathJoin( nPath, core->GamePath, "characters", fName, NULL );
|
||||
stream = FileStream::OpenFile(nPath);
|
||||
PluginHolder<ActorMgr> actormgr(IE_CRE_CLASS_ID);
|
||||
if (!actormgr->Open(stream)) {
|
||||
return -1;
|
||||
}
|
||||
actor = actormgr->GetActor(PartySlot);
|
||||
} else {
|
||||
actor = GetCreature(ResRef, PartySlot);
|
||||
}
|
||||
|
||||
if ( !actor ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (VersionOverride != -1) {
|
||||
actor->version = VersionOverride;
|
||||
}
|
||||
|
||||
//both fields are of length 9, make this sure!
|
||||
memcpy(actor->Area, core->GetGame()->CurrentArea, sizeof(actor->Area) );
|
||||
if (actor->BaseStats[IE_STATE_ID] & STATE_DEAD) {
|
||||
actor->SetStance( IE_ANI_TWITCH );
|
||||
} else {
|
||||
actor->SetStance( IE_ANI_AWAKE );
|
||||
}
|
||||
actor->SetOrientation( 0, false );
|
||||
|
||||
if ( PartySlot != 0 ) {
|
||||
return core->GetGame()->JoinParty( actor, JP_JOIN|JP_INITPOS );
|
||||
}
|
||||
else {
|
||||
return core->GetGame()->AddNPC( actor );
|
||||
}
|
||||
}
|
||||
|
||||
/** Loads a 2DA Table, returns -1 on error or the Table Index on success */
|
||||
int GameData::LoadTable(const ieResRef ResRef)
|
||||
{
|
||||
int ind = GetTableIndex( ResRef );
|
||||
if (ind != -1) {
|
||||
tables[ind].refcount++;
|
||||
return ind;
|
||||
}
|
||||
//print("(%s) Table not found... Loading from file\n", ResRef);
|
||||
DataStream* str = GetResource( ResRef, IE_2DA_CLASS_ID );
|
||||
if (!str) {
|
||||
return -1;
|
||||
}
|
||||
PluginHolder<TableMgr> tm(IE_2DA_CLASS_ID);
|
||||
if (!tm) {
|
||||
delete str;
|
||||
return -1;
|
||||
}
|
||||
if (!tm->Open(str)) {
|
||||
return -1;
|
||||
}
|
||||
Table t;
|
||||
t.refcount = 1;
|
||||
strncpy( t.ResRef, ResRef, 8 );
|
||||
t.tm = tm;
|
||||
ind = -1;
|
||||
for (size_t i = 0; i < tables.size(); i++) {
|
||||
if (tables[i].refcount == 0) {
|
||||
ind = ( int ) i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ind != -1) {
|
||||
tables[ind] = t;
|
||||
return ind;
|
||||
}
|
||||
tables.push_back( t );
|
||||
return ( int ) tables.size() - 1;
|
||||
}
|
||||
/** Gets the index of a loaded table, returns -1 on error */
|
||||
int GameData::GetTableIndex(const char* ResRef) const
|
||||
{
|
||||
for (size_t i = 0; i < tables.size(); i++) {
|
||||
if (tables[i].refcount == 0)
|
||||
continue;
|
||||
if (strnicmp( tables[i].ResRef, ResRef, 8 ) == 0)
|
||||
return ( int ) i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/** Gets a Loaded Table by its index, returns NULL on error */
|
||||
Holder<TableMgr> GameData::GetTable(unsigned int index) const
|
||||
{
|
||||
if (index >= tables.size()) {
|
||||
return NULL;
|
||||
}
|
||||
if (tables[index].refcount == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return tables[index].tm;
|
||||
}
|
||||
|
||||
/** Frees a Loaded Table, returns false on error, true on success */
|
||||
bool GameData::DelTable(unsigned int index)
|
||||
{
|
||||
if (index==0xffffffff) {
|
||||
tables.clear();
|
||||
return true;
|
||||
}
|
||||
if (index >= tables.size()) {
|
||||
return false;
|
||||
}
|
||||
if (tables[index].refcount == 0) {
|
||||
return false;
|
||||
}
|
||||
tables[index].refcount--;
|
||||
if (tables[index].refcount == 0)
|
||||
if (tables[index].tm)
|
||||
tables[index].tm.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
Palette *GameData::GetPalette(const ieResRef resname)
|
||||
{
|
||||
Palette *palette = (Palette *) PaletteCache.GetResource(resname);
|
||||
if (palette) {
|
||||
return palette;
|
||||
}
|
||||
//additional hack for allowing NULL's
|
||||
if (PaletteCache.RefCount(resname)!=-1) {
|
||||
return NULL;
|
||||
}
|
||||
ResourceHolder<ImageMgr> im(resname);
|
||||
if (im == NULL) {
|
||||
PaletteCache.SetAt(resname, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
palette = new Palette();
|
||||
im->GetPalette(256,palette->col);
|
||||
palette->named=true;
|
||||
PaletteCache.SetAt(resname, (void *) palette);
|
||||
return palette;
|
||||
}
|
||||
|
||||
void GameData::FreePalette(Palette *&pal, const ieResRef name)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (!pal) {
|
||||
return;
|
||||
}
|
||||
if (!name || !name[0]) {
|
||||
if(pal->named) {
|
||||
error("GameData", "Palette is supposed to be named, but got no name!\n");
|
||||
} else {
|
||||
pal->Release();
|
||||
pal=NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!pal->named) {
|
||||
error("GameData", "Unnamed palette, it should be %s!\n", name);
|
||||
}
|
||||
res=PaletteCache.DecRef((void *) pal, name, true);
|
||||
if (res<0) {
|
||||
error("Core", "Corrupted Palette cache encountered (reference count went below zero), Palette name is: %.8s\n", name);
|
||||
}
|
||||
if (!res) {
|
||||
pal->Release();
|
||||
}
|
||||
pal = NULL;
|
||||
}
|
||||
|
||||
Item* GameData::GetItem(const ieResRef resname)
|
||||
{
|
||||
Item *item = (Item *) ItemCache.GetResource(resname);
|
||||
if (item) {
|
||||
return item;
|
||||
}
|
||||
DataStream* str = GetResource( resname, IE_ITM_CLASS_ID );
|
||||
PluginHolder<ItemMgr> sm(IE_ITM_CLASS_ID);
|
||||
if (!sm) {
|
||||
delete ( str );
|
||||
return NULL;
|
||||
}
|
||||
if (!sm->Open(str)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item = new Item();
|
||||
//this is required for storing the 'source'
|
||||
strnlwrcpy(item->Name, resname, 8);
|
||||
sm->GetItem( item );
|
||||
if (item == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ItemCache.SetAt(resname, (void *) item);
|
||||
return item;
|
||||
}
|
||||
|
||||
//you can supply name for faster access
|
||||
void GameData::FreeItem(Item const *itm, const ieResRef name, bool free)
|
||||
{
|
||||
int res;
|
||||
|
||||
res=ItemCache.DecRef((void *) itm, name, free);
|
||||
if (res<0) {
|
||||
error("Core", "Corrupted Item cache encountered (reference count went below zero), Item name is: %.8s\n", name);
|
||||
}
|
||||
if (res) return;
|
||||
if (free) delete itm;
|
||||
}
|
||||
|
||||
Spell* GameData::GetSpell(const ieResRef resname, bool silent)
|
||||
{
|
||||
Spell *spell = (Spell *) SpellCache.GetResource(resname);
|
||||
if (spell) {
|
||||
return spell;
|
||||
}
|
||||
DataStream* str = GetResource( resname, IE_SPL_CLASS_ID, silent );
|
||||
PluginHolder<SpellMgr> sm(IE_SPL_CLASS_ID);
|
||||
if (!sm) {
|
||||
delete ( str );
|
||||
return NULL;
|
||||
}
|
||||
if (!sm->Open(str)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spell = new Spell();
|
||||
//this is required for storing the 'source'
|
||||
strnlwrcpy(spell->Name, resname, 8);
|
||||
sm->GetSpell( spell, silent );
|
||||
if (spell == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SpellCache.SetAt(resname, (void *) spell);
|
||||
return spell;
|
||||
}
|
||||
|
||||
void GameData::FreeSpell(Spell *spl, const ieResRef name, bool free)
|
||||
{
|
||||
int res;
|
||||
|
||||
res=SpellCache.DecRef((void *) spl, name, free);
|
||||
if (res<0) {
|
||||
printMessage("Core", "Corrupted Spell cache encountered (reference count went below zero), Spell name is: %.8s or %.8s\n", LIGHT_RED,
|
||||
name, spl->Name);
|
||||
abort();
|
||||
}
|
||||
if (res) return;
|
||||
if (free) delete spl;
|
||||
}
|
||||
|
||||
Effect* GameData::GetEffect(const ieResRef resname)
|
||||
{
|
||||
Effect *effect = (Effect *) EffectCache.GetResource(resname);
|
||||
if (effect) {
|
||||
return effect;
|
||||
}
|
||||
DataStream* str = GetResource( resname, IE_EFF_CLASS_ID );
|
||||
PluginHolder<EffectMgr> em(IE_EFF_CLASS_ID);
|
||||
if (!em) {
|
||||
delete ( str );
|
||||
return NULL;
|
||||
}
|
||||
if (!em->Open(str)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
effect = em->GetEffect(new Effect() );
|
||||
if (effect == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EffectCache.SetAt(resname, (void *) effect);
|
||||
return effect;
|
||||
}
|
||||
|
||||
void GameData::FreeEffect(Effect *eff, const ieResRef name, bool free)
|
||||
{
|
||||
int res;
|
||||
|
||||
res=EffectCache.DecRef((void *) eff, name, free);
|
||||
if (res<0) {
|
||||
error("Core", "Corrupted Effect cache encountered (reference count went below zero), Effect name is: %.8s\n", name);
|
||||
}
|
||||
if (res) return;
|
||||
if (free) delete eff;
|
||||
}
|
||||
|
||||
//if the default setup doesn't fit for an animation
|
||||
//create a vvc for it!
|
||||
ScriptedAnimation* GameData::GetScriptedAnimation( const char *effect, bool doublehint)
|
||||
{
|
||||
ScriptedAnimation *ret = NULL;
|
||||
|
||||
if (Exists( effect, IE_VVC_CLASS_ID, true ) ) {
|
||||
DataStream *ds = GetResource( effect, IE_VVC_CLASS_ID );
|
||||
ret = new ScriptedAnimation(ds);
|
||||
} else {
|
||||
AnimationFactory *af = (AnimationFactory *)
|
||||
GetFactoryResource( effect, IE_BAM_CLASS_ID, IE_NORMAL );
|
||||
if (af) {
|
||||
ret = new ScriptedAnimation();
|
||||
ret->LoadAnimationFactory( af, doublehint?2:0);
|
||||
}
|
||||
}
|
||||
if (ret) {
|
||||
strnlwrcpy(ret->ResName, effect, 8);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Return single BAM frame as a sprite. Use if you want one frame only,
|
||||
// otherwise it's not efficient
|
||||
Sprite2D* GameData::GetBAMSprite(const ieResRef ResRef, int cycle, int frame)
|
||||
{
|
||||
Sprite2D *tspr;
|
||||
AnimationFactory* af = ( AnimationFactory* )
|
||||
GetFactoryResource( ResRef, IE_BAM_CLASS_ID, IE_NORMAL );
|
||||
if (!af) return 0;
|
||||
if (cycle == -1)
|
||||
tspr = af->GetFrameWithoutCycle( (unsigned short) frame );
|
||||
else
|
||||
tspr = af->GetFrame( (unsigned short) frame, (unsigned char) cycle );
|
||||
return tspr;
|
||||
}
|
||||
|
||||
void* GameData::GetFactoryResource(const char* resname, SClass_ID type,
|
||||
unsigned char mode, bool silent)
|
||||
{
|
||||
int fobjindex = factory->IsLoaded(resname,type);
|
||||
// already cached
|
||||
if ( fobjindex != -1)
|
||||
return factory->GetFactoryObject( fobjindex );
|
||||
|
||||
// empty resref
|
||||
if (!strcmp(resname, ""))
|
||||
return NULL;
|
||||
|
||||
switch (type) {
|
||||
case IE_BAM_CLASS_ID:
|
||||
{
|
||||
DataStream* ret = GetResource( resname, type, silent );
|
||||
if (ret) {
|
||||
PluginHolder<AnimationMgr> ani(IE_BAM_CLASS_ID);
|
||||
if (!ani)
|
||||
return NULL;
|
||||
if (!ani->Open(ret))
|
||||
return NULL;
|
||||
AnimationFactory* af = ani->GetAnimationFactory( resname, mode );
|
||||
factory->AddFactoryObject( af );
|
||||
return af;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
case IE_BMP_CLASS_ID:
|
||||
{
|
||||
ResourceHolder<ImageMgr> img(resname);
|
||||
if (img) {
|
||||
ImageFactory* fact = img->GetImageFactory( resname );
|
||||
factory->AddFactoryObject( fact );
|
||||
return fact;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
default:
|
||||
print( "\n" );
|
||||
printMessage("KEYImporter", "%s files are not supported.\n", WHITE,
|
||||
core->TypeExt(type));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Store* GameData::GetStore(const ieResRef ResRef)
|
||||
{
|
||||
StoreMap::iterator it = stores.find(ResRef);
|
||||
if (it != stores.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
DataStream* str = gamedata->GetResource(ResRef, IE_STO_CLASS_ID);
|
||||
PluginHolder<StoreMgr> sm(IE_STO_CLASS_ID);
|
||||
if (sm == NULL) {
|
||||
delete ( str );
|
||||
return NULL;
|
||||
}
|
||||
if (!sm->Open(str)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Store* store = sm->GetStore(new Store());
|
||||
if (store == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
strnlwrcpy(store->Name, ResRef, 8);
|
||||
// The key needs to last as long as the store,
|
||||
// so use the one we just copied.
|
||||
stores[store->Name] = store;
|
||||
return store;
|
||||
}
|
||||
|
||||
void GameData::SaveStore(Store* store)
|
||||
{
|
||||
if (!store)
|
||||
return;
|
||||
StoreMap::iterator it = stores.find(store->Name);
|
||||
if (it == stores.end()) {
|
||||
error("GameData", "Saving a store that wasn't cached.");
|
||||
}
|
||||
|
||||
PluginHolder<StoreMgr> sm(IE_STO_CLASS_ID);
|
||||
if (sm == NULL) {
|
||||
error("GameData", "Can't save store to cache.");
|
||||
}
|
||||
|
||||
FileStream str;
|
||||
|
||||
if (!str.Create(store->Name, IE_STO_CLASS_ID)) {
|
||||
error("GameData", "Can't create file while saving store.");
|
||||
}
|
||||
if (!sm->PutStore(&str, store)) {
|
||||
error("GameData", "Error saving store.");
|
||||
}
|
||||
|
||||
stores.erase(it);
|
||||
delete store;
|
||||
}
|
||||
|
||||
void GameData::SaveAllStores()
|
||||
{
|
||||
while (!stores.empty()) {
|
||||
SaveStore(stores.begin()->second);
|
||||
}
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GAMEDATA_H
|
||||
#define GAMEDATA_H
|
||||
|
||||
#include "SClassID.h"
|
||||
#include "exports.h"
|
||||
#include "ie_types.h"
|
||||
#include "iless.h"
|
||||
|
||||
#include "Cache.h"
|
||||
#include "Holder.h"
|
||||
#include "ResourceManager.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _MSC_VER // No SFINAE
|
||||
#include "TableMgr.h"
|
||||
#endif
|
||||
|
||||
class Actor;
|
||||
struct Effect;
|
||||
class Factory;
|
||||
class Item;
|
||||
class Palette;
|
||||
class ScriptedAnimation;
|
||||
class Spell;
|
||||
class Sprite2D;
|
||||
class TableMgr;
|
||||
class Store;
|
||||
|
||||
struct Table {
|
||||
Holder<TableMgr> tm;
|
||||
char ResRef[8];
|
||||
unsigned int refcount;
|
||||
};
|
||||
|
||||
class GEM_EXPORT GameData : public ResourceManager
|
||||
{
|
||||
public:
|
||||
GameData();
|
||||
~GameData();
|
||||
|
||||
void ClearCaches();
|
||||
|
||||
/** Returns actor */
|
||||
Actor *GetCreature(const char *ResRef, unsigned int PartySlot=0);
|
||||
/** Returns a PC index, by loading a creature */
|
||||
int LoadCreature(const char *ResRef, unsigned int PartySlot, bool character=false, int VersionOverride=-1);
|
||||
|
||||
|
||||
// 2DA table functions.
|
||||
// (See also the AutoTable class)
|
||||
|
||||
/** Loads a 2DA Table, returns -1 on error or the Table Index on success */
|
||||
int LoadTable(const char * ResRef);
|
||||
/** Gets the index of a loaded table, returns -1 on error */
|
||||
int GetTableIndex(const char * ResRef) const;
|
||||
/** Gets a Loaded Table by its index, returns NULL on error */
|
||||
Holder<TableMgr> GetTable(unsigned int index) const;
|
||||
/** Frees a Loaded Table, returns false on error, true on success */
|
||||
bool DelTable(unsigned int index);
|
||||
|
||||
Palette* GetPalette(const ieResRef resname);
|
||||
void FreePalette(Palette *&pal, const ieResRef name=NULL);
|
||||
|
||||
Item* GetItem(const ieResRef resname);
|
||||
void FreeItem(Item const *itm, const ieResRef name, bool free=false);
|
||||
Spell* GetSpell(const ieResRef resname, bool silent=false);
|
||||
void FreeSpell(Spell *spl, const ieResRef name, bool free=false);
|
||||
Effect* GetEffect(const ieResRef resname);
|
||||
void FreeEffect(Effect *eff, const ieResRef name, bool free=false);
|
||||
|
||||
/** creates a vvc/bam animation object at point */
|
||||
ScriptedAnimation* GetScriptedAnimation( const char *ResRef, bool doublehint);
|
||||
|
||||
/** returns a single sprite (not cached) from a BAM resource */
|
||||
Sprite2D* GetBAMSprite(const ieResRef ResRef, int cycle, int frame);
|
||||
|
||||
/** returns factory resource, currently works only with animations */
|
||||
void* GetFactoryResource(const char* resname, SClass_ID type,
|
||||
unsigned char mode = IE_NORMAL, bool silent=false);
|
||||
|
||||
Store* GetStore(const ieResRef ResRef);
|
||||
/// Saves a store to the cache and frees it.
|
||||
void SaveStore(Store* store);
|
||||
/// Saves all stores in the cache
|
||||
void SaveAllStores();
|
||||
private:
|
||||
Cache ItemCache;
|
||||
Cache SpellCache;
|
||||
Cache EffectCache;
|
||||
Cache PaletteCache;
|
||||
Factory* factory;
|
||||
std::vector<Table> tables;
|
||||
typedef std::map<const char*, Store*, iless> StoreMap;
|
||||
StoreMap stores;
|
||||
};
|
||||
|
||||
extern GEM_EXPORT GameData * gamedata;
|
||||
|
||||
template <class T>
|
||||
class ResourceHolder : public Holder<T>
|
||||
{
|
||||
public:
|
||||
ResourceHolder()
|
||||
{
|
||||
}
|
||||
ResourceHolder(const char* resname)
|
||||
: Holder<T>(static_cast<T*>(gamedata->GetResource(resname,&T::ID)))
|
||||
{
|
||||
}
|
||||
ResourceHolder(const char* resname, const ResourceManager& manager, bool silent = false)
|
||||
: Holder<T>(static_cast<T*>(manager.GetResource(resname,&T::ID,silent)))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,140 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
#ifndef GSUTILS_H
|
||||
#define GSUTILS_H
|
||||
|
||||
#include "GameScript/GameScript.h"
|
||||
|
||||
#include "defsounds.h"
|
||||
#include "exports.h"
|
||||
#include "strrefs.h"
|
||||
|
||||
#include "Interface.h"
|
||||
|
||||
//indebug flags
|
||||
#define ID_REFERENCE 1
|
||||
#define ID_CUTSCENE 2
|
||||
#define ID_VARIABLES 4
|
||||
#define ID_ACTIONS 8
|
||||
#define ID_TRIGGERS 16
|
||||
|
||||
extern Holder<SymbolMgr> triggersTable;
|
||||
extern Holder<SymbolMgr> actionsTable;
|
||||
extern Holder<SymbolMgr> overrideActionsTable;
|
||||
extern Holder<SymbolMgr> objectsTable;
|
||||
extern TriggerFunction triggers[MAX_TRIGGERS];
|
||||
extern ActionFunction actions[MAX_ACTIONS];
|
||||
extern short actionflags[MAX_ACTIONS];
|
||||
extern short triggerflags[MAX_TRIGGERS];
|
||||
extern ObjectFunction objects[MAX_OBJECTS];
|
||||
extern IDSFunction idtargets[MAX_OBJECT_FIELDS];
|
||||
extern Cache SrcCache; //cache for string resources (pst)
|
||||
extern Cache BcsCache; //cache for scripts
|
||||
extern int ObjectIDSCount;
|
||||
extern int MaxObjectNesting;
|
||||
extern bool HasAdditionalRect;
|
||||
extern bool HasTriggerPoint;
|
||||
extern bool NoCreate;
|
||||
extern bool HasKaputz;
|
||||
extern ieResRef *ObjectIDSTableNames;
|
||||
extern int ObjectFieldsCount;
|
||||
extern int ExtraParametersCount;
|
||||
extern int InDebug;
|
||||
extern Gem_Polygon **polygons;
|
||||
|
||||
#define MIC_INVALID -2
|
||||
#define MIC_FULL -1
|
||||
#define MIC_NOITEM 0
|
||||
#define MIC_GOTITEM 1
|
||||
|
||||
GEM_EXPORT int GetReaction(Actor *target, Scriptable *Sender);
|
||||
int GetHappiness(Scriptable *Sender, int reputation);
|
||||
int GetHPPercent(Scriptable *Sender);
|
||||
bool StoreHasItemCore(const ieResRef storename, const ieResRef itemname);
|
||||
bool HasItemCore(Inventory *inventory, const ieResRef itemname, ieDword flags);
|
||||
void ClickCore(Scriptable *Sender, Point point, int type, int speed);
|
||||
void TransformItemCore(Actor *actor, Action *parameters, bool onlyone);
|
||||
void CreateVisualEffectCore(Actor *target, const char *effect, int iterations);
|
||||
void CreateVisualEffectCore(Scriptable *Sender, const Point &position, const char *effect, int iterations);
|
||||
void GetPositionFromScriptable(Scriptable* scr, Point &position, bool trap);
|
||||
void BeginDialog(Scriptable* Sender, Action* parameters, int flags);
|
||||
void ChangeAnimationCore(Actor *src, const char *resref, bool effect);
|
||||
void PolymorphCopyCore(Actor *src, Actor *tar, bool base);
|
||||
void CreateCreatureCore(Scriptable* Sender, Action* parameters, int flags);
|
||||
int MoveItemCore(Scriptable *Sender, Scriptable *target, const char *resref, int flags, int setflag);
|
||||
void MoveToObjectCore(Scriptable *Sender, Action *parameters, ieDword flags, bool untilsee);
|
||||
bool CreateItemCore(CREItem *item, const char *resref, int a, int b, int c);
|
||||
void AttackCore(Scriptable *Sender, Scriptable *target, int flags);
|
||||
void InitScriptTables();
|
||||
void HandleBitMod(ieDword &value1, ieDword value2, int opcode);
|
||||
bool ResolveSpellName(ieResRef spellres, Action *parameter);
|
||||
GEM_EXPORT void ResolveSpellName(ieResRef spellres, ieDword number);
|
||||
GEM_EXPORT ieDword ResolveSpellNumber(const ieResRef spellres);
|
||||
bool ResolveItemName(ieResRef itemres, Actor *act, ieDword Slot);
|
||||
void EscapeAreaCore(Scriptable *Sender, const Point &p, const char *area, const Point &enter, int flags, int wait);
|
||||
void GoNear(Scriptable *Sender, const Point &p);
|
||||
void MoveNearerTo(Scriptable *Sender, Scriptable *target, int distance);
|
||||
int MoveNearerTo(Scriptable *Sender, const Point &p, int distance, int no_release);
|
||||
|
||||
#define NO_OPERATION -1
|
||||
#define LESS_OR_EQUALS 0
|
||||
//iwd2 diffmode with gemrb enhancements
|
||||
#define EQUALS 1
|
||||
#define LESS_THAN 2
|
||||
#define GREATER_THAN 3
|
||||
#define GREATER_OR_EQUALS 4
|
||||
#define NOT_EQUALS 5
|
||||
#define BINARY_LESS_OR_EQUALS 6 //(left has only bits in right)
|
||||
#define BINARY_MORE_OR_EQUALS 7 //(left has equal or more bits than right)
|
||||
#define BINARY_INTERSECT 8 //(left and right has at least one common bit)
|
||||
#define BINARY_NOT_INTERSECT 9 //(no common bits)
|
||||
#define BINARY_MORE 10 //left has more bits than right
|
||||
#define BINARY_LESS 11 //left has less bits than right
|
||||
|
||||
GEM_EXPORT int GetGroup(Actor *actor);
|
||||
|
||||
GEM_EXPORT void FreeSrc(SrcVector *poi, const ieResRef key);
|
||||
GEM_EXPORT SrcVector *LoadSrc(const ieResRef resname);
|
||||
Action *ParamCopy(Action *parameters);
|
||||
Action *ParamCopyNoOverride(Action *parameters);
|
||||
void SetVariable(Scriptable* Sender, const char* VarName, ieDword value);
|
||||
Point GetEntryPoint(const char *areaname, const char *entryname);
|
||||
//these are used from other plugins
|
||||
GEM_EXPORT int CanSee(Scriptable* Sender, Scriptable* target, bool range, int nodead);
|
||||
GEM_EXPORT int SeeCore(Scriptable* Sender, Trigger* parameters, int justlos);
|
||||
GEM_EXPORT int DiffCore(ieDword a, ieDword b, int diffmode);
|
||||
GEM_EXPORT void DisplayStringCore(Scriptable* Sender, int Strref, int flags);
|
||||
GEM_EXPORT void SetVariable(Scriptable* Sender, const char* VarName, const char* Context, ieDword value);
|
||||
GEM_EXPORT void MoveBetweenAreasCore(Actor* actor, const char *area, const Point &position, int face, bool adjust);
|
||||
GEM_EXPORT ieDword CheckVariable(Scriptable* Sender, const char* VarName, bool *valid = NULL);
|
||||
GEM_EXPORT ieDword CheckVariable(Scriptable* Sender, const char* VarName, const char* Context, bool *valid = NULL);
|
||||
Action* GenerateActionCore(const char *src, const char *str, unsigned short actionID);
|
||||
Trigger *GenerateTriggerCore(const char *src, const char *str, int trIndex, int negate);
|
||||
unsigned int GetSpellDistance(const ieResRef spellres, Scriptable *Sender);
|
||||
unsigned int GetItemDistance(const ieResRef itemres, int header);
|
||||
void SetupWishCore(Scriptable *Sender, int column, int picks);
|
||||
Gem_Polygon *GetPolygon2DA(ieDword index);
|
||||
|
||||
inline int Bones(ieDword value)
|
||||
{
|
||||
return core->Roll((value&0xf000)>>12, (value&0xff0)>>8, value&15);
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,674 +0,0 @@
|
||||
/* GemRB - Infinity Engine Emulator
|
||||
* Copyright (C) 2003-2005 The GemRB Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GameScript/Matching.h"
|
||||
|
||||
#include "GameScript/GSUtils.h"
|
||||
|
||||
#include "Interface.h"
|
||||
#include "Game.h"
|
||||
#include "Map.h"
|
||||
#include "TileMap.h"
|
||||
#include "Scriptable/Container.h"
|
||||
#include "Scriptable/Door.h"
|
||||
#include "Scriptable/InfoPoint.h"
|
||||
|
||||
/* return a Targets object with a single scriptable inside */
|
||||
static inline Targets* ReturnScriptableAsTarget(Scriptable *sc)
|
||||
{
|
||||
if (!sc) return NULL;
|
||||
Targets *tgts = new Targets();
|
||||
tgts->AddTarget(sc, 0, 0);
|
||||
return tgts;
|
||||
}
|
||||
|
||||
/* do IDS filtering: [PC], [ENEMY], etc */
|
||||
static inline bool DoObjectIDSCheck(Object *oC, Actor *ac, bool *filtered) {
|
||||
for (int j = 0; j < ObjectIDSCount; j++) {
|
||||
if (!oC->objectFields[j]) {
|
||||
continue;
|
||||
}
|
||||
*filtered = true;
|
||||
IDSFunction func = idtargets[j];
|
||||
if (!func) {
|
||||
printMessage("GameScript", "Unimplemented IDS targeting opcode: %d\n", YELLOW, j);
|
||||
continue;
|
||||
}
|
||||
if (!func( ac, oC->objectFields[j] ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* do object filtering: Myself, LastAttackerOf(Player1), etc */
|
||||
static inline Targets *DoObjectFiltering(Scriptable *Sender, Targets *tgts, Object *oC, int ga_flags) {
|
||||
for (int i = 0; i < MaxObjectNesting; i++) {
|
||||
int filterid = oC->objectFilters[i];
|
||||
if (!filterid) break;
|
||||
|
||||
ObjectFunction func = objects[filterid];
|
||||
if (!func) {
|
||||
printMessage("GameScript", "Unknown object filter: %d %s\n", YELLOW,
|
||||
filterid, objectsTable->GetValue(filterid));
|
||||
continue;
|
||||
}
|
||||
|
||||
tgts = func(Sender, tgts, ga_flags);
|
||||
if (!tgts->Count()) {
|
||||
delete tgts;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return tgts;
|
||||
}
|
||||
|
||||
static EffectRef fx_protection_creature_ref = { "Protection:Creature", -1 };
|
||||
|
||||
static inline bool DoObjectChecks(Map *map, Scriptable *Sender, Actor *target, int &dist, bool ignoreinvis=false)
|
||||
{
|
||||
dist = SquaredMapDistance(Sender, target);
|
||||
|
||||
// TODO: what do we check for non-actors?
|
||||
// non-actors have a visual range (15), we should do visual range and LOS
|
||||
|
||||
if (Sender->Type == ST_ACTOR) {
|
||||
Actor *source = (Actor *)Sender;
|
||||
|
||||
// Detect() ignores invisibility completely
|
||||
if (!ignoreinvis) {
|
||||
// TODO: move this stuff into a shared function so it can be used elsewhere?
|
||||
|
||||
// SEEINVISIBLE skips these checks :-)
|
||||
if (source->Modified[IE_SEEINVISIBLE] == 0) {
|
||||
ieDword state = target->Modified[IE_STATE_ID];
|
||||
// check for invisibility
|
||||
if ((state & STATE_INVISIBLE) != 0) return false;
|
||||
// check for improved invisibility? probably not
|
||||
//if ((state & STATE_INVIS2) != 0) return false;
|
||||
}
|
||||
|
||||
// maybe this should be setting an invis flag?
|
||||
// TODO: should SEEINVISIBLE ignore this? Detect()?
|
||||
if (target->Modified[IE_AVATARREMOVAL]) return false;
|
||||
}
|
||||
|
||||
// visual range check
|
||||
int visualrange = source->Modified[IE_VISUALRANGE];
|
||||
if (dist > visualrange*visualrange) return false;
|
||||
|
||||
// LOS check
|
||||
if (!map->IsVisible(Sender->Pos, target->Pos)) return false;
|
||||
|
||||
// protection against creature
|
||||
if (target->fxqueue.HasEffect(fx_protection_creature_ref)) {
|
||||
// TODO: de-hardcode these (may not all be correct anyway)
|
||||
if (target->fxqueue.HasEffectWithParamPair(fx_protection_creature_ref, 2, source->Modified[IE_EA])) return false;
|
||||
if (target->fxqueue.HasEffectWithParamPair(fx_protection_creature_ref, 3, source->Modified[IE_GENERAL])) return false;
|
||||
if (target->fxqueue.HasEffectWithParamPair(fx_protection_creature_ref, 4, source->Modified[IE_RACE])) return false;
|
||||
if (target->fxqueue.HasEffectWithParamPair(fx_protection_creature_ref, 5, source->Modified[IE_CLASS])) return false;
|
||||
if (target->fxqueue.HasEffectWithParamPair(fx_protection_creature_ref, 6, source->Modified[IE_SPECIFIC])) return false;
|
||||
if (target->fxqueue.HasEffectWithParamPair(fx_protection_creature_ref, 7, source->Modified[IE_SEX])) return false;
|
||||
if (target->fxqueue.HasEffectWithParamPair(fx_protection_creature_ref, 8, source->Modified[IE_ALIGNMENT])) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* returns actors that match the [x.y.z] expression */
|
||||
static Targets* EvaluateObject(Map *map, Scriptable* Sender, Object* oC, int ga_flags)
|
||||
{
|
||||
// if you ActionOverride a global actor, they might not have a map :(
|
||||
// TODO: don't allow this to happen?
|
||||
if (!map) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (oC->objectName[0]) {
|
||||
//We want the object by its name... (doors/triggers don't play here!)
|
||||
Actor* aC = map->GetActor( oC->objectName, ga_flags );
|
||||
|
||||
/*if (!aC && (ga_flags&GA_GLOBAL) ) {
|
||||
aC = FindActorNearby(oC->objectName, map, ga_flags );
|
||||
}*/
|
||||
|
||||
//return here because object name/IDS targeting are mutually exclusive
|
||||
return ReturnScriptableAsTarget(aC);
|
||||
}
|
||||
|
||||
if (oC->objectFields[0]==-1) {
|
||||
// this is an internal hack, allowing us to pass actor ids around as objects
|
||||
Actor* aC = map->GetActorByGlobalID( (ieDword) oC->objectFields[1] );
|
||||
if (aC) {
|
||||
if (!aC->ValidTarget(ga_flags)) {
|
||||
return NULL;
|
||||
}
|
||||
return ReturnScriptableAsTarget(aC);
|
||||
}
|
||||
Door *door = map->GetDoorByGlobalID( (ieDword) oC->objectFields[1]);
|
||||
if (door) {
|
||||
return ReturnScriptableAsTarget(door);
|
||||
}
|
||||
|
||||
Container* cont = map->GetContainerByGlobalID((ieDword) oC->objectFields[1]);
|
||||
if (cont) {
|
||||
return ReturnScriptableAsTarget(cont);
|
||||
}
|
||||
|
||||
InfoPoint* trap = map->GetInfoPointByGlobalID((ieDword) oC->objectFields[1]);
|
||||
if (trap) {
|
||||
return ReturnScriptableAsTarget(trap);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Targets *tgts = NULL;
|
||||
|
||||
//we need to get a subset of actors from the large array
|
||||
//if this gets slow, we will need some index tables
|
||||
int i = map->GetActorCount(true);
|
||||
while (i--) {
|
||||
Actor *ac = map->GetActor(i, true);
|
||||
if (!ac) continue; // is this check really needed?
|
||||
// don't return Sender in IDS targeting!
|
||||
if (ac == Sender) continue;
|
||||
bool filtered = false;
|
||||
if (DoObjectIDSCheck(oC, ac, &filtered)) {
|
||||
if (!filtered) {
|
||||
// if no filters were applied..
|
||||
assert(!tgts);
|
||||
return NULL;
|
||||
}
|
||||
int dist;
|
||||
if (DoObjectChecks(map, Sender, ac, dist, (ga_flags & GA_DETECT) != 0)) {
|
||||
if (!tgts) tgts = new Targets();
|
||||
tgts->AddTarget((Scriptable *) ac, dist, ga_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tgts;
|
||||
}
|
||||
|
||||
Targets* GetAllObjects(Map *map, Scriptable* Sender, Object* oC, int ga_flags)
|
||||
{
|
||||
if (!oC) {
|
||||
return NULL;
|
||||
}
|
||||
Targets* tgts = EvaluateObject(map, Sender, oC, ga_flags);
|
||||
//if we couldn't find an endpoint by name or object qualifiers
|
||||
//it is not an Actor, but could still be a Door or Container (scriptable)
|
||||
if (!tgts && oC->objectName[0]) {
|
||||
return NULL;
|
||||
}
|
||||
//now lets do the object filter stuff, we create Targets because
|
||||
//it is possible to start from blank sheets using endpoint filters
|
||||
//like (Myself, Protagonist etc)
|
||||
if (!tgts) {
|
||||
tgts = new Targets();
|
||||
}
|
||||
tgts = DoObjectFiltering(Sender, tgts, oC, ga_flags);
|
||||
return tgts;
|
||||
}
|
||||
|
||||
Targets *GetAllActors(Scriptable *Sender, int ga_flags)
|
||||
{
|
||||
Map *map = Sender->GetCurrentArea();
|
||||
|
||||
int i = map->GetActorCount(true);
|
||||
Targets *tgts = new Targets();
|
||||
while (i--) {
|
||||
Actor *ac = map->GetActor(i,true);
|
||||
int dist = Distance(Sender->Pos, ac->Pos);
|
||||
tgts->AddTarget((Scriptable *) ac, dist, ga_flags);
|
||||
}
|
||||
return tgts;
|
||||
}
|
||||
|
||||
/* get a non-actor object from a map, by name */
|
||||
Scriptable *GetActorObject(TileMap *TMap, const char *name)
|
||||
{
|
||||
Scriptable * aC = TMap->GetDoor( name );
|
||||
if (aC) {
|
||||
return aC;
|
||||
}
|
||||
|
||||
//containers should have a precedence over infopoints because otherwise
|
||||
//AR1512 sanity test quest would fail
|
||||
//If this order couldn't be maintained, then 'Contains' should have a
|
||||
//unique call to get containers only
|
||||
|
||||
//No... it was not an door... maybe a Container?
|
||||
aC = TMap->GetContainer( name );
|
||||
if (aC) {
|
||||
return aC;
|
||||
}
|
||||
|
||||
//No... it was not a container ... maybe an InfoPoint?
|
||||
aC = TMap->GetInfoPoint( name );
|
||||
if (aC) {
|
||||
return aC;
|
||||
}
|
||||
return aC;
|
||||
}
|
||||
|
||||
// blocking actions need to store some kinds of objects between ticks
|
||||
Scriptable* GetStoredActorFromObject(Scriptable* Sender, Object* oC, int ga_flags)
|
||||
{
|
||||
Scriptable *tar = NULL;
|
||||
// retrieve an existing target if it still exists and is valid
|
||||
if (Sender->CurrentActionTarget) {
|
||||
tar = core->GetGame()->GetActorByGlobalID(Sender->CurrentActionTarget);
|
||||
if (tar) {
|
||||
// always an actor, check if it satisfies flags
|
||||
if (((Actor *)tar)->ValidTarget(ga_flags)) {
|
||||
return tar;
|
||||
}
|
||||
}
|
||||
return NULL; // target invalid/gone
|
||||
}
|
||||
tar = GetActorFromObject(Sender, oC, ga_flags);
|
||||
// maybe store the target if it's an actor..
|
||||
if (tar && tar->Type == ST_ACTOR) {
|
||||
// .. but we only want objects created via objectFilters
|
||||
if (oC->objectFilters[0]) {
|
||||
Sender->CurrentActionTarget = tar->GetGlobalID();
|
||||
}
|
||||
}
|
||||
return tar;
|
||||
}
|
||||
|
||||
Scriptable* GetActorFromObject(Scriptable* Sender, Object* oC, int ga_flags)
|
||||
{
|
||||
Scriptable *aC = NULL;
|
||||
|
||||
if (!oC) {
|
||||
return NULL;
|
||||
}
|
||||
Game *game = core->GetGame();
|
||||
Targets *tgts = GetAllObjects(Sender->GetCurrentArea(), Sender, oC, ga_flags);
|
||||
if (tgts) {
|
||||
//now this could return other than actor objects
|
||||
aC = tgts->GetTarget(0,-1);
|
||||
delete tgts;
|
||||
if (aC || oC->objectFields[0]!=-1) {
|
||||
return aC;
|
||||
}
|
||||
|
||||
//global actors are always found by object ID!
|
||||
return game->GetGlobalActorByGlobalID(oC->objectFields[1]);
|
||||
}
|
||||
|
||||
if (oC->objectName[0]) {
|
||||
// if you ActionOverride a global actor, they might not have a map :(
|
||||
// TODO: don't allow this to happen?
|
||||
if (Sender->GetCurrentArea()) {
|
||||
aC = GetActorObject(Sender->GetCurrentArea()->GetTileMap(), oC->objectName );
|
||||
if (aC) {
|
||||
return aC;
|
||||
}
|
||||
}
|
||||
|
||||
//global actors are always found by scripting name!
|
||||
aC = game->FindPC(oC->objectName);
|
||||
if (aC) {
|
||||
return aC;
|
||||
}
|
||||
aC = game->FindNPC(oC->objectName);
|
||||
if (aC) {
|
||||
return aC;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool MatchActor(Scriptable *Sender, ieDword actorID, Object* oC)
|
||||
{
|
||||
if (!Sender) {
|
||||
return false;
|
||||
}
|
||||
Actor *ac = Sender->GetCurrentArea()->GetActorByGlobalID(actorID);
|
||||
if (!ac) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// [0]/[ANYONE] can match all actors
|
||||
if (!oC) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool filtered = false;
|
||||
|
||||
// name matching
|
||||
if (oC->objectName[0]) {
|
||||
if (strnicmp(ac->GetScriptName(), oC->objectName, 32) != 0) {
|
||||
return false;
|
||||
}
|
||||
filtered = true;
|
||||
}
|
||||
|
||||
// IDS targeting
|
||||
// (if we already matched by name, we don't do this)
|
||||
// TODO: check distance? area? visibility?
|
||||
if (!filtered && !DoObjectIDSCheck(oC, ac, &filtered)) return false;
|
||||
|
||||
// globalID hack should never get here
|
||||
assert(oC->objectFilters[0] != -1);
|
||||
|
||||
// object filters
|
||||
if (oC->objectFilters[0]) {
|
||||
// object filters insist on having a stupid targets list,
|
||||
// so we waste a lot of time here
|
||||
Targets *tgts = new Targets();
|
||||
int ga_flags = 0; // TODO: correct?
|
||||
|
||||
// handle already-filtered vs not-yet-filtered cases
|
||||
// e.g. LastTalkedToBy(Myself) vs LastTalkedToBy
|
||||
if (filtered) tgts->AddTarget(ac, 0, ga_flags);
|
||||
|
||||
tgts = DoObjectFiltering(Sender, tgts, oC, ga_flags);
|
||||
if (!tgts) return false;
|
||||
|
||||
// and sometimes object filters are lazy and not only don't filter
|
||||
// what we give them, they clear it and return a list :(
|
||||
// so we have to search the whole list..
|
||||
bool ret = false;
|
||||
targetlist::iterator m;
|
||||
const targettype *tt = tgts->GetFirstTarget(m, ST_ACTOR);
|
||||
while (tt) {
|
||||
Actor *actor = (Actor *) tt->actor;
|
||||
if (actor->GetGlobalID() == actorID) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
tt = tgts->GetNextTarget(m, ST_ACTOR);
|
||||
}
|
||||
delete tgts;
|
||||
if (!ret) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int GetObjectCount(Scriptable* Sender, Object* oC)
|
||||
{
|
||||
if (!oC) {
|
||||
return 0;
|
||||
}
|
||||
// EvaluateObject will return [PC]
|
||||
// GetAllObjects will also return Myself (evaluates object filters)
|
||||
// i believe we need the latter here
|
||||
Targets* tgts = GetAllObjects(Sender->GetCurrentArea(), Sender, oC, 0);
|
||||
int count = tgts->Count();
|
||||
delete tgts;
|
||||
return count;
|
||||
}
|
||||
|
||||
//TODO:
|
||||
//check numcreaturesatmylevel(myself, 1)
|
||||
//when the actor is alone
|
||||
//it should (obviously) return true if the trigger
|
||||
//evaluates object filters
|
||||
//also check numcreaturesgtmylevel(myself,0) with
|
||||
//actor having at high level
|
||||
int GetObjectLevelCount(Scriptable* Sender, Object* oC)
|
||||
{
|
||||
if (!oC) {
|
||||
return 0;
|
||||
}
|
||||
// EvaluateObject will return [PC]
|
||||
// GetAllObjects will also return Myself (evaluates object filters)
|
||||
// i believe we need the latter here
|
||||
Targets* tgts = GetAllObjects(Sender->GetCurrentArea(), Sender, oC, 0);
|
||||
int count = 0;
|
||||
if (tgts) {
|
||||
targetlist::iterator m;
|
||||
const targettype *tt = tgts->GetFirstTarget(m, ST_ACTOR);
|
||||
while (tt) {
|
||||
count += ((Actor *) tt->actor)->GetXPLevel(true);
|
||||
tt = tgts->GetNextTarget(m, ST_ACTOR);
|
||||
}
|
||||
}
|
||||
delete tgts;
|
||||
return count;
|
||||
}
|
||||
|
||||
Targets *GetMyTarget(Scriptable *Sender, Actor *actor, Targets *parameters, int ga_flags)
|
||||
{
|
||||
if (!actor) {
|
||||
if (Sender->Type==ST_ACTOR) {
|
||||
actor = (Actor *) Sender;
|
||||
}
|
||||
}
|
||||
parameters->Clear();
|
||||
if (actor) {
|
||||
Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastTarget);
|
||||
if (target) {
|
||||
parameters->AddTarget(target, 0, ga_flags);
|
||||
}
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
Targets *XthNearestDoor(Targets *parameters, unsigned int count)
|
||||
{
|
||||
//get the origin
|
||||
Scriptable *origin = parameters->GetTarget(0, -1);
|
||||
parameters->Clear();
|
||||
if (!origin) {
|
||||
return parameters;
|
||||
}
|
||||
//get the doors based on it
|
||||
Map *map = origin->GetCurrentArea();
|
||||
unsigned int i =(unsigned int) map->TMap->GetDoorCount();
|
||||
if (count>i) {
|
||||
return parameters;
|
||||
}
|
||||
while (i--) {
|
||||
Door *door = map->TMap->GetDoor(i);
|
||||
unsigned int dist = Distance(origin->Pos, door->Pos);
|
||||
parameters->AddTarget(door, dist, 0);
|
||||
}
|
||||
|
||||
//now get the xth door
|
||||
origin = parameters->GetTarget(count, ST_DOOR);
|
||||
parameters->Clear();
|
||||
if (!origin) {
|
||||
return parameters;
|
||||
}
|
||||
parameters->AddTarget(origin, 0, 0);
|
||||
return parameters;
|
||||
}
|
||||
|
||||
Targets *XthNearestOf(Targets *parameters, int count, int ga_flags)
|
||||
{
|
||||
Scriptable *origin;
|
||||
|
||||
if (count<0) {
|
||||
const targettype *t = parameters->GetLastTarget(ST_ACTOR);
|
||||
origin = t->actor;
|
||||
} else {
|
||||
origin = parameters->GetTarget(count, ST_ACTOR);
|
||||
}
|
||||
parameters->Clear();
|
||||
if (!origin) {
|
||||
return parameters;
|
||||
}
|
||||
parameters->AddTarget(origin, 0, ga_flags);
|
||||
return parameters;
|
||||
}
|
||||
|
||||
//mygroup means the same specifics as origin
|
||||
Targets *XthNearestMyGroupOfType(Scriptable *origin, Targets *parameters, unsigned int count, int ga_flags)
|
||||
{
|
||||
if (origin->Type != ST_ACTOR) {
|
||||
parameters->Clear();
|
||||
return parameters;
|
||||
}
|
||||
|
||||
targetlist::iterator m;
|
||||
const targettype *t = parameters->GetFirstTarget(m, ST_ACTOR);
|
||||
if (!t) {
|
||||
return parameters;
|
||||
}
|
||||
Actor *actor = (Actor *) origin;
|
||||
//determining the specifics of origin
|
||||
ieDword type = actor->GetStat(IE_SPECIFIC); //my group
|
||||
|
||||
while ( t ) {
|
||||
if (t->actor->Type!=ST_ACTOR) {
|
||||
t=parameters->RemoveTargetAt(m);
|
||||
continue;
|
||||
}
|
||||
Actor *actor = (Actor *) (t->actor);
|
||||
if (actor->GetStat(IE_SPECIFIC) != type) {
|
||||
t=parameters->RemoveTargetAt(m);
|
||||
continue;
|
||||
}
|
||||
t = parameters->GetNextTarget(m, ST_ACTOR);
|
||||
}
|
||||
return XthNearestOf(parameters,count, ga_flags);
|
||||
}
|
||||
|
||||
Targets *ClosestEnemySummoned(Scriptable *origin, Targets *parameters, int ga_flags)
|
||||
{
|
||||
if (origin->Type != ST_ACTOR) {
|
||||
parameters->Clear();
|
||||
return parameters;
|
||||
}
|
||||
|
||||
targetlist::iterator m;
|
||||
const targettype *t = parameters->GetFirstTarget(m, ST_ACTOR);
|
||||
if (!t) {
|
||||
return parameters;
|
||||
}
|
||||
Actor *actor = (Actor *) origin;
|
||||
//determining the allegiance of the origin
|
||||
int type = GetGroup(actor);
|
||||
|
||||
if (type==2) {
|
||||
parameters->Clear();
|
||||
return parameters;
|
||||
}
|
||||
|
||||
actor = NULL;
|
||||
while ( t ) {
|
||||
Actor *tmp = (Actor *) (t->actor);
|
||||
if (tmp->GetStat(IE_SEX) != SEX_SUMMON) {
|
||||
continue;
|
||||
}
|
||||
if (type) { //origin is PC
|
||||
if (tmp->GetStat(IE_EA) <= EA_GOODCUTOFF) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (tmp->GetStat(IE_EA) >= EA_EVILCUTOFF) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
actor = tmp;
|
||||
t = parameters->GetNextTarget(m, ST_ACTOR);
|
||||
}
|
||||
parameters->Clear();
|
||||
parameters->AddTarget(actor, 0, ga_flags);
|
||||
return parameters;
|
||||
}
|
||||
|
||||
Targets *XthNearestEnemyOfType(Scriptable *origin, Targets *parameters, unsigned int count, int ga_flags)
|
||||
{
|
||||
if (origin->Type != ST_ACTOR) {
|
||||
parameters->Clear();
|
||||
return parameters;
|
||||
}
|
||||
|
||||
targetlist::iterator m;
|
||||
const targettype *t = parameters->GetFirstTarget(m, ST_ACTOR);
|
||||
if (!t) {
|
||||
return parameters;
|
||||
}
|
||||
Actor *actor = (Actor *) origin;
|
||||
//determining the allegiance of the origin
|
||||
int type = GetGroup(actor);
|
||||
|
||||
if (type==2) {
|
||||
parameters->Clear();
|
||||
return parameters;
|
||||
}
|
||||
|
||||
while ( t ) {
|
||||
if (t->actor->Type!=ST_ACTOR) {
|
||||
t=parameters->RemoveTargetAt(m);
|
||||
continue;
|
||||
}
|
||||
Actor *actor = (Actor *) (t->actor);
|
||||
// IDS targeting already did object checks (unless we need to override Detect?)
|
||||
if (type) { //origin is PC
|
||||
if (actor->GetStat(IE_EA) <= EA_GOODCUTOFF) {
|
||||
t=parameters->RemoveTargetAt(m);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (actor->GetStat(IE_EA) >= EA_EVILCUTOFF) {
|
||||
t=parameters->RemoveTargetAt(m);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
t = parameters->GetNextTarget(m, ST_ACTOR);
|
||||
}
|
||||
return XthNearestOf(parameters,count, ga_flags);
|
||||
}
|
||||
|
||||
Targets *XthNearestEnemyOf(Targets *parameters, int count, int ga_flags)
|
||||
{
|
||||
Actor *origin = (Actor *) parameters->GetTarget(0, ST_ACTOR);
|
||||
parameters->Clear();
|
||||
if (!origin) {
|
||||
return parameters;
|
||||
}
|
||||
//determining the allegiance of the origin
|
||||
int type = GetGroup(origin);
|
||||
|
||||
if (type==2) {
|
||||
return parameters;
|
||||
}
|
||||
Map *map = origin->GetCurrentArea();
|
||||
int i = map->GetActorCount(true);
|
||||
Actor *ac;
|
||||
while (i--) {
|
||||
ac=map->GetActor(i,true);
|
||||
int distance;
|
||||
//int distance = Distance(ac, origin);
|
||||
// TODO: if it turns out you need to check Sender here, beware you take the right distance!
|
||||
// (n the original games, this is only used for NearestEnemyOf(Player1) in obsgolem.bcs)
|
||||
if (!DoObjectChecks(map, origin, ac, distance)) continue;
|
||||
if (type) { //origin is PC
|
||||
if (ac->GetStat(IE_EA) >= EA_EVILCUTOFF) {
|
||||
parameters->AddTarget(ac, distance, ga_flags);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ac->GetStat(IE_EA) <= EA_GOODCUTOFF) {
|
||||
parameters->AddTarget(ac, distance, ga_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
return XthNearestOf(parameters,count, ga_flags);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user