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

GH-384 Support script documentation #388

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions src/editor/plugins/orchestrator_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ void OrchestratorPlugin::_notification(int p_what)

// Register the plugin's icon for CreateScript Dialog
Ref<Theme> theme = ThemeDB::get_singleton()->get_default_theme();
if (theme.is_valid() && !theme->has_icon(_get_plugin_name(), "EditorIcons"))
theme->set_icon(_get_plugin_name(), "EditorIcons", _get_plugin_icon());
if (theme.is_valid() && !theme->has_icon(OScript::get_class_static(), "EditorIcons"))
theme->set_icon(OScript::get_class_static(), "EditorIcons", _get_plugin_icon());

_window_wrapper = memnew(OrchestratorWindowWrapper);
_window_wrapper->set_window_title(vformat("Orchestrator - Godot Engine"));
Expand Down
18 changes: 18 additions & 0 deletions src/orchestration/orchestration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,24 @@ void Orchestration::validate_and_build(BuildLog& p_log)
}
}

void Orchestration::set_brief_description(const String& p_description)
{
if (!_brief_description.match(p_description))
{
_brief_description = p_description;
_self->emit_changed();
}
}

void Orchestration::set_description(const String& p_description)
{
if (!_description.match(p_description))
{
_description = p_description;
_self->emit_changed();
}
}

void Orchestration::add_node(const Ref<OScriptGraph>& p_graph, const Ref<OScriptNode>& p_node)
{
ERR_FAIL_COND_MSG(_has_instances(), "Cannot add node, instances exist.");
Expand Down
18 changes: 18 additions & 0 deletions src/orchestration/orchestration.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ class Orchestration
HashMap<StringName, Ref<OScriptSignal>> _signals; //! Map of all user-defined signals
HashMap<StringName, Ref<OScriptGraph>> _graphs; //! Map of all defined graphs
Resource* _self; //! Reference to the outer resource type
String _brief_description; //! The brief description
String _description; //! The description

//~ Begin Serialization Interface
TypedArray<OScriptNode> _get_nodes_internal() const;
Expand Down Expand Up @@ -158,6 +160,22 @@ class Orchestration
/// @param p_log the build log
virtual void validate_and_build(BuildLog& p_log);

/// Get the brief description for the orchestration
/// @return the brief description
virtual String get_brief_description() const { return _brief_description; }

/// Set the brief description
/// @param p_description the brief description
virtual void set_brief_description(const String& p_description);

/// Get the description for the orchestration
/// @return the description
virtual String get_description() const { return _description; }

/// Set the description for the orchestration
/// @param p_description the description
virtual void set_description(const String& p_description);

//~ Begin Node Interface
void add_node(const Ref<OScriptGraph>& p_graph, const Ref<OScriptNode>& p_node);
void remove_node(int p_node_id);
Expand Down
24 changes: 24 additions & 0 deletions src/script/function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ void OScriptFunction::_get_property_list(List<PropertyInfo> *r_list) const
r_list->push_back(PropertyInfo(Variant::DICTIONARY, "method"));
r_list->push_back(PropertyInfo(Variant::BOOL, "user_defined"));
r_list->push_back(PropertyInfo(Variant::INT, "id"));
r_list->push_back(PropertyInfo(Variant::STRING, "description", PROPERTY_HINT_MULTILINE_TEXT));
}

bool OScriptFunction::_get(const StringName &p_name, Variant &r_value)
Expand All @@ -51,6 +52,11 @@ bool OScriptFunction::_get(const StringName &p_name, Variant &r_value)
r_value = _user_defined;
return true;
}
else if (p_name.match("description"))
{
r_value = _description;
return true;
}
return false;
}

Expand Down Expand Up @@ -78,6 +84,15 @@ bool OScriptFunction::_set(const StringName &p_name, const Variant &p_value)
_user_defined = p_value;
result = true;
}
else if (p_name.match("description"))
{
_description = p_value;

if (_orchestration)
_orchestration->get_self()->emit_changed();

result = true;
}

if (result)
emit_changed();
Expand Down Expand Up @@ -261,3 +276,12 @@ void OScriptFunction::set_has_return_value(bool p_has_return_value)
emit_changed();
}
}

