diff --git a/server-rs/crates/platform-tripo/src/common/validation.rs b/server-rs/crates/platform-tripo/src/common/validation.rs index d24e307ba..83faf324f 100644 --- a/server-rs/crates/platform-tripo/src/common/validation.rs +++ b/server-rs/crates/platform-tripo/src/common/validation.rs @@ -206,6 +206,16 @@ pub(crate) fn validate_generation_options( } } + // pbr 依赖贴图:契约里写着「依赖贴图」,api-server 侧也已按同一口径拒绝, + // 这里补上直连调用方这一层,别把「不会成立的组合」拖到 provider 那边才报错。 + if options.texture == Some(false) && options.pbr == Some(true) { + return Err(invalid( + Some(TripoField::Pbr), + TripoValidationReason::InvalidCombination, + "pbr=true requires texture=true", + )); + } + if let Some(face_limit) = options.face_limit { let (minimum, maximum) = face_limit_bounds(family, options); if face_limit < minimum || face_limit > maximum { @@ -469,6 +479,28 @@ mod tests { } } + /// pbr 依赖贴图:`texture=false` 与 `pbr=true` 是自相矛盾的组合,提交前就要拒绝。 + #[test] + fn pbr_requires_texture() { + let mut options = minimal_options(Model3dModelVersion::H31); + options.texture = Some(false); + options.pbr = Some(true); + + let error = validate_generation_options(&options) + .expect_err("texture=false 与 pbr=true 同时给出必须被拒"); + assert_eq!( + rejection(error), + Some(( + Some(TripoField::Pbr), + TripoValidationReason::InvalidCombination + )) + ); + + // 显式带贴图时同一个 pbr 取值合法。 + options.texture = Some(true); + validate_generation_options(&options).expect("texture=true 时 pbr=true 应放行"); + } + /// `quad=true` 只对 v3.x 家族与 P2 放行,其余家族按 Quad 字段拒绝。 #[test] fn quad_is_limited_to_v3_families_and_p2() {