Add PropertyListHelper in all simple cases
This commit is contained in:
parent
b2f425fe68
commit
e95e954c68
|
@ -161,6 +161,10 @@ Vector<int> TileMap::_get_tile_map_data_using_compatibility_format(int p_layer)
|
||||||
return tile_data;
|
return tile_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TileMap::_set_layer_tile_data(int p_layer, const PackedInt32Array &p_data) {
|
||||||
|
_set_tile_map_data_using_compatibility_format(p_layer, format, p_data);
|
||||||
|
}
|
||||||
|
|
||||||
void TileMap::_notification(int p_what) {
|
void TileMap::_notification(int p_what) {
|
||||||
switch (p_what) {
|
switch (p_what) {
|
||||||
case TileMap::NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
|
case TileMap::NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
|
||||||
|
@ -741,41 +745,23 @@ Rect2 TileMap::_edit_get_rect() const {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
|
bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
|
int index;
|
||||||
|
const String sname = p_name;
|
||||||
|
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
Vector<String> components = String(p_name).split("/", true, 2);
|
||||||
if (p_name == "format") {
|
if (sname == "format") {
|
||||||
if (p_value.get_type() == Variant::INT) {
|
if (p_value.get_type() == Variant::INT) {
|
||||||
format = (TileMapDataFormat)(p_value.operator int64_t()); // Set format used for loading.
|
format = (TileMapDataFormat)(p_value.operator int64_t()); // Set format used for loading.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifndef DISABLE_DEPRECATED
|
#ifndef DISABLE_DEPRECATED
|
||||||
else if (p_name == "tile_data") { // Kept for compatibility reasons.
|
else if (sname == "cell_quadrant_size") {
|
||||||
if (p_value.is_array()) {
|
|
||||||
if (layers.size() == 0) {
|
|
||||||
TileMapLayer *new_layer = memnew(TileMapLayer);
|
|
||||||
add_child(new_layer, false, INTERNAL_MODE_FRONT);
|
|
||||||
new_layer->set_as_tile_map_internal_node(0);
|
|
||||||
new_layer->set_name("Layer0");
|
|
||||||
new_layer->set_tile_set(tile_set);
|
|
||||||
new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
|
|
||||||
layers.push_back(new_layer);
|
|
||||||
}
|
|
||||||
_set_tile_map_data_using_compatibility_format(0, format, p_value);
|
|
||||||
_emit_changed();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} else if (p_name == "cell_quadrant_size") {
|
|
||||||
set_rendering_quadrant_size(p_value);
|
set_rendering_quadrant_size(p_value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // DISABLE_DEPRECATED
|
#endif // DISABLE_DEPRECATED
|
||||||
else if (components.size() == 2 && components[0].begins_with("layer_") && components[0].trim_prefix("layer_").is_valid_int()) {
|
else if (property_helper.is_property_valid(sname, &index)) {
|
||||||
int index = components[0].trim_prefix("layer_").to_int();
|
|
||||||
if (index < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index >= (int)layers.size()) {
|
if (index >= (int)layers.size()) {
|
||||||
while (index >= (int)layers.size()) {
|
while (index >= (int)layers.size()) {
|
||||||
TileMapLayer *new_layer = memnew(TileMapLayer);
|
TileMapLayer *new_layer = memnew(TileMapLayer);
|
||||||
|
@ -792,172 +778,38 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
update_configuration_warnings();
|
update_configuration_warnings();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (components[1] == "name") {
|
if (property_helper.property_set_value(sname, p_value)) {
|
||||||
set_layer_name(index, p_value);
|
if (components[1] == "tile_data") {
|
||||||
|
_emit_changed();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (components[1] == "enabled") {
|
|
||||||
set_layer_enabled(index, p_value);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "modulate") {
|
|
||||||
set_layer_modulate(index, p_value);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "y_sort_enabled") {
|
|
||||||
set_layer_y_sort_enabled(index, p_value);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "y_sort_origin") {
|
|
||||||
set_layer_y_sort_origin(index, p_value);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "z_index") {
|
|
||||||
set_layer_z_index(index, p_value);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "navigation_enabled") {
|
|
||||||
set_layer_navigation_enabled(index, p_value);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "tile_data") {
|
|
||||||
_set_tile_map_data_using_compatibility_format(index, format, p_value);
|
|
||||||
_emit_changed();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TileMap::_get(const StringName &p_name, Variant &r_ret) const {
|
bool TileMap::_get(const StringName &p_name, Variant &r_ret) const {
|
||||||
|
const String sname = p_name;
|
||||||
|
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
Vector<String> components = String(p_name).split("/", true, 2);
|
||||||
if (p_name == "format") {
|
if (p_name == "format") {
|
||||||
r_ret = TileMapDataFormat::TILE_MAP_DATA_FORMAT_MAX - 1; // When saving, always save highest format.
|
r_ret = TileMapDataFormat::TILE_MAP_DATA_FORMAT_MAX - 1; // When saving, always save highest format.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#ifndef DISABLE_DEPRECATED
|
#ifndef DISABLE_DEPRECATED
|
||||||
else if (p_name == "cell_quadrant_size") { // Kept for compatibility reasons.
|
else if (sname == "cell_quadrant_size") { // Kept for compatibility reasons.
|
||||||
r_ret = get_rendering_quadrant_size();
|
r_ret = get_rendering_quadrant_size();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (components.size() == 2 && components[0].begins_with("layer_") && components[0].trim_prefix("layer_").is_valid_int()) {
|
else {
|
||||||
int index = components[0].trim_prefix("layer_").to_int();
|
return property_helper.property_get_value(sname, r_ret);
|
||||||
if (index < 0 || index >= (int)layers.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (components[1] == "name") {
|
|
||||||
r_ret = get_layer_name(index);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "enabled") {
|
|
||||||
r_ret = is_layer_enabled(index);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "modulate") {
|
|
||||||
r_ret = get_layer_modulate(index);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "y_sort_enabled") {
|
|
||||||
r_ret = is_layer_y_sort_enabled(index);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "y_sort_origin") {
|
|
||||||
r_ret = get_layer_y_sort_origin(index);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "z_index") {
|
|
||||||
r_ret = get_layer_z_index(index);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "navigation_enabled") {
|
|
||||||
r_ret = is_layer_navigation_enabled(index);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "tile_data") {
|
|
||||||
r_ret = _get_tile_map_data_using_compatibility_format(index);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileMap::_get_property_list(List<PropertyInfo> *p_list) const {
|
void TileMap::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||||
p_list->push_back(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
|
p_list->push_back(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
|
||||||
p_list->push_back(PropertyInfo(Variant::NIL, "Layers", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
|
property_helper.get_property_list(p_list, layers.size());
|
||||||
|
|
||||||
#define MAKE_LAYER_PROPERTY(m_type, m_name, m_hint) \
|
|
||||||
{ \
|
|
||||||
const String property_name = vformat("layer_%d/" m_name, i); \
|
|
||||||
p_list->push_back(PropertyInfo(m_type, property_name, PROPERTY_HINT_NONE, m_hint, (get(property_name) == property_get_revert(property_name)) ? PROPERTY_USAGE_EDITOR : PROPERTY_USAGE_DEFAULT)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < layers.size(); i++) {
|
|
||||||
MAKE_LAYER_PROPERTY(Variant::STRING, "name", "");
|
|
||||||
MAKE_LAYER_PROPERTY(Variant::BOOL, "enabled", "");
|
|
||||||
MAKE_LAYER_PROPERTY(Variant::COLOR, "modulate", "");
|
|
||||||
MAKE_LAYER_PROPERTY(Variant::BOOL, "y_sort_enabled", "");
|
|
||||||
MAKE_LAYER_PROPERTY(Variant::INT, "y_sort_origin", "suffix:px");
|
|
||||||
MAKE_LAYER_PROPERTY(Variant::INT, "z_index", "");
|
|
||||||
MAKE_LAYER_PROPERTY(Variant::BOOL, "navigation_enabled", "");
|
|
||||||
p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("layer_%d/tile_data", i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef MAKE_LAYER_PROPERTY
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TileMap::_property_can_revert(const StringName &p_name) const {
|
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
|
||||||
if (components.size() == 2 && components[0].begins_with("layer_")) {
|
|
||||||
int index = components[0].trim_prefix("layer_").to_int();
|
|
||||||
if (index <= 0 || index >= (int)layers.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (components[1] == "name") {
|
|
||||||
return layers[index]->get_name() != default_layer->get_name();
|
|
||||||
} else if (components[1] == "enabled") {
|
|
||||||
return layers[index]->is_enabled() != default_layer->is_enabled();
|
|
||||||
} else if (components[1] == "modulate") {
|
|
||||||
return layers[index]->get_modulate() != default_layer->get_modulate();
|
|
||||||
} else if (components[1] == "y_sort_enabled") {
|
|
||||||
return layers[index]->is_y_sort_enabled() != default_layer->is_y_sort_enabled();
|
|
||||||
} else if (components[1] == "y_sort_origin") {
|
|
||||||
return layers[index]->get_y_sort_origin() != default_layer->get_y_sort_origin();
|
|
||||||
} else if (components[1] == "z_index") {
|
|
||||||
return layers[index]->get_z_index() != default_layer->get_z_index();
|
|
||||||
} else if (components[1] == "navigation_enabled") {
|
|
||||||
return layers[index]->is_navigation_enabled() != default_layer->is_navigation_enabled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TileMap::_property_get_revert(const StringName &p_name, Variant &r_property) const {
|
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
|
||||||
if (components.size() == 2 && components[0].begins_with("layer_")) {
|
|
||||||
int index = components[0].trim_prefix("layer_").to_int();
|
|
||||||
if (index <= 0 || index >= (int)layers.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (components[1] == "name") {
|
|
||||||
r_property = default_layer->get_name();
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "enabled") {
|
|
||||||
r_property = default_layer->is_enabled();
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "modulate") {
|
|
||||||
r_property = default_layer->get_modulate();
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "y_sort_enabled") {
|
|
||||||
r_property = default_layer->is_y_sort_enabled();
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "y_sort_origin") {
|
|
||||||
r_property = default_layer->get_y_sort_origin();
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "z_index") {
|
|
||||||
r_property = default_layer->get_z_index();
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "navigation_enabled") {
|
|
||||||
r_property = default_layer->is_navigation_enabled();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 TileMap::map_to_local(const Vector2i &p_pos) const {
|
Vector2 TileMap::map_to_local(const Vector2i &p_pos) const {
|
||||||
|
@ -1215,11 +1067,26 @@ TileMap::TileMap() {
|
||||||
new_layer->set_tile_set(tile_set);
|
new_layer->set_tile_set(tile_set);
|
||||||
new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
|
new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
|
||||||
layers.push_back(new_layer);
|
layers.push_back(new_layer);
|
||||||
default_layer = memnew(TileMapLayer);
|
|
||||||
}
|
|
||||||
|
|
||||||
TileMap::~TileMap() {
|
if (!base_property_helper.is_initialized()) {
|
||||||
memdelete(default_layer);
|
// Initialize static PropertyListHelper if it wasn't yet. This has to be done here,
|
||||||
|
// because creating TileMapLayer in a static context is not always safe.
|
||||||
|
TileMapLayer *defaults = memnew(TileMapLayer);
|
||||||
|
|
||||||
|
base_property_helper.set_prefix("layer_");
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::STRING, "name"), defaults->get_name(), &TileMap::set_layer_name, &TileMap::get_layer_name);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "enabled"), defaults->is_enabled(), &TileMap::set_layer_enabled, &TileMap::is_layer_enabled);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::COLOR, "modulate"), defaults->get_modulate(), &TileMap::set_layer_modulate, &TileMap::get_layer_modulate);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "y_sort_enabled"), defaults->is_y_sort_enabled(), &TileMap::set_layer_y_sort_enabled, &TileMap::is_layer_y_sort_enabled);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::INT, "y_sort_origin", PROPERTY_HINT_NONE, "suffix:px"), defaults->get_y_sort_origin(), &TileMap::set_layer_y_sort_origin, &TileMap::get_layer_y_sort_origin);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::INT, "z_index"), defaults->get_z_index(), &TileMap::set_layer_z_index, &TileMap::get_layer_z_index);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "navigation_enabled"), defaults->is_navigation_enabled(), &TileMap::set_layer_navigation_enabled, &TileMap::is_layer_navigation_enabled);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::PACKED_INT32_ARRAY, "tile_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), Vector<int>(), &TileMap::_set_layer_tile_data, &TileMap::_get_tile_map_data_using_compatibility_format);
|
||||||
|
|
||||||
|
memdelete(defaults);
|
||||||
|
}
|
||||||
|
|
||||||
|
property_helper.setup_for_instance(base_property_helper, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef TILEMAP_CALL_FOR_LAYER
|
#undef TILEMAP_CALL_FOR_LAYER
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define TILE_MAP_H
|
#define TILE_MAP_H
|
||||||
|
|
||||||
#include "scene/2d/tile_map_layer.h"
|
#include "scene/2d/tile_map_layer.h"
|
||||||
|
#include "scene/property_list_helper.h"
|
||||||
#include "scene/resources/2d/tile_set.h"
|
#include "scene/resources/2d/tile_set.h"
|
||||||
|
|
||||||
class Control;
|
class Control;
|
||||||
|
@ -73,7 +74,9 @@ private:
|
||||||
|
|
||||||
// Layers.
|
// Layers.
|
||||||
LocalVector<TileMapLayer *> layers;
|
LocalVector<TileMapLayer *> layers;
|
||||||
TileMapLayer *default_layer; // Dummy layer to fetch default values.
|
|
||||||
|
static inline PropertyListHelper base_property_helper;
|
||||||
|
PropertyListHelper property_helper;
|
||||||
|
|
||||||
// Transforms for collision_animatable.
|
// Transforms for collision_animatable.
|
||||||
Transform2D last_valid_transform;
|
Transform2D last_valid_transform;
|
||||||
|
@ -86,13 +89,14 @@ private:
|
||||||
// Kept for compatibility with TileMap. With TileMapLayers as individual nodes, the format is stored directly in the array.
|
// Kept for compatibility with TileMap. With TileMapLayers as individual nodes, the format is stored directly in the array.
|
||||||
void _set_tile_map_data_using_compatibility_format(int p_layer, TileMapDataFormat p_format, const Vector<int> &p_data);
|
void _set_tile_map_data_using_compatibility_format(int p_layer, TileMapDataFormat p_format, const Vector<int> &p_data);
|
||||||
Vector<int> _get_tile_map_data_using_compatibility_format(int p_layer) const;
|
Vector<int> _get_tile_map_data_using_compatibility_format(int p_layer) const;
|
||||||
|
void _set_layer_tile_data(int p_layer, const PackedInt32Array &p_data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool _set(const StringName &p_name, const Variant &p_value);
|
bool _set(const StringName &p_name, const Variant &p_value);
|
||||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||||
bool _property_can_revert(const StringName &p_name) const;
|
bool _property_can_revert(const StringName &p_name) const { return property_helper.property_can_revert(p_name); }
|
||||||
bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
|
bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return property_helper.property_get_revert(p_name, r_property); }
|
||||||
|
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
@ -235,7 +239,6 @@ public:
|
||||||
PackedStringArray get_configuration_warnings() const override;
|
PackedStringArray get_configuration_warnings() const override;
|
||||||
|
|
||||||
TileMap();
|
TileMap();
|
||||||
~TileMap();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VARIANT_ENUM_CAST(TileMap::VisibilityMode);
|
VARIANT_ENUM_CAST(TileMap::VisibilityMode);
|
||||||
|
|
|
@ -1255,52 +1255,6 @@ int FileDialog::get_option_count() const {
|
||||||
return options.size();
|
return options.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileDialog::_set(const StringName &p_name, const Variant &p_value) {
|
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
|
||||||
if (components.size() >= 2 && components[0].begins_with("option_") && components[0].trim_prefix("option_").is_valid_int()) {
|
|
||||||
int item_index = components[0].trim_prefix("option_").to_int();
|
|
||||||
String property = components[1];
|
|
||||||
if (property == "name") {
|
|
||||||
set_option_name(item_index, p_value);
|
|
||||||
return true;
|
|
||||||
} else if (property == "values") {
|
|
||||||
set_option_values(item_index, p_value);
|
|
||||||
return true;
|
|
||||||
} else if (property == "default") {
|
|
||||||
set_option_default(item_index, p_value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileDialog::_get(const StringName &p_name, Variant &r_ret) const {
|
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
|
||||||
if (components.size() >= 2 && components[0].begins_with("option_") && components[0].trim_prefix("option_").is_valid_int()) {
|
|
||||||
int item_index = components[0].trim_prefix("option_").to_int();
|
|
||||||
String property = components[1];
|
|
||||||
if (property == "name") {
|
|
||||||
r_ret = get_option_name(item_index);
|
|
||||||
return true;
|
|
||||||
} else if (property == "values") {
|
|
||||||
r_ret = get_option_values(item_index);
|
|
||||||
return true;
|
|
||||||
} else if (property == "default") {
|
|
||||||
r_ret = get_option_default(item_index);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileDialog::_get_property_list(List<PropertyInfo> *p_list) const {
|
|
||||||
for (int i = 0; i < options.size(); i++) {
|
|
||||||
p_list->push_back(PropertyInfo(Variant::STRING, vformat("option_%d/name", i)));
|
|
||||||
p_list->push_back(PropertyInfo(Variant::PACKED_STRING_ARRAY, vformat("option_%d/values", i)));
|
|
||||||
p_list->push_back(PropertyInfo(Variant::INT, vformat("option_%d/default", i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileDialog::_bind_methods() {
|
void FileDialog::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("_cancel_pressed"), &FileDialog::_cancel_pressed);
|
ClassDB::bind_method(D_METHOD("_cancel_pressed"), &FileDialog::_cancel_pressed);
|
||||||
|
|
||||||
|
@ -1386,6 +1340,13 @@ void FileDialog::_bind_methods() {
|
||||||
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, FileDialog, icon_hover_color, "font_hover_color", "Button");
|
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, FileDialog, icon_hover_color, "font_hover_color", "Button");
|
||||||
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, FileDialog, icon_focus_color, "font_focus_color", "Button");
|
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, FileDialog, icon_focus_color, "font_focus_color", "Button");
|
||||||
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, FileDialog, icon_pressed_color, "font_pressed_color", "Button");
|
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, FileDialog, icon_pressed_color, "font_pressed_color", "Button");
|
||||||
|
|
||||||
|
Option defaults;
|
||||||
|
|
||||||
|
base_property_helper.set_prefix("option_");
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::STRING, "name"), defaults.name, &FileDialog::set_option_name, &FileDialog::get_option_name);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::PACKED_STRING_ARRAY, "values"), defaults.values, &FileDialog::set_option_values, &FileDialog::get_option_values);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::INT, "default"), defaults.default_idx, &FileDialog::set_option_default, &FileDialog::get_option_default);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileDialog::set_show_hidden_files(bool p_show) {
|
void FileDialog::set_show_hidden_files(bool p_show) {
|
||||||
|
@ -1563,6 +1524,8 @@ FileDialog::FileDialog() {
|
||||||
if (register_func) {
|
if (register_func) {
|
||||||
register_func(this);
|
register_func(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property_helper.setup_for_instance(base_property_helper, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileDialog::~FileDialog() {
|
FileDialog::~FileDialog() {
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "scene/gui/line_edit.h"
|
#include "scene/gui/line_edit.h"
|
||||||
#include "scene/gui/option_button.h"
|
#include "scene/gui/option_button.h"
|
||||||
#include "scene/gui/tree.h"
|
#include "scene/gui/tree.h"
|
||||||
|
#include "scene/property_list_helper.h"
|
||||||
|
|
||||||
class GridContainer;
|
class GridContainer;
|
||||||
|
|
||||||
|
@ -137,6 +138,10 @@ private:
|
||||||
Vector<String> values;
|
Vector<String> values;
|
||||||
int default_idx = 0;
|
int default_idx = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline PropertyListHelper base_property_helper;
|
||||||
|
PropertyListHelper property_helper;
|
||||||
|
|
||||||
Vector<Option> options;
|
Vector<Option> options;
|
||||||
Dictionary selected_options;
|
Dictionary selected_options;
|
||||||
bool options_dirty = false;
|
bool options_dirty = false;
|
||||||
|
@ -187,9 +192,11 @@ private:
|
||||||
protected:
|
protected:
|
||||||
void _validate_property(PropertyInfo &p_property) const;
|
void _validate_property(PropertyInfo &p_property) const;
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
bool _set(const StringName &p_name, const Variant &p_value);
|
bool _set(const StringName &p_name, const Variant &p_value) { return property_helper.property_set_value(p_name, p_value); }
|
||||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
bool _get(const StringName &p_name, Variant &r_ret) const { return property_helper.property_get_value(p_name, r_ret); }
|
||||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
void _get_property_list(List<PropertyInfo> *p_list) const { property_helper.get_property_list(p_list, options.size()); }
|
||||||
|
bool _property_can_revert(const StringName &p_name) const { return property_helper.property_can_revert(p_name); }
|
||||||
|
bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return property_helper.property_get_revert(p_name, r_property); }
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -153,54 +153,25 @@ void MenuButton::_notification(int p_what) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MenuButton::_set(const StringName &p_name, const Variant &p_value) {
|
bool MenuButton::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
const String sname = p_name;
|
||||||
if (components.size() >= 2 && components[0] == "popup") {
|
if (property_helper.is_property_valid(sname)) {
|
||||||
bool valid;
|
bool valid;
|
||||||
popup->set(String(p_name).trim_prefix("popup/"), p_value, &valid);
|
popup->set(sname.trim_prefix("popup/"), p_value, &valid);
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MenuButton::_get(const StringName &p_name, Variant &r_ret) const {
|
bool MenuButton::_get(const StringName &p_name, Variant &r_ret) const {
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
const String sname = p_name;
|
||||||
if (components.size() >= 2 && components[0] == "popup") {
|
if (property_helper.is_property_valid(sname)) {
|
||||||
bool valid;
|
bool valid;
|
||||||
r_ret = popup->get(String(p_name).trim_prefix("popup/"), &valid);
|
r_ret = popup->get(sname.trim_prefix("popup/"), &valid);
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuButton::_get_property_list(List<PropertyInfo> *p_list) const {
|
|
||||||
for (int i = 0; i < popup->get_item_count(); i++) {
|
|
||||||
p_list->push_back(PropertyInfo(Variant::STRING, vformat("popup/item_%d/text", i)));
|
|
||||||
|
|
||||||
PropertyInfo pi = PropertyInfo(Variant::OBJECT, vformat("popup/item_%d/icon", i), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D");
|
|
||||||
pi.usage &= ~(popup->get_item_icon(i).is_null() ? PROPERTY_USAGE_STORAGE : 0);
|
|
||||||
p_list->push_back(pi);
|
|
||||||
|
|
||||||
pi = PropertyInfo(Variant::INT, vformat("popup/item_%d/checkable", i), PROPERTY_HINT_ENUM, "No,As Checkbox,As Radio Button");
|
|
||||||
pi.usage &= ~(!popup->is_item_checkable(i) ? PROPERTY_USAGE_STORAGE : 0);
|
|
||||||
p_list->push_back(pi);
|
|
||||||
|
|
||||||
pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/checked", i));
|
|
||||||
pi.usage &= ~(!popup->is_item_checked(i) ? PROPERTY_USAGE_STORAGE : 0);
|
|
||||||
p_list->push_back(pi);
|
|
||||||
|
|
||||||
pi = PropertyInfo(Variant::INT, vformat("popup/item_%d/id", i), PROPERTY_HINT_RANGE, "0,10,1,or_greater");
|
|
||||||
p_list->push_back(pi);
|
|
||||||
|
|
||||||
pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/disabled", i));
|
|
||||||
pi.usage &= ~(!popup->is_item_disabled(i) ? PROPERTY_USAGE_STORAGE : 0);
|
|
||||||
p_list->push_back(pi);
|
|
||||||
|
|
||||||
pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/separator", i));
|
|
||||||
pi.usage &= ~(!popup->is_item_separator(i) ? PROPERTY_USAGE_STORAGE : 0);
|
|
||||||
p_list->push_back(pi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuButton::_bind_methods() {
|
void MenuButton::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_popup"), &MenuButton::get_popup);
|
ClassDB::bind_method(D_METHOD("get_popup"), &MenuButton::get_popup);
|
||||||
ClassDB::bind_method(D_METHOD("show_popup"), &MenuButton::show_popup);
|
ClassDB::bind_method(D_METHOD("show_popup"), &MenuButton::show_popup);
|
||||||
|
@ -215,6 +186,17 @@ void MenuButton::_bind_methods() {
|
||||||
ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "popup/item_");
|
ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "popup/item_");
|
||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("about_to_popup"));
|
ADD_SIGNAL(MethodInfo("about_to_popup"));
|
||||||
|
|
||||||
|
PopupMenu::Item defaults(true);
|
||||||
|
|
||||||
|
base_property_helper.set_prefix("popup/item_");
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::STRING, "text"), defaults.text);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), defaults.icon);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::INT, "checkable", PROPERTY_HINT_ENUM, "No,As Checkbox,As Radio Button"), defaults.checkable_type);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "checked"), defaults.checked);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0,10,1,or_greater"), defaults.id);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "disabled"), defaults.disabled);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "separator"), defaults.separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuButton::set_disable_shortcuts(bool p_disabled) {
|
void MenuButton::set_disable_shortcuts(bool p_disabled) {
|
||||||
|
@ -235,6 +217,8 @@ MenuButton::MenuButton(const String &p_text) :
|
||||||
add_child(popup, false, INTERNAL_MODE_FRONT);
|
add_child(popup, false, INTERNAL_MODE_FRONT);
|
||||||
popup->connect("about_to_popup", callable_mp(this, &MenuButton::_popup_visibility_changed).bind(true));
|
popup->connect("about_to_popup", callable_mp(this, &MenuButton::_popup_visibility_changed).bind(true));
|
||||||
popup->connect("popup_hide", callable_mp(this, &MenuButton::_popup_visibility_changed).bind(false));
|
popup->connect("popup_hide", callable_mp(this, &MenuButton::_popup_visibility_changed).bind(false));
|
||||||
|
|
||||||
|
property_helper.setup_for_instance(base_property_helper, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuButton::~MenuButton() {
|
MenuButton::~MenuButton() {
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include "scene/gui/button.h"
|
#include "scene/gui/button.h"
|
||||||
#include "scene/gui/popup_menu.h"
|
#include "scene/gui/popup_menu.h"
|
||||||
|
#include "scene/property_list_helper.h"
|
||||||
|
|
||||||
class MenuButton : public Button {
|
class MenuButton : public Button {
|
||||||
GDCLASS(MenuButton, Button);
|
GDCLASS(MenuButton, Button);
|
||||||
|
@ -42,13 +43,18 @@ class MenuButton : public Button {
|
||||||
bool disable_shortcuts = false;
|
bool disable_shortcuts = false;
|
||||||
PopupMenu *popup = nullptr;
|
PopupMenu *popup = nullptr;
|
||||||
|
|
||||||
|
static inline PropertyListHelper base_property_helper;
|
||||||
|
PropertyListHelper property_helper;
|
||||||
|
|
||||||
void _popup_visibility_changed(bool p_visible);
|
void _popup_visibility_changed(bool p_visible);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
bool _set(const StringName &p_name, const Variant &p_value);
|
bool _set(const StringName &p_name, const Variant &p_value);
|
||||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
void _get_property_list(List<PropertyInfo> *p_list) const { property_helper.get_property_list(p_list, popup->get_item_count()); }
|
||||||
|
bool _property_can_revert(const StringName &p_name) const { return property_helper.property_can_revert(p_name); }
|
||||||
|
bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return property_helper.property_get_revert(p_name, r_property); }
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
|
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
|
||||||
|
|
||||||
|
|
|
@ -154,23 +154,20 @@ void OptionButton::_notification(int p_what) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OptionButton::_set(const StringName &p_name, const Variant &p_value) {
|
bool OptionButton::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
int index;
|
||||||
if (components.size() >= 2 && components[0] == "popup") {
|
const String sname = p_name;
|
||||||
const String &property = components[2];
|
|
||||||
if (property != "text" && property != "icon" && property != "id" && property != "disabled" && property != "separator") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (property_helper.is_property_valid(sname, &index)) {
|
||||||
bool valid;
|
bool valid;
|
||||||
popup->set(String(p_name).trim_prefix("popup/"), p_value, &valid);
|
popup->set(sname.trim_prefix("popup/"), p_value, &valid);
|
||||||
|
|
||||||
int idx = components[1].get_slice("_", 1).to_int();
|
if (index == current) {
|
||||||
if (idx == current) {
|
|
||||||
// Force refreshing currently displayed item.
|
// Force refreshing currently displayed item.
|
||||||
current = NONE_SELECTED;
|
current = NONE_SELECTED;
|
||||||
_select(idx, false);
|
_select(index, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const String property = sname.get_slice("/", 2);
|
||||||
if (property == "text" || property == "icon") {
|
if (property == "text" || property == "icon") {
|
||||||
_queue_update_size_cache();
|
_queue_update_size_cache();
|
||||||
}
|
}
|
||||||
|
@ -180,42 +177,6 @@ bool OptionButton::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OptionButton::_get(const StringName &p_name, Variant &r_ret) const {
|
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
|
||||||
if (components.size() >= 2 && components[0] == "popup") {
|
|
||||||
const String &property = components[2];
|
|
||||||
if (property != "text" && property != "icon" && property != "id" && property != "disabled" && property != "separator") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool valid;
|
|
||||||
r_ret = popup->get(String(p_name).trim_prefix("popup/"), &valid);
|
|
||||||
return valid;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OptionButton::_get_property_list(List<PropertyInfo> *p_list) const {
|
|
||||||
for (int i = 0; i < popup->get_item_count(); i++) {
|
|
||||||
p_list->push_back(PropertyInfo(Variant::STRING, vformat("popup/item_%d/text", i)));
|
|
||||||
|
|
||||||
PropertyInfo pi = PropertyInfo(Variant::OBJECT, vformat("popup/item_%d/icon", i), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D");
|
|
||||||
pi.usage &= ~(popup->get_item_icon(i).is_null() ? PROPERTY_USAGE_STORAGE : 0);
|
|
||||||
p_list->push_back(pi);
|
|
||||||
|
|
||||||
pi = PropertyInfo(Variant::INT, vformat("popup/item_%d/id", i), PROPERTY_HINT_RANGE, "0,10,1,or_greater");
|
|
||||||
p_list->push_back(pi);
|
|
||||||
|
|
||||||
pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/disabled", i));
|
|
||||||
pi.usage &= ~(!popup->is_item_disabled(i) ? PROPERTY_USAGE_STORAGE : 0);
|
|
||||||
p_list->push_back(pi);
|
|
||||||
|
|
||||||
pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/separator", i));
|
|
||||||
pi.usage &= ~(!popup->is_item_separator(i) ? PROPERTY_USAGE_STORAGE : 0);
|
|
||||||
p_list->push_back(pi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OptionButton::_focused(int p_which) {
|
void OptionButton::_focused(int p_which) {
|
||||||
emit_signal(SNAME("item_focused"), p_which);
|
emit_signal(SNAME("item_focused"), p_which);
|
||||||
}
|
}
|
||||||
|
@ -606,6 +567,15 @@ void OptionButton::_bind_methods() {
|
||||||
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, OptionButton, arrow_icon, "arrow");
|
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, OptionButton, arrow_icon, "arrow");
|
||||||
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, OptionButton, arrow_margin);
|
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, OptionButton, arrow_margin);
|
||||||
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, OptionButton, modulate_arrow);
|
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, OptionButton, modulate_arrow);
|
||||||
|
|
||||||
|
PopupMenu::Item defaults(true);
|
||||||
|
|
||||||
|
base_property_helper.set_prefix("popup/item_");
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::STRING, "text"), defaults.text, &OptionButton::_dummy_setter, &OptionButton::get_item_text);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), defaults.icon, &OptionButton::_dummy_setter, &OptionButton::get_item_icon);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0,10,1,or_greater"), defaults.id, &OptionButton::_dummy_setter, &OptionButton::get_item_id);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "disabled"), defaults.disabled, &OptionButton::_dummy_setter, &OptionButton::is_item_disabled);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "separator"), defaults.separator, &OptionButton::_dummy_setter, &OptionButton::is_item_separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptionButton::set_disable_shortcuts(bool p_disabled) {
|
void OptionButton::set_disable_shortcuts(bool p_disabled) {
|
||||||
|
@ -625,6 +595,8 @@ OptionButton::OptionButton(const String &p_text) :
|
||||||
popup->connect("index_pressed", callable_mp(this, &OptionButton::_selected));
|
popup->connect("index_pressed", callable_mp(this, &OptionButton::_selected));
|
||||||
popup->connect("id_focused", callable_mp(this, &OptionButton::_focused));
|
popup->connect("id_focused", callable_mp(this, &OptionButton::_focused));
|
||||||
popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed).bind(false));
|
popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed).bind(false));
|
||||||
|
|
||||||
|
property_helper.setup_for_instance(base_property_helper, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionButton::~OptionButton() {
|
OptionButton::~OptionButton() {
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include "scene/gui/button.h"
|
#include "scene/gui/button.h"
|
||||||
#include "scene/gui/popup_menu.h"
|
#include "scene/gui/popup_menu.h"
|
||||||
|
#include "scene/property_list_helper.h"
|
||||||
|
|
||||||
class OptionButton : public Button {
|
class OptionButton : public Button {
|
||||||
GDCLASS(OptionButton, Button);
|
GDCLASS(OptionButton, Button);
|
||||||
|
@ -64,11 +65,15 @@ class OptionButton : public Button {
|
||||||
int modulate_arrow = 0;
|
int modulate_arrow = 0;
|
||||||
} theme_cache;
|
} theme_cache;
|
||||||
|
|
||||||
|
static inline PropertyListHelper base_property_helper;
|
||||||
|
PropertyListHelper property_helper;
|
||||||
|
|
||||||
void _focused(int p_which);
|
void _focused(int p_which);
|
||||||
void _selected(int p_which);
|
void _selected(int p_which);
|
||||||
void _select(int p_which, bool p_emit = false);
|
void _select(int p_which, bool p_emit = false);
|
||||||
void _select_int(int p_which);
|
void _select_int(int p_which);
|
||||||
void _refresh_size_cache();
|
void _refresh_size_cache();
|
||||||
|
void _dummy_setter() {} // Stub for PropertyListHelper (_set() doesn't use it).
|
||||||
|
|
||||||
virtual void pressed() override;
|
virtual void pressed() override;
|
||||||
|
|
||||||
|
@ -78,8 +83,10 @@ protected:
|
||||||
|
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
bool _set(const StringName &p_name, const Variant &p_value);
|
bool _set(const StringName &p_name, const Variant &p_value);
|
||||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
bool _get(const StringName &p_name, Variant &r_ret) const { return property_helper.property_get_value(p_name, r_ret); }
|
||||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
void _get_property_list(List<PropertyInfo> *p_list) const { property_helper.get_property_list(p_list, popup->get_item_count()); }
|
||||||
|
bool _property_can_revert(const StringName &p_name) const { return property_helper.property_can_revert(p_name); }
|
||||||
|
bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return property_helper.property_get_revert(p_name, r_property); }
|
||||||
void _validate_property(PropertyInfo &p_property) const;
|
void _validate_property(PropertyInfo &p_property) const;
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,10 @@ class PopupMenu : public Popup {
|
||||||
static inline PropertyListHelper base_property_helper;
|
static inline PropertyListHelper base_property_helper;
|
||||||
PropertyListHelper property_helper;
|
PropertyListHelper property_helper;
|
||||||
|
|
||||||
|
// To make Item available.
|
||||||
|
friend class OptionButton;
|
||||||
|
friend class MenuButton;
|
||||||
|
|
||||||
RID global_menu;
|
RID global_menu;
|
||||||
RID system_menu;
|
RID system_menu;
|
||||||
NativeMenu::SystemMenus system_menu_id = NativeMenu::INVALID_MENU_ID;
|
NativeMenu::SystemMenus system_menu_id = NativeMenu::INVALID_MENU_ID;
|
||||||
|
|
|
@ -1720,58 +1720,6 @@ bool TabBar::get_deselect_enabled() const {
|
||||||
return deselect_enabled;
|
return deselect_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TabBar::_set(const StringName &p_name, const Variant &p_value) {
|
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
|
||||||
if (components.size() >= 2 && components[0].begins_with("tab_") && components[0].trim_prefix("tab_").is_valid_int()) {
|
|
||||||
int tab_index = components[0].trim_prefix("tab_").to_int();
|
|
||||||
const String &property = components[1];
|
|
||||||
if (property == "title") {
|
|
||||||
set_tab_title(tab_index, p_value);
|
|
||||||
return true;
|
|
||||||
} else if (property == "icon") {
|
|
||||||
set_tab_icon(tab_index, p_value);
|
|
||||||
return true;
|
|
||||||
} else if (property == "disabled") {
|
|
||||||
set_tab_disabled(tab_index, p_value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TabBar::_get(const StringName &p_name, Variant &r_ret) const {
|
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
|
||||||
if (components.size() >= 2 && components[0].begins_with("tab_") && components[0].trim_prefix("tab_").is_valid_int()) {
|
|
||||||
int tab_index = components[0].trim_prefix("tab_").to_int();
|
|
||||||
const String &property = components[1];
|
|
||||||
if (property == "title") {
|
|
||||||
r_ret = get_tab_title(tab_index);
|
|
||||||
return true;
|
|
||||||
} else if (property == "icon") {
|
|
||||||
r_ret = get_tab_icon(tab_index);
|
|
||||||
return true;
|
|
||||||
} else if (property == "disabled") {
|
|
||||||
r_ret = is_tab_disabled(tab_index);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabBar::_get_property_list(List<PropertyInfo> *p_list) const {
|
|
||||||
for (int i = 0; i < tabs.size(); i++) {
|
|
||||||
p_list->push_back(PropertyInfo(Variant::STRING, vformat("tab_%d/title", i)));
|
|
||||||
|
|
||||||
PropertyInfo pi = PropertyInfo(Variant::OBJECT, vformat("tab_%d/icon", i), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D");
|
|
||||||
pi.usage &= ~(get_tab_icon(i).is_null() ? PROPERTY_USAGE_STORAGE : 0);
|
|
||||||
p_list->push_back(pi);
|
|
||||||
|
|
||||||
pi = PropertyInfo(Variant::BOOL, vformat("tab_%d/disabled", i));
|
|
||||||
pi.usage &= ~(!is_tab_disabled(i) ? PROPERTY_USAGE_STORAGE : 0);
|
|
||||||
p_list->push_back(pi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabBar::_bind_methods() {
|
void TabBar::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_tab_count", "count"), &TabBar::set_tab_count);
|
ClassDB::bind_method(D_METHOD("set_tab_count", "count"), &TabBar::set_tab_count);
|
||||||
ClassDB::bind_method(D_METHOD("get_tab_count"), &TabBar::get_tab_count);
|
ClassDB::bind_method(D_METHOD("get_tab_count"), &TabBar::get_tab_count);
|
||||||
|
@ -1890,10 +1838,19 @@ void TabBar::_bind_methods() {
|
||||||
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabBar, close_icon, "close");
|
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabBar, close_icon, "close");
|
||||||
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, button_pressed_style, "button_pressed");
|
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, button_pressed_style, "button_pressed");
|
||||||
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, button_hl_style, "button_highlight");
|
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, button_hl_style, "button_highlight");
|
||||||
|
|
||||||
|
Tab defaults(true);
|
||||||
|
|
||||||
|
base_property_helper.set_prefix("tab_");
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::STRING, "title"), defaults.text, &TabBar::set_tab_title, &TabBar::get_tab_title);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), defaults.icon, &TabBar::set_tab_icon, &TabBar::get_tab_icon);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "disabled"), defaults.disabled, &TabBar::set_tab_disabled, &TabBar::is_tab_disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
TabBar::TabBar() {
|
TabBar::TabBar() {
|
||||||
set_size(Size2(get_size().width, get_minimum_size().height));
|
set_size(Size2(get_size().width, get_minimum_size().height));
|
||||||
set_focus_mode(FOCUS_ALL);
|
set_focus_mode(FOCUS_ALL);
|
||||||
connect("mouse_exited", callable_mp(this, &TabBar::_on_mouse_exited));
|
connect("mouse_exited", callable_mp(this, &TabBar::_on_mouse_exited));
|
||||||
|
|
||||||
|
property_helper.setup_for_instance(base_property_helper, this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define TAB_BAR_H
|
#define TAB_BAR_H
|
||||||
|
|
||||||
#include "scene/gui/control.h"
|
#include "scene/gui/control.h"
|
||||||
|
#include "scene/property_list_helper.h"
|
||||||
#include "scene/resources/text_line.h"
|
#include "scene/resources/text_line.h"
|
||||||
|
|
||||||
class TabBar : public Control {
|
class TabBar : public Control {
|
||||||
|
@ -77,8 +78,13 @@ private:
|
||||||
Tab() {
|
Tab() {
|
||||||
text_buf.instantiate();
|
text_buf.instantiate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tab(bool p_dummy) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline PropertyListHelper base_property_helper;
|
||||||
|
PropertyListHelper property_helper;
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int max_drawn_tab = 0;
|
int max_drawn_tab = 0;
|
||||||
int highlight_arrow = -1;
|
int highlight_arrow = -1;
|
||||||
|
@ -163,9 +169,11 @@ private:
|
||||||
protected:
|
protected:
|
||||||
virtual void gui_input(const Ref<InputEvent> &p_event) override;
|
virtual void gui_input(const Ref<InputEvent> &p_event) override;
|
||||||
|
|
||||||
bool _set(const StringName &p_name, const Variant &p_value);
|
bool _set(const StringName &p_name, const Variant &p_value) { return property_helper.property_set_value(p_name, p_value); }
|
||||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
bool _get(const StringName &p_name, Variant &r_ret) const { return property_helper.property_get_value(p_name, r_ret); }
|
||||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
void _get_property_list(List<PropertyInfo> *p_list) const { property_helper.get_property_list(p_list, tabs.size()); }
|
||||||
|
bool _property_can_revert(const StringName &p_name) const { return property_helper.property_can_revert(p_name); }
|
||||||
|
bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return property_helper.property_get_revert(p_name, r_property); }
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#include "property_list_helper.h"
|
#include "property_list_helper.h"
|
||||||
|
|
||||||
const PropertyListHelper::Property *PropertyListHelper::_get_property(const String &p_property, int *r_index) const {
|
const PropertyListHelper::Property *PropertyListHelper::_get_property(const String &p_property, int *r_index) const {
|
||||||
const Vector<String> components = p_property.split("/", true, 2);
|
const Vector<String> components = p_property.rsplit("/", true, 1);
|
||||||
if (components.size() < 2 || !components[0].begins_with(prefix)) {
|
if (components.size() < 2 || !components[0].begins_with(prefix)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -48,36 +48,73 @@ const PropertyListHelper::Property *PropertyListHelper::_get_property(const Stri
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyListHelper::_call_setter(const MethodBind *p_setter, int p_index, const Variant &p_value) const {
|
void PropertyListHelper::_call_setter(const MethodBind *p_setter, int p_index, const Variant &p_value) const {
|
||||||
|
DEV_ASSERT(p_setter);
|
||||||
Variant args[] = { p_index, p_value };
|
Variant args[] = { p_index, p_value };
|
||||||
const Variant *argptrs[] = { &args[0], &args[1] };
|
const Variant *argptrs[] = { &args[0], &args[1] };
|
||||||
Callable::CallError ce;
|
Callable::CallError ce;
|
||||||
p_setter->call(object, argptrs, 2, ce);
|
p_setter->call(object, argptrs, 2, ce);
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant PropertyListHelper::_call_getter(const MethodBind *p_getter, int p_index) const {
|
Variant PropertyListHelper::_call_getter(const Property *p_property, int p_index) const {
|
||||||
|
if (!p_property->getter) {
|
||||||
|
return object->get(prefix + itos(p_index) + "/" + p_property->info.name);
|
||||||
|
}
|
||||||
|
|
||||||
Callable::CallError ce;
|
Callable::CallError ce;
|
||||||
Variant args[] = { p_index };
|
Variant args[] = { p_index };
|
||||||
const Variant *argptrs[] = { &args[0] };
|
const Variant *argptrs[] = { &args[0] };
|
||||||
return p_getter->call(object, argptrs, 1, ce);
|
return p_property->getter->call(object, argptrs, 1, ce);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyListHelper::set_prefix(const String &p_prefix) {
|
void PropertyListHelper::set_prefix(const String &p_prefix) {
|
||||||
prefix = p_prefix;
|
prefix = p_prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PropertyListHelper::register_property(const PropertyInfo &p_info, const Variant &p_default) {
|
||||||
|
Property property;
|
||||||
|
property.info = p_info;
|
||||||
|
property.default_value = p_default;
|
||||||
|
|
||||||
|
property_list[p_info.name] = property;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PropertyListHelper::is_initialized() const {
|
||||||
|
return !property_list.is_empty();
|
||||||
|
}
|
||||||
|
|
||||||
void PropertyListHelper::setup_for_instance(const PropertyListHelper &p_base, Object *p_object) {
|
void PropertyListHelper::setup_for_instance(const PropertyListHelper &p_base, Object *p_object) {
|
||||||
prefix = p_base.prefix;
|
prefix = p_base.prefix;
|
||||||
property_list = p_base.property_list;
|
property_list = p_base.property_list;
|
||||||
object = p_object;
|
object = p_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PropertyListHelper::is_property_valid(const String &p_property, int *r_index) const {
|
||||||
|
const Vector<String> components = p_property.rsplit("/", true, 1);
|
||||||
|
if (components.size() < 2 || !components[0].begins_with(prefix)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const String index_string = components[0].trim_prefix(prefix);
|
||||||
|
if (!index_string.is_valid_int()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_index) {
|
||||||
|
*r_index = index_string.to_int();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return property_list.has(components[1]);
|
||||||
|
}
|
||||||
|
|
||||||
void PropertyListHelper::get_property_list(List<PropertyInfo> *p_list, int p_count) const {
|
void PropertyListHelper::get_property_list(List<PropertyInfo> *p_list, int p_count) const {
|
||||||
for (int i = 0; i < p_count; i++) {
|
for (int i = 0; i < p_count; i++) {
|
||||||
for (const KeyValue<String, Property> &E : property_list) {
|
for (const KeyValue<String, Property> &E : property_list) {
|
||||||
const Property &property = E.value;
|
const Property &property = E.value;
|
||||||
|
|
||||||
PropertyInfo info = property.info;
|
PropertyInfo info = property.info;
|
||||||
if (_call_getter(property.getter, i) == property.default_value) {
|
if (_call_getter(&property, i) == property.default_value) {
|
||||||
info.usage &= (~PROPERTY_USAGE_STORAGE);
|
info.usage &= (~PROPERTY_USAGE_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +129,7 @@ bool PropertyListHelper::property_get_value(const String &p_property, Variant &r
|
||||||
const Property *property = _get_property(p_property, &index);
|
const Property *property = _get_property(p_property, &index);
|
||||||
|
|
||||||
if (property) {
|
if (property) {
|
||||||
r_ret = _call_getter(property->getter, index);
|
r_ret = _call_getter(property, index);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -110,8 +147,7 @@ bool PropertyListHelper::property_set_value(const String &p_property, const Vari
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PropertyListHelper::property_can_revert(const String &p_property) const {
|
bool PropertyListHelper::property_can_revert(const String &p_property) const {
|
||||||
int index;
|
return is_property_valid(p_property);
|
||||||
return _get_property(p_property, &index) != nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PropertyListHelper::property_get_revert(const String &p_property, Variant &r_value) const {
|
bool PropertyListHelper::property_get_revert(const String &p_property, Variant &r_value) const {
|
||||||
|
@ -129,8 +165,10 @@ PropertyListHelper::~PropertyListHelper() {
|
||||||
// No object = it's the main helper. Do a cleanup.
|
// No object = it's the main helper. Do a cleanup.
|
||||||
if (!object) {
|
if (!object) {
|
||||||
for (const KeyValue<String, Property> &E : property_list) {
|
for (const KeyValue<String, Property> &E : property_list) {
|
||||||
memdelete(E.value.setter);
|
if (E.value.setter) {
|
||||||
memdelete(E.value.getter);
|
memdelete(E.value.setter);
|
||||||
|
memdelete(E.value.getter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,10 +48,12 @@ class PropertyListHelper {
|
||||||
|
|
||||||
const Property *_get_property(const String &p_property, int *r_index) const;
|
const Property *_get_property(const String &p_property, int *r_index) const;
|
||||||
void _call_setter(const MethodBind *p_setter, int p_index, const Variant &p_value) const;
|
void _call_setter(const MethodBind *p_setter, int p_index, const Variant &p_value) const;
|
||||||
Variant _call_getter(const MethodBind *p_getter, int p_index) const;
|
Variant _call_getter(const Property *p_property, int p_index) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void set_prefix(const String &p_prefix);
|
void set_prefix(const String &p_prefix);
|
||||||
|
// Register property without setter/getter. Only use when you don't need PropertyListHelper for _set/_get logic.
|
||||||
|
void register_property(const PropertyInfo &p_info, const Variant &p_default);
|
||||||
|
|
||||||
template <typename S, typename G>
|
template <typename S, typename G>
|
||||||
void register_property(const PropertyInfo &p_info, const Variant &p_default, S p_setter, G p_getter) {
|
void register_property(const PropertyInfo &p_info, const Variant &p_default, S p_setter, G p_getter) {
|
||||||
|
@ -64,7 +66,9 @@ public:
|
||||||
property_list[p_info.name] = property;
|
property_list[p_info.name] = property;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_initialized() const;
|
||||||
void setup_for_instance(const PropertyListHelper &p_base, Object *p_object);
|
void setup_for_instance(const PropertyListHelper &p_base, Object *p_object);
|
||||||
|
bool is_property_valid(const String &p_property, int *r_index = nullptr) const;
|
||||||
|
|
||||||
void get_property_list(List<PropertyInfo> *p_list, int p_count) const;
|
void get_property_list(List<PropertyInfo> *p_list, int p_count) const;
|
||||||
bool property_get_value(const String &p_property, Variant &r_ret) const;
|
bool property_get_value(const String &p_property, Variant &r_ret) const;
|
||||||
|
|
|
@ -676,63 +676,6 @@ bool AudioStreamRandomizer::is_monophonic() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AudioStreamRandomizer::_get(const StringName &p_name, Variant &r_ret) const {
|
|
||||||
if (AudioStream::_get(p_name, r_ret)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
|
||||||
if (components.size() == 2 && components[0].begins_with("stream_") && components[0].trim_prefix("stream_").is_valid_int()) {
|
|
||||||
int index = components[0].trim_prefix("stream_").to_int();
|
|
||||||
if (index < 0 || index >= (int)audio_stream_pool.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (components[1] == "stream") {
|
|
||||||
r_ret = get_stream(index);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "weight") {
|
|
||||||
r_ret = get_stream_probability_weight(index);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AudioStreamRandomizer::_set(const StringName &p_name, const Variant &p_value) {
|
|
||||||
if (AudioStream::_set(p_name, p_value)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Vector<String> components = String(p_name).split("/", true, 2);
|
|
||||||
if (components.size() == 2 && components[0].begins_with("stream_") && components[0].trim_prefix("stream_").is_valid_int()) {
|
|
||||||
int index = components[0].trim_prefix("stream_").to_int();
|
|
||||||
if (index < 0 || index >= (int)audio_stream_pool.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (components[1] == "stream") {
|
|
||||||
set_stream(index, p_value);
|
|
||||||
return true;
|
|
||||||
} else if (components[1] == "weight") {
|
|
||||||
set_stream_probability_weight(index, p_value);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioStreamRandomizer::_get_property_list(List<PropertyInfo> *p_list) const {
|
|
||||||
AudioStream::_get_property_list(p_list); // Define the trivial scalar properties.
|
|
||||||
p_list->push_back(PropertyInfo(Variant::NIL, "Streams", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
|
|
||||||
for (int i = 0; i < audio_stream_pool.size(); i++) {
|
|
||||||
p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("stream_%d/stream", i), PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"));
|
|
||||||
p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("stream_%d/weight", i), PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioStreamRandomizer::_bind_methods() {
|
void AudioStreamRandomizer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("add_stream", "index", "stream", "weight"), &AudioStreamRandomizer::add_stream, DEFVAL(1.0));
|
ClassDB::bind_method(D_METHOD("add_stream", "index", "stream", "weight"), &AudioStreamRandomizer::add_stream, DEFVAL(1.0));
|
||||||
ClassDB::bind_method(D_METHOD("move_stream", "index_from", "index_to"), &AudioStreamRandomizer::move_stream);
|
ClassDB::bind_method(D_METHOD("move_stream", "index_from", "index_to"), &AudioStreamRandomizer::move_stream);
|
||||||
|
@ -764,9 +707,17 @@ void AudioStreamRandomizer::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(PLAYBACK_RANDOM_NO_REPEATS);
|
BIND_ENUM_CONSTANT(PLAYBACK_RANDOM_NO_REPEATS);
|
||||||
BIND_ENUM_CONSTANT(PLAYBACK_RANDOM);
|
BIND_ENUM_CONSTANT(PLAYBACK_RANDOM);
|
||||||
BIND_ENUM_CONSTANT(PLAYBACK_SEQUENTIAL);
|
BIND_ENUM_CONSTANT(PLAYBACK_SEQUENTIAL);
|
||||||
|
|
||||||
|
PoolEntry defaults;
|
||||||
|
|
||||||
|
base_property_helper.set_prefix("stream_");
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), defaults.stream, &AudioStreamRandomizer::set_stream, &AudioStreamRandomizer::get_stream);
|
||||||
|
base_property_helper.register_property(PropertyInfo(Variant::FLOAT, "weight", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), defaults.weight, &AudioStreamRandomizer::set_stream_probability_weight, &AudioStreamRandomizer::get_stream_probability_weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioStreamRandomizer::AudioStreamRandomizer() {}
|
AudioStreamRandomizer::AudioStreamRandomizer() {
|
||||||
|
property_helper.setup_for_instance(base_property_helper, this);
|
||||||
|
}
|
||||||
|
|
||||||
void AudioStreamPlaybackRandomizer::start(double p_from_pos) {
|
void AudioStreamPlaybackRandomizer::start(double p_from_pos) {
|
||||||
playing = playback;
|
playing = playback;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include "core/io/image.h"
|
#include "core/io/image.h"
|
||||||
#include "core/io/resource.h"
|
#include "core/io/resource.h"
|
||||||
|
#include "scene/property_list_helper.h"
|
||||||
#include "servers/audio/audio_filter_sw.h"
|
#include "servers/audio/audio_filter_sw.h"
|
||||||
#include "servers/audio_server.h"
|
#include "servers/audio_server.h"
|
||||||
|
|
||||||
|
@ -236,9 +237,12 @@ private:
|
||||||
|
|
||||||
struct PoolEntry {
|
struct PoolEntry {
|
||||||
Ref<AudioStream> stream;
|
Ref<AudioStream> stream;
|
||||||
float weight;
|
float weight = 1.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline PropertyListHelper base_property_helper;
|
||||||
|
PropertyListHelper property_helper;
|
||||||
|
|
||||||
HashSet<AudioStreamPlaybackRandomizer *> playbacks;
|
HashSet<AudioStreamPlaybackRandomizer *> playbacks;
|
||||||
Vector<PoolEntry> audio_stream_pool;
|
Vector<PoolEntry> audio_stream_pool;
|
||||||
float random_pitch_scale = 1.0f;
|
float random_pitch_scale = 1.0f;
|
||||||
|
@ -254,9 +258,11 @@ private:
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
bool _set(const StringName &p_name, const Variant &p_value);
|
bool _set(const StringName &p_name, const Variant &p_value) { return property_helper.property_set_value(p_name, p_value); }
|
||||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
bool _get(const StringName &p_name, Variant &r_ret) const { return property_helper.property_get_value(p_name, r_ret); }
|
||||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
void _get_property_list(List<PropertyInfo> *p_list) const { property_helper.get_property_list(p_list, audio_stream_pool.size()); }
|
||||||
|
bool _property_can_revert(const StringName &p_name) const { return property_helper.property_can_revert(p_name); }
|
||||||
|
bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return property_helper.property_get_revert(p_name, r_property); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void add_stream(int p_index, Ref<AudioStream> p_stream, float p_weight = 1.0);
|
void add_stream(int p_index, Ref<AudioStream> p_stream, float p_weight = 1.0);
|
||||||
|
|
Loading…
Reference in New Issue