Skip to content

Commit

Permalink
Stabilized several dialog systems as well as interaction::do_interact
Browse files Browse the repository at this point in the history
  • Loading branch information
QueenOfSquiggles committed Jan 18, 2024
1 parent 1272558 commit 5e7fd55
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 41 deletions.
38 changes: 19 additions & 19 deletions squiggles_core.gdextension
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,39 @@ reloadable = true

[libraries]
;; Debug Binaries
linux.debug.x86_64 = "res://addons/squiggles_core/target/debug/libsquiggles_core.so"
windows.debug.x86_64 = "res://addons/squiggles_core/target/debug/squiggles_core.dll"
macos.debug = "res://addons/squiggles_core/target/debug/libsquiggles_core.dylib"
macos.debug.arm64 = "res://addons/squiggles_core/target/debug/libsquiggles_core.dylib"
linux.debug.x86_64 = "res://addons/squiggles-core/target/debug/libsquiggles_core.so"
windows.debug.x86_64 = "res://addons/squiggles-core/target/debug/squiggles_core.dll"
macos.debug = "res://addons/squiggles-core/target/debug/libsquiggles_core.dylib"
macos.debug.arm64 = "res://addons/squiggles-core/target/debug/libsquiggles_core.dylib"

;; Release Binaries
linux.release.x86_64 = "res://addons/squiggles_core/target/release/libsquiggles_core.so"
windows.release.x86_64 = "res://addons/squiggles_core/target/release/squiggles_core.dll"
macos.release = "res://addons/squiggles_core/target/release/libsquiggles_core.dylib"
macos.release.arm64 = "res://addons/squiggles_core/target/release/libsquiggles_core.dylib"
linux.release.x86_64 = "res://addons/squiggles-core/target/release/libsquiggles_core.so"
windows.release.x86_64 = "res://addons/squiggles-core/target/release/squiggles_core.dll"
macos.release = "res://addons/squiggles-core/target/release/libsquiggles_core.dylib"
macos.release.arm64 = "res://addons/squiggles-core/target/release/libsquiggles_core.dylib"


[icons]

;; camera.rs

CameraBrain3D = "res://addons/squiggles_core/assets/icons/camera_brain.svg"
VirtualCamera3D = "res://addons/squiggles_core/assets/icons/virtual_camera.svg"
CameraBrain3D = "res://addons/squiggles-core/assets/icons/camera_brain.svg"
VirtualCamera3D = "res://addons/squiggles-core/assets/icons/virtual_camera.svg"

;; interaction.rs

InteractRaycast3D = "res://addons/squiggles_core/assets/icons/interaction_raycast3d.svg"
InteractArea3D = "res://addons/squiggles_core/assets/icons/interaction_area3d.svg"
InteractionObjectArea3D = "res://addons/squiggles_core/assets/icons/interact_object_area3d.svg"
InteractionObjectStaticBody3D = "res://addons/squiggles_core/assets/icons/interact_object_static3d.svg"
InteractionObjectCharacterBody3D = "res://addons/squiggles_core/assets/icons/interact_object_character3d.svg"
InteractRaycast3D = "res://addons/squiggles-core/assets/icons/interaction_raycast3d.svg"
InteractArea3D = "res://addons/squiggles-core/assets/icons/interaction_area3d.svg"
InteractionObjectArea3D = "res://addons/squiggles-core/assets/icons/interact_object_area3d.svg"
InteractionObjectStaticBody3D = "res://addons/squiggles-core/assets/icons/interact_object_static3d.svg"
InteractionObjectCharacterBody3D = "res://addons/squiggles-core/assets/icons/interact_object_character3d.svg"

;; state_machine.rs

FiniteStateMachine = "res://addons/squiggles_core/assets/icons/fsm.svg"
FiniteState = "res://addons/squiggles_core/assets/icons/fsm_state.svg"
FiniteSubStateMachine = "res://addons/squiggles_core/assets/icons/fsm_sub_state.svg"
FiniteStateMachine = "res://addons/squiggles-core/assets/icons/fsm.svg"
FiniteState = "res://addons/squiggles-core/assets/icons/fsm_state.svg"
FiniteSubStateMachine = "res://addons/squiggles-core/assets/icons/fsm_sub_state.svg"

;; utility_nodes/gui_interact.rs

