This commit is contained in:
JeroenV26 2025-11-03 17:11:16 +01:00
commit 88e87cb54a
12 changed files with 311 additions and 9 deletions

View file

@ -1,4 +1,4 @@
[gd_resource type="ClueDB" load_steps=4 format=3 uid="uid://dlf8dxiter8b8"]
[gd_resource type="ClueDB" load_steps=23 format=3 uid="uid://dlf8dxiter8b8"]
[ext_resource type="Texture2D" uid="uid://p7uaxluyc0tk" path="res://assets/photo-images/Knife.jpg" id="1_q5eka"]
@ -9,5 +9,122 @@ image = ExtResource("1_q5eka")
[sub_resource type="ClueData" id="ClueData_q5eka"]
id = 1
[sub_resource type="ClueData" id="ClueData_du6rq"]
id = 2
[sub_resource type="ClueData" id="ClueData_y8781"]
id = 3
[sub_resource type="ClueData" id="ClueData_mhl4k"]
id = 4
[sub_resource type="ClueData" id="ClueData_k2o5n"]
id = 5
[sub_resource type="ClueData" id="ClueData_bgtdi"]
id = 6
[sub_resource type="ClueData" id="ClueData_u53f6"]
id = 7
[sub_resource type="ClueData" id="ClueData_e5lqe"]
id = 8
[sub_resource type="ClueData" id="ClueData_doypg"]
id = 9
[sub_resource type="ClueData" id="ClueData_0lck8"]
id = 10
[sub_resource type="ClueData" id="ClueData_fqtcy"]
popup_text = "Victim: Flora Lamb
Age: 35
Profession: Detective
Blood Type: A+
Shoe Size: 39
Hair Color: Black"
id = 11
[sub_resource type="ClueData" id="ClueData_qpqg2"]
popup_text = "Name: Velma Graves
Age: 37
Profession: Detective
Blood Type: AB+
Shoe Size: 43
Hair Color: Brown"
id = 12
[sub_resource type="ClueData" id="ClueData_k6v75"]
popup_text = "Name: Floyd Hunt
Age: 34
Profession: Detective
Blood Type: B+
Shoe Size: 42
Hair Color: Brown"
id = 13
[sub_resource type="ClueData" id="ClueData_037ed"]
popup_text = "Name: Richard O'Brien
Age: 40
Profession: Cleaner
Blood Type: 0
Shoe Size: 39
Hair Color: Brown"
id = 14
[sub_resource type="ClueData" id="ClueData_ucrra"]
popup_text = "Name: Gordon Chevield
Age: 36
Profession: Detective
Blood Type: AB-
Shoe Size: 47
Hair Color: Brown"
id = 15
[sub_resource type="ClueData" id="ClueData_lrkph"]
popup_text = "Name: Sadie Wood
Age: 44
Profession: Maintenance Technician
Blood Type: A+
Shoe Size: 41
Hair Color: Blond"
id = 16
[sub_resource type="ClueData" id="ClueData_mi3iw"]
popup_text = "Name: Ursula Glass
Age: 47
Profession: Detective
Blood Type: B-
Shoe Size: 44
Hair Color: Brown"
id = 17
[sub_resource type="ClueData" id="ClueData_iamej"]
popup_text = "Name: Barney Ortiz
Age: 27
Profession: Detective
Blood Type: AB+
Shoe Size: 42
Hair Color: Black"
id = 18
[sub_resource type="ClueData" id="ClueData_lf4cx"]
popup_text = "Amos Shwartz
Age: 44
Profession: Detective
Blood type: A+
Shoe size: 43
Hair Color: Blond"
id = 19
[sub_resource type="ClueData" id="ClueData_tdk3v"]
popup_text = "Name: Grace Ross
Age: 29
Profession: Detective
Blood Type: AB+
Shoe Size: 44
Hair Color: Black"
id = 20
[resource]
clues = [SubResource("ClueData_kxjsf"), SubResource("ClueData_q5eka")]
clues = [SubResource("ClueData_kxjsf"), SubResource("ClueData_q5eka"), SubResource("ClueData_du6rq"), SubResource("ClueData_y8781"), SubResource("ClueData_mhl4k"), SubResource("ClueData_k2o5n"), SubResource("ClueData_bgtdi"), SubResource("ClueData_u53f6"), SubResource("ClueData_e5lqe"), SubResource("ClueData_doypg"), SubResource("ClueData_0lck8"), SubResource("ClueData_fqtcy"), SubResource("ClueData_qpqg2"), SubResource("ClueData_k6v75"), SubResource("ClueData_037ed"), SubResource("ClueData_ucrra"), SubResource("ClueData_lrkph"), SubResource("ClueData_mi3iw"), SubResource("ClueData_iamej"), SubResource("ClueData_lf4cx"), SubResource("ClueData_tdk3v")]

