From 9724fb73abf9fd3760a4f3f3ac941a119708c97b Mon Sep 17 00:00:00 2001 From: dam Date: Thu, 16 Dec 2021 01:17:34 +0000 Subject: First prototype with working database and staging area. Fix incorrect warp in date picker. Disable physics engine. --- icons/icon.png | Bin 0 -> 19327 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 icons/icon.png (limited to 'icons/icon.png') diff --git a/icons/icon.png b/icons/icon.png new file mode 100755 index 0000000..4b35a32 Binary files /dev/null and b/icons/icon.png differ -- cgit v1.2.3 From 3f29bb41d713240eb7ba831f68981674d4db9eb9 Mon Sep 17 00:00:00 2001 From: dam Date: Thu, 16 Dec 2021 17:04:09 +0000 Subject: Fix issues when creating/editing entries. Fix android icon. --- export_presets.cfg | 6 ++--- icons/icon.png | Bin 19327 -> 42947 bytes icons/icon.xcf | Bin 0 -> 112237 bytes icons/icon_background.png | Bin 0 -> 36824 bytes icons/icon_background.png.import | 35 ++++++++++++++++++++++++++ icons/icon_foreground.png | Bin 0 -> 6327 bytes icons/icon_foreground.png.import | 35 ++++++++++++++++++++++++++ logic/database.gd | 52 ++++++++++++++++++--------------------- logic/stage.gd | 45 +++++++++++++++++++++------------ project.godot | 2 +- 10 files changed, 127 insertions(+), 48 deletions(-) create mode 100644 icons/icon.xcf create mode 100644 icons/icon_background.png create mode 100644 icons/icon_background.png.import create mode 100644 icons/icon_foreground.png create mode 100644 icons/icon_foreground.png.import (limited to 'icons/icon.png') diff --git a/export_presets.cfg b/export_presets.cfg index ae6c4cf..06377bd 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -35,9 +35,9 @@ package/name="" package/signed=true package/classify_as_game=false package/retain_data_on_uninstall=false -launcher_icons/main_192x192="" -launcher_icons/adaptive_foreground_432x432="" -launcher_icons/adaptive_background_432x432="" +launcher_icons/main_192x192="res://icons/icon.png" +launcher_icons/adaptive_foreground_432x432="res://icons/icon_foreground.png" +launcher_icons/adaptive_background_432x432="res://icons/icon_background.png" graphics/32_bits_framebuffer=true graphics/opengl_debug=false xr_features/xr_mode=0 diff --git a/icons/icon.png b/icons/icon.png index 4b35a32..63760ec 100755 Binary files a/icons/icon.png and b/icons/icon.png differ diff --git a/icons/icon.xcf b/icons/icon.xcf new file mode 100644 index 0000000..abfbec1 Binary files /dev/null and b/icons/icon.xcf differ diff --git a/icons/icon_background.png b/icons/icon_background.png new file mode 100644 index 0000000..6ee62e1 Binary files /dev/null and b/icons/icon_background.png differ diff --git a/icons/icon_background.png.import b/icons/icon_background.png.import new file mode 100644 index 0000000..7b6caab --- /dev/null +++ b/icons/icon_background.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon_background.png-7c479113bc74649f6884d5867344a330.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icons/icon_background.png" +dest_files=[ "res://.import/icon_background.png-7c479113bc74649f6884d5867344a330.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/icons/icon_foreground.png b/icons/icon_foreground.png new file mode 100644 index 0000000..919f2ff Binary files /dev/null and b/icons/icon_foreground.png differ diff --git a/icons/icon_foreground.png.import b/icons/icon_foreground.png.import new file mode 100644 index 0000000..8427899 --- /dev/null +++ b/icons/icon_foreground.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon_foreground.png-386f0ed4375c2b690a85127a54f3c7b2.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icons/icon_foreground.png" +dest_files=[ "res://.import/icon_foreground.png-386f0ed4375c2b690a85127a54f3c7b2.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/logic/database.gd b/logic/database.gd index 1abb984..db449ae 100644 --- a/logic/database.gd +++ b/logic/database.gd @@ -52,38 +52,34 @@ func _ready(): add_button.connect("pressed", self, "add_action") stage.connect("save", self, "save") stage.connect("discard", self, "discard") - refresh_list() + for it in db: + self.add_item(get_entry_view(it)) func get_entry_view(database_entry: Dictionary) -> String: return "%6s | %6s | %s" % [database_entry.process_id, database_entry.surgery_id, get_entry_date(database_entry)] -func refresh_list(): - self.clear() - for it in db: - self.add_item(get_entry_view(it)) - - func clear_selection(): unselect_all() func delete_action(): - # @DAM Could do some performance improvements var selected_entries_idx := self.get_selected_items() - var sorted_idx := Array(selected_entries_idx) - sorted_idx.sort() - sorted_idx.invert() - for idx in sorted_idx: - db.remove(idx) - self.remove_item(idx) + if selected_entries_idx.size() == 0: + return + assert(selected_entries_idx.size() == 1, "Multiple selected items not supported.") + var selected_idx = selected_entries_idx[0] + db.remove(selected_idx) + self.remove_item(selected_idx) + store_database() func edit_action(): var selected_entries_idx := self.get_selected_items() - if selected_entries_idx.size() != 1: + if selected_entries_idx.size() == 0: return + assert(selected_entries_idx.size() == 1, "Multiple selected items not supported.") staged_idx = selected_entries_idx[0] self.visible = false stage.visible = true @@ -95,20 +91,17 @@ func add_action(): stage.visible = true var staged := instance_entry() stage.set_stage(staged) - # @DAM This signal is connected but, if we select "DISCARD" it stays connectd. - # Maybe I should always keep the connection and use two different buttons on sage screen. - stage.connect("save", self, "save_new", [], CONNECT_ONESHOT) func save(database_entry: Dictionary): + database_entry = instance_entry(database_entry) # @DAM Maybe we could not be creating endless dictionaries? if staged_idx >= 0: db[staged_idx] = database_entry set_item_text(staged_idx, get_entry_view(database_entry)) -# items[staged_idx] = get_entry_view(database_entry) else: db.append(database_entry) add_item(get_entry_view(database_entry)) - + store_database() staged_idx = -1 self.visible = true @@ -118,9 +111,9 @@ func discard(): self.visible = true -func load_database(): +func load_database(file_path: String = DATABASE_FILE_PATH): var file := File.new() - file.open(DATABASE_FILE_PATH, File.READ_WRITE) + file.open(file_path, File.READ_WRITE) var headers: PoolStringArray var is_first_line := true # while database_file.eof_reached() == false: @@ -177,9 +170,9 @@ func load_database(): ] -func store_database(): +func store_database(file_path: String = DATABASE_FILE_PATH): var file := File.new() - file.open(DATABASE_FILE_PATH, File.WRITE) + file.open(file_path, File.WRITE) var header := PoolStringArray(ENTRY_PROTOTYPE.keys()) file.store_csv_line(header) var entry := PoolStringArray() @@ -188,14 +181,17 @@ func store_database(): file.close() -func instance_entry(params: Dictionary = {}) -> Dictionary: +static func instance_entry(params: Dictionary = {}) -> Dictionary: var new_entry := ENTRY_PROTOTYPE.duplicate(true) new_entry.process_id = params.get("process_id", "") new_entry.surgery_id = params.get("surgery_id", "") new_entry.place = params.get("place", "") var today = OS.get_date() - set_entry_date(new_entry, params.get("date", DATE_FORMAT % [today.year, today.month, today.day])) + new_entry.date_year = params.get("date_year", today.year) + new_entry.date_month = params.get("date_month", today.month) + new_entry.date_day = params.get("date_day", today.day) + new_entry.date = params.get("date", get_entry_date(new_entry)) new_entry.anesthetic = params.get("anesthetic", "") new_entry.first_assistant = params.get("first_assistant", "") @@ -210,11 +206,11 @@ func instance_entry(params: Dictionary = {}) -> Dictionary: return new_entry -func get_entry_date(entry: Dictionary) -> String: +static func get_entry_date(entry: Dictionary) -> String: return DATE_FORMAT % [entry.date_year, entry.date_month, entry.date_day] -func set_entry_date(entry: Dictionary, date: String): +static func set_entry_date(entry: Dictionary, date: String): date = date.strip_edges().replace(" ", DATE_SEPARATOR).replace("/", DATE_SEPARATOR).replace("\\", DATE_SEPARATOR) var year_month_idx := date.find(DATE_SEPARATOR) var month_day_idx := date.find(DATE_SEPARATOR, year_month_idx + 1) diff --git a/logic/stage.gd b/logic/stage.gd index a9f4fee..19018fa 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -54,22 +54,35 @@ func set_stage(entry: Dictionary): func get_stage() -> Dictionary: - var entry: Dictionary - entry.process_id = process_id.text - entry.surgery_id = surgery_id.text - entry.date_year = date.get_year() - entry.date_month = date.get_month() - entry.date_day = date.get_day() - entry.place = place.text - entry.anesthetic = anesthetic.text - entry.first_assistant = first_assistant.text - entry.type = type.text - entry.sub_type = sub_type.text - entry.sub_sub_type = sub_sub_type.text - entry.pathology = pathology.text - entry.intervention = intervention.text - entry.is_urgency = is_urgency.pressed - entry.notes = notes.text + +# var entry: Dictionary = Database.instance_entry({ +# "process_id": process_id.text, +# "surgery_id": surgery_id.text, +# "date_year": date.get_year(), +# "date_month": date.get_month(), +# "date_day": date.get_day(), +# "place": place.text, +# "anesthetic": anesthetic.text, +# "first_assistant": first_assistant.text, +# "type": type.text, +# }) + var entry: Dictionary = { + "process_id": process_id.text, + "surgery_id": surgery_id.text, + "date_year": date.get_year(), + "date_month": date.get_month(), + "date_day": date.get_day(), + "place": place.text, + "anesthetic": anesthetic.text, + "first_assistant": first_assistant.text, + "type": type.text, + "sub_type": sub_type.text, + "sub_sub_type": sub_sub_type.text, + "pathology": pathology.text, + "intervention": intervention.text, + "is_urgency": is_urgency.pressed, + "notes": notes.text, + } return entry diff --git a/project.godot b/project.godot index 41969be..584ffa8 100644 --- a/project.godot +++ b/project.godot @@ -43,7 +43,7 @@ run/main_scene="res://main.tscn" boot_splash/image="res://icons/icon.png" boot_splash/fullsize=false boot_splash/use_filter=false -boot_splash/bg_color=Color( 0, 0, 0, 1 ) +boot_splash/bg_color=Color( 0, 0, 0, 0 ) config/icon="res://icons/icon.png" config/quit_on_go_back=false -- cgit v1.2.3 From a2af4c7d07259a091deabdceaa5da1a2f7757c5e Mon Sep 17 00:00:00 2001 From: dam Date: Sat, 18 Dec 2021 03:14:52 +0000 Subject: Add drag detection threshold to date picker. Prototype touch drag on database screen. --- date_picker/value_picker.gd | 7 ++- icons/icon.png | Bin 42947 -> 43811 bytes icons/icon.xcf | Bin 112237 -> 151900 bytes icons/icon_background.png | Bin 36824 -> 37713 bytes logic/database.gd | 137 ++++++++++++++++++++++++++++++++++++++------ logic/stage.gd | 11 +++- main.tscn | 1 + project.godot | 2 +- touch_scroll.gd | 66 +++++++++++++++++++++ 9 files changed, 205 insertions(+), 19 deletions(-) create mode 100644 touch_scroll.gd (limited to 'icons/icon.png') diff --git a/date_picker/value_picker.gd b/date_picker/value_picker.gd index 5e77294..fcd7dff 100644 --- a/date_picker/value_picker.gd +++ b/date_picker/value_picker.gd @@ -5,6 +5,7 @@ class_name ValuePicker const VELOCITY_DECAYING_FACTOR: float = 5.5 const BINNING_THRESHOLD: float = 0.75 const BINNING_ADJUST_P: float = 5.0 +const DRAG_THRESHOLD_CM: float = 0.250 export var min_value: int export var max_value: int @@ -19,6 +20,7 @@ var anchor: float var value: int var offset: float +var screen_dpcm: float var scroll_unit_height: float var label_previous_base_position: float var label_current_base_position: float @@ -39,6 +41,7 @@ func _ready(): input.connect("focus_entered", self, "input_focus_entered") input.connect("focus_exited", self, "input_focus_exited") + screen_dpcm = float(OS.get_screen_dpi()) / 2.54 scroll_unit_height = label_current.rect_size.y label_previous_base_position = label_previous.rect_position.y label_current_base_position = label_current.rect_position.y @@ -105,7 +108,8 @@ func _gui_input(event: InputEvent): var drag := event as InputEventScreenDrag pointer.current_position = drag.position pointer.velocity = drag.speed - pointer.was_dragged = true + if pointer.current_position.distance_to(pointer.initial_position) / screen_dpcm > DRAG_THRESHOLD_CM: + pointer.was_dragged = true func input_text_entered(new_text: String): @@ -113,6 +117,7 @@ func input_text_entered(new_text: String): func input_focus_entered(): + pointer.velocity = Vector2.ZERO # Avoid changing to other value once entering input. input.text = "%d" % value input.visible = true input.select_all() diff --git a/icons/icon.png b/icons/icon.png index 63760ec..95c7db3 100755 Binary files a/icons/icon.png and b/icons/icon.png differ diff --git a/icons/icon.xcf b/icons/icon.xcf index abfbec1..57986fb 100644 Binary files a/icons/icon.xcf and b/icons/icon.xcf differ diff --git a/icons/icon_background.png b/icons/icon_background.png index 6ee62e1..bbb555d 100644 Binary files a/icons/icon_background.png and b/icons/icon_background.png differ diff --git a/logic/database.gd b/logic/database.gd index db449ae..5f91c12 100644 --- a/logic/database.gd +++ b/logic/database.gd @@ -24,6 +24,7 @@ const ENTRY_PROTOTYPE: Dictionary = { } var db: Array +var selected_idx: int var staged_idx: int onready var delete_button: Button = get_node("actions/delete") @@ -34,18 +35,14 @@ onready var stage: Stage = get_node("/root/main/stage") func _init(): + selected_idx = -1 staged_idx = -1 load_database() store_database() # @DAM Only for testing. -# @DAM WIP -#func _notification(what: int): -# if what == MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST: -# clear_selection() - - func _ready(): + self.connect("item_selected", self, "item_selected") self.connect("nothing_selected", self, "clear_selection") delete_button.connect("pressed", self, "delete_action") edit_button.connect("pressed", self, "edit_action") @@ -56,31 +53,63 @@ func _ready(): self.add_item(get_entry_view(it)) +func _notification(what: int): + if what == MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST: + if selected_idx >= 0: + clear_selection() + else: + get_tree().quit() + + +# @DAM Testing +#var last_event +#var bypass: bool = false +#func _gui_input(event: InputEvent): +# if bypass == false: +# if event is InputEventScreenTouch && event.is_pressed(): +# accept_event() +# last_event = event +# elif event is InputEventScreenTouch && event.is_pressed() == false: +# bypass = true +# get_tree().input_event(event) +# bypass = false +# else: +# var x = 3 + + func get_entry_view(database_entry: Dictionary) -> String: return "%6s | %6s | %s" % [database_entry.process_id, database_entry.surgery_id, get_entry_date(database_entry)] +func item_selected(index: int): + if selected_idx >= 0: + set_item_text(selected_idx, get_entry_view(db[selected_idx])) + selected_idx = index + set_item_text(selected_idx, "> " + get_entry_view(db[selected_idx]) + " <") + + + func clear_selection(): + if selected_idx >= 0: + set_item_text(selected_idx, get_entry_view(db[selected_idx])) + selected_idx = -1 unselect_all() func delete_action(): - var selected_entries_idx := self.get_selected_items() - if selected_entries_idx.size() == 0: + if selected_idx < 0: return - assert(selected_entries_idx.size() == 1, "Multiple selected items not supported.") - var selected_idx = selected_entries_idx[0] + db.remove(selected_idx) self.remove_item(selected_idx) store_database() func edit_action(): - var selected_entries_idx := self.get_selected_items() - if selected_entries_idx.size() == 0: + if selected_idx < 0: return - assert(selected_entries_idx.size() == 1, "Multiple selected items not supported.") - staged_idx = selected_entries_idx[0] + + staged_idx = selected_idx self.visible = false stage.visible = true stage.set_stage(db[staged_idx]) @@ -116,7 +145,7 @@ func load_database(file_path: String = DATABASE_FILE_PATH): file.open(file_path, File.READ_WRITE) var headers: PoolStringArray var is_first_line := true -# while database_file.eof_reached() == false: +# while database_file.eof_reached() == false: # @DAM Why this? while file.get_position() < file.get_len(): var csv_entry := file.get_csv_line() if is_first_line: @@ -135,7 +164,10 @@ func load_database(file_path: String = DATABASE_FILE_PATH): _: entry[field_name] = field_value db.append(entry) + + fake_database() return + db = [ instance_entry({ "process_id": "000001", @@ -191,7 +223,7 @@ static func instance_entry(params: Dictionary = {}) -> Dictionary: new_entry.date_year = params.get("date_year", today.year) new_entry.date_month = params.get("date_month", today.month) new_entry.date_day = params.get("date_day", today.day) - new_entry.date = params.get("date", get_entry_date(new_entry)) + new_entry.date = params.get("date", get_entry_date(new_entry)) # @DAM We should store only one version of the date. new_entry.anesthetic = params.get("anesthetic", "") new_entry.first_assistant = params.get("first_assistant", "") @@ -220,3 +252,76 @@ static func set_entry_date(entry: Dictionary, date: String): entry.date_day = int(date.substr(month_day_idx + 1)) +func fake_database(): + db.resize(0) + for idx in range(50): + var date_year = 1 + int(float(idx) / 365.0) + var date_month = idx % 12 + var date_day = idx % 365 + db.append(instance_entry({ + "process_id": "%06d" % idx, + "surgery_id": "s%05d" % idx, + "date": "%04d-%02d-%02d" % [date_year, date_month, date_day] + })) + + + + + + + +# @DAM Testing. +export(float) var drag_threshold = 5 + +onready var touch_enabled = OS.has_touchscreen_ui_hint() +onready var v_scroll = get_v_scroll() + +var dragging = false +var pressed = false +var last_event +# must be _input, as _gui_input has bugs, with no touch.pressed = false events +# see: https://github.com/godotengine/godot/issues/16761 +func _gui_input(event): + + if event is InputEventScreenDrag: + self.v_scroll.value -= event.relative.y + + return + if not visible: + return + + if not touch_enabled: + return + + if event is InputEventScreenDrag: + accept_event() + if event.speed == Vector2(): + # we're on a device and speed is broken + # see: https://github.com/godotengine/godot/issues/3623 + event.speed = event.relative + if abs(event.speed.y) >= drag_threshold: + # scroll the list + dragging = true + v_scroll.value -= event.relative.y + return + + if event is InputEventScreenTouch: + if event.index == 0: + accept_event() + if dragging && event.pressed == false: + # prints("end drag") + dragging = false + pressed = false + else: + if event.pressed && pressed == false: + # prints("touch start") + pressed = true + accept_event() + # TODO: prevent select highlight + elif !event.pressed && pressed == true: + # prints("touch end and accept") + pressed = false + var ev = InputEventAction.new() + ev.action = "ui_accept" + ev.pressed = true + Input.parse_input_event(ev) diff --git a/logic/stage.gd b/logic/stage.gd index 19018fa..207b451 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -1,4 +1,4 @@ -extends Control +extends ScrollContainer class_name Stage signal save # (database_entry: Dictionary) @@ -66,6 +66,7 @@ func get_stage() -> Dictionary: # "first_assistant": first_assistant.text, # "type": type.text, # }) + # @DAM Simplify all this... avoid creating multiple entries/dictionaries. var entry: Dictionary = { "process_id": process_id.text, "surgery_id": surgery_id.text, @@ -86,6 +87,14 @@ func get_stage() -> Dictionary: return entry +# @DAM Testing. Needs all children controllers to have Mouse > Filter : Pass. +func _gui_input(event): + accept_event() + if event is InputEventScreenDrag: + self.scroll_vertical -= event.relative.y + return + + func _notification(what: int): if what == MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST: discard_action() diff --git a/main.tscn b/main.tscn index 53f083a..4096c59 100644 --- a/main.tscn +++ b/main.tscn @@ -116,6 +116,7 @@ margin_top = 112.0 margin_right = 1080.0 margin_bottom = 312.0 rect_min_size = Vector2( 400, 200 ) +mouse_filter = 0 [node name="place" type="LineEdit" parent="stage/controls"] margin_top = 316.0 diff --git a/project.godot b/project.godot index 584ffa8..3df8f21 100644 --- a/project.godot +++ b/project.godot @@ -19,7 +19,7 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://date_picker/date_picker.gd" }, { -"base": "Control", +"base": "ScrollContainer", "class": "Stage", "language": "GDScript", "path": "res://logic/stage.gd" diff --git a/touch_scroll.gd b/touch_scroll.gd new file mode 100644 index 0000000..ea92087 --- /dev/null +++ b/touch_scroll.gd @@ -0,0 +1,66 @@ +extends Control + + +func _gui_input(event: InputEvent): +#func _input(event: InputEvent): +# return + if event is InputEventScreenDrag: + self.v_scroll.value -= event.relative.y +# accept_event() + +#func _gui_input(event): +# accept_event() +# get_tree().set_input_as_handled() +# if event is InputEventScreenDrag: +# get_parent().v_scroll.value -= event.relative.y + + +export(float) var drag_threshold = 5 +onready var touch_enabled = OS.has_touchscreen_ui_hint() +onready var v_scroll = get_parent().get_v_scroll() + +var dragging = false +var pressed = false +var last_event +# must be _input, as _gui_input has bugs, with no touch.pressed = false events +# see: https://github.com/godotengine/godot/issues/16761 +func _input_disabled(event): +#func _gui_input(event): + + if not visible: + return + + if not touch_enabled: + return + + if event is InputEventScreenDrag: + accept_event() + if event.speed == Vector2(): + # we're on a device and speed is broken + # see: https://github.com/godotengine/godot/issues/3623 + event.speed = event.relative + if abs(event.speed.y) >= drag_threshold: + # scroll the list + dragging = true + v_scroll.value -= event.relative.y + return + + if event is InputEventScreenTouch: + if event.index == 0: + accept_event() + if dragging && event.pressed == false: + # prints("end drag") + dragging = false + pressed = false + else: + if event.pressed && pressed == false: + # prints("touch start") + pressed = true + # TODO: prevent select highlight + elif !event.pressed && pressed == true: + # prints("touch end and accept") + pressed = false + var ev = InputEventAction.new() + ev.action = "ui_accept" + ev.pressed = true + Input.parse_input_event(ev) -- cgit v1.2.3