void OScriptFunction::set_description(const String& p_description)
{
if (_description != p_description)
{
_description = p_description;
emit_changed();
}
}
9 changes: 9 additions & 0 deletions src/script/function.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class OScriptFunction : public Resource
bool _user_defined{ false }; //! Whether function is user-defined
int _owning_node_id{ -1 }; //! Owning node id
bool _returns_value{ false }; //! Whether the function returns a value
String _description; //! Function description

protected:
//~ Begin Wrapped Interface
Expand Down Expand Up @@ -170,6 +171,14 @@ class OScriptFunction : public Resource
/// Sets whether the function has a return value
/// @param p_has_return_value value true if the function has a return value, false otherwise
void set_has_return_value(bool p_has_return_value);

/// Get the description
/// @return the description
String get_description() const { return _description; }

/// Sets the description
/// @param p_description the description
void set_description(const String& p_description);
};

#endif // ORCHESTRATOR_SCRIPT_FUNCTION_H
4 changes: 2 additions & 2 deletions src/script/language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ String OScriptLanguage::_get_name() const

String OScriptLanguage::_get_type() const
{
return TYPE;
return OScript::get_class_static();
}

String OScriptLanguage::_get_extension() const
Expand All @@ -104,7 +104,7 @@ bool OScriptLanguage::_supports_builtin_mode() const

bool OScriptLanguage::_supports_documentation() const
{
return false;
return true;
}

bool OScriptLanguage::_is_using_templates()
Expand Down
20 changes: 20 additions & 0 deletions src/script/nodes/functions/function_terminator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ void OScriptNodeFunctionTerminator::_get_property_list(List<PropertyInfo>* r_lis
r_list->push_back(PropertyInfo(Variant::STRING, "function_id", PROPERTY_HINT_NONE, "", read_only_serialize));
r_list->push_back(PropertyInfo(Variant::STRING, "function_name", PROPERTY_HINT_NONE, "", read_only_editor));

r_list->push_back(PropertyInfo(Variant::STRING, "description", PROPERTY_HINT_MULTILINE_TEXT));

if (function.is_valid())
{
if (_supports_return_values())
Expand Down Expand Up @@ -113,6 +115,15 @@ bool OScriptNodeFunctionTerminator::_get(const StringName& p_name, Variant& r_va
return true;
}
}
else if (p_name.match("description"))
{
Ref<OScriptFunction> function = get_function();
if (function.is_valid())
{
r_value = function->get_description();
return true;
}
}
return false;
}

Expand Down Expand Up @@ -176,6 +187,15 @@ bool OScriptNodeFunctionTerminator::_set(const StringName& p_name, const Variant
return true;
}
}
else if (p_name.match("description"))
{
Ref<OScriptFunction> function = get_function();
if (function.is_valid())
{
function->set_description(p_value);
return true;
}
}
return false;
}

Expand Down
13 changes: 10 additions & 3 deletions src/script/script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "script/instances/script_instance.h"
#include "script/instances/script_instance_placeholder.h"
#include "script/nodes/script_nodes.h"
#include "script_docdata.h"

#include <godot_cpp/classes/engine.hpp>
#include <godot_cpp/core/mutex_lock.hpp>
Expand Down Expand Up @@ -74,6 +75,14 @@ void OScript::_bind_methods()
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "graphs", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_graphs",
"_get_graphs");

ClassDB::bind_method(D_METHOD("_set_brief_description", "description"), &OScript::_set_brief_description);
ClassDB::bind_method(D_METHOD("_get_brief_description"), &OScript::_get_brief_description);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "brief_description", PROPERTY_HINT_MULTILINE_TEXT), "_set_brief_description", "_get_brief_description");

ClassDB::bind_method(D_METHOD("_set_description", "description"), &OScript::_set_description);
ClassDB::bind_method(D_METHOD("_get_description"), &OScript::_get_description);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "description", PROPERTY_HINT_MULTILINE_TEXT), "_set_description", "_get_description");

ADD_SIGNAL(MethodInfo("connections_changed", PropertyInfo(Variant::STRING, "caller")));
ADD_SIGNAL(MethodInfo("functions_changed"));
ADD_SIGNAL(MethodInfo("variables_changed"));
Expand Down Expand Up @@ -209,9 +218,7 @@ Error OScript::_reload(bool p_keep_state)

