Skip to main content

hapi_rs/ffi/
structs.rs

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