GuiInteract = "res://addons/squiggles_core/assets/icons/gui_interact.svg"
GuiInteract = "res://addons/squiggles-core/assets/icons/gui_interact.svg"
22 changes: 18 additions & 4 deletions src/scene/dialog/core_dialog.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::VecDeque;

use godot::{
engine::{Engine, Json},
engine::{self, Engine, Json},
prelude::*,
};

Expand Down Expand Up @@ -154,8 +154,15 @@ impl CoreDialog {
StringName::from(DialogEvents::SIGNAL_TRACK_SIGNAL),
&[
name.to_variant(),
Array::from_iter(args.iter().map(|s| Json::parse_string(s.to_godot())))
.to_variant(),
Array::from_iter(args.iter().map(|s| {
let mut json = Json::new_gd();
if json.parse(s.to_godot()) != engine::global::Error::OK {
// handle invalid types as a simple string value
return s.to_variant();
}
json.get_data()
}))
.to_variant(),
],
);
}
Expand All @@ -169,8 +176,12 @@ impl CoreDialog {
pub fn blackboard_action(&mut self, action: GString) {
self.blackboard.parse_action(action.to_string());
let Some((event_name, event_arg)) = self.blackboard.get_event() else {
if let Some(gui) = &mut self.gui {
gui.bind_mut().mark_event_handled();
}
return;
};
godot_print!("Processing event: {}({:#?})", event_name, event_arg);
match event_name.as_str() {
// TODO handle events with pub const value
"end" => {
Expand All @@ -183,7 +194,7 @@ impl CoreDialog {
let Entry::Number(index) = event_arg else {
return;
};
let index = (index.floor() - 1f32) as usize;
let index = (index.floor()) as usize;
let Some(gui) = &mut self.gui else {
return;
};
Expand All @@ -197,6 +208,9 @@ impl CoreDialog {
_ => godot_error!("Unhandled internal event! event: \"{}\"", event_name),
}
self.blackboard.mark_event_handled();
if let Some(gui) = &mut self.gui {
gui.bind_mut().mark_event_handled();
}
}

#[func]
Expand Down
19 changes: 11 additions & 8 deletions src/scene/dialog/dialog_blackboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,10 @@ impl Default for Blackboard {
impl Blackboard {
/// Parses the action string
pub fn parse_action(&mut self, code: String) {
// godot_print!("Running action(s): {}", code);
if code.is_empty() {
return;
}
for action in code.split(';') {
// godot_print!("Running sub-action: {}", action);
let mut parts = VecDeque::from_iter(action.trim().split(' ').map(|dirty| dirty.trim()));
let command = parts.pop_front().unwrap_or("");
let mut callback: Option<_> = None;
Expand Down Expand Up @@ -114,12 +115,9 @@ impl Blackboard {
}

pub fn parse_query(&mut self, code: String) -> bool {
// godot_print!("Running quer(y/ies): {}", code);
for query in code.split("and") {
let mut chunk_val = false;
for options in query.split("or") {
// godot_print!("Running sub-query: {}", options);

let parts = Vec::from_iter(options.split_whitespace());
if parts.len() != 3 {
if query.contains('\"') {
Expand All @@ -141,7 +139,6 @@ impl Blackboard {
fn parse_query_value(&mut self, query: (&str, &str, &str)) -> bool {
let arg1 = self.get_numeric_value(query.0);
let arg2 = self.get_numeric_value(query.2);
// godot_print!("Running internal comparison: {} {} {}", arg1, query.1, arg2);
match query.1 {
"==" => arg1 == arg2,
"!=" => arg1 != arg2,
Expand All @@ -168,7 +165,6 @@ impl Blackboard {
return;
};
self.entries.insert(key.to_string(), entry.clone());
// godot_print!("Set value: {} = {}. Enum value: {}", key, value, entry);
}

pub fn unset(&mut self, key: &str) {
Expand Down Expand Up @@ -387,6 +383,14 @@ impl Blackboard {
Some(self.entries.get(key)?.clone())
}

pub fn has_entry(&self, key: &str) -> bool {
self.entries.contains_key(key)
}

pub fn has_event(&self) -> bool {
self.has_entry(Self::EVENT_KEY)
}

pub fn debug_print(&self) {
let mappings: Vec<String> = self
.entries
Expand All @@ -399,7 +403,6 @@ impl Blackboard {
buffer += "\n";
}
buffer += " }";
// godot_print!("{}", buffer);
}
}

Expand Down
45 changes: 37 additions & 8 deletions src/scene/dialog/dialog_gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ use super::{
dialog_track::{ChoiceOptionEntry, Line},
};

/// The current state of the Dialog GUI,
#[derive(Debug, Default, PartialEq)]
enum DialogState {
/// Active meaning we are actively processing nodes and pushing data to be visible
#[default]
Active,
/// Pending meaning we are currently waiting on an external process and don't want to create a degenerate reference to CoreDialog by forcing a push
Pending,
}

#[derive(GodotClass)]
#[class(init, base=CanvasLayer)]
pub struct DialogGUI {
Expand All @@ -30,6 +40,7 @@ pub struct DialogGUI {
dialog_text: Option<Gd<RichTextLabel>>,
options_root: Option<Gd<Control>>,
current_index: usize,
state: DialogState,
#[base]
base: Base<CanvasLayer>,
}
Expand All @@ -44,7 +55,7 @@ impl ICanvasLayer for DialogGUI {
self.create_structure();
if let Some(line) = self.get_next_text_line() {
self.load_line(&line);
} else {
} else if self.state != DialogState::Pending {
godot_warn!(
"No text nodes found in dialog track on load. Something must have gone wrong?"
);
Expand Down Expand Up @@ -73,6 +84,13 @@ impl ICanvasLayer for DialogGUI {
self.load_next_line();
}
}
fn process(&mut self, _delta: f64) {
if self.state != DialogState::Pending {
return;
}
// downtime should only be for 2-3 frames MAX! so this aaggresive polling ***shouldn't*** have a big effect on the performance??
self.load_next_line();
}

fn exit_tree(&mut self) {
//pass
Expand Down Expand Up @@ -211,17 +229,18 @@ impl DialogGUI {
root.add_child(button.clone().upcast());
button.set_text(self.parse_text(&option.text).into());
let action = option.action.clone();
if !action.is_empty() {
self.state = DialogState::Pending;
}
button
.connect_ex(
"pressed".into(),
Callable::from_fn(
format!("choice_button_{} ({})", index, option.text),
move |_| {
if !action.is_empty() {
CoreDialog::singleton()
.bind_mut()
.blackboard_action(action.clone().into());
}
CoreDialog::singleton()
.bind_mut()
.blackboard_action(action.clone().into());
let Some(gui) = &mut CoreDialog::singleton().bind().gui.clone() else {
godot_error!(
"Failed to find instance of the CoreDialog's DialogGUI"
Expand Down Expand Up @@ -341,9 +360,11 @@ impl DialogGUI {
options,
} => Some(line),
Line::Action { action } => {
self.state = DialogState::Pending;
godot_print!("Pending processing for action {}", action);
CoreDialog::singleton()
.call_deferred("blackboard_action".into(), &[action.to_variant()]);
continue;
return None; // force break to allow processing events
}
Line::Signal { name, args } => {
CoreDialog::singleton()
Expand Down Expand Up @@ -417,12 +438,15 @@ impl DialogGUI {
}

fn load_next_line(&mut self) {
if self.state == DialogState::Pending {
return;
}

let Some(margin) = self.base().get_child(0) else {
godot_error!("Failed to access child of DialogGUI!");
return;
};
let margin = margin.cast::<Control>();

if let Some(line) = self.get_next_text_line() {
self.load_line(&line);
} else {
Expand All @@ -444,6 +468,11 @@ impl DialogGUI {
}
}

pub fn mark_event_handled(&mut self) {
godot_print!("Action marked as handled");
self.state = DialogState::Active;
}

fn parse_text(&self, in_text: &String) -> String {
let trans = self.base().tr(in_text.into()).into();
CoreDialog::singleton().bind().blackboard_parse(trans)
Expand Down
6 changes: 4 additions & 2 deletions src/scene/interaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,10 @@ impl InteractRaycast3D {

#[func]
fn do_interact(&mut self) {
if let Some(mut target) = self.target.clone() {
target.call_deferred(StringName::from(METHOD_INTERACT), &[]);
if let Some(target) = self.target.as_mut() {
if target.is_instance_valid() {
target.call_deferred(StringName::from(METHOD_INTERACT), &[]);
}
}
}
}
Expand Down

0 comments on commit 5e7fd55

Please sign in to comment.