1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#![doc(html_logo_url = "https://media.sidefx.com/uploads/products/engine/engine_orange.svg")]
//! # Rust bindings to Houdini Engine C API.
//!
//! Official HAPI [documentation](https://www.sidefx.com/docs/hengine/):
//!
//! Check out the [examples](https://github.com/alexxbb/hapi-rs/tree/main/examples):
//!
//! `cargo run --example ...`
//!
//!
//! # Building and running
//!
//! **HFS** environment variable must be set for the build script to link to Houdini libraries.
//!
//! For runtime discovery of Houdini libraries there are several options:
//!
//! ## Mac & Linux
//!
//! **Option 1**
//!
//! Build with RPATH via the RUSTFLAGS variable:
//! ```bash
//! RUSTFLAGS="-C link-args=-Wl,-rpath,/path/to/hfs/dsolib" cargo build
//! ```
//! **Option 2**
//!
//! Add a cargo config file to your project: `.cargo/config`
//!```text
//! [target.'cfg(target_os = "linux")']
//! rustflags = ["-C", "link-arg=-Wl,-rpath=/opt/hfs/19.5.368/dsolib"]
//! [target.x86_64-apple-darwin]
//! rustflags = ["-C",
//!     "link-arg=-Wl,-rpath,/Applications/Houdini/Current/Frameworks/Houdini.framework/Versions/Current/Libraries",
//! ]
//!```
//! **Option 3**
//!
//! At runtime via env variables: `$LD_LIBRARY_PATH` on Linux and `$DYLD_LIBRARY_PATH` on MacOS
//!
//! ## Windows
//! `$HFS` variable must be set for building.
//! Runtime Houdini libraries are required to be in $PATH: Add $HFS/bin to $PATH.
//!
//! # API Overview
//!
//! This crates aims to be easy to use, hiding the inconvenient C API as much as possible
//! while also trying to keep function names clear and close to original.
//! To archive this, the crate wraps every single C struct in a new struct and provide getters/setters for its fields.
//! All structs and enums have their `HAPI_` prefix removed.
//!
//! In addition all enum variants are shortened.
//! For example:
//! ```ignore
//! // Original struct:
//! struct HAPI_NodeInfo {
//!    pub parmCount: ::std::os::raw::c_int,
//!    ...
//! }
//! // This crate's struct:
//! let info: crate::node::NodeInfo;
//! let count: i32 = info.parm_count();
//!
//! // Original enum (C)
//!  enum HAPI_InputType {
//!       HAPI_INPUT_INVALID = -1,
//!       ...
//! };
//! // This crate's enum
//! enum InputType {
//!     Invalid = -1,
//!     ...
//! }
//! ```
//! Some underlying C structs don't provide a direct way of creating them or they might not provide methods
//! for modifying them, due to this crate's attempt for proper data encapsulation, minimizing noise and improving safety.
//! Structs that you **do** need the ability to create, implement [Default] and some a `Builder Pattern` with convenient `with_` and `set_` methods:
//! ```ignore
//! let part_info = PartInfo::default()
//!    .with_part_type(PartType::Mesh)
//!    .with_face_count(6);
//! ```
//!
//! # Error type
//! All API calls return [`HapiError`] ([HAPI_Result](https://www.sidefx.com/docs/hengine/_h_a_p_i___common_8h.html#ac52e921ba2c7fc21a0f245678f76c836))
//! In case of error, the HapiError struct contains an `Option<String>` with an error message returned from the Engine.
//! Additional error context is available in the `contexts` field of the error type.
//!
//!
//! # Strings
//! Houdini Engine being C API, makes life a little harder for Rust programmer when it comes to strings.
//! The crate chose to accept some overhead related to string conversion in exchange for a nicer API and
//! easy of use.
//!
//! For example getting/setting a parameter value will perform a conversion CString <-> String,
//! but not in every situation such conversion is acceptable, for example reading geometry string attributes
//! can be very expensive since we have do potentially thousands of CString to String conversions.
//!
//! To aid this situation, the crate provides custom structs which implement different iterators,
//! which yield CString or String types. See the [`stringhandle`] module for more info.
//!
//!
//! # Nodes
//! [`node::NodeHandle`] is lightweight handle to a Houdini node, it's returned by some APIs and can not
//! be created by the users. The [`node::NodeHandle`] has a limited functionality because it doesn't hold
//! a pointer to the [`session::Session`].
//!
//! [`node::HoudiniNode`] is the main type which combines [`node::NodeHandle`], [`node::NodeInfo`]
//! and [`session::Session`] types into a single struct which exports most of the node APIs.
//!
//! Some APIs choose to return a lightweight [`node::NodeHandle`] that can be simply passed to other APIs.
//! You can upgrade the handle to a full node by [`node::NodeHandle::to_node`] to get access to full node API.
//!
//! Due to HAPI only exposes a limited subset of APIs to Houdini, and to keep things simple,
//! there no different flavors of [`node::HoudiniNode`].
//! Instead this type provides the common node APIs and some node-type-specific APIs are available
//! in separate types like [`pdg::TopNode`] and [`geometry::Geometry`] which hold [`node::HoudiniNode`]
//! as a struct field (composition vs inheritance).
//!
//! # Parameters
//! Parameters are modelled with [`parameter::Parameter`] enum that contains different parameter types.
//! Common parameter methods are provided in [`parameter::ParmBaseTrait`].

pub mod asset;
pub mod attribute;
pub mod geometry;
pub mod material;
pub mod node;
pub mod parameter;
pub mod session;
pub mod stringhandle;
pub mod volume;
pub mod pdg;
mod errors;
mod utils;
mod ffi;

pub use errors::{HapiError, Result};
pub use ffi::enums;
pub use ffi::structs::Viewport;

/// Houdini version this library was build upon
#[derive(Debug)]
pub struct HoudiniVersion {
    pub major: u32,
    pub minor: u32,
    pub build: u32,
    pub patch: u32,
}

/// Engine version this library was build upon
#[derive(Debug)]
pub struct EngineVersion {
    pub major: u32,
    pub minor: u32,
    pub api: u32,
}

/// Houdini version this library was build upon
pub const HOUDINI_VERSION: HoudiniVersion = HoudiniVersion {
    major: ffi::raw::HAPI_VERSION_HOUDINI_MAJOR,
    minor: ffi::raw::HAPI_VERSION_HOUDINI_MINOR,
    build: ffi::raw::HAPI_VERSION_HOUDINI_BUILD,
    patch: ffi::raw::HAPI_VERSION_HOUDINI_PATCH,
};

/// Engine version this library was build upon
pub const ENGINE_VERSION: EngineVersion = EngineVersion {
    major: ffi::raw::HAPI_VERSION_HOUDINI_ENGINE_MAJOR,
    minor: ffi::raw::HAPI_VERSION_HOUDINI_ENGINE_MINOR,
    api: ffi::raw::HAPI_VERSION_HOUDINI_ENGINE_API,
};