/* * pawsmainwidget.cpp - Author: Andrew Craig * * Copyright (C) 2003 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 of the License) * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ // pawsmainwidget.cpp: implementation of the pawsMainWidget class. // ////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include #include "psmainwidget.h" #include "chatwindow.h" #include "paws/pawsmanager.h" #include "inventorywindow.h" #include "pawsinfowindow.h" #include "util/log.h" #include "util/strutil.h" #include "util/psxmlparser.h" #include "pscamera.h" #include "pscharcontrol.h" #include "effects/pseffectmanager.h" #include "actionhandler.h" #include "paws/pawsprefmanager.h" #include "pawsgameboard.h" #define DEFAULT_CONFIG_FILE_NAME "/this/data/options/entityinter_def.xml" #define CONFIG_FILE_NAME "/this/data/options/entityinter.xml" #define FONT_SIZE 13 // Size for the font at 800x600 ////////////////////////////////////////////////////////////////////// // entity types ////////////////////////////////////////////////////////////////////// psEntityType::psEntityType(csString id, csString label, int dflt, csString commandsStr, csString labelsStr) { this->id = id; this->label = label; this->dflt = dflt; usedCommand = dflt; Split(labelsStr, this->labels); Split(commandsStr, this->commands); } psEntityTypes::psEntityTypes(iObjectRegistry* objReg) { this->objReg = objReg; vfs = CS_QUERY_REGISTRY( objReg, iVFS ); types.Push(new psEntityType("items", "Items", 2, "use|combine|pickup|unlock|examine", "Use|Combine|Pick up|Unlock|Examine")); types.Push(new psEntityType("players", "Players", 0, "playerdesc|exchange|attack", "Description|Exchange|Attack")); types.Push(new psEntityType("merchants", "Merchants", 0, "buysell|give|playerdesc|attack", "Buy/Sell|Give|Description|Attack")); types.Push(new psEntityType("aliveNPCs", "Alive NPCs", 3, "buysell|give|playerdesc|attack", "Buy/Sell|Give|Description|Attack")); types.Push(new psEntityType("deadNPCs", "Dead NPCs", 0, "loot|playerdesc", "Loot|Description")); types.Push(new psEntityType("petNPCs", "Pet NPCs", 0, "playerdesc", "Description")); /*If you add a new psEntityType don't forget to add the widgets in data/gui/configentityinter.xml!!!*/ } bool psEntityTypes::LoadConfigFromFile() { // Check if there have been created a custom file // else use the default file. csString fileName = CONFIG_FILE_NAME; if (!vfs->Exists(fileName)) { fileName = DEFAULT_CONFIG_FILE_NAME; } csRef doc = ParseFile(objReg, fileName); if (!doc) { Error2("Parse error in %s", fileName.GetData()); return false; } csRef rootNode = doc->GetRoot(); if(!rootNode) { Error2("No XML root in %s", fileName.GetData()); return false; } csRef topNode = rootNode->GetNode("EntityInteraction"); if(!topNode) { Error2("No tag in %s", fileName.GetData()); return false; } for (size_t i=0; i < types.Length(); i++) { csRef entNode = topNode->GetNode(types[i]->id); if (entNode != NULL) { types[i]->usedCommand = entNode->GetAttributeValueAsInt("value"); } else { types[i]->usedCommand = types[i]->dflt; } } return true; } bool psEntityTypes::SaveConfigToFile() { csString xml; xml = "\n"; for (size_t i=0; i < types.Length(); i++) xml += csString().Format("\t<%s value='%i'/>\n", types[i]->id.GetData(), types[i]->usedCommand); xml += ""; return vfs->WriteFile(CONFIG_FILE_NAME, xml.GetData(), xml.Length()); } csString psEntityTypes::BuildDfltBehaviors() { csString dflt; for (size_t i=0; i < types.Length(); i++) { if (i > 0) dflt += "|"; dflt += types[i]->commands[types[i]->usedCommand]; } return dflt; } ////////////////////////////////////////////////////////////////////// // psMainWidget ////////////////////////////////////////////////////////////////////// psMainWidget::psMainWidget() : entTypes(PawsManager::GetSingleton().GetObjectRegistry()), psCmdBase( NULL,NULL, PawsManager::GetSingleton().GetObjectRegistry() ) { cel = NULL; chatWindow = NULL; locked = false; entTypes.LoadConfigFromFile(); lastWidget = 0; } psMainWidget::~psMainWidget() { if(msgqueue) msgqueue->Unsubscribe(this, MSGTYPE_SYSTEM); } bool psMainWidget::OnDoubleClick( int button, int keyModifier, int x, int y ) { // Check to see if an entity was selected. pawsWidget* underlaying = WidgetAt( x, y ); if ( psengine->GetPSCamera() && underlaying == this ) { GEMClientObject* over = FindMouseOverObject( x, y ); if ( psengine->GetMouseBinds()->CheckBind( "EntitySelect", button, keyModifier) ) { if ( over ) { psUserActionMessage action( 0, over->GetEntity()->GetID(), "dfltBehavior", entTypes.BuildDfltBehaviors() ); action.SendMessage(); } } } return false; } bool psMainWidget::OnKeyDown( int keyCode, int key, int modifiers ) { if (!locked) { if (pawsMainWidget::OnKeyDown(keyCode,key,modifiers)) { return true; } // Check for tabing in and out of chat window. psCharController* charctrl = psengine->GetCharControl(); if(!charctrl) return true; if ( charctrl->MatchTrigger("Toggle chat",psControl::KEYBOARD,keyCode,modifiers) ) { if ( chatWindow == NULL ) { chatWindow = (pawsChatWindow*)FindWidget("ChatWindow"); } if ( chatWindow ) { if ( chatWindow->InputActive() ) { if ( lastWidget ) { BringToTop(lastWidget); PawsManager::GetSingleton().SetCurrentFocusedWidget( lastWidget ); } } else { lastWidget = PawsManager::GetSingleton().GetCurrentFocusedWidget(); chatWindow->Show(); BringToTop( chatWindow ); PawsManager::GetSingleton().SetCurrentFocusedWidget( chatWindow->FindWidget("InputText") ); } } return true; } if ( charctrl->MatchTrigger("Reply tell",psControl::KEYBOARD,keyCode,modifiers) ) { if ( chatWindow == NULL ) { chatWindow = (pawsChatWindow*)FindWidget("ChatWindow"); } if (chatWindow && HasFocus()) { chatWindow->Show(); BringToTop( chatWindow ); PawsManager::GetSingleton().SetCurrentFocusedWidget( chatWindow->FindWidget("InputText") ); chatWindow->AutoReply(); } return true; } if ( charctrl->MatchTrigger("Close",psControl::KEYBOARD,keyCode,modifiers) ) { pawsWidget* widget = PawsManager::GetSingleton().GetCurrentFocusedWidget(); if (widget != this) { //Keep checking for a parent untill the main widget is found for (pawsWidget* parent = widget->GetParent();parent != this;parent=widget->GetParent()) widget = parent; widget->Close(); } else { pawsControlWindow* ctrlWindow = dynamic_cast(FindWidget("ControlWindow")); if(!ctrlWindow) return false; // Should never happen, but no way to be sure. ctrlWindow->Toggle(); } return true; } return false; } //If we return true, it will not parse the keycode to CharControl return true; } bool psMainWidget::OnMouseDown( int button, int keyModifier, int x, int y ) { pawsWidget* bar = FindWidget("ControlWindow"); if (!bar) return false;// no gui loaded, so nothing here can be done. // Check to see if we are dropping an item if ( psengine->GetSlotManager() && psengine->GetSlotManager()->IsDragging() ) { psengine->GetSlotManager()->DropItem(); return true; } // Check to see if we are dropping a game piece pawsGameBoard *gameBoard = dynamic_cast(FindWidget("GameBoardWindow")); if (gameBoard && gameBoard->IsDragging()) { gameBoard->DropPiece(); } // Close interact menu automatically pawsWidget* interactWindow = FindWidget("InteractWindow"); if (interactWindow) interactWindow->Hide(); if (button == csmbWheelUp) { psengine->GetPSCamera()->MoveDistance(-1.0f); return true; } if (button == csmbWheelDown) { psengine->GetPSCamera()->MoveDistance(1.0f); return true; } // Check to see if an entity was selected pawsWidget* underlaying = WidgetAt(x,y); if ( psengine->GetPSCamera() && underlaying == this ) { GEMClientObject* over = FindMouseOverObject( x, y ); if (psengine->GetMouseBinds()->CheckBind("EntitySelect", button, keyModifier)) { if ( over ) { psengine->GetCharManager()->SetTarget(over,"select"); } else { // Deselect current target psengine->GetCharManager()->SetTarget(NULL, "select"); //// Check for Action Location //{ // int poly = 0; // csVector3 pos; // iMeshWrapper* mesh = psengine->GetPSCamera()->FindMeshUnder2D( x, y, &pos, &poly ); // if (mesh) // { // iSector* sector = psengine->GetPSCamera()->GetICamera()->GetSector(); // const char* sectorname = sector->QueryObject()->GetName(); // const char* meshname = mesh->QueryObject()->GetName(); // psengine->GetActionHandler()->Query( "SELECT", sectorname, meshname, poly, pos); // } //} } } // Check Context Menu if (psengine->GetMouseBinds()->CheckBind("ContextMenu", button, keyModifier)) { if ( over ) { psengine->GetCharManager()->SetTarget(over, "context"); } else { // Deselect current target psengine->GetCharManager()->SetTarget(NULL, "select"); // Check for Action Location { int poly = 0; csVector3 pos; iMeshWrapper* mesh = psengine->GetPSCamera()->FindMeshUnder2D( x, y, &pos, &poly ); if (mesh) { iSector* sector = psengine->GetPSCamera()->GetICamera()->GetSector(); const char* sectorname = sector->QueryObject()->GetName(); const char* meshname = mesh->QueryObject()->GetName(); // See if it's worth quering //bool meshRecorded = psengine->GetCelClient()->IsMeshSubjectToAction(sectorname,meshname); //pawsWidget* action = PawsManager::GetSingleton().FindWidget("AddEditActionWindow"); //if((action && action->IsVisible()) || meshRecorded) psengine->GetActionHandler()->Query( "SELECT", sectorname, meshname, poly, pos); } } } } } return false; } bool psMainWidget::OnMouseUp( int button, int keyModifier, int x, int y ) { return false; } void psMainWidget::SetCamera( iCelEntity* entity ) { /* Let the main widget know about the camera since it needs it * to locate other entities using hitbeam. */ // csRef pccamera = CEL_QUERY_PROPCLASS(entity->GetPropertyClassList(), // iPcCamera ); // guiCamera = pccamera->GetCamera(); } GEMClientObject* psMainWidget::FindMouseOverObject( int x, int y ) { if ( !cel ) { cel = psengine->GetCelClient(); } if (!psengine->GetPSCamera()) return NULL; iMeshWrapper* sel = psengine->GetPSCamera()->FindMeshUnder2D(x,y); if ( sel ) { if (!sel->QueryObject()) return NULL; csRef entity = cel->GetPlLayer()->FindAttachedEntity( sel->QueryObject() ); if ( entity ) { GEMClientObject* target = cel->FindObject( entity->GetID() ); return target; } else { return NULL; } } return NULL; } bool psMainWidget::SetupMain() { psCmdBase::Setup( psengine->GetMsgHandler(), psengine->GetCmdHandler()); float fontsize; //fontsize = float(FONT_SIZE) / float(1024) * ; fontsize = PawsManager::GetSingleton().GetFontFactor() * float(FONT_SIZE); printf("Using fontsize %d for resolution %dx%d\n",(int)fontsize,screenFrame.Width(),screenFrame.Height()); mesgFont = graphics2D->GetFontServer()->LoadFont("/this/data/ttf/verdana.ttf",(int)fontsize); mesgFirstFont = graphics2D->GetFontServer()->LoadFont("/this/data/ttf/scurlock.ttf",(int)fontsize*2); msgqueue->Subscribe(this, MSGTYPE_SYSTEM); return true; } void psMainWidget::HandleMessage( MsgEntry* message ) { if(message->GetType() != MSGTYPE_SYSTEM) return; psSystemMessage mesg(message); int color = -1; if(mesg.type == MSG_ERROR) color = graphics2D->FindRGB(255,0,0); else if(mesg.type == MSG_RESULT) color = graphics2D->FindRGB(255,255,0); else if(mesg.type == MSG_OK) color = graphics2D->FindRGB(0,255,0); else if(mesg.type == MSG_ACK) color = graphics2D->FindRGB(0,0,255); if(color != -1) PrintOnScreen(mesg.msgline,color); } void psMainWidget::DrawChildren() { // Call the widget's draw functions first pawsMainWidget::DrawChildren(); for(size_t i = 0; i < onscreen.Length();i++) { ClipToParent(); onscreen[i]->Draw(); } } void psMainWidget::DeleteChild(pawsWidget* txtBox) { for(size_t i = 0; i < onscreen.Length();i++) { if(txtBox == onscreen[i]) { pawsWidget* widget = onscreen[i]; onscreen.DeleteIndex(i); delete widget; return; } } pawsMainWidget::DeleteChild(txtBox); } void psMainWidget::PrintOnScreen( const char* text, int color, float ymod ) { if (strlen(text) < 2) { Error2("Tried to print text with less than 2 chars in a Fading way (%s)",text); return; } // Create a fading textbox widget pawsFadingTextBox* txtBox = (pawsFadingTextBox*)PawsManager::GetSingleton().CreateWidget("pawsFadingTextBox"); if (!txtBox) { Error1("Couldn't create a pawsFadingTextBox for onscreen message!"); return; } txtBox->SetParent(this); txtBox->SetText(text,mesgFirstFont,mesgFont,color); // Set options and enable txtBox->Show(); onscreen.Push(txtBox); // Do like this to have full controll on the controlls :P // Set the right size int h=0,w=0; txtBox->GetSize(w,h); txtBox->Resize(w,h,0); int x,y; x = (ScreenFrame().Width() / 2) - (w / 2); y = (int)(ScreenFrame().Height() * ymod) - (h / 2); y = y - ScreenFrame().Height() / 8; txtBox->MoveTo(x,y); // Move the others down if (onscreen.Length() < 2) return; int j = 0; for (int i = (int)onscreen.Length()-2; i >= 0; i--) { j++; pawsFadingTextBox* widget = (pawsFadingTextBox*)onscreen[i]; widget->MoveDelta(0,h); if (j > 2) // force fading if there is more than 2 elements widget->Fade(); } } void psMainWidget::ClearFadingText() { for (int i = (int)onscreen.Length()-1; i >= 0; i--) { pawsFadingTextBox* widget = (pawsFadingTextBox*)onscreen[i]; widget->DeleteYourself(); } }