Improve CCS dialogue layout

This commit is contained in:
hz
2026-08-06 04:41:44 -05:00
parent 4792ff2620
commit ee8e8cf787
4 changed files with 205 additions and 37 deletions
+61 -4
View File
@@ -74,9 +74,25 @@ func _run() -> void:
await process_frame
_assert(screen.active_scene.is_patient_dialogue_visible(), "a selected topic should display the patient's response")
_assert(not screen.active_scene.choice_container.visible, "the next choices should wait until the patient finishes speaking")
_assert(_label_content_fits(screen.active_scene.dialogue_text), "the complete patient response should fit inside its speech bubble")
screen.active_scene.complete_dialogue_reveal()
_assert(screen.active_scene.choice_container.columns == 2, "branching interview choices should use two columns")
_assert(screen.active_scene.choice_container.get_child_count() == 8, "all available branching topics should render")
_assert(not screen.active_scene.choice_container.visible, "the completed response should remain visible during the short reading hold")
await create_timer(screen.active_scene.RESPONSE_HOLD_SECONDS + 0.1).timeout
await process_frame
_assert(not screen.active_scene.is_patient_dialogue_visible(), "questions should replace the patient response after the reading hold")
_assert(screen.active_scene.choice_container.get_child_count() == 4, "the first question page should contain four choices")
_assert(screen.active_scene.choice_pager.visible, "eight choices should display paging controls")
_assert(screen.active_scene.choice_page == 0, "new question sets should begin on the first page")
_assert(_visible_choice_ids(screen.active_scene) == ["topic_0", "topic_1", "topic_2", "topic_3"], "the first page should preserve choice order and IDs")
_assert(_choice_labels_fit(screen.active_scene), "first-page question text should fit within every button")
screen.active_scene._change_choice_page(1)
await process_frame
_assert(screen.active_scene.choice_page == 1, "Next should advance to the second question page")
_assert(screen.active_scene.choice_container.get_child_count() == 4, "the second question page should contain the remaining choices")
_assert(_visible_choice_ids(screen.active_scene) == ["topic_4", "topic_5", "topic_6", "topic_7"], "the second page should preserve choice order and IDs")
_assert(_choice_labels_fit(screen.active_scene), "second-page question text should fit within every button")
screen.active_scene._change_choice_page(-1)
_assert(screen.active_scene.choice_page == 0, "Previous should return to the first question page")
service.attempt = _sample_attempt(true)
screen._on_attempt_changed()
@@ -84,7 +100,9 @@ func _run() -> void:
_assert(screen.active_scene.dialogue_text.text == "Okay, doctor.", "attempt updates should advance the rendered patient response")
_assert(not screen.active_scene.choice_container.visible, "the terminal action should wait for the closing response")
screen.active_scene.complete_dialogue_reveal()
screen.active_scene.complete_response_transition()
_assert(screen.active_scene.choice_container.get_child_count() == 1, "terminal dialogue should expose the management handoff")
_assert(not screen.active_scene.choice_pager.visible, "a single terminal action should not show paging controls")
screen.active_scene.interview_continue_requested.emit()
_assert(host.shown_screen == "ccs_player", "terminal dialogue should hand off the same attempt to the CCS player")
@@ -143,9 +161,19 @@ func _sample_graphical_debrief() -> Dictionary:
func _sample_branching_attempt() -> Dictionary:
var option_texts := [
"Tell me more about the dizziness. Does the room spin, and have you fainted?",
"How has the fatigue affected you, and how have you been sleeping and eating?",
"You mentioned your stomach. Please describe the discomfort and when it occurs.",
"Have you had black stools, blood in vomit or stool, trouble swallowing, persistent vomiting, weight loss, or severe sudden pain?",
"What medicines do you take, including aspirin, ibuprofen, naproxen, or other over-the-counter products?",
"Do you have prior stomach problems, other medical conditions, surgeries, or medication allergies?",
"Do you smoke, drink alcohol, or use recreational drugs?",
"Any fever, shortness of breath, headaches, bowel changes, or urinary symptoms?"
]
var choices: Array = []
for index in 8:
choices.append({"id": "topic_%d" % index, "text": "Ask about history topic %d" % (index + 1), "nextNodeId": "topic_%d" % index})
choices.append({"id": "topic_%d" % index, "text": option_texts[index], "nextNodeId": "topic_%d" % index})
return {
"id": "attempt-1", "state": "active", "revision": 2,
"simulatedStartUtc": "2026-08-05T09:00:00Z", "simulatedMinute": 0,
@@ -153,12 +181,41 @@ func _sample_branching_attempt() -> Dictionary:
"openingCompleted": false,
"interview": {
"currentNodeId": "chief_concern",
"currentNode": {"id": "chief_concern", "patientText": "I feel tired and lightheaded.", "isTerminal": false, "choices": choices},
"currentNode": {
"id": "chief_concern",
"patientText": "For the past few weeks, I have felt worn out, and every so often I get lightheaded—especially when I stand up quickly.",
"isTerminal": false,
"choices": choices
},
"visitedChoiceIds": ["chief_concern"], "completed": false
}
}
func _visible_choice_ids(scene: Control) -> Array:
var ids: Array = []
for child in scene.choice_container.get_children():
ids.append(str(child.get_meta("choice_id", "")))
return ids
func _choice_labels_fit(scene: Control) -> bool:
for button in scene.choice_container.get_children():
var label := button.get_child(0) as Label
if label == null or not _label_content_fits(label):
return false
if not scene.choice_area.get_global_rect().encloses(button.get_global_rect()):
return false
return true
func _label_content_fits(label: Label) -> bool:
var font := label.get_theme_font("font")
var font_size := label.get_theme_font_size("font_size")
var content_height := float(label.get_line_count()) * font.get_height(font_size)
return content_height <= label.size.y + 0.5
func _assert(condition: bool, message: String) -> void:
if condition:
return