Skip to content

Commit

Permalink
Added Structs to GDScript.
Browse files Browse the repository at this point in the history
  • Loading branch information
nlupugla committed Apr 22, 2024
1 parent 2b94e3d commit d906d86
Show file tree
Hide file tree
Showing 37 changed files with 1,213 additions and 527 deletions.
2 changes: 2 additions & 0 deletions core/object/script_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ class Script : public Resource {

virtual void get_constants(HashMap<StringName, Variant> *p_constants) {}
virtual void get_members(HashSet<StringName> *p_constants) {}
virtual const StructInfo *get_struct_info(const String &p_struct_name) const { return ClassDB::get_struct_info(p_struct_name); }

virtual bool is_placeholder_fallback_enabled() const { return false; }

Expand Down Expand Up @@ -292,6 +293,7 @@ class ScriptLanguage : public Object {
CODE_COMPLETION_KIND_NODE_PATH,
CODE_COMPLETION_KIND_FILE_PATH,
CODE_COMPLETION_KIND_PLAIN_TEXT,
CODE_COMPLETION_KIND_STRUCT,
CODE_COMPLETION_KIND_MAX
};

Expand Down
33 changes: 24 additions & 9 deletions core/variant/struct_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,18 +182,33 @@ struct StructInfo {
Vector<Variant> default_values;

StructInfo(){};
StructInfo(const StringName &p_name, const int32_t p_count, const Vector<StringName> &p_names, const Vector<Variant::Type> &p_types, const Vector<StringName> &p_class_names, const Vector<const StructInfo *> &p_struct_member_infos, const Vector<Variant> &p_default_values) {
name = p_name;
count = p_count;
names = p_names;
types = p_types;
class_names = p_class_names;
struct_member_infos = p_struct_member_infos;
default_values = p_default_values;
};
StructInfo(const StringName &p_name, const int32_t p_count) :
name(p_name), count(p_count) {
names.resize(p_count);
types.resize(p_count);
class_names.resize(p_count);
struct_member_infos.resize(p_count);
default_values.resize(p_count);
}
StructInfo(const StringName &p_name, const int32_t p_count, const Vector<StringName> &p_names, const Vector<Variant::Type> &p_types, const Vector<StringName> &p_class_names, const Vector<const StructInfo *> &p_struct_member_infos, const Vector<Variant> &p_default_values) :
name(p_name),
count(p_count),
names(p_names),
types(p_types),
class_names(p_class_names),
struct_member_infos(p_struct_member_infos),
default_values(p_default_values){};

Dictionary to_dict() const;

_FORCE_INLINE_ void set(int32_t p_index, const StringName &p_name, const Variant::Type &p_type, const StringName &p_class_name, const StructInfo *p_struct_member_info, const Variant &p_default_value) {
names.write[p_index] = p_name;
types.write[p_index] = p_type;
class_names.write[p_index] = p_class_name;
struct_member_infos.write[p_index] = p_struct_member_info;
default_values.write[p_index] = p_default_value;
}

_FORCE_INLINE_ bool operator==(const StructInfo &p_struct_info) const {
return name == p_struct_info.name;
}
Expand Down
18 changes: 9 additions & 9 deletions doc/classes/CodeEdit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -590,31 +590,31 @@
<constant name="KIND_CLASS" value="0" enum="CodeCompletionKind">
Marks the option as a class.
</constant>
<constant name="KIND_FUNCTION" value="1" enum="CodeCompletionKind">
<constant name="KIND_FUNCTION" value="2" enum="CodeCompletionKind">
Marks the option as a function.
</constant>
<constant name="KIND_SIGNAL" value="2" enum="CodeCompletionKind">
<constant name="KIND_SIGNAL" value="3" enum="CodeCompletionKind">
Marks the option as a Godot signal.
</constant>
<constant name="KIND_VARIABLE" value="3" enum="CodeCompletionKind">
<constant name="KIND_VARIABLE" value="4" enum="CodeCompletionKind">
Marks the option as a variable.
</constant>
<constant name="KIND_MEMBER" value="4" enum="CodeCompletionKind">
<constant name="KIND_MEMBER" value="5" enum="CodeCompletionKind">
Marks the option as a member.
</constant>
<constant name="KIND_ENUM" value="5" enum="CodeCompletionKind">
<constant name="KIND_ENUM" value="6" enum="CodeCompletionKind">
Marks the option as an enum entry.
</constant>
<constant name="KIND_CONSTANT" value="6" enum="CodeCompletionKind">
<constant name="KIND_CONSTANT" value="7" enum="CodeCompletionKind">
Marks the option as a constant.
</constant>
<constant name="KIND_NODE_PATH" value="7" enum="CodeCompletionKind">
<constant name="KIND_NODE_PATH" value="8" enum="CodeCompletionKind">
Marks the option as a Godot node path.
</constant>
<constant name="KIND_FILE_PATH" value="8" enum="CodeCompletionKind">
<constant name="KIND_FILE_PATH" value="9" enum="CodeCompletionKind">
Marks the option as a file path.
</constant>
<constant name="KIND_PLAIN_TEXT" value="9" enum="CodeCompletionKind">
<constant name="KIND_PLAIN_TEXT" value="10" enum="CodeCompletionKind">
Marks the option as unclassified or plain text.
</constant>
<constant name="LOCATION_LOCAL" value="0" enum="CodeCompletionLocation">
Expand Down
20 changes: 10 additions & 10 deletions doc/classes/ScriptLanguageExtension.xml
Original file line number Diff line number Diff line change
Expand Up @@ -393,25 +393,25 @@
</constant>
<constant name="CODE_COMPLETION_KIND_CLASS" value="0" enum="CodeCompletionKind">
</constant>
<constant name="CODE_COMPLETION_KIND_FUNCTION" value="1" enum="CodeCompletionKind">
<constant name="CODE_COMPLETION_KIND_FUNCTION" value="2" enum="CodeCompletionKind">
</constant>
<constant name="CODE_COMPLETION_KIND_SIGNAL" value="2" enum="CodeCompletionKind">
<constant name="CODE_COMPLETION_KIND_SIGNAL" value="3" enum="CodeCompletionKind">
</constant>
<constant name="CODE_COMPLETION_KIND_VARIABLE" value="3" enum="CodeCompletionKind">
<constant name="CODE_COMPLETION_KIND_VARIABLE" value="4" enum="CodeCompletionKind">
</constant>
<constant name="CODE_COMPLETION_KIND_MEMBER" value="4" enum="CodeCompletionKind">
<constant name="CODE_COMPLETION_KIND_MEMBER" value="5" enum="CodeCompletionKind">
</constant>
<constant name="CODE_COMPLETION_KIND_ENUM" value="5" enum="CodeCompletionKind">
<constant name="CODE_COMPLETION_KIND_ENUM" value="6" enum="CodeCompletionKind">
</constant>
<constant name="CODE_COMPLETION_KIND_CONSTANT" value="6" enum="CodeCompletionKind">
<constant name="CODE_COMPLETION_KIND_CONSTANT" value="7" enum="CodeCompletionKind">
</constant>
<constant name="CODE_COMPLETION_KIND_NODE_PATH" value="7" enum="CodeCompletionKind">
<constant name="CODE_COMPLETION_KIND_NODE_PATH" value="8" enum="CodeCompletionKind">
</constant>
<constant name="CODE_COMPLETION_KIND_FILE_PATH" value="8" enum="CodeCompletionKind">
<constant name="CODE_COMPLETION_KIND_FILE_PATH" value="9" enum="CodeCompletionKind">
</constant>
<constant name="CODE_COMPLETION_KIND_PLAIN_TEXT" value="9" enum="CodeCompletionKind">
<constant name="CODE_COMPLETION_KIND_PLAIN_TEXT" value="10" enum="CodeCompletionKind">
</constant>
<constant name="CODE_COMPLETION_KIND_MAX" value="10" enum="CodeCompletionKind">
<constant name="CODE_COMPLETION_KIND_MAX" value="11" enum="CodeCompletionKind">
</constant>
</constants>
</class>
12 changes: 12 additions & 0 deletions modules/gdscript/editor/gdscript_docgen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,18 @@ void GDScriptDocGen::_doctype_from_gdtype(const GDType &p_gdtype, String &r_type
}
}
return;
case GDType::STRUCT:
r_type = "Array";
// TODO: just copied from enum for now, probably needs Struct specific logic
r_enum = String(p_gdtype.native_type).replace("::", ".");
if (r_enum.begins_with("res://")) {
r_enum = r_enum.trim_prefix("res://");
int dot_pos = r_enum.rfind(".");
if (dot_pos >= 0) {
r_enum = r_enum.left(dot_pos).quote() + r_enum.substr(dot_pos);
}
}
return;
case GDType::VARIANT:
case GDType::RESOLVING:
case GDType::UNRESOLVED:
Expand Down
32 changes: 32 additions & 0 deletions modules/gdscript/gdscript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,33 @@ GDScript *GDScript::get_root_script() {
return result;
}

const StructInfo *GDScript::get_struct_info(const String &p_struct_name) const {
if (const StructInfo *info = structs.getptr(p_struct_name)) {
return info;
}

Vector<String> names = String(p_struct_name).split(".");
if (names.size() == 2) {
if (const StructInfo *info = ClassDB::get_struct_info(names[0], names[1])) {
return info;
}
}
// TODO: this is to handle cases where the name is something like U"res://main.gd.MyStruct" but there should probably be a better solution
return structs.getptr(names[names.size() - 1]);
}

void GDScript::set_struct_info(const StructInfo &p_struct_info) {
if (ClassDB::get_struct_info(p_struct_info.name)) {
// TODO: warn about shadowing native struct?
return;
}
if (structs.has(p_struct_info.name)) {
// TODO: warn about shadowing script struct?
return;
}
structs.insert(p_struct_info.name, p_struct_info);
}

RBSet<GDScript *> GDScript::get_dependencies() {
RBSet<GDScript *> dependencies;

Expand Down Expand Up @@ -1307,6 +1334,7 @@ void GDScript::_collect_function_dependencies(GDScriptFunction *p_func, RBSet<GD
}

void GDScript::_collect_dependencies(RBSet<GDScript *> &p_dependencies, const GDScript *p_except) {
// TODO: Do I need Struct logic here?
if (p_dependencies.has(this)) {
return;
}
Expand Down Expand Up @@ -1356,6 +1384,7 @@ GDScript::GDScript() :
}

void GDScript::_save_orphaned_subclasses(ClearData *p_clear_data) {
// TODO: Do I need Struct logic here?
struct ClassRefWithName {
ObjectID id;
String fully_qualified_name;
Expand Down Expand Up @@ -2158,6 +2187,8 @@ void GDScriptLanguage::init() {
_add_global(n, nc);
}

// TODO: Structs?

//populate singletons

List<Engine::Singleton> singletons;
Expand Down Expand Up @@ -2598,6 +2629,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"namespace", // Reserved for potential future use.
"signal",
"static",
"struct",
"trait", // Reserved for potential future use.
"var",
// Other keywords.
Expand Down
3 changes: 3 additions & 0 deletions modules/gdscript/gdscript.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ class GDScript : public Script {
HashMap<StringName, Variant> constants;
HashMap<StringName, GDScriptFunction *> member_functions;
HashMap<StringName, Ref<GDScript>> subclasses;
HashMap<StringName, StructInfo> structs;
HashMap<StringName, MethodInfo> _signals;
Dictionary rpc_config;

Expand Down Expand Up @@ -258,6 +259,8 @@ class GDScript : public Script {
}
const HashMap<StringName, GDScriptFunction *> &get_member_functions() const { return member_functions; }
const Ref<GDScriptNativeClass> &get_native() const { return native; }
virtual const StructInfo *get_struct_info(const String &p_struct_name) const override;
void set_struct_info(const StructInfo &p_struct_info);

RBSet<GDScript *> get_dependencies();
HashMap<GDScript *, RBSet<GDScript *>> get_all_dependencies();
Expand Down
Loading

0 comments on commit d906d86

Please sign in to comment.