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/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/EntityCondition.cpp b/src/xrGame/EntityCondition.cpp index 9e818f01fa7..bfa15035c24 100644 --- a/src/xrGame/EntityCondition.cpp +++ b/src/xrGame/EntityCondition.cpp @@ -300,14 +300,14 @@ float CEntityCondition::HitOutfitEffect( if (!pInvOwner) return hit_power; - CCustomOutfit* 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); @@ -376,7 +376,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/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/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..e88a115d2f3 100644 --- a/src/xrGame/UIZoneMap.cpp +++ b/src/xrGame/UIZoneMap.cpp @@ -93,10 +93,17 @@ 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:dist_text", 0, &m_Counter_text); + m_background.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/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: 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/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 new file mode 100644 index 00000000000..158e1dd785a --- /dev/null +++ b/src/xrGame/ui/UIDiaryWnd.cpp @@ -0,0 +1,343 @@ +#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" +#define DIAREYA_ENCY "encyclopedia_item.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(DIAREYA_ENCY, "encyclopedia_wnd:objective_item"); + CEncyclopediaArticle* mCEItem = m_ArticlesDB[pSelItem->GetValue()]; + article_info->SetArticle(mCEItem); + 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/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..de621db371a --- /dev/null +++ b/src/xrGame/ui/UIEncyclopediaWnd.cpp @@ -0,0 +1,263 @@ +//============================================================================= +// 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" + +#define ENCYCLOPEDIA_DIALOG_XML "encyclopedia.xml" +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), + m_flags(eNeedReload), + m_uTreeItemColor(color_rgba(255, 255, 255, 255)), + m_uTreeRootColor(color_rgba(255, 255, 255, 255)) + +{ +} + +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.InitAutoStaticGroup(uiXml, "left_auto_static", 0, UIEncyclopediaInfoBkg); + xml_init.InitAutoStaticGroup(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 = (CUITreeViewItem*)pData; + R_ASSERT(pTVItem); + if (!pTVItem) return; + + if (pTVItem->vSubItems.size()) + { + CEncyclopediaArticle* A = m_ArticlesDB[pTVItem->vSubItems[0]->GetValue()]; + + xr_string caption = "# "; + 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 = "# "; + 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 (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); + + 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(); +} + +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 (const auto& kv : m_ArticlesDB) + if (kv->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 (const auto& kv : m_ArticlesDB) + if (kv->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..5fdf477f7e5 --- /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..3d415c19da0 --- /dev/null +++ b/src/xrGame/ui/UIEventsWnd.cpp @@ -0,0 +1,319 @@ +#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_currFilter(ETaskFilters::eActiveTask) +{ + 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, ShadowOfChernobylMode)) + 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, i); + m_ListWnd->AddWindow(pTaskItem, true); + } + else { + CUITaskSubItem* pTaskItem = xr_new(this); + pTaskItem->SetGameTask(task, i); + 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) + { + CUITaskSubItem* itm = (CUITaskSubItem*)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/UIHudStatesWnd.cpp b/src/xrGame/ui/UIHudStatesWnd.cpp index 9cfcb6307e1..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()); @@ -857,7 +875,8 @@ void CUIHudStatesWnd::DrawZoneIndicators() 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/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/UIMainIngameWnd.cpp b/src/xrGame/ui/UIMainIngameWnd.cpp index eadd88bdae2..579269b73e6 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)) { @@ -232,7 +232,10 @@ void CUIMainIngameWnd::Init() 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->InitFromXml(uiXml, NULL); + else + m_ui_hud_states->InitFromXml(uiXml, "hud_states"); int i = 0; while (true) @@ -270,13 +273,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/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/UINewsItemWnd.cpp b/src/xrGame/ui/UINewsItemWnd.cpp index 18406af4f45..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(); @@ -18,7 +31,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/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/UIPdaContactsWnd.cpp b/src/xrGame/ui/UIPdaContactsWnd.cpp new file mode 100644 index 00000000000..76c12f788d6 --- /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" +#define PDA_CONTACT_CHAR "pda_character.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); + + CUICharacterInfo* pItem = NULL; + pItem = xr_new(); + UIListWnd->AddWindow(pItem, true); + VERIFY(pda->GetOriginalOwner()); + pItem->InitCharacterInfo(Fvector2(), Fvector2(UIListWnd->GetWidth(), 85), PDA_CONTACT_CHAR); + pItem->InitCharacter(pda->GetOriginalOwner()->object_id()); +} + +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..e9a1bd8edbf --- /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); + + + 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 1f17e502dfd..dfd3bf9d98a 100644 --- a/src/xrGame/ui/UIPdaWnd.cpp +++ b/src/xrGame/ui/UIPdaWnd.cpp @@ -28,13 +28,16 @@ #include "UIActorInfo.h" #include "UIRankingWnd.h" #include "UILogsWnd.h" +#include "UIEventsWnd.h" +#include "UIEncyclopediaWnd.h" #include "UIScriptWnd.h" +#include "UIDiaryWnd.h" +#include "UIPdaContactsWnd.h" #define PDA_XML "pda.xml" u32 g_pda_info_state = 0; -void RearrangeTabButtons(CUITabControl* pTab); CDialogHolder* CurrentDialogHolder(); CUIPdaWnd::CUIPdaWnd() : CUIDialogWnd(CUIPdaWnd::GetDebugType()) @@ -43,7 +46,11 @@ CUIPdaWnd::CUIPdaWnd() : CUIDialogWnd(CUIPdaWnd::GetDebugType()) pUITaskWnd = nullptr; pUIFactionWarWnd = nullptr; pUIActorInfo = nullptr; + pUIDiaryWnd = nullptr; pUIRankingWnd = nullptr; + pUIEncyclopediaWnd = nullptr; + pUIPdaContactsWnd = nullptr; + pUIEventsWnd = nullptr; pUILogsWnd = nullptr; m_hint_wnd = nullptr; Init(); @@ -59,11 +66,20 @@ CUIPdaWnd::~CUIPdaWnd() delete_data(pUIFactionWarWnd); if (pUIActorInfo) delete_data(pUIActorInfo); + if (pUIDiaryWnd) + delete_data(pUIDiaryWnd); if (pUIRankingWnd) delete_data(pUIRankingWnd); if (pUILogsWnd) delete_data(pUILogsWnd); - delete_data(m_hint_wnd); + if (pUIEventsWnd) + delete_data(pUIEventsWnd); + if (pUIEncyclopediaWnd) + delete_data(pUIEncyclopediaWnd); + if (pUIPdaContactsWnd) + delete_data(pUIPdaContactsWnd); + if (m_hint_wnd) + delete_data(m_hint_wnd); if (UINoice) delete_data(UINoice); } @@ -78,9 +94,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", this); + 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 +112,15 @@ 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"); + m_hint_wnd = UIHelper::CreateHint(uiXml, "hint_wnd", false); if (IsGameTypeSingle()) { @@ -122,6 +147,22 @@ void CUIPdaWnd::Init() pUILogsWnd = xr_new(); if (!pUILogsWnd->Init()) xr_delete(pUILogsWnd); + + pUIEventsWnd = xr_new(); + if (!pUIEventsWnd->Init()) + xr_delete(pUIEventsWnd); + + pUIEncyclopediaWnd = xr_new(); + if (!pUIEncyclopediaWnd->Init()) + xr_delete(pUIEncyclopediaWnd); + + pUIPdaContactsWnd = xr_new(); + if (!pUIPdaContactsWnd->Init()) + xr_delete(pUIPdaContactsWnd); + + pUIDiaryWnd = xr_new(); + if (!pUIDiaryWnd->Init()) + xr_delete(pUIDiaryWnd); } UITabControl = xr_new(); @@ -175,24 +216,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; } }; } @@ -253,23 +290,43 @@ 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 }, - }; - - for (const auto& [id, wnd] : availableWindowsList) - { - if (section == id && wnd) + if (ShadowOfChernobylMode) { + const std::tuple availableWindowsList_SOC[] = + { + {"eptTasks", pUIEventsWnd}, + {"eptMap", pUIMapWnd}, + {"eptDiary", pUIDiaryWnd}, + {"eptContacts", pUIPdaContactsWnd}, + {"eptStalkersRanking", pUIEncyclopediaWnd}, + {"eptStatistics", pUIActorInfo}, + {"eptEncyclopedia", pUIEncyclopediaWnd}, + }; + for (const auto& [id, wnd] : availableWindowsList_SOC) + { + if (section == id && wnd) + { + m_pActiveDialog = wnd; + break; + } + } + } + else { + const std::tuple availableWindowsList[] = + { + { "eptMap", pUIMapWnd }, + { "eptTasks", pUITaskWnd }, + { "eptFractionWar", pUIFactionWarWnd }, + { "eptStatistics", pUIActorInfo }, + { "eptRanking", pUIRankingWnd }, + { "eptLogs", pUILogsWnd }, + }; + for (const auto& [id, wnd] : availableWindowsList) { - m_pActiveDialog = wnd; - break; + if (section == id && wnd) + { + m_pActiveDialog = wnd; + break; + } } } @@ -368,8 +425,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 @@ -386,9 +444,7 @@ void CUIPdaWnd::UpdatePda() pUILogsWnd->UpdateNews(); if (m_pActiveDialog == pUITaskWnd && pUITaskWnd) - { pUITaskWnd->ReloadTaskInfo(); - } } void CUIPdaWnd::UpdateRankingWnd() @@ -416,7 +472,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 4949d38dc3f..5e0dc08ca35 100644 --- a/src/xrGame/ui/UIPdaWnd.h +++ b/src/xrGame/ui/UIPdaWnd.h @@ -18,12 +18,16 @@ class CUIActorInfoWnd; class CUIRankingWnd; class CUILogsWnd; class CUIAnimatedStatic; +class CUIEncyclopediaWnd; +class CUIEventsWnd; class UIHint; +class CUIDiaryWnd; +class CUIPdaContactsWnd; class CUIPdaWnd final : public CUIDialogWnd { +private: typedef CUIDialogWnd inherited; - protected: CUITabControl* UITabControl; CUI3tButton* m_btn_close; @@ -45,9 +49,13 @@ class CUIPdaWnd final : public CUIDialogWnd // Поддиалоги PDA CUIMapWnd* pUIMapWnd; CUITaskWnd* pUITaskWnd; + CUIEncyclopediaWnd* pUIEncyclopediaWnd; + CUIPdaContactsWnd* pUIPdaContactsWnd; + CUIEventsWnd* pUIEventsWnd; CUIFactionWarWnd* pUIFactionWarWnd; CUIActorInfoWnd* pUIActorInfo; CUIRankingWnd* pUIRankingWnd; + CUIDiaryWnd* pUIDiaryWnd; CUILogsWnd* pUILogsWnd; virtual void Reset(); @@ -79,6 +87,7 @@ class CUIPdaWnd final : public CUIDialogWnd void Show_SecondTaskWnd(bool status); void Show_MapWnd(bool status); void Show_ContactsWnd(bool status); + 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..9b68ef2d0be 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(); @@ -505,3 +508,269 @@ 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, u16 obj_id) +{ + inherited::InitTask(gt); + + CStringTable stbl; + SGameTaskObjective obj = OwnerTask()->Objective(obj_id); + + 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, u16 obj_id) +{ + inherited::InitTask(gt); + + CStringTable stbl; + SGameTaskObjective obj = OwnerTask()->Objective(obj_id); + + 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..f8c4af3e18d 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; @@ -114,11 +116,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, u16 ob); + 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, u16 ob); + 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..7e8bb1e1bdc 100644 --- a/src/xrGame/xrGame.vcxproj +++ b/src/xrGame/xrGame.vcxproj @@ -1271,9 +1271,13 @@ + + + + @@ -1315,7 +1319,9 @@ + + @@ -1337,6 +1343,7 @@ + @@ -3103,9 +3110,13 @@ + + + + @@ -3190,7 +3201,9 @@ + + @@ -3222,6 +3235,7 @@ + diff --git a/src/xrGame/xrGame.vcxproj.filters b/src/xrGame/xrGame.vcxproj.filters index dc88506d03f..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} @@ -2227,6 +2221,24 @@ {8ca91267-ead8-4233-af9a-9771664b4be5} + + {df96536d-0741-421a-864e-d0f2b39a10ce} + + + {3946c692-4a83-47fe-b1bf-95955dbafe2a} + + + {e608d3d0-db12-46e0-a811-94ca1a5b7938} + + + {4d1f97bc-e355-4d23-929d-844c10d4f4dc} + + + {88b2008c-d91b-4387-b903-9223e6800188} + + + {f21f213a-d49e-4bc4-88eb-c2c3da37b244} + @@ -5740,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 @@ -6308,6 +6320,27 @@ Core\Common\ObjectFactory + + UI\Common\PDA\Events + + + UI\Common\PDA\Tasks + + + UI\Common\PDA\Encyclopedia + + + UI\Common\PDA\Encyclopedia + + + UI\Common\PDA\Diary + + + UI\Common\PDA\Contacts + + + UI\Common\PDA\Contacts + @@ -8909,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 @@ -9495,6 +9528,27 @@ Core\Common\ObjectFactory + + UI\Common\PDA\Events + + + UI\Common\PDA\Tasks + + + UI\Common\PDA\Encyclopedia + + + UI\Common\PDA\Encyclopedia + + + UI\Common\PDA\Diary + + + UI\Common\PDA\Contacts + + + UI\Common\PDA\Contacts + 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/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/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/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 }; 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/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); 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); 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 +