text: #include "stdafx.h"
  #include "map_spot.h"
  #include "map_location.h"
  
  #include "ui/UIXmlInit.h"
  #include "ui/UIMApWnd.h"
  #include "level.h"
  #include "ui/UIInventoryUtilities.h"
  #include "../xrEngine/xr_object.h"
  #include "object_broker.h"
  #include "ui/UITextureMaster.h"
  #include "ui/UIHelper.h"
  
  #include "xrRender/UIShader.h"
  #include "gametaskmanager.h"
  #include "gametask.h"
  
  CMapSpot::CMapSpot(CMapLocation* ml) : m_map_location(ml) {
      m_bScale = false;
      m_location_level = 0;
      m_border_static = NULL;
      m_scale_bounds.set(-1.0f, -1.0f);
  }
  
  CMapSpot::~CMapSpot() {}
  
  void CMapSpot::Load(CUIXml* xml, LPCSTR path) {
      CUIXmlInit::InitStatic(*xml, path, 0, this);
      if (!Heading()) {
          SetWidth(GetWidth() * UI().get_current_kx());
          SetStretchTexture(true);
      }
  
      int i = xml->ReadAttribInt(path, 0, "scale", 0);
      m_bScale = (i == 1);
      m_scale_bounds.x = xml->ReadAttribFlt(path, 0, "scale_min", -1.0f);
      if (m_bScale) {
          m_scale_bounds.y = xml->ReadAttribFlt(path, 0, "scale_max", -1.0f);
          R_ASSERT2(m_scale_bounds.x > 0 && m_scale_bounds.y > 0, path);
      }
      m_location_level = xml->ReadAttribInt(path, 0, "location_level", 0);
  
      m_originSize = GetWndSize();
  
      string512 str;
      strconcat(sizeof(str), str, path, ":static_border");
      if (xml->NavigateToNode(str)) {
          m_border_static = UIHelper::CreateStatic(*xml, str, this);
          m_border_static->Show(false);
          if (!Heading()) {
              m_border_static->SetWidth(m_border_static->GetWidth() * UI().get_current_kx());
              m_border_static->SetStretchTexture(true);
          }
      }
      m_mark_focused = false;
  }
  
  LPCSTR CMapSpot::GetHint() { return MapLocation()->GetHint(); };
  
  void CMapSpot::SetWndPos(const Fvector2& pos) { inherited::SetWndPos(pos); }
  
  void CMapSpot::Update() {
      inherited::Update();
      if (m_bCursorOverWindow) {
          if (Device.dwTimeGlobal > (m_dwFocusReceiveTime + 500)) {
              GetMessageTarget()->SendMessage(this, MAP_SHOW_HINT, NULL);
          }
      }
  }
  
  bool CMapSpot::OnMouseDown(int mouse_btn) {
      if (mouse_btn == MOUSE_1) {
          CGameTask* t = Level().GameTaskManager().HasGameTask(m_map_location, true);
          if (t) {
              GetMessageTarget()->SendMessage(this, MAP_SELECT_SPOT);
              return true;
          }
          return false;
      } else {
          return false;
      }
  }
  
  void CMapSpot::OnFocusLost() {
      inherited::OnFocusLost();
      GetMessageTarget()->SendMessage(this, MAP_HIDE_HINT, NULL);
  }
  
  void CMapSpot::show_static_border(bool status) {
      if (m_border_static) {
          m_border_static->Show(status);
      }
  }
  
  void CMapSpot::mark_focused() { m_mark_focused = true; }
  
  // -------------------------------------------------------------------------------------------------
  
  CMapSpotPointer::CMapSpotPointer(CMapLocation* ml) : inherited(ml) {}
  
  CMapSpotPointer::~CMapSpotPointer() {}
  
  LPCSTR CMapSpotPointer::GetHint() { return NULL; }
  
  //////////////////////////////////////////////////
  CMiniMapSpot::CMiniMapSpot(CMapLocation* ml) : inherited(ml) {}
  
  CMiniMapSpot::~CMiniMapSpot() {}
  
  void CMiniMapSpot::Load(CUIXml* xml, LPCSTR path) {
      inherited::Load(xml, path);
  
      string256 buf;
  
      Frect base_rect;
      base_rect.x1 = 0;
      base_rect.y1 = 0;
      base_rect.x2 = xml->ReadAttribFlt(path, 0, "width", 0);
      base_rect.y2 = xml->ReadAttribFlt(path, 0, "height", 0);
  
      Frect _stored_rect = m_UIStaticItem.GetTextureRect();
  
      strconcat(sizeof(buf), buf, path, ":texture_above");
      XML_NODE n = xml->NavigateToNode(buf, 0);
      if (n) {
          LPCSTR texture = xml->Read(buf, 0, NULL);
          CUITextureMaster::InitTexture(texture, &m_UIStaticItem);
          if (strchr(texture, '\\')) {
              float x = xml->ReadAttribFlt(buf, 0, "x", base_rect.x1);
              float y = xml->ReadAttribFlt(buf, 0, "y", base_rect.y1);
              float width = xml->ReadAttribFlt(buf, 0, "width", base_rect.width());
              float height = xml->ReadAttribFlt(buf, 0, "height", base_rect.height());
              m_tex_rect_above.set(x, y, x + width, y + height);
          } else
              m_tex_rect_above = m_UIStaticItem.GetTextureRect();
  
          m_icon_above = m_UIStaticItem.GetShader();
      }
  
      strconcat(sizeof(buf), buf, path, ":texture_below");
      n = xml->NavigateToNode(buf, 0);
      if (n) {
          LPCSTR texture = xml->Read(buf, 0, NULL);
          CUITextureMaster::InitTexture(texture, &m_UIStaticItem);
          if (strchr(texture, '\\')) {
              float x = xml->ReadAttribFlt(buf, 0, "x", base_rect.x1);
              float y = xml->ReadAttribFlt(buf, 0, "y", base_rect.y1);
              float width = xml->ReadAttribFlt(buf, 0, "width", base_rect.width());
              float height = xml->ReadAttribFlt(buf, 0, "height", base_rect.height());
              m_tex_rect_below.set(x, y, x + width, y + height);
          } else
              m_tex_rect_below = m_UIStaticItem.GetTextureRect();
  
          m_icon_below = m_UIStaticItem.GetShader();
      }
      strconcat(sizeof(buf), buf, path, ":texture");
      n = xml->NavigateToNode(buf, 0);
      if (n) {
          LPCSTR texture = xml->Read(buf, 0, NULL);
          CUITextureMaster::InitTexture(texture, &m_UIStaticItem);
          if (strchr(texture, '\\')) {
              float x = xml->ReadAttribFlt(buf, 0, "x", base_rect.x1);
              float y = xml->ReadAttribFlt(buf, 0, "y", base_rect.y1);
              float width = xml->ReadAttribFlt(buf, 0, "width", base_rect.width());
              float height = xml->ReadAttribFlt(buf, 0, "height", base_rect.height());
              m_tex_rect_normal.set(x, y, x + width, y + height);
          } else
              m_tex_rect_normal = m_UIStaticItem.GetTextureRect();
  
          m_icon_normal = m_UIStaticItem.GetShader();
      }
  
      m_UIStaticItem.SetTextureRect(_stored_rect);
  }
  
  void CMiniMapSpot::Draw() {
      CObject* O = Level().CurrentViewEntity();
      if (O && m_icon_above->inited() && m_icon_below->inited()) {
          float ml_y = MapLocation()->GetLastPosition().y;
          float d = O->Position().y - ml_y;
  
          if (d > 1.8f) {
              GetUIStaticItem().SetShader(m_icon_below);
              GetUIStaticItem().SetTextureRect(m_tex_rect_below);
          } else if (d < -1.8f) {
              GetUIStaticItem().SetShader(m_icon_above);
              GetUIStaticItem().SetTextureRect(m_tex_rect_above);
          } else {
              GetUIStaticItem().SetShader(m_icon_normal);
              GetUIStaticItem().SetTextureRect(m_tex_rect_normal);
          }
      };
  
      inherited::Draw();
  }
  
  /// ---------------------------------------------------------------------------------------------
  void CUIStaticOrig::InitWndOrigin() {
      m_origin_pos = GetWndPos();
      m_origin_size = GetWndSize();
  }
  
  void CUIStaticOrig::ScaleOrigin(float k) {
      SetWndPos(Fvector2().set(m_origin_pos.x * k, m_origin_pos.y * k));
      SetWndSize(Fvector2().set(m_origin_size.x * k, m_origin_size.y * k));
  }
  
  CComplexMapSpot::CComplexMapSpot(CMapLocation* ml) : inherited(ml) {
      m_infinity_time = false;
      m_last_delay = 0;
      m_timer_finish = 0;
      m_left_icon = NULL;
      m_right_icon = NULL;
      m_top_icon = NULL;
      m_timer = NULL;
  }
  
  CComplexMapSpot::~CComplexMapSpot() {}
  
  CUIStaticOrig* CComplexMapSpot::CreateStaticOrig(CUIXml& xml, LPCSTR ui_path) {
      CUIStaticOrig* ui = xr_new<CUIStaticOrig>();
      AttachChild(ui);
      ui->SetAutoDelete(true);
      CUIXmlInit::InitStatic(xml, ui_path, 0, ui);
      ui->InitWndOrigin();
      return ui;
  }
  
  void CComplexMapSpot::Load(CUIXml* xml, LPCSTR path) // complex_spot_template
  {
      inherited::Load(xml, path);
  
      XML_NODE stored_root = xml->GetLocalRoot();
      XML_NODE node = xml->NavigateToNode(path, 0);
      xml->SetLocalRoot(node);
  
      m_left_icon = CreateStaticOrig(*xml, "left_icon");
      m_right_icon = CreateStaticOrig(*xml, "right_icon");
      m_top_icon = CreateStaticOrig(*xml, "top_icon");
      m_timer = CreateStaticOrig(*xml, "timer");
  
      xml->SetLocalRoot(stored_root);
  }
  
  void CComplexMapSpot::SetTimerFinish(ALife::_TIME_ID time) // ms
  {
      if (time <= 0) {
          m_timer_finish = 0;
          m_infinity_time = true;
          m_timer->Show(false);
      } else {
          m_timer_finish = time;
          m_infinity_time = false;
          m_timer->Show(true);
      }
  }
  
  void CComplexMapSpot::Update() {
      inherited::Update();
  
      m_last_delay += Device.dwTimeDelta;
      if (m_last_delay > 310) {
          m_last_delay = 0;
          if (Level().GetGameTime() > m_timer_finish) {
              /*if ( !m_infinity_time )
              {
                      MapLocation()->DisableSpot();
              }*/
          } else {
              if (!m_infinity_time) {
                  ALife::_TIME_ID dt = m_timer_finish - Level().GetGameTime();
                  m_timer->TextItemControl()->SetText(
                      GetTimeAsString(dt, InventoryUtilities::etpTimeToMinutes, ':', false).c_str());
              }
          }
      }
  
      if (MapLocation()->SpotEnabled()) {
          m_timer->Show((m_timer->GetWndSize().x > 5.0f) && (Level().GetGameTime() < m_timer_finish));
      }
  }
  
  void CComplexMapSpot::SetWndSize(const Fvector2& size) {
      inherited::SetWndSize(size);
  
      if (m_originSize.x == 0.0f || m_originSize.y == 0.0f) {
          return;
      }
      float k = size.x / m_originSize.x;
  
      for (WINDOW_LIST_it it = m_ChildWndList.begin(); m_ChildWndList.end() != it; ++it) {
          CUIStaticOrig* static_orig = smart_cast<CUIStaticOrig*>(*it);
          if (static_orig) {
              static_orig->ScaleOrigin(k);
          }
      }
  
      if (m_timer) {
          float xp = 0.5f * (GetWndSize().x - m_timer->GetWndSize().x);
          m_timer->SetWndPos(Fvector2().set(xp, m_timer->GetWndPos().y));
      }
  }
  