Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added proof of concept for mutation minigame #8

Merged
merged 7 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added blender/DNA.blend
Binary file not shown.
Binary file added blender/DNA.blend1
Binary file not shown.
Binary file added blender/Materials.blend
Binary file not shown.
Binary file added blender/Materials.blend1
Binary file not shown.
Binary file added blender/MenuItemTemplate.blend
Binary file not shown.
Binary file added blender/MenuItemTemplate.blend1
Binary file not shown.
1 change: 1 addition & 0 deletions blender/categories.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Binary file added blender/mutation_minigame/Deletion.blend
Binary file not shown.
Binary file added blender/mutation_minigame/Deletion.blend1
Binary file not shown.
Binary file added blender/mutation_minigame/Insertion.blend
Binary file not shown.
Binary file added blender/mutation_minigame/Insertion.blend1
Binary file not shown.
Binary file added blender/mutation_minigame/Substitution.blend
Binary file not shown.
Binary file added src/Quaternary_v1_21_10_2023.wav
Binary file not shown.
24 changes: 24 additions & 0 deletions src/Quaternary_v1_21_10_2023.wav.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[remap]

importer="wav"
type="AudioStreamWAV"
uid="uid://cn2oum7f7usj4"
path="res://.godot/imported/Quaternary_v1_21_10_2023.wav-20336e9ec6ea741be637b9878ef76fb3.sample"

[deps]

source_file="res://Quaternary_v1_21_10_2023.wav"
dest_files=["res://.godot/imported/Quaternary_v1_21_10_2023.wav-20336e9ec6ea741be637b9878ef76fb3.sample"]

[params]

force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=2
edit/loop_begin=1181538
edit/loop_end=1772308
compress/mode=0
38 changes: 38 additions & 0 deletions src/features/dynamicmenu/DragButton.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
class_name DragButton extends Button
## Button that can be dragged.
##
## Meant to be used in combination with Dynamic Menu, or any class that implements
## [method DynamicMenu.hide_slide_child] and [method DyanamicMenu.reveal_slide_child]

## set this in child classes to control the drop data of the button, can be anything
var drop_data: Variant

func _ready():
pass

var dragging: bool = false

func _get_drag_data(at_position):
var preview = Control.new()
var me = self.duplicate()
preview.add_child(me)
me.position = Vector2(0,0)

get_parent().hide_slide_child(self)
set_drag_preview(preview)
dragging = true
return drop_data

var done: bool = false

func _notification(what):
match what:
NOTIFICATION_DRAG_END:
if dragging and !is_drag_successful() and not done:
get_parent().reveal_slide_child(self)
dragging = false
if is_drag_successful() and not self.visible:
done = true



3 changes: 3 additions & 0 deletions src/features/dynamicmenu/DragButton.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[gd_scene format=3 uid="uid://dkpr6ekyhoogl"]

[node name="DragButton" type="Button"]
47 changes: 47 additions & 0 deletions src/features/dynamicmenu/DynamicMenu.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
class_name DynamicMenu extends Control
## A menu that can animate the appearance and dissapearance of control nodes
##
## extend this class on top of a box or grid container for automatic spacing

## Animate the reveal of a child of the dynamic menu
func reveal_slide_child(node: Control) -> void:
IllustratedMan-code marked this conversation as resolved.
Show resolved Hide resolved
var spacer = Control.new()
# set this if you want a min size for the spacer
#spacer.custom_minimum_size = Vector2(1,1)
self.add_child(spacer)
self.move_child(spacer, node.get_index())
var tween = create_tween()

var min_size: Vector2 = node.get_minimum_size()
if node.custom_minimum_size != Vector2(0,0):
min_size = node.custom_minimum_size
tween.tween_property(spacer, "custom_minimum_size",min_size, 0.2)
var spacer_finished = func():
self.remove_child(spacer)
node.visible = true
tween.connect("finished", spacer_finished)

## Animate the dissapearance of a child of the dynamic menu
func hide_slide_child(node: Control) -> void:
var spacer = Control.new()
spacer.custom_minimum_size = node.size
self.add_child(spacer)
self.move_child(spacer, node.get_index())
node.visible = false
var tween = create_tween()
tween.tween_property(spacer, "custom_minimum_size", Vector2(0,0), 0.2)
var spacer_finished = func():
self.remove_child(spacer)
tween.connect("finished", spacer_finished)




# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
pass
8 changes: 8 additions & 0 deletions src/features/dynamicmenu/DynamicMenu.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://cqh02rjae8qi6"]

[ext_resource type="Script" path="res://features/dynamicmenu/DynamicMenu.gd" id="1_3nblp"]

[node name="DynamicMenu" type="FlowContainer"]
offset_right = 40.0
offset_bottom = 40.0
script = ExtResource("1_3nblp")
63 changes: 63 additions & 0 deletions src/features/globals/globals.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
class_name Globals

enum NitrogenousBase {
A,
G,
T,
C,
BLANK,
U
}

