From bcbee9337e96d8ff5675e64cca264be624721bdd Mon Sep 17 00:00:00 2001 From: werasik2aa Date: Sat, 13 Sep 2025 03:57:55 +0700 Subject: [PATCH 01/12] SOC V1 (no pda tasks, weapon hud and marks) --- src/xrCore/Crypto/trivial_encryptor.h | 2 +- src/xrCore/LocatorAPI.cpp | 2 +- src/xrGame/UIGameSP.cpp | 36 +++++++++++-------- src/xrGame/UIZoneMap.cpp | 17 ++++++--- src/xrGame/inventory_upgrade_manager.cpp | 4 +-- src/xrGame/ui/UIHudStatesWnd.cpp | 2 +- src/xrGame/ui/UIMainIngameWnd.cpp | 30 +++++++++------- src/xrGame/ui/UINewsItemWnd.cpp | 5 ++- src/xrGame/ui/UIPdaWnd.cpp | 26 ++++++++++---- src/xrGame/ui/UIPdaWnd.h | 1 + .../xrServer_Objects_ALife.cpp | 6 +++- src/xrUICore/XML/UIXmlInitBase.cpp | 2 +- 12 files changed, 86 insertions(+), 47 deletions(-) diff --git a/src/xrCore/Crypto/trivial_encryptor.h b/src/xrCore/Crypto/trivial_encryptor.h index cc4446e888b..47f9b00ad05 100644 --- a/src/xrCore/Crypto/trivial_encryptor.h +++ b/src/xrCore/Crypto/trivial_encryptor.h @@ -26,11 +26,11 @@ class XRCORE_API trivial_encryptor key m_key; public: + key_flag m_current_key = key_flag::russian; const key m_key_russian; const key m_key_worldwide; private: - key_flag m_current_key; type m_alphabet[alphabet_size]; type m_alphabet_back[alphabet_size]; diff --git a/src/xrCore/LocatorAPI.cpp b/src/xrCore/LocatorAPI.cpp index 2f7b1d09bf9..792b5735bf8 100644 --- a/src/xrCore/LocatorAPI.cpp +++ b/src/xrCore/LocatorAPI.cpp @@ -305,7 +305,7 @@ IReader* open_chunk(void* ptr, u32 ID, pcstr archiveName, size_t archiveSize, bo size_t dest_sz = 0; if (shouldDecrypt) // Try WW key first - g_trivial_encryptor.decode(src_data, dwSize, src_data); + g_trivial_encryptor.decode(src_data, dwSize, src_data, trivial_encryptor::key_flag::russian); bool result = _decompressLZ(&dest, &dest_sz, src_data, dwSize, archiveSize); diff --git a/src/xrGame/UIGameSP.cpp b/src/xrGame/UIGameSP.cpp index 1563a41e5cd..362b15b7aa6 100644 --- a/src/xrGame/UIGameSP.cpp +++ b/src/xrGame/UIGameSP.cpp @@ -158,26 +158,34 @@ bool CUIGameSP::IR_UIOnKeyboardPress(int dik) CGameTask* t1 = Level().GameTaskManager().ActiveTask(eTaskTypeStoryline); CGameTask* t2 = Level().GameTaskManager().ActiveTask(eTaskTypeAdditional); + // WERASIK2AA: SOC ISSUE + if (ShadowOfChernobylMode) + { + CGameTask* t = t1 ? t1 : t2; + if (t) + m_game_objective->m_static->SetTextST(*t->m_Description); + else + m_game_objective->m_static->SetTextST("st_no_active_task"); + break; + } + if (t1 && t2) { m_game_objective->m_static->SetTextST(t1->m_Title.c_str()); StaticDrawableWrapper* sm2 = AddCustomStatic("secondary_task", true); - sm2->m_static->SetTextST(t2->m_Title.c_str()); + sm2->m_static->SetTextST(*t2->m_Title); + break; } - else - { - if (t1 || t2) - { - CGameTask* t = (t1) ? t1 : t2; - m_game_objective->m_static->SetTextST(t->m_Title.c_str()); - StaticDrawableWrapper* sm2 = AddCustomStatic("secondary_task", true); - sm2->m_static->TextItemControl()->SetTextST(t->m_Description.c_str()); - } - else - { - m_game_objective->m_static->TextItemControl()->SetTextST("st_no_active_task"); - } + + // WERASIK2AA: T1? + CGameTask* t = t1 ? t1 : t2; + if (t) { + m_game_objective->m_static->SetTextST(t->m_Title.c_str()); + StaticDrawableWrapper* sm2 = AddCustomStatic("secondary_task", true); + sm2->m_static->TextItemControl()->SetTextST(*t->m_Description); } + else + m_game_objective->m_static->TextItemControl()->SetTextST("st_no_active_task"); } break; } diff --git a/src/xrGame/UIZoneMap.cpp b/src/xrGame/UIZoneMap.cpp index 71f643d0b69..98774f7833c 100644 --- a/src/xrGame/UIZoneMap.cpp +++ b/src/xrGame/UIZoneMap.cpp @@ -93,10 +93,19 @@ void CUIZoneMap::Init(bool motionIconAttached) if (IsGameTypeSingle()) { - CUIXmlInit::InitStatic(uiXml, "minimap:static_counter", 0, &m_Counter); - m_background.AttachChild(&m_Counter); - CUIXmlInit::InitStatic(uiXml, "minimap:static_counter:text_static", 0, &m_Counter_text); - m_Counter.AttachChild(&m_Counter_text); + if (ShadowOfChernobylMode) + { + CUIXmlInit::InitStatic(uiXml, "minimap:background", 0, &m_Counter); + m_background.AttachChild(&m_Counter); + CUIXmlInit::InitStatic(uiXml, "minimap:background:dist_text", 0, &m_Counter_text); + m_Counter.AttachChild(&m_Counter_text); + } + else { + CUIXmlInit::InitStatic(uiXml, "minimap:static_counter", 0, &m_Counter); + m_background.AttachChild(&m_Counter); + CUIXmlInit::InitStatic(uiXml, "minimap:static_counter:text_static", 0, &m_Counter_text); + m_Counter.AttachChild(&m_Counter_text); + } if (motionIconAttached) { diff --git a/src/xrGame/inventory_upgrade_manager.cpp b/src/xrGame/inventory_upgrade_manager.cpp index 2015076f530..2d93230bd62 100644 --- a/src/xrGame/inventory_upgrade_manager.cpp +++ b/src/xrGame/inventory_upgrade_manager.cpp @@ -183,9 +183,7 @@ void Manager::load_all_properties() if (!pSettings->section_exist(properties_section) && ShadowOfChernobylMode) return; - - VERIFY2( - pSettings->section_exist(properties_section), make_string("Section [%s] does not exist !", properties_section)); + VERIFY2(pSettings->section_exist(properties_section), make_string("Section [%s] does not exist !", properties_section)); VERIFY2(pSettings->line_count(properties_section), make_string("Section [%s] is empty !", properties_section)); CInifile::Sect& inv_section = pSettings->r_section(properties_section); diff --git a/src/xrGame/ui/UIHudStatesWnd.cpp b/src/xrGame/ui/UIHudStatesWnd.cpp index 9cfcb6307e1..404f38a5f94 100644 --- a/src/xrGame/ui/UIHudStatesWnd.cpp +++ b/src/xrGame/ui/UIHudStatesWnd.cpp @@ -854,7 +854,7 @@ float CUIHudStatesWnd::get_zone_cur_power(ALife::EHitType hit_type) void CUIHudStatesWnd::DrawZoneIndicators() { CActor* actor = smart_cast(Level().CurrentViewEntity()); - if (!actor) + if (!actor || ShadowOfChernobylMode) return; UpdateIndicators(actor); diff --git a/src/xrGame/ui/UIMainIngameWnd.cpp b/src/xrGame/ui/UIMainIngameWnd.cpp index eadd88bdae2..dddb108a09f 100644 --- a/src/xrGame/ui/UIMainIngameWnd.cpp +++ b/src/xrGame/ui/UIMainIngameWnd.cpp @@ -76,7 +76,7 @@ void CUIMainIngameWnd::Init() CUIXml uiXml; uiXml.Load(CONFIG_PATH, UI_PATH, UI_PATH_DEFAULT, MAININGAME_XML); - CUIXmlInit::InitWindow(uiXml, "main", 0, this); + CUIXmlInit::InitWindow(uiXml, "main", 0, this, !ShadowOfChernobylMode); Enable(false); @@ -220,7 +220,7 @@ void CUIMainIngameWnd::Init() AttachChild(UIMotionIcon); } - UIStaticDiskIO = UIHelper::CreateStatic(uiXml, "disk_io", this); + UIStaticDiskIO = UIHelper::CreateStatic(uiXml, "disk_io", this, !ShadowOfChernobylMode); if (IsGameTypeSingle() && uiXml.NavigateToNode("artefact_panel", 0)) { @@ -229,10 +229,12 @@ void CUIMainIngameWnd::Init() this->AttachChild(UIArtefactPanel); } - m_ui_hud_states = xr_new(); - m_ui_hud_states->SetAutoDelete(true); - AttachChild(m_ui_hud_states); - m_ui_hud_states->InitFromXml(uiXml, "hud_states"); + if (!ShadowOfChernobylMode) { + m_ui_hud_states = xr_new(); + m_ui_hud_states->SetAutoDelete(true); + AttachChild(m_ui_hud_states); + m_ui_hud_states->InitFromXml(uiXml, "hud_states"); + } int i = 0; while (true) @@ -270,13 +272,15 @@ void CUIMainIngameWnd::Draw() if (IOActive) UIStaticDiskIO_start_time = Device.fTimeGlobal; - if ((UIStaticDiskIO_start_time + 1.0f) < Device.fTimeGlobal) - UIStaticDiskIO->Show(false); - else - { - u32 alpha = clampr(iFloor(255.f * (1.f - (Device.fTimeGlobal - UIStaticDiskIO_start_time) / 1.f)), 0, 255); - UIStaticDiskIO->Show(true); - UIStaticDiskIO->SetTextureColor(color_rgba(255, 255, 255, alpha)); + if (UIStaticDiskIO) { + if ((UIStaticDiskIO_start_time + 1.0f) < Device.fTimeGlobal) + UIStaticDiskIO->Show(false); + else + { + u32 alpha = clampr(iFloor(255.f * (1.f - (Device.fTimeGlobal - UIStaticDiskIO_start_time) / 1.f)), 0, 255); + UIStaticDiskIO->Show(true); + UIStaticDiskIO->SetTextureColor(color_rgba(255, 255, 255, alpha)); + } } FS.dwOpenCounter = 0; diff --git a/src/xrGame/ui/UINewsItemWnd.cpp b/src/xrGame/ui/UINewsItemWnd.cpp index 18406af4f45..98dd75a6503 100644 --- a/src/xrGame/ui/UINewsItemWnd.cpp +++ b/src/xrGame/ui/UINewsItemWnd.cpp @@ -18,7 +18,10 @@ void CUINewsItemWnd::Init(CUIXml& uiXml, LPCSTR start_from) uiXml.SetLocalRoot(node); m_UIImage = UIHelper::CreateStatic(uiXml, "image", this); - m_UICaption = UIHelper::CreateStatic(uiXml, "caption_static", this, false); // no caption tag in SOC + if (ShadowOfChernobylMode) + m_UICaption = UIHelper::CreateStatic(uiXml, "caption_static", this, false); // no caption tag in SOC + else + m_UICaption = UIHelper::CreateStatic(uiXml, "updated_section_static", this, false); // no caption tag in SOC m_UIText = UIHelper::CreateStatic(uiXml, "text_static", this, false); m_UIDate = UIHelper::CreateStatic(uiXml, "date_static", this, false); diff --git a/src/xrGame/ui/UIPdaWnd.cpp b/src/xrGame/ui/UIPdaWnd.cpp index 1f17e502dfd..78bb785ab35 100644 --- a/src/xrGame/ui/UIPdaWnd.cpp +++ b/src/xrGame/ui/UIPdaWnd.cpp @@ -78,9 +78,14 @@ void CUIPdaWnd::Init() CUIXmlInit::InitWindow(uiXml, "main", 0, this); - UIMainPdaFrame = UIHelper::CreateStatic(uiXml, "background_static", this); - m_caption = UIHelper::CreateStatic(uiXml, "caption_static", this); - m_caption_const = (m_caption->GetText()); + UIMainPdaFrame = UIHelper::CreateStatic(uiXml, "background_static", this, false); + + if (ShadowOfChernobylMode) + m_caption = UIHelper::CreateStatic(uiXml, "timer_frame_line:title", this); // no caption tag in SOC + else + m_caption = UIHelper::CreateStatic(uiXml, "caption_static", this); // no caption tag in SOC + + m_caption_const = m_caption ? m_caption->GetText() : ""; m_clock = UIHelper::CreateStatic(uiXml, "clock_wnd", this, false); if (uiXml.NavigateToNode("anim_static")) // XXX: Replace with UIHelper @@ -91,11 +96,17 @@ void CUIPdaWnd::Init() CUIXmlInit::InitAnimatedStatic(uiXml, "anim_static", 0, anim_static); } - m_btn_close = UIHelper::Create3tButton(uiXml, "close_button", this); + if (ShadowOfChernobylMode) + m_btn_close = UIHelper::Create3tButton(uiXml, "off_button", this); + else + m_btn_close = UIHelper::Create3tButton(uiXml, "close_button", this); + m_btn_close->SetAccelerator(kUI_BACK, false, 2); UI().Focus().UnregisterFocusable(m_btn_close); - m_hint_wnd = UIHelper::CreateHint(uiXml, "hint_wnd"); + + if (!ShadowOfChernobylMode) + m_hint_wnd = UIHelper::CreateHint(uiXml, "hint_wnd", false); if (IsGameTypeSingle()) { @@ -368,8 +379,9 @@ void CUIPdaWnd::DrawHint() pUIMapWnd->DrawHint(); else if (m_pActiveDialog == pUIRankingWnd && pUIRankingWnd) pUIRankingWnd->DrawHint(); - - m_hint_wnd->Draw(); + + if (m_hint_wnd) + m_hint_wnd->Draw(); } bool CUIPdaWnd::NeedCursor() const diff --git a/src/xrGame/ui/UIPdaWnd.h b/src/xrGame/ui/UIPdaWnd.h index 4949d38dc3f..3394dff1fcc 100644 --- a/src/xrGame/ui/UIPdaWnd.h +++ b/src/xrGame/ui/UIPdaWnd.h @@ -79,6 +79,7 @@ class CUIPdaWnd final : public CUIDialogWnd void Show_SecondTaskWnd(bool status); void Show_MapWnd(bool status); void Show_ContactsWnd(bool status); + void DrawUpdatedSections(); void SetActiveDialog(CUIWindow* wnd) { m_pActiveDialog = wnd; } CUIWindow* GetActiveDialog() const { return m_pActiveDialog; } diff --git a/src/xrServerEntities/xrServer_Objects_ALife.cpp b/src/xrServerEntities/xrServer_Objects_ALife.cpp index 28dbe007bc4..272d0690a61 100644 --- a/src/xrServerEntities/xrServer_Objects_ALife.cpp +++ b/src/xrServerEntities/xrServer_Objects_ALife.cpp @@ -172,8 +172,12 @@ void SFillPropData::load() std::sort(character_profiles.begin(), character_profiles.end(), SortStringsByAlphabetPred); #endif // AI_COMPILER - luabind::object table; + if (ShadowOfChernobylMode) { + Msg("![ERROR] SHADOW OF CHERNOBYL DOESN'T HAVE this smart_covers.descriptions!!!"); + return; + } + luabind::object table; R_ASSERT(GEnv.ScriptEngine->function_object("smart_covers.descriptions", table, LUA_TTABLE)); for (luabind::iterator I(table), E; I != E; ++I) diff --git a/src/xrUICore/XML/UIXmlInitBase.cpp b/src/xrUICore/XML/UIXmlInitBase.cpp index 627ab7f1fe0..1190ea87c1e 100644 --- a/src/xrUICore/XML/UIXmlInitBase.cpp +++ b/src/xrUICore/XML/UIXmlInitBase.cpp @@ -758,7 +758,7 @@ bool CUIXmlInitBase::InitTabControl(CUIXml& xml_doc, pcstr path, newButton->m_btn_id = xml_doc.ReadAttrib("button", i, "id"); if (!newButton->m_btn_id.size()) { - R_ASSERT4(defaultIdsAllowed, "Tab control tab doesn't have 'id' assigned.", xml_doc.m_xml_file_name, path); + R_ASSERT4(ShadowOfChernobylMode || defaultIdsAllowed, "Tab control tab doesn't have 'id' assigned.", xml_doc.m_xml_file_name, path); Msg("~ [%s] doesn't have `id` tag in file [%s]", xml_doc.m_xml_file_name, path); string32 temp; xr_sprintf(temp, "%d", i); From 9ad27e45425f638fc60202f4d4778731bbb36722 Mon Sep 17 00:00:00 2001 From: werasik2aa Date: Sat, 13 Sep 2025 04:21:19 +0700 Subject: [PATCH 02/12] FixIndiciator V1 --- src/xrGame/ui/UIHudStatesWnd.cpp | 53 +++++++++++++++++++++---------- src/xrGame/ui/UIMainIngameWnd.cpp | 11 ++++--- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/xrGame/ui/UIHudStatesWnd.cpp b/src/xrGame/ui/UIHudStatesWnd.cpp index 404f38a5f94..79a1e420217 100644 --- a/src/xrGame/ui/UIHudStatesWnd.cpp +++ b/src/xrGame/ui/UIHudStatesWnd.cpp @@ -77,14 +77,15 @@ ALife::EInfluenceType CUIHudStatesWnd::get_indik_type(ALife::EHitType hit_type) void CUIHudStatesWnd::InitFromXml(CUIXml& xml, LPCSTR path) { ZoneScoped; - - CUIXmlInit::InitWindow(xml, path, 0, this); XML_NODE stored_root = xml.GetLocalRoot(); + if (path) { + CUIXmlInit::InitWindow(xml, path, 0, this); - XML_NODE new_root = xml.NavigateToNode(path, 0); - xml.SetLocalRoot(new_root); + XML_NODE new_root = xml.NavigateToNode(path, 0); + xml.SetLocalRoot(new_root); + } - m_back = UIHelper::CreateStatic(xml, "back", this); + m_back = UIHelper::CreateStatic(xml, "back", this, !ShadowOfChernobylMode); m_back_v = UIHelper::CreateStatic(xml, "back_v", this, false); // XXX: replace with UIHelper @@ -136,22 +137,39 @@ void CUIHudStatesWnd::InitFromXml(CUIXml& xml, LPCSTR path) m_resist_back[ALife::infl_psi] = UIHelper::CreateStatic(xml, "resist_back_psi", this, false); // electra = no has CStatic!! - m_indik[ALife::infl_rad] = UIHelper::CreateStatic(xml, "indik_rad", this); - m_indik[ALife::infl_fire] = UIHelper::CreateStatic(xml, "indik_fire", this); - m_indik[ALife::infl_acid] = UIHelper::CreateStatic(xml, "indik_acid", this); - m_indik[ALife::infl_psi] = UIHelper::CreateStatic(xml, "indik_psi", this); + if (ShadowOfChernobylMode) { + m_indik[ALife::infl_rad] = UIHelper::CreateStatic(xml, "radiation_static", this); + m_indik[ALife::infl_fire] = UIHelper::CreateStatic(xml, "wound_static", this); + m_indik[ALife::infl_acid] = UIHelper::CreateStatic(xml, "starvation_static", this); + m_indik[ALife::infl_psi] = UIHelper::CreateStatic(xml, "psy_health_static", this); + } else { + m_indik[ALife::infl_rad] = UIHelper::CreateStatic(xml, "indik_rad", this); + m_indik[ALife::infl_fire] = UIHelper::CreateStatic(xml, "indik_fire", this); + m_indik[ALife::infl_acid] = UIHelper::CreateStatic(xml, "indik_acid", this); + m_indik[ALife::infl_psi] = UIHelper::CreateStatic(xml, "indik_psi", this); + } m_lanim_name = xml.ReadAttrib("indik_rad", 0, "light_anim", ""); m_ui_weapon_sign_ammo = UIHelper::CreateStatic(xml, "static_ammo", weaponsParent, false); //m_ui_weapon_sign_ammo->SetEllipsis( CUIStatic::eepEnd, 2 ); - m_ui_weapon_cur_ammo = UIHelper::CreateStatic(xml, "static_cur_ammo", this, false); - m_ui_weapon_fmj_ammo = UIHelper::CreateStatic(xml, "static_fmj_ammo", this, false); - m_ui_weapon_ap_ammo = UIHelper::CreateStatic(xml, "static_ap_ammo", this, false); - m_ui_weapon_third_ammo = UIHelper::CreateStatic(xml, "static_third_ammo", this, false); //Alundaio: Option to display a third ammo type - m_fire_mode = UIHelper::CreateStatic(xml, "static_fire_mode", this); - m_ui_grenade = UIHelper::CreateStatic(xml, "static_grenade", this, false); + if (ShadowOfChernobylMode) + { + m_ui_weapon_cur_ammo = UIHelper::CreateStatic(xml, "static_ammo", this, false); + m_ui_weapon_fmj_ammo = UIHelper::CreateStatic(xml, "static_ammo", this, false); + m_ui_weapon_ap_ammo = UIHelper::CreateStatic(xml, "static_ammo", this, false); + m_ui_weapon_third_ammo = UIHelper::CreateStatic(xml, "static_ammo", this, false); + m_fire_mode = UIHelper::CreateStatic(xml, "static_weapon", this); + m_ui_grenade = UIHelper::CreateStatic(xml, "static_weapon", this, false); + } else { + m_ui_weapon_cur_ammo = UIHelper::CreateStatic(xml, "static_cur_ammo", this, false); + m_ui_weapon_fmj_ammo = UIHelper::CreateStatic(xml, "static_fmj_ammo", this, false); + m_ui_weapon_ap_ammo = UIHelper::CreateStatic(xml, "static_ap_ammo", this, false); + m_ui_weapon_third_ammo = UIHelper::CreateStatic(xml, "static_third_ammo", this, false); //Alundaio: Option to display a third ammo type + m_fire_mode = UIHelper::CreateStatic(xml, "static_fire_mode", this); + m_ui_grenade = UIHelper::CreateStatic(xml, "static_grenade", this, false); + } m_ui_weapon_icon = UIHelper::CreateStatic(xml, "static_wpn_icon", weaponsParent); m_ui_weapon_icon->SetShader(InventoryUtilities::GetEquipmentIconsShader()); @@ -854,10 +872,11 @@ float CUIHudStatesWnd::get_zone_cur_power(ALife::EHitType hit_type) void CUIHudStatesWnd::DrawZoneIndicators() { CActor* actor = smart_cast(Level().CurrentViewEntity()); - if (!actor || ShadowOfChernobylMode) + if (!actor) return; - UpdateIndicators(actor); + if (!ShadowOfChernobylMode) + UpdateIndicators(actor); if (m_indik[ALife::infl_rad]->IsShown()) m_indik[ALife::infl_rad]->Draw(); diff --git a/src/xrGame/ui/UIMainIngameWnd.cpp b/src/xrGame/ui/UIMainIngameWnd.cpp index dddb108a09f..579269b73e6 100644 --- a/src/xrGame/ui/UIMainIngameWnd.cpp +++ b/src/xrGame/ui/UIMainIngameWnd.cpp @@ -229,12 +229,13 @@ void CUIMainIngameWnd::Init() this->AttachChild(UIArtefactPanel); } - if (!ShadowOfChernobylMode) { - m_ui_hud_states = xr_new(); - m_ui_hud_states->SetAutoDelete(true); - AttachChild(m_ui_hud_states); + m_ui_hud_states = xr_new(); + m_ui_hud_states->SetAutoDelete(true); + AttachChild(m_ui_hud_states); + if (ShadowOfChernobylMode) + m_ui_hud_states->InitFromXml(uiXml, NULL); + else m_ui_hud_states->InitFromXml(uiXml, "hud_states"); - } int i = 0; while (true) From c8c159614ff5c4adc73ec312c41f612fc123f868 Mon Sep 17 00:00:00 2001 From: werasik2aa Date: Sat, 13 Sep 2025 05:18:09 +0700 Subject: [PATCH 03/12] MISSING->SAME DOG ANIMS --- src/xrGame/UIZoneMap.cpp | 2 -- src/xrGame/ai/monsters/dog/dog.cpp | 18 +++++++++--------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/xrGame/UIZoneMap.cpp b/src/xrGame/UIZoneMap.cpp index 98774f7833c..74544517c96 100644 --- a/src/xrGame/UIZoneMap.cpp +++ b/src/xrGame/UIZoneMap.cpp @@ -95,8 +95,6 @@ void CUIZoneMap::Init(bool motionIconAttached) { if (ShadowOfChernobylMode) { - CUIXmlInit::InitStatic(uiXml, "minimap:background", 0, &m_Counter); - m_background.AttachChild(&m_Counter); CUIXmlInit::InitStatic(uiXml, "minimap:background:dist_text", 0, &m_Counter_text); m_Counter.AttachChild(&m_Counter_text); } diff --git a/src/xrGame/ai/monsters/dog/dog.cpp b/src/xrGame/ai/monsters/dog/dog.cpp index f69d70fc5a0..794ac997943 100644 --- a/src/xrGame/ai/monsters/dog/dog.cpp +++ b/src/xrGame/ai/monsters/dog/dog.cpp @@ -303,27 +303,27 @@ LPCSTR CAI_Dog::get_current_animation() switch (current_anim) { case 1: - return "stand_idle_smelling_up_0"; //Нюхает вверх + return ShadowOfChernobylMode ? "sit_stand_up_0" : "stand_idle_smelling_up_0"; //Нюхает вверх case 2: - return "stand_idle_smelling_down_0"; //Нюхает вниз + return ShadowOfChernobylMode ? "stand_check_corpse_0" : "stand_idle_smelling_down_0"; //Нюхает вниз case 3: - return "stand_idle_smelling_look_around_0"; //Нюхает по кругу + return ShadowOfChernobylMode ? "stand_check_corpse_0" : "stand_idle_smelling_look_around_0"; //Нюхает по кругу case 4: - return "stand_idle_dig_ground_0"; //Обнюховает и роет землю + return ShadowOfChernobylMode ? "stand_check_corpse_0" : "stand_idle_dig_ground_0"; //Обнюховает и роет землю case 5: - return "stand_idle_howl_0"; //Воет + return ShadowOfChernobylMode ? "sit_stand_up_0" : "stand_idle_howl_0"; //Воет case 6: - return "stand_growl_idle_0"; //Рычит стоя + return ShadowOfChernobylMode ? "stand_scared_0" : "stand_growl_idle_0"; //Рычит стоя case 7: - return "stand_idle_shake_0"; //Отряхивается !!!!! + return ShadowOfChernobylMode ? "stand_drag_1" : "stand_idle_shake_0"; //Отряхивается !!!!! case 8: return "stand_sit_down_0"; //Садиться case 9: return "sit_idle_0"; // Cидит case 10: - return "sit_idle_1"; //Чухается сидя + return ShadowOfChernobylMode ? "stand_idle_0" : "sit_idle_1"; //Чухается сидя case 11: - return "sit_idle_2"; //Оглядывается сидя + return ShadowOfChernobylMode ? "sit_idle_0" : "sit_idle_2"; //Оглядывается сидя case 12: return "sit_stand_up_0"; //Встает case 13: From 520d12f691e777586fd4f3a778ca0bc29be3a206 Mon Sep 17 00:00:00 2001 From: werasik2aa Date: Sat, 13 Sep 2025 05:48:09 +0700 Subject: [PATCH 04/12] DamageOUTFIT --- src/xrGame/EntityCondition.cpp | 9 +++++++-- src/xrGame/UIZoneMap.cpp | 2 +- src/xrServerEntities/inventory_space.h | 17 +++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/xrGame/EntityCondition.cpp b/src/xrGame/EntityCondition.cpp index 9e818f01fa7..52c28611d65 100644 --- a/src/xrGame/EntityCondition.cpp +++ b/src/xrGame/EntityCondition.cpp @@ -300,7 +300,12 @@ float CEntityCondition::HitOutfitEffect( if (!pInvOwner) return hit_power; - CCustomOutfit* pOutfit = (CCustomOutfit*)pInvOwner->inventory().ItemFromSlot(OUTFIT_SLOT); + CCustomOutfit* pOutfit; + if (ShadowOfChernobylMode) + pOutfit = (CCustomOutfit*)pInvOwner->inventory().ItemFromSlot(OUTFIT_SLOT_SOC); + else + pOutfit = (CCustomOutfit*)pInvOwner->inventory().ItemFromSlot(OUTFIT_SLOT); + CHelmet* pHelmet = (CHelmet*)pInvOwner->inventory().ItemFromSlot(HELMET_SLOT); if (!pOutfit && !pHelmet) return hit_power; @@ -376,7 +381,7 @@ CWound* CEntityCondition::ConditionHit(SHit* pHDS) bool bAddWound = pHDS->add_wound; - float hit_power_org = pHDS->damage(); + float hit_power_org = pHDS->power; float hit_power = hit_power_org; hit_power = HitOutfitEffect(hit_power_org, pHDS->hit_type, pHDS->boneID, pHDS->armor_piercing, bAddWound); diff --git a/src/xrGame/UIZoneMap.cpp b/src/xrGame/UIZoneMap.cpp index 74544517c96..e88a115d2f3 100644 --- a/src/xrGame/UIZoneMap.cpp +++ b/src/xrGame/UIZoneMap.cpp @@ -96,7 +96,7 @@ void CUIZoneMap::Init(bool motionIconAttached) if (ShadowOfChernobylMode) { CUIXmlInit::InitStatic(uiXml, "minimap:background:dist_text", 0, &m_Counter_text); - m_Counter.AttachChild(&m_Counter_text); + m_background.AttachChild(&m_Counter_text); } else { CUIXmlInit::InitStatic(uiXml, "minimap:static_counter", 0, &m_Counter); diff --git a/src/xrServerEntities/inventory_space.h b/src/xrServerEntities/inventory_space.h index 68a7a730c1f..8275b62cbe8 100644 --- a/src/xrServerEntities/inventory_space.h +++ b/src/xrServerEntities/inventory_space.h @@ -24,6 +24,23 @@ enum SLOTS_COUNT }; +enum +{ + KNIFE_SLOT_SOC, + PISTOL_SLOT_SOC, + RIFLE_SLOT_SOC, + GRENADE_SLOT_SOC, + APPARATUS_SLOT_SOC, + BOLT_SLOT_SOC, + OUTFIT_SLOT_SOC, + PDA_SLOT_SOC, + DETECTOR_SLOT_SOC, + TORCH_SLOT_SOC, + ARTEFACT_SLOT_SOC, + SLOTS_TOTAL_SOC, + NO_ACTIVE_SLOT_SOC = 0xffffffff +} + #define RUCK_HEIGHT 280 #define RUCK_WIDTH 7 From 4f9890c423910224cf897d23afd738ccea1c2ae4 Mon Sep 17 00:00:00 2001 From: werasik2aa Date: Sun, 14 Sep 2025 03:59:43 +0700 Subject: [PATCH 05/12] SOCPDA PREVIEW --- src/.clang-format | 168 ------ src/xrGame/EntityCondition.cpp | 9 +- src/xrGame/ui/UIEncyclopediaArticleWnd.cpp | 76 +++ src/xrGame/ui/UIEncyclopediaArticleWnd.h | 24 + src/xrGame/ui/UIEncyclopediaWnd.cpp | 269 ++++++++++ src/xrGame/ui/UIEncyclopediaWnd.h | 69 +++ src/xrGame/ui/UIEventsWnd.cpp | 318 ++++++++++++ src/xrGame/ui/UIEventsWnd.h | 63 +++ src/xrGame/ui/UIGameTutorialSimpleItem.cpp | 2 +- src/xrGame/ui/UIMapWnd.cpp | 2 +- src/xrGame/ui/UIPdaWnd.cpp | 98 ++-- src/xrGame/ui/UIPdaWnd.h | 5 + src/xrGame/ui/UITaskDescrWnd.cpp | 79 +++ src/xrGame/ui/UITaskDescrWnd.h | 26 + src/xrGame/ui/UITaskWnd.cpp | 277 +++++++++- src/xrGame/ui/UITaskWnd.h | 60 ++- src/xrGame/xrGame.vcxproj | 8 + src/xrGame/xrGame.vcxproj.filters | 30 ++ src/xrServerEntities/inventory_space.h | 17 - src/xrUICore/ScrollView/UITreeViewItem.cpp | 574 +++++++++++++++++++++ src/xrUICore/ScrollView/UITreeViewItem.h | 129 +++++ src/xrUICore/Windows/UIFrameLineWnd.h | 4 +- src/xrUICore/xrUICore.vcxproj | 2 + src/xrUICore/xrUICore.vcxproj.filters | 6 + 24 files changed, 2078 insertions(+), 237 deletions(-) delete mode 100644 src/.clang-format create mode 100644 src/xrGame/ui/UIEncyclopediaArticleWnd.cpp create mode 100644 src/xrGame/ui/UIEncyclopediaArticleWnd.h create mode 100644 src/xrGame/ui/UIEncyclopediaWnd.cpp create mode 100644 src/xrGame/ui/UIEncyclopediaWnd.h create mode 100644 src/xrGame/ui/UIEventsWnd.cpp create mode 100644 src/xrGame/ui/UIEventsWnd.h create mode 100644 src/xrGame/ui/UITaskDescrWnd.cpp create mode 100644 src/xrGame/ui/UITaskDescrWnd.h create mode 100644 src/xrUICore/ScrollView/UITreeViewItem.cpp create mode 100644 src/xrUICore/ScrollView/UITreeViewItem.h diff --git a/src/.clang-format b/src/.clang-format deleted file mode 100644 index b07e62caebd..00000000000 --- a/src/.clang-format +++ /dev/null @@ -1,168 +0,0 @@ -# Configured for clang-format 21 ---- -Language: Cpp -Standard: c++17 -IndentWidth: 4 -TabWidth: 4 -UseTab: Never -AccessModifierOffset: -4 -AlignAfterOpenBracket: DontAlign -AlignArrayOfStructures: Right -AlignConsecutiveAssignments: None -AlignConsecutiveBitFields: AcrossComments -AlignConsecutiveDeclarations: None -AlignConsecutiveMacros: None -AlignConsecutiveShortCaseStatements: AcrossComments -AlignEscapedNewlines: LeftWithLastLine -AlignOperands: DontAlign -AlignTrailingComments: - Kind: Always -AllowAllArgumentsOnNextLine: false -AllowAllParametersOfDeclarationOnNextLine: false -AllowBreakBeforeNoexceptSpecifier: Never -AllowShortBlocksOnASingleLine: Empty -AllowShortCaseLabelsOnASingleLine: true -AllowShortCompoundRequirementOnASingleLine: true -AllowShortEnumsOnASingleLine: false -AllowShortFunctionsOnASingleLine: Empty -AllowShortIfStatementsOnASingleLine: Never -AllowShortLambdasOnASingleLine: Empty -AllowShortLoopsOnASingleLine: false -AllowShortNamespacesOnASingleLine: false -AlwaysBreakBeforeMultilineStrings: false -BinPackArguments: true -BinPackParameters: true -BitFieldColonSpacing: Both -BraceWrapping: - AfterCaseLabel: true - AfterClass: true - AfterControlStatement: Always - AfterEnum: true - AfterFunction: true - AfterNamespace: true - AfterStruct: true - AfterUnion: true - AfterExternBlock: true - BeforeCatch: true - BeforeElse: true - BeforeLambdaBody: true - BeforeWhile: false - IndentBraces: false - SplitEmptyFunction: false - SplitEmptyRecord: false - SplitEmptyNamespace: true -BreakAfterAttributes: Leave -BreakAfterReturnType: Automatic -BreakBeforeBinaryOperators: None -BreakBeforeBraces: Custom -BreakBeforeConceptDeclarations: Always -BreakBeforeTemplateCloser: true -BreakBeforeTernaryOperators: false -BreakBinaryOperations: RespectPrecedence -BreakConstructorInitializers: BeforeColon -BreakFunctionDefinitionParameters: false -BreakInheritanceList: AfterComma -BreakStringLiterals: true -BreakTemplateDeclarations: Yes -ColumnLimit: 160 # for a monitor with a resolution width of 1920 pixels -CommentPragmas: '^ (IWYU pragma:|NOLINT)' -CompactNamespaces: false -#ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: false -EmptyLineAfterAccessModifier: Never -EmptyLineBeforeAccessModifier: LogicalBlock -EnumTrailingComma: Leave -FixNamespaceComments: true -#IncludeBlocks: Regroup -IncludeCategories: - - Regex: '(stdafx.h|pch.hpp|pch.h|precompiled.h)' - Priority: -1 - - Regex: '^<' - Priority: 1 - - Regex: '^"' - Priority: 2 -IndentAccessModifiers: false -IndentCaseBlocks: false -IndentCaseLabels: false -IndentExportBlock: false -IndentExternBlock: NoIndent -IndentGotoLabels: false -IndentPPDirectives: AfterHash -IndentRequiresClause: false -IndentWrappedFunctionNames: false -InsertBraces: false -InsertNewlineAtEOF: true -InsertTrailingCommas: false -KeepEmptyLines: - AtEndOfFile: false - AtStartOfBlock: false - AtStartOfFile: false -LambdaBodyIndentation: Signature -# MacroBlockBegin: '' -# MacroBlockEnd: '' -# Macros: -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -PackConstructorInitializers: BinPack -PenaltyBreakAssignment: 0 -PenaltyBreakBeforeFirstCallParameter: 100 -PenaltyBreakBeforeMemberAccess: 0 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakOpenParenthesis: 300 -PenaltyBreakScopeResolution: 25 -PenaltyBreakString: 1000 -PenaltyExcessCharacter: 10 -PenaltyReturnTypeOnItsOwnLine: 1000000 -PointerAlignment: Left -QualifierOrder: [friend, volatile, inline, static, constexpr, const, restrict, type] -ReferenceAlignment: Pointer -ReflowComments: IndentOnly -RemoveEmptyLinesInUnwrappedLines: true -# RemoveSemicolon: true -RequiresClausePosition: WithPreceding -RequiresExpressionIndentation: OuterScope -SeparateDefinitionBlocks: Always -ShortNamespaceLines: 5 -# SortIncludes: true -SortUsingDeclarations: Lexicographic -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false -SpaceAfterOperatorKeyword: false -SpaceAfterTemplateKeyword: true -SpaceAroundPointerQualifiers: Default -SpaceBeforeAssignmentOperators: true -SpaceBeforeCaseColon: false -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true -SpaceBeforeParens: Custom -SpaceBeforeParensOptions: - AfterControlStatements: true - AfterForeachMacros: false - AfterFunctionDeclarationName: false - AfterFunctionDefinitionName: false - AfterIfMacros: false - AfterOverloadedOperator: false - AfterPlacementOperator: true - AfterRequiresInClause: true - AfterRequiresInExpression: true - BeforeNonEmptyParentheses: false -SpaceBeforeRangeBasedForLoopColon: true -SpaceBeforeSquareBrackets: false -SpaceInEmptyBlock: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: Never -SpacesInContainerLiterals: false -SpacesInLineCommentPrefix: - Minimum: 1 - Maximum: -1 -SpacesInParens: Never -SpacesInSquareBrackets: false -# StatementAttributeLikeMacros: -# StatementMacros: -# WhitespaceSensitiveMacros: -WrapNamespaceBodyWithEmptyLines: Never -... diff --git a/src/xrGame/EntityCondition.cpp b/src/xrGame/EntityCondition.cpp index 52c28611d65..bfa15035c24 100644 --- a/src/xrGame/EntityCondition.cpp +++ b/src/xrGame/EntityCondition.cpp @@ -300,19 +300,14 @@ float CEntityCondition::HitOutfitEffect( if (!pInvOwner) return hit_power; - CCustomOutfit* pOutfit; - if (ShadowOfChernobylMode) - pOutfit = (CCustomOutfit*)pInvOwner->inventory().ItemFromSlot(OUTFIT_SLOT_SOC); - else - pOutfit = (CCustomOutfit*)pInvOwner->inventory().ItemFromSlot(OUTFIT_SLOT); - + CCustomOutfit* pOutfit = pInvOwner->GetOutfit(); CHelmet* pHelmet = (CHelmet*)pInvOwner->inventory().ItemFromSlot(HELMET_SLOT); if (!pOutfit && !pHelmet) return hit_power; float new_hit_power = hit_power; if (pOutfit) - new_hit_power = pOutfit->HitThroughArmor(hit_power, element, ap, add_wound, hit_type); + new_hit_power =pOutfit->HitThroughArmor(hit_power, element, ap, add_wound, hit_type); if (pHelmet) new_hit_power = pHelmet->HitThroughArmor(new_hit_power, element, ap, add_wound, hit_type); diff --git a/src/xrGame/ui/UIEncyclopediaArticleWnd.cpp b/src/xrGame/ui/UIEncyclopediaArticleWnd.cpp new file mode 100644 index 00000000000..c2216721208 --- /dev/null +++ b/src/xrGame/ui/UIEncyclopediaArticleWnd.cpp @@ -0,0 +1,76 @@ +#include "stdafx.h" +#include "UIEncyclopediaArticleWnd.h" +#include "xrUICore/Static/UIStatic.h" +#include "../encyclopedia_article.h" +#include "UIXmlInit.h" + +CUIEncyclopediaArticleWnd::CUIEncyclopediaArticleWnd() : + CUIWindow("CUIEncyclopediaArticleWnd"), + m_UIImage(NULL), + m_UIText(NULL), + m_Article(NULL) +{ +} + +CUIEncyclopediaArticleWnd::~CUIEncyclopediaArticleWnd() +{ +} + +bool CUIEncyclopediaArticleWnd::Init(LPCSTR xml_name, LPCSTR start_from) +{ + CUIXml uiXml; + + if (!uiXml.Load(CONFIG_PATH, UI_PATH, xml_name, ShadowOfChernobylMode)) + return false; + + CUIXmlInit xml_init; + + string512 str; + + strcpy_s(str, sizeof(str), start_from); + xml_init.InitWindow(uiXml, str, 0, this); + + strconcat(sizeof(str), str, start_from, ":image"); + m_UIImage = xr_new("Image static"); // Конструктор с именем + m_UIImage->SetAutoDelete(true); + xml_init.InitStatic(uiXml, str, 0, m_UIImage); + AttachChild(m_UIImage); + + strconcat(sizeof(str), str, start_from, ":text_cont"); + m_UIText = xr_new("Text static"); // Конструктор с именем + m_UIText->SetAutoDelete(true); + xml_init.InitStatic(uiXml, str, 0, m_UIText); + AttachChild(m_UIText); + + return true; +} + +void CUIEncyclopediaArticleWnd::SetArticle(CEncyclopediaArticle* article) +{ + if (article->data() && article->data()->image.GetConstHeading()) { + m_UIImage->SetShader(article->data()->image.GetShader()); + m_UIImage->SetWndRect(article->data()->image.GetStaticItem()->GetTextureRect()); + m_UIImage->SetWndSize(article->data()->image.GetWndSize()); + + float img_x = (GetWidth() - m_UIImage->GetWidth()) / 2.0f; + img_x = _max(0.0f, img_x); + m_UIImage->SetWndPos(Fvector2(img_x, m_UIImage->GetWndPos().y)); + }; + m_UIText->SetText(*CStringTable().translate(article->data()->text.c_str())); + m_UIText->AdjustHeightToText(); + + AdjustLauout(); +} + +void CUIEncyclopediaArticleWnd::AdjustLauout() +{ + m_UIText->SetWndPos(Fvector2(m_UIText->GetWndPos().x, m_UIImage->GetWndPos().y + m_UIImage->GetHeight())); + SetHeight(m_UIImage->GetWndPos().y + m_UIImage->GetHeight() + m_UIText->GetHeight()); +} + +void CUIEncyclopediaArticleWnd::SetArticle(LPCSTR article) +{ + CEncyclopediaArticle A; + A.Load(article); + SetArticle(&A); +} diff --git a/src/xrGame/ui/UIEncyclopediaArticleWnd.h b/src/xrGame/ui/UIEncyclopediaArticleWnd.h new file mode 100644 index 00000000000..db5a628abaf --- /dev/null +++ b/src/xrGame/ui/UIEncyclopediaArticleWnd.h @@ -0,0 +1,24 @@ +#pragma once +#include "xrUICore/Windows/UIWindow.h" + +class CUIStatic; +class CEncyclopediaArticle; + +class CUIEncyclopediaArticleWnd :public CUIWindow +{ + typedef CUIWindow inherited; + + CUIStatic* m_UIImage; + CUIStatic* m_UIText; + CEncyclopediaArticle* m_Article; + +protected: + void AdjustLauout(); + +public: + CUIEncyclopediaArticleWnd(); + virtual ~CUIEncyclopediaArticleWnd(); + bool Init(LPCSTR xml_name, LPCSTR start_from); + void SetArticle(CEncyclopediaArticle*); + void SetArticle(LPCSTR); +}; diff --git a/src/xrGame/ui/UIEncyclopediaWnd.cpp b/src/xrGame/ui/UIEncyclopediaWnd.cpp new file mode 100644 index 00000000000..d925905e303 --- /dev/null +++ b/src/xrGame/ui/UIEncyclopediaWnd.cpp @@ -0,0 +1,269 @@ +//============================================================================= +// Filename: UIEncyclopediaWnd.cpp +// Created by Roman E. Marchenko, vortex@gsc-game.kiev.ua +// Copyright 2004. GSC Game World +// --------------------------------------------------------------------------- +// Encyclopedia window +//============================================================================= + +#include "StdAfx.h" +#include "UIEncyclopediaWnd.h" +#include "UIXmlInit.h" +#include "xrUICore/Windows/UIFrameWindow.h" +#include "xrUICore/Windows/UIFrameLineWnd.h" +#include "xrUICore/Static/UIAnimatedStatic.h" +#include "xrUICore/ListWnd/UIListWnd.h" +#include "xrUICore/ScrollView/UIScrollView.h" +#include "xrUICore/ScrollView/UITreeViewItem.h" +#include "UIEncyclopediaArticleWnd.h" +#include "../encyclopedia_article.h" +#include "../alife_registry_wrappers.h" +#include "../actor.h" +#include "Common/object_broker.h" + +#define ENCYCLOPEDIA_DIALOG_XML "encyclopedia.xml" +#define ALL_PDA_HEADER_PREFIX "# "; +CUIEncyclopediaWnd::CUIEncyclopediaWnd() : + CUIWindow("CUIEncyclopediaWnd"), + prevArticlesCount(0), + UIEncyclopediaIdxBkg(NULL), + UIEncyclopediaInfoBkg(NULL), + UIEncyclopediaIdxHeader(NULL), + UIEncyclopediaInfoHeader(NULL), + UIAnimation(NULL), + UIArticleHeader(NULL), + UIIdxList(NULL), + UIInfoList(NULL), + m_pTreeRootFont(NULL), + m_pTreeItemFont(NULL) +{ +} + +CUIEncyclopediaWnd::~CUIEncyclopediaWnd() +{ + DeleteArticles(); +} + + +bool CUIEncyclopediaWnd::Init() +{ + CUIXml uiXml; + + if (!uiXml.Load(CONFIG_PATH, UI_PATH, ENCYCLOPEDIA_DIALOG_XML, ShadowOfChernobylMode)) + return false; + + CUIXmlInit xml_init; + + xml_init.InitWindow(uiXml, "main_wnd", 0, this); + + // Load xml data - ИСПРАВЛЕНИЕ КОНСТРУКТОРОВ + UIEncyclopediaIdxBkg = xr_new("IdxBackground"); + UIEncyclopediaIdxBkg->SetAutoDelete(true); + AttachChild(UIEncyclopediaIdxBkg); + xml_init.InitFrameWindow(uiXml, "right_frame_window", 0, UIEncyclopediaIdxBkg); + + xml_init.InitFont(uiXml, "tree_item_font", 0, m_uTreeItemColor, m_pTreeItemFont); + R_ASSERT(m_pTreeItemFont); + xml_init.InitFont(uiXml, "tree_root_font", 0, m_uTreeRootColor, m_pTreeRootFont); + R_ASSERT(m_pTreeRootFont); + + UIEncyclopediaIdxHeader = xr_new("IdxHeader"); + UIEncyclopediaIdxHeader->SetAutoDelete(true); + UIEncyclopediaIdxBkg->AttachChild(UIEncyclopediaIdxHeader); + xml_init.InitFrameLine(uiXml, "right_frame_line", 0, UIEncyclopediaIdxHeader); + + UIAnimation = xr_new(); + UIAnimation->SetAutoDelete(true); + UIEncyclopediaIdxHeader->AttachChild(UIAnimation); + xml_init.InitAnimatedStatic(uiXml, "a_static", 0, UIAnimation); + + UIEncyclopediaInfoBkg = xr_new("InfoBackground"); + UIEncyclopediaInfoBkg->SetAutoDelete(true); + AttachChild(UIEncyclopediaInfoBkg); + xml_init.InitFrameWindow(uiXml, "left_frame_window", 0, UIEncyclopediaInfoBkg); + + UIEncyclopediaInfoHeader = xr_new("InfoHeader"); + UIEncyclopediaInfoHeader->SetAutoDelete(true); + UIEncyclopediaInfoBkg->AttachChild(UIEncyclopediaInfoHeader); + + UIEncyclopediaInfoHeader->UITitleText = xr_new("UITitleText"); + UIEncyclopediaInfoHeader->UITitleText->SetEllipsis(true); + xml_init.InitFrameLine(uiXml, "left_frame_line", 0, UIEncyclopediaInfoHeader); + + UIArticleHeader = xr_new("ArticleHeader"); + UIArticleHeader->SetAutoDelete(true); + UIEncyclopediaInfoBkg->AttachChild(UIArticleHeader); + xml_init.InitStatic(uiXml, "article_header_static", 0, UIArticleHeader); + + UIIdxList = xr_new(); + UIIdxList->SetAutoDelete(true); + UIEncyclopediaIdxBkg->AttachChild(UIIdxList); + xml_init.InitListWnd(uiXml, "idx_list", 0, UIIdxList); + UIIdxList->SetMessageTarget(this); + UIIdxList->EnableScrollBar(true); + + UIInfoList = xr_new(); + UIInfoList->SetAutoDelete(true); + UIEncyclopediaInfoBkg->AttachChild(UIInfoList); + xml_init.InitScrollView(uiXml, "info_list", 0, UIInfoList); + + xml_init.InitWindow(uiXml, "left_auto_static", 0, UIEncyclopediaInfoBkg); + xml_init.InitWindow(uiXml, "right_auto_static", 0, UIEncyclopediaIdxBkg); + + return true; +} + +void CUIEncyclopediaWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData) +{ + if (UIIdxList == pWnd && LIST_ITEM_CLICKED == msg) + { + CUITreeViewItem* pTVItem = static_cast(pData); + R_ASSERT(pTVItem); + + if (pTVItem->vSubItems.size()) + { + CEncyclopediaArticle* A = m_ArticlesDB[pTVItem->vSubItems[0]->GetValue()]; + + xr_string caption = ALL_PDA_HEADER_PREFIX; + caption += "/"; + caption += CStringTable().translate(A->data()->group).c_str(); + + UIEncyclopediaInfoHeader->UITitleText->SetText(caption.c_str()); + UIArticleHeader->SetTextST(*(A->data()->group)); + SetCurrentArtice(NULL); + } + else + { + CEncyclopediaArticle* A = m_ArticlesDB[pTVItem->GetValue()]; + xr_string caption = ALL_PDA_HEADER_PREFIX; + caption += "/"; + caption += CStringTable().translate(A->data()->group).c_str(); + caption += "/"; + caption += CStringTable().translate(A->data()->name).c_str(); + + UIEncyclopediaInfoHeader->UITitleText->SetText(caption.c_str()); + SetCurrentArtice(pTVItem); + UIArticleHeader->SetTextST(*(A->data()->name)); + } + } + + inherited::SendMessage(pWnd, msg, pData); +} + +void CUIEncyclopediaWnd::Draw() +{ + + if (m_flags.test(eNeedReload)) { + if (Actor()->encyclopedia_registry->registry().objects_ptr() && Actor()->encyclopedia_registry->registry().objects_ptr()->size() > prevArticlesCount) + { + ARTICLE_VECTOR::const_iterator it = Actor()->encyclopedia_registry->registry().objects_ptr()->begin(); + std::advance(it, prevArticlesCount); + for (; it != Actor()->encyclopedia_registry->registry().objects_ptr()->end(); it++) + { + if (ARTICLE_DATA::eEncyclopediaArticle == it->article_type) + { + AddArticle(it->article_id, it->readed); + } + } + prevArticlesCount = Actor()->encyclopedia_registry->registry().objects_ptr()->size(); + } + + m_flags.set(eNeedReload, FALSE); + } + + inherited::Draw(); +} + +void CUIEncyclopediaWnd::ReloadArticles() +{ + m_flags.set(eNeedReload, TRUE); +} + + +void CUIEncyclopediaWnd::Show(bool status) +{ + if (status) + ReloadArticles(); + + inherited::Show(status); +} + + +bool CUIEncyclopediaWnd::HasArticle(shared_str id) +{ + ReloadArticles(); + for (std::size_t i = 0; i < m_ArticlesDB.size(); ++i) + { + if (m_ArticlesDB[i]->Id() == id) return true; + } + return false; +} + + +void CUIEncyclopediaWnd::DeleteArticles() +{ + UIIdxList->RemoveAll(); + delete_data(m_ArticlesDB); +} + +void CUIEncyclopediaWnd::SetCurrentArtice(CUITreeViewItem* pTVItem) +{ + UIInfoList->ScrollToBegin(); + UIInfoList->Clear(); + + if (!pTVItem) return; + + // для начала проверим, что нажатый элемент не рутовый + if (!pTVItem->IsRoot()) + { + + CUIEncyclopediaArticleWnd* article_info = xr_new(); + article_info->Init("encyclopedia_item.xml", "encyclopedia_wnd:objective_item"); + article_info->SetArticle(m_ArticlesDB[pTVItem->GetValue()]); + UIInfoList->AddWindow(article_info, true); + + // Пометим как прочитанную + if (!pTVItem->IsArticleReaded()) + { + if (Actor()->encyclopedia_registry->registry().objects_ptr()) + { + for (ARTICLE_VECTOR::iterator it = Actor()->encyclopedia_registry->registry().objects().begin(); + it != Actor()->encyclopedia_registry->registry().objects().end(); it++) + { + if (ARTICLE_DATA::eEncyclopediaArticle == it->article_type && + m_ArticlesDB[pTVItem->GetValue()]->Id() == it->article_id) + { + it->readed = true; + break; + } + } + } + } + } +} + +void CUIEncyclopediaWnd::AddArticle(shared_str article_id, bool bReaded) +{ + for (std::size_t i = 0; i < m_ArticlesDB.size(); i++) + { + if (m_ArticlesDB[i]->Id() == article_id) return; + } + + // Добавляем элемент + m_ArticlesDB.resize(m_ArticlesDB.size() + 1); + CEncyclopediaArticle*& a = m_ArticlesDB.back(); + a = xr_new(); + a->Load(article_id); + + + // Теперь создаем иерархию вещи по заданному пути + + CreateTreeBranch(a->data()->group, a->data()->name, UIIdxList, m_ArticlesDB.size() - 1, + m_pTreeRootFont, m_uTreeRootColor, m_pTreeItemFont, m_uTreeItemColor, bReaded); +} + +void CUIEncyclopediaWnd::Reset() +{ + inherited::Reset(); + ReloadArticles(); +} diff --git a/src/xrGame/ui/UIEncyclopediaWnd.h b/src/xrGame/ui/UIEncyclopediaWnd.h new file mode 100644 index 00000000000..2a5dc5896a2 --- /dev/null +++ b/src/xrGame/ui/UIEncyclopediaWnd.h @@ -0,0 +1,69 @@ +//============================================================================= +// Filename: UIEncyclopediaWnd.h +// Created by Roman E. Marchenko, vortex@gsc-game.kiev.ua +// Copyright 2004. GSC Game World +// --------------------------------------------------------------------------- +// Encyclopedia window +//============================================================================= + +#pragma once + +#include "xrUICore/Windows/UIWindow.h" +#include "../encyclopedia_article_defs.h" + +class CEncyclopediaArticle; +class CUIFrameWindow; +class CUIFrameLineWnd; +class CUIAnimatedStatic; +class CUIStatic; +class CUIListWnd; +class CUIEncyclopediaCore; +class CUIScrollView; +class CUITreeViewItem; + +class CUIEncyclopediaWnd: public CUIWindow +{ +private: + typedef CUIWindow inherited; + enum {eNeedReload=(1<<0),}; + Flags16 m_flags; +public: + CUIEncyclopediaWnd (); + virtual ~CUIEncyclopediaWnd (); + + virtual bool Init (); + virtual void Show (bool status); + virtual void SendMessage (CUIWindow *pWnd, s16 msg, void* pData = NULL); + virtual void Draw (); + + void AddArticle (shared_str, bool bReaded); + void DeleteArticles (); + bool HasArticle (shared_str); + + void ReloadArticles (); + virtual void Reset (); +protected: + u32 prevArticlesCount; + // Элементы графического оформления + CUIFrameWindow* UIEncyclopediaIdxBkg; + CUIFrameWindow* UIEncyclopediaInfoBkg; + CUIFrameLineWnd* UIEncyclopediaIdxHeader; + CUIFrameLineWnd* UIEncyclopediaInfoHeader; + CUIAnimatedStatic* UIAnimation; + CUIStatic* UIArticleHeader; + + // Хранилище статей + typedef xr_vector ArticlesDB; + typedef ArticlesDB::iterator ArticlesDB_it; + + ArticlesDB m_ArticlesDB; + CGameFont* m_pTreeRootFont; + u32 m_uTreeRootColor; + CGameFont* m_pTreeItemFont; + u32 m_uTreeItemColor; + + CUIListWnd* UIIdxList; + CUIScrollView* UIInfoList; + + void SetCurrentArtice(CUITreeViewItem *pTVItem); +}; diff --git a/src/xrGame/ui/UIEventsWnd.cpp b/src/xrGame/ui/UIEventsWnd.cpp new file mode 100644 index 00000000000..f40791ab4c5 --- /dev/null +++ b/src/xrGame/ui/UIEventsWnd.cpp @@ -0,0 +1,318 @@ +#include "StdAfx.h" +#include "UIPdaWnd.h" +#include "PDA.h" +#include "GameTask.h" +#include "Actor.h" +#include "alife_registry_wrappers.h" +#include "GameTaskManager.h" +#include "UIEventsWnd.h" +#include "xrUICore/XML/xrUIXmlParser.h" +#include "UIXmlInit.h" +#include "UIInventoryUtilities.h" + +#include "Level.h" +#include "UIGameCustom.h" + +#include "xrUICore/Static/UIStatic.h" +#include "xrUICore/Windows/UIFrameWindow.h" +#include "xrUICore/TabControl/UITabControl.h" +#include "UIMapWnd.h" +#include "xrUICore/Windows/UIFrameLineWnd.h" +#include "Common/object_broker.h" +#include "UIMessagesWindow.h" +#include "UIMainIngameWnd.h" +#include "xrUICore/TabControl/UITabButton.h" +#include "xrUICore/Static/UIAnimatedStatic.h" + +#include "UIHelper.h" +#include "xrUICore/Hint/UIHint.h" +#include "xrUICore/Buttons/UIBtnHint.h" +#include "UITaskWnd.h" +#include "UIFactionWarWnd.h" +#include "UIActorInfo.h" +#include "UIRankingWnd.h" +#include "UILogsWnd.h" +#include "UIScriptWnd.h" +#include "encyclopedia_article.h" + +#define PDA_EVENTS_XML "pda_events.xml" + +CUIEventsWnd::CUIEventsWnd() : + CUIWindow("CUIEventsWnd"), + m_UILeftFrame(NULL), + m_UIRightWnd(NULL), + m_UILeftHeader(NULL), + m_UIAnimation(NULL), + m_UIMapWnd(NULL), + m_UITaskInfoWnd(NULL), + m_ListWnd(NULL), + m_TaskFilter(NULL) +{ + m_flags.zero(); +} + +CUIEventsWnd::~CUIEventsWnd() +{ + delete_data(m_UIMapWnd); + delete_data(m_UITaskInfoWnd); +} + +bool CUIEventsWnd::Init() +{ + CUIXml xml; + if (!xml.Load(CONFIG_PATH, UI_PATH, UI_PATH_DEFAULT, PDA_EVENTS_XML, false)) + return false; + + CUIXmlInit xml_init; + xml_init.InitWindow(xml, "main_wnd", 0, this); + + // ИСПРАВЛЕНИЕ: Конструкторы с именами + m_UILeftFrame = xr_new("LeftFrame"); + m_UILeftFrame->SetAutoDelete(true); + AttachChild(m_UILeftFrame); + xml_init.InitFrameWindow(xml, "main_wnd:left_frame", 0, m_UILeftFrame); + + m_UILeftHeader = xr_new("LeftHeader"); + m_UILeftHeader->SetAutoDelete(true); + m_UILeftFrame->AttachChild(m_UILeftHeader); + xml_init.InitFrameLine(xml, "main_wnd:left_frame:left_frame_header", 0, m_UILeftHeader); + + m_UIAnimation = xr_new(); + m_UIAnimation->SetAutoDelete(true); + xml_init.InitAnimatedStatic(xml, "main_wnd:left_frame:left_frame_header:anim_static", 0, m_UIAnimation); + m_UILeftHeader->AttachChild(m_UIAnimation); + + m_UIRightWnd = xr_new("RightWindow"); + m_UIRightWnd->SetAutoDelete(true); + AttachChild(m_UIRightWnd); + xml_init.InitWindow(xml, "main_wnd:right_frame", 0, m_UIRightWnd); + + m_UIMapWnd = xr_new(nullptr); + m_UIMapWnd->SetAutoDelete(false); + m_UIMapWnd->Init("pda_events.xml", "main_wnd:right_frame:map_wnd", !ShadowOfChernobylMode); + + m_UITaskInfoWnd = xr_new(); + m_UITaskInfoWnd->SetAutoDelete(false); + m_UITaskInfoWnd->Init(&xml, "main_wnd:right_frame:task_descr_view"); + + // ИСПРАВЛЕНИЕ: Конструктор CUIScrollView с именем + m_ListWnd = xr_new(); + m_ListWnd->SetAutoDelete(true); + m_UILeftFrame->AttachChild(m_ListWnd); + xml_init.InitScrollView(xml, "main_wnd:left_frame:list", 0, m_ListWnd); + + // ИСПРАВЛЕНИЕ: Конструктор CUITabControl с именем + m_TaskFilter = xr_new(); + m_TaskFilter->SetAutoDelete(true); + m_UILeftFrame->AttachChild(m_TaskFilter); + + xml_init.InitTabControl(xml, "main_wnd:left_frame:filter_tab", 0, m_TaskFilter); + m_TaskFilter->SetWindowName("filter_tab"); + Register(m_TaskFilter); + AddCallback(m_TaskFilter, TAB_CHANGED, CUIWndCallback::void_function(this, &CUIEventsWnd::OnFilterChanged)); + + m_currFilter = eActiveTask; + //SetDescriptionMode(true); + + m_ui_task_item_xml.Load(CONFIG_PATH, UI_PATH, "job_item.xml"); + + return true; +} + +void CUIEventsWnd::Update() +{ + if (m_flags.test(flNeedReload)) { + ReloadList(false); + m_flags.set(flNeedReload, FALSE); + } + inherited::Update(); +} + +void CUIEventsWnd::Draw() +{ + inherited::Draw(); +} + +void CUIEventsWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData) +{ + CUIWndCallback::OnEvent(pWnd, msg, pData); +} + +void CUIEventsWnd::OnFilterChanged(CUIWindow* w, void*) +{ + m_currFilter = (ETaskFilters)m_TaskFilter->GetActiveIndex(); + ReloadList(false); + if (!GetDescriptionMode()) + SetDescriptionMode(true); +} + +void CUIEventsWnd::Reload() +{ + m_flags.set(flNeedReload, TRUE); +} + +void CUIEventsWnd::ReloadList(bool bClearOnly) +{ + m_ListWnd->Clear(); + if (bClearOnly) return; + + if (!g_actor) return; + vGameTasks& tasks = Level().GameTaskManager().GetGameTasks(); + vGameTasks::iterator it = tasks.begin(); + CGameTask* task = NULL; + + for (; it != tasks.end(); ++it) + { + task = (*it).game_task; + R_ASSERT(task); + R_ASSERT(task->GetObjectivesCount() > 0); + + if (!Filter(task)) continue; + for (u16 i = 0; i < task->GetObjectivesCount(); ++i) + { + if (i == 0) + { + CUITaskRootItem* pTaskItem = xr_new(this); + pTaskItem->SetGameTask(task); + m_ListWnd->AddWindow(pTaskItem, true); + } + else { + CUITaskSubItem* pTaskItem = xr_new(this); + pTaskItem->SetGameTask(task); + m_ListWnd->AddWindow(pTaskItem, true); + } + } + } +} + +void CUIEventsWnd::Show(bool status) +{ + inherited::Show(status); + m_UIMapWnd->Show(status); + m_UITaskInfoWnd->Show(status); + + ReloadList(status == false); + +} + +bool CUIEventsWnd::Filter(CGameTask* t) +{ + ETaskState task_state = t->Objective(0).GetTaskState(); + switch (m_currFilter) + { + case CUIEventsWnd::eActiveTask: + return task_state == eTaskStateInProgress; + case CUIEventsWnd::eAccomplishedTask: + return task_state == eTaskStateCompleted; + case CUIEventsWnd::eFailedTask: + return task_state == eTaskStateFail; + case CUIEventsWnd::eMaxTask: + return false; + default: + return false; + } +} + + +void CUIEventsWnd::SetDescriptionMode(bool bMap) +{ + if (bMap) { + m_UIRightWnd->DetachChild(m_UITaskInfoWnd); + m_UIRightWnd->AttachChild(m_UIMapWnd); + } + else { + m_UIRightWnd->DetachChild(m_UIMapWnd); + m_UIRightWnd->AttachChild(m_UITaskInfoWnd); + } + m_flags.set(flMapMode, bMap); +} + +bool CUIEventsWnd::GetDescriptionMode() +{ + return !!m_flags.test(flMapMode); +} + +void CUIEventsWnd::ShowDescription(CGameTask* t, int idx) +{ + if (GetDescriptionMode()) {//map + SGameTaskObjective& o = t->Objective(idx); + CMapLocation* ml = o.LinkedMapLocation(); + + if (ml && ml->SpotEnabled()) + m_UIMapWnd->SetTargetMap(ml->GetLevelName(), ml->GetPosition(), true); + } + else + { + SGameTaskObjective& o = t->Objective(0); + idx = 0; + + m_UITaskInfoWnd->ClearAll(); + + if (Actor()->encyclopedia_registry->registry().objects_ptr()) + { + string512 need_group; + if (idx == 0) + strcpy(need_group, *t->m_ID); + else if (!o.m_article_key.size()) + sprintf_s(need_group, "%s/%d", *t->m_ID, idx); + else + sprintf_s(need_group, "%s/%s", *t->m_ID, *o.m_article_key); + + ARTICLE_VECTOR::const_iterator it = Actor()->encyclopedia_registry->registry().objects_ptr()->begin(); + + for (; it != Actor()->encyclopedia_registry->registry().objects_ptr()->end(); ++it) + { + if (ARTICLE_DATA::eTaskArticle == it->article_type) + { + CEncyclopediaArticle A; + A.Load(it->article_id); + + const shared_str& group = A.data()->group; + + if (strstr(*group, need_group) == *group) + { + u32 sz = xr_strlen(need_group); + if (group.size() == sz || (*group)[sz] == '/') + m_UITaskInfoWnd->AddArticle(&A); + } + else if (it->article_id == o.m_article_id) + { + CEncyclopediaArticle A; + A.Load(it->article_id); + m_UITaskInfoWnd->AddArticle(&A); + } + } + } + } + } + + int sz = m_ListWnd->GetSize(); + for (int i = 0; i < sz; ++i) + { + CUITaskItem* itm = (CUITaskItem*)m_ListWnd->GetItem(i); + if (itm->OwnerTask() == t && itm->OwnerTask()->ActiveObjective().m_idx == idx) + itm->MarkSelected(true); + else + itm->MarkSelected(false); + } +} + +bool CUIEventsWnd::ItemHasDescription(CUITaskItem* itm) +{ + if (itm->OwnerTask()->ActiveObjective().m_idx == 0)// root + return itm->OwnerTask()->LinkedMapLocation(); + else + { + SGameTaskObjective obj = itm->OwnerTask()->ActiveObjective(); + CMapLocation* ml = obj.LinkedMapLocation(); + bool bHasLocation = (NULL != ml); + bool bIsMapMode = GetDescriptionMode(); + bool b = (bIsMapMode && bHasLocation && ml->SpotEnabled()); + return b; + } +} +void CUIEventsWnd::Reset() +{ + inherited::Reset(); + Reload(); +} diff --git a/src/xrGame/ui/UIEventsWnd.h b/src/xrGame/ui/UIEventsWnd.h new file mode 100644 index 00000000000..5d49372bd8b --- /dev/null +++ b/src/xrGame/ui/UIEventsWnd.h @@ -0,0 +1,63 @@ +#pragma once +#include "xrUICore/Windows/UIWindow.h" +#include "xrUICore/Callbacks/UIWndCallback.h" +#include "UITaskDescrWnd.h" +#include "UIXmlInit.h" + +class CUIFrameWindow; +class CUIFrameLineWnd; +class CUIAnimatedStatic; +class CUIMapWnd; +class CUI3tButton; +class CUITabControl; +class CGameTask; +class CUITaskWnd; +class CUIScrollView; +class CUITaskItem; + +class CUIEventsWnd : public CUIWindow, public CUIWndCallback{ + typedef CUIWindow inherited; + enum ETaskFilters{ eActiveTask = 0, + eAccomplishedTask, + eFailedTask, +//. eOwnTask, + eMaxTask}; + enum EEventWndFlags{ + flNeedReload =(1<<0), + flMapMode =(1<<1), + }; + Flags16 m_flags; + ETaskFilters m_currFilter; + CUIFrameWindow* m_UILeftFrame; + CUIWindow* m_UIRightWnd; + CUIFrameLineWnd* m_UILeftHeader; + CUIAnimatedStatic* m_UIAnimation; + CUIMapWnd* m_UIMapWnd; + CUITaskDescrWnd* m_UITaskInfoWnd; + CUIScrollView* m_ListWnd; + CUITabControl* m_TaskFilter; + + bool Filter (CGameTask* t); + void __stdcall OnFilterChanged (CUIWindow*,void*); + void ReloadList (bool bClearOnly); + +public: + void SetDescriptionMode (bool bMap); + bool GetDescriptionMode (); + void ShowDescription (CGameTask* t, int idx); + bool ItemHasDescription (CUITaskItem*); +public: + + CUIEventsWnd (); + virtual ~CUIEventsWnd (); + virtual void SendMessage (CUIWindow* pWnd, s16 msg, void* pData); + bool Init (); + virtual void Update (); + virtual void Draw (); + virtual void Show (bool status); + void Reload (); + virtual void Reset (); + + CUIXml m_ui_task_item_xml; + +}; diff --git a/src/xrGame/ui/UIGameTutorialSimpleItem.cpp b/src/xrGame/ui/UIGameTutorialSimpleItem.cpp index b197f67be87..a8d569c76be 100644 --- a/src/xrGame/ui/UIGameTutorialSimpleItem.cpp +++ b/src/xrGame/ui/UIGameTutorialSimpleItem.cpp @@ -304,7 +304,7 @@ void CUISequenceSimpleItem::Start() bShowPda = true; } - if ((!pda.IsShown() && bShowPda) || (pda.IsShown() && !bShowPda)) + if (pda.IsShown() != bShowPda) { isTimeDilatedInPDA = TimeDilator()->GetModeEnability(UITimeDilator::Pda); TimeDilator()->SetModeEnability(UITimeDilator::Pda, false); diff --git a/src/xrGame/ui/UIMapWnd.cpp b/src/xrGame/ui/UIMapWnd.cpp index 75df8e9e9cf..56a61f96121 100644 --- a/src/xrGame/ui/UIMapWnd.cpp +++ b/src/xrGame/ui/UIMapWnd.cpp @@ -64,7 +64,7 @@ CUIMapWnd::~CUIMapWnd() g_map_wnd = NULL; } -bool CUIMapWnd::Init(cpcstr xml_name, cpcstr start_from, bool critical /*= true*/) +bool CUIMapWnd::Init(cpcstr xml_name, cpcstr start_from, bool critical) { CUIXml uiXml; if (!uiXml.Load(CONFIG_PATH, UI_PATH, UI_PATH_DEFAULT, xml_name, critical)) diff --git a/src/xrGame/ui/UIPdaWnd.cpp b/src/xrGame/ui/UIPdaWnd.cpp index 78bb785ab35..5da893280c3 100644 --- a/src/xrGame/ui/UIPdaWnd.cpp +++ b/src/xrGame/ui/UIPdaWnd.cpp @@ -28,13 +28,14 @@ #include "UIActorInfo.h" #include "UIRankingWnd.h" #include "UILogsWnd.h" +#include "UIEventsWnd.h" +#include "UIEncyclopediaWnd.h" #include "UIScriptWnd.h" #define PDA_XML "pda.xml" u32 g_pda_info_state = 0; -void RearrangeTabButtons(CUITabControl* pTab); CDialogHolder* CurrentDialogHolder(); CUIPdaWnd::CUIPdaWnd() : CUIDialogWnd(CUIPdaWnd::GetDebugType()) @@ -44,6 +45,8 @@ CUIPdaWnd::CUIPdaWnd() : CUIDialogWnd(CUIPdaWnd::GetDebugType()) pUIFactionWarWnd = nullptr; pUIActorInfo = nullptr; pUIRankingWnd = nullptr; + pUIEncyclopediaWnd = nullptr; + pUIEventsWnd = nullptr; pUILogsWnd = nullptr; m_hint_wnd = nullptr; Init(); @@ -63,7 +66,12 @@ CUIPdaWnd::~CUIPdaWnd() delete_data(pUIRankingWnd); if (pUILogsWnd) delete_data(pUILogsWnd); - delete_data(m_hint_wnd); + if (pUIEventsWnd) + delete_data(pUIEventsWnd); + if (pUIEncyclopediaWnd) + delete_data(pUIEncyclopediaWnd); + if (m_hint_wnd) + delete_data(m_hint_wnd); if (UINoice) delete_data(UINoice); } @@ -81,7 +89,7 @@ void CUIPdaWnd::Init() UIMainPdaFrame = UIHelper::CreateStatic(uiXml, "background_static", this, false); if (ShadowOfChernobylMode) - m_caption = UIHelper::CreateStatic(uiXml, "timer_frame_line:title", this); // no caption tag in SOC + m_caption = UIHelper::CreateStatic(uiXml, "timer_frame_line", this); else m_caption = UIHelper::CreateStatic(uiXml, "caption_static", this); // no caption tag in SOC @@ -105,34 +113,54 @@ void CUIPdaWnd::Init() UI().Focus().UnregisterFocusable(m_btn_close); - if (!ShadowOfChernobylMode) + if (ShadowOfChernobylMode) + m_hint_wnd = UIHelper::CreateHint(uiXml, "left_frame", false); + else m_hint_wnd = UIHelper::CreateHint(uiXml, "hint_wnd", false); if (IsGameTypeSingle()) { - pUIMapWnd = xr_new(m_hint_wnd); - if (!pUIMapWnd->Init("pda_map.xml", "map_wnd", false)) - xr_delete(pUIMapWnd); - pUITaskWnd = xr_new(m_hint_wnd); - if (!pUITaskWnd->Init()) - xr_delete(pUITaskWnd); + if (ShadowOfChernobylMode) + { + pUIMapWnd = xr_new(m_hint_wnd); + if (!pUIMapWnd->Init("pda_map.xml", "map_wnd", false)) + xr_delete(pUIMapWnd); + + pUIEventsWnd = xr_new(); + if (!pUIEventsWnd->Init()) + xr_delete(pUIEventsWnd); + + pUIEncyclopediaWnd = xr_new(); + if (!pUIEncyclopediaWnd->Init()) + xr_delete(pUIEncyclopediaWnd); + } + else { + + pUIMapWnd = xr_new(m_hint_wnd); + if (!pUIMapWnd->Init("pda_map.xml", "map_wnd", false)) + xr_delete(pUIMapWnd); + + pUITaskWnd = xr_new(m_hint_wnd); + if (!pUITaskWnd->Init()) + xr_delete(pUITaskWnd); - pUIFactionWarWnd = xr_new(m_hint_wnd); - if (!pUIFactionWarWnd->Init()) - xr_delete(pUIFactionWarWnd); + pUIFactionWarWnd = xr_new(m_hint_wnd); + if (!pUIFactionWarWnd->Init()) + xr_delete(pUIFactionWarWnd); - pUIActorInfo = xr_new(); - if (!pUIActorInfo->Init()) - xr_delete(pUIActorInfo); + pUIActorInfo = xr_new(); + if (!pUIActorInfo->Init()) + xr_delete(pUIActorInfo); - pUIRankingWnd = xr_new(); - if (!pUIRankingWnd->Init()) - xr_delete(pUIRankingWnd); + pUIRankingWnd = xr_new(); + if (!pUIRankingWnd->Init()) + xr_delete(pUIRankingWnd); - pUILogsWnd = xr_new(); - if (!pUILogsWnd->Init()) - xr_delete(pUILogsWnd); + pUILogsWnd = xr_new(); + if (!pUILogsWnd->Init()) + xr_delete(pUILogsWnd); + } } UITabControl = xr_new(); @@ -179,6 +207,7 @@ void CUIPdaWnd::Init() RearrangeTabButtons(UITabControl); } + void CUIPdaWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData) { switch (msg) @@ -186,24 +215,20 @@ void CUIPdaWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData) case TAB_CHANGED: { if (pWnd == UITabControl) - { - const auto& id = UITabControl->GetActiveId(); - SetActiveSubdialog(id); - } + SetActiveSubdialog(UITabControl->GetActiveId()); break; } case BUTTON_CLICKED: { if (pWnd == m_btn_close) - { HideDialog(); - } break; } default: { if (m_pActiveDialog) m_pActiveDialog->SendMessage(pWnd, msg, pData); + break; } }; } @@ -267,12 +292,13 @@ void CUIPdaWnd::SetActiveSubdialog(const shared_str& section) const std::tuple availableWindowsList[] = { - { "eptMap", pUIMapWnd }, - { "eptTasks", pUITaskWnd }, - { "eptFractionWar", pUIFactionWarWnd }, - { "eptStatistics", pUIActorInfo }, - { "eptRanking", pUIRankingWnd }, - { "eptLogs", pUILogsWnd }, + { "eptMap", pUIMapWnd }, + { "eptTasks", pUITaskWnd }, + { "eptFractionWar", pUIFactionWarWnd }, + { "eptStatistics", pUIActorInfo }, + { "eptRanking", pUIRankingWnd }, + { "eptLogs", pUILogsWnd }, + { "eptEncyclopedia", pUIEventsWnd }, }; for (const auto& [id, wnd] : availableWindowsList) @@ -398,9 +424,7 @@ void CUIPdaWnd::UpdatePda() pUILogsWnd->UpdateNews(); if (m_pActiveDialog == pUITaskWnd && pUITaskWnd) - { pUITaskWnd->ReloadTaskInfo(); - } } void CUIPdaWnd::UpdateRankingWnd() @@ -428,7 +452,7 @@ void CUIPdaWnd::Reset() } void CUIPdaWnd::SetCaption(pcstr text) { m_caption->SetText(text); } -void RearrangeTabButtons(CUITabControl* pTab) +void CUIPdaWnd::RearrangeTabButtons(CUITabControl* pTab) { const auto& buttons = *pTab->GetButtonsVector(); diff --git a/src/xrGame/ui/UIPdaWnd.h b/src/xrGame/ui/UIPdaWnd.h index 3394dff1fcc..47e7642df3d 100644 --- a/src/xrGame/ui/UIPdaWnd.h +++ b/src/xrGame/ui/UIPdaWnd.h @@ -18,6 +18,8 @@ class CUIActorInfoWnd; class CUIRankingWnd; class CUILogsWnd; class CUIAnimatedStatic; +class CUIEncyclopediaWnd; +class CUIEventsWnd; class UIHint; class CUIPdaWnd final : public CUIDialogWnd @@ -45,6 +47,8 @@ class CUIPdaWnd final : public CUIDialogWnd // Поддиалоги PDA CUIMapWnd* pUIMapWnd; CUITaskWnd* pUITaskWnd; + CUIEncyclopediaWnd* pUIEncyclopediaWnd; + CUIEventsWnd* pUIEventsWnd; CUIFactionWarWnd* pUIFactionWarWnd; CUIActorInfoWnd* pUIActorInfo; CUIRankingWnd* pUIRankingWnd; @@ -80,6 +84,7 @@ class CUIPdaWnd final : public CUIDialogWnd void Show_MapWnd(bool status); void Show_ContactsWnd(bool status); void DrawUpdatedSections(); + void RearrangeTabButtons(CUITabControl* pTab); void SetActiveDialog(CUIWindow* wnd) { m_pActiveDialog = wnd; } CUIWindow* GetActiveDialog() const { return m_pActiveDialog; } diff --git a/src/xrGame/ui/UITaskDescrWnd.cpp b/src/xrGame/ui/UITaskDescrWnd.cpp new file mode 100644 index 00000000000..be2d2b9f6a4 --- /dev/null +++ b/src/xrGame/ui/UITaskDescrWnd.cpp @@ -0,0 +1,79 @@ +#include "stdafx.h" +#include "UITaskDescrWnd.h" +#include "UIXmlInit.h" +#include "xrUICore/Windows/UIFrameWindow.h" +#include "xrUICore/Windows/UIFrameLineWnd.h" +#include "xrUICore/ScrollView/UIScrollView.h" +#include "UIEncyclopediaArticleWnd.h" +#include "../encyclopedia_article.h" + + +CUITaskDescrWnd::CUITaskDescrWnd() : + CUIWindow("CUITaskDescrWnd"), + m_UITaskInfoWnd(NULL), + m_UIMainFrame(NULL), + m_UIMainHeader(NULL) +{ +} + +CUITaskDescrWnd::~CUITaskDescrWnd() +{ +} + +bool CUITaskDescrWnd::Init(CUIXml* doc, LPCSTR start_from) +{ + CUIXmlInit xml_init; + + if (!xml_init.InitWindow(*doc, start_from, 0, this, ShadowOfChernobylMode)) + return false; + + string512 str; + + // ИСПРАВЛЕНИЕ: Конструкторы с именами + m_UIMainFrame = xr_new("MainFrame"); + m_UIMainFrame->SetAutoDelete(true); + AttachChild(m_UIMainFrame); + + strconcat(sizeof(str), str, start_from, ":main_frame"); + xml_init.InitFrameWindow(*doc, str, 0, m_UIMainFrame); + + m_UIMainHeader = xr_new("MainHeader"); + m_UIMainHeader->SetAutoDelete(true); + m_UIMainFrame->AttachChild(m_UIMainHeader); + strconcat(sizeof(str), str, start_from, ":main_frame:header_frame_line"); + xml_init.InitFrameLine(*doc, str, 0, m_UIMainHeader); + + m_UITaskInfoWnd = xr_new(); + m_UITaskInfoWnd->SetAutoDelete(true); + m_UIMainFrame->AttachChild(m_UITaskInfoWnd); + strconcat(sizeof(str), str, start_from, ":main_frame:scroll_view"); + xml_init.InitScrollView(*doc, str, 0, m_UITaskInfoWnd); + + return true; +} + +void CUITaskDescrWnd::Draw() +{ + inherited::Draw(); +} + +void CUITaskDescrWnd::ClearAll() +{ + m_UITaskInfoWnd->Clear(); +} + +void CUITaskDescrWnd::AddArticle(LPCSTR article) +{ + CUIEncyclopediaArticleWnd* article_info = xr_new(); + article_info->Init("encyclopedia_item.xml", "events_wnd:objective_item"); + article_info->SetArticle(article); + m_UITaskInfoWnd->AddWindow(article_info, true); +} + +void CUITaskDescrWnd::AddArticle(CEncyclopediaArticle* article) +{ + CUIEncyclopediaArticleWnd* article_info = xr_new(); + article_info->Init("encyclopedia_item.xml", "events_wnd:objective_item"); + article_info->SetArticle(article); + m_UITaskInfoWnd->AddWindow(article_info, true); +} diff --git a/src/xrGame/ui/UITaskDescrWnd.h b/src/xrGame/ui/UITaskDescrWnd.h new file mode 100644 index 00000000000..04ea8c1d4b2 --- /dev/null +++ b/src/xrGame/ui/UITaskDescrWnd.h @@ -0,0 +1,26 @@ +#pragma once +#include "xrUICore/Windows/UIWindow.h" + +class CUIScrollView; +class CUIFrameWindow; +class CUIFrameLineWnd; +class CUIXml; +class CEncyclopediaArticle; + +class CUITaskDescrWnd :public CUIWindow +{ + typedef CUIWindow inherited; +protected: + CUIScrollView* m_UITaskInfoWnd; + CUIFrameWindow* m_UIMainFrame; + CUIFrameLineWnd* m_UIMainHeader; + +public: + CUITaskDescrWnd(); + virtual ~CUITaskDescrWnd(); + virtual void Draw(); + bool Init(CUIXml* doc, LPCSTR start_from); + void ClearAll(); + void AddArticle(LPCSTR article); + void AddArticle(CEncyclopediaArticle* article); +}; diff --git a/src/xrGame/ui/UITaskWnd.cpp b/src/xrGame/ui/UITaskWnd.cpp index 8149ff9b061..b0e3949e425 100644 --- a/src/xrGame/ui/UITaskWnd.cpp +++ b/src/xrGame/ui/UITaskWnd.cpp @@ -20,6 +20,8 @@ #include "GametaskManager.h" #include "Actor.h" #include "xrUICore/Buttons/UICheckButton.h" +#include "UIPdaWnd.h" +#include "UIEventsWnd.h" CUITaskWnd::CUITaskWnd(UIHint* hint) : CUIWindow("CUITaskWnd"), hint_wnd(hint) {} @@ -453,7 +455,8 @@ void CUITaskItem::InitTask(CGameTask* task) } S = m_info["t_caption"]; - S->TextItemControl()->SetTextST((task) ? task->m_Title.c_str() : ""); + if (S) + S->TextItemControl()->SetTextST((task) ? task->m_Title.c_str() : ""); } void CUITaskItem::OnFocusReceive() @@ -469,7 +472,7 @@ void CUITaskItem::OnFocusLost() show_hint_can = false; show_hint = false; } - +IC TASK_OBJECTIVE_ID CUITaskItem::ObjectiveIdx() { return m_owner->ActiveObjective().m_idx; } void CUITaskItem::Update() { inherited::Update(); @@ -484,6 +487,9 @@ void CUITaskItem::Update() } void CUITaskItem::OnMouseScroll(float iDirection) {} +void CUITaskItem::MarkSelected(bool b) { + //m_pStoryLineTaskItem->SetButtonMode(b ? CUIButton::BUTTON_PUSHED : CUIButton::BUTTON_NORMAL); +} bool CUITaskItem::OnMouseAction(float x, float y, EUIMessages mouse_action) { if (inherited::OnMouseAction(x, y, mouse_action)) @@ -505,3 +511,270 @@ bool CUITaskItem::OnMouseAction(float x, float y, EUIMessages mouse_action) } void CUITaskItem::SendMessage(CUIWindow* pWnd, s16 msg, void* pData) { inherited::SendMessage(pWnd, msg, pData); } + + + + +CUITaskRootItem::CUITaskRootItem(CUIEventsWnd* w) : m_EventsWnd(w) +{ + Init(m_EventsWnd->m_ui_task_item_xml, ""); +} + +CUITaskRootItem::~CUITaskRootItem() +{ +} + +void CUITaskRootItem::Init(CUIXml& xml, LPCSTR path) +{ + SetWindowName("job_item"); + Register(this); + AddCallback(this, BUTTON_CLICKED, CUIWndCallback::void_function(this, &CUITaskRootItem::OnSwitchDescriptionClicked)); + + m_taskImage = xr_new("MIMAGE"); + m_taskImage->SetAutoDelete(true); + AttachChild(m_taskImage); + + m_captionStatic = xr_new("MIMAGE2"); + m_captionStatic->SetAutoDelete(true); + AttachChild(m_captionStatic); + + m_remTimeStatic = xr_new("MIMAGE3"); + m_remTimeStatic->SetAutoDelete(true); + AttachChild(m_remTimeStatic); + + m_switchDescriptionBtn = xr_new(); + m_switchDescriptionBtn->SetAutoDelete(true); + AttachChild(m_switchDescriptionBtn); + + m_captionTime = xr_new(); + m_captionTime->SetAutoDelete(true); + AttachChild(m_captionTime); + + m_switchDescriptionBtn->SetWindowName("m_switchDescriptionBtn"); + Register(m_switchDescriptionBtn); + AddCallback(m_switchDescriptionBtn, BUTTON_CLICKED, CUIWndCallback::void_function(this, &CUITaskRootItem::OnSwitchDescriptionClicked)); + + CUIXmlInit xml_init; + CUIXml& uiXml = m_EventsWnd->m_ui_task_item_xml; + xml_init.InitWindow(uiXml, "task_root_item", 0, this); + + xml_init.InitStatic(uiXml, "task_root_item:image", 0, m_taskImage); + xml_init.InitStatic(uiXml, "task_root_item:caption", 0, m_captionStatic); + xml_init.InitStatic(uiXml, "task_root_item:caption_time", 0, m_captionTime); + xml_init.InitStatic(uiXml, "task_root_item:rem_time", 0, m_remTimeStatic); + + xml_init.Init3tButton(uiXml, "task_root_item:switch_description_btn", 0, m_switchDescriptionBtn); +} + +void CUITaskRootItem::SetGameTask(CGameTask* gt) +{ + inherited::InitTask(gt); + + CStringTable stbl; + SGameTaskObjective obj = OwnerTask()->ActiveObjective(); + + m_taskImage->InitTexture(*OwnerTask()->m_icon_texture_name); + + m_taskImage->SetWndRect(obj.m_icon_rect); + //m_taskImage->ClipperOn(); + m_taskImage->SetStretchTexture(true); + + m_captionStatic->SetText(*stbl.translate(OwnerTask()->m_Title)); + m_captionStatic->AdjustHeightToText(); + + xr_string txt = ""; + txt += *(InventoryUtilities::GetDateAsString(gt->m_ReceiveTime, InventoryUtilities::edpDateToDay)); + txt += " "; + txt += *(InventoryUtilities::GetTimeAsString(gt->m_ReceiveTime, InventoryUtilities::etpTimeToMinutes)); + + m_captionTime->SetText(txt.c_str()); + m_captionTime->SetWndPos(Fvector2(m_captionTime->GetWndPos().x, m_captionStatic->GetWndPos().y + m_captionStatic->GetHeight() + 3.0f)); + + float h = _max(m_taskImage->GetWndPos().y + m_taskImage->GetHeight(), m_captionTime->GetWndPos().y + m_captionTime->GetHeight()); + h = _max(h, m_switchDescriptionBtn->GetWndPos().y + m_switchDescriptionBtn->GetHeight()); + SetHeight(h); + + + m_curr_descr_mode = m_EventsWnd->GetDescriptionMode(); + if (m_curr_descr_mode) + m_switchDescriptionBtn->InitTexture("ui_icons_newPDA_showtext"); + else + m_switchDescriptionBtn->InitTexture("ui_icons_newPDA_showmap"); + + m_remTimeStatic->Show((OwnerTask()->Objective(0).GetTaskState() & eTaskStateInProgress) && + (OwnerTask()->m_ReceiveTime != OwnerTask()->m_TimeToComplete)); + + if (m_remTimeStatic->IsShown()) + { + float _height = GetWndSize().y; + Fvector2 _pos = m_captionTime->GetWndPos(); + _pos.y += m_captionTime->GetWndSize().y; + _pos.x = m_remTimeStatic->GetWndPos().x; + + m_remTimeStatic->SetWndPos(_pos); + + _height = _max(_height, _pos.y + m_remTimeStatic->GetWndSize().y); + SetHeight(_height); + } +} + +void CUITaskRootItem::Update() +{ + inherited::Update(); + + if (m_curr_descr_mode != m_EventsWnd->GetDescriptionMode()) { + m_curr_descr_mode = m_EventsWnd->GetDescriptionMode(); + if (m_curr_descr_mode) + m_switchDescriptionBtn->InitTexture("ui_icons_newPDA_showtext"); + else + m_switchDescriptionBtn->InitTexture("ui_icons_newPDA_showmap"); + } + + m_switchDescriptionBtn->SetButtonState(m_EventsWnd->GetDescriptionMode() ? CUIButton::BUTTON_NORMAL : + CUIButton::BUTTON_PUSHED); + + if (m_remTimeStatic->IsShown()) + { + string512 buff, buff2; + InventoryUtilities::GetTimePeriodAsString(buff, sizeof(buff), Level().GetGameTime(), OwnerTask()->m_TimeToComplete); + sprintf_s(buff2, "%s %s", *CStringTable().translate("ui_st_time_remains"), buff); + m_remTimeStatic->SetText(buff2); + + } +} + +bool CUITaskRootItem::OnDbClick() +{ + return true; +} + +void CUITaskRootItem::OnSwitchDescriptionClicked(CUIWindow*, void*) +{ + m_switchDescriptionBtn->SetButtonState(m_EventsWnd->GetDescriptionMode() ? + CUIButton::BUTTON_PUSHED : CUIButton::BUTTON_NORMAL); + + m_EventsWnd->SetDescriptionMode(!m_EventsWnd->GetDescriptionMode()); + m_EventsWnd->ShowDescription(OwnerTask(), ObjectiveIdx()); +} + +void CUITaskRootItem::MarkSelected(bool b) +{ +} + + +CUITaskSubItem::CUITaskSubItem(CUIEventsWnd* w) : m_EventsWnd(w) +{ + Init(m_EventsWnd->m_ui_task_item_xml, ""); +} + +CUITaskSubItem::~CUITaskSubItem() +{ +} + +void CUITaskSubItem::Init(CUIXml& xml, LPCSTR path) +{ + SetWindowName("job_item"); + Register(this); + AddCallback(this, BUTTON_CLICKED, CUIWndCallback::void_function(this, &CUITaskSubItem::OnShowDescriptionClicked)); + + CUIXml& uiXml = m_EventsWnd->m_ui_task_item_xml; + + m_stateStatic = xr_new("MIMAGE22"); + m_stateStatic->SetAutoDelete(true); + AttachChild(m_stateStatic); + + m_descriptionStatic = xr_new("MIMAGE11"); + m_descriptionStatic->SetAutoDelete(true); + AttachChild(m_descriptionStatic); + + m_ActiveObjectiveStatic = xr_new("MIMAGE0"); + m_ActiveObjectiveStatic->SetAutoDelete(true); + AttachChild(m_ActiveObjectiveStatic); + + m_showDescriptionBtn = xr_new(); + m_showDescriptionBtn->SetAutoDelete(true); + AttachChild(m_showDescriptionBtn); + + m_showDescriptionBtn->SetWindowName("m_showDescriptionBtn"); + Register(m_showDescriptionBtn); + + AddCallback(m_showDescriptionBtn, BUTTON_CLICKED, CUIWndCallback::void_function(this, &CUITaskSubItem::OnShowDescriptionClicked)); + + + CUIXmlInit xml_init; + xml_init.InitWindow(uiXml, "task_sub_item", 0, this); + xml_init.InitStatic(uiXml, "task_sub_item:state_image", 0, m_stateStatic); + xml_init.InitStatic(uiXml, "task_sub_item:description", 0, m_descriptionStatic); + xml_init.InitStatic(uiXml, "task_sub_item:active_objecttive_image", 0, m_ActiveObjectiveStatic); + xml_init.Init3tButton(uiXml, "task_sub_item:show_descr_btn", 0, m_showDescriptionBtn); + + + m_active_color = xml_init.GetColor(uiXml, "task_sub_item:description:text_colors:active", 0, 0x00); + m_failed_color = xml_init.GetColor(uiXml, "task_sub_item:description:text_colors:failed", 0, 0x00); + m_accomplished_color = xml_init.GetColor(uiXml, "task_sub_item:description:text_colors:accomplished", 0, 0x00); +} + +void CUITaskSubItem::SetGameTask(CGameTask* gt) +{ + inherited::InitTask(gt); + + CStringTable stbl; + SGameTaskObjective obj = OwnerTask()->ActiveObjective(); + + m_descriptionStatic->SetText(*stbl.translate(obj.m_Description)); + m_descriptionStatic->AdjustHeightToText(); + float h = _max(m_ActiveObjectiveStatic->GetWndPos().y + m_ActiveObjectiveStatic->GetHeight(), + m_descriptionStatic->GetWndPos().y + m_descriptionStatic->GetHeight()); + SetHeight(h); + switch (obj.GetTaskState()) + { + //. case eTaskUserDefined: + case eTaskStateInProgress: + m_stateStatic->InitTexture("ui_icons_PDA_subtask_active"); + m_descriptionStatic->SetTextColor(m_active_color); + break; + case eTaskStateFail: + m_stateStatic->InitTexture("ui_icons_PDA_subtask_failed"); + m_descriptionStatic->SetTextColor(m_failed_color); + break; + case eTaskStateCompleted: + m_stateStatic->InitTexture("ui_icons_PDA_subtask_accomplished"); + m_descriptionStatic->SetTextColor(m_accomplished_color); + break; + default: + NODEFAULT; + }; +} + +void CUITaskSubItem::Update() +{ + inherited::Update(); + bool bIsActive = (Level().GameTaskManager().ActiveTask() == OwnerTask()); + m_ActiveObjectiveStatic->Show(bIsActive); + m_showDescriptionBtn->Show(m_EventsWnd->ItemHasDescription(this)); + +} + +bool CUITaskSubItem::OnDbClick() +{ + if (OwnerTask()->GetTaskState() != eTaskStateInProgress) + return true; + if (Level().GameTaskManager().ActiveTask() != OwnerTask()); + Level().GameTaskManager().SetActiveTask(OwnerTask()); + return true; +} + +void CUITaskSubItem::OnActiveObjectiveClicked() +{ + m_EventsWnd->ShowDescription(OwnerTask(), ObjectiveIdx()); +} + +void CUITaskSubItem::OnShowDescriptionClicked(CUIWindow*, void*) +{ + m_EventsWnd->ShowDescription(OwnerTask(), ObjectiveIdx()); +} + +void CUITaskSubItem::MarkSelected(bool b) +{ + m_showDescriptionBtn->SetButtonState(b ? CUIButton::BUTTON_PUSHED : CUIButton::BUTTON_NORMAL); +} diff --git a/src/xrGame/ui/UITaskWnd.h b/src/xrGame/ui/UITaskWnd.h index d4e67d733ff..899a1afb78c 100644 --- a/src/xrGame/ui/UITaskWnd.h +++ b/src/xrGame/ui/UITaskWnd.h @@ -4,6 +4,7 @@ #include "xrUICore/Callbacks/UIWndCallback.h" #include "xrCore/Containers/AssociativeVector.hpp" #include "GameTaskDefs.h" +#include "UIPdaWnd.h" class CUIMapWnd; class CUIMapFilters; @@ -17,6 +18,7 @@ class CUIFrameWindow; class UITaskListWnd; class UIMapLegend; class UIHint; +class CUIEventsWnd; class CUITaskWnd final : public CUIWindow, public CUIWndCallback { @@ -91,7 +93,7 @@ class CUITaskWnd final : public CUIWindow, public CUIWndCallback void OnTask2DbClicked(CUIWindow*, void*); }; -class CUITaskItem final : public CUIWindow +class CUITaskItem : public CUIWindow { private: typedef CUIWindow inherited; @@ -107,6 +109,7 @@ class CUITaskItem final : public CUIWindow virtual void Update(); virtual void OnMouseScroll(float iDirection); virtual bool OnMouseAction(float x, float y, EUIMessages mouse_action); + virtual void MarkSelected(bool b); virtual void SendMessage(CUIWindow* pWnd, s16 msg, void* pData); void Init(CUIXml& uiXml, LPCSTR path); @@ -114,11 +117,62 @@ class CUITaskItem final : public CUIWindow CGameTask* OwnerTask() const { return m_owner; } pcstr GetDebugType() override { return "CUITaskItem"; } - + IC TASK_OBJECTIVE_ID ObjectiveIdx(); public: bool show_hint_can{}; bool show_hint{}; - protected: u32 m_hint_wt; }; + + +class CUITaskRootItem :public CUITaskItem, public CUIWndCallback +{ +private: + typedef CUITaskItem inherited; + typedef CUIWndCallback inheriteda; +protected: + CUIStatic* m_taskImage; + CUIStatic* m_captionStatic; + CUIStatic* m_captionTime; + CUIStatic* m_remTimeStatic; + CUIEventsWnd* m_EventsWnd; + CUI3tButton* m_switchDescriptionBtn; + bool m_curr_descr_mode; + virtual void Init(CUIXml& xml, LPCSTR path); +public: + CUITaskRootItem(CUIEventsWnd* w); + virtual ~CUITaskRootItem(); + virtual void Update(); + virtual void SetGameTask(CGameTask* gt); + void __stdcall OnSwitchDescriptionClicked(CUIWindow*, void*); + + virtual void MarkSelected(bool b); + virtual bool OnDbClick(); +}; + +class CUITaskSubItem :public CUITaskItem, public CUIWndCallback +{ +private: + typedef CUITaskItem inherited; + typedef CUIWndCallback inheriteda; + u32 m_active_color; + u32 m_failed_color; + u32 m_accomplished_color; +protected: + CUIStatic* m_ActiveObjectiveStatic; + CUI3tButton* m_showDescriptionBtn; + CUIStatic* m_descriptionStatic; + CUIEventsWnd* m_EventsWnd; + CUIStatic* m_stateStatic; + virtual void Init(CUIXml& xml, LPCSTR path); +public: + CUITaskSubItem(CUIEventsWnd* w); + virtual ~CUITaskSubItem(); + virtual void Update(); + virtual void SetGameTask(CGameTask* gt); + void OnActiveObjectiveClicked(); + void __stdcall OnShowDescriptionClicked(CUIWindow*, void*); + virtual void MarkSelected(bool b); + virtual bool OnDbClick(); +}; diff --git a/src/xrGame/xrGame.vcxproj b/src/xrGame/xrGame.vcxproj index b24dd1c2c20..1d5e8ad83eb 100644 --- a/src/xrGame/xrGame.vcxproj +++ b/src/xrGame/xrGame.vcxproj @@ -1274,6 +1274,9 @@ + + + @@ -1337,6 +1340,7 @@ + @@ -3106,6 +3110,9 @@ + + + @@ -3222,6 +3229,7 @@ + diff --git a/src/xrGame/xrGame.vcxproj.filters b/src/xrGame/xrGame.vcxproj.filters index dc88506d03f..90c68fc3124 100644 --- a/src/xrGame/xrGame.vcxproj.filters +++ b/src/xrGame/xrGame.vcxproj.filters @@ -2227,6 +2227,12 @@ {8ca91267-ead8-4233-af9a-9771664b4be5} + + {df96536d-0741-421a-864e-d0f2b39a10ce} + + + {3946c692-4a83-47fe-b1bf-95955dbafe2a} + @@ -6308,6 +6314,18 @@ Core\Common\ObjectFactory + + UI\Common\PDA\Events + + + UI\Common\PDA\Tasks + + + UI\Common\PDA\Encyclopedia + + + UI\Common\PDA\Encyclopedia + @@ -9495,6 +9513,18 @@ Core\Common\ObjectFactory + + UI\Common\PDA\Events + + + UI\Common\PDA\Tasks + + + UI\Common\PDA\Encyclopedia + + + UI\Common\PDA\Encyclopedia + diff --git a/src/xrServerEntities/inventory_space.h b/src/xrServerEntities/inventory_space.h index 8275b62cbe8..68a7a730c1f 100644 --- a/src/xrServerEntities/inventory_space.h +++ b/src/xrServerEntities/inventory_space.h @@ -24,23 +24,6 @@ enum SLOTS_COUNT }; -enum -{ - KNIFE_SLOT_SOC, - PISTOL_SLOT_SOC, - RIFLE_SLOT_SOC, - GRENADE_SLOT_SOC, - APPARATUS_SLOT_SOC, - BOLT_SLOT_SOC, - OUTFIT_SLOT_SOC, - PDA_SLOT_SOC, - DETECTOR_SLOT_SOC, - TORCH_SLOT_SOC, - ARTEFACT_SLOT_SOC, - SLOTS_TOTAL_SOC, - NO_ACTIVE_SLOT_SOC = 0xffffffff -} - #define RUCK_HEIGHT 280 #define RUCK_WIDTH 7 diff --git a/src/xrUICore/ScrollView/UITreeViewItem.cpp b/src/xrUICore/ScrollView/UITreeViewItem.cpp new file mode 100644 index 00000000000..841f0678e4c --- /dev/null +++ b/src/xrUICore/ScrollView/UITreeViewItem.cpp @@ -0,0 +1,574 @@ +//============================================================================= +// Filename: UITreeViewItem.cpp +// Created by Roman E. Marchenko, vortex@gsc-game.kiev.ua +// Copyright 2004. GSC Game World +// --------------------------------------------------------------------------- +// TreeView Item class +//============================================================================= + +#include "pch.hpp" +#include "UITreeViewItem.h" +#include "ListWnd/UIListWnd.h" + + +#define UNREAD_COLOR 0xff00ff00 +#define READ_COLOR 0xffffffff + +////////////////////////////////////////////////////////////////////////// + +// Смещение относительно родителя +const int subShift = 1; +const char * const treeItemBackgroundTexture = "ui\\ui_pda_over_list"; +// Цвет непрочитанного элемента +static const u32 unreadColor = 0xff00ff00; + +////////////////////////////////////////////////////////////////////////// + +CUITreeViewItem::CUITreeViewItem() : + isRoot(false), + isOpened(false), + iTextShift(0), + pOwner(NULL), + m_uUnreadedColor(UNREAD_COLOR), + m_uReadedColor(READ_COLOR), + m_bArticleRead(FALSE), + UIBkg("CUITreeViewItem") // Явная инициализация для STALKER +{ + AttachChild(&UIBkg); + UIBkg.InitTexture(treeItemBackgroundTexture); + UIBkg.TextureOff(); + UIBkg.SetTextureOffset(-20, 0); + SetHighlightText(false); + + m_bManualSetColor = false; +} + +////////////////////////////////////////////////////////////////////////// + +CUITreeViewItem::~CUITreeViewItem() +{ + DeleteAllSubItems(); +} + +////////////////////////////////////////////////////////////////////////// + +void CUITreeViewItem::OnRootChanged() +{ + xr_string str; + if (isRoot) + { + // Вставляем после последнего пробела перед текстом знак + или - + str = GetText(); + + xr_string::size_type pos = str.find_first_not_of(" "); + if (xr_string::npos == pos) pos = 0; + + if (pos == 0) + { + ++iTextShift; + str.insert(0, " "); + } + else + --pos; + + if (isOpened) + // Add minus sign + str.replace(pos, 1, "-"); + else + // Add plus sign + str.replace(pos, 1, "+"); + + inherited::SetText(str.c_str()); + } + else + { + str = GetText(); + // Remove "+/-" sign + xr_string::size_type pos = str.find_first_of("+-"); + + if (pos == 0) + { + for (int i = 0; i < iTextShift; ++i) + str.insert(pos, " "); + } + else + str.replace(pos, 1, " "); + + inherited::SetText(str.c_str()); + } +} + +////////////////////////////////////////////////////////////////////////// + +void CUITreeViewItem::OnOpenClose() +{ + // Если мы не являемся узлом дерева, значит ничего не делаем + if (!isRoot) return; + + xr_string str; + + str = GetText(); + xr_string::size_type pos = str.find_first_of("+-"); + + if (xr_string::npos != pos) + { + if (isOpened) + // Change minus sign to plus + str.replace(pos, 1, "-"); + else + // Change plus sign to minus + str.replace(pos, 1, "+"); + } + + inherited::SetText(str.c_str()); +} + +////////////////////////////////////////////////////////////////////////// + +void CUITreeViewItem::Open() +{ + // Если не рут или уже открыты, то ничего не делаем + if (!isRoot || isOpened) return; + isOpened = true; + + // Изменяем состояние + OnOpenClose(); + + // Аттачим все подэлементы к родтельскому листбоксу + CUIListWnd *pList = smart_cast(GetParent()); + + R_ASSERT(pList); + if (!pList) return; + + int pos = pList->GetItemPos(this); + + for (SubItems_it it = vSubItems.begin(); it != vSubItems.end(); ++it) + { + pList->AddItem(*it, ++pos); + } +} + +////////////////////////////////////////////////////////////////////////// + +void CUITreeViewItem::Close() +{ + // Если не рут или уже открыты, то ничего не делаем + if (!isRoot || !isOpened) return; + isOpened = false; + + // Изменяем состояние + OnOpenClose(); + + // Детачим все подэлементы + CUIListWnd *pList = smart_cast(GetParent()); + + R_ASSERT(pList); + if (!pList) return; + + int pos; + + // Сначала все закрыть + for (SubItems_it it = vSubItems.begin(); it != vSubItems.end(); ++it) + { + (*it)->Close(); + } + + // Затем все датачим + for (SubItems_it it = vSubItems.begin(); it != vSubItems.end(); ++it) + { + pos = pList->GetItemPos(*it); + pList->RemoveItem(pos); + } +} + +////////////////////////////////////////////////////////////////////////// + +void CUITreeViewItem::AddItem(CUITreeViewItem *pItem) +{ + R_ASSERT(pItem); + if (!pItem) return; + + pItem->SetTextShift(subShift + iTextShift); + + vSubItems.push_back(pItem); + pItem->SetAutoDelete(false); + + pItem->SetOwner(this); + pItem->SetText(pItem->GetText()); +} + +////////////////////////////////////////////////////////////////////////// + +void CUITreeViewItem::DeleteAllSubItems() +{ + for (SubItems_it it = vSubItems.begin(); it != vSubItems.end(); ++it) + { + CUIWindow *pWindow = (*it)->GetParent(); + + if (pWindow) + pWindow->DetachChild(*it); + + xr_delete(*it); + } + + vSubItems.clear(); +} + +////////////////////////////////////////////////////////////////////////// + +void CUITreeViewItem::SetRoot(bool set) +{ + if (isRoot) return; + + isRoot = set; + OnRootChanged(); +} + +////////////////////////////////////////////////////////////////////////// + +void CUITreeViewItem::SetText(LPCSTR str) +{ + xr_string s = str; + xr_string::size_type pos = s.find_first_not_of(" +-"); + + if (pos < static_cast(iTextShift)) + { + for (u32 i = 0; i < iTextShift - pos; ++i) + s.insert(0, " "); + } + else if (pos > static_cast(iTextShift)) + { + s.erase(0, pos - iTextShift); + } + + inherited::SetText(s.c_str()); +} + +////////////////////////////////////////////////////////////////////////// + +void CUITreeViewItem::SendMessage(CUIWindow* pWnd, s16 msg, void* pData) +{ + static CUITreeViewItem *pPrevFocusedItem = NULL; + + if (pWnd == this && BUTTON_CLICKED == msg) + { + if (IsRoot()) + { + IsOpened() ? Close() : Open(); + } + else + { + MarkArticleAsRead(true); + } + } + else if (pWnd == this && WINDOW_FOCUS_RECEIVED == msg) + { + UIBkg.TextureOn(); + + if (pPrevFocusedItem) + { + pPrevFocusedItem->UIBkg.TextureOff(); + } + pPrevFocusedItem = this; + } + else if (pWnd == this && WINDOW_FOCUS_LOST == msg) + { + UIBkg.TextureOff(); + pPrevFocusedItem = NULL; + } + else + inherited::SendMessage(pWnd, msg, pData); +} + +////////////////////////////////////////////////////////////////////////// + +CUITreeViewItem * CUITreeViewItem::Find(LPCSTR text) const +{ + // Пробегаемся по списку подчиненных элементов, и ищем элемент с заданным текстом + // Если среди подч. эл-тов есть root'ы, то ищем рекурсивно в них + CUITreeViewItem *pResult = NULL; + xr_string caption; + + for (SubItems::const_iterator it = vSubItems.begin(); it != vSubItems.end(); ++it) + { + caption = (*it)->GetText(); + xr_string::size_type pos = caption.find_first_not_of(" +-"); + if (pos != xr_string::npos) + { + caption.erase(0, pos); + } + + if (xr_strcmp(caption.c_str(), text) == 0) + pResult = *it; + + if ((*it)->IsRoot() && !pResult) + pResult = (*it)->Find(text); + + if (pResult) break; + } + + return pResult; +} + +////////////////////////////////////////////////////////////////////////// + +CUITreeViewItem * CUITreeViewItem::Find(int value) const +{ + CUITreeViewItem *pResult = NULL; + + for (SubItems::const_iterator it = vSubItems.begin(); it != vSubItems.end(); ++it) + { + if ((*it)->GetValue() == value) pResult = *it; + + if ((*it)->IsRoot() && !pResult) + pResult = (*it)->Find(value); + + if (pResult) break; + } + + return pResult; +} + +////////////////////////////////////////////////////////////////////////// + +CUITreeViewItem * CUITreeViewItem::Find(CUITreeViewItem * pItem) const +{ + CUITreeViewItem *pResult = NULL; + + for (SubItems::const_iterator it = vSubItems.begin(); it != vSubItems.end(); ++it) + { + if ((*it)->IsRoot() && !pResult) + pResult = (*it)->Find(pItem); + else + if (pItem == *it) pResult = *it; + + if (pResult) break; + } + + return pResult; +} + +////////////////////////////////////////////////////////////////////////// + +xr_string CUITreeViewItem::GetHierarchyAsText() +{ + xr_string name; + + if (GetOwner()) + { + name = GetOwner()->GetHierarchyAsText(); + } + + xr_string::size_type prevPos = name.size() + 1; + name += static_cast("/") + static_cast(GetText()); + + // Удаляем мусор: [ +-] + xr_string::size_type pos = name.find_first_not_of("/ +-", prevPos); + if (xr_string::npos != pos) + { + name.erase(prevPos, pos - prevPos); + } + + return name; +} + +////////////////////////////////////////////////////////////////////////// + +void CUITreeViewItem::MarkArticleAsRead(bool value) +{ + // Если элемент рутовый, то мы его маркаем его, и все чилды + if (IsRoot()) + { + m_bArticleRead = value; + if(!m_bManualSetColor) + SetItemColor(); + + for (SubItems_it it = vSubItems.begin(); it != vSubItems.end(); ++it) + { + (*it)->m_bArticleRead = value; + (*it)->SetItemColor(); + if ((*it)->IsRoot()) + (*it)->MarkArticleAsRead(value); + } + } + else + { + // Если же нет, то маркаем себя и говорим проверить свой парентовый элемент + m_bArticleRead = value; + if(!m_bManualSetColor) + SetItemColor(); + CheckParentMark(GetOwner()); + } +} + +////////////////////////////////////////////////////////////////////////// + +void CUITreeViewItem::CheckParentMark(CUITreeViewItem *pOwner) +{ + // Берем рута, смотрим на его чилдов, и если среди них есть хоть 1 + // непрочитанный, то маркаем себя как непрочитанный, и говорим провериться выше. + bool f = false; + if (pOwner && pOwner->IsRoot()) + { + for (SubItems_it it = pOwner->vSubItems.begin(); it != pOwner->vSubItems.end(); ++it) + { + if (!(*it)->IsArticleReaded()) + { + pOwner->m_bArticleRead = false; + pOwner->SetItemColor(); + f = true; + } + } + + if (!f) + { + // Если мы тут, то все артиклы прочитанны, и можно маркнуть себя как прочитанная ветвь + pOwner->m_bArticleRead = true; + pOwner->SetItemColor(); + } + + pOwner->CheckParentMark(pOwner->GetOwner()); + } +} + +////////////////////////////////////////////////////////////////////////// +// Standalone function for tree hierarchy creation +////////////////////////////////////////////////////////////////////////// + +void CreateTreeBranch(shared_str nesting, shared_str leafName, CUIListWnd *pListToAdd, int leafProperty, + CGameFont *pRootFont, u32 rootColor, CGameFont *pLeafFont, u32 leafColor, bool markRead) +{ + // Nested function emulation + class AddTreeTail_ + { + private: + CGameFont *pRootFnt; + u32 rootItemColor; + public: + AddTreeTail_(CGameFont *f, u32 cl) + : pRootFnt (f), + rootItemColor (cl) + {} + + CUITreeViewItem * operator () (GroupTree_it it, GroupTree &cont, CUITreeViewItem *pItemToIns) + { + // Вставляем иерархию разделов в энциклопедию + CUITreeViewItem *pNewItem = NULL; + + for (GroupTree_it it2 = it; it2 != cont.end(); ++it2) + { + pNewItem = xr_new(); + pItemToIns->AddItem(pNewItem); + pNewItem->SetFont(pRootFnt); + pNewItem->SetText(*(*it2)); + pNewItem->SetReadedColor(rootItemColor); + pNewItem->SetRoot(true); + pItemToIns = pNewItem; + } + + return pNewItem; + } + } AddTreeTail(pRootFont, rootColor); + + //----------------------------------------------------------------------------- + // Function body + //----------------------------------------------------------------------------- + + // Начинаем алгоритм определения группы вещи в иерархии энциклопедии + R_ASSERT(*nesting); + R_ASSERT(pListToAdd); + R_ASSERT(pLeafFont); + R_ASSERT(pRootFont); + xr_string group = *nesting; + + // Парсим строку группы для определения вложенности + GroupTree groupTree; + + xr_string::size_type pos; + xr_string oneLevel; + + while (true) + { + pos = group.find('/'); + if (pos != xr_string::npos) + { + oneLevel.assign(group, 0, pos); + shared_str str(oneLevel.c_str()); + groupTree.push_back(CStringTable().translate(str)); + group.erase(0, pos + 1); + } + else + { + groupTree.push_back(CStringTable().translate(group.c_str())); + break; + } + } + + // Теперь ищем нет ли затребованных групп уже в наличии + CUITreeViewItem *pTVItem = NULL, *pTVItemChilds = NULL; + bool status = false; + + // Для всех рутовых элементов + for (int i = 0; i < pListToAdd->GetItemsCount(); ++i) + { + pTVItem = smart_cast(pListToAdd->GetItem(i)); + R_ASSERT(pTVItem); + + pTVItem->Close(); + + xr_string caption = pTVItem->GetText(); + // Remove "+" sign + caption.erase(0, 1); + + // Ищем не содержит ли он данной иерархии и добавляем новые элементы если не найдено + if (0 == xr_strcmp(caption.c_str(), *groupTree.front())) + { + // Уже содержит. Надо искать глубже + pTVItemChilds = pTVItem; + for (GroupTree_it it = groupTree.begin() + 1; it != groupTree.end(); ++it) + { + pTVItem = pTVItemChilds->Find(*(*it)); + // Не нашли, надо вставлять хвост списка вложенности + if (!pTVItem) + { + pTVItemChilds = AddTreeTail(it, groupTree, pTVItemChilds); + status = true; + break; + } + pTVItemChilds = pTVItem; + } + } + + if (status) break; + } + + // Прошли все существующее дерево, и не нашли? Тогда добавляем новую иерархию + if (!pTVItemChilds) + { + pTVItemChilds = xr_new(); + pTVItemChilds->SetFont(pRootFont); + pTVItemChilds->SetText(*groupTree.front()); + pTVItemChilds->SetReadedColor(rootColor); + pTVItemChilds->SetRoot(true); + pListToAdd->AddItem(pTVItemChilds); + + // Если в списке вложенности 1 элемент, то хвоста нет, и соответственно ничего не добавляем + if (groupTree.size() > 1) + pTVItemChilds = AddTreeTail(groupTree.begin() + 1, groupTree, pTVItemChilds); + } + + // К этому моменту pTVItemChilds обязательно должна быть не NULL + R_ASSERT(pTVItemChilds); + + // Cначала проверяем нет ли записи с таким названием, и добавляем если нет + // if (!pTVItemChilds->Find(*name)) + // { + pTVItem = xr_new(); + pTVItem->SetFont(pLeafFont); + pTVItem->SetReadedColor(leafColor); + pTVItem->SetText(*CStringTable().translate(*leafName)); + pTVItem->SetValue(leafProperty); + pTVItemChilds->AddItem(pTVItem); + pTVItem->MarkArticleAsRead(markRead); + // } +} diff --git a/src/xrUICore/ScrollView/UITreeViewItem.h b/src/xrUICore/ScrollView/UITreeViewItem.h new file mode 100644 index 00000000000..24b6b7a1a45 --- /dev/null +++ b/src/xrUICore/ScrollView/UITreeViewItem.h @@ -0,0 +1,129 @@ +//============================================================================= +// Filename: UITreeViewItem.h +// Created by Roman E. Marchenko, vortex@gsc-game.kiev.ua +// Copyright 2004. GSC Game World +// --------------------------------------------------------------------------- +// TreeView Item class +//============================================================================= + +#ifndef UI_TREE_VIEW_ITEM_H_ +#define UI_TREE_VIEW_ITEM_H_ + +#pragma once + +#include "xrUICore\ListWnd\UIListItem.h" + +class CUIListWnd; + +class XRUICORE_API CUITreeViewItem : public CUIListItem +{ +protected: + typedef CUIListItem inherited; + // Являемся ли мы началом подыерархии + bool isRoot; + // Если мы рут, то этот флаг показывает открыта наша подыерархия или нет + bool isOpened; + // Смещение в пробелах + int iTextShift; + // Кому мы пренадлежим + CUITreeViewItem* pOwner; +public: + void SetRoot(bool set); + bool IsRoot() const { return isRoot; } + + // Устанавливаем смещение текста + void SetTextShift(int delta) { iTextShift += delta; } + + // Владелец + CUITreeViewItem* GetOwner() const { return pOwner; } + void SetOwner(CUITreeViewItem* owner) { pOwner = owner; } +protected: + // Функция вызываемая при изменении свойства рута + // для изменения визуального представления себя + virtual void OnRootChanged(); +public: + // Раксрыть/свернуть локальнцю иерархию + void Open(); + void Close(); + bool IsOpened() const { return isOpened; } +protected: + // Функция вызываемая при изменении cостояния открыто/закрыто + // для изменения визуального представления себя + virtual void OnOpenClose(); +public: + + // Список элементов, которые уровнем ниже нас + typedef xr_vector SubItems; + typedef SubItems::iterator SubItems_it; + SubItems vSubItems; + + CUIStatic UIBkg; + + // Добавить элемент + void AddItem(CUITreeViewItem* pItem); + // Удалить все + void DeleteAllSubItems(); + // Найти элемент с заданным именем + // Return: указатель на элемент, если нашли, либо NULL в противном случае + CUITreeViewItem* Find(LPCSTR text) const; + // Найти элемент с заданным значением + // Return: указатель на элемент, если нашли, либо NULL в противном случае + CUITreeViewItem* Find(int value) const; + // Найти заданный элемент + // Return: указатель на элемент, если нашли, либо NULL в противном случае + CUITreeViewItem* Find(CUITreeViewItem* pItem) const; + // Вернуть иерархию от верха до текущего элемента в виде строки-пути + // Рутовые элементы заканчиваются символом "/" + xr_string GetHierarchyAsText(); + + // Redefine some stuff + // ATTENTION! Для корректного функционирования значков [+-] вызов SetText + // Должен предшествовать SetRoot + virtual void SetText(LPCSTR str); + virtual void SendMessage(CUIWindow* pWnd, s16 msg, void* pData); + + // Ctor and Dtor + CUITreeViewItem(); + virtual ~CUITreeViewItem(); + + // Устанавливаем цвет текста в зависимости от того, прочитан ли артикл + void MarkArticleAsRead(bool value); + bool IsArticleReaded() { return m_bArticleRead; } + // Цвет текста когда артикл не прочитан и не прочитан + void SetReadedColor(u32 cl) { m_uReadedColor = cl; } + void SetUnreadedColor(u32 cl) { m_uUnreadedColor = cl; } + void SetManualSetColor(bool val) { m_bManualSetColor = val; } + // Устанавливаем цвет в зависимости от состояния элемента + void SetItemColor() + { + m_bArticleRead ? SetTextColor(m_uReadedColor) : SetTextColor(m_uUnreadedColor); + } + +private: + friend class CUIListWnd; + + // Применить состояние вверх по иерархии + void CheckParentMark(CUITreeViewItem* pOwner); + // Цвет текста когда артикл не прочитан + u32 m_uUnreadedColor; + // Цвет текста когда артикл не прочитан + u32 m_uReadedColor; + // Флажек состояния прочитки + bool m_bArticleRead; + // Если true, то MarkArticleAsRead не будет вызывать + // SetItemColor() + bool m_bManualSetColor; +}; + +////////////////////////////////////////////////////////////////////////// +// Function for automatic tree hierarchy creation +////////////////////////////////////////////////////////////////////////// + +DEF_VECTOR(GroupTree, shared_str); + +////////////////////////////////////////////////////////////////////////// + +XRUICORE_API void CreateTreeBranch(shared_str nestingTree, shared_str leafName, CUIListWnd* pListToAdd, int leafProperty, + CGameFont* pRootFont, u32 rootColor, CGameFont* pLeafFont, u32 leafColor, bool markRead); + +#endif //UI_TREE_VIEW_ITEM_H_ diff --git a/src/xrUICore/Windows/UIFrameLineWnd.h b/src/xrUICore/Windows/UIFrameLineWnd.h index d6d7eba45b7..6c7216c6f46 100644 --- a/src/xrUICore/Windows/UIFrameLineWnd.h +++ b/src/xrUICore/Windows/UIFrameLineWnd.h @@ -1,5 +1,6 @@ #pragma once #include "UIWindow.h" +#include "../Static/UIStatic.h" class XRUICORE_API CUIFrameLineWnd : public CUIWindow, public ITextureOwner { @@ -58,7 +59,8 @@ class XRUICORE_API CUIFrameLineWnd : public CUIWindow, public ITextureOwner pcstr GetDebugType() override { return "CUIFrameLineWnd"; } bool FillDebugTree(const CUIDebugState& debugState) override; void FillDebugInfo() override; - + CUIStatic* UITitleText; + CUIStatic* GetTitleStatic() { return UITitleText; }; protected: bool inc_pos(Frect& rect, int counter, int i, Fvector2& LTp, Fvector2& RBp, Fvector2& LTt, Fvector2& RBt); void DrawElements(); diff --git a/src/xrUICore/xrUICore.vcxproj b/src/xrUICore/xrUICore.vcxproj index 0b9e9b29c63..22d12621936 100644 --- a/src/xrUICore/xrUICore.vcxproj +++ b/src/xrUICore/xrUICore.vcxproj @@ -95,6 +95,7 @@ + @@ -159,6 +160,7 @@ + diff --git a/src/xrUICore/xrUICore.vcxproj.filters b/src/xrUICore/xrUICore.vcxproj.filters index 75b334576b2..d37deed5844 100644 --- a/src/xrUICore/xrUICore.vcxproj.filters +++ b/src/xrUICore/xrUICore.vcxproj.filters @@ -242,6 +242,9 @@ + + ScrollView + @@ -419,6 +422,9 @@ + + ScrollView + From f19dd1fbed48e9582b5308f08bccd685587d502b Mon Sep 17 00:00:00 2001 From: werasik2aa Date: Sun, 14 Sep 2025 04:14:30 +0700 Subject: [PATCH 06/12] PDA TASK SUB TASK NAMES --- src/xrGame/ui/UIEventsWnd.cpp | 12 ++++++------ src/xrGame/ui/UIPdaWnd.cpp | 7 ++++++- src/xrGame/ui/UITaskWnd.cpp | 12 ++++-------- src/xrGame/ui/UITaskWnd.h | 5 ++--- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/xrGame/ui/UIEventsWnd.cpp b/src/xrGame/ui/UIEventsWnd.cpp index f40791ab4c5..570a77942ff 100644 --- a/src/xrGame/ui/UIEventsWnd.cpp +++ b/src/xrGame/ui/UIEventsWnd.cpp @@ -173,12 +173,12 @@ void CUIEventsWnd::ReloadList(bool bClearOnly) if (i == 0) { CUITaskRootItem* pTaskItem = xr_new(this); - pTaskItem->SetGameTask(task); + pTaskItem->SetGameTask(task, i); m_ListWnd->AddWindow(pTaskItem, true); } else { CUITaskSubItem* pTaskItem = xr_new(this); - pTaskItem->SetGameTask(task); + pTaskItem->SetGameTask(task, i); m_ListWnd->AddWindow(pTaskItem, true); } } @@ -201,11 +201,11 @@ bool CUIEventsWnd::Filter(CGameTask* t) switch (m_currFilter) { case CUIEventsWnd::eActiveTask: - return task_state == eTaskStateInProgress; + return task_state & eTaskStateInProgress; case CUIEventsWnd::eAccomplishedTask: - return task_state == eTaskStateCompleted; + return task_state & eTaskStateCompleted; case CUIEventsWnd::eFailedTask: - return task_state == eTaskStateFail; + return task_state & eTaskStateFail; case CUIEventsWnd::eMaxTask: return false; default: @@ -289,7 +289,7 @@ void CUIEventsWnd::ShowDescription(CGameTask* t, int idx) int sz = m_ListWnd->GetSize(); for (int i = 0; i < sz; ++i) { - CUITaskItem* itm = (CUITaskItem*)m_ListWnd->GetItem(i); + CUITaskSubItem* itm = (CUITaskSubItem*)m_ListWnd->GetItem(i); if (itm->OwnerTask() == t && itm->OwnerTask()->ActiveObjective().m_idx == idx) itm->MarkSelected(true); else diff --git a/src/xrGame/ui/UIPdaWnd.cpp b/src/xrGame/ui/UIPdaWnd.cpp index 5da893280c3..a11fdde385d 100644 --- a/src/xrGame/ui/UIPdaWnd.cpp +++ b/src/xrGame/ui/UIPdaWnd.cpp @@ -134,6 +134,10 @@ void CUIPdaWnd::Init() pUIEncyclopediaWnd = xr_new(); if (!pUIEncyclopediaWnd->Init()) xr_delete(pUIEncyclopediaWnd); + + pUIActorInfo = xr_new(); + if (!pUIActorInfo->Init()) + xr_delete(pUIActorInfo); } else { @@ -298,7 +302,8 @@ void CUIPdaWnd::SetActiveSubdialog(const shared_str& section) { "eptStatistics", pUIActorInfo }, { "eptRanking", pUIRankingWnd }, { "eptLogs", pUILogsWnd }, - { "eptEncyclopedia", pUIEventsWnd }, + { "eptEncyclopedia", pUIEncyclopediaWnd }, + { "eptContacts", pUIEventsWnd} }; for (const auto& [id, wnd] : availableWindowsList) diff --git a/src/xrGame/ui/UITaskWnd.cpp b/src/xrGame/ui/UITaskWnd.cpp index b0e3949e425..9b68ef2d0be 100644 --- a/src/xrGame/ui/UITaskWnd.cpp +++ b/src/xrGame/ui/UITaskWnd.cpp @@ -487,9 +487,6 @@ void CUITaskItem::Update() } void CUITaskItem::OnMouseScroll(float iDirection) {} -void CUITaskItem::MarkSelected(bool b) { - //m_pStoryLineTaskItem->SetButtonMode(b ? CUIButton::BUTTON_PUSHED : CUIButton::BUTTON_NORMAL); -} bool CUITaskItem::OnMouseAction(float x, float y, EUIMessages mouse_action) { if (inherited::OnMouseAction(x, y, mouse_action)) @@ -566,12 +563,12 @@ void CUITaskRootItem::Init(CUIXml& xml, LPCSTR path) xml_init.Init3tButton(uiXml, "task_root_item:switch_description_btn", 0, m_switchDescriptionBtn); } -void CUITaskRootItem::SetGameTask(CGameTask* gt) +void CUITaskRootItem::SetGameTask(CGameTask* gt, u16 obj_id) { inherited::InitTask(gt); CStringTable stbl; - SGameTaskObjective obj = OwnerTask()->ActiveObjective(); + SGameTaskObjective obj = OwnerTask()->Objective(obj_id); m_taskImage->InitTexture(*OwnerTask()->m_icon_texture_name); @@ -700,7 +697,6 @@ void CUITaskSubItem::Init(CUIXml& xml, LPCSTR path) AddCallback(m_showDescriptionBtn, BUTTON_CLICKED, CUIWndCallback::void_function(this, &CUITaskSubItem::OnShowDescriptionClicked)); - CUIXmlInit xml_init; xml_init.InitWindow(uiXml, "task_sub_item", 0, this); xml_init.InitStatic(uiXml, "task_sub_item:state_image", 0, m_stateStatic); @@ -714,12 +710,12 @@ void CUITaskSubItem::Init(CUIXml& xml, LPCSTR path) m_accomplished_color = xml_init.GetColor(uiXml, "task_sub_item:description:text_colors:accomplished", 0, 0x00); } -void CUITaskSubItem::SetGameTask(CGameTask* gt) +void CUITaskSubItem::SetGameTask(CGameTask* gt, u16 obj_id) { inherited::InitTask(gt); CStringTable stbl; - SGameTaskObjective obj = OwnerTask()->ActiveObjective(); + SGameTaskObjective obj = OwnerTask()->Objective(obj_id); m_descriptionStatic->SetText(*stbl.translate(obj.m_Description)); m_descriptionStatic->AdjustHeightToText(); diff --git a/src/xrGame/ui/UITaskWnd.h b/src/xrGame/ui/UITaskWnd.h index 899a1afb78c..f8c4af3e18d 100644 --- a/src/xrGame/ui/UITaskWnd.h +++ b/src/xrGame/ui/UITaskWnd.h @@ -109,7 +109,6 @@ class CUITaskItem : public CUIWindow virtual void Update(); virtual void OnMouseScroll(float iDirection); virtual bool OnMouseAction(float x, float y, EUIMessages mouse_action); - virtual void MarkSelected(bool b); virtual void SendMessage(CUIWindow* pWnd, s16 msg, void* pData); void Init(CUIXml& uiXml, LPCSTR path); @@ -144,7 +143,7 @@ class CUITaskRootItem :public CUITaskItem, public CUIWndCallback CUITaskRootItem(CUIEventsWnd* w); virtual ~CUITaskRootItem(); virtual void Update(); - virtual void SetGameTask(CGameTask* gt); + virtual void SetGameTask(CGameTask* gt, u16 ob); void __stdcall OnSwitchDescriptionClicked(CUIWindow*, void*); virtual void MarkSelected(bool b); @@ -170,7 +169,7 @@ class CUITaskSubItem :public CUITaskItem, public CUIWndCallback CUITaskSubItem(CUIEventsWnd* w); virtual ~CUITaskSubItem(); virtual void Update(); - virtual void SetGameTask(CGameTask* gt); + virtual void SetGameTask(CGameTask* gt, u16 ob); void OnActiveObjectiveClicked(); void __stdcall OnShowDescriptionClicked(CUIWindow*, void*); virtual void MarkSelected(bool b); From b9871e9b7a3833d4d074a94b3a91aa7402530a34 Mon Sep 17 00:00:00 2001 From: werasik2aa Date: Sun, 14 Sep 2025 04:16:43 +0700 Subject: [PATCH 07/12] Tab filter crash fix --- src/xrUICore/Windows/UIWindow.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/xrUICore/Windows/UIWindow.cpp b/src/xrUICore/Windows/UIWindow.cpp index b027e93af35..1f7ec18ddda 100644 --- a/src/xrUICore/Windows/UIWindow.cpp +++ b/src/xrUICore/Windows/UIWindow.cpp @@ -81,8 +81,7 @@ void CUIWindow::AttachChild(CUIWindow* pChild) void CUIWindow::DetachChild(CUIWindow* pChild) { - R_ASSERT(pChild); - if (NULL == pChild) + if (!pChild) return; if (m_pMouseCapturer == pChild) @@ -90,8 +89,8 @@ void CUIWindow::DetachChild(CUIWindow* pChild) //. SafeRemoveChild (pChild); auto it = std::find(m_ChildWndList.begin(), m_ChildWndList.end(), pChild); - R_ASSERT(it != m_ChildWndList.end()); - m_ChildWndList.erase(it); + if (it != m_ChildWndList.end()) + m_ChildWndList.erase(it); pChild->SetParent(NULL); From 91d03b79c8bfe473d5def6e4ecd59387efc8d81e Mon Sep 17 00:00:00 2001 From: werasik2aa Date: Sun, 14 Sep 2025 04:21:21 +0700 Subject: [PATCH 08/12] AddSOC --- src/xrGame/ui/UIPdaWnd.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/xrGame/ui/UIPdaWnd.cpp b/src/xrGame/ui/UIPdaWnd.cpp index a11fdde385d..dd738020d54 100644 --- a/src/xrGame/ui/UIPdaWnd.cpp +++ b/src/xrGame/ui/UIPdaWnd.cpp @@ -302,16 +302,36 @@ void CUIPdaWnd::SetActiveSubdialog(const shared_str& section) { "eptStatistics", pUIActorInfo }, { "eptRanking", pUIRankingWnd }, { "eptLogs", pUILogsWnd }, - { "eptEncyclopedia", pUIEncyclopediaWnd }, - { "eptContacts", pUIEventsWnd} }; - for (const auto& [id, wnd] : availableWindowsList) + const std::tuple availableWindowsList_SOC[] = { - if (section == id && wnd) + {"eptTasks", pUIEventsWnd}, + {"eptMap", pUIMapWnd}, + {"eptDiary", pUIEncyclopediaWnd}, + {"eptContacts", pUIEncyclopediaWnd}, + {"eptStalkersRanking", pUIEncyclopediaWnd}, + {"eptStatistics", pUIActorInfo}, + {"eptEncyclopedia", pUIEncyclopediaWnd}, + }; + if (ShadowOfChernobylMode) { + for (const auto& [id, wnd] : availableWindowsList_SOC) + { + if (section == id && wnd) + { + m_pActiveDialog = wnd; + break; + } + } + } + else { + for (const auto& [id, wnd] : availableWindowsList) { - m_pActiveDialog = wnd; - break; + if (section == id && wnd) + { + m_pActiveDialog = wnd; + break; + } } } From 783e96ea36a089899b0d2bf8d147a3cf9fdb242a Mon Sep 17 00:00:00 2001 From: werasik2aa Date: Sun, 14 Sep 2025 04:57:27 +0700 Subject: [PATCH 09/12] SOC->BOLT draw fix --- src/xrGame/GameTask.cpp | 14 ++++++------- src/xrGame/Inventory.cpp | 27 ++++++++++++------------- src/xrGame/ui/UIPdaWnd.cpp | 40 ++++++++++++++++++-------------------- 3 files changed, 38 insertions(+), 43 deletions(-) diff --git a/src/xrGame/GameTask.cpp b/src/xrGame/GameTask.cpp index 967fe321c9c..a96246d89a6 100644 --- a/src/xrGame/GameTask.cpp +++ b/src/xrGame/GameTask.cpp @@ -150,8 +150,8 @@ void CGameTask::Load(const TASK_ID& id) //* objective.m_def_location_enabled = !gameTaskXml.ReadInt(l_root, "map_location_hidden", 0, 0); - [[maybe_unused]] const bool b1 = (0 == objective.m_map_location.size()); - [[maybe_unused]] const bool b2 = (nullptr == object_story_id); + const bool b1 = (0 == objective.m_map_location.size()); + const bool b2 = (nullptr == object_story_id); VERIFY3(b1 == b2, "check [map_location_type] and [object_story_id] fields in objective definition for: ", objective.m_Description.c_str()); @@ -211,12 +211,12 @@ void CGameTask::Load(const TASK_ID& id) //------function_complete { - const int info_num = gameTaskXml.GetNodesNum(l_root, "function_complete"); + const int info_num = gameTaskXml.GetNodesNum(l_root, "function_call_complete"); objective.m_complete_lua_functions.resize(info_num); for (int j = 0; j < info_num; ++j) { cpcstr str = gameTaskXml.Read(l_root, "function_complete", j, nullptr); - [[maybe_unused]] const bool functor_exists = GEnv.ScriptEngine->functor(str, objective.m_complete_lua_functions[j]); + const bool functor_exists = GEnv.ScriptEngine->functor(str, objective.m_complete_lua_functions[j]); THROW3(functor_exists, "Cannot find script function described in task objective ", str); } } @@ -228,7 +228,7 @@ void CGameTask::Load(const TASK_ID& id) for (int j = 0; j < info_num; ++j) { cpcstr str = gameTaskXml.Read(l_root, "function_fail", j, nullptr); - [[maybe_unused]] const bool functor_exists = GEnv.ScriptEngine->functor(str, objective.m_fail_lua_functions[j]); + const bool functor_exists = GEnv.ScriptEngine->functor(str, objective.m_fail_lua_functions[j]); THROW3(functor_exists, "Cannot find script function described in task objective ", str); } } @@ -240,7 +240,7 @@ void CGameTask::Load(const TASK_ID& id) for (int i = 0; i < info_num; ++i) { cpcstr str = gameTaskXml.Read(l_root, "function_call_complete", i, nullptr); - [[maybe_unused]] const bool functor_exists = GEnv.ScriptEngine->functor(str, objective.m_lua_functions_on_complete[i]); + const bool functor_exists = GEnv.ScriptEngine->functor(str, objective.m_lua_functions_on_complete[i]); THROW3(functor_exists, "Cannot find script function described in task objective ", str); } } @@ -252,7 +252,7 @@ void CGameTask::Load(const TASK_ID& id) for (int j = 0; j < info_num; ++j) { cpcstr str = gameTaskXml.Read(l_root, "function_call_fail", j, nullptr); - [[maybe_unused]] const bool functor_exists = GEnv.ScriptEngine->functor(str, objective.m_lua_functions_on_fail[j]); + const bool functor_exists = GEnv.ScriptEngine->functor(str, objective.m_lua_functions_on_fail[j]); THROW3(functor_exists, "Cannot find script function described in task objective ", str); } } diff --git a/src/xrGame/Inventory.cpp b/src/xrGame/Inventory.cpp index ff39a1707e8..8ea5e4eae40 100644 --- a/src/xrGame/Inventory.cpp +++ b/src/xrGame/Inventory.cpp @@ -65,30 +65,27 @@ CInventory::CInventory() m_slots.emplace_back(CInventorySlot{}); // Dynamically create as many slots as we may define in system.ltx - u16 i = 0; - do + u32 maxSlot = 0; + for (u32 i = 0; i < slotsCount + 1; ++i) { - ++i; - string256 slot_persistent; string256 slot_active; xr_sprintf(slot_persistent, "slot_persistent_%d", i); xr_sprintf(slot_active, "slot_active_%d", i); - if (!pSettings->line_exist("inventory", slot_persistent)) - { - --i; - break; - } + if (pSettings->line_exist("inventory", slot_persistent)) { - const bool isPersistent = pSettings->r_bool("inventory", slot_persistent); - const bool isActive = pSettings->read_if_exists("inventory", slot_active, - ShadowOfChernobylMode ? defaultSlotActiveness[i] : false); + const bool isPersistent = pSettings->r_bool("inventory", slot_persistent); + const bool isActive = pSettings->read_if_exists("inventory", slot_active, + ShadowOfChernobylMode ? defaultSlotActiveness[i] : false); + + m_slots.emplace_back(CInventorySlot{ nullptr, isPersistent, isActive }); + maxSlot = i; + } + } - m_slots.emplace_back(CInventorySlot{ nullptr, isPersistent, isActive }); - } while (true); + m_iLastSlot = maxSlot; - m_iLastSlot = i; #ifndef MASTER_GOLD if (m_iLastSlot != slotsCount) { diff --git a/src/xrGame/ui/UIPdaWnd.cpp b/src/xrGame/ui/UIPdaWnd.cpp index dd738020d54..ad650f25965 100644 --- a/src/xrGame/ui/UIPdaWnd.cpp +++ b/src/xrGame/ui/UIPdaWnd.cpp @@ -293,28 +293,17 @@ void CUIPdaWnd::SetActiveSubdialog(const shared_str& section) UIMainPdaFrame->SetKeyboardCapture(nullptr, true); m_pActiveDialog->Show(false); } - - const std::tuple availableWindowsList[] = - { - { "eptMap", pUIMapWnd }, - { "eptTasks", pUITaskWnd }, - { "eptFractionWar", pUIFactionWarWnd }, - { "eptStatistics", pUIActorInfo }, - { "eptRanking", pUIRankingWnd }, - { "eptLogs", pUILogsWnd }, - }; - - const std::tuple availableWindowsList_SOC[] = - { - {"eptTasks", pUIEventsWnd}, - {"eptMap", pUIMapWnd}, - {"eptDiary", pUIEncyclopediaWnd}, - {"eptContacts", pUIEncyclopediaWnd}, - {"eptStalkersRanking", pUIEncyclopediaWnd}, - {"eptStatistics", pUIActorInfo}, - {"eptEncyclopedia", pUIEncyclopediaWnd}, - }; if (ShadowOfChernobylMode) { + const std::tuple availableWindowsList_SOC[] = + { + {"eptTasks", pUIEventsWnd}, + {"eptMap", pUIMapWnd}, + {"eptDiary", pUIEncyclopediaWnd}, + {"eptContacts", pUIEncyclopediaWnd}, + {"eptStalkersRanking", pUIEncyclopediaWnd}, + {"eptStatistics", pUIActorInfo}, + {"eptEncyclopedia", pUIEncyclopediaWnd}, + }; for (const auto& [id, wnd] : availableWindowsList_SOC) { if (section == id && wnd) @@ -325,6 +314,15 @@ void CUIPdaWnd::SetActiveSubdialog(const shared_str& section) } } else { + const std::tuple availableWindowsList[] = + { + { "eptMap", pUIMapWnd }, + { "eptTasks", pUITaskWnd }, + { "eptFractionWar", pUIFactionWarWnd }, + { "eptStatistics", pUIActorInfo }, + { "eptRanking", pUIRankingWnd }, + { "eptLogs", pUILogsWnd }, + }; for (const auto& [id, wnd] : availableWindowsList) { if (section == id && wnd) From a10b9f2aa8b572864ee9aba8761389c1954b1ba1 Mon Sep 17 00:00:00 2001 From: werasik2aa Date: Mon, 15 Sep 2025 21:10:51 +0700 Subject: [PATCH 10/12] Diareya SOC (ONLY WINDOW) --- src/xrGame/ui/UIDiaryWnd.cpp | 341 ++++++++++++++++++++++++++++ src/xrGame/ui/UIDiaryWnd.h | 106 +++++---- src/xrGame/ui/UIEncyclopediaWnd.cpp | 5 +- src/xrGame/ui/UIEventsWnd.cpp | 2 +- src/xrGame/ui/UILogsWnd.h | 3 +- src/xrGame/ui/UINewsItemWnd.cpp | 13 ++ src/xrGame/ui/UINewsItemWnd.h | 4 +- src/xrGame/ui/UIPdaWnd.cpp | 70 +++--- src/xrGame/ui/UIPdaWnd.h | 5 +- src/xrGame/xrGame.vcxproj | 2 + src/xrGame/xrGame.vcxproj.filters | 9 + 11 files changed, 465 insertions(+), 95 deletions(-) create mode 100644 src/xrGame/ui/UIDiaryWnd.cpp diff --git a/src/xrGame/ui/UIDiaryWnd.cpp b/src/xrGame/ui/UIDiaryWnd.cpp new file mode 100644 index 00000000000..9e800099888 --- /dev/null +++ b/src/xrGame/ui/UIDiaryWnd.cpp @@ -0,0 +1,341 @@ +#include "stdafx.h" +#include "UIDiaryWnd.h" +#include "xrUICore/Windows/UIFrameWindow.h" +#include "xrUICore/Windows/UIFrameLineWnd.h" +#include "UINewsItemWnd.h" +#include "xrUICore/Static/UIAnimatedStatic.h" +#include "UIXmlInit.h" +#include "xrUICore/TabControl/UITabControl.h" +#include "xrUICore/TabControl/UITabButton.h" +#include "xrUICore/ScrollView/UIScrollView.h" +#include "xrUICore/ListWnd/UIListWnd.h" +#include "xrUICore/ScrollView/UITreeViewItem.h" +#include "UIEncyclopediaArticleWnd.h" +#include "../level.h" +#include "../actor.h" +#include "../alife_registry_wrappers.h" +#include "../encyclopedia_article.h" + +#define DIAREYA_INFO "events_new.xml" +#define DIAREYA_NEWS "news.xml" +CUIDiaryWnd::CUIDiaryWnd() : CUIWindow("CUIDiaryWnd"), m_currFilter(eNone) +{ + +} + +CUIDiaryWnd::~CUIDiaryWnd() +{ + delete_data(m_UINewsWnd); + delete_data(m_SrcListWnd); + delete_data(m_DescrView); + delete_data(m_ArticlesDB); + delete_data(m_updatedSectionImage); + delete_data(m_oldSectionImage); +} + +void CUIDiaryWnd::Show(bool status) +{ + inherited::Show(status); + if (status) + Reload((EDiaryFilter)m_FilterTab->GetActiveIndex()); +} + +bool CUIDiaryWnd::Init() +{ + CUIXml uiXml; + + if (!uiXml.Load(CONFIG_PATH, UI_PATH, DIAREYA_INFO, ShadowOfChernobylMode)) + return false; + + CUIXmlInit xml_init; + xml_init.InitWindow(uiXml, "main_wnd", 0, this); + + m_UILeftFrame = xr_new("diary_left_frame"); + m_UILeftFrame->SetAutoDelete(true); + xml_init.InitFrameWindow(uiXml, "main_wnd:left_frame", 0, m_UILeftFrame); + AttachChild(m_UILeftFrame); + + m_UILeftHeader = xr_new("diary_left_frame_header"); + m_UILeftHeader->SetAutoDelete(true); + xml_init.InitFrameLine(uiXml, "main_wnd:left_frame:left_frame_header", 0, m_UILeftHeader); + m_UILeftFrame->AttachChild(m_UILeftHeader); + + m_FilterTab = xr_new(); + m_FilterTab->SetAutoDelete(true); + m_UILeftHeader->AttachChild(m_FilterTab); + xml_init.InitTabControl(uiXml, "main_wnd:left_frame:left_frame_header:filter_tab", 0, m_FilterTab); + m_FilterTab->SetWindowName("filter_tab"); + Register(m_FilterTab); + AddCallback(m_FilterTab, TAB_CHANGED, CUIWndCallback::void_function(this, &CUIDiaryWnd::OnFilterChanged)); + + m_UIAnimation = xr_new(); + m_UIAnimation->SetAutoDelete(true); + xml_init.InitAnimatedStatic(uiXml, "main_wnd:left_frame:left_frame_header:anim_static", 0, m_UIAnimation); + m_UILeftHeader->AttachChild(m_UIAnimation); + + + m_UILeftWnd = xr_new("diary_left_frame_work_area"); + m_UILeftWnd->SetAutoDelete(true); + xml_init.InitWindow(uiXml, "main_wnd:left_frame:work_area", 0, m_UILeftWnd); + m_UILeftFrame->AttachChild(m_UILeftWnd); + + m_SrcListWnd = xr_new(); + m_SrcListWnd->SetAutoDelete(false); + xml_init.InitListWnd(uiXml, "main_wnd:left_frame:work_area:src_list", 0, m_SrcListWnd); + m_SrcListWnd->SetWindowName("src_list"); + Register(m_SrcListWnd); + AddCallback(m_SrcListWnd, LIST_ITEM_CLICKED, CUIWndCallback::void_function(this, &CUIDiaryWnd::OnSrcListItemClicked)); + + xml_init.InitFont(uiXml, "main_wnd:left_frame:work_area:src_list:tree_item_font", 0, m_uTreeItemColor, m_pTreeItemFont); + R_ASSERT(m_pTreeItemFont); + xml_init.InitFont(uiXml, "main_wnd:left_frame:work_area:src_list:tree_root_font", 0, m_uTreeRootColor, m_pTreeRootFont); + R_ASSERT(m_pTreeRootFont); + + m_UIRightFrame = xr_new("diary_right_frame"); + m_UIRightFrame->SetAutoDelete(true); + xml_init.InitFrameWindow(uiXml, "main_wnd:right_frame", 0, m_UIRightFrame); + AttachChild(m_UIRightFrame); + + m_UIRightHeader = xr_new("diary_right_frame_header"); + m_UIRightHeader->SetAutoDelete(true); + xml_init.InitFrameLine(uiXml, "main_wnd:right_frame:right_frame_header", 0, m_UIRightHeader); + m_UIRightFrame->AttachChild(m_UIRightHeader); + + m_UIRightWnd = xr_new("diary_right_frame_work_area"); + m_UIRightWnd->SetAutoDelete(true); + xml_init.InitWindow(uiXml, "main_wnd:right_frame:work_area", 0, m_UIRightWnd); + m_UIRightFrame->AttachChild(m_UIRightWnd); + + CUIXml uiXmlNEWS; + bool Gadina = uiXmlNEWS.Load(CONFIG_PATH, UI_PATH, DIAREYA_NEWS); + R_ASSERT3(Gadina, "xml file not found", DIAREYA_NEWS); + + m_UINewsWnd = xr_new(); + m_UINewsWnd->SetAutoDelete(false); + m_UINewsWnd->Init(uiXmlNEWS, ""); + + m_DescrView = xr_new(); + m_DescrView->SetAutoDelete(false); + xml_init.InitScrollView(uiXml, "main_wnd:right_frame:work_area:scroll_view", 0, m_DescrView); + + m_updatedSectionImage = xr_new("diary_updated_section_static"); + xml_init.InitStatic(uiXml, "updated_section_static", 0, m_updatedSectionImage); + + m_oldSectionImage = xr_new("diary_old_section_static"); + xml_init.InitStatic(uiXml, "old_section_static", 0, m_oldSectionImage); + + RearrangeTabButtons(m_FilterTab, m_sign_places); + + return true; +} + + +void CUIDiaryWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData) +{ + CUIWndCallback::OnEvent(pWnd, msg, pData); +} + +void CUIDiaryWnd::OnFilterChanged(CUIWindow* w, void*) +{ + Reload((EDiaryFilter)m_FilterTab->GetActiveIndex()); +} + +void CUIDiaryWnd::Reload(EDiaryFilter new_filter) +{ + //. if(m_currFilter==new_filter) return; + + switch (m_currFilter) { + case eJournal: + UnloadJournalTab(); + break; + // case eInfo: + // UnloadInfoTab (); + // break; + case eNews: + UnloadNewsTab(); + break; + }; + + m_currFilter = new_filter; + + switch (m_currFilter) { + case eJournal: + LoadJournalTab(ARTICLE_DATA::eJournalArticle); + break; + case eNews: + LoadNewsTab(); + break; + }; +} + +void CUIDiaryWnd::AddNews() +{ + m_UINewsWnd->AddNews(); +} + +void CUIDiaryWnd::UnloadJournalTab() +{ + m_UILeftWnd->DetachChild(m_SrcListWnd); + m_SrcListWnd->RemoveAll(); + m_SrcListWnd->Show(false); + + m_UIRightWnd->DetachChild(m_DescrView); + m_DescrView->Show(false); + delete_data(m_ArticlesDB); + m_DescrView->Clear(); +} + +void CUIDiaryWnd::LoadJournalTab(ARTICLE_DATA::EArticleType _type) +{ + delete_data(m_ArticlesDB); + + m_UILeftWnd->AttachChild(m_SrcListWnd); + m_SrcListWnd->Show(true); + + m_UIRightWnd->AttachChild(m_DescrView); + m_DescrView->Show(true); + + if (Actor()->encyclopedia_registry->registry().objects_ptr()) + { + ARTICLE_VECTOR::const_iterator it = Actor()->encyclopedia_registry->registry().objects_ptr()->begin(); + for (; it != Actor()->encyclopedia_registry->registry().objects_ptr()->end(); it++) + { + if (_type == it->article_type) + + { + m_ArticlesDB.resize(m_ArticlesDB.size() + 1); + CEncyclopediaArticle*& a = m_ArticlesDB.back(); + a = xr_new(); + a->Load(it->article_id); + + bool bReaded = false; + CreateTreeBranch(a->data()->group, a->data()->name, m_SrcListWnd, m_ArticlesDB.size() - 1, + m_pTreeRootFont, m_uTreeRootColor, m_pTreeItemFont, m_uTreeItemColor, bReaded); + } + } + } + g_pda_info_state &= !EDiarySections::eDJournal; +} + +void CUIDiaryWnd::LoadInfoTab() +{ + LoadJournalTab(ARTICLE_DATA::eInfoArticle); + g_pda_info_state &= ~EDiarySections::eDInfo; +} + + +void CUIDiaryWnd::UnloadNewsTab() +{ + m_UIRightWnd->DetachChild(m_UINewsWnd); + m_UINewsWnd->Show(false); +} + +void CUIDiaryWnd::LoadNewsTab() +{ + m_UIRightWnd->AttachChild(m_UINewsWnd); + m_UINewsWnd->Show(true); + g_pda_info_state &= ~EDiarySections::eDNews; +} + +void CUIDiaryWnd::OnSrcListItemClicked(CUIWindow* w, void* p) +{ + CUITreeViewItem* pSelItem = (CUITreeViewItem*)p; + m_DescrView->Clear(); + if (!pSelItem->IsRoot()) + { + CUIEncyclopediaArticleWnd* article_info = xr_new(); + article_info->Init("encyclopedia_item.xml", "encyclopedia_wnd:objective_item"); + article_info->SetArticle(m_ArticlesDB[pSelItem->GetValue()]); + m_DescrView->AddWindow(article_info, true); + } +} + +void CUIDiaryWnd::Draw() +{ + inherited::Draw(); + + m_updatedSectionImage->Update(); + m_oldSectionImage->Update(); + + Fvector2 tab_pos; + m_FilterTab->GetAbsolutePos(tab_pos); + + Fvector2 pos; + + pos = m_sign_places[eNews]; + pos.add(tab_pos); + + if (g_pda_info_state & EDiarySections::eDNews) + { + m_updatedSectionImage->SetWndPos(pos); + m_updatedSectionImage->Draw(); + } + else { + m_oldSectionImage->SetWndPos(pos); + m_oldSectionImage->Draw(); + } + + + pos = m_sign_places[eJournal]; + pos.add(tab_pos); + if (g_pda_info_state & EDiarySections::eDJournal) + { + m_updatedSectionImage->SetWndPos(pos); + m_updatedSectionImage->Draw(); + } + else { + m_oldSectionImage->SetWndPos(pos); + m_oldSectionImage->Draw(); + } +} + +void CUIDiaryWnd::Reset() +{ + inherited::Reset(); +} + + +void CUIDiaryWnd::RearrangeTabButtons(CUITabControl* pTab, xr_vector& vec_sign_places) +{ + TABS_VECTOR* btn_vec = pTab->GetButtonsVector(); + TABS_VECTOR::iterator it = btn_vec->begin(); + TABS_VECTOR::iterator it_e = btn_vec->end(); + vec_sign_places.clear(); + vec_sign_places.resize(btn_vec->size()); + + Fvector2 pos; + pos.set((*it)->GetWndPos()); + Fvector2 sign_sz; + sign_sz.set(9.0f + 3.0f, 11.0f); + u32 idx = 0; + float btn_text_len = 0.0f; + CUIStatic* st = NULL; + + for (; it != it_e; ++it, ++idx) + { + if (idx != 0) + { + st = xr_new("button_diary_test"); + st->SetAutoDelete(true); + pTab->AttachChild(st); + + st->SetFont((*it)->GetFont()); + st->SetTextColor(color_rgba(90, 90, 90, 255)); + st->SetText("//"); + st->SetWndSize((*it)->GetWndSize()); + st->AdjustWidthToText(); + st->SetWndPos(pos); + pos.x += st->GetWndSize().x; + } + + vec_sign_places[idx].set(pos); + vec_sign_places[idx].y += iFloor(((*it)->GetWndSize().y - sign_sz.y) / 2.0f); + vec_sign_places[idx].y = (float)iFloor(vec_sign_places[idx].y); + pos.x += sign_sz.x; + + (*it)->SetWndPos(pos); + (*it)->AdjustWidthToText(); + btn_text_len = (*it)->GetWndSize().x; + pos.x += btn_text_len + 3.0f; + } +} diff --git a/src/xrGame/ui/UIDiaryWnd.h b/src/xrGame/ui/UIDiaryWnd.h index 032267aecf3..3e54a24ce55 100644 --- a/src/xrGame/ui/UIDiaryWnd.h +++ b/src/xrGame/ui/UIDiaryWnd.h @@ -1,10 +1,11 @@ + #pragma once -/* -#include "UIWindow.h" -#include "UIWndCallback.h" +#include "xrUICore/Windows/UIWindow.h" +#include "xrUICore/Callbacks/UIWndCallback.h" #include "../encyclopedia_article_defs.h" -class CUINewsWnd; + +class CUINewsItemWnd; class CUIFrameLineWnd; class CUIFrameWindow; class CUIAnimatedStatic; @@ -14,59 +15,68 @@ class CUIScrollView; class CUIListWnd; class CEncyclopediaArticle; -class CUIDiaryWnd: public CUIWindow, public CUIWndCallback +class CUIDiaryWnd : public CUIWindow, public CUIWndCallback { +private: typedef CUIWindow inherited; + enum EDiaryFilter : u32 { + eJournal, + eNews, + eNone, + eInfo + }; + enum EDiarySections : u32 { + eDNews = (1 << 10) | (1 << 1), + eDInfo = (1 << 10) | (1 << 2), + eDJournal = (1 << 10) | (1 << 3), + }; protected: - shared_str m_currFilter; + u32 g_pda_info_state; + EDiaryFilter m_currFilter; - CUINewsWnd* m_UINewsWnd; + CUINewsItemWnd* m_UINewsWnd; - CUIWindow* m_UILeftWnd; - CUIWindow* m_UIRightWnd; - CUIFrameWindow* m_UILeftFrame; - CUIFrameLineWnd* m_UILeftHeader; - CUIFrameWindow* m_UIRightFrame; - CUIFrameLineWnd* m_UIRightHeader; - CUIAnimatedStatic* m_UIAnimation; - CUITabControl* m_FilterTab; - CUIListWnd* m_SrcListWnd; - CUIScrollView* m_DescrView; - CGameFont* m_pTreeRootFont; - u32 m_uTreeRootColor; - CGameFont* m_pTreeItemFont; - u32 m_uTreeItemColor; + CUIWindow* m_UILeftWnd; + CUIWindow* m_UIRightWnd; + CUIFrameWindow* m_UILeftFrame; + CUIFrameLineWnd* m_UILeftHeader; + CUIFrameWindow* m_UIRightFrame; + CUIFrameLineWnd* m_UIRightHeader; + CUIAnimatedStatic* m_UIAnimation; + CUITabControl* m_FilterTab; + CUIListWnd* m_SrcListWnd; + CUIScrollView* m_DescrView; + CGameFont* m_pTreeRootFont; + u32 m_uTreeRootColor; + CGameFont* m_pTreeItemFont; + u32 m_uTreeItemColor; - xr_vector m_sign_places; - CUIStatic* m_updatedSectionImage; - CUIStatic* m_oldSectionImage; + xr_vector m_sign_places; + CUIStatic* m_updatedSectionImage; + CUIStatic* m_oldSectionImage; - typedef xr_vector ArticlesDB; - typedef xr_vector::iterator ArticlesDB_it; - ArticlesDB m_ArticlesDB; + typedef xr_vector ArticlesDB; + typedef xr_vector::iterator ArticlesDB_it; + ArticlesDB m_ArticlesDB; - void OnFilterChanged (CUIWindow*,void*); - void OnSrcListItemClicked (CUIWindow*,void*); - void UnloadJournalTab (); - void LoadJournalTab (ARTICLE_DATA::EArticleType _type); - void UnloadInfoTab (); - void LoadInfoTab (); - void UnloadNewsTab (); - void LoadNewsTab (); - void Reload (const shared_str& new_filter); + void __stdcall OnFilterChanged(CUIWindow*, void*); + void __stdcall OnSrcListItemClicked(CUIWindow*, void*); + void UnloadJournalTab(); + void LoadJournalTab(ARTICLE_DATA::EArticleType _type); + void LoadInfoTab(); + void UnloadNewsTab(); + void LoadNewsTab(); + void Reload(EDiaryFilter new_filter); public: - CUIDiaryWnd (); - virtual ~CUIDiaryWnd (); + CUIDiaryWnd(); + virtual ~CUIDiaryWnd(); - virtual void SendMessage (CUIWindow* pWnd, s16 msg, void* pData); - virtual void Draw (); - virtual void Reset (); - - void Init (); - void AddNews (); - void MarkNewsAsRead (bool status); - virtual void Show (bool status); + virtual void SendMessage(CUIWindow* pWnd, s16 msg, void* pData); + virtual void Draw(); + virtual void Reset(); + bool Init(); + void AddNews(); + void RearrangeTabButtons(CUITabControl* pTab, xr_vector& vec_sign_places); + virtual void Show(bool status); }; - -*/ diff --git a/src/xrGame/ui/UIEncyclopediaWnd.cpp b/src/xrGame/ui/UIEncyclopediaWnd.cpp index d925905e303..efc540c408e 100644 --- a/src/xrGame/ui/UIEncyclopediaWnd.cpp +++ b/src/xrGame/ui/UIEncyclopediaWnd.cpp @@ -22,7 +22,6 @@ #include "Common/object_broker.h" #define ENCYCLOPEDIA_DIALOG_XML "encyclopedia.xml" -#define ALL_PDA_HEADER_PREFIX "# "; CUIEncyclopediaWnd::CUIEncyclopediaWnd() : CUIWindow("CUIEncyclopediaWnd"), prevArticlesCount(0), @@ -124,7 +123,7 @@ void CUIEncyclopediaWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData) { CEncyclopediaArticle* A = m_ArticlesDB[pTVItem->vSubItems[0]->GetValue()]; - xr_string caption = ALL_PDA_HEADER_PREFIX; + xr_string caption = "# "; caption += "/"; caption += CStringTable().translate(A->data()->group).c_str(); @@ -135,7 +134,7 @@ void CUIEncyclopediaWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData) else { CEncyclopediaArticle* A = m_ArticlesDB[pTVItem->GetValue()]; - xr_string caption = ALL_PDA_HEADER_PREFIX; + xr_string caption = "# "; caption += "/"; caption += CStringTable().translate(A->data()->group).c_str(); caption += "/"; diff --git a/src/xrGame/ui/UIEventsWnd.cpp b/src/xrGame/ui/UIEventsWnd.cpp index 570a77942ff..e823002a12e 100644 --- a/src/xrGame/ui/UIEventsWnd.cpp +++ b/src/xrGame/ui/UIEventsWnd.cpp @@ -60,7 +60,7 @@ CUIEventsWnd::~CUIEventsWnd() bool CUIEventsWnd::Init() { CUIXml xml; - if (!xml.Load(CONFIG_PATH, UI_PATH, UI_PATH_DEFAULT, PDA_EVENTS_XML, false)) + if (!xml.Load(CONFIG_PATH, UI_PATH, UI_PATH_DEFAULT, PDA_EVENTS_XML, ShadowOfChernobylMode)) return false; CUIXmlInit xml_init; diff --git a/src/xrGame/ui/UILogsWnd.h b/src/xrGame/ui/UILogsWnd.h index 87ab366ba33..aedc7f4697f 100644 --- a/src/xrGame/ui/UILogsWnd.h +++ b/src/xrGame/ui/UILogsWnd.h @@ -31,6 +31,7 @@ class CUILogsWnd final : public CUIWindow, public CUIWndCallback { private: typedef CUIWindow inherited; + CUIXml m_uiXml; CUICharacterInfo* m_actor_ch_info{}; @@ -59,8 +60,6 @@ class CUILogsWnd final : public CUIWindow, public CUIWndCallback CUIWindow* CreateItem(); CUIWindow* ItemFromCache(); - // void ItemToCache (CUIWindow* w); - CUIXml m_uiXml; public: CUILogsWnd(); diff --git a/src/xrGame/ui/UINewsItemWnd.cpp b/src/xrGame/ui/UINewsItemWnd.cpp index 98dd75a6503..82ba6693168 100644 --- a/src/xrGame/ui/UINewsItemWnd.cpp +++ b/src/xrGame/ui/UINewsItemWnd.cpp @@ -11,6 +11,19 @@ CUINewsItemWnd::CUINewsItemWnd() : CUIWindow("CUINewsItemWnd") {} void CUINewsItemWnd::Init(CUIXml& uiXml, LPCSTR start_from) { + if (ShadowOfChernobylMode) + { + string512 pth; + CUIXmlInit xml_init; + strconcat(sizeof pth, pth, start_from, "list"); + xml_init.InitWindow(uiXml, pth, 0, this); + m_UIScrollView = xr_new(); + m_UIScrollView->SetAutoDelete(true); + AttachChild(m_UIScrollView); + xml_init.InitScrollView(uiXml, pth, 0, m_UIScrollView); + return; + } + CUIXmlInit::InitWindow(uiXml, start_from, 0, this); XML_NODE stored_root = uiXml.GetLocalRoot(); diff --git a/src/xrGame/ui/UINewsItemWnd.h b/src/xrGame/ui/UINewsItemWnd.h index e4a20f8fa00..5928ef8ef31 100644 --- a/src/xrGame/ui/UINewsItemWnd.h +++ b/src/xrGame/ui/UINewsItemWnd.h @@ -7,12 +7,14 @@ struct GAME_NEWS_DATA; class CUINewsItemWnd final : public CUIWindow { +protected: typedef CUIWindow inherited; CUIStatic* m_UIDate; CUIStatic* m_UICaption; CUIStatic* m_UIText; CUIStatic* m_UIImage; + CUIScrollView* m_UIScrollView; public: CUINewsItemWnd(); @@ -20,6 +22,6 @@ class CUINewsItemWnd final : public CUIWindow void Init(CUIXml& uiXml, LPCSTR start_from); void Setup(GAME_NEWS_DATA& news_data); virtual void Update(){}; - + void AddNews() { } pcstr GetDebugType() override { return "CUINewsItemWnd"; } }; diff --git a/src/xrGame/ui/UIPdaWnd.cpp b/src/xrGame/ui/UIPdaWnd.cpp index ad650f25965..7913aa6b56d 100644 --- a/src/xrGame/ui/UIPdaWnd.cpp +++ b/src/xrGame/ui/UIPdaWnd.cpp @@ -31,6 +31,7 @@ #include "UIEventsWnd.h" #include "UIEncyclopediaWnd.h" #include "UIScriptWnd.h" +#include "UIDiaryWnd.h" #define PDA_XML "pda.xml" @@ -44,6 +45,7 @@ CUIPdaWnd::CUIPdaWnd() : CUIDialogWnd(CUIPdaWnd::GetDebugType()) pUITaskWnd = nullptr; pUIFactionWarWnd = nullptr; pUIActorInfo = nullptr; + pUIDiaryWnd = nullptr; pUIRankingWnd = nullptr; pUIEncyclopediaWnd = nullptr; pUIEventsWnd = nullptr; @@ -62,6 +64,8 @@ CUIPdaWnd::~CUIPdaWnd() delete_data(pUIFactionWarWnd); if (pUIActorInfo) delete_data(pUIActorInfo); + if (pUIDiaryWnd) + delete_data(pUIDiaryWnd); if (pUIRankingWnd) delete_data(pUIRankingWnd); if (pUILogsWnd) @@ -121,50 +125,41 @@ void CUIPdaWnd::Init() if (IsGameTypeSingle()) { - if (ShadowOfChernobylMode) - { - pUIMapWnd = xr_new(m_hint_wnd); - if (!pUIMapWnd->Init("pda_map.xml", "map_wnd", false)) - xr_delete(pUIMapWnd); - - pUIEventsWnd = xr_new(); - if (!pUIEventsWnd->Init()) - xr_delete(pUIEventsWnd); + pUIMapWnd = xr_new(m_hint_wnd); + if (!pUIMapWnd->Init("pda_map.xml", "map_wnd", false)) + xr_delete(pUIMapWnd); - pUIEncyclopediaWnd = xr_new(); - if (!pUIEncyclopediaWnd->Init()) - xr_delete(pUIEncyclopediaWnd); + pUITaskWnd = xr_new(m_hint_wnd); + if (!pUITaskWnd->Init()) + xr_delete(pUITaskWnd); - pUIActorInfo = xr_new(); - if (!pUIActorInfo->Init()) - xr_delete(pUIActorInfo); - } - else { + pUIFactionWarWnd = xr_new(m_hint_wnd); + if (!pUIFactionWarWnd->Init()) + xr_delete(pUIFactionWarWnd); - pUIMapWnd = xr_new(m_hint_wnd); - if (!pUIMapWnd->Init("pda_map.xml", "map_wnd", false)) - xr_delete(pUIMapWnd); + pUIActorInfo = xr_new(); + if (!pUIActorInfo->Init()) + xr_delete(pUIActorInfo); - pUITaskWnd = xr_new(m_hint_wnd); - if (!pUITaskWnd->Init()) - xr_delete(pUITaskWnd); + pUIRankingWnd = xr_new(); + if (!pUIRankingWnd->Init()) + xr_delete(pUIRankingWnd); - pUIFactionWarWnd = xr_new(m_hint_wnd); - if (!pUIFactionWarWnd->Init()) - xr_delete(pUIFactionWarWnd); + pUILogsWnd = xr_new(); + if (!pUILogsWnd->Init()) + xr_delete(pUILogsWnd); - pUIActorInfo = xr_new(); - if (!pUIActorInfo->Init()) - xr_delete(pUIActorInfo); + pUIEventsWnd = xr_new(); + if (!pUIEventsWnd->Init()) + xr_delete(pUIEventsWnd); - pUIRankingWnd = xr_new(); - if (!pUIRankingWnd->Init()) - xr_delete(pUIRankingWnd); + pUIEncyclopediaWnd = xr_new(); + if (!pUIEncyclopediaWnd->Init()) + xr_delete(pUIEncyclopediaWnd); - pUILogsWnd = xr_new(); - if (!pUILogsWnd->Init()) - xr_delete(pUILogsWnd); - } + pUIDiaryWnd = xr_new(); + if (!pUIDiaryWnd->Init()) + xr_delete(pUIDiaryWnd); } UITabControl = xr_new(); @@ -211,7 +206,6 @@ void CUIPdaWnd::Init() RearrangeTabButtons(UITabControl); } - void CUIPdaWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData) { switch (msg) @@ -298,7 +292,7 @@ void CUIPdaWnd::SetActiveSubdialog(const shared_str& section) { {"eptTasks", pUIEventsWnd}, {"eptMap", pUIMapWnd}, - {"eptDiary", pUIEncyclopediaWnd}, + {"eptDiary", pUIDiaryWnd}, {"eptContacts", pUIEncyclopediaWnd}, {"eptStalkersRanking", pUIEncyclopediaWnd}, {"eptStatistics", pUIActorInfo}, diff --git a/src/xrGame/ui/UIPdaWnd.h b/src/xrGame/ui/UIPdaWnd.h index 47e7642df3d..709a8a2f849 100644 --- a/src/xrGame/ui/UIPdaWnd.h +++ b/src/xrGame/ui/UIPdaWnd.h @@ -21,11 +21,12 @@ class CUIAnimatedStatic; class CUIEncyclopediaWnd; class CUIEventsWnd; class UIHint; +class CUIDiaryWnd; class CUIPdaWnd final : public CUIDialogWnd { +private: typedef CUIDialogWnd inherited; - protected: CUITabControl* UITabControl; CUI3tButton* m_btn_close; @@ -52,6 +53,7 @@ class CUIPdaWnd final : public CUIDialogWnd CUIFactionWarWnd* pUIFactionWarWnd; CUIActorInfoWnd* pUIActorInfo; CUIRankingWnd* pUIRankingWnd; + CUIDiaryWnd* pUIDiaryWnd; CUILogsWnd* pUILogsWnd; virtual void Reset(); @@ -83,7 +85,6 @@ class CUIPdaWnd final : public CUIDialogWnd void Show_SecondTaskWnd(bool status); void Show_MapWnd(bool status); void Show_ContactsWnd(bool status); - void DrawUpdatedSections(); void RearrangeTabButtons(CUITabControl* pTab); void SetActiveDialog(CUIWindow* wnd) { m_pActiveDialog = wnd; } diff --git a/src/xrGame/xrGame.vcxproj b/src/xrGame/xrGame.vcxproj index 1d5e8ad83eb..37e565e0761 100644 --- a/src/xrGame/xrGame.vcxproj +++ b/src/xrGame/xrGame.vcxproj @@ -1271,6 +1271,7 @@ + @@ -3107,6 +3108,7 @@ + diff --git a/src/xrGame/xrGame.vcxproj.filters b/src/xrGame/xrGame.vcxproj.filters index 90c68fc3124..013fcfb0c3e 100644 --- a/src/xrGame/xrGame.vcxproj.filters +++ b/src/xrGame/xrGame.vcxproj.filters @@ -2233,6 +2233,9 @@ {3946c692-4a83-47fe-b1bf-95955dbafe2a} + + {e608d3d0-db12-46e0-a811-94ca1a5b7938} + @@ -6326,6 +6329,9 @@ UI\Common\PDA\Encyclopedia + + UI\Common\PDA\Diary + @@ -9525,6 +9531,9 @@ UI\Common\PDA\Encyclopedia + + UI\Common\PDA\Diary + From 5b0eac3d263eaf4f69a651acc4ccdb1508095653 Mon Sep 17 00:00:00 2001 From: werasik2aa Date: Mon, 15 Sep 2025 22:20:29 +0700 Subject: [PATCH 11/12] SomeFix UI POSIS, CONTACTS TAB ADD --- src/xrGame/ui/UICharacterInfo.cpp | 4 - src/xrGame/ui/UIDiaryWnd.cpp | 6 +- src/xrGame/ui/UIEncyclopediaWnd.cpp | 5 +- src/xrGame/ui/UIEncyclopediaWnd.h | 78 ++++++------- src/xrGame/ui/UIEventsWnd.cpp | 3 +- src/xrGame/ui/UIPdaContactsWnd.cpp | 171 ++++++++++++++++++++++++++++ src/xrGame/ui/UIPdaContactsWnd.h | 56 +++++++++ src/xrGame/ui/UIPdaListItem.cpp | 47 ++++++++ src/xrGame/ui/UIPdaListItem.h | 27 +++++ src/xrGame/ui/UIPdaWnd.cpp | 17 +-- src/xrGame/ui/UIPdaWnd.h | 2 + src/xrGame/xrGame.vcxproj | 4 + src/xrGame/xrGame.vcxproj.filters | 35 ++++-- src/xrUICore/Hint/UIHint.cpp | 16 ++- src/xrUICore/Static/UIStatic.cpp | 13 +++ src/xrUICore/Static/UIStatic.h | 3 + 16 files changed, 418 insertions(+), 69 deletions(-) create mode 100644 src/xrGame/ui/UIPdaContactsWnd.cpp create mode 100644 src/xrGame/ui/UIPdaContactsWnd.h create mode 100644 src/xrGame/ui/UIPdaListItem.cpp create mode 100644 src/xrGame/ui/UIPdaListItem.h diff --git a/src/xrGame/ui/UICharacterInfo.cpp b/src/xrGame/ui/UICharacterInfo.cpp index 5c242e8e1a8..a8c18d5ed6a 100644 --- a/src/xrGame/ui/UICharacterInfo.cpp +++ b/src/xrGame/ui/UICharacterInfo.cpp @@ -26,13 +26,9 @@ using namespace InventoryUtilities; CSE_ALifeTraderAbstract* ch_info_get_from_id(u16 id) { if (ai().get_alife() && ai().get_game_graph()) - { return smart_cast(ai().alife().objects().object(id)); - } else - { return smart_cast(Level().Server->GetGameState()->get_entity_from_eid(id)); - } } void CUICharacterInfo::InitCharacterInfo(Fvector2 pos, Fvector2 size, CUIXml* xml_doc) diff --git a/src/xrGame/ui/UIDiaryWnd.cpp b/src/xrGame/ui/UIDiaryWnd.cpp index 9e800099888..158e1dd785a 100644 --- a/src/xrGame/ui/UIDiaryWnd.cpp +++ b/src/xrGame/ui/UIDiaryWnd.cpp @@ -18,6 +18,7 @@ #define DIAREYA_INFO "events_new.xml" #define DIAREYA_NEWS "news.xml" +#define DIAREYA_ENCY "encyclopedia_item.xml" CUIDiaryWnd::CUIDiaryWnd() : CUIWindow("CUIDiaryWnd"), m_currFilter(eNone) { @@ -244,8 +245,9 @@ void CUIDiaryWnd::OnSrcListItemClicked(CUIWindow* w, void* p) if (!pSelItem->IsRoot()) { CUIEncyclopediaArticleWnd* article_info = xr_new(); - article_info->Init("encyclopedia_item.xml", "encyclopedia_wnd:objective_item"); - article_info->SetArticle(m_ArticlesDB[pSelItem->GetValue()]); + article_info->Init(DIAREYA_ENCY, "encyclopedia_wnd:objective_item"); + CEncyclopediaArticle* mCEItem = m_ArticlesDB[pSelItem->GetValue()]; + article_info->SetArticle(mCEItem); m_DescrView->AddWindow(article_info, true); } } diff --git a/src/xrGame/ui/UIEncyclopediaWnd.cpp b/src/xrGame/ui/UIEncyclopediaWnd.cpp index efc540c408e..c01b0256a8f 100644 --- a/src/xrGame/ui/UIEncyclopediaWnd.cpp +++ b/src/xrGame/ui/UIEncyclopediaWnd.cpp @@ -19,7 +19,6 @@ #include "../encyclopedia_article.h" #include "../alife_registry_wrappers.h" #include "../actor.h" -#include "Common/object_broker.h" #define ENCYCLOPEDIA_DIALOG_XML "encyclopedia.xml" CUIEncyclopediaWnd::CUIEncyclopediaWnd() : @@ -106,8 +105,8 @@ bool CUIEncyclopediaWnd::Init() UIEncyclopediaInfoBkg->AttachChild(UIInfoList); xml_init.InitScrollView(uiXml, "info_list", 0, UIInfoList); - xml_init.InitWindow(uiXml, "left_auto_static", 0, UIEncyclopediaInfoBkg); - xml_init.InitWindow(uiXml, "right_auto_static", 0, UIEncyclopediaIdxBkg); + xml_init.InitAutoStaticGroup(uiXml, "left_auto_static", 0, UIEncyclopediaInfoBkg); + xml_init.InitAutoStaticGroup(uiXml, "right_auto_static", 0, UIEncyclopediaIdxBkg); return true; } diff --git a/src/xrGame/ui/UIEncyclopediaWnd.h b/src/xrGame/ui/UIEncyclopediaWnd.h index 2a5dc5896a2..5fdf477f7e5 100644 --- a/src/xrGame/ui/UIEncyclopediaWnd.h +++ b/src/xrGame/ui/UIEncyclopediaWnd.h @@ -1,9 +1,9 @@ //============================================================================= -// Filename: UIEncyclopediaWnd.h -// Created by Roman E. Marchenko, vortex@gsc-game.kiev.ua -// Copyright 2004. GSC Game World -// --------------------------------------------------------------------------- -// Encyclopedia window +// Filename: UIEncyclopediaWnd.h +// Created by Roman E. Marchenko, vortex@gsc-game.kiev.ua +// Copyright 2004. GSC Game World +// --------------------------------------------------------------------------- +// Encyclopedia window //============================================================================= #pragma once @@ -21,49 +21,49 @@ class CUIEncyclopediaCore; class CUIScrollView; class CUITreeViewItem; -class CUIEncyclopediaWnd: public CUIWindow +class CUIEncyclopediaWnd : public CUIWindow { private: - typedef CUIWindow inherited; - enum {eNeedReload=(1<<0),}; - Flags16 m_flags; + typedef CUIWindow inherited; + enum { eNeedReload = (1 << 0), }; + Flags16 m_flags; public: - CUIEncyclopediaWnd (); - virtual ~CUIEncyclopediaWnd (); + CUIEncyclopediaWnd(); + virtual ~CUIEncyclopediaWnd(); - virtual bool Init (); - virtual void Show (bool status); - virtual void SendMessage (CUIWindow *pWnd, s16 msg, void* pData = NULL); - virtual void Draw (); + virtual bool Init(); + virtual void Show(bool status); + virtual void SendMessage(CUIWindow* pWnd, s16 msg, void* pData = NULL); + virtual void Draw(); - void AddArticle (shared_str, bool bReaded); - void DeleteArticles (); - bool HasArticle (shared_str); + void AddArticle(shared_str, bool bReaded); + void DeleteArticles(); + bool HasArticle(shared_str); - void ReloadArticles (); - virtual void Reset (); + void ReloadArticles(); + virtual void Reset(); protected: - u32 prevArticlesCount; - // Элементы графического оформления - CUIFrameWindow* UIEncyclopediaIdxBkg; - CUIFrameWindow* UIEncyclopediaInfoBkg; - CUIFrameLineWnd* UIEncyclopediaIdxHeader; - CUIFrameLineWnd* UIEncyclopediaInfoHeader; - CUIAnimatedStatic* UIAnimation; - CUIStatic* UIArticleHeader; + u32 prevArticlesCount; + // Элементы графического оформления + CUIFrameWindow* UIEncyclopediaIdxBkg; + CUIFrameWindow* UIEncyclopediaInfoBkg; + CUIFrameLineWnd* UIEncyclopediaIdxHeader; + CUIFrameLineWnd* UIEncyclopediaInfoHeader; + CUIAnimatedStatic* UIAnimation; + CUIStatic* UIArticleHeader; - // Хранилище статей - typedef xr_vector ArticlesDB; - typedef ArticlesDB::iterator ArticlesDB_it; + // Хранилище статей + typedef xr_vector ArticlesDB; + typedef ArticlesDB::iterator ArticlesDB_it; - ArticlesDB m_ArticlesDB; - CGameFont* m_pTreeRootFont; - u32 m_uTreeRootColor; - CGameFont* m_pTreeItemFont; - u32 m_uTreeItemColor; + ArticlesDB m_ArticlesDB; + CGameFont* m_pTreeRootFont; + u32 m_uTreeRootColor; + CGameFont* m_pTreeItemFont; + u32 m_uTreeItemColor; - CUIListWnd* UIIdxList; - CUIScrollView* UIInfoList; + CUIListWnd* UIIdxList; + CUIScrollView* UIInfoList; - void SetCurrentArtice(CUITreeViewItem *pTVItem); + void SetCurrentArtice(CUITreeViewItem* pTVItem); }; diff --git a/src/xrGame/ui/UIEventsWnd.cpp b/src/xrGame/ui/UIEventsWnd.cpp index e823002a12e..3d415c19da0 100644 --- a/src/xrGame/ui/UIEventsWnd.cpp +++ b/src/xrGame/ui/UIEventsWnd.cpp @@ -46,7 +46,8 @@ CUIEventsWnd::CUIEventsWnd() : m_UIMapWnd(NULL), m_UITaskInfoWnd(NULL), m_ListWnd(NULL), - m_TaskFilter(NULL) + m_TaskFilter(NULL), + m_currFilter(ETaskFilters::eActiveTask) { m_flags.zero(); } diff --git a/src/xrGame/ui/UIPdaContactsWnd.cpp b/src/xrGame/ui/UIPdaContactsWnd.cpp new file mode 100644 index 00000000000..389a0e45967 --- /dev/null +++ b/src/xrGame/ui/UIPdaContactsWnd.cpp @@ -0,0 +1,171 @@ +#include "stdafx.h" +#include "UIPdaContactsWnd.h" +#include "../Pda.h" +#include "UIXmlInit.h" +#include "../actor.h" +#include "xrUICore/Windows/UIFrameWindow.h" +#include "xrUICore/Windows/UIFrameLineWnd.h" +#include "xrUICore/Static/UIAnimatedStatic.h" +#include "xrUICore/ScrollView/UIScrollView.h" +#include "UICharacterInfo.h" + +#define PDA_CONTACT_HEIGHT 70 +#define PDA_CONTACTS_XML "pda_contacts_new.xml" +extern CSE_ALifeTraderAbstract* ch_info_get_from_id(u16 id); + +CUIPdaContactsWnd::CUIPdaContactsWnd() : CUIWindow("UIPdaContactsWnd") +{ + m_flags.zero(); +} + +CUIPdaContactsWnd::~CUIPdaContactsWnd() +{ +} + +void CUIPdaContactsWnd::Show(bool status) +{ + inherited::Show(status); + if (status) UIDetailsWnd->Clear(); + +} + +bool CUIPdaContactsWnd::Init() +{ + CUIXml uiXml; + + if (!uiXml.Load(CONFIG_PATH, UI_PATH, PDA_CONTACTS_XML, ShadowOfChernobylMode)) + return false; + + CUIXmlInit xml_init; + xml_init.InitWindow(uiXml, "main_wnd", 0, this); + + UIFrameContacts = xr_new("UIFrameContacts"); + UIFrameContacts->SetAutoDelete(true); + AttachChild(UIFrameContacts); + xml_init.InitFrameWindow(uiXml, "left_frame_window", 0, UIFrameContacts); + + UIContactsHeader = xr_new("UIContactsHeader"); + UIContactsHeader->SetAutoDelete(true); + UIFrameContacts->AttachChild(UIContactsHeader); + xml_init.InitFrameLine(uiXml, "left_frame_line", 0, UIContactsHeader); + + UIRightFrame = xr_new("contacts_right_frame_window"); + UIRightFrame->SetAutoDelete(true); + AttachChild(UIRightFrame); + xml_init.InitFrameWindow(uiXml, "right_frame_window", 0, UIRightFrame); + + UIRightFrameHeader = xr_new("contacts_right_frame_line"); + UIRightFrameHeader->SetAutoDelete(true); + UIRightFrame->AttachChild(UIRightFrameHeader); + xml_init.InitFrameLine(uiXml, "right_frame_line", 0, UIRightFrameHeader); + + UIAnimation = xr_new(); + UIAnimation->SetAutoDelete(true); + UIContactsHeader->AttachChild(UIAnimation); + xml_init.InitAnimatedStatic(uiXml, "a_static", 0, UIAnimation); + + UIListWnd = xr_new(); + UIListWnd->SetAutoDelete(true); + UIFrameContacts->AttachChild(UIListWnd); + xml_init.InitScrollView(uiXml, "list", 0, UIListWnd); + + UIDetailsWnd = xr_new(); + UIDetailsWnd->SetAutoDelete(true); + UIRightFrame->AttachChild(UIDetailsWnd); + xml_init.InitScrollView(uiXml, "detail_list", 0, UIDetailsWnd); + + xml_init.InitAutoStaticGroup(uiXml, "left_auto_static", 0, UIFrameContacts); + xml_init.InitAutoStaticGroup(uiXml, "right_auto_static", 0, UIRightFrame); + + return true; +} + + +void CUIPdaContactsWnd::Update() +{ + if (TRUE == m_flags.test(flNeedUpdate)) { + RemoveAll(); + + CPda* pPda = Actor()->GetPDA(); + if (!pPda) return; + + pPda->ActivePDAContacts(m_pda_list); + + for (const auto &kv : m_pda_list) + AddContact(kv); + + m_flags.set(flNeedUpdate, FALSE); + } + inherited::Update(); +} + +void CUIPdaContactsWnd::AddContact(CPda* pda) +{ + VERIFY(pda); + + CUIPdaContactItem* pItem = NULL; + pItem = xr_new(this); + UIListWnd->AddWindow(pItem, true); + VERIFY(pda->GetOriginalOwner()); + pItem->Init(pda->GetOriginalOwner()->object_id()); + pItem->SetWidth(UIListWnd->GetWidth()); + pItem->SetHeight(85); + pItem->m_data = pda; +} + +void CUIPdaContactsWnd::RemoveContact(CPda* pda) +{ + u32 cnt = UIListWnd->GetSize(); + + for (u32 i = 0; i < cnt; ++i) { + CUIWindow* w = UIListWnd->GetItem(i); + CUIPdaContactItem* itm = (CUIPdaContactItem*)(w); + + if (itm->m_data == pda) { + if (itm->GetSelected()) + UIDetailsWnd->Clear(); + UIListWnd->RemoveWindow(w); + break; + } + } +} + +//удалить все контакты из списка +void CUIPdaContactsWnd::RemoveAll() +{ + UIListWnd->Clear(); + UIDetailsWnd->Clear(); +} + +void CUIPdaContactsWnd::Reload() +{ + m_flags.set(flNeedUpdate, TRUE); +} + +void CUIPdaContactsWnd::Reset() +{ + inherited::Reset(); + Reload(); +} + +CUIPdaContactItem::~CUIPdaContactItem() +{ +} + +void CUIPdaContactItem::SetSelected(bool b) +{ + CUISelectable::SetSelected(b); + if (b) { + m_cw->UIDetailsWnd->Clear(); + CCharacterInfo chInfo; + CSE_ALifeTraderAbstract* T = ch_info_get_from_id(UIInfo->OwnerID()); + chInfo.Init(T); + } +} + +bool CUIPdaContactItem::OnMouseDown(int mouse_btn) +{ + bool ThisP = mouse_btn == MOUSE_1; + if (ThisP) m_cw->UIListWnd->SetSelected(this); + return ThisP; +} diff --git a/src/xrGame/ui/UIPdaContactsWnd.h b/src/xrGame/ui/UIPdaContactsWnd.h new file mode 100644 index 00000000000..05597e4a084 --- /dev/null +++ b/src/xrGame/ui/UIPdaContactsWnd.h @@ -0,0 +1,56 @@ + +#pragma once + +#include "xrUICore/Windows/UIWindow.h" +#include "UIPdaListItem.h" + +class CUIFrameWindow; +class CUIFrameLineWnd; +class CUIStatic; +class CUIAnimatedStatic; +class CUIScrollView; +class CPda; + +class CUIPdaContactsWnd : public CUIWindow +{ +private: + typedef CUIWindow inherited; + enum { flNeedUpdate = (1 << 0), }; + Flags8 m_flags; + xr_vector m_pda_list; +public: + CUIPdaContactsWnd(); + virtual ~CUIPdaContactsWnd(); + + bool Init(); + + virtual void Update(); + virtual void Reset(); + + virtual void Show(bool status); + + void AddContact(CPda* pda); + void RemoveContact(CPda* pda); + void RemoveAll(); + void Reload(); + + CUIScrollView* UIListWnd; + CUIScrollView* UIDetailsWnd; + +protected: + CUIFrameWindow* UIFrameContacts; + CUIFrameLineWnd* UIContactsHeader; + CUIFrameWindow* UIRightFrame; + CUIFrameLineWnd* UIRightFrameHeader; + CUIAnimatedStatic* UIAnimation; +}; + +class CUIPdaContactItem :public CUIPdaListItem, public CUISelectable +{ + CUIPdaContactsWnd* m_cw; +public: + CUIPdaContactItem(CUIPdaContactsWnd* cw) { m_cw = cw; } + virtual ~CUIPdaContactItem(); + virtual void SetSelected(bool b); + virtual bool OnMouseDown(int mouse_btn); +}; diff --git a/src/xrGame/ui/UIPdaListItem.cpp b/src/xrGame/ui/UIPdaListItem.cpp new file mode 100644 index 00000000000..7a8fb974198 --- /dev/null +++ b/src/xrGame/ui/UIPdaListItem.cpp @@ -0,0 +1,47 @@ +#include "stdafx.h" + +#include "UIPdaListItem.h" +#include "../actor.h" +#include "UIInventoryUtilities.h" +#include "UIXmlInit.h" + +#include "xrUICore/Windows/UIFrameWindow.h" +#include "..\InventoryOwner.h" +#include "UICharacterInfo.h" +#include "xrUICore/Static/UIStatic.h" + +#define PDA_CONTACT_CHAR "pda_character.xml" + +CUIPdaListItem::CUIPdaListItem() : CUIWindow("CUIPdaListItem") +{ + UIMask = NULL; + UIInfo = NULL; +} + +CUIPdaListItem::~CUIPdaListItem() +{ +} + +void CUIPdaListItem::Init(u16 pizdabol) +{ + CUIXml uiXml; + bool xml_result = uiXml.Load(CONFIG_PATH, UI_PATH, PDA_CONTACT_CHAR); + R_ASSERT2(xml_result, "xml file not found"); + + VERIFY(pInvOwner); + UIInfo = xr_new(); + UIInfo->SetAutoDelete(true); + AttachChild(UIInfo); + UIInfo->InitCharacter(pizdabol); + + CUIXmlInit xml_init; + if (uiXml.NavigateToNode("mask_frame_window", 0)) + { + UIMask = xr_new("UIMask_pda"); + UIMask->SetAutoDelete(true); + xml_init.InitFrameWindow(uiXml, "mask_frame_window", 0, UIMask); + UIInfo->UIIcon().SetMask(UIMask); + } + + xml_init.InitAutoStaticGroup(uiXml, "pda_char_auto_statics", 0, this); +} diff --git a/src/xrGame/ui/UIPdaListItem.h b/src/xrGame/ui/UIPdaListItem.h new file mode 100644 index 00000000000..0f8a5efd94b --- /dev/null +++ b/src/xrGame/ui/UIPdaListItem.h @@ -0,0 +1,27 @@ +////////////////////////////////////////////////////////////////////// +// UIPdaListItem.h: элемент окна списка в PDA +// для отображения информации о контакте PDA +////////////////////////////////////////////////////////////////////// + +#pragma once +#include "xrUICore/Windows/UIWindow.h" + +class CUIFrameWindow; +class CUICharacterInfo; +class CInventoryOwner; +class CPda; + +class CUIPdaListItem : public CUIWindow +{ +private: + typedef CUIWindow inherited; +public: + CUIPdaListItem(); + virtual ~CUIPdaListItem(); + virtual void Init(u16 dark); + CPda* m_data; +protected: + //информация о персонаже + CUIFrameWindow* UIMask; + CUICharacterInfo* UIInfo; +}; diff --git a/src/xrGame/ui/UIPdaWnd.cpp b/src/xrGame/ui/UIPdaWnd.cpp index 7913aa6b56d..dfd3bf9d98a 100644 --- a/src/xrGame/ui/UIPdaWnd.cpp +++ b/src/xrGame/ui/UIPdaWnd.cpp @@ -32,6 +32,7 @@ #include "UIEncyclopediaWnd.h" #include "UIScriptWnd.h" #include "UIDiaryWnd.h" +#include "UIPdaContactsWnd.h" #define PDA_XML "pda.xml" @@ -48,6 +49,7 @@ CUIPdaWnd::CUIPdaWnd() : CUIDialogWnd(CUIPdaWnd::GetDebugType()) pUIDiaryWnd = nullptr; pUIRankingWnd = nullptr; pUIEncyclopediaWnd = nullptr; + pUIPdaContactsWnd = nullptr; pUIEventsWnd = nullptr; pUILogsWnd = nullptr; m_hint_wnd = nullptr; @@ -74,6 +76,8 @@ CUIPdaWnd::~CUIPdaWnd() delete_data(pUIEventsWnd); if (pUIEncyclopediaWnd) delete_data(pUIEncyclopediaWnd); + if (pUIPdaContactsWnd) + delete_data(pUIPdaContactsWnd); if (m_hint_wnd) delete_data(m_hint_wnd); if (UINoice) @@ -116,15 +120,10 @@ void CUIPdaWnd::Init() m_btn_close->SetAccelerator(kUI_BACK, false, 2); UI().Focus().UnregisterFocusable(m_btn_close); - - if (ShadowOfChernobylMode) - m_hint_wnd = UIHelper::CreateHint(uiXml, "left_frame", false); - else - m_hint_wnd = UIHelper::CreateHint(uiXml, "hint_wnd", false); + m_hint_wnd = UIHelper::CreateHint(uiXml, "hint_wnd", false); if (IsGameTypeSingle()) { - pUIMapWnd = xr_new(m_hint_wnd); if (!pUIMapWnd->Init("pda_map.xml", "map_wnd", false)) xr_delete(pUIMapWnd); @@ -157,6 +156,10 @@ void CUIPdaWnd::Init() if (!pUIEncyclopediaWnd->Init()) xr_delete(pUIEncyclopediaWnd); + pUIPdaContactsWnd = xr_new(); + if (!pUIPdaContactsWnd->Init()) + xr_delete(pUIPdaContactsWnd); + pUIDiaryWnd = xr_new(); if (!pUIDiaryWnd->Init()) xr_delete(pUIDiaryWnd); @@ -293,7 +296,7 @@ void CUIPdaWnd::SetActiveSubdialog(const shared_str& section) {"eptTasks", pUIEventsWnd}, {"eptMap", pUIMapWnd}, {"eptDiary", pUIDiaryWnd}, - {"eptContacts", pUIEncyclopediaWnd}, + {"eptContacts", pUIPdaContactsWnd}, {"eptStalkersRanking", pUIEncyclopediaWnd}, {"eptStatistics", pUIActorInfo}, {"eptEncyclopedia", pUIEncyclopediaWnd}, diff --git a/src/xrGame/ui/UIPdaWnd.h b/src/xrGame/ui/UIPdaWnd.h index 709a8a2f849..5e0dc08ca35 100644 --- a/src/xrGame/ui/UIPdaWnd.h +++ b/src/xrGame/ui/UIPdaWnd.h @@ -22,6 +22,7 @@ class CUIEncyclopediaWnd; class CUIEventsWnd; class UIHint; class CUIDiaryWnd; +class CUIPdaContactsWnd; class CUIPdaWnd final : public CUIDialogWnd { @@ -49,6 +50,7 @@ class CUIPdaWnd final : public CUIDialogWnd CUIMapWnd* pUIMapWnd; CUITaskWnd* pUITaskWnd; CUIEncyclopediaWnd* pUIEncyclopediaWnd; + CUIPdaContactsWnd* pUIPdaContactsWnd; CUIEventsWnd* pUIEventsWnd; CUIFactionWarWnd* pUIFactionWarWnd; CUIActorInfoWnd* pUIActorInfo; diff --git a/src/xrGame/xrGame.vcxproj b/src/xrGame/xrGame.vcxproj index 37e565e0761..7e8bb1e1bdc 100644 --- a/src/xrGame/xrGame.vcxproj +++ b/src/xrGame/xrGame.vcxproj @@ -1319,7 +1319,9 @@ + + @@ -3199,7 +3201,9 @@ + + diff --git a/src/xrGame/xrGame.vcxproj.filters b/src/xrGame/xrGame.vcxproj.filters index 013fcfb0c3e..d1e562cecbe 100644 --- a/src/xrGame/xrGame.vcxproj.filters +++ b/src/xrGame/xrGame.vcxproj.filters @@ -1861,12 +1861,6 @@ {ddf96ea9-ef48-422b-9ac9-d1c7aafa5cd6} - - {88b2008c-d91b-4387-b903-9223e6800188} - - - {f21f213a-d49e-4bc4-88eb-c2c3da37b244} - {39ccfc67-3565-45a8-a2f8-8580cd504d0e} @@ -2236,6 +2230,15 @@ {e608d3d0-db12-46e0-a811-94ca1a5b7938} + + {4d1f97bc-e355-4d23-929d-844c10d4f4dc} + + + {88b2008c-d91b-4387-b903-9223e6800188} + + + {f21f213a-d49e-4bc4-88eb-c2c3da37b244} + @@ -5749,10 +5752,10 @@ UI\Common\PDA\Tasks - UI\Common\PDA\logs + UI\Common\PDA\Logs - UI\Common\PDA\logs\News + UI\Common\PDA\Logs\News UI\Common\ui-item-infos @@ -6332,6 +6335,12 @@ UI\Common\PDA\Diary + + UI\Common\PDA\Contacts + + + UI\Common\PDA\Contacts + @@ -8933,10 +8942,10 @@ UI\Common\PDA\Tasks - UI\Common\PDA\logs + UI\Common\PDA\Logs - UI\Common\PDA\logs\News + UI\Common\PDA\Logs\News UI\Common\ui-item-infos @@ -9534,6 +9543,12 @@ UI\Common\PDA\Diary + + UI\Common\PDA\Contacts + + + UI\Common\PDA\Contacts + diff --git a/src/xrUICore/Hint/UIHint.cpp b/src/xrUICore/Hint/UIHint.cpp index f2b83134269..e92164066cc 100644 --- a/src/xrUICore/Hint/UIHint.cpp +++ b/src/xrUICore/Hint/UIHint.cpp @@ -29,14 +29,24 @@ void UIHint::init_from_xml(CUIXml& xml, LPCSTR path) m_background = xr_new("Background"); AttachChild(m_background); m_background->SetAutoDelete(true); - CUIXmlInitBase::InitFrameWindow(xml, "background", 0, m_background); + if (ShadowOfChernobylMode) + CUIXmlInitBase::InitFrameWindow(xml, "background_static", 0, m_background); + else + CUIXmlInitBase::InitFrameWindow(xml, "background", 0, m_background); m_text = xr_new("Text"); AttachChild(m_text); m_text->SetAutoDelete(true); - CUIXmlInitBase::InitStatic(xml, "text", 0, m_text); - m_border = xml.ReadAttribFlt("background", 0, "border", 0.0f); + if (ShadowOfChernobylMode) + CUIXmlInitBase::InitStatic(xml, "timer_frame_line:title", 0, m_text); + else + CUIXmlInitBase::InitStatic(xml, "text", 0, m_text); + + if (ShadowOfChernobylMode) + m_border = xml.ReadAttribFlt("mbbackground_frame_line", 0, "border", 0.0f); + else + m_border = xml.ReadAttribFlt("background", 0, "border", 0.0f); xml.SetLocalRoot(stored_root); m_visible = false; diff --git a/src/xrUICore/Static/UIStatic.cpp b/src/xrUICore/Static/UIStatic.cpp index 4620df7e2c9..acd9d1194ca 100644 --- a/src/xrUICore/Static/UIStatic.cpp +++ b/src/xrUICore/Static/UIStatic.cpp @@ -271,3 +271,16 @@ void CUIStatic::OnFocusLost() if (g_statHint->Owner() == this) g_statHint->Discard(); } + + +void CUIStatic::SetMask(CUIFrameWindow* pMask) +{ + DetachChild(m_pMask); + m_pMask = pMask; + if (m_pMask) { + AttachChild(m_pMask); + Frect r = GetWndRect(); + m_pMask->SetWidth(r.right - r.left); + m_pMask->SetHeight(r.bottom - r.top); + } +} diff --git a/src/xrUICore/Static/UIStatic.h b/src/xrUICore/Static/UIStatic.h index 3d3654d4505..1e709ab5228 100644 --- a/src/xrUICore/Static/UIStatic.h +++ b/src/xrUICore/Static/UIStatic.h @@ -91,6 +91,7 @@ class XRUICORE_API CUIStatic : public CUIWindow, public ITextureOwner, public CU void AdjustWidthToText(); void SetShader(const ui_shader& sh); + void SetMask(CUIFrameWindow* pMask); CUIStaticItem& GetUIStaticItem() { return m_UIStaticItem; } void SetStretchTexture(bool stretch_texture) { m_bStretchTexture = stretch_texture; } bool GetStretchTexture() { return m_bStretchTexture; } @@ -109,7 +110,9 @@ class XRUICORE_API CUIStatic : public CUIWindow, public ITextureOwner, public CU protected: CUILines* m_pTextControl{}; + CUIFrameWindow* m_pMask; CUIStaticItem m_UIStaticItem; + Fvector2 m_TextureOffset; bool m_bStretchTexture{}; bool m_bTextureEnable{ true }; From 41477686ecf5a5feb70d8d2cbc58f5b234f402fc Mon Sep 17 00:00:00 2001 From: werasik2aa Date: Tue, 16 Sep 2025 01:56:28 +0700 Subject: [PATCH 12/12] Edits V1 --- src/xrGame/ui/UIEncyclopediaWnd.cpp | 54 +++++++++++++---------------- src/xrGame/ui/UIPdaContactsWnd.cpp | 12 +++---- src/xrGame/ui/UIPdaListItem.cpp | 2 +- 3 files changed, 32 insertions(+), 36 deletions(-) diff --git a/src/xrGame/ui/UIEncyclopediaWnd.cpp b/src/xrGame/ui/UIEncyclopediaWnd.cpp index c01b0256a8f..de621db371a 100644 --- a/src/xrGame/ui/UIEncyclopediaWnd.cpp +++ b/src/xrGame/ui/UIEncyclopediaWnd.cpp @@ -21,7 +21,7 @@ #include "../actor.h" #define ENCYCLOPEDIA_DIALOG_XML "encyclopedia.xml" -CUIEncyclopediaWnd::CUIEncyclopediaWnd() : +CUIEncyclopediaWnd::CUIEncyclopediaWnd() : CUIWindow("CUIEncyclopediaWnd"), prevArticlesCount(0), UIEncyclopediaIdxBkg(NULL), @@ -33,7 +33,11 @@ CUIEncyclopediaWnd::CUIEncyclopediaWnd() : UIIdxList(NULL), UIInfoList(NULL), m_pTreeRootFont(NULL), - m_pTreeItemFont(NULL) + m_pTreeItemFont(NULL), + m_flags(eNeedReload), + m_uTreeItemColor(color_rgba(255, 255, 255, 255)), + m_uTreeRootColor(color_rgba(255, 255, 255, 255)) + { } @@ -51,7 +55,6 @@ bool CUIEncyclopediaWnd::Init() return false; CUIXmlInit xml_init; - xml_init.InitWindow(uiXml, "main_wnd", 0, this); // Load xml data - ИСПРАВЛЕНИЕ КОНСТРУКТОРОВ @@ -115,8 +118,9 @@ void CUIEncyclopediaWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData) { if (UIIdxList == pWnd && LIST_ITEM_CLICKED == msg) { - CUITreeViewItem* pTVItem = static_cast(pData); + CUITreeViewItem* pTVItem = (CUITreeViewItem*)pData; R_ASSERT(pTVItem); + if (!pTVItem) return; if (pTVItem->vSubItems.size()) { @@ -150,25 +154,20 @@ void CUIEncyclopediaWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData) void CUIEncyclopediaWnd::Draw() { + if (Actor()->encyclopedia_registry && + (m_flags.test(eNeedReload) || Actor()->encyclopedia_registry->registry().objects().size() > prevArticlesCount)) + { + ARTICLE_VECTOR::const_iterator it = Actor()->encyclopedia_registry->registry().objects().begin(); + std::advance(it, prevArticlesCount); - if (m_flags.test(eNeedReload)) { - if (Actor()->encyclopedia_registry->registry().objects_ptr() && Actor()->encyclopedia_registry->registry().objects_ptr()->size() > prevArticlesCount) - { - ARTICLE_VECTOR::const_iterator it = Actor()->encyclopedia_registry->registry().objects_ptr()->begin(); - std::advance(it, prevArticlesCount); - for (; it != Actor()->encyclopedia_registry->registry().objects_ptr()->end(); it++) - { - if (ARTICLE_DATA::eEncyclopediaArticle == it->article_type) - { - AddArticle(it->article_id, it->readed); - } - } - prevArticlesCount = Actor()->encyclopedia_registry->registry().objects_ptr()->size(); - } - + for (const auto& kv : Actor()->encyclopedia_registry->registry().objects()) + if (ARTICLE_DATA::eEncyclopediaArticle == kv.article_type) + AddArticle(kv.article_id, kv.readed); + prevArticlesCount = Actor()->encyclopedia_registry->registry().objects().size(); m_flags.set(eNeedReload, FALSE); } + inherited::Draw(); } @@ -190,10 +189,9 @@ void CUIEncyclopediaWnd::Show(bool status) bool CUIEncyclopediaWnd::HasArticle(shared_str id) { ReloadArticles(); - for (std::size_t i = 0; i < m_ArticlesDB.size(); ++i) - { - if (m_ArticlesDB[i]->Id() == id) return true; - } + for (const auto& kv : m_ArticlesDB) + if (kv->Id() == id) + return true; return false; } @@ -242,10 +240,10 @@ void CUIEncyclopediaWnd::SetCurrentArtice(CUITreeViewItem* pTVItem) void CUIEncyclopediaWnd::AddArticle(shared_str article_id, bool bReaded) { - for (std::size_t i = 0; i < m_ArticlesDB.size(); i++) - { - if (m_ArticlesDB[i]->Id() == article_id) return; - } + + for (const auto& kv : m_ArticlesDB) + if (kv->Id() == article_id) + return; // Добавляем элемент m_ArticlesDB.resize(m_ArticlesDB.size() + 1); @@ -253,9 +251,7 @@ void CUIEncyclopediaWnd::AddArticle(shared_str article_id, bool bReaded) a = xr_new(); a->Load(article_id); - // Теперь создаем иерархию вещи по заданному пути - CreateTreeBranch(a->data()->group, a->data()->name, UIIdxList, m_ArticlesDB.size() - 1, m_pTreeRootFont, m_uTreeRootColor, m_pTreeItemFont, m_uTreeItemColor, bReaded); } diff --git a/src/xrGame/ui/UIPdaContactsWnd.cpp b/src/xrGame/ui/UIPdaContactsWnd.cpp index 389a0e45967..76c12f788d6 100644 --- a/src/xrGame/ui/UIPdaContactsWnd.cpp +++ b/src/xrGame/ui/UIPdaContactsWnd.cpp @@ -11,6 +11,8 @@ #define PDA_CONTACT_HEIGHT 70 #define PDA_CONTACTS_XML "pda_contacts_new.xml" +#define PDA_CONTACT_CHAR "pda_character.xml" + extern CSE_ALifeTraderAbstract* ch_info_get_from_id(u16 id); CUIPdaContactsWnd::CUIPdaContactsWnd() : CUIWindow("UIPdaContactsWnd") @@ -103,14 +105,12 @@ void CUIPdaContactsWnd::AddContact(CPda* pda) { VERIFY(pda); - CUIPdaContactItem* pItem = NULL; - pItem = xr_new(this); + CUICharacterInfo* pItem = NULL; + pItem = xr_new(); UIListWnd->AddWindow(pItem, true); VERIFY(pda->GetOriginalOwner()); - pItem->Init(pda->GetOriginalOwner()->object_id()); - pItem->SetWidth(UIListWnd->GetWidth()); - pItem->SetHeight(85); - pItem->m_data = pda; + pItem->InitCharacterInfo(Fvector2(), Fvector2(UIListWnd->GetWidth(), 85), PDA_CONTACT_CHAR); + pItem->InitCharacter(pda->GetOriginalOwner()->object_id()); } void CUIPdaContactsWnd::RemoveContact(CPda* pda) diff --git a/src/xrGame/ui/UIPdaListItem.cpp b/src/xrGame/ui/UIPdaListItem.cpp index 7a8fb974198..e9a1bd8edbf 100644 --- a/src/xrGame/ui/UIPdaListItem.cpp +++ b/src/xrGame/ui/UIPdaListItem.cpp @@ -32,7 +32,7 @@ void CUIPdaListItem::Init(u16 pizdabol) UIInfo = xr_new(); UIInfo->SetAutoDelete(true); AttachChild(UIInfo); - UIInfo->InitCharacter(pizdabol); + CUIXmlInit xml_init; if (uiXml.NavigateToNode("mask_frame_window", 0))