TypedArray<Dictionary> OScript::_get_documentation() const
{
// todo: see how to generate it from the script/node contents
// see doc_data & script_language_extension
return {};
return OScriptDocData::create_documentation(Ref<OScript>(this));
}

bool OScript::_has_static_method(const StringName& p_method) const
Expand Down
4 changes: 4 additions & 0 deletions src/script/script.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ class OScript : public ScriptExtension, public Orchestration
void _set_variables(const TypedArray<OScriptVariable>& p_variables) { _set_variables_internal(p_variables); }
TypedArray<OScriptSignal> _get_signals() const { return _get_signals_internal(); }
void _set_signals(const TypedArray<OScriptSignal>& p_signals) { _set_signals_internal(p_signals); }
void _set_brief_description(const String& p_description) { set_brief_description(p_description); }
String _get_brief_description() const { return get_brief_description(); }
void _set_description(const String& p_description) { set_description(p_description); }
String _get_description() const { return get_description(); }
//~ End Serialization API

/// Update export placeholders
Expand Down
106 changes: 106 additions & 0 deletions src/script/script_docdata.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// This file is part of the Godot Orchestrator project.
//
// Copyright (c) 2023-present Vahera Studios LLC and its contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "script/script_docdata.h"

Dictionary OScriptDocData::_create_property_documentation(const PropertyInfo& p_property)
{
Dictionary property;
property["name"] = p_property.name;
property["type"] = p_property.type == Variant::NIL ? "Variant" : Variant::get_type_name(p_property.type);
return property;
}

TypedArray<Dictionary> OScriptDocData::_get_method_arguments_documentation(const std::vector<PropertyInfo>& p_properties)
{
TypedArray<Dictionary> data;
for (const PropertyInfo& property : p_properties)
data.push_back(_create_property_documentation(property));

return data;
}

String OScriptDocData::_get_method_return_type(const MethodInfo& p_method)
{
if (p_method.return_val.type == Variant::NIL)
return p_method.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT ? "Variant" : "void";

return Variant::get_type_name(p_method.return_val.type);
}

Dictionary OScriptDocData::_method_info_documentation(const MethodInfo& p_method, const String& p_description)
{
Dictionary data;
data["name"] = p_method.name;
data["description"] = p_description;
data["return_type"] = _get_method_return_type(p_method);
data["arguments"] = _get_method_arguments_documentation(p_method.arguments);
return data;
}

TypedArray<Dictionary> OScriptDocData::_create_properties_documentation(const Ref<OScript>& p_script)
{
TypedArray<Dictionary> data;
for (const Ref<OScriptVariable>& variable : p_script->get_variables())
{
Dictionary property_data = _create_property_documentation(variable->get_info());
property_data["description"] = variable->get_description();

data.push_back(property_data);
}
return data;
}

TypedArray<Dictionary> OScriptDocData::_create_signals_documentation(const Ref<OScript>& p_script)
{
TypedArray<Dictionary> data;
for (const Ref<OScriptSignal>& signal : p_script->get_custom_signals())
{
const MethodInfo& mi = signal->get_method_info();
data.push_back(_method_info_documentation(mi, signal->get("description")));
}
return data;
}

TypedArray<Dictionary> OScriptDocData::_create_functions_documentation(const Ref<OScript>& p_script)
{
TypedArray<Dictionary> data;
for (const Ref<OScriptFunction>& function : p_script->get_functions())
{
const MethodInfo& mi = function->get_method_info();
data.push_back(_method_info_documentation(mi, function->get("description")));
}
return data;
}

TypedArray<Dictionary> OScriptDocData::create_documentation(const Ref<OScript>& p_script)
{
Dictionary data;
data["name"] = vformat("\"%s\"", p_script->get_path().replace("res://", ""));
data["inherits"] = p_script->get_base_type();
data["brief_description"] = p_script->get_brief_description();
data["description"] = p_script->get_description();
data["methods"] = _create_functions_documentation(p_script);
data["signals"] = _create_signals_documentation(p_script);
data["properties"] = _create_properties_documentation(p_script);
data["is_deprecated"] = false;
data["is_experimental"] = false;
data["is_script_doc"] = true;
data["script_path"] = p_script->get_path();

// We currently only support 1 class per Orchestration
return Array::make(data);
}
Loading
Loading