rpfm_extensions/diagnostics/
anim_fragment_battle.rs1use getset::{Getters, MutGetters};
14use serde_derive::{Serialize, Deserialize};
15
16use std::collections::{HashMap, HashSet};
17use std::{fmt, fmt::Display};
18
19use rpfm_lib::files::{RFile, RFileDecoded};
20
21use crate::dependencies::Dependencies;
22use crate::diagnostics::*;
23
24#[derive(Debug, Clone, Default, Getters, MutGetters, Serialize, Deserialize)]
30#[getset(get = "pub", get_mut = "pub")]
31pub struct AnimFragmentBattleDiagnostic {
32 path: String,
33 pack: String,
34 results: Vec<AnimFragmentBattleDiagnosticReport>
35}
36
37pub type AnimFragmentBattleAnimRefRef = (usize, bool, bool, bool);
41
42pub type AnimFragmentBattleEntryRef = (usize, Option<AnimFragmentBattleAnimRefRef>);
44
45#[derive(Debug, Clone, Getters, MutGetters, Serialize, Deserialize)]
47#[getset(get = "pub", get_mut = "pub")]
48pub struct AnimFragmentBattleDiagnosticReport {
49 locomotion_graph: bool,
50 entry: Option<AnimFragmentBattleEntryRef>,
51 report_type: AnimFragmentBattleDiagnosticReportType,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub enum AnimFragmentBattleDiagnosticReportType {
56 LocomotionGraphPathNotFound(String),
57 FilePathNotFound(String),
58 MetaFilePathNotFound(String),
59 SndFilePathNotFound(String),
60}
61
62impl AnimFragmentBattleDiagnosticReport {
67 pub fn new(report_type: AnimFragmentBattleDiagnosticReportType, locomotion_graph: bool, entry: Option<AnimFragmentBattleEntryRef>) -> Self {
68 Self {
69 locomotion_graph,
70 entry,
71 report_type
72 }
73 }
74}
75
76impl DiagnosticReport for AnimFragmentBattleDiagnosticReport {
77 fn message(&self) -> String {
78 match &self.report_type {
79 AnimFragmentBattleDiagnosticReportType::LocomotionGraphPathNotFound(path) => format!("Locomotion Graph file not found: {path}."),
80 AnimFragmentBattleDiagnosticReportType::FilePathNotFound(path) => format!("'File Path' file not found: {path}."),
81 AnimFragmentBattleDiagnosticReportType::MetaFilePathNotFound(path) => format!("'Meta File Path' file not found: {path}."),
82 AnimFragmentBattleDiagnosticReportType::SndFilePathNotFound(path) => format!("'Snd File Path' file not found: {path}."),
83 }
84 }
85
86 fn level(&self) -> DiagnosticLevel {
87 match self.report_type {
88 AnimFragmentBattleDiagnosticReportType::LocomotionGraphPathNotFound(_) => DiagnosticLevel::Warning,
89 AnimFragmentBattleDiagnosticReportType::FilePathNotFound(_) => DiagnosticLevel::Warning,
90 AnimFragmentBattleDiagnosticReportType::MetaFilePathNotFound(_) => DiagnosticLevel::Warning,
91 AnimFragmentBattleDiagnosticReportType::SndFilePathNotFound(_) => DiagnosticLevel::Warning,
92 }
93 }
94}
95
96impl Display for AnimFragmentBattleDiagnosticReportType {
97 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98 Display::fmt(match self {
99 Self::LocomotionGraphPathNotFound(_) => "LocomotionGraphPathNotFound",
100 Self::FilePathNotFound(_) => "FilePathNotFound",
101 Self::MetaFilePathNotFound(_) => "MetaFilePathNotFound",
102 Self::SndFilePathNotFound(_) => "SndFilePathNotFound",
103 }, f)
104 }
105}
106
107impl AnimFragmentBattleDiagnostic {
108 pub fn new(path: &str, pack: &str) -> Self {
109 Self {
110 path: path.to_owned(),
111 pack: pack.to_owned(),
112 results: vec![],
113 }
114 }
115
116 #[allow(clippy::too_many_arguments)]
118 pub fn check(
119 pack_key: &str,
120 file: &RFile,
121 dependencies: &Dependencies,
122 global_ignored_diagnostics: &[String],
123 ignored_fields: &[String],
124 ignored_diagnostics: &HashSet<String>,
125 ignored_diagnostics_for_fields: &HashMap<String, Vec<String>>,
126 local_path_list: &HashMap<String, Vec<String>>,
127 ) ->Option<DiagnosticType> {
128 if let Ok(RFileDecoded::AnimFragmentBattle(fragment)) = file.decoded() {
129 let mut diagnostic = AnimFragmentBattleDiagnostic::new(file.path_in_container_raw(), pack_key);
130
131 if !Diagnostics::ignore_diagnostic(global_ignored_diagnostics, None, Some("LocomotionGraphPathNotFound"), ignored_fields, ignored_diagnostics, ignored_diagnostics_for_fields) && !fragment.locomotion_graph().is_empty() {
132 let path = fragment.locomotion_graph().replace('\\', "/");
133 let mut path_found = false;
134
135 if !path_found && local_path_list.get(&path.to_lowercase()).is_some() {
136 path_found = true;
137 }
138
139 if !path_found && dependencies.file_exists(&path, true, true, true) {
140 path_found = true;
141 }
142
143 if !path_found {
144 let result = AnimFragmentBattleDiagnosticReport::new(AnimFragmentBattleDiagnosticReportType::LocomotionGraphPathNotFound(fragment.locomotion_graph().to_owned()), true, None);
145 diagnostic.results_mut().push(result);
146 }
147 }
148
149 for (row, entry) in fragment.entries().iter().enumerate() {
150 for (subrow, anim_ref) in entry.anim_refs().iter().enumerate() {
151 if !Diagnostics::ignore_diagnostic(global_ignored_diagnostics, None, Some("FilePathNotFound"), ignored_fields, ignored_diagnostics, ignored_diagnostics_for_fields) && !anim_ref.file_path().is_empty() {
152 let path = anim_ref.file_path().replace('\\', "/");
153 let mut path_found = false;
154
155 if !path_found && local_path_list.get(&path.to_lowercase()).is_some() {
156 path_found = true;
157 }
158
159 if !path_found && dependencies.file_exists(&path, true, true, true) {
160 path_found = true;
161 }
162
163 if !path_found {
164 let result = AnimFragmentBattleDiagnosticReport::new(AnimFragmentBattleDiagnosticReportType::FilePathNotFound(anim_ref.file_path().to_owned()), false, Some((row, Some((subrow, true, false, false)))));
165 diagnostic.results_mut().push(result);
166 }
167 }
168
169 if !Diagnostics::ignore_diagnostic(global_ignored_diagnostics, None, Some("MetaFilePathNotFound"), ignored_fields, ignored_diagnostics, ignored_diagnostics_for_fields) && !anim_ref.meta_file_path().is_empty() {
170 let path = anim_ref.meta_file_path().replace('\\', "/");
171 let mut path_found = false;
172
173 if !path_found && local_path_list.get(&path.to_lowercase()).is_some() {
174 path_found = true;
175 }
176
177 if !path_found && dependencies.file_exists(&path, true, true, true) {
178 path_found = true;
179 }
180
181 if !path_found {
182 let result = AnimFragmentBattleDiagnosticReport::new(AnimFragmentBattleDiagnosticReportType::MetaFilePathNotFound(anim_ref.meta_file_path().to_owned()), false, Some((row, Some((subrow, false, true, false)))));
183 diagnostic.results_mut().push(result);
184 }
185 }
186
187 if !Diagnostics::ignore_diagnostic(global_ignored_diagnostics, None, Some("SndFilePathNotFound"), ignored_fields, ignored_diagnostics, ignored_diagnostics_for_fields) && !anim_ref.snd_file_path().is_empty() {
188 let path = anim_ref.snd_file_path().replace('\\', "/");
189 let mut path_found = false;
190
191 if !path_found && local_path_list.get(&path.to_lowercase()).is_some() {
192 path_found = true;
193 }
194
195 if !path_found && dependencies.file_exists(&path, true, true, true) {
196 path_found = true;
197 }
198
199 if !path_found {
200 let result = AnimFragmentBattleDiagnosticReport::new(AnimFragmentBattleDiagnosticReportType::SndFilePathNotFound(anim_ref.snd_file_path().to_owned()), false, Some((row, Some((subrow, false, false, true)))));
201 diagnostic.results_mut().push(result);
202 }
203 }
204 }
205 }
206
207 if !diagnostic.results().is_empty() {
208 Some(DiagnosticType::AnimFragmentBattle(diagnostic))
209 } else { None }
210 } else { None }
211 }
212}