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