PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/crates/broanetco_game/src/texture.rs

https://gitlab.com/rardiol/BroaNetCo
Rust | 398 lines | 338 code | 30 blank | 30 comment | 16 complexity | 92dcce374aa4704b303960a1f7c7350f MD5 | raw file
  1. /*
  2. * Copyright 2018 Ricardo Luis Souza Ardissone
  3. *
  4. * This file is part of BroaNetCo.
  5. *
  6. * BroaNetCo is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * BroaNetCo is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with BroaNetCo. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. use std::iter;
  20. use std::path::PathBuf;
  21. use crate::map::*;
  22. use crate::replay::{ReplayLog, ReplayLoggerMessage};
  23. use crate::*;
  24. pub type NTDGroup<T> = (TextureParams, Vec<T>);
  25. #[allow(dead_code)]
  26. pub type NTDTGroup = NTDGroup<NamedTextureDataTransfer>;
  27. pub type MapNTDGroup<T> = Vec<T>;
  28. #[derive(Clone, Debug, Serialize, Deserialize, Default, Derivative)]
  29. #[derivative(Hash)]
  30. pub struct NamedTextureData<TE> {
  31. #[serde(skip_serializing)]
  32. #[serde(skip_deserializing)]
  33. #[derivative(Hash = "ignore")]
  34. pub texture_data: TE,
  35. // TODO: An alternative to this
  36. pub asset_path: NTDAssetPath,
  37. }
  38. /// Doesn't contain actual textures, just the asset name
  39. pub type NamedTextureDataTransfer = NamedTextureData<()>;
  40. impl<T> NamedTextureData<T> {
  41. pub const fn new_textured(asset_path: NTDAssetPath, texture_data: T) -> Self {
  42. Self {
  43. asset_path,
  44. texture_data,
  45. }
  46. }
  47. }
  48. impl NamedTextureDataTransfer {
  49. pub const fn new(asset_path: NTDAssetPath) -> Self {
  50. Self::new_textured(asset_path, ())
  51. }
  52. }
  53. /// Information about how the NTDGroup should be drawn
  54. #[derive(Copy, Clone, Debug, Serialize, Hash, Deserialize, Derivative)]
  55. #[derivative(Default)]
  56. pub enum TextureParams {
  57. #[derivative(Default)]
  58. /// Rotate the top of the image to the direction it is pointing to
  59. /// Draw entire image with scaling
  60. TopDown,
  61. /// Draw the entire image without rotation with scaling
  62. Simple,
  63. /// Treat the image as if from https://github.com/cosmo-ray/Universal-LPC-spritesheet
  64. LPC,
  65. }
  66. /// Where to find an image for texture
  67. #[derive(Clone, Debug, Serialize, Hash, Deserialize, Derivative)]
  68. #[derivative(Default)]
  69. pub enum NTDAssetPath {
  70. /// Simple image loaded from file
  71. #[derivative(Default)]
  72. Image(PathBuf),
  73. /// Layer of an xcf file
  74. #[cfg(feature = "xcf")]
  75. XcfLayer { layer: String, file_path: PathBuf },
  76. }
  77. pub type NTDT = NamedTextureDataTransfer;
  78. pub trait NTDTrait: TryIntoParams<(), NamedTextureDataTransfer> + Debug + Clone {}
  79. /// Try Into with parameters
  80. pub trait TryIntoParams<Params, Out> {
  81. type Error: Debug;
  82. fn try_into_params(self, params: &mut Params) -> Result<Out, Self::Error>;
  83. }
  84. /// Into with parameters
  85. pub trait IntoParams<Params, Out> {
  86. fn into_params(self, params: &mut Params) -> Out;
  87. }
  88. impl<Params, Out, T> IntoParams<Params, Out> for T
  89. where
  90. T: TryIntoParams<Params, Out, Error = Void>,
  91. {
  92. fn into_params(self, params: &mut Params) -> Out {
  93. self.try_into_params(params).unwrap()
  94. }
  95. }
  96. impl NTDTrait for NamedTextureDataTransfer {}
  97. impl TryIntoParams<(), NamedTextureDataTransfer> for NamedTextureDataTransfer {
  98. type Error = Void;
  99. fn try_into_params(self, (): &mut ()) -> Result<NamedTextureDataTransfer, Void> {
  100. Ok(self)
  101. }
  102. }
  103. fn it_ut<
  104. Params,
  105. IN: TryIntoParams<Params, OUT, Error = Error>,
  106. OUT,
  107. IT: iter::IntoIterator<Item = IN>,
  108. OUTIT: iter::FromIterator<OUT>,
  109. Error: Debug,
  110. >(
  111. iter: IT,
  112. params: &mut Params,
  113. ) -> Result<OUTIT, Error> {
  114. crate::util::iter_result_convert(iter, |x| x.try_into_params(params))
  115. }
  116. impl<Params, NTD: TryIntoParams<Params, NTDOut>, NTDOut> TryIntoParams<Params, GSInit<NTDOut>>
  117. for GSInit<NTD>
  118. {
  119. type Error = <NTD as TryIntoParams<Params, NTDOut>>::Error;
  120. fn try_into_params(self, params: &mut Params) -> Result<GSInit<NTDOut>, Self::Error> {
  121. use GSInit::*;
  122. Ok(match self {
  123. GGSA(vec) => GGSA(it_ut(vec, params)?),
  124. ReplayLog(log) => ReplayLog(Box::new(log.try_into_params(params)?)),
  125. })
  126. }
  127. }
  128. impl<Params, NTD: TryIntoParams<Params, NTDOut>, NTDOut>
  129. TryIntoParams<Params, ReplayLoggerMessage<NTDOut>> for ReplayLoggerMessage<NTD>
  130. {
  131. type Error = <NTD as TryIntoParams<Params, NTDOut>>::Error;
  132. fn try_into_params(
  133. self,
  134. params: &mut Params,
  135. ) -> Result<ReplayLoggerMessage<NTDOut>, Self::Error> {
  136. Ok(match self {
  137. Self::GSApply(gsa) => ReplayLoggerMessage::GSApply(gsa),
  138. Self::GodGSApply(ggsa) => {
  139. ReplayLoggerMessage::GodGSApply(ggsa.try_into_params(params)?)
  140. }
  141. })
  142. }
  143. }
  144. impl<Params, NTD: TryIntoParams<Params, NTDOut>, NTDOut> TryIntoParams<Params, ReplayLog<NTDOut>>
  145. for ReplayLog<NTD>
  146. {
  147. type Error = <NTD as TryIntoParams<Params, NTDOut>>::Error;
  148. fn try_into_params(self, params: &mut Params) -> Result<ReplayLog<NTDOut>, Self::Error> {
  149. Ok((self.0.try_into_params(params)?, it_ut(self.1, params)?))
  150. }
  151. }
  152. impl<Params, NTD: TryIntoParams<Params, NTDOut>, NTDOut> TryIntoParams<Params, MapElement<NTDOut>>
  153. for MapElement<NTD>
  154. {
  155. type Error = <NTD as TryIntoParams<Params, NTDOut>>::Error;
  156. fn try_into_params(self, params: &mut Params) -> Result<MapElement<NTDOut>, Self::Error> {
  157. let dissolved: (_, _, _, _, _, _, _, _, _, _) = self.into();
  158. let converted = (
  159. dissolved.0,
  160. dissolved.1,
  161. dissolved.2,
  162. dissolved.3,
  163. dissolved.4,
  164. dissolved.5,
  165. dissolved.6,
  166. dissolved.7,
  167. it_ut(dissolved.8, params)?,
  168. dissolved.9,
  169. );
  170. Ok(converted.into())
  171. }
  172. }
  173. impl<Params, TOut, TIn: TryIntoParams<Params, TOut>> TryIntoParams<Params, (MapLocation, TOut)>
  174. for (MapLocation, TIn)
  175. {
  176. type Error = <TIn as TryIntoParams<Params, TOut>>::Error;
  177. fn try_into_params(self, params: &mut Params) -> Result<(MapLocation, TOut), Self::Error> {
  178. Ok((self.0, self.1.try_into_params(params)?))
  179. }
  180. }
  181. impl<Params, T2, T: TryIntoParams<Params, T2>> TryIntoParams<Params, Option<T2>> for Option<T> {
  182. type Error = <T as TryIntoParams<Params, T2>>::Error;
  183. fn try_into_params(self, params: &mut Params) -> Result<Option<T2>, Self::Error> {
  184. self.map(|x| x.try_into_params(params)).transpose()
  185. }
  186. }
  187. impl<Params, NTD: TryIntoParams<Params, NTDOut>, NTDOut> TryIntoParams<Params, Map<NTDOut>>
  188. for Map<NTD>
  189. {
  190. type Error = <NTD as TryIntoParams<Params, NTDOut>>::Error;
  191. fn try_into_params(self, params: &mut Params) -> Result<Map<NTDOut>, Self::Error> {
  192. use toodee::TooDeeOps;
  193. let dissolved: (_, _, _) = self.into();
  194. let converted = (
  195. dissolved.0,
  196. dissolved.1,
  197. TooDee::from_vec(
  198. dissolved.2.num_cols(),
  199. dissolved.2.num_rows(),
  200. crate::util::iter_result_convert(dissolved.2, |x| x.try_into_params(params))?,
  201. ),
  202. );
  203. Ok(converted.into())
  204. }
  205. }
  206. impl<T, Params, NTD: TryIntoParams<Params, NTDOut>, NTDOut>
  207. TryIntoParams<Params, (Status<NTDOut>, T)> for (Status<NTD>, T)
  208. {
  209. type Error = <NTD as TryIntoParams<Params, NTDOut>>::Error;
  210. fn try_into_params(self, params: &mut Params) -> Result<(Status<NTDOut>, T), Self::Error> {
  211. Ok((self.0.try_into_params(params)?, self.1))
  212. }
  213. }
  214. impl<Params, NTD: TryIntoParams<Params, NTDOut>, NTDOut> TryIntoParams<Params, Status<NTDOut>>
  215. for Status<NTD>
  216. {
  217. type Error = <NTD as TryIntoParams<Params, NTDOut>>::Error;
  218. fn try_into_params(self, params: &mut Params) -> Result<Status<NTDOut>, Self::Error> {
  219. let dissolved: (_, _, _, _, _, _, _) = self.into();
  220. let (a, b) = dissolved.6;
  221. let converted = (
  222. dissolved.0,
  223. it_ut::<_, _, _, Vec<_>, Vec<_>, _>(dissolved.1.into(), params)?.into(),
  224. it_ut::<_, _, _, Vec<_>, Vec<_>, _>(dissolved.2.into(), params)?.into(),
  225. dissolved.3,
  226. dissolved.4,
  227. dissolved.5,
  228. (a, it_ut(b, params)?),
  229. );
  230. Ok(converted.into())
  231. }
  232. }
  233. impl<Params, NTD: TryIntoParams<Params, NTDOut>, NTDOut> TryIntoParams<Params, Combater<NTDOut>>
  234. for Combater<NTD>
  235. {
  236. type Error = <NTD as TryIntoParams<Params, NTDOut>>::Error;
  237. fn try_into_params(self, params: &mut Params) -> Result<Combater<NTDOut>, Self::Error> {
  238. let dissolved: (_, _, _, _, _, _, _, _, _, _) = self.into();
  239. let (a, b) = dissolved.7;
  240. let converted = (
  241. dissolved.0,
  242. it_ut(dissolved.1, params)?,
  243. dissolved.2,
  244. dissolved.3,
  245. dissolved.4,
  246. dissolved.5,
  247. dissolved.6,
  248. (a, it_ut(b, params)?),
  249. dissolved.8,
  250. dissolved.9,
  251. );
  252. Ok(converted.into())
  253. }
  254. }
  255. impl<Params, NTD: TryIntoParams<Params, NTDOut>, NTDOut> TryIntoParams<Params, Faction<NTDOut>>
  256. for Faction<NTD>
  257. {
  258. type Error = <NTD as TryIntoParams<Params, NTDOut>>::Error;
  259. fn try_into_params(self, params: &mut Params) -> Result<Faction<NTDOut>, Self::Error> {
  260. let dissolved: (_, _, _, _, _) = self.into();
  261. let converted = (
  262. dissolved.0,
  263. dissolved.1,
  264. dissolved.2,
  265. dissolved.3,
  266. dissolved.4.try_into_params(params)?,
  267. );
  268. Ok(converted.into())
  269. }
  270. }
  271. impl<Params, NTD: TryIntoParams<Params, NTDOut>, NTDOut> TryIntoParams<Params, GodGSApply<NTDOut>>
  272. for GodGSApply<NTD>
  273. {
  274. type Error = <NTD as TryIntoParams<Params, NTDOut>>::Error;
  275. fn try_into_params(self, params: &mut Params) -> Result<GodGSApply<NTDOut>, Self::Error> {
  276. use GodGSApply::*;
  277. Ok(match self {
  278. AddCombater(com) => AddCombater(com.try_into_params(params)?),
  279. AddFaction(faction) => AddFaction(faction.try_into_params(params)?),
  280. AddAIGameMaster(priority, aigm) => {
  281. AddAIGameMaster(priority, aigm.try_into_params(params)?)
  282. }
  283. SetMapElement { location, element } => SetMapElement {
  284. location,
  285. element: element.try_into_params(params)?,
  286. },
  287. GSApply(gsapply) => GSApply(gsapply),
  288. SetRNG(seed) => SetRNG(seed),
  289. SetPlayingID(id) => SetPlayingID(id),
  290. SetName(name) => SetName(name),
  291. SetTick(x) => SetTick(x),
  292. GSEffect(x) => GSEffect(x),
  293. })
  294. }
  295. }
  296. impl<Params, NTD: TryIntoParams<Params, NTDOut>, NTDOut> TryIntoParams<Params, AIGameMaster<NTDOut>>
  297. for AIGameMaster<NTD>
  298. {
  299. type Error = <NTD as TryIntoParams<Params, NTDOut>>::Error;
  300. fn try_into_params(self, params: &mut Params) -> Result<AIGameMaster<NTDOut>, Self::Error> {
  301. use AIGameMaster::*;
  302. Ok(match self {
  303. ExpandMapRangeCombater { range, element } => ExpandMapRangeCombater {
  304. range,
  305. element: element.try_into_params(params)?,
  306. },
  307. MapSpreader {
  308. interval,
  309. next_tick,
  310. spreader_name,
  311. odds,
  312. overtextures,
  313. new_element,
  314. range,
  315. } => MapSpreader {
  316. interval,
  317. next_tick,
  318. spreader_name,
  319. odds,
  320. overtextures,
  321. new_element: new_element.try_into_params(params)?,
  322. range,
  323. },
  324. Spawn {
  325. positions,
  326. combater,
  327. next_tick,
  328. interval,
  329. } => Spawn {
  330. positions,
  331. combater,
  332. next_tick,
  333. interval,
  334. },
  335. KingOfTheHill {
  336. valid_for,
  337. position,
  338. ticks,
  339. startcount,
  340. } => KingOfTheHill {
  341. valid_for,
  342. position,
  343. ticks,
  344. startcount,
  345. },
  346. CombaterEffectOnTerrain {
  347. map_element_name,
  348. effect,
  349. } => CombaterEffectOnTerrain {
  350. map_element_name,
  351. effect,
  352. },
  353. LastManStanding { valid_for } => LastManStanding { valid_for },
  354. Choice {
  355. tick,
  356. faction,
  357. text,
  358. choices,
  359. } => Choice {
  360. tick,
  361. faction,
  362. text,
  363. choices,
  364. },
  365. RevealMap { range } => RevealMap { range },
  366. })
  367. }
  368. }