From 7cb4290601010459b09376396c7833ec391c25bf Mon Sep 17 00:00:00 2001 From: jacopograndi Date: Fri, 24 Dec 2021 21:11:39 +0100 Subject: working on it --- scripts/gui_bottom_bar.gd | 41 +++++++++ scripts/gui_picker.gd | 49 +++++++++++ scripts/gui_top_bar.gd | 31 +++++++ scripts/gui_turret.gd | 60 +++++++++++++ scripts/load_map.gd | 113 +++++++++++++++++++++++++ scripts/load_scenes.gd | 7 ++ scripts/load_turrets.gd | 52 ++++++++++++ scripts/placer.gd | 210 ++++++++++++++++++++++++++++++++++++++++++++++ scripts/resources.gd | 27 ++++++ scripts/saveload.gd | 26 ++++++ 10 files changed, 616 insertions(+) create mode 100644 scripts/gui_bottom_bar.gd create mode 100644 scripts/gui_picker.gd create mode 100644 scripts/gui_top_bar.gd create mode 100644 scripts/gui_turret.gd create mode 100644 scripts/load_map.gd create mode 100644 scripts/load_scenes.gd create mode 100644 scripts/load_turrets.gd create mode 100644 scripts/placer.gd create mode 100644 scripts/resources.gd create mode 100644 scripts/saveload.gd (limited to 'scripts') diff --git a/scripts/gui_bottom_bar.gd b/scripts/gui_bottom_bar.gd new file mode 100644 index 0000000..0a7b7b8 --- /dev/null +++ b/scripts/gui_bottom_bar.gd @@ -0,0 +1,41 @@ +extends Control + +var _in_editor : bool +var voxel_picker : Control +var map_tool_picker : Control +var turret_picker : Control + +var _load_turrets : Node + +var gui : Control + +func _fetch (): + if gui == null: gui = get_parent() + if voxel_picker == null: voxel_picker = $voxels + if map_tool_picker == null: map_tool_picker = $map_tools + if turret_picker == null: turret_picker = $turrets + + var root = get_tree().root.get_child(0) + if _load_turrets == null: + _load_turrets = root.get_node("saveload").get_node("load_turrets") + +func build (): + _fetch() + turret_picker.build(_load_turrets.get_base_turrets()) + voxel_picker.build() + map_tool_picker.build() + +func refresh (in_editor : bool): + _fetch() + _in_editor = in_editor + + if _in_editor: + voxel_picker.visible = true + map_tool_picker.visible = true + else: + voxel_picker.visible = false + map_tool_picker.visible = false + + turret_picker.refresh(gui.player.sel) + voxel_picker.refresh(gui.player.sel) + map_tool_picker.refresh(gui.player.sel) diff --git a/scripts/gui_picker.gd b/scripts/gui_picker.gd new file mode 100644 index 0000000..df4ee9b --- /dev/null +++ b/scripts/gui_picker.gd @@ -0,0 +1,49 @@ +extends Panel + +var _hbox : HBoxContainer +var _gui_button : Resource = load("res://scenes/gui/gui_turret.tscn") + +var _options = [] + +var gui : Control + +func _fetch (): + if gui == null: gui = get_parent().gui + if _hbox == null: _hbox = $ScrollContainer/Hbox + +func build (options : Array = []): + _fetch() + + if options.size() > 0: + for n in _hbox.get_children(): n.queue_free() + + _options = options + for t in _options: + var gt : TextureButton = _gui_button.instance() + gt.name = t.name + _hbox.add_child(gt) + gt.init(t) + + for child in _hbox.get_children(): + if child.get_signal_connection_list("pressed").size() == 0: + child.connect("mouse_entered", self, "_on_gui_turret_mouse_entered", [child.name]) + child.connect("mouse_exited", self, "_on_gui_turret_mouse_entered", [child.name]) + child.connect("pressed", self, "_on_gui_turret_pressed", [child.name]) + +func refresh (sel = ""): + _fetch() + if sel.type == "": + for child in _hbox.get_children(): child.picked = false + if sel.type == name: + for child in _hbox.get_children(): + child.picked = child.name == sel.name + +func _on_gui_turret_mouse_entered(name : String): + print(name + " entered from " + self.name) + +func _on_gui_turret_mouse_exited(name : String): + print(name + " exited from " + self.name) + +func _on_gui_turret_pressed(name : String): + print(name + " pressed from " + self.name) + gui.player.selected_event(name, self.name) diff --git a/scripts/gui_top_bar.gd b/scripts/gui_top_bar.gd new file mode 100644 index 0000000..a002e87 --- /dev/null +++ b/scripts/gui_top_bar.gd @@ -0,0 +1,31 @@ +extends Control + +var _in_editor : bool +var _editor_button : Button +var _hbox : HBoxContainer + +var _resources : Node +var _gui : Control + +func refresh (in_editor : bool): + _in_editor = in_editor + + var root = get_tree().root.get_child(0) + _resources = root.get_node("player").get_node("resources") + + if _gui == null: _gui = get_parent() + if _hbox == null: _hbox = $panel/resources/HBoxContainer + if _editor_button == null: _editor_button = $panel/editor_button + + if _in_editor: _editor_button.text = "Editor" + else: _editor_button.text = "Playmode" + +func _process (_delta): + for r in _resources.get_names(): + _hbox.get_node(r).text = str(_resources[r]) + r + +func _on_editor_button_down(): + _gui.player.gui_editor_toggle_event() + +func _on_wave_button_pressed(): + _gui.player.gui_start_wave_event() diff --git a/scripts/gui_turret.gd b/scripts/gui_turret.gd new file mode 100644 index 0000000..9faeb7a --- /dev/null +++ b/scripts/gui_turret.gd @@ -0,0 +1,60 @@ +extends TextureButton + +var _turret : Dictionary + +var _color_rect : ColorRect +var _name_label : Label +var _cash_label : Label + +var _viewport : Viewport +var _spinner : Node +var _mesh : Node + +var _resources : Node + +var picked : bool +var enabled : bool = false + +var _rotate_timer : float + +func init (turret : Dictionary): + _turret = turret + _color_rect = $ColorRect + _name_label = $hbox/name_label + _cash_label = $cash_label + _viewport = $viewport + _spinner = $viewport/spinner + + var root = get_tree().root.get_child(0) + _resources = root.get_node("player").get_node("resources") + + _name_label.text = turret.name + _cash_label.text = _resources.dict_to_str(turret.cost) + + var load_turrets = root.get_node("saveload").get_node("load_turrets") + if !load_turrets.loaded: yield(load_turrets, "done_loading") + var model = load_turrets.models[turret.model_name] + _mesh = model.instance() + _spinner.add_child(_mesh) + + texture_normal = _viewport.get_texture() + +func _process(delta): + if !has_node("viewport"): return + if _spinner == null: _spinner = $viewport/spinner + if _spinner != null: + if _resources == null: + var root = get_tree().root.get_child(0) + _resources = root.get_node("player").get_node("resources") + + var afforded = _resources.greater_than(_turret.cost) + if afforded: _color_rect.color = Color(0,0,0,0) + else: _color_rect.color = Color(0,0,0,0.5) + + if afforded and (is_hovered() or picked): + _spinner.transform.basis = _spinner.transform.rotated(Vector3.UP, delta).basis + _rotate_timer = 0 + else: + _rotate_timer = min(1, _rotate_timer + delta * 5) + var idle_rot = Transform.rotated(Vector3.UP, PI-PI/4).basis + _spinner.transform.basis = _spinner.transform.basis.slerp(idle_rot, _rotate_timer) diff --git a/scripts/load_map.gd b/scripts/load_map.gd new file mode 100644 index 0000000..8130997 --- /dev/null +++ b/scripts/load_map.gd @@ -0,0 +1,113 @@ +extends Node + +var _world : VoxelMesh = null +var _path_holder : Node = null +var _attach_point_holder : Node = null + +var _load_scenes : Node = null + +func _ready(): + map_load() + +func fetch (): + var root = get_tree().root.get_child(0) + if _world == null: + _world = root.get_node("world") + if _path_holder == null: + _path_holder = root.get_node("path") + if _attach_point_holder == null: + _attach_point_holder = root.get_node("attach") + if _load_scenes == null: + _load_scenes = root.get_node("saveload").get_node("load_scenes") + +func get_map_state (): + fetch() + var state = {} + + state["voxels"] = [] + for pos in _world.get_voxels(): + var vox = { "pos": [pos.x, pos.y, pos.z], "id":_world.get_voxel_id(pos) } + state["voxels"] += [vox] + + state["path"] = [] + for node in _path_holder.get_children(): + var pos = node.transform.origin; + var rot = node.transform.basis.get_rotation_quat(); + var pobj = { + "pos": [pos.x, pos.y, pos.z], + "rot": [rot.x, rot.y, rot.z, rot.w], + "id": node.name + } + state["path"] += [pobj] + + state["attach"] = [] + for node in _attach_point_holder.get_children(): + var pos = node.transform.origin; + var rot = node.transform.basis.get_rotation_quat(); + var pobj = { + "pos": [pos.x, pos.y, pos.z], + "rot": [rot.x, rot.y, rot.z, rot.w], + "id": node.name + } + state["attach"] += [pobj] + + return state + +func set_map_state (state): + fetch() + _world.erase_voxels() + for vox in state["voxels"]: + var vecpos = Vector3(vox.pos[0], vox.pos[1], vox.pos[2]); + _world.set_voxel(vecpos, vox.id) + _world.update_mesh() + + for n in _path_holder.get_children(): n.queue_free() + + for pobj in state["path"]: + var blue = _load_scenes.path + if "start" in pobj.id: + blue = _load_scenes.path_start + if "end" in pobj.id: + blue = _load_scenes.path_end + var instance = blue.instance() + _path_holder.add_child(instance) + var vecpos = Vector3(pobj.pos[0], pobj.pos[1], pobj.pos[2]); + instance.transform.origin = vecpos; + var quat = Quat(pobj.rot[0], pobj.rot[1], pobj.rot[2], pobj.rot[3]); + instance.transform.basis = Basis(quat); + + for n in _attach_point_holder.get_children(): n.queue_free() + + for pobj in state["attach"]: + var blue = _load_scenes.attach_point + var instance = blue.instance() + _attach_point_holder.add_child(instance) + var vecpos = Vector3(pobj.pos[0], pobj.pos[1], pobj.pos[2]); + instance.transform.origin = vecpos; + var quat = Quat(pobj.rot[0], pobj.rot[1], pobj.rot[2], pobj.rot[3]); + instance.transform.basis = Basis(quat); + + +func map_save(): + var save_game = File.new() + save_game.open("user://map0.json", File.WRITE) + save_game.store_string(to_json(get_map_state())) + save_game.close() + print("saved") + +func map_load(): + var save_game = File.new() + save_game.open("user://map0.json", File.READ) + var raw = save_game.get_as_text() + save_game.close() + + var state = parse_json(raw) + set_map_state(state) + print("loaded") + + +func _process(_delta): + if Input.is_action_just_released("save"): + map_save() + if Input.is_action_just_released("load"): + map_load() diff --git a/scripts/load_scenes.gd b/scripts/load_scenes.gd new file mode 100644 index 0000000..fe237a4 --- /dev/null +++ b/scripts/load_scenes.gd @@ -0,0 +1,7 @@ +extends Node + +var turret : PackedScene = load("res://scenes/turret.tscn") +var path_start : PackedScene = load("res://scenes/path_start.tscn") +var path : PackedScene = load("res://scenes/path.tscn") +var path_end : PackedScene= load("res://scenes/path_end.tscn") +var attach_point : PackedScene = load("res://scenes/attach_point.tscn") diff --git a/scripts/load_turrets.gd b/scripts/load_turrets.gd new file mode 100644 index 0000000..3c9f378 --- /dev/null +++ b/scripts/load_turrets.gd @@ -0,0 +1,52 @@ +extends Node + +var saveload : Node + +var info : Dictionary +var models : Dictionary +var thumbs : Dictionary + +var loaded : bool = false +signal done_loading + +func _ready(): + get_saveload() + load_models() + load_info() + emit_signal("done_loading") + loaded = true + +func get_saveload(): + if saveload == null: saveload = get_tree().root.get_child(0).get_node("saveload") + +func get_base_turrets(): + var results = [] + for turr in info.values(): + var flag = true + for oth in info.values(): + if oth.name == turr.name: continue + if turr.name in oth.upgrades: + flag = false + if flag: results.append(turr) + return results + +func load_info(): + info.clear() + var files = saveload.parse_dir("res://assets", ".json") + for turr in files: + var parsed = saveload.load_parse_json("res://assets/" + turr) + if parsed != null: + for tin in parsed: + info[tin.name] = tin + +func load_models(): + models.clear() + var files = saveload.parse_dir("res://models/turrets", ".glb") + for turr in files: + models[turr] = load("res://models/turrets/" + turr) + +func load_thumbs(): + thumbs.clear() + var files = saveload.parse_dir("res://textures/thumbnails", ".png") + for turr in files: + thumbs[turr] = load("res://textures/thumbnails/" + turr) diff --git a/scripts/placer.gd b/scripts/placer.gd new file mode 100644 index 0000000..f06944e --- /dev/null +++ b/scripts/placer.gd @@ -0,0 +1,210 @@ +extends Spatial + +var player : Spatial +var world : VoxelMesh +var turret_holder : Node +var path_holder : Node +var attach_point_holder : Node +var load_turrets : Node +var saveload_map : Node +var load_scenes : Node +var ptr : Spatial +var resources : Node + +var normal = Vector3.ZERO +var colliding = false +var colliding_group = [] +var colliding_node : Spatial +var collision_point : Vector3 + +func _ready (): + player = get_parent() + resources = get_parent().get_node("resources") + + var root = get_tree().root.get_child(0) + world = root.get_node("world") + turret_holder = root.get_node("turrets") + attach_point_holder = root.get_node("attach") + path_holder = root.get_node("path") + ptr = root.find_node("pointer"); + + var saveload = root.get_node("saveload") + load_turrets = saveload.get_node("load_turrets") + saveload_map = saveload.get_node("saveload_map") + load_scenes = saveload.get_node("load_scenes") + + if !load_turrets.loaded: yield(load_turrets, "done_loading") + +func _physics_process(_delta): + _pointer() + +func check_overlap_pointer(): + var overlap = false + var space = get_world().direct_space_state + + var center = ptr.transform.origin + normal*0.25 + + var shape: = BoxShape.new() + shape.extents = Vector3(0.24, 0.24, 0.24) + + var params: = PhysicsShapeQueryParameters.new() + params.set_shape(shape) + params.collision_mask = 3 + params.transform = Transform.IDENTITY + params.transform.origin = center + + var result = space.intersect_shape(params) + for body in result: + if !body.collider.get_parent().is_in_group("attach"): + overlap = true + break + + for pos in world.get_voxels(): + var wpos = pos * 0.5 + wpos += Vector3.ONE * (0.5 / 2) + var dist = (wpos - center).length_squared() + if dist < 0.1: + overlap = true + break + + for node in path_holder.get_children(): + var pos = node.transform.origin + var dist = (pos - center).length_squared() + if dist < 0.1: + overlap = true + break + + return overlap + +func _inst_turret (pos, rot): + var instance = load_scenes.turret.instance() + turret_holder.add_child(instance) + instance.transform.origin = pos; + instance.transform.basis = Basis(rot); + instance.refresh_normal() + + var info = load_turrets.info[player.sel.name] + var model = load_turrets.models[info.model_name] + var instance_model = model.instance() + instance_model.name = "model" + instance.add_child(instance_model) + instance.refresh_model() + + instance.refresh_info(info) + +func _inst_path_start (pos, rot): + var instance = load_scenes.path_start.instance() + path_holder.add_child(instance) + instance.transform.origin = pos + normal * 0.25; + instance.transform.basis = Basis(rot); + +func _inst_path (pos, rot): + var instance = load_scenes.path.instance() + path_holder.add_child(instance) + instance.transform.origin = pos + normal * 0.25; + instance.transform.basis = Basis(rot); + instance.set_name("path") + colliding_node.transform.basis = Basis(rot); + +func _inst_path_end (pos, rot): + var instance = load_scenes.path_end.instance() + path_holder.add_child(instance) + instance.transform.origin = pos + normal * 0.25 + instance.transform.basis = Basis(rot); + +func _inst_attach (pos, rot): + var instance = load_scenes.attach_point.instance() + attach_point_holder.add_child(instance) + instance.transform.origin = pos; + instance.transform.basis = Basis(rot); + +func place (group, inst : FuncRef): + if Input.is_action_just_pressed("use"): + if colliding && group in colliding_group: + if !check_overlap_pointer(): + inst.call_func(ptr.transform.origin, ptr.transform.basis.get_rotation_quat()) + return "ok" + +func delete (group): + if Input.is_action_just_pressed("cancel"): + if colliding && group in colliding_group: + colliding_node.queue_free() + +func select (): + pass + +func _pointer (): + if player.sel.name == "" or player.sel.type == "": ptr.visible = false + else: ptr.visible = true + + var space: PhysicsDirectSpaceState = get_world().direct_space_state as PhysicsDirectSpaceState + var mouse2d = get_viewport().get_mouse_position() + var from = player.camera.project_ray_origin(mouse2d) + var to = (from + player.camera.project_ray_normal(mouse2d) * 100) + + ptr.transform.origin = to + + var mask = 1 + if player.sel.name.find("path") != -1: mask = 3 + + var result = space.intersect_ray(from, to, [], mask) + if result.size() > 0: + ptr.visible = true + + colliding = true + normal = result.normal; + collision_point = result.position + + var node = result.collider.get_parent() + colliding_node = node + colliding_group = node.get_groups() + + if ("voxels" in colliding_group or "path" in colliding_group): + var cpos = result.position - normal * (0.5 / 2) + var cursor_position = (cpos / 0.5).floor() * 0.5 + cursor_position += Vector3.ONE * (0.5 / 2) + normal * (0.5 / 2) + collision_point = cursor_position + + if ("attach" in colliding_group): + collision_point = node.global_transform.origin; + normal = (node.global_transform.basis.get_rotation_quat() * Vector3.UP).normalized(); + + ptr.transform.basis = Basis(Utils.quat_look(normal, Vector3.UP)) + ptr.transform.origin = collision_point + else: + colliding = false + colliding_group = [] + ptr.visible = false + + var placed = "" + match player.sel.type: + "map_tools": + match player.sel.name: + "start path": + place("path", funcref(self, "_inst_path_start")) + delete("path") + "path": + place("path", funcref(self, "_inst_path")) + delete("path") + "end path": + place("path", funcref(self, "_inst_path_end")) + delete("path") + "attach": + place("voxels", funcref(self, "_inst_attach")) + delete("attach") + "voxels": + pass + "turrets": + placed = place("attach", funcref(self, "_inst_turret")) + if placed == "ok" and !player.in_editor: + resources.sub(load_turrets.info[player.sel.name].cost) + delete("turret") + + if placed == "ok": + player.sel.name = "" + player.sel.type = "" + if ptr.has_node("preview"): + ptr.get_node("preview").queue_free() + player.refresh_gui() + else: + select() diff --git a/scripts/resources.gd b/scripts/resources.gd new file mode 100644 index 0000000..1fc50c5 --- /dev/null +++ b/scripts/resources.gd @@ -0,0 +1,27 @@ +extends Node + +var T : float = 500 +var k : float = 0 +var a : float = 0 +var d : float = 0 +var s : float = 0 + +func get_names(): return "Tkads" + +func dict_to_str (cost): + var st = "" + for n in cost.keys(): + st += str(cost[n]) + n + return st + +func add (cost): + for n in cost.keys(): self[n] += cost[n] + +func sub (cost): + for n in cost.keys(): self[n] -= cost[n] + +func greater_than (cost): + for n in cost.keys(): + if self[n] < cost[n]: + return false + return true diff --git a/scripts/saveload.gd b/scripts/saveload.gd new file mode 100644 index 0000000..9f7a203 --- /dev/null +++ b/scripts/saveload.gd @@ -0,0 +1,26 @@ +extends Node + + +func load_parse_json (path): + var data_file = File.new() + if data_file.open(path, File.READ) != OK: + return + var data_text = data_file.get_as_text() + data_file.close() + var data_parse = JSON.parse(data_text) + if data_parse.error != OK: + return + var data = data_parse.result + return data + +func parse_dir (path : String, extension : String = ""): + var files = [] + var dir = Directory.new() + dir.open(path) + dir.list_dir_begin(true) + var file = dir.get_next() + while file != "": + if file.ends_with(extension): + files.append(file) + file = dir.get_next() + return files -- cgit v1.2.3-54-g00ecf