feat(previs): 图片生成预演台 - 从图片节点交给 Agent 复现为可编辑 3D 预演

图片工具栏新增「生成预演台」,自动选用支持看图的文本模型并提交复现指令。对话用节点卡片展示「此图」,普通图片演员只写名称时不再要求角色卡绑定。
This commit is contained in:
ddcat666
2026-10-09 17:17:28 +08:00
parent 5f322f2f5e
commit 8dcf0a252b
13 changed files with 282 additions and 23 deletions

View File

@@ -1086,7 +1086,9 @@ func cloudAgentPrevisApplyName(item map[string]any, value *string, label string)
}
func cloudAgentPrevisApplyCharacterBinding(item map[string]any, operation cloudAgentPrevisPatchOperation) error {
provided := operation.CharacterAssetID != nil || operation.CharacterVersionID != nil || operation.ReferenceNodeID != nil || operation.CharacterName != nil
// characterName is descriptive metadata for a real character-card binding;
// a name on an actor from an ordinary reference image must not trigger binding.
provided := operation.CharacterAssetID != nil || operation.CharacterVersionID != nil || operation.ReferenceNodeID != nil
if !provided {
return nil
}
@@ -1122,7 +1124,7 @@ func cloudAgentPrevisApplyCharacterBinding(item map[string]any, operation cloudA
}
func cloudAgentPrevisValidateCharacterBindingInCanvas(doc map[string]any, operation cloudAgentPrevisPatchOperation) error {
if operation.CharacterAssetID == nil && operation.CharacterVersionID == nil && operation.ReferenceNodeID == nil && operation.CharacterName == nil {
if operation.CharacterAssetID == nil && operation.CharacterVersionID == nil && operation.ReferenceNodeID == nil {
return nil
}
if operation.CharacterAssetID == nil || operation.CharacterVersionID == nil || operation.ReferenceNodeID == nil {

View File

@@ -495,6 +495,24 @@ func TestCloudAgentPrevisPatchLimitsAndClosedArguments(t *testing.T) {
}
}
func TestCloudAgentPrevisOrdinaryActorNameDoesNotRequireCharacterBinding(t *testing.T) {
scene, err := cloudAgentPrevisSceneCreateTemplate(cloudAgentPrevisSceneCreateArgs{SceneID: "image-scene", Title: "图片复现", TemplateID: "empty"})
if err != nil {
t.Fatal(err)
}
_, err = cloudAgentPrevisApplyPatchOperation(scene, cloudAgentPrevisPatchOperation{
Type: "object_add", ID: "image-actor", Kind: "actor", Primitive: "character",
Name: previsStringPtr("道姑"), CharacterName: previsStringPtr("道姑"), Pose: "stand",
}, 0)
if err != nil {
t.Fatalf("ordinary image actor was treated as a character binding: %v", err)
}
actor := cloudAgentPrevisFindByID(creationMaps(scene["objects"]), "image-actor")
if actor == nil || actor["characterBinding"] != nil {
t.Fatalf("ordinary actor unexpectedly has character binding: %#v", actor)
}
}
func TestCloudAgentPrevisCharacterBindingAndAnimationPatch(t *testing.T) {
s, canvas := previsMutationFixture(t)
canvas.PayloadJSON = `{"nodes":[{"id":"hero-card","type":"text","metadata":{"workflowKind":"character","characterAssetId":"hero-asset","characterVersionId":"hero-v1"}}],"connections":[],"previsScenes":[]}`