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

Add VariantResource class #30

Merged
merged 10 commits into from
Nov 1, 2020
3 changes: 3 additions & 0 deletions core/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ if env["goost_math_enabled"]:

env_goost.add_source_files(env.modules_sources, "*.cpp")
env_goost.add_source_files(env.modules_sources, "types/*.cpp")

if env["tools"]:
env_goost.add_source_files(env.modules_sources, "types/editor/*.cpp")
25 changes: 24 additions & 1 deletion core/register_core_types.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,37 @@
#include "register_core_types.h"

#include "types/list.h"
#include "core/engine.h"

#include "image/register_image_types.h"
#include "math/register_math_types.h"
#include "types/list.h"
#include "types/variant_resource.h"

#ifdef TOOLS_ENABLED
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
#include "types/editor/variant_resource_preview.h"
#endif

namespace goost {

#ifdef TOOLS_ENABLED
static void _variant_resource_preview_init() {
Ref<VariantResourcePreviewGenerator> variant_resource_preview;
variant_resource_preview.instance();
EditorResourcePreview::get_singleton()->add_preview_generator(variant_resource_preview);
}
#endif

void register_core_types() {
ClassDB::register_class<ListNode>();
ClassDB::register_class<LinkedList>();

ClassDB::register_class<VariantResource>();
#ifdef TOOLS_ENABLED
EditorNode::add_init_callback(_variant_resource_preview_init);
#endif

#ifdef GOOST_IMAGE_ENABLED
register_image_types();
#endif
Expand Down
56 changes: 56 additions & 0 deletions core/types/editor/variant_resource_preview.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "variant_resource_preview.h"
#include "editor/editor_node.h"

bool VariantResourcePreviewGenerator::handles(const String &p_type) const {
return p_type == "VariantResource";
}

Ref<Texture> VariantResourcePreviewGenerator::generate(const Ref<Resource> &p_from, const Size2 &p_size) const {
Ref<VariantResource> var = p_from;
ERR_FAIL_COND_V_MSG(var.is_null(), Ref<VariantResource>(), "Invalid reference to a VariantResource object.");

const Variant &value = var->get_value();

Ref<Texture> tex;

switch (value.get_type()) {
case Variant::NIL: {
tex = EditorNode::get_singleton()->get_class_icon("Variant");
} break;
case Variant::BOOL: {
bool b = value;
String builtin_name = Variant::get_type_name(value.get_type());
String name = b ? "GuiChecked" : "GuiUnchecked";
tex = EditorNode::get_singleton()->get_class_icon(name, builtin_name);
} break;
case Variant::COLOR: {
Color color = value;
Ref<Image> image;
image.instance();
// The small icon will be stretched anyway, speed up generation.
image->create(2, 2, false, Image::FORMAT_RGBA8);
image->fill(color);
Ref<ImageTexture> img_tex;
img_tex.instance();
img_tex->create_from_image(image, 0);
tex = img_tex;
} break;
case Variant::OBJECT: {
Object *obj = value;
Ref<Texture> obj_tex = Ref<Texture>(Object::cast_to<Texture>(obj));
if (obj_tex.is_valid()) {
Ref<Image> image = obj_tex->get_data();
image->resize(p_size.x, p_size.y);
Ref<ImageTexture> img_tex;
img_tex.instance();
img_tex->create_from_image(image, 0);
tex = img_tex;
}
} break;
default: {
String name = Variant::get_type_name(value.get_type());
tex = EditorNode::get_singleton()->get_class_icon(name, "Resource");
};
}
return tex;
}
18 changes: 18 additions & 0 deletions core/types/editor/variant_resource_preview.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef VARIANT_RESOURCE_PREVIEW_H
#define VARIANT_RESOURCE_PREVIEW_H

#include "editor/editor_resource_preview.h"
#include "../variant_resource.h"

class VariantResourcePreviewGenerator : public EditorResourcePreviewGenerator {
GDCLASS(VariantResourcePreviewGenerator, EditorResourcePreviewGenerator);

public:
virtual bool handles(const String &p_type) const;
virtual Ref<Texture> generate(const RES &p_from, const Size2 &p_size) const;

virtual bool generate_small_preview_automatically() const { return true; };
virtual bool can_generate_small_preview() const { return true; };
};

#endif // VARIANT_RESOURCE_PREVIEW_H
245 changes: 245 additions & 0 deletions core/types/variant_resource.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
#include "variant_resource.h"

void VariantResource::set_type(Variant::Type p_type) {
const Variant::Type prev_type = type;
type = p_type;
// Convert previous value to a new type, if possible.
if (prev_type != Variant::NIL) {
value = convert(value, type);
} else {
value = create(type);
}
emit_changed();
_change_notify();
}

Variant VariantResource::create(const Variant::Type &p_type) {
Variant::CallError error;
return Variant::construct(p_type, nullptr, 0, error);
}

Variant VariantResource::convert(const Variant &p_value, const Variant::Type &p_to_type) {
Variant::CallError error;
const Variant *args[1];
args[0] = &p_value;
return Variant::construct(p_to_type, args, 1, error, false); // Non-strict.
}

bool VariantResource::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name.operator String();
if (name == pi.name) {
value = p_value;
type = p_value.get_type();
emit_changed();
} else {
return false;
}
return true;
}

bool VariantResource::_get(const StringName &p_name, Variant &r_ret) const {
String name = p_name.operator String();
if (name == pi.name) {
r_ret = value;
} else {
return false;
}
return true;
}

void VariantResource::set_property_name(const String &p_property_name) {
pi.name = p_property_name;
_change_notify();
}

void VariantResource::set_property_hint(PropertyHint p_property_hint) {
pi.hint = p_property_hint;
_change_notify();
}

void VariantResource::set_property_hint_string(const String &p_property_hint_string) {
pi.hint_string = p_property_hint_string;
_change_notify();
}

void VariantResource::set_property_usage(PropertyUsageFlags p_property_usage) {
pi.usage = p_property_usage;
_change_notify();
}

void VariantResource::_get_property_list(List<PropertyInfo> *p_list) const {
// This property is changed dynamically from other properties.
p_list->push_back(PropertyInfo(type, pi.name, pi.hint, pi.hint_string, pi.usage));
}

String VariantResource::get_type_hints() {
String type_hints;
for (int i = 0; i < Variant::VARIANT_MAX; ++i) {
type_hints += Variant::get_type_name(Variant::Type(i));
if (i < Variant::VARIANT_MAX - 1) {
type_hints += ",";
}
}
return type_hints;
}

String VariantResource::get_property_hint_name(const PropertyHint &p_hint) {
switch (p_hint) {
case PROPERTY_HINT_NONE: {
return "None";
} break;
case PROPERTY_HINT_RANGE: {
return "Range";
} break;
case PROPERTY_HINT_EXP_RANGE: {
return "Exponential Range";
} break;
case PROPERTY_HINT_ENUM: {
return "Enum";
} break;
case PROPERTY_HINT_EXP_EASING: {
return "Exponential Easing";
} break;
case PROPERTY_HINT_LENGTH: {
return "Length";
} break;
case PROPERTY_HINT_SPRITE_FRAME: {
return "SpriteFrame";
} break;
case PROPERTY_HINT_KEY_ACCEL: {
return "Key Accel";
} break;
case PROPERTY_HINT_FLAGS: {
return "Flags";
} break;
case PROPERTY_HINT_LAYERS_2D_RENDER: {
return "Layers 2D Render";
} break;
case PROPERTY_HINT_LAYERS_2D_PHYSICS: {
return "Layers 2D Physics";
} break;
case PROPERTY_HINT_LAYERS_3D_RENDER: {
return "Layers 3D Render";
} break;
case PROPERTY_HINT_LAYERS_3D_PHYSICS: {
return "Layers 3D Physics";
} break;
case PROPERTY_HINT_FILE: {
return "File";
} break;
case PROPERTY_HINT_DIR: {
return "Directory";
} break;
case PROPERTY_HINT_GLOBAL_FILE: {
return "Global File";
} break;
case PROPERTY_HINT_GLOBAL_DIR: {
return "Global Directory";
} break;
case PROPERTY_HINT_RESOURCE_TYPE: {
return "Resource Type";
} break;
case PROPERTY_HINT_MULTILINE_TEXT: {
return "Multiline Text";
} break;
case PROPERTY_HINT_PLACEHOLDER_TEXT: {
return "Placeholder Text";
} break;
case PROPERTY_HINT_COLOR_NO_ALPHA: {
return "Color No Alpha";
} break;
case PROPERTY_HINT_IMAGE_COMPRESS_LOSSY: {
return "Image Compress Lossy";
} break;
case PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS: {
return "Image Compress Lossless";
} break;
case PROPERTY_HINT_OBJECT_ID: {
return "ObjectID";
} break;
case PROPERTY_HINT_TYPE_STRING: {
return "String";
} break;
case PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE: {
return "NodePath To Edited Node";
} break;
case PROPERTY_HINT_METHOD_OF_VARIANT_TYPE: {
return "Method Of Variant Type";
} break;
case PROPERTY_HINT_METHOD_OF_BASE_TYPE: {
return "Method Of Base Type";
} break;
case PROPERTY_HINT_METHOD_OF_INSTANCE: {
return "Method Of Instance";
} break;
case PROPERTY_HINT_METHOD_OF_SCRIPT: {
return "Method Of Script";
} break;
case PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE: {
return "Property Of Variant Type";
} break;
case PROPERTY_HINT_PROPERTY_OF_BASE_TYPE: {
return "Property Of Base Type";
} break;
case PROPERTY_HINT_PROPERTY_OF_INSTANCE: {
return "Property Of Instance";
} break;
case PROPERTY_HINT_PROPERTY_OF_SCRIPT: {
return "Property Of Script";
} break;
case PROPERTY_HINT_OBJECT_TOO_BIG: {
return "Object Too Big";
} break;
case PROPERTY_HINT_NODE_PATH_VALID_TYPES: {
return "NodePath Valid Types";
} break;
case PROPERTY_HINT_SAVE_FILE: {
return "Save File";
} break;
case PROPERTY_HINT_MAX: {
ERR_FAIL_V_MSG("", "Invalid property hint type.");
} break;
}
return "";
}

String VariantResource::get_property_hint_types() {
String hint_types;
for (int i = 0; i < PropertyHint::PROPERTY_HINT_MAX; ++i) {
hint_types += VariantResource::get_property_hint_name(PropertyHint(i));
if (i < PropertyHint::PROPERTY_HINT_MAX - 1) {
hint_types += ",";
}
}
return hint_types;
}

void VariantResource::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_type", "type"), &VariantResource::set_type);
ClassDB::bind_method(D_METHOD("get_type"), &VariantResource::get_type);

ClassDB::bind_method(D_METHOD("set_value", "value"), &VariantResource::set_value);
ClassDB::bind_method(D_METHOD("get_value"), &VariantResource::get_value);

ClassDB::bind_method(D_METHOD("set_property_name", "name"), &VariantResource::set_property_name);
ClassDB::bind_method(D_METHOD("get_property_name"), &VariantResource::get_property_name);

ClassDB::bind_method(D_METHOD("set_property_hint", "hint"), &VariantResource::set_property_hint);
ClassDB::bind_method(D_METHOD("get_property_hint"), &VariantResource::get_property_hint);

ClassDB::bind_method(D_METHOD("set_property_hint_string", "hint_string"), &VariantResource::set_property_hint_string);
ClassDB::bind_method(D_METHOD("get_property_hint_string"), &VariantResource::get_property_hint_string);

ClassDB::bind_method(D_METHOD("set_property_usage", "usage"), &VariantResource::set_property_usage);
ClassDB::bind_method(D_METHOD("get_property_usage"), &VariantResource::get_property_usage);

// DO NOT expose `value` as a property here, this is handled by `_get_property_list()` instead.

ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, get_type_hints()), "set_type", "get_type");

ADD_GROUP("Property", "property_");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "property_name"), "set_property_name", "get_property_name");
ADD_PROPERTY(PropertyInfo(Variant::INT, "property_hint", PROPERTY_HINT_ENUM, get_property_hint_types()), "set_property_hint", "get_property_hint");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "property_hint_string"), "set_property_hint_string", "get_property_hint_string");
ADD_PROPERTY(PropertyInfo(Variant::INT, "property_usage"), "set_property_usage", "get_property_usage");
}
Loading