Skip to content

Commit

Permalink
improvement: let students to stay in the lesson and experiment upon c…
Browse files Browse the repository at this point in the history
…ompletion

closes #52, closes #77
  • Loading branch information
YuriSizov committed Jan 26, 2022
1 parent b1f0045 commit 5ca7512
Show file tree
Hide file tree
Showing 16 changed files with 333 additions and 162 deletions.
6 changes: 0 additions & 6 deletions project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,6 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://resources/Lesson.gd"
}, {
"base": "ColorRect",
"class": "LessonDonePopup",
"language": "GDScript",
"path": "res://ui/components/popups/LessonDonePopup.gd"
}, {
"base": "Resource",
"class": "LessonProgress",
"language": "GDScript",
Expand Down Expand Up @@ -297,7 +292,6 @@ _global_script_class_icons={
"GameView": "",
"LanguageServerError": "",
"Lesson": "",
"LessonDonePopup": "",
"LessonProgress": "",
"MiniGDScriptTokenizer": "",
"OutputConsole": "",
Expand Down
100 changes: 73 additions & 27 deletions ui/UIPractice.gd
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,23 @@ class_name UIPractice
extends Control

const RUN_AUTOTIMER_DURATION := 5.0
const DFM_TRANSITION_DURATION := 0.5

const PracticeHintScene := preload("screens/practice/PracticeHint.tscn")
const LessonDonePopupScene := preload("components/popups/LessonDonePopup.tscn")
const PracticeProgress := preload("screens/practice/PracticeProgress.gd")
const PracticeListPopup := preload("components/popups/PracticeListPopup.gd")
const PracticeDonePopup := preload("components/popups/PracticeDonePopup.gd")

export var test_practice: Resource

var _practice: Practice
var _practice_completed := false
var _practice_solution_used := false

var _script_slice: SliceProperties setget _set_script_slice
var _tester: PracticeTester
# If `true`, the text changed but was not saved.
var _code_editor_is_dirty := false
var _practice: Practice

# Set to true when running the test scene, then to false the moment Events.practice_run_completed emits.
var _run_tests_requested := false
Expand All @@ -24,7 +28,6 @@ var _run_tests_requested := false
var _run_autotimer: Timer

var _is_left_panel_open := true
var _info_panel_start_width := -1.0

var _current_scene: Node

Expand All @@ -33,15 +36,17 @@ onready var _game_container := find_node("GameContainer") as Container
onready var _game_view := _output_container.find_node("GameView") as GameView
onready var _output_console := _output_container.find_node("Console") as OutputConsole

onready var _info_panel_anchors := $Margin/Layout/InfoPanelAnchors as Control
onready var _info_panel := find_node("PracticeInfoPanel") as PracticeInfoPanel
onready var _documentation_panel := find_node("DocumentationPanel") as RichTextLabel
onready var _hints_container := _info_panel.hints_container as Revealer
onready var _practice_progress := _info_panel.progress_bar as PracticeProgress

onready var _practice_list := find_node("PracticeListPopup") as PracticeListPopup
onready var _practice_done_popup := find_node("PracticeDonePopup") as PracticeDonePopup

onready var _code_editor := find_node("CodeEditor") as CodeEditor

onready var _info_panel_control := $Margin/Layout/Control as Control
onready var _tween := $Tween as Tween

func _init():
Expand Down Expand Up @@ -69,13 +74,16 @@ func _ready() -> void:
_practice_progress.connect("next_requested", self, "_on_next_requested")
_practice_progress.connect("list_requested", self, "_on_list_requested")

_practice_done_popup.connect("accepted", self, "_on_next_requested")

Events.connect("practice_run_completed", self, "_test_student_code")

_update_info_panel()
connect("resized", self, "_update_info_panel")

if test_practice and get_parent() == get_tree().root:
setup(test_practice, null, null)

_info_panel_start_width = _info_panel.rect_size.x


func _gui_input(event: InputEvent) -> void:
var mb := event as InputEventMouseButton
Expand All @@ -90,6 +98,8 @@ func setup(practice: Practice, lesson: Lesson, course: Course) -> void:
yield(self, "ready")

_practice = practice
_practice_completed = false
_practice_solution_used = false

_info_panel.goal_rich_text_label.bbcode_text = TextUtils.bbcode_add_code_color(practice.goal)
_info_panel.title_label.text = practice.title.capitalize()
Expand All @@ -110,6 +120,7 @@ func setup(practice: Practice, lesson: Lesson, course: Course) -> void:
slice_path = base_directory.plus_file(slice_path)
_set_script_slice(load(slice_path))
_code_editor.slice_editor.setup(_script_slice)
_code_editor.set_continue_allowed(false)

var validator_path := practice.validator_script_path
if validator_path.is_rel_path():
Expand Down Expand Up @@ -242,60 +253,91 @@ func _test_student_code() -> void:
yield(_info_panel, "tests_updated")

# Show the end of practice popup.
if result.is_success():
Events.emit_signal("practice_completed", _practice)
if not _practice_completed and result.is_success():
_practice_completed = true

if not _practice_solution_used:
Events.emit_signal("practice_completed", _practice)

var popup := LessonDonePopupScene.instance() as LessonDonePopup
add_child(popup)
popup.fade_in(_game_container)
popup.connect("accepted", Events, "emit_signal", [ "practice_next_requested", _practice ])
_practice_done_popup.show()
_practice_done_popup.fade_in(_game_container)

# Clean-up.
_code_editor.unlock_editor()
if _practice_completed:
_code_editor.set_continue_allowed(true)


func _reset_practice() -> void:
# Code it already reset by the slice editor.
# Code is already reset by the slice editor.

_info_panel.reset_tests_status()

if _current_scene.has_method("reset"):
_current_scene.call("reset")


func _update_info_panel() -> void:
_info_panel.rect_min_size = Vector2(_info_panel_anchors.rect_size.x, 0)


func _toggle_distraction_free_mode() -> void:
_is_left_panel_open = not _is_left_panel_open
_tween.stop_all()
var duration := 0.5

# Open the panel.
if _is_left_panel_open:
_tween.interpolate_property(
_info_panel_control,
"rect_min_size:x",
_info_panel_control.rect_min_size.x,
_info_panel_start_width,
duration,
_info_panel_anchors,
"size_flags_stretch_ratio",
_info_panel_anchors.size_flags_stretch_ratio,
1.0,
DFM_TRANSITION_DURATION,
Tween.TRANS_SINE,
Tween.EASE_IN_OUT
)
_tween.interpolate_property(
_code_editor,
"size_flags_stretch_ratio",
_code_editor.size_flags_stretch_ratio,
1.0,
DFM_TRANSITION_DURATION,
Tween.TRANS_SINE,
Tween.EASE_IN_OUT
)
_tween.interpolate_property(
_info_panel_control, "modulate:a", _info_panel_control.modulate.a, 1.0, duration
_info_panel_anchors,
"modulate:a",
_info_panel_anchors.modulate.a,
1.0,
DFM_TRANSITION_DURATION
)
# Close the panel.
else:
_tween.interpolate_property(
_info_panel_control,
"rect_min_size:x",
_info_panel_control.rect_min_size.x,
_info_panel_anchors,
"size_flags_stretch_ratio",
_info_panel_anchors.size_flags_stretch_ratio,
0.0,
duration,
DFM_TRANSITION_DURATION,
Tween.TRANS_SINE,
Tween.EASE_IN_OUT
)
_tween.interpolate_property(
_code_editor,
"size_flags_stretch_ratio",
_code_editor.size_flags_stretch_ratio,
2.0,
DFM_TRANSITION_DURATION,
Tween.TRANS_SINE,
Tween.EASE_IN_OUT
)
_tween.interpolate_property(
_info_panel_control,
_info_panel_anchors,
"modulate:a",
_info_panel_control.modulate.a,
_info_panel_anchors.modulate.a,
0.0,
duration - 0.25,
DFM_TRANSITION_DURATION - 0.25,
Tween.TRANS_LINEAR,
Tween.EASE_IN,
0.15
Expand All @@ -319,6 +361,10 @@ func _on_code_editor_button(which: String) -> void:
_toggle_distraction_free_mode()
_code_editor.ACTIONS.RESTORE:
_reset_practice()
_code_editor.ACTIONS.SOLUTION:
_practice_solution_used = true
_code_editor.ACTIONS.CONTINUE:
_on_next_requested()


func _on_console_toggled() -> void:
Expand Down
38 changes: 23 additions & 15 deletions ui/UIPractice.tscn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[gd_scene load_steps=10 format=2]
[gd_scene load_steps=11 format=2]

[ext_resource path="res://ui/components/CodeEditor.tscn" type="PackedScene" id=1]
[ext_resource path="res://ui/theme/panel_course_page.tres" type="StyleBox" id=2]
Expand All @@ -9,6 +9,7 @@
[ext_resource path="res://ui/theme/panel_game.tres" type="StyleBox" id=7]
[ext_resource path="res://ui/UIPractice.gd" type="Script" id=8]
[ext_resource path="res://ui/theme/fonts/font_text_bold.tres" type="DynamicFont" id=9]
[ext_resource path="res://ui/components/popups/PracticeDonePopup.tscn" type="PackedScene" id=10]

[node name="UIPractice" type="PanelContainer"]
anchor_right = 1.0
Expand All @@ -30,31 +31,31 @@ margin_right = 1920.0
margin_bottom = 1080.0
custom_constants/separation = 12

[node name="Control" type="Control" parent="Margin/Layout"]
margin_right = 623.0
[node name="InfoPanelAnchors" type="Control" parent="Margin/Layout"]
margin_right = 632.0
margin_bottom = 1080.0
rect_min_size = Vector2( 623, 0 )
size_flags_horizontal = 3

[node name="PracticeInfoPanel" parent="Margin/Layout/Control" instance=ExtResource( 3 )]
anchor_left = 1.0
margin_left = -623.0
[node name="PracticeInfoPanel" parent="Margin/Layout/InfoPanelAnchors" instance=ExtResource( 3 )]
grow_horizontal = 0
grow_vertical = 2
size_flags_stretch_ratio = 2.0

[node name="CodeEditor" parent="Margin/Layout" instance=ExtResource( 1 )]
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 635.0
margin_right = 1271.0
margin_left = 644.0
margin_right = 1276.0
margin_bottom = 1080.0

[node name="Output" type="VBoxContainer" parent="Margin/Layout"]
margin_left = 1283.0
margin_left = 1288.0
margin_right = 1920.0
margin_bottom = 1080.0
size_flags_horizontal = 3

[node name="GameAnchors" type="Control" parent="Margin/Layout/Output"]
margin_right = 637.0
margin_right = 632.0
margin_bottom = 717.0
size_flags_vertical = 3
size_flags_stretch_ratio = 2.0
Expand All @@ -70,21 +71,21 @@ __meta__ = {
[node name="MarginContainer" type="MarginContainer" parent="Margin/Layout/Output/GameAnchors/GameContainer"]
margin_left = 8.0
margin_top = 8.0
margin_right = 629.0
margin_right = 624.0
margin_bottom = 709.0
custom_constants/margin_right = 12
custom_constants/margin_top = 12
custom_constants/margin_left = 12
custom_constants/margin_bottom = 60

[node name="GameView" parent="Margin/Layout/Output/GameAnchors/GameContainer/MarginContainer" instance=ExtResource( 4 )]
margin_right = 609.0
margin_right = 604.0
margin_bottom = 641.0

[node name="Label" type="Label" parent="Margin/Layout/Output/GameAnchors/GameContainer"]
margin_left = 8.0
margin_top = 661.0
margin_right = 629.0
margin_right = 624.0
margin_bottom = 709.0
rect_min_size = Vector2( 0, 48 )
size_flags_vertical = 8
Expand All @@ -97,7 +98,7 @@ align = 1
anchor_right = 0.0
anchor_bottom = 0.0
margin_top = 721.0
margin_right = 637.0
margin_right = 632.0
margin_bottom = 1080.0

[node name="PracticeListPopup" parent="." instance=ExtResource( 6 )]
Expand All @@ -107,4 +108,11 @@ anchor_bottom = 0.0
margin_right = 1920.0
margin_bottom = 1080.0

[node name="PracticeDonePopup" parent="." instance=ExtResource( 10 )]
visible = false
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 1920.0
margin_bottom = 1080.0

[node name="Tween" type="Tween" parent="."]
Loading

0 comments on commit 5ca7512

Please sign in to comment.