00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <GLW/GLWChannelView.h>
00022 #include <GLW/GLWFont.h>
00023 #include <GLW/GLWPanel.h>
00024 #include <GLW/GLWColors.h>
00025 #include <GLEXT/GLState.h>
00026 #include <image/ImageFactory.h>
00027 #include <XML/XMLParser.h>
00028 #include <common/Keyboard.h>
00029 #include <common/ToolTipResource.h>
00030 #include <client/ClientChannelManager.h>
00031 #include <client/ScorchedClient.h>
00032 #include <sound/SoundUtils.h>
00033 #include <tank/TankContainer.h>
00034 #include <lang/LangResource.h>
00035 #include <lang/LangParam.h>
00036
00037 GLWChannelViewI::~GLWChannelViewI()
00038 {
00039 }
00040
00041 REGISTER_CLASS_SOURCE(GLWChannelView);
00042
00043 GLWChannelView::GLWChannelView() :
00044 init_(false),
00045 visibleLines_(5), totalLines_(50),
00046 displayTime_(10.0f),
00047 fontSize_(12.0f), outlineFontSize_(14.0f), lineDepth_(18),
00048 currentVisible_(0), lastChannelId_(1), lastWhisperSrc_(0),
00049 alignTop_(false), parentSized_(false), splitLargeLines_(false),
00050 scrollPosition_(-1), allowScroll_(false),
00051 showChannelName_(true), showChannelNumber_(true),
00052 upButton_(x_ + 2.0f, y_ + 1.0f, 12.0f, 12.0f),
00053 downButton_(x_ + 2.0f, y_ + 1.0f, 12.0f, 12.0f),
00054 resetButton_(x_ + 2.0f, y_ + 1.0f, 14.0f, 14.0f),
00055 scrollUpKey_(0), scrollDownKey_(0), scrollResetKey_(0),
00056 handler_(0),
00057 createdTexture_(false)
00058 {
00059 upButton_.setHandler(this);
00060 downButton_.setHandler(this);
00061 resetButton_.setHandler(this);
00062
00063 upButton_.setToolTip(new ToolTipResource(
00064 ToolTip::ToolTipAlignLeft | ToolTip::ToolTipHelp,
00065 "CHAT_PREVIOUS", "Chat Previous",
00066 "CHAT_PREVIOUS_TOOLTIP", "Show previous chat entry"));
00067 downButton_.setToolTip(new ToolTipResource(
00068 ToolTip::ToolTipAlignLeft | ToolTip::ToolTipHelp,
00069 "CHAT_NEXT", "Chat Next",
00070 "CHAT_NEXT_TOOLTIP", "Show next chat entry"));
00071 resetButton_.setToolTip(new ToolTipResource(
00072 ToolTip::ToolTipAlignLeft | ToolTip::ToolTipHelp,
00073 "CHAT_LAST", "Chat Last",
00074 "CHAT_LAST_TOOLTIP", "View end of the chat log, \n"
00075 "hide all elapsed entries"));
00076 }
00077
00078 GLWChannelView::~GLWChannelView()
00079 {
00080 }
00081
00082 GLWChannelView::CurrentChannelEntry *GLWChannelView::getChannel(const std::string &channelName)
00083 {
00084 std::list<CurrentChannelEntry>::iterator itor;
00085 for (itor = currentChannels_.begin();
00086 itor != currentChannels_.end();
00087 itor++)
00088 {
00089 CurrentChannelEntry ¤t = *itor;
00090 if (channelName == current.channel) return ¤t;
00091 if (current.id == atoi(channelName.c_str())) return ¤t;
00092 }
00093 return 0;
00094 }
00095
00096 void GLWChannelView::registeredForChannels(
00097 std::list<ChannelDefinition> ®isteredChannels,
00098 std::list<ChannelDefinition> &availableChannels)
00099 {
00100
00101 std::list<CurrentChannelEntry> oldCurrentChannels = currentChannels_;
00102 std::list<BaseChannelEntry> oldAvailableChannels = availableChannels_;
00103 currentChannels_.clear();
00104 availableChannels_.clear();
00105
00106
00107 {
00108 std::list<ChannelDefinition>::iterator itor;
00109 for (itor = registeredChannels.begin();
00110 itor != registeredChannels.end();
00111 itor++)
00112 {
00113 std::string channel = itor->getChannel();
00114
00115
00116 bool found = false;
00117 std::list<CurrentChannelEntry>::iterator olditor;
00118 for (olditor = oldCurrentChannels.begin();
00119 olditor != oldCurrentChannels.end();
00120 olditor++)
00121 {
00122 CurrentChannelEntry &oldEntry = (*olditor);
00123 if (channel == oldEntry.channel)
00124 {
00125
00126 found = true;
00127 currentChannels_.push_back(oldEntry);
00128 break;
00129 }
00130 }
00131 if (!found)
00132 {
00133
00134 CurrentChannelEntry newEntry;
00135 newEntry.id = lastChannelId_++;
00136 newEntry.color = Vector(0.8f, 0.8f, 0.8f);
00137 newEntry.channel = channel;
00138 newEntry.type = itor->getType();
00139
00140 std::map<std::string, Vector>::iterator colorItor =
00141 channelColors_.find(channel.c_str());
00142 if (colorItor != channelColors_.end())
00143 {
00144 newEntry.color = colorItor->second;
00145 }
00146
00147 currentChannels_.push_back(newEntry);
00148 }
00149 }
00150 }
00151
00152
00153 {
00154 std::list<ChannelDefinition>::iterator itor;
00155 for (itor = availableChannels.begin();
00156 itor != availableChannels.end();
00157 itor++)
00158 {
00159 std::string channel = itor->getChannel();
00160
00161
00162 BaseChannelEntry newEntry;
00163 newEntry.channel = channel;
00164 newEntry.type = itor->getType();
00165 availableChannels_.push_back(newEntry);
00166 }
00167 }
00168
00169 if (handler_) handler_->channelsChanged(getId());
00170 }
00171
00172 void GLWChannelView::joinChannel(const std::string &channelName)
00173 {
00174 std::list<std::string> channels;
00175 formCurrentChannelList(channels);
00176 channels.push_back(channelName);
00177
00178 ClientChannelManager::instance()->changeRegistration(this, channels);
00179 }
00180
00181 void GLWChannelView::leaveChannel(const std::string &channelName)
00182 {
00183 std::list<std::string> channels;
00184 formCurrentChannelList(channels);
00185 channels.remove(channelName);
00186
00187 ClientChannelManager::instance()->changeRegistration(this, channels);
00188 }
00189
00190 void GLWChannelView::channelText(ChannelText &channelText)
00191 {
00192 if (!(channelText.getFlags() & ChannelText::eNoSound) &&
00193 !textSound_.empty())
00194 {
00195 CACHE_SOUND(sound, S3D::getDataFile(textSound_.c_str()));
00196 SoundUtils::playRelativeSound(VirtualSoundPriority::eText, sound);
00197 }
00198
00199 CurrentChannelEntry *channel = getChannel(channelText.getChannel());
00200 if (!channel) return;
00201
00202 Tank *tank = ScorchedClient::instance()->getTankContainer().
00203 getTankById(channelText.getSrcPlayerId());
00204 if (tank)
00205 {
00206 if (channel->type & ChannelDefinition::eWhisperChannel)
00207 {
00208 if (tank != ScorchedClient::instance()->getTankContainer().getCurrentTank())
00209 {
00210 lastWhisperSrc_ = tank->getPlayerId();
00211 }
00212 }
00213 }
00214
00215 LangString channelName;
00216 if (showChannelNumber_)
00217 {
00218 channelName.append(LANG_PARAM_1("{0}. ", channel->id));
00219 }
00220 if (showChannelName_)
00221 {
00222 channelName.append(LANG_PARAM_1("[c:{0}]", channel->channel));
00223 }
00224 if (tank)
00225 {
00226 channelName.append(LANG_PARAM_1("[p:{0}]", tank->getTargetName()));
00227 }
00228 if (channelText.getAdminPlayer()[0])
00229 {
00230 channelName.append(LANG_PARAM_1("[a:{0}]", channelText.getAdminPlayer()));
00231 }
00232 if (!channelName.empty())
00233 {
00234 channelName.append(LANG_STRING(" : "));
00235 }
00236 channelName.append(channelText.getMessage());
00237
00238 GLWChannelViewTextRenderer chanText(this);
00239 chanText.parseText(ScorchedClient::instance()->getContext(), channelName);
00240
00241 bool firstTime = true;
00242 int currentLen = 0;
00243 const LangString &text = chanText.getString();
00244 int totalLen = (int) text.size();
00245 while (currentLen < totalLen)
00246 {
00247
00248 int partLen = splitLine(&text[currentLen]);
00249 bool nl=(text[currentLen + partLen - 1] == '\n');
00250
00251
00252 GLWChannelViewTextRenderer newText(this);
00253 newText.subset(chanText, currentLen, (nl?partLen-1:partLen));
00254 addInfo(channel->color, newText);
00255
00256
00257 currentLen += partLen;
00258 }
00259 }
00260
00261 void GLWChannelView::buttonDown(unsigned int id)
00262 {
00263 if (!allowScroll_) return;
00264
00265 if (id == upButton_.getId())
00266 {
00267 scrollPosition_ ++;
00268 if (scrollPosition_ > (int) textLines_.size() - 1)
00269 scrollPosition_ = (int) textLines_.size() - 1;
00270 }
00271 else if (id == downButton_.getId())
00272 {
00273 scrollPosition_ --;
00274 if (scrollPosition_ < 0) scrollPosition_ = 0;
00275 }
00276 else
00277 {
00278 scrollPosition_ = -1;
00279 }
00280 }
00281
00282 int GLWChannelView::splitLine(const LangString &message)
00283 {
00284 int lastSpace = 0;
00285 int totalLen = (int) message.size();
00286 for (int len=1; len<totalLen; len++)
00287 {
00288 float width = 0.0f;
00289 if (splitLargeLines_)
00290 {
00291 width = GLWFont::instance()->getGameFont()->
00292 getWidth(outlineFontSize_, message, len);
00293 }
00294
00295 if (width > w_)
00296 {
00297
00298 if (lastSpace && (len - lastSpace < 15))
00299 {
00300 return lastSpace;
00301 }
00302 else
00303 {
00304
00305 return len - 1;
00306 }
00307 }
00308
00309 if (message[len] == '\n')
00310 {
00311 return len + 1;
00312 }
00313 if (message[len] == ' ')
00314 {
00315 lastSpace = len + 1;
00316 }
00317 }
00318
00319
00320 return totalLen;
00321 }
00322
00323 void GLWChannelView::addInfo(Vector &color, GLWChannelViewTextRenderer &text)
00324 {
00325 GLWChannelViewEntry entry;
00326 entry.text = text;
00327 entry.timeRemaining = displayTime_;
00328 entry.color = color;
00329 textLines_.push_front(entry);
00330
00331 if (scrollPosition_ > 0)
00332 {
00333 scrollPosition_ ++;
00334 if (scrollPosition_ > (int) textLines_.size() - 1)
00335 scrollPosition_ = (int) textLines_.size() - 1;
00336 }
00337
00338 if (textLines_.size() > (unsigned int) totalLines_)
00339 {
00340 textLines_.pop_back();
00341 }
00342 }
00343
00344 void GLWChannelView::simulate(float frameTime)
00345 {
00346 currentVisible_ = 0;
00347 int count = 0;
00348 std::list<GLWChannelViewEntry>::iterator itor;
00349 for (itor = textLines_.begin();
00350 itor != textLines_.end() && count < visibleLines_;
00351 itor++, count++)
00352 {
00353 GLWChannelViewEntry &entry = (*itor);
00354 entry.timeRemaining -= frameTime;
00355 if (entry.timeRemaining > 0.0f) currentVisible_ ++;
00356 }
00357 }
00358
00359 void GLWChannelView::setX(float x)
00360 {
00361 GLWidget::setX(x);
00362 upButton_.setX(x_ + 1.0f);
00363 downButton_.setX(x_ + 1.0f);
00364 resetButton_.setX(x_ + 1.0f);
00365 }
00366
00367 void GLWChannelView::setY(float y)
00368 {
00369 GLWidget::setY(y);
00370 upButton_.setY(y_ + 36.0f);
00371 downButton_.setY(y_ + 24.0f);
00372 resetButton_.setY(y_ + 6.0f);
00373 }
00374
00375 void GLWChannelView::draw()
00376 {
00377 GLWidget::draw();
00378 if (!createdTexture_)
00379 {
00380 createdTexture_ = true;
00381 ImageHandle upImg = ImageFactory::loadAlphaImageHandle(
00382 S3D::getDataFile("data/windows/arrow_u.png"));
00383 ImageHandle downImg = ImageFactory::loadAlphaImageHandle(
00384 S3D::getDataFile("data/windows/arrow_d.png"));
00385 ImageHandle resetImg = ImageFactory::loadAlphaImageHandle(
00386 S3D::getDataFile("data/windows/arrow_s.png"));
00387
00388 upTexture_.create(upImg, false);
00389 downTexture_.create(downImg, false);
00390 resetTexture_.create(resetImg, false);
00391
00392 upButton_.setTexture(&upTexture_);
00393 downButton_.setTexture(&downTexture_);
00394 resetButton_.setTexture(&resetTexture_);
00395 }
00396
00397 if (allowScroll_)
00398 {
00399 upButton_.draw();
00400 downButton_.draw();
00401 resetButton_.draw();
00402 }
00403
00404 if (!init_)
00405 {
00406 ClientChannelManager::instance()->registerClient(this, startupChannels_);
00407 init_ = true;
00408 if (parent_ && parentSized_)
00409 {
00410 w_ = parent_->getW();
00411 h_ = parent_->getH();
00412 }
00413 }
00414
00415
00416 if (textLines_.empty()) return;
00417
00418
00419 GLState currentStateBlend(GLState::TEXTURE_ON |
00420 GLState::BLEND_ON | GLState::DEPTH_OFF);
00421 float start = y_ + 8.0f;
00422 if (alignTop_)
00423 {
00424 start = y_ + h_ - float(currentVisible_) * lineDepth_;
00425 }
00426
00427
00428
00429 std::list<GLWChannelViewEntry>::iterator startingPos = textLines_.begin();
00430 {
00431 int count = 0;
00432 for (;
00433 startingPos != textLines_.end() && count < scrollPosition_;
00434 startingPos++, count++)
00435 {
00436 }
00437 }
00438
00439
00440
00441
00442 {
00443 int count = 0;
00444 std::list<GLWChannelViewEntry>::iterator itor;
00445 for (itor = startingPos;
00446 itor != textLines_.end() && count < visibleLines_;
00447 itor++, count++)
00448 {
00449 GLWChannelViewEntry &entry = (*itor);
00450
00451 float alpha = 1.0f;
00452 if (scrollPosition_ < 0)
00453 {
00454 if (entry.timeRemaining <= 0.0f) continue;
00455 if (entry.timeRemaining < 1.0f) alpha = entry.timeRemaining;
00456 }
00457
00458 float x = x_ + 20.0f;
00459 float y = start + count * lineDepth_;
00460
00461 GLWFont::instance()->getGameShadowFont()->
00462 drawA(GLWColors::black, alpha, fontSize_,
00463 x - 1.0f, y + 1.0f, 0.0f,
00464 entry.text.getString());
00465 }
00466 }
00467
00468 {
00469 int count = 0;
00470 std::list<GLWChannelViewEntry>::iterator itor;
00471 for (itor = startingPos;
00472 itor != textLines_.end() && count < visibleLines_;
00473 itor++, count++)
00474 {
00475 GLWChannelViewEntry &entry = (*itor);
00476
00477 float alpha = 1.0f;
00478 if (scrollPosition_ < 0)
00479 {
00480 if (entry.timeRemaining <= 0.0f) continue;
00481 if (entry.timeRemaining < 1.0f) alpha = entry.timeRemaining;
00482 }
00483
00484 float x = x_ + 20.0f;
00485 float y = start + count * lineDepth_;
00486
00487 GLWFont::instance()->getGameFont()->
00488 drawA(&entry.text, entry.color, alpha, fontSize_,
00489 x, y, 0.0f,
00490 entry.text.getString());
00491 }
00492 }
00493 }
00494
00495 void GLWChannelView::mouseDown(int button, float x, float y, bool &skipRest)
00496 {
00497 skipRest = false;
00498 upButton_.mouseDown(button, x, y, skipRest);
00499 downButton_.mouseDown(button, x, y, skipRest);
00500 resetButton_.mouseDown(button, x, y, skipRest);
00501 }
00502
00503 void GLWChannelView::mouseUp(int button, float x, float y, bool &skipRest)
00504 {
00505 skipRest = false;
00506 upButton_.mouseUp(button, x, y, skipRest);
00507 downButton_.mouseUp(button, x, y, skipRest);
00508 resetButton_.mouseUp(button, x, y, skipRest);
00509 }
00510
00511 void GLWChannelView::mouseDrag(int button, float mx, float my, float x, float y, bool &skipRest)
00512 {
00513 skipRest = false;
00514 upButton_.mouseDrag(button, mx, my, x, y, skipRest);
00515 downButton_.mouseDrag(button, mx, my, x, y, skipRest);
00516 resetButton_.mouseDrag(button, mx, my, x, y, skipRest);
00517 }
00518
00519 void GLWChannelView::keyDown(char *buffer, unsigned int keyState,
00520 KeyboardHistory::HistoryElement *history, int hisCount,
00521 bool &skipRest)
00522 {
00523 if (scrollUpKey_ && scrollUpKey_->keyDown(buffer, keyState, false))
00524 {
00525 buttonDown(upButton_.getId());
00526 skipRest = true;
00527 }
00528 if (scrollDownKey_ && scrollDownKey_->keyDown(buffer, keyState, false))
00529 {
00530 buttonDown(downButton_.getId());
00531 skipRest = true;
00532 }
00533 if (scrollResetKey_ && scrollResetKey_->keyDown(buffer, keyState, false))
00534 {
00535 buttonDown(resetButton_.getId());
00536 skipRest = true;
00537 }
00538 }
00539
00540 bool GLWChannelView::initFromXML(XMLNode *node)
00541 {
00542 if (!GLWidget::initFromXML(node)) return false;
00543
00544 if (!initFromXMLInternal(node)) return false;
00545
00546 return true;
00547 }
00548
00549 void GLWChannelView::formCurrentChannelList(std::list<std::string> &result)
00550 {
00551 std::list<CurrentChannelEntry>::iterator itor;
00552 for (itor = currentChannels_.begin();
00553 itor != currentChannels_.end();
00554 itor++)
00555 {
00556 CurrentChannelEntry &entry = *itor;
00557 result.push_back(entry.channel);
00558 }
00559 }
00560
00561 bool GLWChannelView::initFromXMLInternal(XMLNode *node)
00562 {
00563 if (!node->getNamedChild("displaytime", displayTime_)) return false;
00564 if (!node->getNamedChild("totallines", totalLines_)) return false;
00565 if (!node->getNamedChild("visiblelines", visibleLines_)) return false;
00566 if (!node->getNamedChild("linedepth", lineDepth_)) return false;
00567 if (!node->getNamedChild("fontsize", fontSize_)) return false;
00568 if (!node->getNamedChild("outlinefontsize", outlineFontSize_)) return false;
00569 if (!node->getNamedChild("textaligntop", alignTop_)) return false;
00570 if (!node->getNamedChild("parentsized", parentSized_)) return false;
00571 if (!node->getNamedChild("splitlargelines", splitLargeLines_)) return false;
00572 if (!node->getNamedChild("allowscroll", allowScroll_)) return false;
00573 if (!node->getNamedChild("showchannelname", showChannelName_)) return false;
00574 if (!node->getNamedChild("showchannelnumber", showChannelNumber_)) return false;
00575
00576 node->getNamedChild("textsound", textSound_, false);
00577
00578 std::string startupchannel;
00579 while (node->getNamedChild("channel", startupchannel, false))
00580 {
00581 startupChannels_.push_back(startupchannel);
00582 }
00583
00584 XMLNode *channelcolors;
00585 while (node->getNamedChild("channelcolor", channelcolors, false))
00586 {
00587 std::string channel;
00588 Vector color;
00589 if (!channelcolors->getNamedChild("channel", channel)) return false;
00590 if (!channelcolors->getNamedChild("color", color)) return false;
00591 channelColors_[channel] = color;
00592 }
00593
00594 std::string scrollUpKey, scrollDownKey, scrollResetKey;
00595 if (node->getNamedChild("scrollupkey", scrollUpKey, false))
00596 {
00597 scrollUpKey_ = Keyboard::instance()->getKey(scrollUpKey.c_str());
00598 }
00599 if (node->getNamedChild("scrolldownkey", scrollDownKey, false))
00600 {
00601 scrollDownKey_ = Keyboard::instance()->getKey(scrollDownKey.c_str());
00602 }
00603 if (node->getNamedChild("scrollresetkey", scrollResetKey, false))
00604 {
00605 scrollResetKey_ = Keyboard::instance()->getKey(scrollResetKey.c_str());
00606 }
00607 return true;
00608 }