Skip to main content

ig_webrender_client/
lib.rs

1use serde::{Deserialize, Serialize};
2use serde_json;
3use std::collections::HashMap;
4
5#[cfg(feature = "schema")]
6use schemars::JsonSchema;
7
8#[derive(Debug, Clone)]
9pub struct Config {
10    /// Render server base url with trailing slash
11    pub base_url: String,
12}
13
14#[derive(Serialize, Deserialize, Debug, Clone)]
15#[cfg_attr(feature = "schema", derive(JsonSchema))]
16
17pub struct CameraPositionAngles {
18    #[serde(rename = "xzAngle")]
19    pub xz_angle: f64,
20    #[serde(rename = "yAngle")]
21    pub y_angle: f64,
22}
23
24#[derive(Serialize, Deserialize, Debug, Clone)]
25#[cfg_attr(feature = "schema", derive(JsonSchema))]
26
27pub struct CameraPositionFixed {
28    pub position: Vector3,
29    #[serde(rename = "lookAt")]
30    pub look_at: Vector3,
31}
32
33#[derive(Serialize, Deserialize, Debug, Clone)]
34#[cfg_attr(feature = "schema", derive(JsonSchema))]
35#[serde(tag = "type", rename_all = "camelCase")]
36pub enum SandboxRenderCameraPositioning {
37    Fixed(CameraPositionFixed),
38    Angles(CameraPositionAngles),
39}
40
41#[derive(Serialize, Deserialize, Debug, Clone)]
42#[cfg_attr(feature = "schema", derive(JsonSchema))]
43
44pub struct Vector3 {
45    pub x: f64,
46    pub y: f64,
47    pub z: f64,
48}
49
50#[derive(Serialize, Deserialize, Debug, Clone)]
51#[cfg_attr(feature = "schema", derive(JsonSchema))]
52#[serde(rename_all = "snake_case")]
53pub enum SandboxRenderLightSetup {
54    DynamicLightCamCube,
55    DynamicLightPhong,
56    HdriLobeUm5cM6P,
57    #[serde(rename = "ig.Configurator")]
58    IgConfigurator,
59    #[serde(rename = "ig.Configurator.PBR_Cubemap")]
60    IgConfiguratorPBRCubemap,
61    #[serde(rename = "ig.Online")]
62    IgOnline,
63    Showcase,
64}
65#[derive(Serialize, Deserialize, Debug, Clone)]
66#[cfg_attr(feature = "schema", derive(JsonSchema))]
67#[serde(rename_all = "snake_case")]
68pub enum SandboxRenderFloor {
69    PlainWhite,
70    ShowcaseMirror,
71}
72
73#[derive(Serialize, Deserialize, Debug, Clone)]
74#[cfg_attr(feature = "schema", derive(JsonSchema))]
75#[serde(rename_all = "camelCase")]
76pub enum SandboxRenderMode {
77    Perspective,
78    Orthographic,
79    Architecture,
80}
81
82#[derive(Serialize, Deserialize, Debug, Clone)]
83#[cfg_attr(feature = "schema", derive(JsonSchema))]
84#[serde(rename_all = "camelCase")]
85pub enum SandboxRenderRenderMode {
86    Pictogram,
87}
88
89#[derive(Serialize, Deserialize, Debug, Clone)]
90#[cfg_attr(feature = "schema", derive(JsonSchema))]
91pub struct SandboxRenderConfiguration {
92    #[serde(rename = "lightSetup")]
93    pub light_setup: SandboxRenderLightSetup,
94    pub floor: SandboxRenderFloor,
95    pub mode: SandboxRenderMode,
96    #[serde(skip_serializing_if = "Option::is_none", rename = "renderMode")]
97    pub render_mode: Option<SandboxRenderRenderMode>,
98    #[serde(
99        skip_serializing_if = "Option::is_none",
100        rename = "transparentBackground"
101    )]
102    pub transparent_background: Option<bool>,
103    #[serde(skip_serializing_if = "Option::is_none")]
104    pub fov: Option<f64>,
105    #[serde(rename = "cameraPositioning")]
106    pub camera_positioning: SandboxRenderCameraPositioning,
107    pub width: u32,
108    pub height: u32,
109}
110
111#[derive(Serialize, Deserialize, Debug, Clone)]
112pub struct SandboxRenderRequest {
113    pub oc: HashMap<String, serde_json::Value>,
114    pub configurations: Vec<SandboxRenderConfiguration>,
115}
116
117#[derive(Serialize, Deserialize, Debug, Clone)]
118pub struct SandboxRenderResultSuccess {
119    #[serde(rename = "mimeType")]
120    pub mime_type: String,
121    pub content: String,
122}
123
124#[derive(Serialize, Deserialize, Debug, Clone)]
125pub struct SandboxRenderResultError {
126    pub message: String,
127}
128
129#[derive(Serialize, Deserialize, Debug, Clone)]
130#[serde(tag = "status", rename_all = "camelCase")]
131pub enum SandboxRenderResult {
132    Success(SandboxRenderResultSuccess),
133    Error(SandboxRenderResultError),
134}
135
136#[derive(Serialize, Deserialize, Debug, Clone)]
137pub struct SandboxRenderResponse {
138    pub results: Vec<SandboxRenderResult>,
139}
140
141#[derive(Serialize, Deserialize, Debug, Clone)]
142pub struct ConfiguratorRenderRequest {
143    #[serde(rename = "configuratorUrl")]
144    pub configurator_url: String,
145    pub pin: String,
146}
147
148#[derive(Serialize, Deserialize, Debug, Clone)]
149pub struct ConfiguratorInternalRenderResponseItem {
150    #[serde(rename = "mimeType")]
151    pub mime_type: String,
152    pub content: String,
153    pub identifier: String,
154    #[serde(rename = "attachmentType")]
155    pub attachment_type: String,
156}
157
158#[derive(Serialize, Deserialize, Debug, Clone)]
159pub struct ConfiguratorRenderResponseSuccess {
160    pub images: Vec<ConfiguratorInternalRenderResponseItem>,
161}
162
163#[derive(Serialize, Deserialize, Debug, Clone)]
164pub struct ConfiguratorRenderResponseError {
165    pub message: String,
166}
167
168#[derive(Serialize, Deserialize, Debug, Clone)]
169#[serde(tag = "status", rename_all = "camelCase")]
170pub enum ConfiguratorRenderResponse {
171    Success(ConfiguratorRenderResponseSuccess),
172    Error(ConfiguratorRenderResponseError),
173}
174
175#[cfg(feature = "client")]
176mod async_feature_module {
177
178    use anyhow::{anyhow, Result};
179    use reqwest::{Client, Url};
180    use std::time::Duration;
181
182    use crate::*;
183
184    pub async fn request_renderings(
185        config: &Config,
186        request: &SandboxRenderRequest,
187        client: Option<&Client>,
188    ) -> Result<SandboxRenderResponse> {
189        let client = match client {
190            Some(client) => client,
191            _ => &Client::new(),
192        };
193        let mut url = Url::parse(&config.base_url)?;
194        url = url.join("api/render")?;
195        let res = client
196            .post(url)
197            .json(request)
198            .timeout(Duration::from_secs(5 * 60))
199            .send()
200            .await?;
201        let status = res.status();
202        let text = res.text().await?;
203        if !status.is_success() {
204            return Err(anyhow!("HTTP error: {}", text));
205        }
206        let parsed: SandboxRenderResponse =
207            serde_json::de::from_str(&text).map_err(|e| anyhow!("Parse error: {e}"))?;
208        Ok(parsed)
209    }
210
211    pub async fn request_configurator_renderings(
212        config: &Config,
213        request: &ConfiguratorRenderRequest,
214        client: Option<&Client>,
215    ) -> Result<ConfiguratorRenderResponse> {
216        let client = match client {
217            Some(client) => client,
218            _ => &Client::new(),
219        };
220
221        let mut url = Url::parse(&config.base_url)?;
222        url = url.join("api/renderConfigurator")?;
223        let res = client
224            .post(url)
225            .json(request)
226            .timeout(Duration::from_secs(5 * 60))
227            .send()
228            .await?;
229        let status = res.status();
230        let text = res.text().await?;
231        if !status.is_success() {
232            return Err(anyhow!("HTTP error: {}", text));
233        }
234        let parsed: ConfiguratorRenderResponse =
235            serde_json::de::from_str(&text).map_err(|e| anyhow!("Parse error: {e}"))?;
236        Ok(parsed)
237    }
238}
239
240#[cfg(feature = "client")]
241pub use async_feature_module::*;