Switch to VectorEngine gpt-image-2 and edits
Replace uses of the legacy `gpt-image-2-all` model with `gpt-image-2` and standardize image workflows: no-reference generation uses POST /v1/images/generations, any-reference flows use POST /v1/images/edits with multipart `image` parts. Update SKILLs, generation scripts, decision logs, and docs to reflect the contract change and edits-vs-generations guidance. Apply corresponding changes across backend (api-server match3d/puzzle modules, openai image adapter, mappers, telemetry, spacetime client/module), frontend components and services (Match3D, Puzzle, CreativeImageInputPanel, runtime shells), and add new spritesheet/parser files and tests. Also add media/logo.png. These changes align repository code and documentation with the VectorEngine image API contract and update generation/upload handling (green-screen -> alpha processing, spritesheet handling, and related tests).
This commit is contained in:
@@ -189,6 +189,12 @@ pub fn compile_result_draft_from_seed(
|
||||
ui_background_prompt: None,
|
||||
ui_background_image_src: None,
|
||||
ui_background_image_object_key: None,
|
||||
level_scene_image_src: None,
|
||||
level_scene_image_object_key: None,
|
||||
ui_spritesheet_image_src: None,
|
||||
ui_spritesheet_image_object_key: None,
|
||||
level_background_image_src: None,
|
||||
level_background_image_object_key: None,
|
||||
background_music: None,
|
||||
candidates: Vec::new(),
|
||||
selected_candidate_id: None,
|
||||
@@ -249,6 +255,12 @@ pub fn build_form_draft_from_parts(
|
||||
ui_background_prompt: None,
|
||||
ui_background_image_src: None,
|
||||
ui_background_image_object_key: None,
|
||||
level_scene_image_src: None,
|
||||
level_scene_image_object_key: None,
|
||||
ui_spritesheet_image_src: None,
|
||||
ui_spritesheet_image_object_key: None,
|
||||
level_background_image_src: None,
|
||||
level_background_image_object_key: None,
|
||||
background_music: None,
|
||||
candidates: Vec::new(),
|
||||
selected_candidate_id: None,
|
||||
@@ -358,6 +370,12 @@ pub fn normalize_puzzle_draft(mut draft: PuzzleResultDraft) -> PuzzleResultDraft
|
||||
ui_background_prompt: None,
|
||||
ui_background_image_src: None,
|
||||
ui_background_image_object_key: None,
|
||||
level_scene_image_src: None,
|
||||
level_scene_image_object_key: None,
|
||||
ui_spritesheet_image_src: None,
|
||||
ui_spritesheet_image_object_key: None,
|
||||
level_background_image_src: None,
|
||||
level_background_image_object_key: None,
|
||||
background_music: None,
|
||||
candidates: draft.candidates.clone(),
|
||||
selected_candidate_id: draft.selected_candidate_id.clone(),
|
||||
@@ -448,6 +466,12 @@ pub fn append_blank_puzzle_level(draft: &PuzzleResultDraft) -> PuzzleResultDraft
|
||||
ui_background_prompt: None,
|
||||
ui_background_image_src: None,
|
||||
ui_background_image_object_key: None,
|
||||
level_scene_image_src: None,
|
||||
level_scene_image_object_key: None,
|
||||
ui_spritesheet_image_src: None,
|
||||
ui_spritesheet_image_object_key: None,
|
||||
level_background_image_src: None,
|
||||
level_background_image_object_key: None,
|
||||
background_music: None,
|
||||
candidates: Vec::new(),
|
||||
selected_candidate_id: None,
|
||||
@@ -804,17 +828,89 @@ fn first_profile_ui_background_level(profile: &PuzzleWorkProfile) -> Option<Puzz
|
||||
})
|
||||
}
|
||||
|
||||
fn first_profile_level_background_level(profile: &PuzzleWorkProfile) -> Option<PuzzleDraftLevel> {
|
||||
normalize_puzzle_levels(profile.levels.clone(), &profile.theme_tags)
|
||||
.unwrap_or_else(|_| profile.levels.clone())
|
||||
.into_iter()
|
||||
.find(|level| {
|
||||
level
|
||||
.level_background_image_src
|
||||
.as_deref()
|
||||
.and_then(normalize_required_string)
|
||||
.is_some()
|
||||
|| level
|
||||
.level_background_image_object_key
|
||||
.as_deref()
|
||||
.and_then(normalize_required_string)
|
||||
.is_some()
|
||||
})
|
||||
}
|
||||
|
||||
fn resolve_puzzle_runtime_ui_background_fields(
|
||||
level: Option<&PuzzleDraftLevel>,
|
||||
fallback_level: Option<&PuzzleDraftLevel>,
|
||||
) -> (Option<String>, Option<String>) {
|
||||
for candidate in [level, fallback_level].into_iter().flatten() {
|
||||
let image_src = candidate
|
||||
.ui_background_image_src
|
||||
.level_background_image_src
|
||||
.as_deref()
|
||||
.and_then(normalize_required_string)
|
||||
.or_else(|| {
|
||||
candidate
|
||||
.ui_background_image_src
|
||||
.as_deref()
|
||||
.and_then(normalize_required_string)
|
||||
});
|
||||
let object_key = candidate
|
||||
.level_background_image_object_key
|
||||
.as_deref()
|
||||
.and_then(|value| normalize_required_string(value.trim_start_matches('/')))
|
||||
.or_else(|| {
|
||||
candidate
|
||||
.ui_background_image_object_key
|
||||
.as_deref()
|
||||
.and_then(|value| normalize_required_string(value.trim_start_matches('/')))
|
||||
});
|
||||
if image_src.is_some() || object_key.is_some() {
|
||||
return (image_src, object_key);
|
||||
}
|
||||
}
|
||||
|
||||
(None, None)
|
||||
}
|
||||
|
||||
fn resolve_puzzle_runtime_level_background_fields(
|
||||
level: Option<&PuzzleDraftLevel>,
|
||||
fallback_level: Option<&PuzzleDraftLevel>,
|
||||
) -> (Option<String>, Option<String>) {
|
||||
for candidate in [level, fallback_level].into_iter().flatten() {
|
||||
let image_src = candidate
|
||||
.level_background_image_src
|
||||
.as_deref()
|
||||
.and_then(normalize_required_string);
|
||||
let object_key = candidate
|
||||
.ui_background_image_object_key
|
||||
.level_background_image_object_key
|
||||
.as_deref()
|
||||
.and_then(|value| normalize_required_string(value.trim_start_matches('/')));
|
||||
if image_src.is_some() || object_key.is_some() {
|
||||
return (image_src, object_key);
|
||||
}
|
||||
}
|
||||
|
||||
(None, None)
|
||||
}
|
||||
|
||||
fn resolve_puzzle_runtime_ui_spritesheet_fields(
|
||||
level: Option<&PuzzleDraftLevel>,
|
||||
fallback_level: Option<&PuzzleDraftLevel>,
|
||||
) -> (Option<String>, Option<String>) {
|
||||
for candidate in [level, fallback_level].into_iter().flatten() {
|
||||
let image_src = candidate
|
||||
.ui_spritesheet_image_src
|
||||
.as_deref()
|
||||
.and_then(normalize_required_string);
|
||||
let object_key = candidate
|
||||
.ui_spritesheet_image_object_key
|
||||
.as_deref()
|
||||
.and_then(|value| normalize_required_string(value.trim_start_matches('/')));
|
||||
if image_src.is_some() || object_key.is_some() {
|
||||
@@ -1092,6 +1188,17 @@ pub fn start_run_with_shuffle_seed_at(
|
||||
current_profile_level.as_ref(),
|
||||
ui_background_level.as_ref(),
|
||||
);
|
||||
let level_background_level = first_profile_level_background_level(entry_profile);
|
||||
let (level_background_image_src, level_background_image_object_key) =
|
||||
resolve_puzzle_runtime_level_background_fields(
|
||||
current_profile_level.as_ref(),
|
||||
level_background_level.as_ref(),
|
||||
);
|
||||
let (ui_spritesheet_image_src, ui_spritesheet_image_object_key) =
|
||||
resolve_puzzle_runtime_ui_spritesheet_fields(
|
||||
current_profile_level.as_ref(),
|
||||
entry_profile.levels.first(),
|
||||
);
|
||||
Ok(PuzzleRunSnapshot {
|
||||
run_id: run_id.clone(),
|
||||
entry_profile_id: entry_profile.profile_id.clone(),
|
||||
@@ -1114,6 +1221,10 @@ pub fn start_run_with_shuffle_seed_at(
|
||||
cover_image_src: entry_profile.cover_image_src.clone(),
|
||||
ui_background_image_src,
|
||||
ui_background_image_object_key,
|
||||
level_background_image_src,
|
||||
level_background_image_object_key,
|
||||
ui_spritesheet_image_src,
|
||||
ui_spritesheet_image_object_key,
|
||||
background_music: current_profile_level
|
||||
.as_ref()
|
||||
.and_then(|level| level.background_music.clone()),
|
||||
@@ -1373,10 +1484,29 @@ pub fn advance_next_level_at(
|
||||
current_profile_level.as_ref(),
|
||||
ui_background_level.as_ref(),
|
||||
);
|
||||
let level_background_level = first_profile_level_background_level(next_profile);
|
||||
let (mut level_background_image_src, mut level_background_image_object_key) =
|
||||
resolve_puzzle_runtime_level_background_fields(
|
||||
current_profile_level.as_ref(),
|
||||
level_background_level.as_ref(),
|
||||
);
|
||||
let (mut ui_spritesheet_image_src, mut ui_spritesheet_image_object_key) =
|
||||
resolve_puzzle_runtime_ui_spritesheet_fields(
|
||||
current_profile_level.as_ref(),
|
||||
next_profile.levels.first(),
|
||||
);
|
||||
if ui_background_image_src.is_none() && ui_background_image_object_key.is_none() {
|
||||
ui_background_image_src = current_level.ui_background_image_src.clone();
|
||||
ui_background_image_object_key = current_level.ui_background_image_object_key.clone();
|
||||
}
|
||||
if level_background_image_src.is_none() && level_background_image_object_key.is_none() {
|
||||
level_background_image_src = current_level.level_background_image_src.clone();
|
||||
level_background_image_object_key = current_level.level_background_image_object_key.clone();
|
||||
}
|
||||
if ui_spritesheet_image_src.is_none() && ui_spritesheet_image_object_key.is_none() {
|
||||
ui_spritesheet_image_src = current_level.ui_spritesheet_image_src.clone();
|
||||
ui_spritesheet_image_object_key = current_level.ui_spritesheet_image_object_key.clone();
|
||||
}
|
||||
|
||||
Ok(PuzzleRunSnapshot {
|
||||
run_id: run.run_id.clone(),
|
||||
@@ -1400,6 +1530,10 @@ pub fn advance_next_level_at(
|
||||
cover_image_src: next_profile.cover_image_src.clone(),
|
||||
ui_background_image_src,
|
||||
ui_background_image_object_key,
|
||||
level_background_image_src,
|
||||
level_background_image_object_key,
|
||||
ui_spritesheet_image_src,
|
||||
ui_spritesheet_image_object_key,
|
||||
background_music: current_profile_level
|
||||
.as_ref()
|
||||
.and_then(|level| level.background_music.clone()),
|
||||
@@ -1461,6 +1595,17 @@ pub fn advance_to_new_work_first_level_at(
|
||||
current_profile_level.as_ref(),
|
||||
ui_background_level.as_ref(),
|
||||
);
|
||||
let level_background_level = first_profile_level_background_level(next_profile);
|
||||
let (level_background_image_src, level_background_image_object_key) =
|
||||
resolve_puzzle_runtime_level_background_fields(
|
||||
current_profile_level.as_ref(),
|
||||
level_background_level.as_ref(),
|
||||
);
|
||||
let (ui_spritesheet_image_src, ui_spritesheet_image_object_key) =
|
||||
resolve_puzzle_runtime_ui_spritesheet_fields(
|
||||
current_profile_level.as_ref(),
|
||||
next_profile.levels.first(),
|
||||
);
|
||||
|
||||
Ok(PuzzleRunSnapshot {
|
||||
run_id: run.run_id.clone(),
|
||||
@@ -1484,6 +1629,10 @@ pub fn advance_to_new_work_first_level_at(
|
||||
cover_image_src: next_profile.cover_image_src.clone(),
|
||||
ui_background_image_src,
|
||||
ui_background_image_object_key,
|
||||
level_background_image_src,
|
||||
level_background_image_object_key,
|
||||
ui_spritesheet_image_src,
|
||||
ui_spritesheet_image_object_key,
|
||||
background_music: current_profile_level
|
||||
.as_ref()
|
||||
.and_then(|level| level.background_music.clone()),
|
||||
@@ -2900,6 +3049,12 @@ mod tests {
|
||||
ui_background_prompt: None,
|
||||
ui_background_image_src: None,
|
||||
ui_background_image_object_key: None,
|
||||
level_scene_image_src: None,
|
||||
level_scene_image_object_key: None,
|
||||
ui_spritesheet_image_src: None,
|
||||
ui_spritesheet_image_object_key: None,
|
||||
level_background_image_src: None,
|
||||
level_background_image_object_key: None,
|
||||
background_music: None,
|
||||
candidates: Vec::new(),
|
||||
selected_candidate_id: None,
|
||||
@@ -3118,6 +3273,12 @@ mod tests {
|
||||
ui_background_prompt: None,
|
||||
ui_background_image_src: None,
|
||||
ui_background_image_object_key: None,
|
||||
level_scene_image_src: None,
|
||||
level_scene_image_object_key: None,
|
||||
ui_spritesheet_image_src: None,
|
||||
ui_spritesheet_image_object_key: None,
|
||||
level_background_image_src: None,
|
||||
level_background_image_object_key: None,
|
||||
background_music: None,
|
||||
candidates: Vec::new(),
|
||||
selected_candidate_id: None,
|
||||
@@ -3133,6 +3294,12 @@ mod tests {
|
||||
ui_background_prompt: None,
|
||||
ui_background_image_src: None,
|
||||
ui_background_image_object_key: None,
|
||||
level_scene_image_src: None,
|
||||
level_scene_image_object_key: None,
|
||||
ui_spritesheet_image_src: None,
|
||||
ui_spritesheet_image_object_key: None,
|
||||
level_background_image_src: None,
|
||||
level_background_image_object_key: None,
|
||||
background_music: None,
|
||||
candidates: Vec::new(),
|
||||
selected_candidate_id: None,
|
||||
@@ -3248,6 +3415,12 @@ mod tests {
|
||||
ui_background_prompt: None,
|
||||
ui_background_image_src: None,
|
||||
ui_background_image_object_key: None,
|
||||
level_scene_image_src: None,
|
||||
level_scene_image_object_key: None,
|
||||
ui_spritesheet_image_src: None,
|
||||
ui_spritesheet_image_object_key: None,
|
||||
level_background_image_src: None,
|
||||
level_background_image_object_key: None,
|
||||
background_music: None,
|
||||
candidates: Vec::new(),
|
||||
selected_candidate_id: None,
|
||||
|
||||
@@ -172,6 +172,12 @@ pub fn build_puzzle_draft_from_creative_fields(
|
||||
ui_background_prompt: None,
|
||||
ui_background_image_src: None,
|
||||
ui_background_image_object_key: None,
|
||||
level_scene_image_src: None,
|
||||
level_scene_image_object_key: None,
|
||||
ui_spritesheet_image_src: None,
|
||||
ui_spritesheet_image_object_key: None,
|
||||
level_background_image_src: None,
|
||||
level_background_image_object_key: None,
|
||||
background_music: None,
|
||||
candidates: Vec::new(),
|
||||
selected_candidate_id: None,
|
||||
|
||||
@@ -138,6 +138,18 @@ pub struct PuzzleDraftLevel {
|
||||
#[serde(default)]
|
||||
pub ui_background_image_object_key: Option<String>,
|
||||
#[serde(default)]
|
||||
pub level_scene_image_src: Option<String>,
|
||||
#[serde(default)]
|
||||
pub level_scene_image_object_key: Option<String>,
|
||||
#[serde(default)]
|
||||
pub ui_spritesheet_image_src: Option<String>,
|
||||
#[serde(default)]
|
||||
pub ui_spritesheet_image_object_key: Option<String>,
|
||||
#[serde(default)]
|
||||
pub level_background_image_src: Option<String>,
|
||||
#[serde(default)]
|
||||
pub level_background_image_object_key: Option<String>,
|
||||
#[serde(default)]
|
||||
pub background_music: Option<PuzzleAudioAsset>,
|
||||
pub candidates: Vec<PuzzleGeneratedImageCandidate>,
|
||||
pub selected_candidate_id: Option<String>,
|
||||
@@ -367,6 +379,14 @@ pub struct PuzzleRuntimeLevelSnapshot {
|
||||
#[serde(default)]
|
||||
pub ui_background_image_object_key: Option<String>,
|
||||
#[serde(default)]
|
||||
pub level_background_image_src: Option<String>,
|
||||
#[serde(default)]
|
||||
pub level_background_image_object_key: Option<String>,
|
||||
#[serde(default)]
|
||||
pub ui_spritesheet_image_src: Option<String>,
|
||||
#[serde(default)]
|
||||
pub ui_spritesheet_image_object_key: Option<String>,
|
||||
#[serde(default)]
|
||||
pub background_music: Option<PuzzleAudioAsset>,
|
||||
pub board: PuzzleBoardSnapshot,
|
||||
pub status: PuzzleRuntimeLevelStatus,
|
||||
|
||||
Reference in New Issue
Block a user