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