/*************************************************************************/ /* visual_script_yield_nodes.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "visual_script_yield_nodes.h" #include "core/os/os.h" #include "scene/main/node.h" #include "scene/main/scene_tree.h" #include "visual_script_nodes.h" ////////////////////////////////////////// ////////////////YIELD/////////// ////////////////////////////////////////// int VisualScriptYield::get_output_sequence_port_count() const { return 1; } bool VisualScriptYield::has_input_sequence_port() const { return true; } int VisualScriptYield::get_input_value_port_count() const { return 0; } int VisualScriptYield::get_output_value_port_count() const { return 0; } String VisualScriptYield::get_output_sequence_port_text(int p_port) const { return String(); } PropertyInfo VisualScriptYield::get_input_value_port_info(int p_idx) const { return PropertyInfo(); } PropertyInfo VisualScriptYield::get_output_value_port_info(int p_idx) const { return PropertyInfo(); } String VisualScriptYield::get_caption() const { return yield_mode == YIELD_RETURN ? RTR("Yield") : RTR("Wait"); } String VisualScriptYield::get_text() const { switch (yield_mode) { case YIELD_RETURN: return ""; break; case YIELD_FRAME: return RTR("Next Frame"); break; case YIELD_PHYSICS_FRAME: return RTR("Next Physics Frame"); break; case YIELD_WAIT: return vformat(RTR("%s sec(s)"), rtos(wait_time)); break; } return String(); } class VisualScriptNodeInstanceYield : public VisualScriptNodeInstance { public: VisualScriptYield::YieldMode mode; float wait_time; virtual int get_working_memory_size() const { return 1; } //yield needs at least 1 //virtual bool is_output_port_unsequenced(int p_idx) const { return false; } //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) { if (p_start_mode == START_MODE_RESUME_YIELD) { return 0; //resuming yield } else { //yield SceneTree *tree = Object::cast_to(OS::get_singleton()->get_main_loop()); if (!tree) { r_error_str = "Main Loop is not SceneTree"; r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; return 0; } Ref state; state.instance(); int ret = STEP_YIELD_BIT; switch (mode) { case VisualScriptYield::YIELD_RETURN: ret = STEP_EXIT_FUNCTION_BIT; break; //return the yield case VisualScriptYield::YIELD_FRAME: state->connect_to_signal(tree, "idle_frame", Array()); break; case VisualScriptYield::YIELD_PHYSICS_FRAME: state->connect_to_signal(tree, "physics_frame", Array()); break; case VisualScriptYield::YIELD_WAIT: state->connect_to_signal(tree->create_timer(wait_time).ptr(), "timeout", Array()); break; } *p_working_mem = state; return ret; } } }; VisualScriptNodeInstance *VisualScriptYield::instance(VisualScriptInstance *p_instance) { VisualScriptNodeInstanceYield *instance = memnew(VisualScriptNodeInstanceYield); //instance->instance=p_instance; instance->mode = yield_mode; instance->wait_time = wait_time; return instance; } void VisualScriptYield::set_yield_mode(YieldMode p_mode) { if (yield_mode == p_mode) { return; } yield_mode = p_mode; ports_changed_notify(); _change_notify(); } VisualScriptYield::YieldMode VisualScriptYield::get_yield_mode() { return yield_mode; } void VisualScriptYield::set_wait_time(float p_time) { if (wait_time == p_time) { return; } wait_time = p_time; ports_changed_notify(); } float VisualScriptYield::get_wait_time() { return wait_time; } void VisualScriptYield::_validate_property(PropertyInfo &property) const { if (property.name == "wait_time") { if (yield_mode != YIELD_WAIT) { property.usage = 0; } } } void VisualScriptYield::_bind_methods() { ClassDB::bind_method(D_METHOD("set_yield_mode", "mode"), &VisualScriptYield::set_yield_mode); ClassDB::bind_method(D_METHOD("get_yield_mode"), &VisualScriptYield::get_yield_mode); ClassDB::bind_method(D_METHOD("set_wait_time", "sec"), &VisualScriptYield::set_wait_time); ClassDB::bind_method(D_METHOD("get_wait_time"), &VisualScriptYield::get_wait_time); ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Frame,Physics Frame,Time", PROPERTY_USAGE_NOEDITOR), "set_yield_mode", "get_yield_mode"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "wait_time"), "set_wait_time", "get_wait_time"); BIND_ENUM_CONSTANT(YIELD_FRAME); BIND_ENUM_CONSTANT(YIELD_PHYSICS_FRAME); BIND_ENUM_CONSTANT(YIELD_WAIT); } VisualScriptYield::VisualScriptYield() { yield_mode = YIELD_FRAME; wait_time = 1; } template static Ref create_yield_node(const String &p_name) { Ref node; node.instance(); node->set_yield_mode(MODE); return node; } /////////////////////////////////////////////////// ////////////////YIELD SIGNAL////////////////////// ////////////////////////////////////////////////// int VisualScriptYieldSignal::get_output_sequence_port_count() const { return 1; } bool VisualScriptYieldSignal::has_input_sequence_port() const { return true; } #ifdef TOOLS_ENABLED static Node *_find_script_node(Node *p_edited_scene, Node *p_current_node, const Ref