use serde::{Deserialize, Serialize};
use serde_json;
use std::collections::HashMap;
#[cfg(feature = "schema")]
use schemars::JsonSchema;
#[derive(Debug, Clone)]
pub struct Config {
pub base_url: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
pub struct CameraPositionAngles {
#[serde(rename = "xzAngle")]
pub xz_angle: f64,
#[serde(rename = "yAngle")]
pub y_angle: f64,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
pub struct CameraPositionFixed {
pub position: Vector3,
#[serde(rename = "lookAt")]
pub look_at: Vector3,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum SandboxRenderCameraPositioning {
Fixed(CameraPositionFixed),
Angles(CameraPositionAngles),
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
pub struct Vector3 {
pub x: f64,
pub y: f64,
pub z: f64,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "snake_case")]
pub enum SandboxRenderLightSetup {
DynamicLightCamCube,
DynamicLightPhong,
HdriLobeUm5cM6P,
#[serde(rename = "ig.Configurator")]
IgConfigurator,
#[serde(rename = "ig.Configurator.PBR_Cubemap")]
IgConfiguratorPBRCubemap,
#[serde(rename = "ig.Online")]
IgOnline,
Showcase,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "snake_case")]
pub enum SandboxRenderFloor {
PlainWhite,
ShowcaseMirror,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase")]
pub enum SandboxRenderMode {
Perspective,
Orthographic,
Architecture,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase")]
pub enum SandboxRenderRenderMode {
Pictogram,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
pub struct SandboxRenderConfiguration {
#[serde(rename = "lightSetup")]
pub light_setup: SandboxRenderLightSetup,
pub floor: SandboxRenderFloor,
pub mode: SandboxRenderMode,
#[serde(skip_serializing_if = "Option::is_none", rename = "renderMode")]
pub render_mode: Option<SandboxRenderRenderMode>,
#[serde(
skip_serializing_if = "Option::is_none",
rename = "transparentBackground"
)]
pub transparent_background: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fov: Option<f64>,
#[serde(rename = "cameraPositioning")]
pub camera_positioning: SandboxRenderCameraPositioning,
pub width: u32,
pub height: u32,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SandboxRenderRequest {
pub oc: HashMap<String, serde_json::Value>,
pub configurations: Vec<SandboxRenderConfiguration>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SandboxRenderResultSuccess {
#[serde(rename = "mimeType")]
pub mime_type: String,
pub content: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SandboxRenderResultError {
pub message: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "status", rename_all = "camelCase")]
pub enum SandboxRenderResult {
Success(SandboxRenderResultSuccess),
Error(SandboxRenderResultError),
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SandboxRenderResponse {
pub results: Vec<SandboxRenderResult>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ConfiguratorRenderRequest {
#[serde(rename = "configuratorUrl")]
pub configurator_url: String,
pub pin: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ConfiguratorInternalRenderResponseItem {
#[serde(rename = "mimeType")]
pub mime_type: String,
pub content: String,
pub identifier: String,
#[serde(rename = "attachmentType")]
pub attachment_type: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ConfiguratorRenderResponseSuccess {
pub images: Vec<ConfiguratorInternalRenderResponseItem>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ConfiguratorRenderResponseError {
pub message: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "status", rename_all = "camelCase")]
pub enum ConfiguratorRenderResponse {
Success(ConfiguratorRenderResponseSuccess),
Error(ConfiguratorRenderResponseError),
}
#[cfg(feature = "client")]
mod async_feature_module {
use anyhow::{anyhow, Result};
use reqwest::{Client, Url};
use std::time::Duration;
use crate::*;
pub async fn request_renderings(
config: &Config,
request: &SandboxRenderRequest,
client: Option<&Client>,
) -> Result<SandboxRenderResponse> {
let client = match client {
Some(client) => client,
_ => &Client::new(),
};
let mut url = Url::parse(&config.base_url)?;
url = url.join("api/render")?;
let res = client
.post(url)
.json(request)
.timeout(Duration::from_secs(5 * 60))
.send()
.await?;
let status = res.status();
let text = res.text().await?;
if !status.is_success() {
return Err(anyhow!("HTTP error: {}", text));
}
let parsed: SandboxRenderResponse =
serde_json::de::from_str(&text).map_err(|e| anyhow!("Parse error: {e}"))?;
Ok(parsed)
}
pub async fn request_configurator_renderings(
config: &Config,
request: &ConfiguratorRenderRequest,
client: Option<&Client>,
) -> Result<ConfiguratorRenderResponse> {
let client = match client {
Some(client) => client,
_ => &Client::new(),
};
let mut url = Url::parse(&config.base_url)?;
url = url.join("api/renderConfigurator")?;
let res = client
.post(url)
.json(request)
.timeout(Duration::from_secs(5 * 60))
.send()
.await?;
let status = res.status();
let text = res.text().await?;
if !status.is_success() {
return Err(anyhow!("HTTP error: {}", text));
}
let parsed: ConfiguratorRenderResponse =
serde_json::de::from_str(&text).map_err(|e| anyhow!("Parse error: {e}"))?;
Ok(parsed)
}
}
#[cfg(feature = "client")]
pub use async_feature_module::*;