View file

@ -20,3 +20,16 @@ texture = SubResource("ImageTexture_usqe2")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, 73)
shape = SubResource("RectangleShape2D_usqe2")
[node name="PanelContainer" type="PanelContainer" parent="."]
z_index = 1
offset_left = -252.0
offset_top = -12.0
offset_right = -88.0
offset_bottom = 157.0
[node name="HoverLabel" type="RichTextLabel" parent="PanelContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "PLACEHOLDER TOOLTIP"
fit_content = true

View file

@ -0,0 +1,62 @@
[gd_scene load_steps=4 format=3 uid="uid://kk4ecpjc4puc"]
[ext_resource type="PackedScene" uid="uid://btcmnw6q6g0h0" path="res://objects/pinned_photo.tscn" id="1_iugs1"]
[sub_resource type="GDScript" id="GDScript_lm1ej"]
script/source = "extends Node
func set_conclusion(method : int, motive : int, murderer : int) -> void:
%Method.clue = method
%Motive.clue = motive
%Murderer.clue = murderer
func _ready() -> void:
%Method.input_pickable = false
%Motive.input_pickable = false
%Murderer.input_pickable = false
"
[sub_resource type="LabelSettings" id="LabelSettings_iugs1"]
font_size = 40
[node name="ResultsUI" type="Node"]
script = SubResource("GDScript_lm1ej")
[node name="YourConclusionLabel" type="Label" parent="."]
offset_left = 230.0
offset_top = 147.0
offset_right = 543.0
offset_bottom = 202.0
text = "Your Conclusion"
label_settings = SubResource("LabelSettings_iugs1")
[node name="Method" parent="." instance=ExtResource("1_iugs1")]
unique_name_in_owner = true
position = Vector2(559, 313)
[node name="Motive" parent="." instance=ExtResource("1_iugs1")]
unique_name_in_owner = true
position = Vector2(936, 379)
[node name="Murderer" parent="." instance=ExtResource("1_iugs1")]
unique_name_in_owner = true
position = Vector2(1316, 306)
[node name="Label2" type="Label" parent="."]
offset_left = 347.0
offset_top = 599.0
offset_right = 660.0
offset_bottom = 654.0
text = "The Truth"
label_settings = SubResource("LabelSettings_iugs1")
[node name="MethodActual" parent="." instance=ExtResource("1_iugs1")]
position = Vector2(559, 734)
clue = 0
[node name="MotiveActual" parent="." instance=ExtResource("1_iugs1")]
position = Vector2(933, 720)
clue = 8
[node name="MurdererActual" parent="." instance=ExtResource("1_iugs1")]
position = Vector2(1316, 727)

View file

@ -1,10 +1,23 @@
[gd_scene load_steps=15 format=3 uid="uid://o3ri154wpbrx"]
[gd_scene load_steps=17 format=3 uid="uid://o3ri154wpbrx"]
[ext_resource type="PackedScene" uid="uid://btcmnw6q6g0h0" path="res://objects/pinned_photo.tscn" id="1_7cefc"]
[ext_resource type="PackedScene" uid="uid://kk4ecpjc4puc" path="res://scenes/results_ui.tscn" id="1_thvsl"]
[ext_resource type="PackedScene" uid="uid://qmb60kjx6yoe" path="res://objects/victim_file.tscn" id="2_vo7lu"]
[ext_resource type="PackedScene" uid="uid://drcl138k0gym0" path="res://objects/witness_report.tscn" id="3_wjago"]
[ext_resource type="PackedScene" uid="uid://cjyr1b0fxfofx" path="res://objects/case_file.tscn" id="4_cnvne"]
[sub_resource type="GDScript" id="GDScript_thvsl"]
script/source = "extends Node2D
@export var conclusion_screen : PackedScene = null
func notify_conclusion_sent(method : int, motive : int, murderer : int) -> void:
var instance := conclusion_screen.instantiate()
instance.set_conclusion(method, motive, murderer)
get_parent().add_child(instance)
self.queue_free()
"
[sub_resource type="QuadMesh" id="QuadMesh_usqe2"]
[sub_resource type="Gradient" id="Gradient_usqe2"]
@ -33,7 +46,7 @@ func _pressed() -> void:
ServerNode.get_singleton().send_conclusion(%WeaponSlot.get_current_clue(), %MotiveSlot.get_current_clue(), %MurdererSlot.get_current_clue())
else:
print(\"Conclusion: \", %WeaponSlot.get_current_clue(), \", \", %MotiveSlot.get_current_clue(), \", \", %MurdererSlot.get_current_clue())
owner.notify_conclusion_sent(%WeaponSlot.get_current_clue(), %MotiveSlot.get_current_clue(), %MurdererSlot.get_current_clue())
func update_can_send():
self.disabled = not (%WeaponSlot.is_filled() and %MotiveSlot.is_filled() and %MurdererSlot.is_filled())
@ -53,7 +66,9 @@ colors = PackedColorArray(0, 0, 0, 1)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_c1nar"]
gradient = SubResource("Gradient_thvsl")
[node name="FlatscreenRoot" type="Node2D"]
[node name="Workspace" type="Node2D"]
script = SubResource("GDScript_thvsl")
conclusion_screen = ExtResource("1_thvsl")
[node name="Camera2D" type="Camera2D" parent="."]
anchor_mode = 0
@ -131,10 +146,47 @@ texture = SubResource("GradientTexture1D_c1nar")
[node name="PhotosParent" type="Node2D" parent="."]
[node name="PinnedPhoto" parent="PhotosParent" instance=ExtResource("1_7cefc")]
position = Vector2(479, 904)
position = Vector2(730, 395)
clue = 11
[node name="PinnedPhoto2" parent="PhotosParent" instance=ExtResource("1_7cefc")]
position = Vector2(111, 900)
clue = 12
[node name="PinnedPhoto3" parent="PhotosParent" instance=ExtResource("1_7cefc")]
position = Vector2(288, 900)
clue = 13
[node name="PinnedPhoto4" parent="PhotosParent" instance=ExtResource("1_7cefc")]
position = Vector2(467, 903)
clue = 14
[node name="PinnedPhoto5" parent="PhotosParent" instance=ExtResource("1_7cefc")]
position = Vector2(640, 903)
clue = 15
[node name="PinnedPhoto6" parent="PhotosParent" instance=ExtResource("1_7cefc")]
position = Vector2(816, 904)
clue = 16
[node name="PinnedPhoto7" parent="PhotosParent" instance=ExtResource("1_7cefc")]
position = Vector2(991, 909)
clue = 18
[node name="PinnedPhoto8" parent="PhotosParent" instance=ExtResource("1_7cefc")]
position = Vector2(1164, 911)
clue = 19
[node name="PinnedPhoto9" parent="PhotosParent" instance=ExtResource("1_7cefc")]
position = Vector2(1334, 914)
clue = 19
[node name="PinnedPhoto10" parent="PhotosParent" instance=ExtResource("1_7cefc")]
position = Vector2(1511, 912)
clue = 20
[node name="PhotoInbox" type="PhotoInbox" parent="PhotosParent"]
position = Vector2(1679, 900)
position = Vector2(1717, 889)
photo_scene = ExtResource("1_7cefc")
[node name="VictimFile" parent="." node_paths=PackedStringArray("open_position") instance=ExtResource("2_vo7lu")]

View file

@ -3,6 +3,7 @@
#include "you_done_it/ydi_client.h"
void ClueData::_bind_methods() {
BIND_HPROPERTY(Variant::STRING, popup_text, PROPERTY_HINT_MULTILINE_TEXT);
BIND_HPROPERTY(Variant::INT, id, PROPERTY_HINT_ENUM, NetworkData::ClueID_hint());
BIND_HPROPERTY(Variant::OBJECT, image, PROPERTY_HINT_RESOURCE_TYPE, "Texture2D");
}
@ -45,3 +46,11 @@ void ClueData::set_image(Ref<Texture2D> image) {
Ref<Texture2D> ClueData::get_image() const {
return this->image;
}
void ClueData::set_popup_text(String value) {
this->popup_text = value;
}
String ClueData::get_popup_text() const {
return this->popup_text;
}

View file

@ -18,9 +18,12 @@ public:
bool get_revealed() const;
void set_image(Ref<Texture2D> image);
Ref<Texture2D> get_image() const;
void set_popup_text(String value);
String get_popup_text() const;
private:
NetworkData::ClueID id{ NetworkData::CLUE_MAX };
bool revealed{ false };
Ref<Texture2D> image{};
String popup_text{};
};

View file

@ -3,8 +3,10 @@
#include "core/input/input_event.h"
#include "macros.h"
#include "scene/2d/mesh_instance_2d.h"
#include "scene/gui/rich_text_label.h"
#include "you_done_it/clue_db.h"
#include "you_done_it/conclusion_field.h"
#include "you_done_it/ydi_networking.h"
void PinnedPhoto::_bind_methods() {
BIND_PROPERTY(Variant::BOOL, can_drop);
@ -14,11 +16,18 @@ void PinnedPhoto::_bind_methods() {
void PinnedPhoto::enter_tree() {
connect("input_event", callable_mp(this, &self_type::on_input_event));
connect("child_entered_tree", callable_mp(this, &self_type::on_child_entered_tree));
if ((this->popup_label = cast_to<RichTextLabel>(get_node(NodePath("%HoverLabel"))))) {
set_clue(get_clue());
}
}
void PinnedPhoto::on_child_entered_tree(Node *node) {
if (MeshInstance2D * meshinst{ cast_to<MeshInstance2D>(node) }) {
this->photo_mesh = meshinst;
set_clue(get_clue()); // force reset clue to update image
} else if (PanelContainer * container{ cast_to<PanelContainer>(node) }) {
this->popup_container = container;
container->set_visible(false);
}
}
@ -37,6 +46,7 @@ void PinnedPhoto::on_input_event(Viewport *viewport, Ref<InputEvent> event, int
this->conclusion_field->notify_photo_picked(this);
this->conclusion_field = nullptr;
}
this->popup_container->set_visible(true);
}
}
@ -50,10 +60,12 @@ void PinnedPhoto::unhandled_input(Ref<InputEvent> const &event) {
get_viewport()->set_input_as_handled();
set_global_position(this->conclusion_field->get_global_position());
set_global_rotation(this->conclusion_field->get_global_rotation());
this->popup_container->set_visible(false);
} else if (this->can_drop) {
this->is_held = false;
get_viewport()->set_input_as_handled();
set_global_rotation(0.0);
this->popup_container->set_visible(false);
}
}
}
@ -95,12 +107,18 @@ bool PinnedPhoto::get_can_drop() const {
void PinnedPhoto::set_clue(NetworkData::ClueID id) {
this->clue = id;
if (photo_mesh) {
if (this->clue == NetworkData::CLUE_MAX) {
return;
}
if (this->photo_mesh) {
Ref<Texture2D> texture{ ClueDB::get_singleton()->get_clue(id)->get_image() };
if (texture.is_valid()) {
photo_mesh->set_texture(texture);
}
}
if (this->popup_label) {
this->popup_label->set_text(ClueDB::get_singleton()->get_clue(id)->get_popup_text());
}
}
NetworkData::ClueID PinnedPhoto::get_clue() const {

View file

@ -3,6 +3,8 @@
#include "core/input/input_event.h"
#include "scene/2d/mesh_instance_2d.h"
#include "scene/2d/physics/animatable_body_2d.h"
#include "scene/gui/panel_container.h"
#include "scene/gui/rich_text_label.h"
#include "scene/main/viewport.h"
#include "you_done_it/ydi_networking.h"
class ConclusionField;
@ -34,4 +36,6 @@ private:
bool is_held{ false };
ConclusionField *conclusion_field{};
Vector<ConclusionField *> near_fields{};
RichTextLabel *popup_label{ nullptr };
PanelContainer *popup_container{ nullptr };
};

View file

@ -1,5 +1,6 @@
#include "ydi_client.h"
#include "core/string/print_string.h"
#include "core/templates/fixed_vector.h"
#include "you_done_it/ydi_networking.h"
#include "zmq.hpp"
#include "zmq_addon.hpp"
@ -14,12 +15,12 @@ struct Connection {
std::optional<zmq::context_t> context{ std::nullopt };
std::optional<zmq::socket_t> socket{ std::nullopt };
std::recursive_mutex mtx;
std::optional<FixedVector<NetworkData::ClueID, 3>> conclusion{ std::nullopt };
std::atomic<NetworkData::ConnectionStatus> status;
std::atomic<bool> stop_threads{ false };
};
std::optional<Connection> connection{ std::nullopt };
std::optional<std::thread> receive_thread{ std::nullopt };
void handle_ok(zmq::multipart_t const &message) {

View file

@ -7,6 +7,9 @@ namespace ydi::client {
void connect(String const &url);
void disconnect();
NetworkData::ConnectionStatus status();
namespace receive {
Vector<NetworkData::ClueID> &conclusion();
}
namespace send {
void reveal_clue(NetworkData::ClueID id);
} //namespace send

View file

@ -16,6 +16,16 @@ void NetworkData::_bind_methods() {
BIND_ENUM_CONSTANT(CLUE_FINGERPRINT);
BIND_ENUM_CONSTANT(CLUE_HAIR);
BIND_ENUM_CONSTANT(CLUE_MAX);
BIND_ENUM_CONSTANT(CLUE_FLORA_LAMB);
BIND_ENUM_CONSTANT(CLUE_VELMA_GRAVES);
BIND_ENUM_CONSTANT(CLUE_FLOYD_HUNT);
BIND_ENUM_CONSTANT(CLUE_RICHARD_OBRIEN);
BIND_ENUM_CONSTANT(CLUE_GORDON_CHEVIELD);
BIND_ENUM_CONSTANT(CLUE_SADIE_WOOD);
BIND_ENUM_CONSTANT(CLUE_URSULA_GLASS);
BIND_ENUM_CONSTANT(CLUE_BARNEY_ORTIZ);
BIND_ENUM_CONSTANT(CLUE_AMOS_SHWARTZ);
BIND_ENUM_CONSTANT(CLUE_GRACE_ROSS);
BIND_ENUM_CONSTANT(CONNECTION_DISCONNECTED);
BIND_ENUM_CONSTANT(CONNECTION_CONNECTED);

View file

@ -39,6 +39,16 @@ public:
CLUE_SIGNED_DOCUMENT,
CLUE_FINGERPRINT,
CLUE_HAIR,
CLUE_FLORA_LAMB,
CLUE_VELMA_GRAVES,
CLUE_FLOYD_HUNT,
CLUE_RICHARD_OBRIEN,
CLUE_GORDON_CHEVIELD,
CLUE_SADIE_WOOD,
CLUE_URSULA_GLASS,
CLUE_BARNEY_ORTIZ,
CLUE_AMOS_SHWARTZ,
CLUE_GRACE_ROSS,
CLUE_MAX);
GDENUM(ConnectionStatus,