Add scene fragments to portrait prompts after clothing.

Thing, room, yard and climate precipitation can contribute a short prompt when they are in frame, with a budget so chairs stay silent.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-20 23:35:17 +03:00
co-authored by Cursor
parent f046f145ec
commit 3c682a2b74
26 changed files with 1020 additions and 26 deletions
+33 -5
View File
@@ -64,7 +64,7 @@ internal sealed class PortraitService(
return PortraitPromptBuildResult.InvalidPrompt;
}
var outcome = await LookupPersonAsync(schoolId, personId, cancellationToken);
var outcome = await LookupBuildInputAsync(schoolId, personId, cancellationToken);
if (outcome.Error == PersonLookupError.UnknownPerson)
{
return PortraitPromptBuildResult.UnknownPerson;
@@ -76,7 +76,12 @@ internal sealed class PortraitService(
}
var profile = ConfigFor(schoolId).Resolve(outcome.Card.Age, kind);
var (positive, negative) = PortraitPromptBuilder.Build(outcome.Card, profile, kind, resolved);
var (positive, negative) = PortraitPromptBuilder.Build(
outcome.Card,
profile,
kind,
resolved,
outcome.Scene);
return PortraitPromptBuildResult.Succeeded(
kind,
positive,
@@ -112,7 +117,7 @@ internal sealed class PortraitService(
}
}
var outcome = await LookupPersonAsync(schoolId, personId, cancellationToken);
var outcome = await LookupBuildInputAsync(schoolId, personId, cancellationToken);
if (outcome.Error == PersonLookupError.UnknownPerson)
{
return PortraitGenerationResult.UnknownPerson;
@@ -124,11 +129,20 @@ internal sealed class PortraitService(
}
var profile = ConfigFor(schoolId).Resolve(outcome.Card.Age, kind);
var (positive, negative) = PortraitPromptBuilder.Build(outcome.Card, profile, kind, promptExtra);
var (positive, negative) = PortraitPromptBuilder.Build(
outcome.Card,
profile,
kind,
promptExtra,
outcome.Scene);
try
{
var bytes = await swarm.GenerateAsync(positive, negative, profile, cancellationToken);
var bytes = await swarm.GenerateAsync(
positive,
negative,
PortraitPromptBuilder.ApplyScene(profile, outcome.Scene),
cancellationToken);
store.SavePortrait(schoolId, personId, kind, bytes, kind == PortraitKind.Custom ? promptExtra : null);
var flags = Flags(schoolId, personId);
var savedPrompt = kind == PortraitKind.Custom ? promptExtra : store.TryReadCustomPortraitPrompt(schoolId, personId);
@@ -159,6 +173,20 @@ internal sealed class PortraitService(
private SwarmUiConfigFile ConfigFor(int schoolId) =>
loop.PortraitSettingsOf(schoolId) ?? settingsStore.Current;
private async Task<PortraitBuildInputResult> LookupBuildInputAsync(
int schoolId,
string personId,
CancellationToken cancellationToken)
{
var command = new GameCommand.GetPortraitBuildInput(
schoolId,
personId,
PromptLocale,
NewCompletion<PortraitBuildInputResult>());
commands.Enqueue(command);
return await command.Result.Task.WaitAsync(PersonLookupTimeout, cancellationToken);
}
private async Task<PersonCardResult> LookupPersonAsync(
int schoolId,
string personId,