mirror of
https://github.com/Relintai/sfw.git
synced 2024-11-08 07:52:09 +01:00
Moved away from stl containers. Also added missing classes.
This commit is contained in:
parent
3d04ef9d1e
commit
65e8c7ec13
@ -27,6 +27,7 @@ ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/safe_refcount.cpp
|
|||||||
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/transform_2d.cpp -o sfw/core/transform_2d.o
|
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/transform_2d.cpp -o sfw/core/transform_2d.o
|
||||||
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/transform.cpp -o sfw/core/transform.o
|
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/transform.cpp -o sfw/core/transform.o
|
||||||
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/ustring.cpp -o sfw/core/ustring.o
|
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/ustring.cpp -o sfw/core/ustring.o
|
||||||
|
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/string_name.cpp -o sfw/core/string_name.o
|
||||||
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/vector2.cpp -o sfw/core/vector2.o
|
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/vector2.cpp -o sfw/core/vector2.o
|
||||||
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/vector2i.cpp -o sfw/core/vector2i.o
|
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/vector2i.cpp -o sfw/core/vector2i.o
|
||||||
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/vector3.cpp -o sfw/core/vector3.o
|
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/vector3.cpp -o sfw/core/vector3.o
|
||||||
@ -67,7 +68,8 @@ ccache g++ -Wall -lm -ldl -lpthread -lX11 -D_REENTRANT -g sfw/core/aabb.o sfw/c
|
|||||||
sfw/core/face3.o sfw/core/logger.o sfw/core/math_funcs.o \
|
sfw/core/face3.o sfw/core/logger.o sfw/core/math_funcs.o \
|
||||||
sfw/core/memory.o sfw/core/pcg.o sfw/core/plane.o sfw/core/projection.o sfw/core/quaternion.o sfw/core/random_pcg.o \
|
sfw/core/memory.o sfw/core/pcg.o sfw/core/plane.o sfw/core/projection.o sfw/core/quaternion.o sfw/core/random_pcg.o \
|
||||||
sfw/core/rect2.o sfw/core/rect2i.o sfw/core/safe_refcount.o sfw/core/transform_2d.o sfw/core/transform.o \
|
sfw/core/rect2.o sfw/core/rect2i.o sfw/core/safe_refcount.o sfw/core/transform_2d.o sfw/core/transform.o \
|
||||||
sfw/core/ustring.o sfw/core/vector2.o sfw/core/vector2i.o sfw/core/vector3.o \
|
sfw/core/ustring.o sfw/core/string_name.o \
|
||||||
|
sfw/core/vector2.o sfw/core/vector2i.o sfw/core/vector3.o \
|
||||||
sfw/core/vector3i.o sfw/core/vector4.o sfw/core/vector4i.o \
|
sfw/core/vector3i.o sfw/core/vector4.o sfw/core/vector4i.o \
|
||||||
sfw/core/pool_vector.o sfw/core/pool_allocator.o sfw/core/mutex.o sfw/core/stime.o \
|
sfw/core/pool_vector.o sfw/core/pool_allocator.o sfw/core/mutex.o sfw/core/stime.o \
|
||||||
sfw/render_core/application.o sfw/render_core/scene.o sfw/render_core/window.o \
|
sfw/render_core/application.o sfw/render_core/scene.o sfw/render_core/window.o \
|
||||||
|
@ -234,10 +234,21 @@ _FORCE_INLINE_ void _RLOG_MACRO_TEMPLATE_FUNC(STR str, A p0, B p1, C p2, D p3, E
|
|||||||
} else \
|
} else \
|
||||||
((void)0)
|
((void)0)
|
||||||
|
|
||||||
#define CRASH_MSG(msg) \
|
#define CRASH_COND_MSG(cond, msg) \
|
||||||
|
if (cond) { \
|
||||||
|
RLogger::log_error(__FUNCTION__, __FILE__, __LINE__, msg); \
|
||||||
|
GENERATE_TRAP \
|
||||||
|
} else \
|
||||||
|
((void)0)
|
||||||
|
|
||||||
|
#define CRASH_MSG(msg) \
|
||||||
RLogger::log_error(__FUNCTION__, __FILE__, __LINE__, msg); \
|
RLogger::log_error(__FUNCTION__, __FILE__, __LINE__, msg); \
|
||||||
GENERATE_TRAP
|
GENERATE_TRAP
|
||||||
|
|
||||||
|
#define CRASH_NOW(msg) \
|
||||||
|
RLogger::log_error(__FUNCTION__, __FILE__, __LINE__, "CRASH!"); \
|
||||||
|
GENERATE_TRAP
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This should be a 'free' assert for program flow and should not be needed in any releases,
|
* This should be a 'free' assert for program flow and should not be needed in any releases,
|
||||||
* only used in dev builds.
|
* only used in dev builds.
|
||||||
|
@ -35,8 +35,9 @@
|
|||||||
#include "hashfuncs.h"
|
#include "hashfuncs.h"
|
||||||
#include "paged_allocator.h"
|
#include "paged_allocator.h"
|
||||||
#include "pair.h"
|
#include "pair.h"
|
||||||
#include "core/math/math_funcs.h"
|
#include "math_funcs.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A HashMap implementation that uses open addressing with Robin Hood hashing.
|
* A HashMap implementation that uses open addressing with Robin Hood hashing.
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
#include "hash_map.h"
|
#include "hash_map.h"
|
||||||
#include "hashfuncs.h"
|
#include "hashfuncs.h"
|
||||||
#include "core/math/math_funcs.h"
|
#include "math_funcs.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,22 +32,19 @@
|
|||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#include "rid.h"
|
#include "aabb.h"
|
||||||
#include "core/math/aabb.h"
|
#include "math_defs.h"
|
||||||
#include "core/math/math_defs.h"
|
#include "math_funcs.h"
|
||||||
#include "core/math/math_funcs.h"
|
#include "rect2.h"
|
||||||
#include "core/math/rect2.h"
|
#include "rect2i.h"
|
||||||
#include "core/math/rect2i.h"
|
#include "vector2.h"
|
||||||
#include "core/math/vector2.h"
|
#include "vector2i.h"
|
||||||
#include "core/math/vector2i.h"
|
#include "vector3.h"
|
||||||
#include "core/math/vector3.h"
|
#include "vector3i.h"
|
||||||
#include "core/math/vector3i.h"
|
#include "vector4.h"
|
||||||
#include "core/math/vector4.h"
|
#include "vector4i.h"
|
||||||
#include "core/math/vector4i.h"
|
#include "string_name.h"
|
||||||
#include "core/object/object_id.h"
|
#include "ustring.h"
|
||||||
#include "core/string/node_path.h"
|
|
||||||
#include "core/string/string_name.h"
|
|
||||||
#include "core/string/ustring.h"
|
|
||||||
#include "core/typedefs.h"
|
#include "core/typedefs.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -321,10 +318,7 @@ struct HashMapHasherDefault {
|
|||||||
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(p_wchar); }
|
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(p_wchar); }
|
||||||
static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(p_uchar); }
|
static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(p_uchar); }
|
||||||
static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(p_uchar); }
|
static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(p_uchar); }
|
||||||
static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); }
|
|
||||||
static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
|
static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
|
||||||
static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); }
|
|
||||||
//static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); }
|
|
||||||
|
|
||||||
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
|
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
|
||||||
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(p_int); }
|
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(p_int); }
|
||||||
|
52
sfw/core/spin_lock.h
Normal file
52
sfw/core/spin_lock.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#ifndef SPIN_LOCK_H
|
||||||
|
#define SPIN_LOCK_H
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
/* spin_lock.h */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* PANDEMONIUM ENGINE */
|
||||||
|
/* https://github.com/Relintai/pandemonium_engine */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2022-present Péter Magyar. */
|
||||||
|
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "core/typedefs.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
class SpinLock {
|
||||||
|
std::atomic_flag locked = ATOMIC_FLAG_INIT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
_ALWAYS_INLINE_ void lock() {
|
||||||
|
while (locked.test_and_set(std::memory_order_acquire)) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ALWAYS_INLINE_ void unlock() {
|
||||||
|
locked.clear(std::memory_order_release);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // SPIN_LOCK_H
|
544
sfw/core/string_name.cpp
Normal file
544
sfw/core/string_name.cpp
Normal file
@ -0,0 +1,544 @@
|
|||||||
|
/*************************************************************************/
|
||||||
|
/* string_name.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* PANDEMONIUM ENGINE */
|
||||||
|
/* https://github.com/Relintai/pandemonium_engine */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2022-present Péter Magyar. */
|
||||||
|
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "string_name.h"
|
||||||
|
|
||||||
|
StaticCString StaticCString::create(const char *p_ptr) {
|
||||||
|
StaticCString scs;
|
||||||
|
scs.ptr = p_ptr;
|
||||||
|
return scs;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringName::_Data *StringName::_table[STRING_TABLE_LEN];
|
||||||
|
|
||||||
|
StringName _scs_create(const char *p_chr, bool p_static) {
|
||||||
|
return (p_chr[0] ? StringName(StaticCString::create(p_chr), p_static) : StringName());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringName::configured = false;
|
||||||
|
Mutex StringName::lock;
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
bool StringName::debug_stringname = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void StringName::setup() {
|
||||||
|
ERR_FAIL_COND(configured);
|
||||||
|
for (int i = 0; i < STRING_TABLE_LEN; i++) {
|
||||||
|
_table[i] = nullptr;
|
||||||
|
}
|
||||||
|
configured = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringName::cleanup() {
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (unlikely(debug_stringname)) {
|
||||||
|
Vector<_Data *> data;
|
||||||
|
for (int i = 0; i < STRING_TABLE_LEN; i++) {
|
||||||
|
_Data *d = _table[i];
|
||||||
|
while (d) {
|
||||||
|
data.push_back(d);
|
||||||
|
d = d->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print_line("\nStringName reference ranking (from most to least referenced):\n");
|
||||||
|
|
||||||
|
data.sort_custom<DebugSortReferences>();
|
||||||
|
int unreferenced_stringnames = 0;
|
||||||
|
int rarely_referenced_stringnames = 0;
|
||||||
|
for (int i = 0; i < data.size(); i++) {
|
||||||
|
print_line(itos(i + 1) + ": " + data[i]->get_name() + " - " + itos(data[i]->debug_references));
|
||||||
|
if (data[i]->debug_references == 0) {
|
||||||
|
unreferenced_stringnames += 1;
|
||||||
|
} else if (data[i]->debug_references < 5) {
|
||||||
|
rarely_referenced_stringnames += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print_line(vformat("\nOut of %d StringNames, %d StringNames were never referenced during this run (0 times) (%.2f%%).", data.size(), unreferenced_stringnames, unreferenced_stringnames / float(data.size()) * 100));
|
||||||
|
print_line(vformat("Out of %d StringNames, %d StringNames were rarely referenced during this run (1-4 times) (%.2f%%).", data.size(), rarely_referenced_stringnames, rarely_referenced_stringnames / float(data.size()) * 100));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//int lost_strings = 0;
|
||||||
|
for (int i = 0; i < STRING_TABLE_LEN; i++) {
|
||||||
|
while (_table[i]) {
|
||||||
|
_Data *d = _table[i];
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (d->static_count.get() != d->refcount.get()) {
|
||||||
|
lost_strings++;
|
||||||
|
if (OS::get_singleton()->is_stdout_verbose()) {
|
||||||
|
if (d->cname) {
|
||||||
|
print_line("Orphan StringName: " + String(d->cname));
|
||||||
|
} else {
|
||||||
|
print_line("Orphan StringName: " + String(d->name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
_table[i] = _table[i]->next;
|
||||||
|
memdelete(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (lost_strings) {
|
||||||
|
print_verbose("StringName: " + itos(lost_strings) + " unclaimed string names at exit.");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
configured = false;
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringName::unref() {
|
||||||
|
ERR_FAIL_COND(!configured);
|
||||||
|
|
||||||
|
if (_data && _data->refcount.unref()) {
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
if (_data->static_count.get() > 0) {
|
||||||
|
if (_data->cname) {
|
||||||
|
ERR_PRINT("BUG: Unreferenced static string to 0: " + String(_data->cname));
|
||||||
|
} else {
|
||||||
|
ERR_PRINT("BUG: Unreferenced static string to 0: " + String(_data->name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_data->prev) {
|
||||||
|
_data->prev->next = _data->next;
|
||||||
|
} else {
|
||||||
|
if (_table[_data->idx] != _data) {
|
||||||
|
ERR_PRINT("BUG!");
|
||||||
|
}
|
||||||
|
|
||||||
|
_table[_data->idx] = _data->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_data->next) {
|
||||||
|
_data->next->prev = _data->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
memdelete(_data);
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
_data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringName::operator==(const String &p_name) const {
|
||||||
|
if (!_data) {
|
||||||
|
return (p_name.length() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (_data->get_name() == p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringName::operator==(const char *p_name) const {
|
||||||
|
if (!_data) {
|
||||||
|
return (p_name[0] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (_data->get_name() == p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringName::operator!=(const String &p_name) const {
|
||||||
|
return !(operator==(p_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringName::operator!=(const StringName &p_name) const {
|
||||||
|
// the real magic of all this mess happens here.
|
||||||
|
// this is why path comparisons are very fast
|
||||||
|
return _data != p_name._data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringName::operator=(const StringName &p_name) {
|
||||||
|
if (this == &p_name) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unref();
|
||||||
|
|
||||||
|
if (p_name._data && p_name._data->refcount.ref()) {
|
||||||
|
_data = p_name._data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringName::StringName(const StringName &p_name) {
|
||||||
|
_data = nullptr;
|
||||||
|
|
||||||
|
ERR_FAIL_COND(!configured);
|
||||||
|
|
||||||
|
if (p_name._data && p_name._data->refcount.ref()) {
|
||||||
|
_data = p_name._data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringName::StringName(const char *p_name, bool p_static) {
|
||||||
|
_data = nullptr;
|
||||||
|
|
||||||
|
ERR_FAIL_COND(!configured);
|
||||||
|
|
||||||
|
if (!p_name || p_name[0] == 0) {
|
||||||
|
return; //empty, ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
uint32_t hash = String::hash(p_name);
|
||||||
|
|
||||||
|
uint32_t idx = hash & STRING_TABLE_MASK;
|
||||||
|
|
||||||
|
_data = _table[idx];
|
||||||
|
|
||||||
|
while (_data) {
|
||||||
|
// compare hash first
|
||||||
|
if (_data->hash == hash && _data->get_name() == p_name) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_data = _data->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_data) {
|
||||||
|
if (_data->refcount.ref()) {
|
||||||
|
// exists
|
||||||
|
if (p_static) {
|
||||||
|
_data->static_count.increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (unlikely(debug_stringname)) {
|
||||||
|
_data->debug_references++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_data = memnew(_Data);
|
||||||
|
_data->name = p_name;
|
||||||
|
_data->refcount.init();
|
||||||
|
_data->static_count.set(p_static ? 1 : 0);
|
||||||
|
_data->hash = hash;
|
||||||
|
_data->idx = idx;
|
||||||
|
_data->cname = NULL;
|
||||||
|
_data->next = _table[idx];
|
||||||
|
_data->prev = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (unlikely(debug_stringname)) {
|
||||||
|
// Keep in memory, force static.
|
||||||
|
_data->refcount.ref();
|
||||||
|
_data->static_count.increment();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (_table[idx]) {
|
||||||
|
_table[idx]->prev = _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
_table[idx] = _data;
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringName::StringName(const StaticCString &p_static_string, bool p_static) {
|
||||||
|
_data = NULL;
|
||||||
|
|
||||||
|
ERR_FAIL_COND(!configured);
|
||||||
|
|
||||||
|
ERR_FAIL_COND(!p_static_string.ptr || !p_static_string.ptr[0]);
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
uint32_t hash = String::hash(p_static_string.ptr);
|
||||||
|
|
||||||
|
uint32_t idx = hash & STRING_TABLE_MASK;
|
||||||
|
|
||||||
|
_data = _table[idx];
|
||||||
|
|
||||||
|
while (_data) {
|
||||||
|
// compare hash first
|
||||||
|
if (_data->hash == hash && _data->get_name() == p_static_string.ptr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_data = _data->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_data) {
|
||||||
|
if (_data->refcount.ref()) {
|
||||||
|
// exists
|
||||||
|
if (p_static) {
|
||||||
|
_data->static_count.increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (unlikely(debug_stringname)) {
|
||||||
|
_data->debug_references++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_data = memnew(_Data);
|
||||||
|
|
||||||
|
_data->refcount.init();
|
||||||
|
_data->static_count.set(p_static ? 1 : 0);
|
||||||
|
_data->hash = hash;
|
||||||
|
_data->idx = idx;
|
||||||
|
_data->cname = p_static_string.ptr;
|
||||||
|
_data->next = _table[idx];
|
||||||
|
_data->prev = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (unlikely(debug_stringname)) {
|
||||||
|
// Keep in memory, force static.
|
||||||
|
_data->refcount.ref();
|
||||||
|
_data->static_count.increment();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (_table[idx]) {
|
||||||
|
_table[idx]->prev = _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
_table[idx] = _data;
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringName::StringName(const String &p_name, bool p_static) {
|
||||||
|
_data = nullptr;
|
||||||
|
|
||||||
|
ERR_FAIL_COND(!configured);
|
||||||
|
|
||||||
|
if (p_name.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
uint32_t hash = p_name.hash();
|
||||||
|
|
||||||
|
uint32_t idx = hash & STRING_TABLE_MASK;
|
||||||
|
|
||||||
|
_data = _table[idx];
|
||||||
|
|
||||||
|
while (_data) {
|
||||||
|
if (_data->hash == hash && _data->get_name() == p_name) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_data = _data->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_data) {
|
||||||
|
if (_data->refcount.ref()) {
|
||||||
|
// exists
|
||||||
|
if (p_static) {
|
||||||
|
_data->static_count.increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (unlikely(debug_stringname)) {
|
||||||
|
_data->debug_references++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_data = memnew(_Data);
|
||||||
|
_data->name = p_name;
|
||||||
|
_data->refcount.init();
|
||||||
|
_data->static_count.set(p_static ? 1 : 0);
|
||||||
|
_data->hash = hash;
|
||||||
|
_data->idx = idx;
|
||||||
|
_data->cname = NULL;
|
||||||
|
_data->next = _table[idx];
|
||||||
|
_data->prev = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (unlikely(debug_stringname)) {
|
||||||
|
// Keep in memory, force static.
|
||||||
|
_data->refcount.ref();
|
||||||
|
_data->static_count.increment();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (_table[idx]) {
|
||||||
|
_table[idx]->prev = _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
_table[idx] = _data;
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringName StringName::search(const char *p_name) {
|
||||||
|
ERR_FAIL_COND_V(!configured, StringName());
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!p_name, StringName());
|
||||||
|
if (!p_name[0]) {
|
||||||
|
return StringName();
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
uint32_t hash = String::hash(p_name);
|
||||||
|
|
||||||
|
uint32_t idx = hash & STRING_TABLE_MASK;
|
||||||
|
|
||||||
|
_Data *_data = _table[idx];
|
||||||
|
|
||||||
|
while (_data) {
|
||||||
|
// compare hash first
|
||||||
|
if (_data->hash == hash && _data->get_name() == p_name) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_data = _data->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_data && _data->refcount.ref()) {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (unlikely(debug_stringname)) {
|
||||||
|
_data->debug_references++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
return StringName(_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
return StringName(); //does not exist
|
||||||
|
}
|
||||||
|
|
||||||
|
StringName StringName::search(const CharType *p_name) {
|
||||||
|
ERR_FAIL_COND_V(!configured, StringName());
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!p_name, StringName());
|
||||||
|
if (!p_name[0]) {
|
||||||
|
return StringName();
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
uint32_t hash = String::hash(p_name);
|
||||||
|
|
||||||
|
uint32_t idx = hash & STRING_TABLE_MASK;
|
||||||
|
|
||||||
|
_Data *_data = _table[idx];
|
||||||
|
|
||||||
|
while (_data) {
|
||||||
|
// compare hash first
|
||||||
|
if (_data->hash == hash && _data->get_name() == p_name) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_data = _data->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_data && _data->refcount.ref()) {
|
||||||
|
lock.unlock();
|
||||||
|
return StringName(_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
return StringName(); //does not exist
|
||||||
|
}
|
||||||
|
StringName StringName::search(const String &p_name) {
|
||||||
|
ERR_FAIL_COND_V(p_name == "", StringName());
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
uint32_t hash = p_name.hash();
|
||||||
|
|
||||||
|
uint32_t idx = hash & STRING_TABLE_MASK;
|
||||||
|
|
||||||
|
_Data *_data = _table[idx];
|
||||||
|
|
||||||
|
while (_data) {
|
||||||
|
// compare hash first
|
||||||
|
if (_data->hash == hash && p_name == _data->get_name()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_data = _data->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_data && _data->refcount.ref()) {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (unlikely(debug_stringname)) {
|
||||||
|
_data->debug_references++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
lock.unlock();
|
||||||
|
return StringName(_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
return StringName(); //does not exist
|
||||||
|
}
|
||||||
|
|
||||||
|
StringName::StringName() {
|
||||||
|
_data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool operator==(const String &p_name, const StringName &p_string_name) {
|
||||||
|
return p_name == p_string_name.operator String();
|
||||||
|
}
|
||||||
|
bool operator!=(const String &p_name, const StringName &p_string_name) {
|
||||||
|
return p_name != p_string_name.operator String();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const char *p_name, const StringName &p_string_name) {
|
||||||
|
return p_name == p_string_name.operator String();
|
||||||
|
}
|
||||||
|
bool operator!=(const char *p_name, const StringName &p_string_name) {
|
||||||
|
return p_name != p_string_name.operator String();
|
||||||
|
}
|
||||||
|
*/
|
231
sfw/core/string_name.h
Normal file
231
sfw/core/string_name.h
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
#ifndef STRING_NAME_H
|
||||||
|
#define STRING_NAME_H
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
/* string_name.h */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* PANDEMONIUM ENGINE */
|
||||||
|
/* https://github.com/Relintai/pandemonium_engine */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2022-present Péter Magyar. */
|
||||||
|
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "mutex.h"
|
||||||
|
#include "safe_refcount.h"
|
||||||
|
#include "ustring.h"
|
||||||
|
|
||||||
|
struct StaticCString {
|
||||||
|
const char *ptr;
|
||||||
|
static StaticCString create(const char *p_ptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
class StringName {
|
||||||
|
enum {
|
||||||
|
STRING_TABLE_BITS = 14,
|
||||||
|
STRING_TABLE_LEN = 1 << STRING_TABLE_BITS,
|
||||||
|
STRING_TABLE_MASK = STRING_TABLE_LEN - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Data {
|
||||||
|
SafeRefCount refcount;
|
||||||
|
SafeNumeric<uint32_t> static_count;
|
||||||
|
const char *cname;
|
||||||
|
String name;
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
uint32_t debug_references;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String get_name() const {
|
||||||
|
return cname ? String(cname) : name;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idx;
|
||||||
|
uint32_t hash;
|
||||||
|
_Data *prev;
|
||||||
|
_Data *next;
|
||||||
|
|
||||||
|
_Data() {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
debug_references = 0;
|
||||||
|
#endif
|
||||||
|
cname = nullptr;
|
||||||
|
prev = nullptr;
|
||||||
|
next = nullptr;
|
||||||
|
idx = 0;
|
||||||
|
hash = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static _Data *_table[STRING_TABLE_LEN];
|
||||||
|
|
||||||
|
_Data *_data;
|
||||||
|
|
||||||
|
union _HashUnion {
|
||||||
|
_Data *ptr;
|
||||||
|
uint32_t hash;
|
||||||
|
|
||||||
|
_HashUnion() {
|
||||||
|
ptr = nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void unref();
|
||||||
|
friend void register_core_types();
|
||||||
|
friend void unregister_core_types();
|
||||||
|
|
||||||
|
static Mutex lock;
|
||||||
|
static void setup();
|
||||||
|
static void cleanup();
|
||||||
|
static bool configured;
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
struct DebugSortReferences {
|
||||||
|
bool operator()(const _Data *p_left, const _Data *p_right) const {
|
||||||
|
return p_left->debug_references > p_right->debug_references;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool debug_stringname;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
StringName(_Data *p_data) {
|
||||||
|
_data = p_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
operator const void *() const {
|
||||||
|
return (_data && (_data->cname || !_data->name.empty())) ? (void *)1 : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const String &p_name) const;
|
||||||
|
bool operator==(const char *p_name) const;
|
||||||
|
bool operator!=(const String &p_name) const;
|
||||||
|
|
||||||
|
_FORCE_INLINE_ bool is_node_unique_name() const {
|
||||||
|
if (!_data) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_data->cname != nullptr) {
|
||||||
|
return _data->cname[0] == '%';
|
||||||
|
} else {
|
||||||
|
return _data->name[0] == '%';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ bool operator<(const StringName &p_name) const {
|
||||||
|
return _data < p_name._data;
|
||||||
|
}
|
||||||
|
_FORCE_INLINE_ bool operator==(const StringName &p_name) const {
|
||||||
|
// the real magic of all this mess happens here.
|
||||||
|
// this is why path comparisons are very fast
|
||||||
|
return _data == p_name._data;
|
||||||
|
}
|
||||||
|
_FORCE_INLINE_ uint32_t hash() const {
|
||||||
|
if (_data) {
|
||||||
|
return _data->hash;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_FORCE_INLINE_ const void *data_unique_pointer() const {
|
||||||
|
return (void *)_data;
|
||||||
|
}
|
||||||
|
bool operator!=(const StringName &p_name) const;
|
||||||
|
|
||||||
|
_FORCE_INLINE_ operator String() const {
|
||||||
|
if (_data) {
|
||||||
|
if (_data->cname) {
|
||||||
|
return String(_data->cname);
|
||||||
|
} else {
|
||||||
|
return _data->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
|
||||||
|
static StringName search(const char *p_name);
|
||||||
|
static StringName search(const CharType *p_name);
|
||||||
|
static StringName search(const String &p_name);
|
||||||
|
|
||||||
|
struct AlphCompare {
|
||||||
|
_FORCE_INLINE_ bool operator()(const StringName &l, const StringName &r) const {
|
||||||
|
const char *l_cname = l._data ? l._data->cname : "";
|
||||||
|
const char *r_cname = r._data ? r._data->cname : "";
|
||||||
|
|
||||||
|
if (l_cname) {
|
||||||
|
if (r_cname) {
|
||||||
|
return is_str_less(l_cname, r_cname);
|
||||||
|
} else {
|
||||||
|
return is_str_less(l_cname, r._data->name.ptr());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (r_cname) {
|
||||||
|
return is_str_less(l._data->name.ptr(), r_cname);
|
||||||
|
} else {
|
||||||
|
return is_str_less(l._data->name.ptr(), r._data->name.ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void operator=(const StringName &p_name);
|
||||||
|
StringName(const char *p_name, bool p_static = false);
|
||||||
|
StringName(const StringName &p_name);
|
||||||
|
StringName(const String &p_name, bool p_static = false);
|
||||||
|
StringName(const StaticCString &p_static_string, bool p_static = false);
|
||||||
|
StringName();
|
||||||
|
_FORCE_INLINE_ ~StringName() {
|
||||||
|
if (likely(configured) && _data) { //only free if configured
|
||||||
|
unref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool operator==(const String &p_name, const StringName &p_string_name);
|
||||||
|
bool operator!=(const String &p_name, const StringName &p_string_name);
|
||||||
|
bool operator==(const char *p_name, const StringName &p_string_name);
|
||||||
|
bool operator!=(const char *p_name, const StringName &p_string_name);
|
||||||
|
*/
|
||||||
|
|
||||||
|
StringName _scs_create(const char *p_chr, bool p_static = false);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The SNAME macro is used to speed up StringName creation, as it allows caching it after the first usage in a very efficient way.
|
||||||
|
* It should NOT be used everywhere, but instead in places where high performance is required and the creation of a StringName
|
||||||
|
* can be costly. Places where it should be used are:
|
||||||
|
* - Control::get_theme_*(<name> and Window::get_theme_*(<name> functions.
|
||||||
|
* - emit_signal(<name>,..) function
|
||||||
|
* - call_deferred(<name>,..) function
|
||||||
|
* - Comparisons to a StringName in overridden _set and _get methods.
|
||||||
|
*
|
||||||
|
* Use in places that can be called hundreds of times per frame (or more) is recommended, but this situation is very rare. If in doubt, do not use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#define SNAME(m_arg) ([]() -> const StringName & { static StringName sname = _scs_create(m_arg, true); return sname; })()
|
||||||
|
|
||||||
|
#endif // STRING_NAME_H
|
@ -36,7 +36,7 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <map>
|
#include "hash_map.h"
|
||||||
|
|
||||||
const char *Image::format_names[Image::FORMAT_MAX] = {
|
const char *Image::format_names[Image::FORMAT_MAX] = {
|
||||||
"Lum8", // luminance
|
"Lum8", // luminance
|
||||||
@ -1748,7 +1748,7 @@ void Image::create(const char **p_xpm) {
|
|||||||
Status status = READING_HEADER;
|
Status status = READING_HEADER;
|
||||||
int line = 0;
|
int line = 0;
|
||||||
|
|
||||||
std::map<String, Color> colormap;
|
HashMap<String, Color> colormap;
|
||||||
int colormap_size = 0;
|
int colormap_size = 0;
|
||||||
uint32_t pixel_size = 0;
|
uint32_t pixel_size = 0;
|
||||||
uint8_t *w_ptr;
|
uint8_t *w_ptr;
|
||||||
|
@ -9,7 +9,7 @@ void Material::bind() {
|
|||||||
shader = ShaderCache::get_singleton()->get_shader(get_material_id());
|
shader = ShaderCache::get_singleton()->get_shader(get_material_id());
|
||||||
|
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
shader = new Shader();
|
shader = memnew(Shader());
|
||||||
|
|
||||||
shader->set_vertex_shader_source(get_vertex_shader_source());
|
shader->set_vertex_shader_source(get_vertex_shader_source());
|
||||||
shader->set_fragment_shader_source(get_fragment_shader_source());
|
shader->set_fragment_shader_source(get_fragment_shader_source());
|
||||||
|
@ -64,18 +64,18 @@ void Mesh::upload() {
|
|||||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||||
glBufferData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size + uvs_vbo_size, NULL, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size + uvs_vbo_size, NULL, GL_STATIC_DRAW);
|
||||||
|
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices_vbo_size, &vertices[0]);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices_vbo_size, vertices.ptr());
|
||||||
|
|
||||||
if (normals_vbo_size > 0) {
|
if (normals_vbo_size > 0) {
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size, normals_vbo_size, &normals[0]);
|
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size, normals_vbo_size, normals.ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colors_vbo_size > 0) {
|
if (colors_vbo_size > 0) {
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size, colors_vbo_size, &colors[0]);
|
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size, colors_vbo_size, colors.ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uvs_vbo_size > 0) {
|
if (uvs_vbo_size > 0) {
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size, uvs_vbo_size, &uvs[0]);
|
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size, uvs_vbo_size, uvs.ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indices_vbo_size > 0) {
|
if (indices_vbo_size > 0) {
|
||||||
@ -84,7 +84,7 @@ void Mesh::upload() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_vbo_size, &indices[0], GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_vbo_size, indices.ptr(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef MESH_H
|
#ifndef MESH_H
|
||||||
#define MESH_H
|
#define MESH_H
|
||||||
|
|
||||||
#include <vector>
|
#include "vector.h"
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "3rd_glad.h"
|
#include "3rd_glad.h"
|
||||||
@ -34,11 +34,11 @@ public:
|
|||||||
|
|
||||||
int vertex_dimesions;
|
int vertex_dimesions;
|
||||||
|
|
||||||
std::vector<float> vertices;
|
Vector<float> vertices;
|
||||||
std::vector<float> normals;
|
Vector<float> normals;
|
||||||
std::vector<float> colors;
|
Vector<float> colors;
|
||||||
std::vector<float> uvs;
|
Vector<float> uvs;
|
||||||
std::vector<uint32_t> indices;
|
Vector<uint32_t> indices;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t vertices_vbo_size;
|
uint32_t vertices_vbo_size;
|
||||||
|
@ -1,145 +1,145 @@
|
|||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
bool Shader::bind() {
|
bool Shader::bind() {
|
||||||
if (current_shader != this) {
|
if (current_shader != this) {
|
||||||
glUseProgram(program);
|
glUseProgram(program);
|
||||||
|
|
||||||
current_shader = this;
|
current_shader = this;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::unbind() {
|
void Shader::unbind() {
|
||||||
if (current_shader == this) {
|
if (current_shader == this) {
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
|
|
||||||
current_shader = NULL;
|
current_shader = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::compile() {
|
void Shader::compile() {
|
||||||
if (!program) {
|
if (!program) {
|
||||||
program = glCreateProgram();
|
program = glCreateProgram();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vertex_shader) {
|
if (!vertex_shader) {
|
||||||
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fragment_shader) {
|
if (!fragment_shader) {
|
||||||
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
}
|
}
|
||||||
|
|
||||||
const GLchar **vertex_shader_source = get_vertex_shader_source();
|
const GLchar **vertex_shader_source = get_vertex_shader_source();
|
||||||
|
|
||||||
glShaderSource(vertex_shader, 1, vertex_shader_source, NULL);
|
glShaderSource(vertex_shader, 1, vertex_shader_source, NULL);
|
||||||
glCompileShader(vertex_shader);
|
glCompileShader(vertex_shader);
|
||||||
|
|
||||||
GLint shader_compiled = GL_FALSE;
|
GLint shader_compiled = GL_FALSE;
|
||||||
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &shader_compiled);
|
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &shader_compiled);
|
||||||
if (shader_compiled != GL_TRUE) {
|
if (shader_compiled != GL_TRUE) {
|
||||||
print_shader_errors(vertex_shader, "compiling Vertex Shader");
|
print_shader_errors(vertex_shader, "compiling Vertex Shader");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
glAttachShader(program, vertex_shader);
|
glAttachShader(program, vertex_shader);
|
||||||
|
|
||||||
|
const GLchar **fragment_shader_source = get_fragment_shader_source();
|
||||||
|
|
||||||
const GLchar **fragment_shader_source = get_fragment_shader_source();
|
glShaderSource(fragment_shader, 1, fragment_shader_source, NULL);
|
||||||
|
glCompileShader(fragment_shader);
|
||||||
|
|
||||||
glShaderSource(fragment_shader, 1, fragment_shader_source, NULL);
|
shader_compiled = GL_FALSE;
|
||||||
glCompileShader(fragment_shader);
|
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &shader_compiled);
|
||||||
|
if (shader_compiled != GL_TRUE) {
|
||||||
|
print_shader_errors(fragment_shader, "compiling Fragment Shader");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
shader_compiled = GL_FALSE;
|
glAttachShader(program, fragment_shader);
|
||||||
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &shader_compiled);
|
|
||||||
if (shader_compiled != GL_TRUE) {
|
|
||||||
print_shader_errors(fragment_shader, "compiling Fragment Shader");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
glAttachShader(program, fragment_shader);
|
glBindAttribLocation(program, ATTRIBUTE_POSITION, "a_position");
|
||||||
|
glBindAttribLocation(program, ATTRIBUTE_NORMAL, "a_normal");
|
||||||
|
glBindAttribLocation(program, ATTRIBUTE_COLOR, "a_color");
|
||||||
|
glBindAttribLocation(program, ATTRIBUTE_UV, "a_uv");
|
||||||
|
|
||||||
glBindAttribLocation(program, ATTRIBUTE_POSITION, "a_position");
|
glLinkProgram(program);
|
||||||
glBindAttribLocation(program, ATTRIBUTE_NORMAL, "a_normal");
|
|
||||||
glBindAttribLocation(program, ATTRIBUTE_COLOR, "a_color");
|
|
||||||
glBindAttribLocation(program, ATTRIBUTE_UV, "a_uv");
|
|
||||||
|
|
||||||
glLinkProgram(program);
|
GLint program_compiled = GL_FALSE;
|
||||||
|
glGetProgramiv(program, GL_LINK_STATUS, &program_compiled);
|
||||||
GLint program_compiled = GL_FALSE;
|
if (program_compiled != GL_TRUE) {
|
||||||
glGetProgramiv(program, GL_LINK_STATUS, &program_compiled);
|
print_program_errors(program);
|
||||||
if (program_compiled != GL_TRUE) {
|
return;
|
||||||
print_program_errors(program);
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void Shader::destroy() {
|
void Shader::destroy() {
|
||||||
glDeleteShader(vertex_shader);
|
glDeleteShader(vertex_shader);
|
||||||
glDeleteShader(fragment_shader);
|
glDeleteShader(fragment_shader);
|
||||||
glDeleteProgram(program);
|
glDeleteProgram(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
const GLchar **Shader::get_vertex_shader_source() {
|
const GLchar **Shader::get_vertex_shader_source() {
|
||||||
return vertex_shader_source;
|
return vertex_shader_source;
|
||||||
}
|
}
|
||||||
void Shader::set_vertex_shader_source(const GLchar **source) {
|
void Shader::set_vertex_shader_source(const GLchar **source) {
|
||||||
vertex_shader_source = source;
|
vertex_shader_source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GLchar **Shader::get_fragment_shader_source() {
|
const GLchar **Shader::get_fragment_shader_source() {
|
||||||
return fragment_shader_source;
|
return fragment_shader_source;
|
||||||
}
|
}
|
||||||
void Shader::set_fragment_shader_source(const GLchar **source) {
|
void Shader::set_fragment_shader_source(const GLchar **source) {
|
||||||
fragment_shader_source = source;
|
fragment_shader_source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::print_shader_errors(const GLuint p_program, const char *name) {
|
void Shader::print_shader_errors(const GLuint p_program, const char *name) {
|
||||||
int max_length = 5000;
|
int max_length = 5000;
|
||||||
std::vector<GLchar> error_log(max_length);
|
Vector<GLchar> error_log;
|
||||||
|
error_log.resize(max_length);
|
||||||
|
|
||||||
glGetShaderInfoLog(p_program, max_length, &max_length, &error_log[0]);
|
glGetShaderInfoLog(p_program, max_length, &max_length, error_log.ptrw());
|
||||||
|
|
||||||
printf("Error %s!\n", name);
|
printf("Error %s!\n", name);
|
||||||
printf("%s!\n", &error_log[0]);
|
printf("%s!\n", error_log.ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::print_program_errors(const GLuint p_program) {
|
void Shader::print_program_errors(const GLuint p_program) {
|
||||||
if (glIsProgram(program)) {
|
if (glIsProgram(program)) {
|
||||||
int info_length = 0;
|
int info_length = 0;
|
||||||
int max_length = 5000;
|
int max_length = 5000;
|
||||||
|
|
||||||
glGetProgramiv(p_program, GL_INFO_LOG_LENGTH, &info_length);
|
glGetProgramiv(p_program, GL_INFO_LOG_LENGTH, &info_length);
|
||||||
|
|
||||||
char *info_log = new char[max_length];
|
char *info_log = new char[max_length];
|
||||||
|
|
||||||
glGetProgramInfoLog(p_program, max_length, &info_length, info_log);
|
glGetProgramInfoLog(p_program, max_length, &info_length, info_log);
|
||||||
|
|
||||||
if (info_length > 0) {
|
if (info_length > 0) {
|
||||||
printf("%s\n", info_log);
|
printf("%s\n", info_log);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] info_log;
|
delete[] info_log;
|
||||||
} else {
|
} else {
|
||||||
printf("print_program_errors: Not a program!\n");
|
printf("print_program_errors: Not a program!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader::Shader() {
|
Shader::Shader() {
|
||||||
vertex_shader = 0;
|
vertex_shader = 0;
|
||||||
fragment_shader = 0;
|
fragment_shader = 0;
|
||||||
program = 0;
|
program = 0;
|
||||||
|
|
||||||
vertex_shader_source = NULL;
|
vertex_shader_source = NULL;
|
||||||
fragment_shader_source = NULL;
|
fragment_shader_source = NULL;
|
||||||
}
|
}
|
||||||
Shader::~Shader() {
|
Shader::~Shader() {
|
||||||
destroy();
|
destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader *Shader::current_shader = NULL;
|
Shader *Shader::current_shader = NULL;
|
||||||
@ -147,25 +147,24 @@ Shader *Shader::current_shader = NULL;
|
|||||||
//Meyers singleton
|
//Meyers singleton
|
||||||
//thread safe
|
//thread safe
|
||||||
ShaderCache *ShaderCache::get_singleton() {
|
ShaderCache *ShaderCache::get_singleton() {
|
||||||
static ShaderCache instance;
|
static ShaderCache instance;
|
||||||
|
|
||||||
return &instance;
|
return &instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader *ShaderCache::get_shader(const int id) {
|
Shader *ShaderCache::get_shader(const int id) {
|
||||||
return shaders[id];
|
return shaders[id];
|
||||||
}
|
}
|
||||||
void ShaderCache::add_shader(const int id, Shader *shader) {
|
void ShaderCache::add_shader(const int id, Shader *shader) {
|
||||||
shaders[id] = shader;
|
shaders[id] = shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderCache::ShaderCache() {
|
ShaderCache::ShaderCache() {
|
||||||
}
|
}
|
||||||
ShaderCache::~ShaderCache() {
|
ShaderCache::~ShaderCache() {
|
||||||
for (const std::pair<int, Shader *> n : shaders) {
|
for (HashMap<int, Shader *>::Element *E = shaders.front(); E; E = E->next) {
|
||||||
delete n.second;
|
memdelete(E->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
shaders.clear();
|
shaders.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define SHADER_H
|
#define SHADER_H
|
||||||
|
|
||||||
#include "3rd_glad.h"
|
#include "3rd_glad.h"
|
||||||
#include <unordered_map>
|
#include "hash_map.h"
|
||||||
|
|
||||||
class Shader {
|
class Shader {
|
||||||
public:
|
public:
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
~ShaderCache();
|
~ShaderCache();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::unordered_map<int, Shader *> shaders;
|
HashMap<int, Shader *> shaders;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHADER_H
|
#endif // SHADER_H
|
||||||
|
@ -17,7 +17,7 @@ void MeshInstance2D::render() {
|
|||||||
|
|
||||||
mesh->render();
|
mesh->render();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < children.size(); ++i) {
|
for (int i = 0; i < children.size(); ++i) {
|
||||||
MeshInstance2D * c = children[i];
|
MeshInstance2D * c = children[i];
|
||||||
|
|
||||||
if (c) {
|
if (c) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef MESH_INSTACE_2D_H
|
#ifndef MESH_INSTACE_2D_H
|
||||||
#define MESH_INSTACE_2D_H
|
#define MESH_INSTACE_2D_H
|
||||||
|
|
||||||
#include <vector>
|
#include "vector.h"
|
||||||
|
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
@ -20,7 +20,7 @@ public:
|
|||||||
|
|
||||||
Transform2D transform;
|
Transform2D transform;
|
||||||
|
|
||||||
std::vector<MeshInstance2D *> children;
|
Vector<MeshInstance2D *> children;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MESH_INSTACE_H
|
#endif // MESH_INSTACE_H
|
||||||
|
@ -17,7 +17,7 @@ void MeshInstance3D::render() {
|
|||||||
|
|
||||||
mesh->render();
|
mesh->render();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < children.size(); ++i) {
|
for (int i = 0; i < children.size(); ++i) {
|
||||||
MeshInstance3D * c = children[i];
|
MeshInstance3D * c = children[i];
|
||||||
|
|
||||||
if (c) {
|
if (c) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef MESH_INSTACE_3D_H
|
#ifndef MESH_INSTACE_3D_H
|
||||||
#define MESH_INSTACE_3D_H
|
#define MESH_INSTACE_3D_H
|
||||||
|
|
||||||
#include <vector>
|
#include "vector.h"
|
||||||
|
|
||||||
#include "object_3d.h"
|
#include "object_3d.h"
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ public:
|
|||||||
Material *material;
|
Material *material;
|
||||||
Mesh *mesh;
|
Mesh *mesh;
|
||||||
|
|
||||||
std::vector<MeshInstance3D *> children;
|
Vector<MeshInstance3D *> children;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MESH_INSTACE_H
|
#endif // MESH_INSTACE_H
|
||||||
|
Loading…
Reference in New Issue
Block a user