const NitrogenousBaseDetails: Dictionary = {
NitrogenousBase.A:{
"name": "A",
"long_name": "ADENINE",
"bond": NitrogenousBase.T,
"bondRNA": NitrogenousBase.U
},
NitrogenousBase.G:{
"name": "G",
"long_name": "GUANINE",
"bond": NitrogenousBase.C,
"bondRNA": NitrogenousBase.C
},
NitrogenousBase.C:{
"name": "C",
"long_name": "CYTOSINE",
"bond": NitrogenousBase.G,
"bondRNA": NitrogenousBase.G
},
NitrogenousBase.T:{
"name": "T",
"long_name": "THYMINE",
"bond": NitrogenousBase.A,
"bondRNA": NitrogenousBase.A
},
NitrogenousBase.U:{
"name": "U",
"long_name": "URACIL",
"bond": NitrogenousBase.A,
"bondRNA": NitrogenousBase.A
},
NitrogenousBase.BLANK:{
"name": " ",
"long_name": " "
}
}
enum Mutation {
INSERTION,
DELETION,
SUBSTITUTION
}
var MutationDetails: Dictionary = {
Mutation.INSERTION: {
"name":"Insertion",
},
Mutation.DELETION: {
"name": "Deletion"
},
Mutation.SUBSTITUTION: {
"name": "Substitution"
}
}
111 changes: 111 additions & 0 deletions src/features/mutation_minigame/nodes/dna/DNA.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
extends DynamicMenu

@export var droppable: bool = true

var base_scene = preload("res://features/mutation_minigame/nodes/dna/Nucleotide.tscn")
var globals = get_node
signal mutation(sequence)

func add_base(base_id: Globals.NitrogenousBase = Globals.NitrogenousBase.BLANK) -> Node:
var base = base_scene.instantiate()
base.base = base_id
base.mutation.connect(mutation_handler)
self.add_child(base)
return base

var bases = [Globals.NitrogenousBase.A,
Globals.NitrogenousBase.G,
Globals.NitrogenousBase.T,
Globals.NitrogenousBase.C]

func random_dna(length: int):
var rng = RandomNumberGenerator.new()
IllustratedMan-code marked this conversation as resolved.
Show resolved Hide resolved

var _start = add_base()
for i in range(length):
var _base = add_base(bases[rng.randi_range(0, bases.size()-1)])
var _spacer = add_base()

func mutate_random(number_of_mutations: int = 4):
var rng = RandomNumberGenerator.new()

var possible_mutations = [
Globals.Mutation.INSERTION,
Globals.Mutation.DELETION,
Globals.Mutation.SUBSTITUTION
]
var mutations = []
for i in range(number_of_mutations):
var rand_base = bases[rng.randi_range(0, bases.size()-1)]
var rand_mutation = possible_mutations[rng.randi_range(0, possible_mutations.size()-1)]
var random_child: Node
var check_mutation = func():
while true:
random_child = get_children()[rng.randi_range(0, get_children().size()-1)]
if random_child.get("base") == Globals.NitrogenousBase.BLANK:
if rand_mutation == Globals.Mutation.INSERTION and random_child.visible:
return random_child
elif random_child.get("base") != null:
if rand_mutation != Globals.Mutation.INSERTION and random_child.visible:
return random_child
random_child = check_mutation.call()
var current_mutation = {
"Type": rand_mutation,
"Base": rand_base,
"node": random_child
}
mutations.append(current_mutation)
mutation_handler(random_child, current_mutation)
return mutations


func mutation_handler(node: Control, data: Dictionary):
if data["Type"] == Globals.Mutation.DELETION:
self.hide_slide_child(node)
self.hide_slide_child(self.get_child(node.get_index() + 1))
IllustratedMan-code marked this conversation as resolved.
Show resolved Hide resolved
node.is_deleted = true
elif data["Type"] == Globals.Mutation.INSERTION:
var blank = add_base()
var base = add_base(data["Base"])
base.visible = false
blank.visible = false
self.move_child(blank, node.get_index()+1)
self.move_child(base, node.get_index()+1)
self.reveal_slide_child(base)
self.reveal_slide_child(blank)
elif data["Type"] == Globals.Mutation.SUBSTITUTION:
node.base = data["Base"]

print(node.base)
print(data)

mutation.emit(sequence())

func make_reciprocal_strand():
for n in sequence_nodes():
n.base = Globals.NitrogenousBaseDetails[n.base].bond

func sequence_nodes():
var children = get_children()

var sequence_array = []
for c in children:
if c.get("base") != Globals.NitrogenousBase.BLANK and c.get("base") != null and c.is_deleted == false:
sequence_array.append(c)
return sequence_array

func reciprocal_sequence():
var sequence_array = []
for n in sequence_nodes():
sequence_array.append(Globals.NitrogenousBaseDetails[n.base].bond)
return sequence_array

func sequence():
var sequence_array = []
for n in sequence_nodes():
sequence_array.append(n.base)
return sequence_array

func _ready():
pass

11 changes: 11 additions & 0 deletions src/features/mutation_minigame/nodes/dna/DNA.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[gd_scene load_steps=2 format=3 uid="uid://drxre10a5wiml"]

[ext_resource type="Script" path="res://features/mutation_minigame/nodes/dna/DNA.gd" id="1_6ygvu"]

[node name="DNA" type="HBoxContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_6ygvu")
Binary file not shown.
33 changes: 33 additions & 0 deletions src/features/mutation_minigame/nodes/dna/FiraCode-Bold.ttf.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[remap]

importer="font_data_dynamic"
type="FontFile"
uid="uid://c44jo1vqdhoyr"
path="res://.godot/imported/FiraCode-Bold.ttf-ffbb26128842d0c9c03a8480f45157f1.fontdata"

[deps]

source_file="res://features/mutation_minigame/nodes/dna/FiraCode-Bold.ttf"
dest_files=["res://.godot/imported/FiraCode-Bold.ttf-ffbb26128842d0c9c03a8480f45157f1.fontdata"]

[params]

Rendering=null
antialiasing=1
generate_mipmaps=false
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
hinting=1
subpixel_positioning=1
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}
Loading