mirror of
https://github.com/Relintai/voxelman.git
synced 2024-11-12 10:15:12 +01:00
Implemented the Merger Voxel Library.
This commit is contained in:
parent
cb91888f2a
commit
fd48f195c6
@ -27,9 +27,6 @@ Ref<VoxelmanLibrary> VoxelSurface::get_library() const {
|
|||||||
|
|
||||||
void VoxelSurface::set_library(Ref<VoxelmanLibrary> library) {
|
void VoxelSurface::set_library(Ref<VoxelmanLibrary> library) {
|
||||||
_library = (*library);
|
_library = (*library);
|
||||||
|
|
||||||
if (_library != NULL)
|
|
||||||
refresh_rects();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 VoxelSurface::transform_uv(const VoxelSurfaceSides p_side, const Vector2 p_uv) const {
|
Vector2 VoxelSurface::transform_uv(const VoxelSurfaceSides p_side, const Vector2 p_uv) const {
|
||||||
|
@ -2,26 +2,18 @@
|
|||||||
|
|
||||||
#include "voxelman_library_merger.h"
|
#include "voxelman_library_merger.h"
|
||||||
|
|
||||||
int VoxelSurfaceMerger::get_atlas_x(const VoxelSurfaceSides side) const {
|
Ref<AtlasTexture> VoxelSurfaceMerger::get_region(const VoxelSurfaceSides side) {
|
||||||
int indx = (side * 2);
|
return _regions[side];
|
||||||
|
|
||||||
return _atlas_positions[indx];
|
|
||||||
}
|
}
|
||||||
void VoxelSurfaceMerger::set_atlas_x(const VoxelSurfaceSides side, int value) {
|
void VoxelSurfaceMerger::set_region(const VoxelSurfaceSides side, Ref<AtlasTexture> texture) {
|
||||||
int indx = (side * 2);
|
_regions[side] = texture;
|
||||||
|
|
||||||
_atlas_positions[indx] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelSurfaceMerger::get_atlas_y(const VoxelSurfaceSides side) const {
|
Ref<Texture> VoxelSurfaceMerger::get_texture(const VoxelSurfaceSides side) {
|
||||||
int indx = (side * 2) + 1;
|
return _textures[side];
|
||||||
|
|
||||||
return _atlas_positions[indx];
|
|
||||||
}
|
}
|
||||||
void VoxelSurfaceMerger::set_atlas_y(const VoxelSurfaceSides side, int value) {
|
void VoxelSurfaceMerger::set_texture(const VoxelSurfaceSides side, Ref<Texture> texture) {
|
||||||
int indx = (side * 2) + 1;
|
_textures[side] = texture;
|
||||||
|
|
||||||
_atlas_positions[indx] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSurfaceMerger::refresh_rects() {
|
void VoxelSurfaceMerger::refresh_rects() {
|
||||||
@ -30,24 +22,38 @@ void VoxelSurfaceMerger::refresh_rects() {
|
|||||||
ERR_FAIL_COND(!ObjectDB::instance_validate(lib));
|
ERR_FAIL_COND(!ObjectDB::instance_validate(lib));
|
||||||
|
|
||||||
for (int i = 0; i < VOXEL_SIDES_COUNT; ++i) {
|
for (int i = 0; i < VOXEL_SIDES_COUNT; ++i) {
|
||||||
float culomn = 1.0 / static_cast<float>(lib->get_atlas_columns());
|
if (!_regions[i].is_valid()) {
|
||||||
float row = 1.0 / static_cast<float>(lib->get_atlas_rows());
|
_rects[i] = Rect2();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<AtlasTexture> at = _regions[i];
|
||||||
|
Ref<Texture> tex = at->get_atlas();
|
||||||
|
|
||||||
|
if (!tex.is_valid()) {
|
||||||
|
_rects[i] = Rect2();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect2 region = at->get_region();
|
||||||
|
float w = tex->get_width();
|
||||||
|
float h = tex->get_height();
|
||||||
|
|
||||||
Rect2 r;
|
Rect2 r;
|
||||||
|
|
||||||
r.position.x = _atlas_positions[i * 2] * culomn;
|
r.position.x = region.position.x / w;
|
||||||
r.position.y = _atlas_positions[i * 2 + 1] * row;
|
r.position.y = region.position.y / h;
|
||||||
|
r.size.x = region.size.x / w;
|
||||||
r.size.x = culomn;
|
r.size.y = region.size.y / h;
|
||||||
r.size.y = row;
|
|
||||||
|
|
||||||
_rects[i] = r;
|
_rects[i] = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VoxelSurfaceMerger::VoxelSurfaceMerger() {
|
VoxelSurfaceMerger::VoxelSurfaceMerger() {
|
||||||
for (int i = 0; i < VOXEL_SIDES_ARRAY_SIZE; ++i) {
|
for (int i = 0; i < VOXEL_SIDES_COUNT; ++i) {
|
||||||
_atlas_positions[i] = 0;
|
_regions[i].unref();
|
||||||
|
_textures[i].unref();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,18 +61,16 @@ VoxelSurfaceMerger::~VoxelSurfaceMerger() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSurfaceMerger::_bind_methods() {
|
void VoxelSurfaceMerger::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_atlas_x", "side"), &VoxelSurfaceMerger::get_atlas_x);
|
ClassDB::bind_method(D_METHOD("get_region", "side"), &VoxelSurfaceMerger::get_region);
|
||||||
ClassDB::bind_method(D_METHOD("set_atlas_x", "side", "value"), &VoxelSurfaceMerger::set_atlas_x);
|
ClassDB::bind_method(D_METHOD("set_region", "side", "texture"), &VoxelSurfaceMerger::set_region);
|
||||||
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "region_top", PROPERTY_HINT_RESOURCE_TYPE, "AtlasTexture", 0), "set_region", "get_region", VOXEL_SIDE_TOP);
|
||||||
ClassDB::bind_method(D_METHOD("get_atlas_y", "side"), &VoxelSurfaceMerger::get_atlas_y);
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "region_bottom", PROPERTY_HINT_RESOURCE_TYPE, "AtlasTexture", 0), "set_region", "get_region", VOXEL_SIDE_BOTTOM);
|
||||||
ClassDB::bind_method(D_METHOD("set_atlas_y", "side", "value"), &VoxelSurfaceMerger::set_atlas_y);
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "region_side", PROPERTY_HINT_RESOURCE_TYPE, "AtlasTexture", 0), "set_region", "get_region", VOXEL_SIDE_SIDE);
|
||||||
|
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::INT, "top_atlas_x"), "set_atlas_x", "get_atlas_x", VOXEL_SIDE_TOP);
|
ClassDB::bind_method(D_METHOD("get_texture", "side"), &VoxelSurfaceMerger::get_texture);
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::INT, "top_atlas_y"), "set_atlas_y", "get_atlas_y", VOXEL_SIDE_TOP);
|
ClassDB::bind_method(D_METHOD("set_texture", "side", "texture"), &VoxelSurfaceMerger::set_texture);
|
||||||
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_top", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", VOXEL_SIDE_TOP);
|
||||||
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_bottom", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", VOXEL_SIDE_BOTTOM);
|
||||||
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_side", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", VOXEL_SIDE_SIDE);
|
||||||
|
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::INT, "bottom_atlas_x"), "set_atlas_x", "get_atlas_x", VOXEL_SIDE_BOTTOM);
|
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::INT, "bottom_atlas_y"), "set_atlas_y", "get_atlas_y", VOXEL_SIDE_BOTTOM);
|
|
||||||
|
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::INT, "side_atlas_x"), "set_atlas_x", "get_atlas_x", VOXEL_SIDE_SIDE);
|
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::INT, "side_atlas_y"), "set_atlas_y", "get_atlas_y", VOXEL_SIDE_SIDE);
|
|
||||||
}
|
}
|
||||||
|
@ -3,15 +3,19 @@
|
|||||||
|
|
||||||
#include "voxel_surface.h"
|
#include "voxel_surface.h"
|
||||||
|
|
||||||
|
#include "scene/resources/texture.h"
|
||||||
|
|
||||||
|
#include "../../texture_packer/texture_packer.h"
|
||||||
|
|
||||||
class VoxelSurfaceMerger : public VoxelSurface {
|
class VoxelSurfaceMerger : public VoxelSurface {
|
||||||
GDCLASS(VoxelSurfaceMerger, VoxelSurface)
|
GDCLASS(VoxelSurfaceMerger, VoxelSurface)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int get_atlas_x(const VoxelSurfaceSides side) const;
|
Ref<AtlasTexture> get_region(const VoxelSurfaceSides side);
|
||||||
void set_atlas_x(const VoxelSurfaceSides side, int value);
|
void set_region(const VoxelSurfaceSides side, Ref<AtlasTexture> texture);
|
||||||
|
|
||||||
int get_atlas_y(const VoxelSurfaceSides side) const;
|
Ref<Texture> get_texture(const VoxelSurfaceSides side);
|
||||||
void set_atlas_y(const VoxelSurfaceSides side, int value);
|
void set_texture(const VoxelSurfaceSides side, Ref<Texture> texture);
|
||||||
|
|
||||||
void refresh_rects();
|
void refresh_rects();
|
||||||
|
|
||||||
@ -22,7 +26,8 @@ protected:
|
|||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _atlas_positions[VOXEL_SIDES_ARRAY_SIZE];
|
Ref<AtlasTexture> _regions[VOXEL_SIDES_COUNT];
|
||||||
|
Ref<Texture> _textures[VOXEL_SIDES_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,21 +1,38 @@
|
|||||||
#include "voxelman_library_merger.h"
|
#include "voxelman_library_merger.h"
|
||||||
|
|
||||||
int VoxelmanLibraryMerger::get_atlas_columns() const {
|
int VoxelmanLibraryMerger::get_texture_flags() const {
|
||||||
return _atlas_columns;
|
return _packer->get_texture_flags();
|
||||||
|
}
|
||||||
|
void VoxelmanLibraryMerger::set_texture_flags(const int flags) {
|
||||||
|
_packer->set_texture_flags(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelmanLibraryMerger::set_atlas_columns(int s) {
|
int VoxelmanLibraryMerger::get_max_atlas_size() const {
|
||||||
ERR_FAIL_COND(s < 0);
|
return _packer->get_max_atlas_size();
|
||||||
_atlas_columns = s;
|
}
|
||||||
|
void VoxelmanLibraryMerger::set_max_atlas_size(const int size) {
|
||||||
|
_packer->set_max_atlas_size(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelmanLibraryMerger::get_atlas_rows() const {
|
bool VoxelmanLibraryMerger::get_keep_original_atlases() const {
|
||||||
return _atlas_rows;
|
return _packer->get_keep_original_atlases();
|
||||||
|
}
|
||||||
|
void VoxelmanLibraryMerger::set_keep_original_atlases(const bool value) {
|
||||||
|
_packer->set_keep_original_atlases(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelmanLibraryMerger::set_atlas_rows(int s) {
|
Color VoxelmanLibraryMerger::get_background_color() const {
|
||||||
ERR_FAIL_COND(s < 0);
|
return _packer->get_background_color();
|
||||||
_atlas_rows = s;
|
}
|
||||||
|
void VoxelmanLibraryMerger::set_background_color(const Color color) {
|
||||||
|
_packer->set_background_color(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VoxelmanLibraryMerger::get_margin() const {
|
||||||
|
return _packer->get_margin();
|
||||||
|
}
|
||||||
|
void VoxelmanLibraryMerger::set_margin(const int margin) {
|
||||||
|
_packer->set_margin(margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<VoxelSurface> VoxelmanLibraryMerger::get_voxel_surface(int index) const {
|
Ref<VoxelSurface> VoxelmanLibraryMerger::get_voxel_surface(int index) const {
|
||||||
@ -73,9 +90,44 @@ void VoxelmanLibraryMerger::set_voxel_surfaces(const Vector<Variant> &surfaces)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VoxelmanLibraryMerger::refresh_rects() {
|
void VoxelmanLibraryMerger::refresh_rects() {
|
||||||
|
bool texture_added = false;
|
||||||
for (int i = 0; i < _voxel_surfaces.size(); i++) {
|
for (int i = 0; i < _voxel_surfaces.size(); i++) {
|
||||||
Ref<VoxelSurfaceMerger> surface = Ref<VoxelSurfaceMerger>(_voxel_surfaces[i]);
|
Ref<VoxelSurfaceMerger> surface = Ref<VoxelSurfaceMerger>(_voxel_surfaces[i]);
|
||||||
|
|
||||||
|
if (surface.is_valid()) {
|
||||||
|
for (int j = 0; j < VoxelSurface::VOXEL_SIDES_COUNT; ++j) {
|
||||||
|
Ref<Texture> tex = surface->get_texture(static_cast<VoxelSurface::VoxelSurfaceSides>(j));
|
||||||
|
|
||||||
|
if (!tex.is_valid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!_packer->contains_texture(tex)) {
|
||||||
|
texture_added = true;
|
||||||
|
surface->set_region(static_cast<VoxelSurface::VoxelSurfaceSides>(j), _packer->add_texture(tex));
|
||||||
|
} else {
|
||||||
|
surface->set_region(static_cast<VoxelSurface::VoxelSurfaceSides>(j), _packer->get_texture(tex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture_added) {
|
||||||
|
_packer->merge();
|
||||||
|
|
||||||
|
ERR_FAIL_COND(_packer->get_texture_count() == 0);
|
||||||
|
|
||||||
|
Ref<Texture> tex = _packer->get_generated_texture(0);
|
||||||
|
|
||||||
|
Ref<SpatialMaterial> mat = get_material();
|
||||||
|
|
||||||
|
if (mat.is_valid()) {
|
||||||
|
mat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < _voxel_surfaces.size(); i++) {
|
||||||
|
Ref<VoxelSurfaceMerger> surface = _voxel_surfaces[i];
|
||||||
|
|
||||||
if (surface.is_valid()) {
|
if (surface.is_valid()) {
|
||||||
surface->refresh_rects();
|
surface->refresh_rects();
|
||||||
}
|
}
|
||||||
@ -83,8 +135,11 @@ void VoxelmanLibraryMerger::refresh_rects() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VoxelmanLibraryMerger::VoxelmanLibraryMerger() {
|
VoxelmanLibraryMerger::VoxelmanLibraryMerger() {
|
||||||
_atlas_rows = 8;
|
_packer.instance();
|
||||||
_atlas_columns = 8;
|
_packer->set_texture_flags(Texture::FLAG_MIPMAPS | Texture::FLAG_FILTER);
|
||||||
|
_packer->set_max_atlas_size(1024);
|
||||||
|
_packer->set_keep_original_atlases(false);
|
||||||
|
_packer->set_margin(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
VoxelmanLibraryMerger::~VoxelmanLibraryMerger() {
|
VoxelmanLibraryMerger::~VoxelmanLibraryMerger() {
|
||||||
@ -98,17 +153,30 @@ VoxelmanLibraryMerger::~VoxelmanLibraryMerger() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_voxel_surfaces.clear();
|
_voxel_surfaces.clear();
|
||||||
|
|
||||||
|
_packer.unref();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VoxelmanLibraryMerger::_bind_methods() {
|
void VoxelmanLibraryMerger::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_atlas_columns"), &VoxelmanLibraryMerger::get_atlas_columns);
|
ClassDB::bind_method(D_METHOD("get_texture_flags"), &VoxelmanLibraryMerger::get_texture_flags);
|
||||||
ClassDB::bind_method(D_METHOD("set_atlas_columns", "value"), &VoxelmanLibraryMerger::set_atlas_columns);
|
ClassDB::bind_method(D_METHOD("set_texture_flags", "flags"), &VoxelmanLibraryMerger::set_texture_flags);
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "atlas_columns"), "set_atlas_columns", "get_atlas_columns");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter,Anisotropic Linear,Convert to Linear,Mirrored Repeat,Video Surface"), "set_texture_flags", "get_texture_flags");
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_atlas_rows"), &VoxelmanLibraryMerger::get_atlas_rows);
|
ClassDB::bind_method(D_METHOD("get_max_atlas_size"), &VoxelmanLibraryMerger::get_max_atlas_size);
|
||||||
ClassDB::bind_method(D_METHOD("set_atlas_rows", "value"), &VoxelmanLibraryMerger::set_atlas_rows);
|
ClassDB::bind_method(D_METHOD("set_max_atlas_size", "size"), &VoxelmanLibraryMerger::set_max_atlas_size);
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "atlas_rows"), "set_atlas_rows", "get_atlas_rows");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_atlas_size"), "set_max_atlas_size", "get_max_atlas_size");
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("get_keep_original_atlases"), &VoxelmanLibraryMerger::get_keep_original_atlases);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_keep_original_atlases", "value"), &VoxelmanLibraryMerger::set_keep_original_atlases);
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_original_atlases"), "set_keep_original_atlases", "get_keep_original_atlases");
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("get_background_color"), &VoxelmanLibraryMerger::get_background_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_background_color", "color"), &VoxelmanLibraryMerger::set_background_color);
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_background_color", "get_background_color");
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("get_margin"), &VoxelmanLibraryMerger::get_margin);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_margin", "size"), &VoxelmanLibraryMerger::set_margin);
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "margin"), "set_margin", "get_margin");
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_voxel_surfaces"), &VoxelmanLibraryMerger::get_voxel_surfaces);
|
ClassDB::bind_method(D_METHOD("get_voxel_surfaces"), &VoxelmanLibraryMerger::get_voxel_surfaces);
|
||||||
ClassDB::bind_method(D_METHOD("set_voxel_surfaces"), &VoxelmanLibraryMerger::set_voxel_surfaces);
|
ClassDB::bind_method(D_METHOD("set_voxel_surfaces"), &VoxelmanLibraryMerger::set_voxel_surfaces);
|
||||||
|
@ -16,11 +16,20 @@ class VoxelmanLibraryMerger : public VoxelmanLibrary {
|
|||||||
GDCLASS(VoxelmanLibraryMerger, VoxelmanLibrary)
|
GDCLASS(VoxelmanLibraryMerger, VoxelmanLibrary)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int get_atlas_columns() const;
|
int get_texture_flags() const;
|
||||||
void set_atlas_columns(int s);
|
void set_texture_flags(const int flags);
|
||||||
|
|
||||||
int get_atlas_rows() const;
|
int get_max_atlas_size() const;
|
||||||
void set_atlas_rows(int s);
|
void set_max_atlas_size(const int size);
|
||||||
|
|
||||||
|
bool get_keep_original_atlases() const;
|
||||||
|
void set_keep_original_atlases(const bool value);
|
||||||
|
|
||||||
|
Color get_background_color() const;
|
||||||
|
void set_background_color(const Color color);
|
||||||
|
|
||||||
|
int get_margin() const;
|
||||||
|
void set_margin(const int margin);
|
||||||
|
|
||||||
Ref<VoxelSurface> get_voxel_surface(int index) const;
|
Ref<VoxelSurface> get_voxel_surface(int index) const;
|
||||||
void set_voxel_surface(int index, Ref<VoxelSurface> value);
|
void set_voxel_surface(int index, Ref<VoxelSurface> value);
|
||||||
@ -41,9 +50,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
Vector<Ref<VoxelSurfaceMerger> > _voxel_surfaces;
|
Vector<Ref<VoxelSurfaceMerger> > _voxel_surfaces;
|
||||||
|
|
||||||
//atlas
|
Ref<TexturePacker> _packer;
|
||||||
int _atlas_columns;
|
|
||||||
int _atlas_rows;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VOXEL_LIBRARY_H
|
#endif
|
||||||
|
@ -66,6 +66,7 @@ void VoxelmanLibrarySimple::set_voxel_surfaces(const Vector<Variant> &surfaces)
|
|||||||
|
|
||||||
if (surface.is_valid()) {
|
if (surface.is_valid()) {
|
||||||
surface->set_library(this);
|
surface->set_library(this);
|
||||||
|
surface->refresh_rects();
|
||||||
}
|
}
|
||||||
|
|
||||||
_voxel_surfaces.push_back(surface);
|
_voxel_surfaces.push_back(surface);
|
||||||
|
Loading…
Reference in New Issue
Block a user