1use crate::Result;
4use crate::ffi::{ImageInfo, raw::HAPI_MaterialInfo};
5use crate::node::{HoudiniNode, NodeHandle};
6use crate::parameter::ParmHandle;
7use crate::session::Session;
8use std::ffi::CString;
9use std::path::Path;
10
11#[derive(Debug, Clone)]
12pub struct Material {
14 pub(crate) session: Session,
15 pub(crate) info: HAPI_MaterialInfo,
16}
17
18impl Material {
19 #[inline]
20 pub fn node(&self) -> Result<HoudiniNode> {
21 HoudiniNode::new(self.session.clone(), self.node_handle(), None)
22 }
23
24 #[inline]
25 fn node_handle(&self) -> NodeHandle {
26 NodeHandle(self.info.nodeId)
27 }
28
29 #[inline]
30 #[must_use]
31 pub fn has_changed(&self) -> bool {
32 self.info.hasChanged > 0
33 }
34
35 pub fn render_texture(&self, parm_name: &str) -> Result<()> {
36 debug_assert!(self.session.is_valid());
37 let name = CString::new(parm_name)?;
38 let id = crate::ffi::get_parm_id_from_name(&name, self.node_handle(), &self.session)?;
39 crate::ffi::render_texture_to_image(&self.session, self.node_handle(), ParmHandle(id))
40 }
41
42 pub fn extract_image_to_file(
43 &self,
44 image_planes: impl AsRef<str>,
45 path: impl AsRef<Path>,
46 ) -> Result<String> {
47 debug_assert!(self.session.is_valid());
48 extract_image_to_file(&self.session, self.node_handle(), image_planes, path)
49 }
50
51 pub fn extract_image_to_memory(
52 &self,
53 buffer: &mut Vec<u8>,
54 image_planes: impl AsRef<str>,
55 format: impl AsRef<str>,
56 ) -> Result<()> {
57 debug_assert!(self.session.is_valid());
58 extract_image_to_memory(
59 &self.session,
60 self.node_handle(),
61 buffer,
62 image_planes,
63 format,
64 )
65 }
66
67 pub fn set_image_info(&self, info: &ImageInfo) -> Result<()> {
68 debug_assert!(self.session.is_valid());
69 crate::ffi::set_image_info(&self.session, self.node_handle(), info)
70 }
71
72 pub fn get_image_info(&self) -> Result<ImageInfo> {
73 debug_assert!(self.session.is_valid());
74 crate::ffi::get_image_info(&self.session, self.node_handle()).map(ImageInfo)
75 }
76
77 pub fn get_image_planes(&self) -> Result<Vec<String>> {
78 debug_assert!(self.session.is_valid());
79 crate::ffi::get_image_planes(&self.session, self.node_handle())
80 .map(|a| a.into_iter().collect())
81 }
82}
83
84pub(crate) fn extract_image_to_file(
85 session: &Session,
86 node: NodeHandle,
87 image_planes: impl AsRef<str>,
88 path: impl AsRef<Path>,
89) -> Result<String> {
90 debug_assert!(session.is_valid());
91 let path = path.as_ref();
92 let format = CString::new(
93 path.extension()
94 .expect("extension")
95 .to_string_lossy()
96 .to_string()
97 .to_uppercase(),
98 )?;
99 let image_planes = CString::new(image_planes.as_ref())?;
100 let dest_folder = crate::utils::path_to_cstring(path.parent().expect("parent"))?;
101 let dest_file = CString::new(
102 path.file_stem()
103 .expect("extension")
104 .to_string_lossy()
105 .to_string(),
106 )?;
107 crate::ffi::extract_image_to_file(
108 session,
109 node,
110 &format,
111 &image_planes,
112 &dest_folder,
113 &dest_file,
114 )
115}
116
117pub(crate) fn extract_image_to_memory(
118 session: &Session,
119 node: NodeHandle,
120 buffer: &mut Vec<u8>,
121 image_planes: impl AsRef<str>,
122 format: impl AsRef<str>,
123) -> Result<()> {
124 let format = CString::new(format.as_ref())?;
125 let image_planes = CString::new(image_planes.as_ref())?;
126 crate::ffi::extract_image_to_memory(session, node, buffer, &format, &image_planes)
127}