So I am doing this in a header file gui_base.hpp "gui_flags" is simply a definition of bitflags, nsp_input is needed to access a variable in "handle mouse" and in gui_text.hpp i declare the textblock class. Every "gui_" file is in the GUI:: namespace.
#ifndef _GUI_BASE_HPP_
#define _GUI_BASE_HPP_
#include "gui_flags.hpp"
#include "nsp_input.hpp"
#include "gui_text.hpp"
class GUI::base
{
protected:
struct s_lastclick
{
float ltime,rtime;
glm::vec2 pos;
bool rc, lc, first;
};
std::string m_name;
float m_width;
float m_height;
glm::vec2 m_center;
glm::mat2x2 m_tlbr;
GUI_FLAGS m_flags;
s_lastclick m_lastclick;
textblock m_textblock;
std::map<std::string, std::shared_ptr<base>> m_slaves;
glm::vec4 color;
public:
base(std::string gn, float &gw, float &gh, glm::vec2 &gc);
bool check_borders();
void move(glm::vec2 &gpos);
void move(float &x, float &y);
void toggle_flags(GUI_FLAGS f);
void open();
void close();
void set_color(glm::vec3 &color);
void set_transparency(float &t);
void enslave(std::string name, std::shared_ptr<base> &gslave);
void free_slave(std::string name);
void check_slaves();
void add_text(std::string text, glm::vec2 position, glm::vec3 color,
GLfloat scale=1.0f, GLfloat padx=8.0f, GLfloat pady=8.0f);
virtual void handle_mouse();
virtual void handle_keys();
};
#endif // _GUI_BASE_HPP_
If more details are needed, I can copy them here, I just didn't want to spam too much code.
The compiler simply gives two errors:
obj\Debug\Sources\gui_base.o:c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\mingw32\bits\gthr-default.h|402|first defined here|
||error: ld returned 1 exit status|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|
All variables and funtions are defined in gui_base.cpp (including the virtual ones). I am more or less transferring it "into" the namespace, as I had it working as a "normal" class in the global namespace just fine, so I assume it has soemthing to do with it. But given my lack of experience, I am a little overwhelmed by the small amount of (for me) understandable information given by the compiler error.
Most entries I could find were multiple definition errors regarding definitions in the header files, which - in my understanding - I do not have in my header.
Here is the gui_base.cpp:
#include "../Headers/gui_base.hpp"
namespace input_handler
{
std::unique_ptr<s_mouse> up_mouse;
std::map<uint32_t, bool> KEYS;
}
GUI::base::base(std::string gn, float &gw, float &gh, glm::vec2 &gc) : m_name(gn),
m_width(gw),
m_height(gh),
m_center(gc)
{
resource_manager::calc_tlbr(m_tlbr, m_center, m_width, m_height);
}
void GUI::base::handle_keys()
{
}
void GUI::base::handle_mouse()
{
}
bool GUI::base::check_borders()
{
if(input_handler::up_mouse->position.x > m_tlbr[0].x &&
input_handler::up_mouse->position.y < m_tlbr[0].y &&
input_handler::up_mouse->position.x < m_tlbr[1].x &&
input_handler::up_mouse->position.y > m_tlbr[1].y)
return true;
else
return false;
}
void GUI::base::move(glm::vec2 &gpos)
{
m_center = gpos;
resource_manager::calc_tlbr(m_tlbr, m_center, m_width, m_height);
}
void GUI::base::move(float &x, float &y)
{
m_center = glm::vec2(x,y);
resource_manager::calc_tlbr(m_tlbr, m_center, m_width, m_height);
}
void GUI::base::enslave(std::string name, std::shared_ptr<base> &gslave)
{
m_slaves[name] = gslave;
}
void GUI::base::check_slaves()
{
for(auto iter : m_slaves)
{
if(iter.second->check_borders())
{
if(iter.second->m_flags & GUI_OPEN)
iter.second->check_slaves();
}
else
continue;
}
}
void GUI::base::open()
{
toggle_flags(GUI_OPEN | GUI_DRAW | GUI_CLOSED);
if(!m_slaves.empty())
{
for(auto iter : m_slaves)
{
iter.second->open();
}
}
}
void GUI::base::toggle_flags(GUI_FLAGS f)
{
m_flags ^= f;
}
void GUI::base::close()
{
toggle_flags(GUI_OPEN | GUI_DRAW | GUI_CLOSED);
if(!m_slaves.empty())
{
for(auto iter : m_slaves)
{
iter.second->close();
}
}
}
void GUI::base::add_text(std::string text, glm::vec2 position, glm::vec3 color,
GLfloat scale, GLfloat padx, GLfloat pady)
{
m_textblock = GUI::textblock(position, color, scale, padx, pady, text);
}
EDIT: My class is declared in the nsp_gui.hpp file, which is included in the gui_text.hpp file (which is included in the regarding gui_base file)
there I declare my class as follows:
#ifndef _NSP_GUI_HPP_
#define _NSP_GUI_HPP_
namespace GUI
{
//the renderer class
class renderer;
class base;
class window;
//init function -> text will be in the GUI
extern void init_gui();
}
#endif // _NSP_GUI_HPP_
Blame on me - I found this in the build log (wasn't aware that there one.. sorry):
obj\Debug\Sources\gui_text.o:gui_text.cpp:(.bss+0x0): multiple definition of GUI::textblock_storage[abi:cxx11] obj\Debug\Sources\gui_base.o:gui_base.cpp:(.bss+0x0): first defined here obj\Debug\Sources\gui_window.o:gui_window.cpp:(.bss+0x0): multiple definition of GUI::textblock_storage[abi:cxx11]
textblock storage i declared in gui_text.hpp: (gui_window "simply" inherits from gui_base, so this may be why it is occuring in there)
#ifndef _GUI_TEXT_HPP_
#define _GUI_TEXT_HPP_
#include "nsp_rmng.hpp"
#include "nsp_gui.hpp"
#include <ft2build.h>
#include FT_FREETYPE_H
namespace GUI
{
extern void init_alphabet();
extern void write();
class textblock
{
public:
glm::vec2 position;
glm::vec4 instancing;
glm::vec3 color;
GLfloat scale, padx, pady;
std::string text;
void calc_offsets();
textblock(){};
textblock(glm::vec2 &p, glm::vec3 &c,
GLfloat &s, GLfloat &px, GLfloat &py,
std::string &t);
};
std::map<std::string, textblock> textblock_storage;
}
#endif // _GUI_TEXT_HPP_
The strange thing is that I do not define it anywhere. I do not use it yet either in the base nor text.cpp, even though I want to use it within the gui_text.cpp. Shouldn't it be just an unknown reference then?