hapi_rs/ffi/
structs.rs

1use super::raw::*;
2use crate::{
3    errors::Result,
4    node::{HoudiniNode, NodeHandle},
5    parameter::ParmHandle,
6    pdg::WorkItemId,
7    session::Session,
8    stringhandle::StringHandle,
9};
10use debug_ignore::DebugIgnore;
11use pastey::paste;
12use std::ffi::{CStr, CString};
13
14macro_rules! get {
15
16    ($method:ident->$field:ident->bool) => {
17        #[inline]
18        pub fn $method(&self) -> bool {
19            self.0.$field == 1
20        }
21    };
22
23    // wrap raw ids into handle i.e NodeHandle, ParmHandle etc
24    ($method:ident->$field:ident->[handle: $hdl:ident]) => {
25        #[inline]
26        pub fn $method(&self) -> $hdl {
27            $hdl(self.0.$field)
28        }
29    };
30
31    ($self_:ident, $method:ident->$block:block->$tp:ty) => {
32        #[inline]
33        pub fn $method(&$self_) -> $tp {
34            $block
35        }
36    };
37
38    ($method:ident->$field:ident->Result<String>) => {
39        #[inline]
40        pub fn $method(&self) -> Result<String> {
41            use crate::stringhandle::StringHandle;
42            crate::stringhandle::get_string(StringHandle(self.0.$field), &self.1)
43        }
44    };
45
46    (with_session $method:ident->$field:ident->Result<String>) => {
47        #[inline]
48        pub fn $method(&self, session: &Session) -> Result<String> {
49            use crate::stringhandle::StringHandle;
50            crate::stringhandle::get_string(StringHandle(self.0.$field), session)
51        }
52    };
53
54    ($method:ident->$field:ident->Result<CString>) => {
55        #[inline]
56        pub fn $method(&self) -> Result<CString> {
57            use crate::stringhandle::StringHandle;
58            crate::stringhandle::get_cstring(StringHandle(self.0.$field), &self.1)
59        }
60    };
61
62    ($method:ident->$field:ident->$tp:ty) => {
63        #[inline]
64        pub fn $method(&self) -> $tp {
65            self.0.$field
66        }
67    };
68
69    ($method:ident->$field:ident->[$($tp:tt)*]) => {
70        get!($method->$field->[$($tp)*]);
71    };
72}
73// Impl Default trait for struct
74// Default StructName [HapiFunction => HapiType];
75// Example: Default CurveInfo [HAPI_CurveInfo_Create => HAPI_CurveInfo];
76//
77// Generate getters, setters and with ("builder") methods
78// [get|set|with] struct_field->ffiStructField->[ValueType];
79//  get:
80//      fn get_struct_field(&self) -> ValueType { self.ffiStructField }
81//  set:
82//      fn set_struct_field(&self, val: ValueType)  { self.ffiStructField = val; }
83//  with:
84//      fn with_struct_field(self, val: ValueType) -> Self  { self.ffiStructField = val; self }
85//
86// Special case for string handles:
87// [get+session] name->name->[ValueType]
88// fn get_name(&self, session: &Session) -> Result<String> { session.get_string(self.0.name) }
89//
90
91macro_rules! wrap {
92    (_with_ $method:ident->$field:ident->bool) => {
93        paste!{
94            pub fn [<with_ $method>](mut self, val: bool) -> Self {self.0.$field = val as i8; self}
95        }
96    };
97    (_with_ $method:ident->$field:ident->$tp:ty) => {
98        paste!{
99            pub fn [<with_ $method>](mut self, val: $tp) -> Self {self.0.$field = val; self}
100        }
101    };
102    (_set_ $method:ident->$field:ident->bool) => {
103        paste!{
104            pub fn [<set_ $method>](&mut self, val: bool)  {self.0.$field = val as i8}
105        }
106    };
107    (_set_ $method:ident->$field:ident->$tp:ty) => {
108        paste!{
109            pub fn [<set_ $method>](&mut self, val: $tp)  {self.0.$field = val}
110        }
111    };
112
113    // impl [get|set]
114    ([get] $object:ident $method:ident->$field:ident->$($tp:tt)*) => {
115        get!($method->$field->$($tp)*);
116    };
117
118    ([get+session] $object:ident $method:ident->$field:ident->$($tp:tt)*) => {
119        get!(with_session $method->$field->$($tp)*);
120    };
121
122    ([set] $object:ident $method:ident->$field:ident->$($tp:tt)*) => {
123        $(wrap!{_set_ $method->$field->$tp})*
124    };
125
126    ([with] $object:ident $method:ident->$field:ident->$($tp:tt)*) => {
127        $(wrap!{_with_ $method->$field->$tp})*
128    };
129
130    ([get|set] $object:ident $method:ident->$field:ident->$($tp:tt)*) => {
131        get!($method->$field->$($tp)*);
132        $(wrap!{_set_ $method->$field->$tp})*
133    };
134    ([get|set|with] $object:ident $method:ident->$field:ident->$($tp:tt)*) => {
135        get!($method->$field->$($tp)*);
136        $(wrap!{_set_ $method->$field->$tp})*
137        $(wrap!{_with_ $method->$field->$tp})*
138    };
139
140    (Default $object:ident [$create_func:path=>$ffi_tp:ty]; $($rest:tt)*) => {
141        impl Default for $object {
142            fn default() -> Self {
143                #[allow(unused_unsafe)]
144                Self(unsafe { $create_func() })
145            }
146        }
147        wrap!{_impl_methods_ $object $ffi_tp $($rest)*}
148    };
149
150    (impl $object:ident=>$ffi_tp:ty; $($rest:tt)*) => {
151        wrap!{_impl_methods_ $object $ffi_tp $($rest)*}
152    };
153
154
155    (_impl_methods_ $object:ident $ffi_tp:ty
156        $([$($access:tt)*] $method:ident->$field:ident->[$($tp:tt)*]);* $(;)?
157    ) => {
158        impl $object {
159            $(wrap!([$($access)*] $object $method->$field->$($tp)*);)*
160
161            #[inline]
162            pub fn ptr(&self) -> *const $ffi_tp {
163                &self.0 as *const _
164            }
165        }
166    };
167}
168
169/// Configurations for sessions.
170/// Note: For async attribute access, make sure to set connection_count to at least 1.
171#[derive(Clone, Debug)]
172pub struct SessionInfo(pub(crate) HAPI_SessionInfo);
173
174wrap! {
175    Default SessionInfo [HAPI_SessionInfo_Create => HAPI_SessionInfo];
176    [get|set|with] connection_count->connectionCount->[i32];
177    [get|set|with] port_type->portType->[TcpPortType];
178    [get] min_port->minPort->[i32];
179    [get] max_port->maxPort->[i32];
180    [get] ports->ports->[[i32;128usize]];
181    [get] shared_memory_buffer_type->sharedMemoryBufferType->[ThriftSharedMemoryBufferType];
182    [get] shared_memory_buffer_size->sharedMemoryBufferSize->[i64];
183}
184
185// We need to make sure the server values match the session values, so we don't allow the user to change this via the SessionInfo struct
186impl SessionInfo {
187    pub(crate) fn set_shared_memory_buffer_type(&mut self, value: ThriftSharedMemoryBufferType) {
188        self.0.sharedMemoryBufferType = value;
189    }
190
191    pub(crate) fn set_shared_memory_buffer_size(&mut self, value: i64) {
192        self.0.sharedMemoryBufferSize = value;
193    }
194}
195
196/// Options to configure a Thrift server being started from HARC.
197#[derive(Clone, Debug)]
198pub struct ThriftServerOptions(pub(crate) HAPI_ThriftServerOptions);
199
200wrap! {
201    Default ThriftServerOptions [HAPI_ThriftServerOptions_Create => HAPI_ThriftServerOptions];
202    [get|set|with] auto_close->autoClose->[bool];
203    [get|set|with] timeout_ms->timeoutMs->[f32];
204    [get|set|with] verbosity->verbosity->[StatusVerbosity];
205    [get|set|with] shared_memory_buffer_type->sharedMemoryBufferType->[ThriftSharedMemoryBufferType];
206    [get|set|with] shared_memory_buffer_size->sharedMemoryBufferSize->[i64];
207}
208
209#[derive(Clone)]
210pub struct CompositorOptions(pub(crate) HAPI_CompositorOptions);
211
212wrap! {
213    Default CompositorOptions [HAPI_CompositorOptions_Create => HAPI_CompositorOptions];
214    [get|set] max_resolution_x->maximumResolutionX->[i32];
215    [get|set] max_resolution_y->maximumResolutionY->[i32];
216}
217
218/// Menu parameter label and value
219#[derive(Clone)]
220pub struct ParmChoiceInfo(pub(crate) HAPI_ParmChoiceInfo, pub(crate) Session);
221
222impl std::fmt::Debug for ParmChoiceInfo {
223    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
224        use std::borrow::Cow;
225
226        let get_str = |h: i32| -> Cow<str> {
227            match crate::ffi::get_string_bytes(&self.1, StringHandle(h)) {
228                // SAFETY: Don't care about utf in Debug
229                Ok(bytes) => unsafe { Cow::Owned(String::from_utf8_unchecked(bytes)) },
230                Err(_) => Cow::Borrowed("!!! Could not retrieve string"),
231            }
232        };
233
234        f.debug_struct("ParmChoiceInfo")
235            .field("label", &get_str(self.0.labelSH))
236            .field("value", &get_str(self.0.valueSH))
237            .finish()
238    }
239}
240
241impl ParmChoiceInfo {
242    get!(value->valueSH->Result<String>);
243    get!(label->labelSH->Result<String>);
244}
245
246/// [Documentation](https://www.sidefx.com/docs/hengine/struct_h_a_p_i___parm_info.html)
247#[derive(Debug)]
248pub struct ParmInfo(
249    pub(crate) HAPI_ParmInfo,
250    pub(crate) DebugIgnore<Session>,
251    pub(crate) Option<CString>,
252);
253
254impl ParmInfo {
255    pub(crate) fn new(inner: HAPI_ParmInfo, session: Session, name: Option<CString>) -> Self {
256        Self(inner, DebugIgnore(session), name)
257    }
258}
259
260impl ParmInfo {
261    get!(id->id->[handle: ParmHandle]);
262    get!(parent_id->parentId->[handle: ParmHandle]);
263    get!(child_index->childIndex->i32);
264    get!(parm_type->type_->ParmType);
265    get!(script_type->scriptType->PrmScriptType);
266    get!(permissions->permissions->Permissions);
267    get!(tag_count->tagCount->i32);
268    get!(size->size->i32);
269    get!(choice_count->choiceCount->i32);
270    get!(choice_list_type->choiceListType->ChoiceListType);
271    get!(has_min->hasMin->bool);
272    get!(has_max->hasMax->bool);
273    get!(has_uimin->hasUIMin->bool);
274    get!(has_uimax->hasUIMax->bool);
275    get!(min->min->f32);
276    get!(max->max->f32);
277    get!(uimin->UIMin->f32);
278    get!(uimax->UIMax->f32);
279    get!(invisible->invisible->bool);
280    get!(disabled->disabled->bool);
281    get!(spare->spare->bool);
282    get!(join_next->joinNext->bool);
283    get!(label_none->labelNone->bool);
284    get!(int_values_index->intValuesIndex->i32);
285    get!(float_values_index->floatValuesIndex->i32);
286    get!(string_values_index->stringValuesIndex->i32);
287    get!(choice_index->choiceIndex->i32);
288    get!(input_node_type->inputNodeType->NodeType);
289    get!(input_node_flag->inputNodeFlag->NodeFlags);
290    get!(is_child_of_multi_parm->isChildOfMultiParm->bool);
291    get!(instance_num->instanceNum->i32);
292    get!(instance_length->instanceLength->i32);
293    get!(instance_count->instanceCount->i32);
294    get!(instance_start_offset->instanceStartOffset->i32);
295    get!(ramp_type->rampType->RampType);
296    get!(type_info->typeInfoSH->Result<String>);
297    get!(name->nameSH->Result<String>);
298    get!(name_cstr->nameSH->Result<CString>);
299    get!(label->labelSH->Result<String>);
300    get!(template_name->templateNameSH->Result<String>);
301    get!(help->helpSH->Result<String>);
302    get!(visibility_condition->visibilityConditionSH->Result<String>);
303    get!(disabled_condition->disabledConditionSH->Result<String>);
304}
305
306// #[derive(Clone)]
307/// [Documentation](https://www.sidefx.com/docs/hengine/struct_h_a_p_i___node_info.html)
308pub struct NodeInfo(pub(crate) HAPI_NodeInfo, pub(crate) DebugIgnore<Session>);
309
310impl NodeInfo {
311    get!(name->nameSH->Result<String>);
312    get!(internal_path->internalNodePathSH->Result<String>);
313    get!(node_type->type_->NodeType);
314    get!(is_valid->isValid->bool);
315    get!(unique_node_id->uniqueHoudiniNodeId->i32);
316    get!(total_cook_count->totalCookCount->i32);
317    get!(child_node_count->childNodeCount->i32);
318    get!(parm_count->parmCount->i32);
319    get!(input_count->inputCount->i32);
320    get!(output_count->outputCount->i32);
321    get!(is_time_dependent->isTimeDependent->bool);
322    get!(created_post_asset_load->createdPostAssetLoad->bool);
323    get!(parm_int_value_count->parmIntValueCount->i32);
324    get!(parm_float_value_count->parmFloatValueCount->i32);
325    get!(parm_string_value_count->parmStringValueCount->i32);
326    get!(parm_choice_count->parmChoiceCount->i32);
327    get!(node_handle->id->[handle: NodeHandle]);
328    get!(parent_id->parentId->[handle: NodeHandle]);
329
330    pub(crate) fn new(session: &Session, node: NodeHandle) -> Result<Self> {
331        let session = session.clone();
332        let inner = crate::ffi::get_node_info(node, &session)?;
333        Ok(Self(inner, DebugIgnore(session)))
334    }
335}
336
337impl std::fmt::Debug for NodeInfo {
338    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
339        let err = "Error in Debug impl";
340        f.debug_struct("NodeInfo")
341            .field("name", &self.name().as_deref().unwrap_or(err))
342            .field(
343                "internal_path",
344                &self.internal_path().as_deref().unwrap_or(err),
345            )
346            .field("type", &self.node_type())
347            .field("is_valid", &self.is_valid())
348            .field("time_dependent", &self.is_time_dependent())
349            .field("total_cook_count", &self.total_cook_count())
350            .field("parm_count", &self.parm_count())
351            .field("child_count", &self.child_node_count())
352            .field("input_count", &self.input_count())
353            .field("output_count", &self.output_count())
354            .finish()
355    }
356}
357
358/// [Documentation](https://www.sidefx.com/docs/hengine/struct_h_a_p_i___cook_options.html)
359#[derive(Debug, Clone)]
360pub struct CookOptions(pub(crate) HAPI_CookOptions);
361
362wrap!(
363    Default CookOptions [HAPI_CookOptions_Create => HAPI_CookOptions];
364    [get|set|with] split_geo_by_group->splitGeosByGroup->[bool];
365    [get|set|with] split_geos_by_attribute->splitGeosByAttribute->[bool];
366    [get|set|with] max_vertices_per_primitive->maxVerticesPerPrimitive->[i32];
367    [get|set|with] refine_curve_to_linear->refineCurveToLinear->[bool];
368    [get|set|with] curve_refine_lod->curveRefineLOD->[f32];
369    [get|set|with] clear_errors_and_warnings->clearErrorsAndWarnings->[bool];
370    [get|set|with] cook_templated_geos->cookTemplatedGeos->[bool];
371    [get|set|with] split_points_by_vertex_attributes->splitPointsByVertexAttributes->[bool];
372    [get|set|with] handle_box_part_types->handleBoxPartTypes->[bool];
373    [get|set|with] handle_sphere_part_types->handleSpherePartTypes->[bool];
374    [get|set|with] check_part_changes->checkPartChanges->[bool];
375    [get|set|with] cache_mesh_topology->cacheMeshTopology->[bool];
376    [get|set|with] prefer_output_nodes->preferOutputNodes->[bool];
377    [get|set|with] packed_prim_instancing_mode->packedPrimInstancingMode->[PackedPrimInstancingMode];
378    [get+session] split_attr->splitAttrSH->[Result<String>];
379);
380
381#[derive(Debug, Clone)]
382pub struct AttributeInfo(pub(crate) HAPI_AttributeInfo);
383
384impl Default for AttributeInfo {
385    fn default() -> Self {
386        let mut inner = unsafe { HAPI_AttributeInfo_Create() };
387        // FIXME: Uninitialized variable in Houdini 20.0.625
388        inner.totalArrayElements = 0;
389        Self(inner)
390    }
391}
392wrap! {
393  _impl_methods_ AttributeInfo HAPI_AttributeInfo[get]exists->exists->[bool];
394  [get]original_owner->originalOwner->[AttributeOwner];
395  [get|set|with]total_array_elements->totalArrayElements->[i64];
396  [get|set|with]owner->owner->[AttributeOwner];
397  [get|set|with]storage->storage->[StorageType];
398  [get|set|with]tuple_size->tupleSize->[i32];
399  [get|set|with]type_info->typeInfo->[AttributeTypeInfo];
400  [get|set|with]count->count->[i32];
401}
402
403impl AttributeInfo {
404    pub(crate) fn new(
405        node: &HoudiniNode,
406        part_id: i32,
407        owner: AttributeOwner,
408        name: &CStr,
409    ) -> Result<Self> {
410        Ok(Self(crate::ffi::get_attribute_info(
411            node, part_id, owner, name,
412        )?))
413    }
414}
415
416/// [Documentation](https://www.sidefx.com/docs/hengine/struct_h_a_p_i___asset_info.html)
417#[derive(Debug)]
418pub struct AssetInfo(pub(crate) HAPI_AssetInfo, pub DebugIgnore<Session>);
419
420impl AssetInfo {
421    get!(node_id->nodeId->[handle: NodeHandle]);
422    get!(object_node_id->objectNodeId->[handle: NodeHandle]);
423    get!(has_ever_cooked->hasEverCooked->bool);
424    get!(have_objects_changed->haveObjectsChanged->bool);
425    get!(have_materials_changed->haveMaterialsChanged->bool);
426    get!(object_count->objectCount->i32);
427    get!(handle_count->handleCount->i32);
428    get!(transform_input_count->transformInputCount->i32);
429    get!(geo_input_count->geoInputCount->i32);
430    get!(geo_output_count->geoOutputCount->i32);
431    get!(name->nameSH->Result<String>);
432    get!(label->labelSH->Result<String>);
433    get!(file_path->filePathSH->Result<String>);
434    get!(version->versionSH->Result<String>);
435    get!(full_op_name->fullOpNameSH->Result<String>);
436    get!(help_text->helpTextSH->Result<String>);
437    get!(help_url->helpURLSH->Result<String>);
438}
439
440/// [Documentation](https://www.sidefx.com/docs/hengine/struct_h_a_p_i___object_info.html)
441#[derive(Debug)]
442pub struct ObjectInfo<'session>(
443    pub(crate) HAPI_ObjectInfo,
444    pub DebugIgnore<&'session Session>,
445);
446
447impl ObjectInfo<'_> {
448    get!(name->nameSH->Result<String>);
449    get!(object_instance_path->objectInstancePathSH->Result<String>);
450    get!(has_transform_changed->hasTransformChanged->bool);
451    get!(have_geos_changed->haveGeosChanged->bool);
452    get!(is_visible->isVisible->bool);
453    get!(is_instancer->isInstancer->bool);
454    get!(is_instanced->isInstanced->bool);
455    get!(geo_count->geoCount->bool);
456    get!(node_id->nodeId->[handle: NodeHandle]);
457    get!(object_to_instance_id->objectToInstanceId->[handle: NodeHandle]);
458    pub fn to_node(&self) -> Result<HoudiniNode> {
459        self.node_id().to_node(&self.1)
460    }
461}
462
463#[derive(Debug, Clone)]
464/// [Documentation](https://www.sidefx.com/docs/hengine/struct_h_a_p_i___geo_info.html)
465pub struct GeoInfo(pub(crate) HAPI_GeoInfo);
466
467impl<'s> GeoInfo {
468    get!(geo_type->type_->GeoType);
469    get!(with_session name->nameSH->Result<String>);
470    get!(node_id->nodeId->[handle: NodeHandle]);
471    get!(is_editable->isEditable->bool);
472    get!(is_templated->isTemplated->bool);
473    get!(is_display_geo->isDisplayGeo->bool);
474    get!(has_geo_changed->hasGeoChanged->bool);
475    get!(has_material_changed->hasMaterialChanged->bool);
476    get!(edge_group_count->edgeGroupCount->i32);
477    get!(point_group_count->pointGroupCount->i32);
478    get!(primitive_group_count->primitiveGroupCount->i32);
479    get!(part_count->partCount->i32);
480
481    pub fn from_node(node: &'s HoudiniNode) -> Result<Self> {
482        GeoInfo::from_handle(node.handle, &node.session)
483    }
484    pub fn from_handle(handle: NodeHandle, session: &'s Session) -> Result<GeoInfo> {
485        crate::ffi::get_geo_info(session, handle).map(GeoInfo)
486    }
487}
488
489#[derive(Debug)]
490pub struct PartInfo(pub(crate) HAPI_PartInfo);
491
492wrap!(
493    Default PartInfo [HAPI_PartInfo_Create => HAPI_PartInfo];
494    [get] part_id->id->[i32];
495    [get] attribute_counts->attributeCounts->[[i32; 4]];
496    [get] has_changed->hasChanged->[bool];
497    [get] is_instanced->isInstanced->[bool];
498    [get+session] name->nameSH->[Result<String>];
499    [get|set|with] part_type->type_->[PartType];
500    [get|set|with] face_count->faceCount->[i32];
501    [get|set|with] point_count->pointCount->[i32];
502    [get|set|with] vertex_count->vertexCount->[i32];
503    [get|set|with] instance_count->instanceCount->[i32];
504    [get|set|with] instanced_part_count->instancedPartCount->[i32];
505);
506
507#[derive(Debug, Clone)]
508pub struct TimelineOptions(pub(crate) HAPI_TimelineOptions);
509
510wrap!(
511    Default TimelineOptions [HAPI_TimelineOptions_Create => HAPI_TimelineOptions];
512    [get|set|with] fps->fps->[f64];
513    [get|set|with] start_time->startTime->[f64];
514    [get|set|with] end_time->endTime->[f64];
515);
516
517#[derive(Debug, Clone)]
518pub struct CurveInfo(pub(crate) HAPI_CurveInfo);
519
520wrap!(
521    Default CurveInfo [HAPI_CurveInfo_Create => HAPI_CurveInfo];
522    [get|set|with] curve_type->curveType->[CurveType];
523    [get|set|with] curve_count->curveCount->[i32];
524    [get|set|with] vertex_count->vertexCount->[i32];
525    [get|set|with] knot_count->knotCount->[i32];
526    [get|set|with] periodic->isPeriodic->[bool];
527    [get|set|with] rational->isRational->[bool];
528    [get|set|with] closed->isClosed->[bool];
529    [get|set|with] has_knots->hasKnots->[bool];
530    [get|set|with] order->order->[i32];
531);
532
533#[derive(Debug, Clone)]
534pub struct Viewport(pub(crate) HAPI_Viewport);
535
536wrap!(
537    Default Viewport [HAPI_Viewport_Create => HAPI_Viewport];
538    [get|set|with] position->position->[[f32; 3]];
539    [get|set|with] rotation->rotationQuaternion->[[f32; 4]];
540    [get|set|with] offset->offset->[f32];
541);
542
543#[derive(Debug, Clone)]
544/// [Documentation](https://www.sidefx.com/docs/hengine/struct_h_a_p_i___transform.html)
545pub struct Transform(pub(crate) HAPI_Transform);
546
547wrap!(
548    Default Transform [HAPI_Transform_Create => HAPI_Transform];
549    [get|set|with] position->position->[[f32;3]];
550    [get|set|with] rotation->rotationQuaternion->[[f32;4]];
551    [get|set|with] scale->scale->[[f32;3]];
552    [get|set|with] shear->shear->[[f32;3]];
553    [get|set|with] rst_order->rstOrder->[RSTOrder];
554);
555
556impl Transform {
557    pub fn from_matrix(session: &Session, matrix: &[f32; 16], rst_order: RSTOrder) -> Result<Self> {
558        crate::ffi::convert_matrix_to_quat(session, matrix, rst_order).map(Transform)
559    }
560
561    pub fn convert_to_matrix(&self, session: &Session) -> Result<[f32; 16]> {
562        crate::ffi::convert_transform_quat_to_matrix(session, &self.0)
563    }
564}
565
566#[derive(Debug, Clone)]
567/// [Documentation](https://www.sidefx.com/docs/hengine/struct_h_a_p_i___transform_euler.html)
568pub struct TransformEuler(pub(crate) HAPI_TransformEuler);
569
570wrap!(
571    Default TransformEuler [HAPI_TransformEuler_Create => HAPI_TransformEuler];
572    [get|set|with] position->position->[[f32;3]];
573    [get|set|with] rotation->rotationEuler->[[f32;3]];
574    [get|set|with] scale->scale->[[f32;3]];
575    [get|set|with] shear->shear->[[f32;3]];
576    [get|set|with] roation_order->rotationOrder->[XYZOrder];
577    [get|set|with] rst_order->rstOrder->[RSTOrder];
578);
579
580impl TransformEuler {
581    pub fn convert_transform(
582        &self,
583        session: &Session,
584        rst_order: RSTOrder,
585        rot_order: XYZOrder,
586    ) -> Result<Self> {
587        crate::ffi::convert_transform(session, &self.0, rst_order, rot_order).map(TransformEuler)
588    }
589
590    pub fn from_matrix(
591        session: &Session,
592        matrix: &[f32; 16],
593        rst_order: RSTOrder,
594        rot_order: XYZOrder,
595    ) -> Result<Self> {
596        crate::ffi::convert_matrix_to_euler(session, matrix, rst_order, rot_order)
597            .map(TransformEuler)
598    }
599
600    pub fn convert_to_matrix(&self, session: &Session) -> Result<[f32; 16]> {
601        crate::ffi::convert_transform_euler_to_matrix(session, &self.0)
602    }
603}
604
605#[derive(Debug, Clone)]
606pub struct SessionSyncInfo(pub(crate) HAPI_SessionSyncInfo);
607
608wrap!(
609    Default SessionSyncInfo [HAPI_SessionSyncInfo_Create => HAPI_SessionSyncInfo];
610    [get|set|with] cook_using_houdini_time->cookUsingHoudiniTime->[bool];
611    [get|set|with] sync_viewport->syncViewport->[bool];
612);
613
614#[derive(Debug, Clone)]
615pub struct BoxInfo(pub(crate) HAPI_BoxInfo);
616
617// TODO: Why not impl Default?
618fn _create_box_info() -> HAPI_BoxInfo {
619    HAPI_BoxInfo {
620        center: Default::default(),
621        size: Default::default(),
622        rotation: Default::default(),
623    }
624}
625
626wrap!(
627    Default BoxInfo [_create_box_info => HAPI_BoxInfo];
628    [get|set|with] center->center->[[f32;3]];
629    [get|set|with] rotation->rotation->[[f32;3]];
630    [get|set|with] size->size->[[f32;3]];
631);
632
633#[derive(Debug, Clone)]
634pub struct SphereInfo(pub(crate) HAPI_SphereInfo);
635
636// TODO: Why not impl Default?
637fn _create_sphere_info() -> HAPI_SphereInfo {
638    HAPI_SphereInfo {
639        center: Default::default(),
640        radius: 0.0,
641    }
642}
643
644wrap!(
645    Default SphereInfo [_create_sphere_info => HAPI_SphereInfo];
646    [get|set|with] center->center->[[f32;3]];
647    [get|set|with] radius->radius->[f32];
648);
649
650#[repr(C)]
651#[derive(Debug, Clone)]
652pub struct ImageInfo(pub(crate) HAPI_ImageInfo);
653
654wrap!(
655    Default ImageInfo [HAPI_ImageInfo_Create => HAPI_ImageInfo];
656    [get|set|with] x_res->xRes->[i32];
657    [get|set|with] y_res->yRes->[i32];
658    [get|set|with] gamma->gamma->[f64];
659    [get|set|with] data_format->dataFormat->[ImageDataFormat];
660    [get|set|with] interleaved->interleaved->[bool];
661    [get|set|with] packing->packing->[ImagePacking];
662    [get+session] image_format->imageFileFormatNameSH->[Result<String>];
663);
664
665#[repr(C)]
666#[derive(Debug, Clone)]
667/// For parameter animation
668pub struct KeyFrame {
669    pub time: f32,
670    pub value: f32,
671    pub in_tangent: f32,
672    pub out_tangent: f32,
673}
674
675#[derive(Debug, Clone)]
676pub struct ImageFileFormat<'a>(
677    pub(crate) HAPI_ImageFileFormat,
678    pub(crate) DebugIgnore<&'a Session>,
679);
680
681impl ImageFileFormat<'_> {
682    get!(name->nameSH->Result<String>);
683    get!(description->descriptionSH->Result<String>);
684    get!(extension->defaultExtensionSH->Result<String>);
685}
686
687#[derive(Debug, Clone)]
688pub struct VolumeInfo(pub(crate) HAPI_VolumeInfo);
689
690wrap!(
691    impl VolumeInfo => HAPI_VolumeInfo;
692    [get+session] name->nameSH->[Result<String>];
693    [get] volume_type->type_->[VolumeType];
694    [get|set|with] x_length->xLength->[i32];
695    [get|set|with] y_length->yLength->[i32];
696    [get|set|with] z_length->zLength->[i32];
697    [get|set|with] min_x->minX->[i32];
698    [get|set|with] min_y->minY->[i32];
699    [get|set|with] min_z->minZ->[i32];
700    [get|set|with] tuple_size->tupleSize->[i32];
701    [get|set|with] storage->storage->[StorageType];
702    [get|set|with] tile_size->tileSize->[i32];
703    [get|set|with] has_taper->hasTaper->[bool];
704    [get|set|with] x_taper->xTaper->[f32];
705    [get|set|with] y_taper->yTaper->[f32];
706);
707
708impl VolumeInfo {
709    fn transform(&self) -> Transform {
710        Transform(self.0.transform)
711    }
712    fn set_transform(&mut self, transform: Transform) {
713        self.0.transform = transform.0
714    }
715    fn with_transform(mut self, transform: Transform) -> Self {
716        self.0.transform = transform.0;
717        self
718    }
719}
720
721#[derive(Debug, Clone)]
722pub struct VolumeTileInfo(pub(crate) HAPI_VolumeTileInfo);
723
724wrap!(
725    impl VolumeTileInfo => HAPI_VolumeTileInfo;
726    [get|set|with] min_x->minX->[i32];
727    [get|set|with] min_y->minY->[i32];
728    [get|set|with] min_z->minZ->[i32];
729    [get] is_valid->isValid->[bool];
730);
731
732#[derive(Debug, Clone)]
733pub struct VolumeVisualInfo(pub(crate) HAPI_VolumeVisualInfo);
734
735wrap!(
736    impl VolumeVisualInfo => HAPI_VolumeVisualInfo;
737    [get|set|with] visual_type->type_->[VolumeVisualType];
738    [get|set|with] iso->iso->[f32];
739    [get|set|with] density->density->[f32];
740);
741
742#[derive(Debug, Clone)]
743pub struct InputCurveInfo(pub(crate) HAPI_InputCurveInfo);
744
745wrap!(
746    Default InputCurveInfo [HAPI_InputCurveInfo_Create => HAPI_InputCurveInfo];
747    [get|set|with] curve_type->curveType->[CurveType];
748    [get|set|with] order->order->[i32];
749    [get|set|with] closed->closed->[bool];
750    [get|set|with] reverse->reverse->[bool];
751    [get|set|with] input_method->inputMethod->[InputCurveMethod];
752    [get|set|with] breakpoint_parameterization->breakpointParameterization->[InputCurveParameterization];
753);
754
755#[derive(Debug, Copy, Clone)]
756pub struct PDGEventInfo(pub(crate) HAPI_PDG_EventInfo);
757
758impl PDGEventInfo {
759    get!(node_id->nodeId->[handle: NodeHandle]);
760    get!(workitem_id->workItemId->[handle: WorkItemId]);
761    get!(dependency_id->dependencyId->i32);
762    get!(with_session message->msgSH->Result<String>);
763    pub fn current_state(&self) -> PdgWorkItemState {
764        unsafe { std::mem::transmute::<i32, PdgWorkItemState>(self.0.currentState) }
765    }
766    pub fn last_state(&self) -> PdgWorkItemState {
767        unsafe { std::mem::transmute::<i32, PdgWorkItemState>(self.0.lastState) }
768    }
769    pub fn event_type(&self) -> PdgEventType {
770        unsafe { std::mem::transmute::<i32, PdgEventType>(self.0.eventType) }
771    }
772}
773
774#[derive(Debug)]
775pub struct PDGWorkItemOutputFile<'session>(
776    pub(crate) HAPI_PDG_WorkItemOutputFile,
777    pub(crate) DebugIgnore<&'session Session>,
778);
779
780impl PDGWorkItemOutputFile<'_> {
781    get!(path->filePathSH->Result<String>);
782    get!(tag->tagSH->Result<String>);
783    get!(sha->hash->i64);
784}
785
786pub struct PDGWorkItemInfo(pub(crate) HAPI_PDG_WorkItemInfo);
787
788wrap! {
789    impl PDGWorkItemInfo => HAPI_PDG_WorkItemInfo;
790    [get] index->index->[i32];
791    [get] output_file_count->outputFileCount->[i32];
792    [get+session] name->nameSH->[Result<String>];
793}