Files
Vangers/src/actint/aci_scr.cpp
2022-05-12 21:36:56 +07:00

1813 lines
37 KiB
C++

/* ---------------------------- INCLUDE SECTION ----------------------------- */
#include "../global.h"
#include "lang.h"
#include "../iscreen/hfont.h"
#include "aci_evnt.h"
#include "aci_scr.h"
#include "a_consts.h"
#include "acsconst.h"
#include "../network.h"
#include "../iscreen/iscreen.h"
#ifndef _WIN32
#include <arpa/inet.h> // ntohl() FIXME: remove
#endif
/* ----------------------------- STRUCT SECTION ----------------------------- */
/* ----------------------------- EXTERN SECTION ----------------------------- */
extern int iMouseX;
extern int iMouseY;
extern int NetworkON;
extern char* aciSTR_ON;
extern char* aciSTR_OFF;
extern iScreenOption** iScrOpt;
/* --------------------------- PROTOTYPE SECTION ---------------------------- */
int iGetKeyName(int vkey,int shift,int lng_flag);
void ibsout(int x,int y,void* ptr);
int acsEventActive(aciScreenEventCommand* p);
void acsSendEvent(aciScreenEventCommand* p);
void acsSetFlush(int x,int y,int sx,int sy);
aciScreenResource* acsGetResource(int id);
void acsGetResourceSize(aciScreenResource* p,int& x,int& y,int& sx,int& sy);
int acsGetMaxFrame(int res_id);
void aOutStr(int x,int y,int font,int color,unsigned char* str,int space = 1);
int aStrLen(unsigned char* str,int font,int space = 1);
void acsOutStr(int x,int y,int fnt,int col,unsigned char* str,int space);
void aciPutSpr32(int x,int y,int sx,int sy,void* buf,int col,int col_sz);
int acsStrLen(int fnt,unsigned char* str,int space);
void acsChangeStrState(int id);
void acsLoadFonts(void);
void acsFreeFonts(void);
void acsHandleExtEvent(int code,int data0 = 0,int data1 = 0,int data2 = 0);
/* --------------------------- DEFINITION SECTION --------------------------- */
#define aci_FREE_LIST(lst,p1,p2,tp) p1 = (tp*)lst -> fPtr; \
while(p1){ \
p2 = (tp*)p1 -> next; \
delete p1; \
p1 = p2; \
} \
lst -> ClearList();
#define ACS_MAX_FONT 2
#define ACS_INPUT_TIMER 3
const int ACS_DELTA_X = (800 - 640) / 2;
const int ACS_DELTA_Y = (600 - 480) / 2;
int acsInputTimer = 0;
int acsInputFlag = 0;
int acsFirstRedraw = 0;
char* acsBackupStr = NULL;
aciScreenDispatcher* acsScrD;
HFont** acsFntTable = NULL;
int aciCurCredits00 = 0;
int acsEventActive(aciScreenEventCommand* p)
{
aciScreenObject* obj;
switch(p -> code){
case ACS_EXEC_SEQUENCE:
obj = acsScrD -> GetObject(p -> data[0]);
if(obj -> activeSeq) return 0;
break;
case ACS_INPUT_STRING:
if(acsScrD -> activeInput) return 0;
break;
case ACS_EXT_EVENT:
if(p -> data[0] == ACS_CHANGE_SOUND_MODE){
obj = acsScrD -> GetObject(ACS_SOUND_MODE);
if(obj -> activeSeq) return 0;
}
if(p -> data[0] == ACS_CHANGE_MUSIC_MODE){
obj = acsScrD -> GetObject(ACS_MUSIC_MODE);
if(obj -> activeSeq) return 0;
}
if(p -> data[0] == ACS_CHANGE_TUTORIAL_MODE){
obj = acsScrD -> GetObject(ACS_TUTORIAL_MODE);
if(obj -> activeSeq) return 0;
}
break;
}
return 1;
}
aciScreenResource* acsGetResource(int id)
{
return acsScrD -> GetResource(id);
}
void acsSendEvent(aciScreenEventCommand* p)
{
acsScrD -> eventLine -> put(p -> code,p -> data[0],p -> data[1],p -> data[2], p -> data[3]);
}
void acsSetFlush(int x,int y,int sx,int sy)
{
acsScrD -> flushLine -> put(0,x,y,sx,sy);
}
aciScreenScroller::aciScreenScroller(void)
{
type = ACS_SCROLLER_OBJ;
CurValue = 0;
MaxValue = 1;
Color = BackColor = 0;
ScrResID = 0;
ScrRes = NULL;
sResID = 0;
sRes = NULL;
ActiveSX = ActiveSY = 0;
ScrResSX = ScrResSY = 0;
sResSX = sResSY = 0;
}
aciScreenScroller::~aciScreenScroller(void)
{
}
aciScreenInputField::aciScreenInputField(void)
{
type = ACS_INPUT_FIELD_OBJ;
MaxStrLen = 0;
string = NULL;
Color = 140;
Space = 1;
Color0 = 140;
Color1 = -1;
Color2 = -1;
font = 0;
}
aciScreenInputField::~aciScreenInputField(void)
{
if(string) delete[] string;
}
aciScreen::aciScreen(void)
{
ID = 0;
flags = 0;
backResID = 0;
backRes = NULL;
events = new XList;
objList = new XList;
resources = new XList;
}
aciScreen::~aciScreen(void)
{
aciScreenEvent* ev,*ev1;
aciScreenObject* obj,*obj1;
aciScreenResource* res,*res1;
res = (aciScreenResource*)resources -> fPtr;
while(res){
res1 = (aciScreenResource*)res -> next;
res -> free();
acsFreeResource(res);
res = res1;
}
delete resources;
aci_FREE_LIST(events,ev,ev1,aciScreenEvent);
delete events;
obj = (aciScreenObject*)objList -> fPtr;
while(obj){
obj1 = (aciScreenObject*)obj -> next;
acsFreeObject(obj);
obj = obj1;
}
delete objList;
}
aciScreenDispatcher::aciScreenDispatcher(void)
{
flags = 0;
curScr = NULL;
curScrID = 1;
QuantCode = 0;
activeInput = NULL;
scrList = new XList;
resources = new XList;
eventLine = new aciScreenEventLine;
flushLine = new aciScreenEventLine;
}
aciScreenDispatcher::~aciScreenDispatcher(void)
{
//aciScreen *scr, *scr1;
aciScreenResource *res, *res1;
res = (aciScreenResource*)resources -> fPtr;
while(res){
res1 = (aciScreenResource*)res -> next;
res -> free();
acsFreeResource(res);
res = res1;
}
delete resources;
//aci_FREE_LIST(scrList,NULL,NULL,aciScreen);
delete scrList;
delete eventLine;
delete flushLine;
}
aciScreenEventLine::aciScreenEventLine(void)
{
int i;
table = new aciScreenEventCommand*[ACS_EVENT_LINE_SIZE];
mem_heap = new char[ACS_EVENT_LINE_SIZE * sizeof(aciScreenEventCommand)];
for(i = 0; i < ACS_EVENT_LINE_SIZE; i ++){
table[i] = (aciScreenEventCommand*)(mem_heap + i * sizeof(aciScreenEventCommand));
table[i] -> init();
}
clear();
}
aciScreenEventLine::~aciScreenEventLine(void)
{
delete[] mem_heap;
delete[] table;
clear();
}
aciScreenEventCommand::aciScreenEventCommand(void)
{
init();
}
aciScreenObject::aciScreenObject(void)
{
ID = 0;
type = ACS_BASE_OBJ;
PosX = PosY = 0;
SizeX = SizeY = 0;
flags = 0;
curFrame = 0;
ResID = -1;
resPtr = NULL;
frameSeq = new XList;
events = new XList;
}
aciScreenObject::~aciScreenObject(void)
{
aciScreenFrameSequence* s,*s1;
aciScreenEvent* ev,*ev1;
aci_FREE_LIST(frameSeq,s,s1,aciScreenFrameSequence);
delete frameSeq;
aci_FREE_LIST(events,ev,ev1,aciScreenEvent);
delete events;
}
aciScreenFrameSequence::aciScreenFrameSequence(void)
{
ID = 0;
ResourceID = -1;
StartFrame = EndFrame = CurFrame = FrameDelta = 0;
}
aciScreenEvent::aciScreenEvent(void)
{
flags = 0;
CurTimer = 0;
MaxTimer = 1;
commSeq = new XList;
keyObj = new aciScreenKeyObject;
}
aciScreenEvent::~aciScreenEvent(void)
{
aciScreenEventCommand* p,*p1;
aci_FREE_LIST(commSeq,p,p1,aciScreenEventCommand);
delete commSeq;
delete keyObj;
}
aciScreenKeyObject::aciScreenKeyObject(void)
{
codes = new XList;
}
aciScreenKeyObject::~aciScreenKeyObject(void)
{
aciScreenKey* p,*p1;
aci_FREE_LIST(codes,p,p1,aciScreenKey);
delete codes;
}
aciScreenResource::aciScreenResource(void)
{
ID = 0;
type = ACS_NONE;
flags = 0;
fname = NULL;
}
aciScreenResource::~aciScreenResource(void)
{
if(fname)
delete fname;
}
aciScreenResourceBMP::aciScreenResourceBMP(void)
{
type = ACS_BMP;
SizeX = SizeY = 0;
data = NULL;
}
aciScreenResourceBMP::~aciScreenResourceBMP(void)
{
if(data)
delete data;
}
aciScreenResourceBML::aciScreenResourceBML(void)
{
type = ACS_BML;
SizeX = SizeY = NumFrames = 0;
data = NULL;
}
aciScreenResourceBML::~aciScreenResourceBML(void)
{
if(data)
delete data;
}
aciScreenResourceBMO::aciScreenResourceBMO(void)
{
type = ACS_BMO;
SizeX = SizeY = NumFrames = 0;
OffsX = OffsY = 0;
data = NULL;
}
aciScreenResourceBMO::~aciScreenResourceBMO(void)
{
if(data)
delete data;
}
aciScreenResourceXBM::aciScreenResourceXBM(void)
{
type = ACS_XBM;
PosX = PosY = 0;
CenterX = CenterY = 0;
bSizeX = bSizeY = 0;
SizeX = SizeY = 0;
SideX = SideY = 0;
ImageSize = 0;
data = NULL;
}
aciScreenResourceXBM::~aciScreenResourceXBM(void)
{
if(data)
delete data;
}
void aciScreenResourceBMP::load(void)
{
XStream fh;
short sx,sy;
int sz;
if(!fname) return;
fh.open(fname,XS_IN);
fh > sx > sy;
SizeX = sx;
SizeY = sy;
sz = SizeX * SizeY;
data = new unsigned char[sz];
fh.read(data,sz);
fh.close();
flags |= ACS_LOADED;
}
void aciScreenResourceBMP::free(void)
{
if(flags & ACS_LOADED && data){
delete data;
}
flags &= ~ACS_LOADED;
data = NULL;
}
void aciScreenResourceBML::load(void)
{
XStream fh;
short sx,sy,num;
int i,sz;
if(!fname) return;
fh.open(fname,XS_IN);
fh > sx > sy > num;
SizeX = sx;
SizeY = sy;
NumFrames = num;
sz = SizeX * SizeY * NumFrames;
data = new unsigned char[sz];
fh.read(data,sz);
fh.close();
frameTable = new unsigned char*[NumFrames];
for(i = 0; i < NumFrames; i ++) frameTable[i] = data + i * SizeX * SizeY;
flags |= ACS_LOADED;
}
void aciScreenResourceBML::free(void)
{
if(flags & ACS_LOADED){
if(data) delete data;
if(frameTable) delete frameTable;
}
flags &= ~ACS_LOADED;
data = NULL;
frameTable = NULL;
}
void aciScreenResourceBMO::load(void)
{
XStream fh;
short sx,sy,num,ox,oy;
int i,sz;
if(!(flags & ACS_BUILD_RESOURCE)){
if(!fname) return;
fh.open(fname,XS_IN);
fh > sx > sy > num > ox > oy;
SizeX = sx;
SizeY = sy;
OffsX = ox;
OffsY = oy;
NumFrames = num;
sz = SizeX * SizeY * NumFrames;
data = new unsigned char[sz];
fh.read(data,sz);
fh.close();
}
else {
NumFrames = 1;
sz = SizeX * SizeY * NumFrames;
data = new unsigned char[sz];
XGR_GetSpr(OffsX,OffsY,SizeX,SizeY,data);
}
frameTable = new unsigned char*[NumFrames];
for(i = 0; i < NumFrames; i ++) frameTable[i] = data + i * SizeX * SizeY;
flags |= ACS_LOADED;
}
void aciScreenResourceBMO::free(void)
{
if(flags & ACS_LOADED){
if(data) {
delete[] data;
}
if(frameTable) {
delete[] frameTable;
}
}
flags &= ~ACS_LOADED;
data = NULL;
frameTable = NULL;
}
void aciScreenResourceXBM::load(void)
{
XStream fh;
if(!fname) return;
fh.open(fname,XS_IN);
fh > PosX > PosY > bSizeX > bSizeY > SizeX > SizeY > ImageSize;
data = new unsigned char[ImageSize];
fh.read(data,ImageSize);
fh.close();
SideX = SizeX/2;
SideY = SizeY/2;
CenterX = PosX + SideX;
CenterY = PosY + SideY;
flags |= ACS_LOADED;
}
void aciScreenResourceXBM::free(void)
{
if(flags & ACS_LOADED && data){
delete data;
}
flags &= ~ACS_LOADED;
data = NULL;
}
void aciScreenResourceBMP::redraw(int x,int y,int frame,int mode)
{
if(x < 0) x = 0;
if(y < 0) y = 0;
if(data){
XGR_PutSpr(x,y,SizeX,SizeY,data,mode);
if(!(flags & ACS_NO_FLUSH))
acsSetFlush(x,y,SizeX,SizeY);
}
}
void aciScreenResourceBML::redraw(int x,int y,int frame,int mode)
{
if(data && frameTable){
XGR_PutSpr(x,y,SizeX,SizeY,frameTable[frame],mode);
if(!(flags & ACS_NO_FLUSH))
acsSetFlush(x,y,SizeX,SizeY);
}
}
void aciScreenResourceBMO::redraw(int x,int y,int frame,int mode)
{
if(data && frameTable){
if(x == -1 && y == -1){
XGR_PutSpr(OffsX,OffsY,SizeX,SizeY,frameTable[frame],mode);
if(!(flags & ACS_NO_FLUSH))
acsSetFlush(OffsX,OffsY,SizeX,SizeY);
}
else {
XGR_PutSpr(x,y,SizeX,SizeY,frameTable[frame],mode);
if(!(flags & ACS_NO_FLUSH))
acsSetFlush(x,y,SizeX,SizeY);
}
}
}
void aciScreenResourceXBM::redraw(int x,int y,int frame,int mode)
{
if(data){
if(x == -1 && y == -1){
ibsout(PosX,PosY,data);
if(!(flags & ACS_NO_FLUSH))
acsSetFlush(PosX,PosY,SizeX,SizeY);
}
else {
ibsout(x,y,data);
if(!(flags & ACS_NO_FLUSH))
acsSetFlush(x,y,SizeX,SizeY);
}
}
}
int aciScreenKeyObject::KeyTrap(int code)
{
aciScreenKey* p = (aciScreenKey*)codes -> fPtr;
while(p){
//std::cout<<"aciScreenKeyObject::KeyTrap "<<p->code<<" "<<code<<std::endl;
if(p -> code == code)
return 1;
p = (aciScreenKey*)p -> next;
}
return 0;
}
void aciScreenKeyObject::AddKey(int code)
{
aciScreenKey* p = new aciScreenKey;
p -> code = code;
codes -> AddElement((XListElement*)p);
}
void aciScreenEventCommand::init(void)
{
int i;
for(i = 0; i < 4; i ++) data[i] = 0;
code = StartTimer = 0;
flags = 0;
}
void aciScreenEventLine::put(int cd,int dt0,int dt1,int dt2,int dt3)
{
if(size < ACS_EVENT_LINE_SIZE){
table[last_index] -> code = cd;
table[last_index] -> data[0] = dt0;
table[last_index] -> data[1] = dt1;
table[last_index] -> data[2] = dt2;
table[last_index] -> data[3] = dt3;
last_index ++;
if(last_index >= ACS_EVENT_LINE_SIZE)
last_index = 0;
size ++;
}
else
ErrH.Abort("Event buffer overflow...");
}
aciScreenEventCommand* aciScreenEventLine::get(void)
{
aciScreenEventCommand* p;
if(size){
p = table[first_index];
first_index ++;
if(first_index >= ACS_EVENT_LINE_SIZE)
first_index = 0;
size --;
return p;
}
return NULL;
}
void aciScreenEventLine::clear(void)
{
size = 0;
first_index = 0;
last_index = 0;
}
void aciScreenEvent::AddCommand(aciScreenEventCommand* p)
{
commSeq -> AddElement((XListElement*)p);
}
void aciScreenObject::AddSeq(aciScreenFrameSequence* p)
{
frameSeq -> AddElement((XListElement*)p);
}
void aciScreenObject::AddEvent(aciScreenEvent* p)
{
events -> AddElement((XListElement*)p);
}
void aciScreen::AddEvent(aciScreenEvent* p)
{
events -> AddElement((XListElement*)p);
}
void aciScreen::AddObject(aciScreenObject* p)
{
objList -> AddElement((XListElement*)p);
}
void aciScreen::AddResource(aciScreenResource* p)
{
resources -> AddElement((XListElement*)p);
}
void aciScreenDispatcher::AddScreen(aciScreen* p)
{
scrList -> AddElement((XListElement*)p);
}
void aciScreenDispatcher::AddResource(aciScreenResource* p)
{
resources -> AddElement((XListElement*)p);
}
aciScreenResource* aciScreen::GetResource(int id)
{
aciScreenResource* p = (aciScreenResource*)resources -> fPtr;
while(p){
if(p -> ID == id) return p;
p = (aciScreenResource*)p -> next;
}
return NULL;
}
aciScreenResource* aciScreenDispatcher::GetResource(int id)
{
aciScreenResource* p = (aciScreenResource*)resources -> fPtr;
while(p){
if(p -> ID == id) return p;
p = (aciScreenResource*)p -> next;
}
return curScr -> GetResource(id);
}
aciScreen* aciScreenDispatcher::GetScreen(int id)
{
aciScreen* p = (aciScreen*)scrList -> fPtr;
while(p){
if(p -> ID == id) return p;
p = (aciScreen*)p -> next;
}
return NULL;
}
aciScreenObject* aciScreenDispatcher::GetObject(int id)
{
return curScr -> GetObject(id);
}
aciScreenObject* aciScreen::GetObject(int id)
{
aciScreenObject* p = (aciScreenObject*)objList -> fPtr;
while(p){
if(p -> ID == id) return p;
p = (aciScreenObject*)p -> next;
}
return NULL;
}
void aciScreen::alloc_mem(void)
{
aciScreenResource* p = (aciScreenResource*)resources -> fPtr;
while(p){
p -> load();
p = (aciScreenResource*)p -> next;
}
}
void aciScreen::free_mem(void)
{
aciScreenResource* p = (aciScreenResource*)resources -> fPtr;
while(p){
p -> free();
p = (aciScreenResource*)p -> next;
}
}
void aciScreenDispatcher::alloc_mem(void)
{
aciScreenResource* p = (aciScreenResource*)resources -> fPtr;
while(p){
p -> load();
p = (aciScreenResource*)p -> next;
}
curScr = GetScreen(curScrID);
curScr -> prepare();
curScr -> alloc_mem();
curScr -> init_objects();
curScr -> backRes = GetResource(curScr -> backResID);
flags &= ~ACS_NEED_EXIT;
flags |= ACS_FORCED_REDRAW;
flags |= ACS_FIRST_REDRAW;
KeyTrap(ACS_STARTUP_KEY, nullptr);
acsLoadFonts();
}
void aciScreenDispatcher::free_mem(void)
{
aciScreenResource* p = (aciScreenResource*)resources -> fPtr;
if(activeInput) CancelInput();
while(p){
p -> free();
p = (aciScreenResource*)p -> next;
}
acsFreeFonts();
}
void aciScreen::init_objects(void)
{
aciScreenObject* p = (aciScreenObject*)objList -> fPtr;
while(p){
p -> init();
p -> prepare();
p = (aciScreenObject*)p -> next;
}
}
void aciScreenDispatcher::KeyTrap(int code, SDL_Event *event)
{
if(activeInput) {
InputQuant(event);
}
if (event == nullptr || event->type != SDL_TEXTINPUT) {
curScr->KeyTrap(code);
}
}
void aciScreen::KeyTrap(int code)
{
//std::cout<<"aciScreen::KeyTrap"<<std::endl;
int x,y,mouse = 0;
aciScreenEvent* ev;
aciScreenObject* p;
if(code < 0){
mouse = 1;
x = iMouseX;
y = iMouseY;
}
ev = (aciScreenEvent*)events -> fPtr;
while(ev){
if(!(ev -> flags & ACS_EVENT_ACTIVE) && ev -> KeyTrap(code))
ev -> Start();
ev = (aciScreenEvent*)ev -> next;
}
p = (aciScreenObject*)objList -> fPtr;
while(p){
if(!mouse || p -> CheckXY(x,y)){
ev = (aciScreenEvent*)p -> events -> fPtr;
while(ev){
if(!(ev -> flags & ACS_EVENT_ACTIVE) && ev -> KeyTrap(code)) {
//std::cout<<"Start"<<std::endl;
ev -> Start();
}
ev = (aciScreenEvent*)ev -> next;
}
}
p = (aciScreenObject*)p -> next;
}
}
void aciScreenObject::prepare(void)
{
aciScreenFrameSequence* seq;
activeSeq = NULL;
StopEvents();
seq = (aciScreenFrameSequence*)frameSeq -> fPtr;
while(seq){
if(seq -> StartFrame == ACS_MAX_FRAME)
seq -> StartFrame = acsGetMaxFrame(seq -> ResourceID);
if(seq -> EndFrame == ACS_MAX_FRAME)
seq -> EndFrame = acsGetMaxFrame(seq -> ResourceID);
seq = (aciScreenFrameSequence*)seq -> next;
}
}
void aciScreenObject::StopEvents(void)
{
aciScreenEvent* ev;
ev = (aciScreenEvent*)events -> fPtr;
while(ev){
ev -> Stop();
ev = (aciScreenEvent*)ev -> next;
}
}
int aciScreenObject::isActive(void)
{
aciScreenEvent* ev;
ev = (aciScreenEvent*)events -> fPtr;
while(ev){
if(ev -> flags & ACS_EVENT_ACTIVE) return 1;
ev = (aciScreenEvent*)ev -> next;
}
return 0;
}
void aciScreen::prepare(void)
{
aciScreenEvent* ev;
ev = (aciScreenEvent*)events -> fPtr;
while(ev){
ev -> Stop();
ev = (aciScreenEvent*)ev -> next;
}
}
void aciScreenEvent::Start(void)
{
Stop();
CurTimer = 0;
flags |= ACS_EVENT_ACTIVE;
}
void aciScreenEvent::Stop(void)
{
flags &= ~ACS_EVENT_ACTIVE;
aciScreenEventCommand* p = (aciScreenEventCommand*)commSeq -> fPtr;
while(p){
p -> flags &= ~ACS_COMMAND_STARTED;
p = (aciScreenEventCommand*)p -> next;
}
}
void aciScreenEvent::Quant(void)
{
aciScreenEventCommand* p = (aciScreenEventCommand*)commSeq -> fPtr;
int nextQuant = 1;
while(p){
if(p -> StartTimer == CurTimer){
if(p -> flags & ACS_COMMAND_STARTED){
if(!acsEventActive(p))
nextQuant = 0;
}
else {
p -> flags |= ACS_COMMAND_STARTED;
acsSendEvent(p);
nextQuant = 0;
}
}
p = (aciScreenEventCommand*)p -> next;
}
if(nextQuant){
CurTimer ++;
if(CurTimer > MaxTimer) Stop();
}
}
void aciScreenObject::EventQuant(void)
{
aciScreenEvent* ev = (aciScreenEvent*)events -> fPtr;
while(ev){
if(ev -> flags & ACS_EVENT_ACTIVE)
ev -> Quant();
ev = (aciScreenEvent*)ev -> next;
}
}
void aciScreen::EventQuant(void)
{
aciScreenObject* p = (aciScreenObject*)objList -> fPtr;
aciScreenEvent* ev = (aciScreenEvent*)events -> fPtr;
while(ev){
if(ev -> flags & ACS_EVENT_ACTIVE)
ev -> Quant();
ev = (aciScreenEvent*)ev -> next;
}
while(p){
p -> EventQuant();
p = (aciScreenObject*)p -> next;
}
}
void aciScreenDispatcher::EventQuant(void)
{
curScr -> EventQuant();
}
void aciScreenDispatcher::FlushEvents(void)
{
aciScreenEventCommand* ev;
while(eventLine -> size){
ev = eventLine -> get();
switch(ev -> code){
case ACS_EXIT:
QuantCode = ev -> data[0]; // resume game pause
flags |= ACS_NEED_EXIT;
break;
case ACS_SET_RESOURCE:
SetResource(ev -> data[0],ev -> data[1],ev -> data[2]);
break;
case ACS_EXEC_SEQUENCE:
SetSequence(ev -> data[0],ev -> data[1]);
break;
case ACS_CHANGE_SCROLLER:
ChangeScroller(ev -> data[0],XGR_MouseObj.PosX + XGR_MouseObj.SpotX);
break;
case ACS_INPUT_STRING:
PrepareInput(ev -> data[0]);
break;
case ACS_EXT_EVENT:
acsHandleExtEvent(ev -> data[0],ev -> data[1],ev -> data[2],ev -> data[3]);
break;
case ACS_CHANGE_STR_STATE:
acsChangeStrState(ev -> data[0]);
break;
}
//std::cout<<"aciScreenDispatcher::FlushEvents "<<ev->code<<" QuantCode:"<<QuantCode<<std::endl;
}
}
void aciScreenDispatcher::flush(void)
{
aciScreenEventCommand* ev;
while(flushLine -> size){
ev = flushLine -> get();
XGR_Flush(ev -> data[0],ev -> data[1],ev -> data[2],ev -> data[3]);
}
}
void aciScreenObject::redraw(void)
{
if(resPtr)
resPtr -> redraw(PosX,PosY,curFrame,XGR_HIDDEN_FON);
acsSetFlush(PosX,PosY,SizeX,SizeY);
flags &= ~ACS_REDRAW_OBJECT;
}
void aciScreen::ChangeCoords(int dx,int dy)
{
aciScreenResource* p = (aciScreenResource*)resources -> fPtr;
while(p){
p -> change_coords(dx,dy);
p = (aciScreenResource*)p -> next;
}
}
void aciScreenDispatcher::ChangeCoords(int dx,int dy)
{
aciScreenResource* p = (aciScreenResource*)resources -> fPtr;
while(p){
p -> change_coords(dx,dy);
p = (aciScreenResource*)p -> next;
}
curScr -> ChangeCoords(dx,dy);
}
int aciScreen::redraw(int force)
{
int ret = 0;
aciScreenResource* res = (aciScreenResource*)resources -> fPtr;
aciScreenObject* p = (aciScreenObject*)objList -> fPtr;
if(force && backRes){
backRes -> redraw(-1,-1,0,XGR_HIDDEN_FON);
}
if(acsFirstRedraw){
while(res){
if(res -> flags & ACS_BUILD_RESOURCE){
res -> free();
res -> load();
}
res = (aciScreenResource*)res -> next;
}
acsFirstRedraw = 0;
}
while(p){
if(force || p -> flags & ACS_REDRAW_OBJECT){
p -> redraw();
ret = 1;
}
p = (aciScreenObject*)p -> next;
}
return ret;
}
int aciScreenDispatcher::redraw(void)
{
int force,ret = 0;
if(flags & ACS_FORCED_REDRAW){
force = 1;
flags ^= ACS_FORCED_REDRAW;
}
else
force = 0;
if(flags & ACS_FIRST_REDRAW){
flags ^= ACS_FIRST_REDRAW;
acsFirstRedraw = 1;
}
else
acsFirstRedraw = 0;
ret = curScr -> redraw(force);
return ret;
}
int aciScreenDispatcher::Quant(int flush_log)
{
int sz,obj_flag = 0;
EventQuant();
FlushEvents();
ObjectQuant();
if(activeInput){
acsInputTimer ++;
if(acsInputTimer >= ACS_INPUT_TIMER){
acsInputTimer = 0;
acsInputFlag = 1;
}
if(acsInputFlag){
sz = strlen(activeInput -> string);
if(activeInput -> string[sz - 1] == '_')
activeInput -> string[sz - 1] = ' ';
else
activeInput -> string[sz - 1] = '_';
activeInput -> flags |= ACS_REDRAW_OBJECT;
acsInputFlag = 0;
}
}
obj_flag = redraw();
if(flush_log)
flush();
else
flushLine -> clear();
if(!obj_flag && !NetworkON){
//KDWIN::Sleep(100);
}
return QuantCode;
}
int aciScreenDispatcher::ObjectQuant(void)
{
int ret = 0;
aciScreenObject* p = (aciScreenObject*)curScr -> objList -> fPtr;
while(p){
if(p -> activeSeq){
p -> ResID = p -> activeSeq -> ResourceID;
p -> resPtr = GetResource(p -> ResID);
p -> curFrame = p -> activeSeq -> CurFrame;
if(p -> activeSeq -> CurFrame == p -> activeSeq -> EndFrame)
p -> activeSeq = NULL;
else
p -> activeSeq -> CurFrame += p -> activeSeq -> FrameDelta;
p -> flags |= ACS_REDRAW_OBJECT;
ret = 1;
}
p -> Quant();
p = (aciScreenObject*)p -> next;
}
return ret;
}
void aciScreenResource::set_name(char* p)
{
int sz = strlen(p) + 1;
fname = new char[sz];
strcpy(fname,p);
}
void aciScreenDispatcher::SetResource(int obj_id,int res_id,int fr)
{
aciScreenResource* res = GetResource(res_id);
aciScreenObject* obj = GetObject(obj_id);
if(obj && res){
obj -> ResID = res -> ID;
obj -> resPtr = res;
if(fr == ACS_MAX_FRAME)
fr = acsGetMaxFrame(res_id);
obj -> curFrame = fr;
res -> flags |= ACS_NO_FLUSH;
acsGetResourceSize(res,obj -> PosX,obj -> PosY,obj -> SizeX,obj -> SizeY);
}
else
ErrH.Abort("SetResource() failed...");
}
void aciScreenDispatcher::SetSequence(int obj_id,int seq_id)
{
aciScreenFrameSequence* seq;
aciScreenObject* obj = GetObject(obj_id);
if(obj){
seq = obj -> GetSequence(seq_id);
obj -> activeSeq = seq;
seq -> CurFrame = seq -> StartFrame;
}
else
ErrH.Abort("SetSequence() failed...");
}
aciScreenFrameSequence* aciScreenObject::GetSequence(int id)
{
aciScreenFrameSequence* seq = (aciScreenFrameSequence*)frameSeq -> fPtr;
while(seq){
if(seq -> ID == id) return seq;
seq = (aciScreenFrameSequence*)seq -> next;
}
return NULL;
}
int acsGetMaxFrame(int res_id)
{
aciScreenResource* p;
aciScreenResourceBML* bml;
aciScreenResourceBMO* bmo;
p = acsScrD -> GetResource(res_id);
if(!p) return 0;
switch(p -> type){
case ACS_BML:
bml = (aciScreenResourceBML*)p;
return (bml -> NumFrames - 1);
case ACS_BMO:
bmo = (aciScreenResourceBMO*)p;
return (bmo -> NumFrames - 1);
}
return 0;
}
void acsGetResourceSize(aciScreenResource* p,int& x,int& y,int& sx,int& sy)
{
aciScreenResourceBMP* bmp;
aciScreenResourceBML* bml;
aciScreenResourceBMO* bmo;
aciScreenResourceXBM* xbm;
switch(p -> type){
case ACS_BMP:
bmp = (aciScreenResourceBMP*)p;
sx = bmp -> SizeX;
sy = bmp -> SizeY;
break;
case ACS_BML:
bml = (aciScreenResourceBML*)p;
sx = bml -> SizeX;
sy = bml -> SizeY;
break;
case ACS_BMO:
bmo = (aciScreenResourceBMO*)p;
x = bmo -> OffsX;
y = bmo -> OffsY;
sx = bmo -> SizeX;
sy = bmo -> SizeY;
break;
case ACS_XBM:
xbm = (aciScreenResourceXBM*)p;
x = xbm -> PosX;
y = xbm -> PosY;
sx = xbm -> SizeX;
sy = xbm -> SizeY;
break;
}
}
int aciScreenObject::CheckXY(int x,int y)
{
if(x >= PosX && x < PosX + SizeX && y >= PosY && y < PosY + SizeY)
return 1;
return 0;
}
int aciScreenScroller::CheckXY(int x,int y)
{
int dx = 0;
if(ScrRes) dx = ScrResSX * 3;
if(x >= PosX - dx && x < PosX + SizeX + dx && y >= PosY && y < PosY + SizeY)
return 1;
return 0;
}
aciScreenResource* acsAllocResource(int type)
{
aciScreenResource* p = NULL;
aciScreenResourceBMP* bmp;
aciScreenResourceBML* bml;
aciScreenResourceBMO* bmo;
aciScreenResourceXBM* xbm;
switch(type){
case ACS_BMP:
bmp = new aciScreenResourceBMP;
p = bmp;
break;
case ACS_BML:
bml = new aciScreenResourceBML;
p = bml;
break;
case ACS_BMO:
bmo = new aciScreenResourceBMO;
p = bmo;
break;
case ACS_XBM:
xbm = new aciScreenResourceXBM;
p = xbm;
break;
}
return p;
}
void acsFreeResource(aciScreenResource* p)
{
aciScreenResourceBMP* bmp;
aciScreenResourceBML* bml;
aciScreenResourceBMO* bmo;
aciScreenResourceXBM* xbm;
switch(p -> type){
case ACS_BMP:
bmp = (aciScreenResourceBMP*)p;
delete bmp;
break;
case ACS_BML:
bml = (aciScreenResourceBML*)p;
delete bml;
break;
case ACS_BMO:
bmo = (aciScreenResourceBMO*)p;
delete bmo;
break;
case ACS_XBM:
xbm = (aciScreenResourceXBM*)p;
delete xbm;
break;
}
}
aciScreenObject* acsAllocObject(int type)
{
aciScreenObject* p = NULL;
aciScreenScroller* scr;
aciScreenInputField* inp;
switch(type){
case ACS_BASE_OBJ:
p = new aciScreenObject;
break;
case ACS_SCROLLER_OBJ:
scr = new aciScreenScroller;
p = scr;
break;
case ACS_INPUT_FIELD_OBJ:
inp = new aciScreenInputField;
p = inp;
break;
}
return p;
}
void acsFreeObject(aciScreenObject* p)
{
aciScreenScroller* scr;
aciScreenInputField* inp;
switch(p -> type){
case ACS_BASE_OBJ:
delete p;
break;
case ACS_SCROLLER_OBJ:
scr = (aciScreenScroller*)p;
delete scr;
break;
case ACS_INPUT_FIELD_OBJ:
inp = (aciScreenInputField*)p;
delete inp;
break;
}
}
void aciScreenScroller::redraw(void)
{
int x,y,dx,dy,sx,_sx,_sy,sdx,sdy;
if(ActiveSX) _sx = ActiveSX;
else _sx = SizeX;
if(ActiveSY) _sy = ActiveSY;
else _sy = SizeY;
sdx = (SizeX - _sx) / 2;
sdy = (SizeY - _sy) / 2;
if(flags & ACS_BACK_RES)
aciScreenObject::redraw();
if(Color){
if(!ScrRes)
sx = (CurValue * _sx) / MaxValue;
else
sx = (CurValue * (_sx - ScrResSX)) / MaxValue + ScrResSX/2;
XGR_Rectangle(PosX + sdx,PosY + sdy,_sx,_sy,BackColor,BackColor,XGR_FILLED);
XGR_Rectangle(PosX + sdx,PosY + sdy,sx,_sy,Color,Color,XGR_FILLED);
}
if(!(flags & ACS_BACK_RES))
aciScreenObject::redraw();
if(sRes){
dx = (SizeX - sResSX) / 2;
dy = (SizeY - sResSY) / 2;
sRes -> redraw(PosX + dx,PosY + dy,0,XGR_HIDDEN_FON);
}
if(ScrRes){
sx = (CurValue * (_sx - ScrResSX)) / MaxValue;
x = PosX + sx;
y = PosY + ((SizeY - ScrResSY) >> 1);
ScrRes -> redraw(x + sdx,y,0,XGR_HIDDEN_FON);
}
}
void aciScreenScroller::Change(int x)
{
x -= PosX;
CurValue = (x * MaxValue) / SizeX;
if(CurValue < 0) CurValue = 0;
if(CurValue > MaxValue) CurValue = MaxValue;
flags |= ACS_REDRAW_OBJECT;
}
void aciScreenInputField::redraw(void)
{
int sz;
aciScreenObject::redraw();
if(!(flags & ACS_ALIGN_CENTER)){
if(flags & ACS_ISCREEN_FONT)
acsOutStr(PosX,PosY,font,Color,(unsigned char*)string,Space);
else
aOutStr(PosX,PosY,font,Color,(unsigned char*)string,Space);
}
else {
if(flags & ACS_ISCREEN_FONT){
sz = acsStrLen(font,(unsigned char*)string,Space);
acsOutStr(PosX + (SizeX - sz)/2,PosY,font,Color,(unsigned char*)string,Space);
}
else {
sz = aStrLen((unsigned char*)string,font,Space);
aOutStr(PosX + (SizeX - sz)/2,PosY,font,Color,(unsigned char*)string,Space);
}
}
}
void aciScreenDispatcher::ChangeScroller(int obj_id,int x)
{
aciScreenScroller* p = (aciScreenScroller*)GetObject(obj_id);
p -> Change(x);
}
void aciScreenDispatcher::SetScroller(int obj_id,int v,int max_v)
{
aciScreenScroller* p = (aciScreenScroller*)GetObject(obj_id);
if(!max_v) max_v = 1;
p -> CurValue = (p -> MaxValue * v) / max_v;
p -> flags |= ACS_REDRAW_OBJECT;
}
void aciScreenScroller::init(void)
{
int x,y;
aciScreenObject::init();
ScrRes = acsGetResource(ScrResID);
if(ScrRes)
acsGetResourceSize(ScrRes,x,y,ScrResSX,ScrResSY);
sRes = acsGetResource(sResID);
if(sRes)
acsGetResourceSize(sRes,x,y,sResSX,sResSY);
}
void aciScreenDispatcher::InputQuant(SDL_Event *event)
{
int sz;
unsigned char* ptr = NULL;
unsigned char chr;
HFont* hfnt = NULL;
if(!activeInput) {
return;
}
if (!(event != nullptr && (event->type == SDL_KEYDOWN || event->type == SDL_TEXTINPUT)))
return;
ptr = (unsigned char*)activeInput -> string;
if(activeInput -> flags & ACS_ISCREEN_FONT) {
hfnt = acsFntTable[activeInput -> font];
}
if (event != nullptr && event->type == SDL_KEYDOWN) {
if (event->key.keysym.sym > 0 && event->key.keysym.sym < 127) {
chr = event->key.keysym.sym;
} else {
return;
}
switch(event->key.keysym.sym) {
case SDLK_RETURN:
DoneInput();
break;
case SDLK_ESCAPE:
CancelInput();
break;
case SDLK_LEFT:
case SDLK_BACKSPACE:
sz = strlen((char*)ptr);
if(sz > 1) {
ptr[sz - 1] = 0;
ptr[sz - 2] = '_';
activeInput->flags |= ACS_REDRAW_OBJECT;
}
break;
}
} else if (event != nullptr && event->type == SDL_TEXTINPUT) {
if ((unsigned char)event->text.text[0] < 128) {
chr = event->text.text[0];
} else {
unsigned short utf = ((unsigned short *)event->text.text)[0];
utf = ntohs(utf);
// All cyrilic chars should be coding in two octets. 8, 11 bit-index for 1,2 octets
if ((utf & (1<<(7))) && !(utf & (1<<(10)))) {
chr = UTF8toCP866(utf);
} else {
chr = ' ';
}
}
if(hfnt && chr < (hfnt->StartChar-hfnt->EndChar+1) && (hfnt->data[chr]->Flags & NULL_HCHAR) && chr != ' ')
return;
sz = strlen((char*)ptr);
if(sz <= activeInput->MaxStrLen) {
ptr[sz - 1] = chr;
ptr[sz] = '_';
ptr[sz + 1] = 0;
activeInput -> flags |= ACS_REDRAW_OBJECT;
}
}
}
// Only for russian letters
unsigned char UTF8toCP866(unsigned short utf) {
if (utf >= 0xd090 && utf <= 0xd0bf) {
return utf - 0xd010;
}
if (utf >= 0xd180 && utf <= 0xd18f) {
return utf - 0xd0a0;
}
switch(utf) {
case 0xd081: //Ё
return 0xf0;
case 0xd191: //ё
return 0xf1;
}
return 0xdb;
}
void aciScreenDispatcher::PrepareInput(int obj_id)
{
int sz;
aciScreenInputField* p = (aciScreenInputField*)GetObject(obj_id);
if(p){
if(activeInput){
activeInput -> StopEvents();
CancelInput();
}
sz = strlen(p -> string) + 1;
if(!acsBackupStr){
acsBackupStr = new char[sz];
strcpy(acsBackupStr,p -> string);
}
p -> string[sz - 1] = '_';
p -> string[sz] = 0;
p -> flags |= ACS_ACTIVE_STRING;
activeInput = p;
SDL_StartTextInput();
}
}
void aciScreenInputField::alloc_str(void)
{
string = new char[MaxStrLen + 2];
memset(string,0,MaxStrLen + 2);
}
void acsLoadFonts(void)
{
int i;
XBuffer XBuf;
if(acsFntTable) acsFreeFonts();
acsFntTable = new HFont*[ACS_MAX_FONT];
for(i = 0; i < ACS_MAX_FONT; i ++){
XBuf.init();
XBuf < "resource/actint/640x480/hfonts/font";
if(i < 10) XBuf < "0";
XBuf <= i < ".fnc";
acsFntTable[i] = new HFont;
acsFntTable[i] -> Flags |= FONT_COLORS;
acsFntTable[i] -> load(XBuf.GetBuf());
acsFntTable[i] -> data[32] -> LeftOffs = acsFntTable[i] -> data[95] -> LeftOffs;
acsFntTable[i] -> data[32] -> RightOffs = acsFntTable[i] -> data[95] -> RightOffs;
}
}
void acsFreeFonts(void)
{
int i;
if(!acsFntTable) return;
for(i = 0; i < ACS_MAX_FONT; i ++)
delete acsFntTable[i];
delete[] acsFntTable;
acsFntTable = NULL;
}
void acsOutStr(int x,int y,int fnt,int col,unsigned char* str,int space)
{
int _x,_y,i,sx,sy,ss,sz = strlen((char*)str),col_sz;
HFont* p = acsFntTable[fnt];
HChar* ch;
unsigned char* ptr;
col_sz = (col >> 8) & 0xFF;
col &= 0xFF;
_x = x;
_y = y;
for(i = 0; i < sz; i ++){
ch = p -> data[str[i]];
ptr = ch -> HeightMap;
sx = ch -> SizeX;
sy = ch -> SizeY;
ss = sx * sy;
if(str[i] == '\n'){
_x = x;
_y += sy + space;
}
else {
aciPutSpr32(_x - ch -> LeftOffs,_y,sx,sy,ptr,col,col_sz);
_x += sx - ch -> RightOffs - ch -> LeftOffs + space;
}
}
}
int aciScreenDispatcher::GetObjectValue(int obj_id,int flag)
{
int ret = 0;
aciScreenObject* p = GetObject(obj_id);
if(p){
switch(p -> type){
case ACS_BASE_OBJ:
if(p -> curFrame) ret = 1;
break;
case ACS_SCROLLER_OBJ:
if(!flag)
ret = ((aciScreenScroller*)p) -> CurValue;
else
ret = ((aciScreenScroller*)p) -> MaxValue;
break;
}
}
return ret;
}
int acsStrLen(int fnt,unsigned char* str,int space)
{
int i,sx,sz = strlen((char*)str),len = 0;
HFont* p = acsFntTable[fnt];
HChar* ch;
for(i = 0; i < sz; i ++){
ch = p -> data[str[i]];
sx = ch -> SizeX;
if(str[i] != '\n'){
len += sx - ch -> RightOffs - ch -> LeftOffs + space;
}
}
return len;
}
void aciScreenDispatcher::CancelInput(void)
{
strcpy(activeInput -> string,acsBackupStr);
activeInput -> flags |= ACS_REDRAW_OBJECT;
activeInput -> flags &= ~ACS_ACTIVE_STRING;
activeInput = NULL;
delete[] acsBackupStr;
acsBackupStr = NULL;
SDL_StopTextInput();
}
void aciScreenDispatcher::DoneInput(void)
{
int sz;
sz = strlen(activeInput -> string);
activeInput -> string[sz - 1] = 0;
activeInput -> flags |= ACS_REDRAW_OBJECT;
activeInput -> flags &= ~ACS_ACTIVE_STRING;
activeInput = NULL;
delete[] acsBackupStr;
acsBackupStr = NULL;
SDL_StopTextInput();
}
void aciScreenInputField::Quant(void)
{
int prev = Color;
Color = Color0;
if(!(flags & ACS_ACTIVE_STRING)){
if(Color1 != -1 && CheckXY(XGR_MouseObj.PosX + XGR_MouseObj.SpotX,XGR_MouseObj.PosY + XGR_MouseObj.SpotY)){
Color = Color1;
}
}
else {
if(Color2 != -1) Color = Color2;
}
if(prev != Color) flags |= ACS_REDRAW_OBJECT;
}
void aciScreenInputField::init(void)
{
Color = Color0;
flags &= ~ACS_ACTIVE_STRING;
}
void aciScreenInputField::change_state(void)
{
if(!strcmp(string,aciSTR_OFF)){
strcpy(string,aciSTR_ON);
}
else {
strcpy(string,aciSTR_OFF);
}
flags |= ACS_REDRAW_OBJECT;
}
void aciScreenInputField::set_state(int v)
{
if(v){
strcpy(string,aciSTR_ON);
}
else {
strcpy(string,aciSTR_OFF);
}
flags |= ACS_REDRAW_OBJECT;
}
int aciScreenInputField::get_state(void)
{
if(!strcmp(string,aciSTR_OFF))
return 0;
return 1;
}
void acsChangeStrState(int id)
{
aciScreenInputField* p = (aciScreenInputField*)acsScrD -> GetObject(id);
if(p) p -> change_state();
}
void acsSetStrState(int id,int state)
{
aciScreenInputField* p = (aciScreenInputField*)acsScrD -> GetObject(id);
if(p) p -> set_state(state);
}
int acsGetStrState(int id)
{
aciScreenInputField* p = (aciScreenInputField*)acsScrD -> GetObject(id);
if(p) return p -> get_state();
return 0;
}