summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/gui/base_button.cpp6
-rw-r--r--scene/gui/base_button.h6
-rw-r--r--scene/gui/popup_menu.cpp24
-rw-r--r--scene/gui/popup_menu.h24
-rw-r--r--scene/gui/shortcut.cpp24
-rw-r--r--scene/gui/shortcut.h6
-rw-r--r--scene/register_scene_types.cpp13
-rw-r--r--scene/resources/texture.cpp304
-rw-r--r--scene/resources/texture.h116
9 files changed, 477 insertions, 46 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index aaae03df68..211082d610 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -326,12 +326,12 @@ bool BaseButton::is_keep_pressed_outside() const {
return keep_pressed_outside;
}
-void BaseButton::set_shortcut(const Ref<ShortCut> &p_shortcut) {
+void BaseButton::set_shortcut(const Ref<Shortcut> &p_shortcut) {
shortcut = p_shortcut;
set_process_unhandled_input(shortcut.is_valid());
}
-Ref<ShortCut> BaseButton::get_shortcut() const {
+Ref<Shortcut> BaseButton::get_shortcut() const {
return shortcut;
}
@@ -414,7 +414,7 @@ void BaseButton::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask", PROPERTY_HINT_FLAGS, "Mouse Left, Mouse Right, Mouse Middle"), "set_button_mask", "get_button_mask");
ADD_PROPERTY(PropertyInfo(Variant::INT, "enabled_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_enabled_focus_mode", "get_enabled_focus_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_pressed_outside"), "set_keep_pressed_outside", "is_keep_pressed_outside");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "ShortCut"), "set_shortcut", "get_shortcut");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "Shortcut"), "set_shortcut", "get_shortcut");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "group", PROPERTY_HINT_RESOURCE_TYPE, "ButtonGroup"), "set_button_group", "get_button_group");
BIND_ENUM_CONSTANT(DRAW_NORMAL);
diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h
index 12272446d5..8e71931f8b 100644
--- a/scene/gui/base_button.h
+++ b/scene/gui/base_button.h
@@ -50,7 +50,7 @@ private:
bool shortcut_in_tooltip;
bool keep_pressed_outside;
FocusMode enabled_focus_mode;
- Ref<ShortCut> shortcut;
+ Ref<Shortcut> shortcut;
ActionMode action_mode;
struct Status {
@@ -118,8 +118,8 @@ public:
void set_enabled_focus_mode(FocusMode p_mode);
FocusMode get_enabled_focus_mode() const;
- void set_shortcut(const Ref<ShortCut> &p_shortcut);
- Ref<ShortCut> get_shortcut() const;
+ void set_shortcut(const Ref<Shortcut> &p_shortcut);
+ Ref<Shortcut> get_shortcut() const;
virtual String get_tooltip(const Point2 &p_pos) const override;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 2fdcf11ca8..bc70809ad5 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -717,7 +717,7 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int
}
#define ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global) \
- ERR_FAIL_COND_MSG(p_shortcut.is_null(), "Cannot add item with invalid ShortCut."); \
+ ERR_FAIL_COND_MSG(p_shortcut.is_null(), "Cannot add item with invalid Shortcut."); \
_ref_shortcut(p_shortcut); \
item.text = p_shortcut->get_name(); \
item.xl_text = tr(item.text); \
@@ -725,7 +725,7 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int
item.shortcut = p_shortcut; \
item.shortcut_is_global = p_global;
-void PopupMenu::add_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
+void PopupMenu::add_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) {
Item item;
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
items.push_back(item);
@@ -733,7 +733,7 @@ void PopupMenu::add_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_g
child_controls_changed();
}
-void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
+void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) {
Item item;
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
item.icon = p_icon;
@@ -742,7 +742,7 @@ void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortC
child_controls_changed();
}
-void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
+void PopupMenu::add_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) {
Item item;
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
@@ -751,7 +751,7 @@ void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bo
child_controls_changed();
}
-void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
+void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) {
Item item;
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
item.icon = p_icon;
@@ -761,7 +761,7 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<
child_controls_changed();
}
-void PopupMenu::add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
+void PopupMenu::add_radio_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) {
Item item;
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
@@ -770,7 +770,7 @@ void PopupMenu::add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_
child_controls_changed();
}
-void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
+void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) {
Item item;
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
item.icon = p_icon;
@@ -931,8 +931,8 @@ String PopupMenu::get_item_tooltip(int p_idx) const {
return items[p_idx].tooltip;
}
-Ref<ShortCut> PopupMenu::get_item_shortcut(int p_idx) const {
- ERR_FAIL_INDEX_V(p_idx, items.size(), Ref<ShortCut>());
+Ref<Shortcut> PopupMenu::get_item_shortcut(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, items.size(), Ref<Shortcut>());
return items[p_idx].shortcut;
}
@@ -970,7 +970,7 @@ void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) {
control->update();
}
-void PopupMenu::set_item_shortcut(int p_idx, const Ref<ShortCut> &p_shortcut, bool p_global) {
+void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bool p_global) {
ERR_FAIL_INDEX(p_idx, items.size());
if (items[p_idx].shortcut.is_valid()) {
_unref_shortcut(items[p_idx].shortcut);
@@ -1209,7 +1209,7 @@ Array PopupMenu::_get_items() const {
return items;
}
-void PopupMenu::_ref_shortcut(Ref<ShortCut> p_sc) {
+void PopupMenu::_ref_shortcut(Ref<Shortcut> p_sc) {
if (!shortcut_refcount.has(p_sc)) {
shortcut_refcount[p_sc] = 1;
p_sc->connect("changed", callable_mp((CanvasItem *)this, &CanvasItem::update));
@@ -1218,7 +1218,7 @@ void PopupMenu::_ref_shortcut(Ref<ShortCut> p_sc) {
}
}
-void PopupMenu::_unref_shortcut(Ref<ShortCut> p_sc) {
+void PopupMenu::_unref_shortcut(Ref<Shortcut> p_sc) {
ERR_FAIL_COND(!shortcut_refcount.has(p_sc));
shortcut_refcount[p_sc]--;
if (shortcut_refcount[p_sc] == 0) {
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index 45a3336747..9535fd07d7 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -61,7 +61,7 @@ class PopupMenu : public Popup {
int _ofs_cache;
int _height_cache;
int h_ofs;
- Ref<ShortCut> shortcut;
+ Ref<Shortcut> shortcut;
bool shortcut_is_global;
bool shortcut_is_disabled;
@@ -114,10 +114,10 @@ class PopupMenu : public Popup {
Array _get_items() const;
void _set_items(const Array &p_items);
- Map<Ref<ShortCut>, int> shortcut_refcount;
+ Map<Ref<Shortcut>, int> shortcut_refcount;
- void _ref_shortcut(Ref<ShortCut> p_sc);
- void _unref_shortcut(Ref<ShortCut> p_sc);
+ void _ref_shortcut(Ref<Shortcut> p_sc);
+ void _unref_shortcut(Ref<Shortcut> p_sc);
bool allow_search;
uint64_t search_time_msec;
@@ -145,12 +145,12 @@ public:
void add_multistate_item(const String &p_label, int p_max_states, int p_default_state = 0, int p_id = -1, uint32_t p_accel = 0);
- void add_shortcut(const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
- void add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
- void add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
- void add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
- void add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
- void add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
+ void add_shortcut(const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false);
+ void add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false);
+ void add_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false);
+ void add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false);
+ void add_radio_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false);
+ void add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false);
void add_submenu_item(const String &p_label, const String &p_submenu, int p_id = -1);
@@ -166,7 +166,7 @@ public:
void set_item_as_checkable(int p_idx, bool p_checkable);
void set_item_as_radio_checkable(int p_idx, bool p_radio_checkable);
void set_item_tooltip(int p_idx, const String &p_tooltip);
- void set_item_shortcut(int p_idx, const Ref<ShortCut> &p_shortcut, bool p_global = false);
+ void set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bool p_global = false);
void set_item_h_offset(int p_idx, int p_offset);
void set_item_multistate(int p_idx, int p_state);
void toggle_item_multistate(int p_idx);
@@ -189,7 +189,7 @@ public:
bool is_item_radio_checkable(int p_idx) const;
bool is_item_shortcut_disabled(int p_idx) const;
String get_item_tooltip(int p_idx) const;
- Ref<ShortCut> get_item_shortcut(int p_idx) const;
+ Ref<Shortcut> get_item_shortcut(int p_idx) const;
int get_item_state(int p_idx) const;
int get_current_index() const;
diff --git a/scene/gui/shortcut.cpp b/scene/gui/shortcut.cpp
index 9f5b9c40c2..f8c7bc44a7 100644
--- a/scene/gui/shortcut.cpp
+++ b/scene/gui/shortcut.cpp
@@ -32,20 +32,20 @@
#include "core/os/keyboard.h"
-void ShortCut::set_shortcut(const Ref<InputEvent> &p_shortcut) {
+void Shortcut::set_shortcut(const Ref<InputEvent> &p_shortcut) {
shortcut = p_shortcut;
emit_changed();
}
-Ref<InputEvent> ShortCut::get_shortcut() const {
+Ref<InputEvent> Shortcut::get_shortcut() const {
return shortcut;
}
-bool ShortCut::is_shortcut(const Ref<InputEvent> &p_event) const {
+bool Shortcut::is_shortcut(const Ref<InputEvent> &p_event) const {
return shortcut.is_valid() && shortcut->shortcut_match(p_event);
}
-String ShortCut::get_as_text() const {
+String Shortcut::get_as_text() const {
if (shortcut.is_valid()) {
return shortcut->as_text();
} else {
@@ -53,21 +53,21 @@ String ShortCut::get_as_text() const {
}
}
-bool ShortCut::is_valid() const {
+bool Shortcut::is_valid() const {
return shortcut.is_valid();
}
-void ShortCut::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_shortcut", "event"), &ShortCut::set_shortcut);
- ClassDB::bind_method(D_METHOD("get_shortcut"), &ShortCut::get_shortcut);
+void Shortcut::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_shortcut", "event"), &Shortcut::set_shortcut);
+ ClassDB::bind_method(D_METHOD("get_shortcut"), &Shortcut::get_shortcut);
- ClassDB::bind_method(D_METHOD("is_valid"), &ShortCut::is_valid);
+ ClassDB::bind_method(D_METHOD("is_valid"), &Shortcut::is_valid);
- ClassDB::bind_method(D_METHOD("is_shortcut", "event"), &ShortCut::is_shortcut);
- ClassDB::bind_method(D_METHOD("get_as_text"), &ShortCut::get_as_text);
+ ClassDB::bind_method(D_METHOD("is_shortcut", "event"), &Shortcut::is_shortcut);
+ ClassDB::bind_method(D_METHOD("get_as_text"), &Shortcut::get_as_text);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), "set_shortcut", "get_shortcut");
}
-ShortCut::ShortCut() {
+Shortcut::Shortcut() {
}
diff --git a/scene/gui/shortcut.h b/scene/gui/shortcut.h
index 063d4e43dc..0d7809e5cf 100644
--- a/scene/gui/shortcut.h
+++ b/scene/gui/shortcut.h
@@ -34,8 +34,8 @@
#include "core/input/input_event.h"
#include "core/resource.h"
-class ShortCut : public Resource {
- GDCLASS(ShortCut, Resource);
+class Shortcut : public Resource {
+ GDCLASS(Shortcut, Resource);
Ref<InputEvent> shortcut;
@@ -50,7 +50,7 @@ public:
String get_as_text() const;
- ShortCut();
+ Shortcut();
};
#endif // SHORTCUT_H
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 0f6475cf0d..39749bcf6f 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -230,6 +230,7 @@ static Ref<ResourceFormatLoaderDynamicFont> resource_loader_dynamic_font;
static Ref<ResourceFormatLoaderStreamTexture2D> resource_loader_stream_texture;
static Ref<ResourceFormatLoaderStreamTextureLayered> resource_loader_texture_layered;
+static Ref<ResourceFormatLoaderStreamTexture3D> resource_loader_texture_3d;
static Ref<ResourceFormatLoaderBMFont> resource_loader_bmfont;
@@ -252,6 +253,9 @@ void register_scene_types() {
resource_loader_texture_layered.instance();
ResourceLoader::add_resource_format_loader(resource_loader_texture_layered);
+ resource_loader_texture_3d.instance();
+ ResourceLoader::add_resource_format_loader(resource_loader_texture_3d);
+
resource_saver_text.instance();
ResourceSaver::add_resource_format_saver(resource_saver_text, true);
@@ -291,7 +295,7 @@ void register_scene_types() {
OS::get_singleton()->yield(); //may take time to init
- ClassDB::register_class<ShortCut>();
+ ClassDB::register_class<Shortcut>();
ClassDB::register_class<Control>();
ClassDB::register_class<Button>();
ClassDB::register_class<Label>();
@@ -701,6 +705,9 @@ void register_scene_types() {
ClassDB::register_class<CameraTexture>();
ClassDB::register_virtual_class<TextureLayered>();
ClassDB::register_virtual_class<ImageTextureLayered>();
+ ClassDB::register_virtual_class<Texture3D>();
+ ClassDB::register_class<ImageTexture3D>();
+ ClassDB::register_class<StreamTexture3D>();
ClassDB::register_class<Cubemap>();
ClassDB::register_class<CubemapArray>();
ClassDB::register_class<Texture2DArray>();
@@ -864,6 +871,7 @@ void register_scene_types() {
ClassDB::add_compatibility_class("RemoteTransform", "RemoteTransform3D");
ClassDB::add_compatibility_class("RigidBody", "RigidBody3D");
ClassDB::add_compatibility_class("Shape", "Shape3D");
+ ClassDB::add_compatibility_class("ShortCut", "Shortcut");
ClassDB::add_compatibility_class("Skeleton", "Skeleton3D");
ClassDB::add_compatibility_class("SkeletonIK", "SkeletonIK3D");
ClassDB::add_compatibility_class("SliderJoint", "SliderJoint3D");
@@ -946,6 +954,9 @@ void unregister_scene_types() {
ResourceLoader::remove_resource_format_loader(resource_loader_texture_layered);
resource_loader_texture_layered.unref();
+ ResourceLoader::remove_resource_format_loader(resource_loader_texture_3d);
+ resource_loader_texture_3d.unref();
+
ResourceLoader::remove_resource_format_loader(resource_loader_stream_texture);
resource_loader_stream_texture.unref();
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 5681613c04..39237e1a33 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -791,8 +791,312 @@ String ResourceFormatLoaderStreamTexture2D::get_resource_type(const String &p_pa
return "";
}
+////////////////////////////////////
+
+TypedArray<Image> Texture3D::_get_data() const {
+ Vector<Ref<Image>> data = get_data();
+
+ TypedArray<Image> ret;
+ ret.resize(data.size());
+ for (int i = 0; i < data.size(); i++) {
+ ret[i] = data[i];
+ }
+ return ret;
+}
+
+void Texture3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_format"), &Texture3D::get_format);
+ ClassDB::bind_method(D_METHOD("get_width"), &Texture3D::get_width);
+ ClassDB::bind_method(D_METHOD("get_height"), &Texture3D::get_height);
+ ClassDB::bind_method(D_METHOD("get_depth"), &Texture3D::get_depth);
+ ClassDB::bind_method(D_METHOD("has_mipmaps"), &Texture3D::has_mipmaps);
+ ClassDB::bind_method(D_METHOD("get_data"), &Texture3D::_get_data);
+}
//////////////////////////////////////////
+Image::Format ImageTexture3D::get_format() const {
+ return format;
+}
+int ImageTexture3D::get_width() const {
+ return width;
+}
+int ImageTexture3D::get_height() const {
+ return height;
+}
+int ImageTexture3D::get_depth() const {
+ return depth;
+}
+bool ImageTexture3D::has_mipmaps() const {
+ return mipmaps;
+}
+
+Error ImageTexture3D::_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data) {
+ Vector<Ref<Image>> images;
+ images.resize(p_data.size());
+ for (int i = 0; i < images.size(); i++) {
+ images.write[i] = p_data[i];
+ }
+ return create(p_format, p_width, p_height, p_depth, p_mipmaps, images);
+}
+
+void ImageTexture3D::_update(const TypedArray<Image> &p_data) {
+ Vector<Ref<Image>> images;
+ images.resize(p_data.size());
+ for (int i = 0; i < images.size(); i++) {
+ images.write[i] = p_data[i];
+ }
+ return update(images);
+}
+
+Error ImageTexture3D::create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) {
+ RID tex = RenderingServer::get_singleton()->texture_3d_create(p_format, p_width, p_height, p_depth, p_mipmaps, p_data);
+ ERR_FAIL_COND_V(tex.is_null(), ERR_CANT_CREATE);
+
+ if (texture.is_valid()) {
+ RenderingServer::get_singleton()->texture_replace(texture, tex);
+ }
+
+ return OK;
+}
+
+void ImageTexture3D::update(const Vector<Ref<Image>> &p_data) {
+ ERR_FAIL_COND(!texture.is_valid());
+ RenderingServer::get_singleton()->texture_3d_update(texture, p_data);
+}
+
+Vector<Ref<Image>> ImageTexture3D::get_data() const {
+ ERR_FAIL_COND_V(!texture.is_valid(), Vector<Ref<Image>>());
+ return RS::get_singleton()->texture_3d_get(texture);
+}
+
+RID ImageTexture3D::get_rid() const {
+ if (!texture.is_valid()) {
+ texture = RS::get_singleton()->texture_3d_placeholder_create();
+ }
+ return texture;
+}
+void ImageTexture3D::set_path(const String &p_path, bool p_take_over) {
+ if (texture.is_valid()) {
+ RenderingServer::get_singleton()->texture_set_path(texture, p_path);
+ }
+
+ Resource::set_path(p_path, p_take_over);
+}
+
+void ImageTexture3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("create", "format", "width", "height", "depth", "use_mipmaps", "data"), &ImageTexture3D::_create);
+ ClassDB::bind_method(D_METHOD("update", "data"), &ImageTexture3D::_update);
+}
+
+ImageTexture3D::ImageTexture3D() {
+}
+
+ImageTexture3D::~ImageTexture3D() {
+ if (texture.is_valid()) {
+ RS::get_singleton()->free(texture);
+ }
+}
+
+////////////////////////////////////////////
+
+void StreamTexture3D::set_path(const String &p_path, bool p_take_over) {
+ if (texture.is_valid()) {
+ RenderingServer::get_singleton()->texture_set_path(texture, p_path);
+ }
+
+ Resource::set_path(p_path, p_take_over);
+}
+
+Image::Format StreamTexture3D::get_format() const {
+ return format;
+}
+
+Error StreamTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> &r_data, Image::Format &r_format, int &r_width, int &r_height, int &r_depth, bool &r_mipmaps) {
+ FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
+
+ uint8_t header[4];
+ f->get_buffer(header, 4);
+ ERR_FAIL_COND_V(header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != 'L', ERR_FILE_UNRECOGNIZED);
+
+ //stored as stream textures (used for lossless and lossy compression)
+ uint32_t version = f->get_32();
+
+ if (version > FORMAT_VERSION) {
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new.");
+ }
+
+ r_depth = f->get_32(); //depth
+ f->get_32(); //ignored (mode)
+ f->get_32(); // ignored (data format)
+
+ f->get_32(); //ignored
+ int mipmaps = f->get_32();
+ f->get_32(); //ignored
+ f->get_32(); //ignored
+
+ r_mipmaps = mipmaps != 0;
+
+ r_data.clear();
+
+ for (int i = 0; i < (r_depth + mipmaps); i++) {
+ Ref<Image> image = StreamTexture2D::load_image_from_file(f, 0);
+ ERR_FAIL_COND_V(image.is_null() || image->empty(), ERR_CANT_OPEN);
+ if (i == 0) {
+ r_format = image->get_format();
+ r_width = image->get_width();
+ r_height = image->get_height();
+ }
+ r_data.push_back(image);
+ }
+
+ return OK;
+}
+
+Error StreamTexture3D::load(const String &p_path) {
+ Vector<Ref<Image>> data;
+
+ int tw, th, td;
+ Image::Format tfmt;
+ bool tmm;
+
+ Error err = _load_data(p_path, data, tfmt, tw, th, td, tmm);
+ if (err) {
+ return err;
+ }
+
+ if (texture.is_valid()) {
+ RID new_texture = RS::get_singleton()->texture_3d_create(tfmt, tw, th, td, tmm, data);
+ RS::get_singleton()->texture_replace(texture, new_texture);
+ } else {
+ texture = RS::get_singleton()->texture_3d_create(tfmt, tw, th, td, tmm, data);
+ }
+
+ w = tw;
+ h = th;
+ d = td;
+ mipmaps = tmm;
+ format = tfmt;
+
+ path_to_file = p_path;
+
+ if (get_path() == String()) {
+ //temporarily set path if no path set for resource, helps find errors
+ RenderingServer::get_singleton()->texture_set_path(texture, p_path);
+ }
+
+ _change_notify();
+ emit_changed();
+ return OK;
+}
+
+String StreamTexture3D::get_load_path() const {
+ return path_to_file;
+}
+
+int StreamTexture3D::get_width() const {
+ return w;
+}
+
+int StreamTexture3D::get_height() const {
+ return h;
+}
+
+int StreamTexture3D::get_depth() const {
+ return d;
+}
+
+bool StreamTexture3D::has_mipmaps() const {
+ return mipmaps;
+}
+
+RID StreamTexture3D::get_rid() const {
+ if (!texture.is_valid()) {
+ texture = RS::get_singleton()->texture_3d_placeholder_create();
+ }
+ return texture;
+}
+
+Vector<Ref<Image>> StreamTexture3D::get_data() const {
+ if (texture.is_valid()) {
+ return RS::get_singleton()->texture_3d_get(texture);
+ } else {
+ return Vector<Ref<Image>>();
+ }
+}
+
+void StreamTexture3D::reload_from_file() {
+ String path = get_path();
+ if (!path.is_resource_file()) {
+ return;
+ }
+
+ path = ResourceLoader::path_remap(path); //remap for translation
+ path = ResourceLoader::import_remap(path); //remap for import
+ if (!path.is_resource_file()) {
+ return;
+ }
+
+ load(path);
+}
+
+void StreamTexture3D::_validate_property(PropertyInfo &property) const {
+}
+
+void StreamTexture3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("load", "path"), &StreamTexture3D::load);
+ ClassDB::bind_method(D_METHOD("get_load_path"), &StreamTexture3D::get_load_path);
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path");
+}
+
+StreamTexture3D::StreamTexture3D() {
+ format = Image::FORMAT_MAX;
+ w = 0;
+ h = 0;
+ d = 0;
+ mipmaps = false;
+}
+
+StreamTexture3D::~StreamTexture3D() {
+ if (texture.is_valid()) {
+ RS::get_singleton()->free(texture);
+ }
+}
+
+/////////////////////////////
+
+RES ResourceFormatLoaderStreamTexture3D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+ Ref<StreamTexture3D> st;
+ st.instance();
+ Error err = st->load(p_path);
+ if (r_error) {
+ *r_error = err;
+ }
+ if (err != OK) {
+ return RES();
+ }
+
+ return st;
+}
+
+void ResourceFormatLoaderStreamTexture3D::get_recognized_extensions(List<String> *p_extensions) const {
+ p_extensions->push_back("stex3d");
+}
+
+bool ResourceFormatLoaderStreamTexture3D::handles_type(const String &p_type) const {
+ return p_type == "StreamTexture3D";
+}
+
+String ResourceFormatLoaderStreamTexture3D::get_resource_type(const String &p_path) const {
+ if (p_path.get_extension().to_lower() == "stex3d") {
+ return "StreamTexture3D";
+ }
+ return "";
+}
+
+////////////////////////////////////////////
+
int AtlasTexture::get_width() const {
if (region.size.width == 0) {
if (atlas.is_valid()) {
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index fd213859b7..eebbf4f233 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -515,6 +515,122 @@ public:
virtual String get_resource_type(const String &p_path) const;
};
+class Texture3D : public Texture {
+ GDCLASS(Texture3D, Texture);
+
+protected:
+ static void _bind_methods();
+
+ TypedArray<Image> _get_data() const;
+
+public:
+ virtual Image::Format get_format() const = 0;
+ virtual int get_width() const = 0;
+ virtual int get_height() const = 0;
+ virtual int get_depth() const = 0;
+ virtual bool has_mipmaps() const = 0;
+ virtual Vector<Ref<Image>> get_data() const = 0;
+};
+
+class ImageTexture3D : public Texture3D {
+ GDCLASS(ImageTexture3D, Texture3D);
+
+ mutable RID texture;
+
+ Image::Format format = Image::FORMAT_MAX;
+ int width = 1;
+ int height = 1;
+ int depth = 1;
+ bool mipmaps = false;
+
+protected:
+ static void _bind_methods();
+
+ Error _create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data);
+ void _update(const TypedArray<Image> &p_data);
+
+public:
+ virtual Image::Format get_format() const override;
+ virtual int get_width() const override;
+ virtual int get_height() const override;
+ virtual int get_depth() const override;
+ virtual bool has_mipmaps() const override;
+
+ Error create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data);
+ void update(const Vector<Ref<Image>> &p_data);
+ virtual Vector<Ref<Image>> get_data() const override;
+
+ virtual RID get_rid() const override;
+ virtual void set_path(const String &p_path, bool p_take_over = false) override;
+
+ ImageTexture3D();
+ ~ImageTexture3D();
+};
+
+class StreamTexture3D : public Texture3D {
+ GDCLASS(StreamTexture3D, Texture3D);
+
+public:
+ enum DataFormat {
+ DATA_FORMAT_IMAGE,
+ DATA_FORMAT_LOSSLESS,
+ DATA_FORMAT_LOSSY,
+ DATA_FORMAT_BASIS_UNIVERSAL,
+ };
+
+ enum {
+ FORMAT_VERSION = 1
+ };
+
+ enum FormatBits {
+ FORMAT_MASK_IMAGE_FORMAT = (1 << 20) - 1,
+ FORMAT_BIT_LOSSLESS = 1 << 20,
+ FORMAT_BIT_LOSSY = 1 << 21,
+ FORMAT_BIT_STREAM = 1 << 22,
+ FORMAT_BIT_HAS_MIPMAPS = 1 << 23,
+ };
+
+private:
+ Error _load_data(const String &p_path, Vector<Ref<Image>> &r_data, Image::Format &r_format, int &r_width, int &r_height, int &r_depth, bool &r_mipmaps);
+ String path_to_file;
+ mutable RID texture;
+ Image::Format format;
+ int w, h, d;
+ bool mipmaps;
+
+ virtual void reload_from_file() override;
+
+protected:
+ static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const override;
+
+public:
+ Image::Format get_format() const override;
+ Error load(const String &p_path);
+ String get_load_path() const;
+
+ int get_width() const override;
+ int get_height() const override;
+ int get_depth() const override;
+ virtual bool has_mipmaps() const override;
+ virtual RID get_rid() const override;
+
+ virtual void set_path(const String &p_path, bool p_take_over) override;
+
+ virtual Vector<Ref<Image>> get_data() const override;
+
+ StreamTexture3D();
+ ~StreamTexture3D();
+};
+
+class ResourceFormatLoaderStreamTexture3D : public ResourceFormatLoader {
+public:
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String &p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
class CurveTexture : public Texture2D {
GDCLASS(CurveTexture, Texture2D);
RES_BASE_EXTENSION("curvetex")