8 Commits
Author SHA1 Message Date
Daniel-Garmig d141b77eaa Optimizaciones y mejoras de Premake.
Cambiar un par de cosas y hacer abstractos los postbuildcommands.
2022-08-29 19:31:10 +02:00
Daniel-Garmig 132f24720e Some Rendering Stuff.
Se ha añadido un método para cambiar el color de clear.
Se ha abstraido la cámara del renderer para más versatilidad a futuro.
Nota: La implementación de la cámara no es nada segura. Tocará revisarlo
2022-08-29 17:54:34 +02:00
Daniel-Garmig 692812a710 Unificar Encoding.
Revisado que todos los archivos son UTF-8 y espacios como indentación.
2022-08-11 16:47:50 +02:00
Daniel-Garmig 006d223f57 Nueva Clase Engine.
Se ha eliminado la antigua clase Game y movido a la nueva clase Engine.
La clase Engine, encargada de iniciar las cosas, ahora está en el Engine
Además, tiene seguridad en la inicialización.
Ya no se inicia el juego si hay error al cargar libs o sistemas.
2022-08-11 15:16:23 +02:00
Daniel-Garmig b2d6a31275 Nuevo sistema de Escenas.
Nos quitamos del medio la cosa rara del SceneBuilder.
Simplificamos la estructura y la hacemos más o menos segura.
2022-08-11 12:57:40 +02:00
Daniel-Garmig ce1886d3db Bump Dear ImGui version to 1.88. 2022-08-10 00:13:14 +02:00
Daniel-Garmig 614ab37ca5 Soporte Linux.
Tenemos soporte para linux.
Sólo faltaba este pequeño detalle, lo demás parece funcionar.
2022-08-09 19:00:12 +02:00
Daniel-Garmig ae17a6bb33 El soporte para Linux está cerca...
Se ha actualizado premake5 para que soporte VS22 y se ha añadido para linux.
Modificada la configuración de premake para crear los makefiles correctamente en sistemas linux.
Modificados todos los include para ser compatibles con linux (cambiar la barrita \ por / ).
Adiciones al .gitignore para ignorar archivos de .make .
2022-08-09 18:26:57 +02:00
62 changed files with 5717 additions and 3759 deletions
+3
View File
@@ -1,5 +1,6 @@
#Directorios: #Directorios:
.vs .vs
.vscode
bin/ bin/
bin-obj/ bin-obj/
@@ -9,3 +10,5 @@ imgui.ini
*.vcxproj *.vcxproj
*.filters *.filters
*.sln *.sln
*.make
Makefile
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
premake/premake5 gmake2
+3
View File
@@ -39,3 +39,6 @@ Repositorio principal de UberEngine. Sin mucho más.
### JSON / AssetManager ### JSON / AssetManager
- [ ] Crear un sistema sencillo (un método o algo común para todas las veces que sea necesario) para añadir seguridad al parse y uso de los JSON. De tal forma que se devuelva el error por consola pero no salten exepciones ni mierdas. - [ ] Crear un sistema sencillo (un método o algo común para todas las veces que sea necesario) para añadir seguridad al parse y uso de los JSON. De tal forma que se devuelva el error por consola pero no salten exepciones ni mierdas.
### Sistema de Escenas.
- [ ] Revisar los métodos para carga/descarga y de cambio de escenas. Creo que se pueden estructurar mejor.
+50 -50
View File
@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <json\json.hpp> #include <json/json.hpp>
using json = nlohmann::ordered_json; using json = nlohmann::ordered_json;
#include <SDL_rect.h> #include <SDL_rect.h>
@@ -9,73 +9,73 @@ using json = nlohmann::ordered_json;
namespace UE namespace UE
{ {
/* All types of Assets that can be loadedand stored by an AssetManager */ /* All types of Assets that can be loadedand stored by an AssetManager */
enum class AssetType enum class AssetType
{ {
Texture = 0, Font, Sound, Other, Unvalid = 15 Texture = 0, Font, Sound, Other, Unvalid = 15
}; };
/* Asset struct. Contains info regarding Assets para ser cargados. */ /* Asset struct. Contains info regarding Assets para ser cargados. */
struct Asset struct Asset
{ {
public: public:
Asset() {}; Asset() {};
Asset(std::string name, Asset(std::string name,
std::string path, std::string path,
AssetType type) AssetType type)
: _name(name), _path(path), _type(type) {} : _name(name), _path(path), _type(type) {}
std::string _name = ""; std::string _name = "";
std::string _path = ""; std::string _path = "";
AssetType _type = AssetType::Unvalid; AssetType _type = AssetType::Unvalid;
}; };
/* Conversión de una struct Asset a JSON */ /* Conversi�n de una struct Asset a JSON */
inline void to_json(nlohmann::ordered_json& j, const Asset& as) inline void to_json(nlohmann::ordered_json& j, const Asset& as)
{ {
j = nlohmann::ordered_json j = nlohmann::ordered_json
{ {
{"name", as._name}, {"name", as._name},
{"Path", as._path}, {"Path", as._path},
{"Type", as._type}, {"Type", as._type},
}; };
} }
/* Conversión de un JSON a una struct Asset */ /* Conversi�n de un JSON a una struct Asset */
inline void from_json(const nlohmann::ordered_json& j, Asset& as) inline void from_json(const nlohmann::ordered_json& j, Asset& as)
{ {
j.at("name").get_to(as._name); j.at("name").get_to(as._name);
j.at("Path").get_to(as._path); j.at("Path").get_to(as._path);
j.at("Type").get_to(as._type); j.at("Type").get_to(as._type);
} }
} }
//--------------- //---------------
//Es necesario hacerlo fuera del namespace UE para que JSON no se enfade. //Es necesario hacerlo fuera del namespace UE para que JSON no se enfade.
// Es importante mantener a tus librerías contentas. // Es importante mantener a tus librer�as contentas.
//--------------- //---------------
/* Conversión de un Struct SDL_Rect a JSON */ /* Conversi�n de un Struct SDL_Rect a JSON */
inline void to_json(nlohmann::ordered_json& j, const SDL_Rect& rect) inline void to_json(nlohmann::ordered_json& j, const SDL_Rect& rect)
{ {
j = nlohmann::ordered_json j = nlohmann::ordered_json
{ {
{"posX", rect.x}, {"posX", rect.x},
{"posY", rect.y}, {"posY", rect.y},
{"sizeX", rect.w}, {"sizeX", rect.w},
{"sizeY", rect.h} {"sizeY", rect.h}
}; };
} }
/* Conversión de un JSON a un struct SDL_Rect */ /* Conversi�n de un JSON a un struct SDL_Rect */
inline void from_json(const nlohmann::ordered_json& j, SDL_Rect& rect) inline void from_json(const nlohmann::ordered_json& j, SDL_Rect& rect)
{ {
j.at("posX").get_to(rect.x); j.at("posX").get_to(rect.x);
j.at("posY").get_to(rect.y); j.at("posY").get_to(rect.y);
j.at("sizeX").get_to(rect.w); j.at("sizeX").get_to(rect.w);
j.at("sizeY").get_to(rect.h); j.at("sizeY").get_to(rect.h);
} }
+156 -179
View File
@@ -1,8 +1,8 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include "Logging\Logger.h" #include "Logging/Logger.h"
#include "Assets\AssetManager.h" #include "Assets/AssetManager.h"
#include "SDL_rect.h" #include "SDL_rect.h"
@@ -10,209 +10,186 @@
namespace UE namespace UE
{ {
void AssetManager::InitAssetManager() void AssetManager::InitAssetManager()
{ {
if (IMG_Init(IMG_INIT_PNG)) UE_LOG_INFO("AssetManager Iniciado con éxito.");
{ }
UE_LOG_INFO("SDL_Image Init.");
}
else
{
UE_LOG_ERROR("SDL_Image - Error al inicarse: {0}", IMG_GetError());
}
if (!TTF_Init()) //Retorna 0 si está correcto. void AssetManager::CleanAssetManager()
{ {
UE_LOG_INFO("SDL_TTF se ha inicializado correctamente."); //Destruye todas las texturas de SDL.
} for (auto i = _textures.begin(); i != _textures.end(); i++)
else {
{ i->second->~Texture();
UE_LOG_ERROR("SDL_TTF - Error al inicarse: {0}", TTF_GetError()); }
}
UE_LOG_INFO("AssetManager Iniciado con éxito."); //Limpiamos las fuentes.
} for (auto i = _fonts.begin(); i != _fonts.end(); i++)
{
//Limpiamos las fuentes.
delete i->second;
}
void AssetManager::CleanAssetManager() //CPP se debería de encargar de ellos, pero bueno.
{ _assetQueue.clear();
//Destruye todas las texturas de SDL. _textures.clear();
for (auto i = _textures.begin(); i != _textures.end(); i++)
{
i->second->~Texture();
}
//Limpiamos las fuentes. UE_LOG_INFO("AssetManager Cleaned");
for (auto i = _fonts.begin(); i != _fonts.end(); i++) }
{
//Limpiamos las fuentes.
delete i->second;
}
//CPP se debería de encargar de ellos, pero bueno.
_assetQueue.clear();
_textures.clear();
IMG_Quit(); void AssetManager::LoadAssetsFromFile(std::string filePath)
{
std::fstream file(filePath.c_str());
UE_LOG_INFO("AssetManager Cleaned"); if (!file.is_open())
} {
UE_LOG_ERROR("No se ha podido abrir la lista de assets: {0}", filePath);
}
//Load Asset data from JSON.
json jread = json::parse(file);
json Textures = jread["Textures"];
json Fonts = jread["Fonts"];
json Sounds = jread["Sounds"];
json Others = jread["Others"];
/* Add assets struct to asset map. */
for (int i = 0; i < Textures.size(); i++)
{
_assetQueue.push_back(Textures.at(i));
}
for (int i = 0; i < Fonts.size(); i++)
{
_assetQueue.push_back(Fonts.at(i));
}
for (int i = 0; i < Sounds.size(); i++)
{
_assetQueue.push_back(Sounds.at(i));
}
for (int i = 0; i < Others.size(); i++)
{
_assetQueue.push_back(Others.at(i));
}
file.close();
}
void AssetManager::LoadAsset(Asset& as)
{
_assetQueue.push_back(as);
}
void AssetManager::ProcessAssetQueue(int amount)
{
int cantidad = amount;
if (amount == -1 || cantidad >= _assetQueue.size())
cantidad = _assetQueue.size();
//Load Assets from files, depending on the type.
for (int i = 0; i < cantidad; i++)
{
Asset& as = _assetQueue.front();
switch (as._type)
{
case AssetType::Texture:
{
LoadTexture(as._name, as._path);
break;
}
case AssetType::Font:
{
LoadFont(as._name, as._path);
break;
}
default:
{
UE_LOG_WARN("Asset {0}, Type {1} Cannot be loaded from {2}", as._name, as._type, as._path);
break;
}
}
_assetQueue.pop_front();
}
}
void AssetManager::LoadAssetsFromFile(std::string filePath) void AssetManager::LoadTexture(std::string name, std::string txPath)
{ {
std::fstream file(filePath.c_str()); Texture* tx = new Texture(txPath, _SDL_Renderer);
_textures.insert(std::make_pair(name, tx));
if (!file.is_open()) //std::fstream file(txPath.c_str());
{
UE_LOG_ERROR("No se ha podido abrir la lista de assets: {0}", filePath);
}
//Load Asset data from JSON. //json jread = json::parse(file);
json jread = json::parse(file); //std::string path = jread["TexturePath"];
json Textures = jread["Textures"]; ////Cargamos la textura.
json Fonts = jread["Fonts"]; //SDL_Surface* loadSurface = IMG_Load(path.c_str());
json Sounds = jread["Sounds"]; //SDL_Texture* tx = SDL_CreateTextureFromSurface(_mainRenderer, loadSurface);
json Others = jread["Others"]; //_textures.insert(std::make_pair(name, tx));
//SDL_FreeSurface(loadSurface);
/* Add assets struct to asset map. */ ////Almacenamos los Rects (sprites) de esa textura.
for (int i = 0; i < Textures.size(); i++) //json textureRects = jread["TextureRects"];
{
_assetQueue.push_back(Textures.at(i)); //_textureRects.insert(std::make_pair(name, std::vector<SDL_Rect>()));
} //std::vector<SDL_Rect>& vector = _textureRects.at(name);
for (int i = 0; i < Fonts.size(); i++)
{ //for (int i = 0; i < textureRects.size(); i++)
_assetQueue.push_back(Fonts.at(i)); //{
} // //json rectData = textureRects.at(i);
for (int i = 0; i < Sounds.size(); i++) // //SDL_Rect rect;
{ // //rect.x = rectData.at()
_assetQueue.push_back(Sounds.at(i));
} // vector.push_back(textureRects.at(i).get<SDL_Rect>());
for (int i = 0; i < Others.size(); i++) //}
{
_assetQueue.push_back(Others.at(i));
}
file.close(); //file.close();
} }
void AssetManager::LoadAsset(Asset& as) void AssetManager::RemoveTexture(std::string name)
{ {
_assetQueue.push_back(as); //Se supone que el erase del map llama al destructor del objeto...
} //Pero no lo he comprobado del todo.
_textures.erase(name);
}
void AssetManager::ProcessAssetQueue(int amount) void AssetManager::LoadFont(std::string name, std::string fontPath)
{ {
int cantidad = amount; Font* fo = new Font(fontPath);
_fonts.insert(std::make_pair(name, fo));
if (amount == -1 || cantidad >= _assetQueue.size()) }
cantidad = _assetQueue.size();
//Load Assets from files, depending on the type.
for (int i = 0; i < cantidad; i++)
{
Asset& as = _assetQueue.front();
switch (as._type)
{
case AssetType::Texture:
{
LoadTexture(as._name, as._path);
break;
}
case AssetType::Font:
{
LoadFont(as._name, as._path);
break;
}
default:
{
UE_LOG_WARN("Asset {0}, Type {1} Cannot be loaded from {2}", as._name, as._type, as._path);
break;
}
}
_assetQueue.pop_front();
}
}
void AssetManager::RemoveFont(std::string name)
{
//Se supone que el erase del map llama al destructor del objeto...
//Pero no lo he comprobado del todo.
_fonts.erase(name);
}
void AssetManager::LoadTexture(std::string name, std::string txPath) //////////DEBUG//////////
{
Texture* tx = new Texture(txPath, _SDL_Renderer);
_textures.insert(std::make_pair(name, tx));
//std::fstream file(txPath.c_str());
//json jread = json::parse(file);
//std::string path = jread["TexturePath"];
////Cargamos la textura.
//SDL_Surface* loadSurface = IMG_Load(path.c_str());
//SDL_Texture* tx = SDL_CreateTextureFromSurface(_mainRenderer, loadSurface);
//_textures.insert(std::make_pair(name, tx));
//SDL_FreeSurface(loadSurface);
////Almacenamos los Rects (sprites) de esa textura.
//json textureRects = jread["TextureRects"];
//_textureRects.insert(std::make_pair(name, std::vector<SDL_Rect>()));
//std::vector<SDL_Rect>& vector = _textureRects.at(name);
//for (int i = 0; i < textureRects.size(); i++)
//{
// //json rectData = textureRects.at(i);
// //SDL_Rect rect;
// //rect.x = rectData.at()
// vector.push_back(textureRects.at(i).get<SDL_Rect>());
//}
//file.close(); void AssetManager::PrintAssetInfo()
} {
std::cout << "AM - Debug INFO: " << std::endl;
for (int i = 0; i < _assetQueue.size(); i++) {
std::cout << _assetQueue[i]._name << " - " << _assetQueue[i]._path << std::endl;
}
}
/////////////////////////
void AssetManager::RemoveTexture(std::string name)
{
//Se supone que el erase del map llama al destructor del objeto...
//Pero no lo he comprobado del todo.
_textures.erase(name);
}
void AssetManager::LoadFont(std::string name, std::string fontPath)
{
Font* fo = new Font(fontPath);
_fonts.insert(std::make_pair(name, fo));
}
void AssetManager::RemoveFont(std::string name)
{
//Se supone que el erase del map llama al destructor del objeto...
//Pero no lo he comprobado del todo.
_fonts.erase(name);
}
//////////DEBUG//////////
void AssetManager::PrintAssetInfo()
{
std::cout << "AM - Debug INFO: " << std::endl;
for (int i = 0; i < _assetQueue.size(); i++) {
std::cout << _assetQueue[i]._name << " - " << _assetQueue[i]._path << std::endl;
}
}
/////////////////////////
} }
+119 -121
View File
@@ -1,7 +1,5 @@
#pragma once #pragma once
#pragma once
/*STD Includes*/ /*STD Includes*/
#include <filesystem> #include <filesystem>
#include <deque> #include <deque>
@@ -13,20 +11,20 @@
#include <SDL_image.h> #include <SDL_image.h>
/*UberEngine Includes*/ /*UberEngine Includes*/
#include "Assets\Asset.h" #include "Assets/Asset.h"
#include "Assets\Texture.h" #include "Assets/Texture.h"
#include "Assets\Font.h" #include "Assets/Font.h"
using json = nlohmann::ordered_json; using json = nlohmann::ordered_json;
/// ///
/// TODO: /// TODO:
/// - Modificar las funciones de Carga para quitar la queue o implementar una que tenga sentido. /// - Modificar las funciones de Carga para quitar la queue o implementar una que tenga sentido.
/// Por ejemplo, se puede crear una cola (std::deque) y cargar un asset cada gameLoop en vez de /// Por ejemplo, se puede crear una cola (std::deque) y cargar un asset cada gameLoop en vez de
/// procesar toda la cola de golpe. Optimizaría la carga de assets. /// procesar toda la cola de golpe. Optimizar�a la carga de assets.
/// - Terminar la implementación del tipo de carga (queue/now). /// - Terminar la implementaci�n del tipo de carga (queue/now).
/// - Modificar los for en la carga de archivo, así como la estructura del archivo JSON. El tipo de Asset está repetido. /// - Modificar los for en la carga de archivo, as� como la estructura del archivo JSON. El tipo de Asset est� repetido.
/// - Logging. /// - Logging.
/// - ERROR HANDLING /// - ERROR HANDLING
/// - More asset types. /// - More asset types.
@@ -34,151 +32,151 @@ using json = nlohmann::ordered_json;
namespace UE namespace UE
{ {
/* Gestiona todos assets primitivos, almacenando sus ptrs en un lugar seguro. */ /* Gestiona todos assets primitivos, almacenando sus ptrs en un lugar seguro. */
class AssetManager class AssetManager
{ {
public: public:
/* Constructor. */ /* Constructor. */
AssetManager(SDL_Renderer* SDLrenderer) AssetManager(SDL_Renderer* SDLrenderer)
: _SDL_Renderer(SDLrenderer) {} : _SDL_Renderer(SDLrenderer) {}
/** /**
* Init AssetManager y todo lo necesario para funcionar correctamente. * Init AssetManager y todo lo necesario para funcionar correctamente.
* - Inicia SDL_IMG. * - Inicia SDL_IMG.
*/ */
void InitAssetManager(); void InitAssetManager();
/** /**
* *
* Clean AssetManager Data on exit * Clean AssetManager Data on exit
* - Elimina todos los assets de sus contenedores. * - Elimina todos los assets de sus contenedores.
* - Descarga SDL_IMG * - Descarga SDL_IMG
*/ */
void CleanAssetManager(); void CleanAssetManager();
/* Carga de Assets */ /* Carga de Assets */
/** /**
* Carga los datos de los Assets desde un fichero JSON según parámetros. * Carga los datos de los Assets desde un fichero JSON seg�n par�metros.
* *
* \param filePath: Ubicación del archivo JSON. * \param filePath: Ubicaci�n del archivo JSON.
* \param loadMethod: Forma de carga. Procesado al momento o añadido a la cola de carga. * \param loadMethod: Forma de carga. Procesado al momento o a�adido a la cola de carga.
* *
*/ */
void LoadAssetsFromFile(std::string filePath); void LoadAssetsFromFile(std::string filePath);
/** /**
* Carga el Asset pasado por parámetro. * Carga el Asset pasado por par�metro.
* *
* \param as: Asset que cargar. * \param as: Asset que cargar.
* \param loadMethod: Forma de carga. Procesado al momento o añadido a la cola de carga. * \param loadMethod: Forma de carga. Procesado al momento o a�adido a la cola de carga.
* *
*/ */
void LoadAsset(Asset& as); void LoadAsset(Asset& as);
/** /**
* Procesa la cola de carga de Assets. * Procesa la cola de carga de Assets.
* *
* \param Amount: Número de Assets de la cola a procesar. Si vale -1 se procesarán todos. * \param Amount: N�mero de Assets de la cola a procesar. Si vale -1 se procesar�n todos.
* *
*/ */
void ProcessAssetQueue(int amount = -1); void ProcessAssetQueue(int amount = -1);
/** /**
* Devuelve la cantidad de Assets que quedan sin procesar en la cola. * Devuelve la cantidad de Assets que quedan sin procesar en la cola.
* De esta forma, se puede hacer un bucle hasta que la cola sea <= 0. * De esta forma, se puede hacer un bucle hasta que la cola sea <= 0.
* *
*/ */
inline int GetAssetQueueSize() { return _assetQueue.size(); } inline int GetAssetQueueSize() { return _assetQueue.size(); }
/// <summary> /// <summary>
/// Comprueba si la cola de carga de Assets está vacía. /// Comprueba si la cola de carga de Assets est� vac�a.
/// </summary> /// </summary>
/// <returns>El resultado de la cola.</returns> /// <returns>El resultado de la cola.</returns>
inline bool IsAssetQueueEmpty() { return _assetQueue.empty(); } inline bool IsAssetQueueEmpty() { return _assetQueue.empty(); }
/*--------------------------------------/ /*--------------------------------------/
* Métodos para manejar las texturas. * * M�todos para manejar las texturas. *
*--------------------------------------*/ *--------------------------------------*/
//Crea una textura de SDL y la añade al mapa de texturas identificada por su nombre. //Crea una textura de SDL y la a�ade al mapa de texturas identificada por su nombre.
void LoadTexture(std::string name, std::string txPath); void LoadTexture(std::string name, std::string txPath);
//Elimina una textura del mapa a partir de su nombre. //Elimina una textura del mapa a partir de su nombre.
void RemoveTexture(std::string name); void RemoveTexture(std::string name);
//Obtiene una textura del mapa a partir de su nombre. //Obtiene una textura del mapa a partir de su nombre.
//inline SDL_Texture* getTexture(std::string textureName) { return _textures.at(textureName); } //inline SDL_Texture* getTexture(std::string textureName) { return _textures.at(textureName); }
inline Texture* getTexture(std::string textureName) { return _textures.at(textureName); } inline Texture* getTexture(std::string textureName) { return _textures.at(textureName); }
//inline std::vector<SDL_Rect>* getTexureRects(std::string textureName) { return &_textureRects.at(textureName); } //inline std::vector<SDL_Rect>* getTexureRects(std::string textureName) { return &_textureRects.at(textureName); }
/*------------------------------------/ /*------------------------------------/
* Métodos para manejar las fuentes. * * M�todos para manejar las fuentes. *
*------------------------------------*/ *------------------------------------*/
/** /**
* Crea un objeto UE:Font y lo añade al mapa de fuentes. * Crea un objeto UE:Font y lo a�ade al mapa de fuentes.
* *
* @param name : Nombre del asset (key para el mapa de fuentes). * @param name : Nombre del asset (key para el mapa de fuentes).
* @param fontPath : Ubicación del archivo de datos sobre la fuente. * @param fontPath : Ubicaci�n del archivo de datos sobre la fuente.
* *
*/ */
void LoadFont(std::string name, std::string fontPath); void LoadFont(std::string name, std::string fontPath);
/** /**
* Elimina una fuente (y en teoría limpia la fuente) dado su nombre de Asset. * Elimina una fuente (y en teor�a limpia la fuente) dado su nombre de Asset.
* *
* @param name : Nombre del Asset (key del mapa de fuentes). * @param name : Nombre del Asset (key del mapa de fuentes).
* *
*/ */
void RemoveFont(std::string name); void RemoveFont(std::string name);
/** /**
* Obtiene y devuelve el ptr a una fuente dado su nombre de asset. * Obtiene y devuelve el ptr a una fuente dado su nombre de asset.
* *
* @param fontName : Nombre del Asset. * @param fontName : Nombre del Asset.
* @return UE::Font* : El ptr a la fuente solicitada. * @return UE::Font* : El ptr a la fuente solicitada.
* *
*/ */
inline Font* GetFont(std::string fontName) { return _fonts.at(fontName); } inline Font* GetFont(std::string fontName) { return _fonts.at(fontName); }
///////DEBUG//////// ///////DEBUG////////
void PrintAssetInfo(); void PrintAssetInfo();
/////////////////// ///////////////////
private: private:
//---------------------- //----------------------
//VARIABLES //VARIABLES
//--------------------- //---------------------
//std::string _assetPath; //std::string _assetPath;
//std::vector<UE::Asset> _assets = {}; //std::vector<UE::Asset> _assets = {};
std::deque<UE::Asset> _assetQueue = {}; std::deque<UE::Asset> _assetQueue = {};
/* Almacenes de asssets */ /* Almacenes de asssets */
//Almacén de SDL_Texture* (ptrs, pues lo gestiona SDL). //Almac�n de SDL_Texture* (ptrs, pues lo gestiona SDL).
//std::unordered_map<std::string, SDL_Texture*> _textures = {}; //std::unordered_map<std::string, SDL_Texture*> _textures = {};
//std::unordered_map<std::string, std::vector<SDL_Rect>> _textureRects = {}; //std::unordered_map<std::string, std::vector<SDL_Rect>> _textureRects = {};
std::unordered_map <std::string, Texture*> _textures = {}; std::unordered_map <std::string, Texture*> _textures = {};
//Almacen de TTF_Fonts* (Para las fuentes de SDL_TTF). //Almacen de TTF_Fonts* (Para las fuentes de SDL_TTF).
std::unordered_map<std::string, Font*> _fonts = {}; std::unordered_map<std::string, Font*> _fonts = {};
//Necesario para crear las SDL_Texture a partir de SDL_Surface. //Necesario para crear las SDL_Texture a partir de SDL_Surface.
SDL_Renderer* _SDL_Renderer = NULL; SDL_Renderer* _SDL_Renderer = NULL;
}; };
} }
+46 -46
View File
@@ -1,79 +1,79 @@
#include "Font.h" #include "Font.h"
#include "Logging\Logger.h" #include "Logging/Logger.h"
#include <fstream> #include <fstream>
#include <json\json.hpp> #include <json/json.hpp>
using json = nlohmann::ordered_json; using json = nlohmann::ordered_json;
TTF_Font* UE::Font::GetFont(int size) TTF_Font* UE::Font::GetFont(int size)
{ {
TTF_Font* font; TTF_Font* font;
auto it = _fonts.find(size); auto it = _fonts.find(size);
if (it == _fonts.end()) if (it == _fonts.end())
{ {
//El tamaño pedido no está disponible. //El tama�o pedido no est� disponible.
//La creamos nueva. //La creamos nueva.
font = CreateFontSize(size); font = CreateFontSize(size);
return font; return font;
} }
//En caso de estar disponible, lo retornamos. //En caso de estar disponible, lo retornamos.
font = it->second; font = it->second;
return font; return font;
} }
void UE::Font::InitFont() void UE::Font::InitFont()
{ {
//Cargamos los datos desde el archivo. //Cargamos los datos desde el archivo.
std::fstream file(_dataPath.c_str()); std::fstream file(_dataPath.c_str());
if (!file.is_open()) if (!file.is_open())
{ {
UE_LOG_ERROR("No se ha podido abrir el archivo de datos de fuente: {0}", _fontPath); UE_LOG_ERROR("No se ha podido abrir el archivo de datos de fuente: {0}", _fontPath);
return; return;
} }
json jread = json::parse(file); json jread = json::parse(file);
_fontPath = jread["FontPath"].get<std::string>(); _fontPath = jread["FontPath"].get<std::string>();
//Obtenemos los tamaños que crear de inicio. //Obtenemos los tama�os que crear de inicio.
std::vector<int> vect = jread["FontSizes"].get<std::vector<int>>(); std::vector<int> vect = jread["FontSizes"].get<std::vector<int>>();
for (auto it : vect) for (auto it : vect)
{ {
CreateFontSize(it); CreateFontSize(it);
} }
file.close(); file.close();
} }
void UE::Font::CleanFont() void UE::Font::CleanFont()
{ {
//Eliminamos todos los tamaños de las fuentes. //Eliminamos todos los tama�os de las fuentes.
for (auto i = _fonts.begin(); i != _fonts.end(); i++) for (auto i = _fonts.begin(); i != _fonts.end(); i++)
{ {
TTF_CloseFont(i->second); TTF_CloseFont(i->second);
} }
} }
TTF_Font* UE::Font::CreateFontSize(int size) TTF_Font* UE::Font::CreateFontSize(int size)
{ {
//Creamos la fuente del tamaño requerido. //Creamos la fuente del tama�o requerido.
TTF_Font* font = TTF_OpenFont(_fontPath.c_str(), size); TTF_Font* font = TTF_OpenFont(_fontPath.c_str(), size);
if (font == nullptr) if (font == nullptr)
{ {
UE_LOG_ERROR("No se ha podido crear la fuente: {0} - Size: {1}", _fontPath, size); UE_LOG_ERROR("No se ha podido crear la fuente: {0} - Size: {1}", _fontPath, size);
return nullptr; return nullptr;
} }
//La añadimos al mapa. //La a�adimos al mapa.
_fonts.insert(std::make_pair(size, font)); _fonts.insert(std::make_pair(size, font));
UE_LOG_TRACE("Font: {0} se ha creado con tamanho: {1}", _fontPath, size); UE_LOG_TRACE("Font: {0} se ha creado con tamanho: {1}", _fontPath, size);
return font; return font;
} }
+59 -59
View File
@@ -7,79 +7,79 @@
namespace UE namespace UE
{ {
/** /**
* Clase Wrapper para las SDL_Fonts. * Clase Wrapper para las SDL_Fonts.
* También sirve de "cache" para los diferentes tamaños de la fuente, de esta forma * Tambi�n sirve de "cache" para los diferentes tama�os de la fuente, de esta forma
* reducimos las veces que generamos las fuentes y podemos utilizar múltiples tamaños de forma sencilla. * reducimos las veces que generamos las fuentes y podemos utilizar m�ltiples tama�os de forma sencilla.
* *
*/ */
class Font class Font
{ {
public: public:
//----------------------- //-----------------------
//----- Constructor ----- //----- Constructor -----
//----------------------- //-----------------------
Font(std::string dataPath) Font(std::string dataPath)
: _dataPath(dataPath) : _dataPath(dataPath)
{ {
InitFont(); InitFont();
} }
~Font() ~Font()
{ {
CleanFont(); CleanFont();
} }
//----------------------- //-----------------------
//------- Methods ------- //------- Methods -------
//----------------------- //-----------------------
/** /**
* Devuelve la fuente del tamaño pedido. * Devuelve la fuente del tama�o pedido.
* En caso de no estar disponible, la genera y la añade al cache antes de devolverla. * En caso de no estar disponible, la genera y la a�ade al cache antes de devolverla.
* *
* @param size : tamaño de la fuente. * @param size : tama�o de la fuente.
* @return TTF_Font* : Fuente del tamaño solicitado. * @return TTF_Font* : Fuente del tama�o solicitado.
*/ */
TTF_Font* GetFont(int size); TTF_Font* GetFont(int size);
private: private:
/** /**
* Crea la fuente a partir del archivo de datos. * Crea la fuente a partir del archivo de datos.
*/ */
void InitFont(); void InitFont();
/** /**
* Limpia la fuente, eliminando todos sus tamaños y vaciando toda la memoria. * Limpia la fuente, eliminando todos sus tama�os y vaciando toda la memoria.
*/ */
void CleanFont(); void CleanFont();
/** /**
* Se encarga de generar el tamaño de fuente deseado. * Se encarga de generar el tama�o de fuente deseado.
* *
* @param size : tamaño a generar. * @param size : tama�o a generar.
* @return TTF_Font* : Ptr al nuevo tamaño generado. Hay que guardarlo en algún sitio. * @return TTF_Font* : Ptr al nuevo tama�o generado. Hay que guardarlo en alg�n sitio.
*/ */
TTF_Font* CreateFontSize(int size); TTF_Font* CreateFontSize(int size);
//----------------------- //-----------------------
//------ Variables ------ //------ Variables ------
//----------------------- //-----------------------
private: private:
//Ubicación del archivo de datos (.json). //Ubicaci�n del archivo de datos (.json).
std::string _dataPath = ""; std::string _dataPath = "";
//Ubicación de la tipografía (.ttf). //Ubicaci�n de la tipograf�a (.ttf).
std::string _fontPath = ""; std::string _fontPath = "";
//Caché de los diferentes tamaños de la fuente. //Cach� de los diferentes tama�os de la fuente.
std::unordered_map<int, TTF_Font*> _fonts = {}; std::unordered_map<int, TTF_Font*> _fonts = {};
}; };
} }
+36 -36
View File
@@ -1,70 +1,70 @@
#include "Texture.h" #include "Texture.h"
#include "Logging\Logger.h" #include "Logging/Logger.h"
#include "Asset.h" #include "Asset.h"
#include <fstream> #include <fstream>
#include <json\json.hpp> #include <json/json.hpp>
using json = nlohmann::ordered_json; using json = nlohmann::ordered_json;
SDL_Rect* UE::Texture::GetTextureRect(int i) SDL_Rect* UE::Texture::GetTextureRect(int i)
{ {
try try
{ {
SDL_Rect* rect = &_txRects.at(i); SDL_Rect* rect = &_txRects.at(i);
return rect; return rect;
} }
catch (const std::out_of_range&) catch (const std::out_of_range&)
{ {
UE_LOG_ERROR("La textura {0} no tiene rect {1}", _txPath, i); UE_LOG_ERROR("La textura {0} no tiene rect {1}", _txPath, i);
return &_txRects.at(0); return &_txRects.at(0);
} }
} }
void UE::Texture::InitTexture() void UE::Texture::InitTexture()
{ {
std::fstream file(_dataPath); std::fstream file(_dataPath);
//Comprobamos si el archivo se ha abierto. //Comprobamos si el archivo se ha abierto.
if (!file.is_open()) if (!file.is_open())
{ {
UE_LOG_ERROR("No se ha podido abrir el archivo de datos de textura: {0}", _dataPath); UE_LOG_ERROR("No se ha podido abrir el archivo de datos de textura: {0}", _dataPath);
return; return;
} }
json jread = json::parse(file); json jread = json::parse(file);
_txPath = jread["TexturePath"].get<std::string>(); _txPath = jread["TexturePath"].get<std::string>();
//Creamos la textura. //Creamos la textura.
CreateTexture(); CreateTexture();
//Cargamos los Rects. //Cargamos los Rects.
json textureRects = jread["TextureRects"]; json textureRects = jread["TextureRects"];
for (int i = 0; i < textureRects.size(); i++) for (int i = 0; i < textureRects.size(); i++)
{ {
AddRect(textureRects.at(i).get<SDL_Rect>()); AddRect(textureRects.at(i).get<SDL_Rect>());
} }
file.close(); file.close();
} }
void UE::Texture::CleanTexture() void UE::Texture::CleanTexture()
{ {
SDL_DestroyTexture(_texture); SDL_DestroyTexture(_texture);
_txRects.clear(); _txRects.clear();
} }
void UE::Texture::CreateTexture() void UE::Texture::CreateTexture()
{ {
SDL_Surface* loadSurface = IMG_Load(_txPath.c_str()); SDL_Surface* loadSurface = IMG_Load(_txPath.c_str());
_texture = SDL_CreateTextureFromSurface(_SDL_Renderer, loadSurface); _texture = SDL_CreateTextureFromSurface(_SDL_Renderer, loadSurface);
SDL_FreeSurface(loadSurface); SDL_FreeSurface(loadSurface);
} }
void UE::Texture::AddRect(SDL_Rect newRect) void UE::Texture::AddRect(SDL_Rect newRect)
{ {
_txRects.push_back(newRect); _txRects.push_back(newRect);
} }
+67 -67
View File
@@ -9,93 +9,93 @@
namespace UE namespace UE
{ {
class Texture class Texture
{ {
public: public:
//----------------------- //-----------------------
//----- Constructor ----- //----- Constructor -----
//----------------------- //-----------------------
Texture(std::string dataPath, SDL_Renderer* renderer) Texture(std::string dataPath, SDL_Renderer* renderer)
: _dataPath(dataPath), _SDL_Renderer(renderer) : _dataPath(dataPath), _SDL_Renderer(renderer)
{ {
InitTexture(); InitTexture();
} }
~Texture() ~Texture()
{ {
CleanTexture(); CleanTexture();
} }
//----------------------- //-----------------------
//------- Methods ------- //------- Methods -------
//----------------------- //-----------------------
/** /**
* Retorna la textura. * Retorna la textura.
*/ */
inline SDL_Texture* GetTexture() { return _texture; } inline SDL_Texture* GetTexture() { return _texture; }
/** /**
* Retorna los Rects de la textura. * Retorna los Rects de la textura.
*/ */
inline std::vector<SDL_Rect>* GetRectsVector() { return &_txRects; } inline std::vector<SDL_Rect>* GetRectsVector() { return &_txRects; }
/** /**
* Retorna el Rect pedido. Comprobando que está disponible. * Retorna el Rect pedido. Comprobando que est� disponible.
* Si no está disponible, devuelve el rect de index 0 (que debería ser el por defecto). * Si no est� disponible, devuelve el rect de index 0 (que deber�a ser el por defecto).
* *
* @param i : Índice del rect. * @param i : �ndice del rect.
* @return El SDL_Rect* solicitado (o el por defecto en caso de error). * @return El SDL_Rect* solicitado (o el por defecto en caso de error).
*/ */
SDL_Rect* GetTextureRect(int i); SDL_Rect* GetTextureRect(int i);
private: private:
/** /**
* Carga los datos desde el archivo de datos y crea la textura y sus rects. * Carga los datos desde el archivo de datos y crea la textura y sus rects.
*/ */
void InitTexture(); void InitTexture();
/** /**
* Limpia todos los datos guardados. * Limpia todos los datos guardados.
*/ */
void CleanTexture(); void CleanTexture();
/** /**
* Método encargado de generar la textura a partir de los valores de la clase. * M�todo encargado de generar la textura a partir de los valores de la clase.
*/ */
void CreateTexture(); void CreateTexture();
/** /**
* Método que añade un SDL_Rect al vector correspondiente. * M�todo que a�ade un SDL_Rect al vector correspondiente.
* @param newRect : Nuevo Rect que añadir al vector de Rects. * @param newRect : Nuevo Rect que a�adir al vector de Rects.
*/ */
void AddRect(SDL_Rect newRect); void AddRect(SDL_Rect newRect);
//----------------------- //-----------------------
//------ Variables ------ //------ Variables ------
//----------------------- //-----------------------
private: private:
//Ubicación del archivo de datos (.json). //Ubicaci�n del archivo de datos (.json).
std::string _dataPath = ""; std::string _dataPath = "";
//El propio renderer de SDL. Es necesario para crear y operar con las SDL_Textures. //El propio renderer de SDL. Es necesario para crear y operar con las SDL_Textures.
SDL_Renderer* _SDL_Renderer = nullptr; SDL_Renderer* _SDL_Renderer = nullptr;
//Ubicación de la textura (.png). //Ubicaci�n de la textura (.png).
std::string _txPath = ""; std::string _txPath = "";
//La propia textura. //La propia textura.
SDL_Texture* _texture = nullptr; SDL_Texture* _texture = nullptr;
//Conjunto de rects que hay en la textura. //Conjunto de rects que hay en la textura.
std::vector<SDL_Rect> _txRects = {}; std::vector<SDL_Rect> _txRects = {};
}; };
} }
+22 -22
View File
@@ -1,53 +1,53 @@
#include "Sprite.h" #include "Sprite.h"
#include "Render\Renderer.h" #include "Render/Renderer.h"
#include "Assets\AssetManager.h" #include "Assets/AssetManager.h"
#include "Logging\Logger.h" #include "Logging/Logger.h"
#include <iostream> #include <iostream>
void UE::Sprite::SetTextureRect(int textureID) void UE::Sprite::SetTextureRect(int textureID)
{ {
SDL_Rect* newRect = _texture->GetTextureRect(textureID); SDL_Rect* newRect = _texture->GetTextureRect(textureID);
if (newRect != nullptr) if (newRect != nullptr)
{ {
_actualTxRect = newRect; _actualTxRect = newRect;
} }
} }
void UE::Sprite::SetActive(bool active) void UE::Sprite::SetActive(bool active)
{ {
isActive = active; isActive = active;
} }
bool UE::Sprite::IsActive() bool UE::Sprite::IsActive()
{ {
return isActive; return isActive;
} }
void UE::Sprite::Draw(Renderer* renderer) void UE::Sprite::Draw(Renderer* renderer)
{ {
//Convertimos a ScreenCoords. //Convertimos a ScreenCoords.
glm::ivec2 screenCoords = renderer->WorldToSreenCoords(_pos); glm::ivec2 screenCoords = renderer->WorldToSreenCoords(_pos);
SDL_Rect position = { screenCoords.x, screenCoords.y, _size.x, _size.y }; SDL_Rect position = { screenCoords.x, screenCoords.y, _size.x, _size.y };
//destination.x = _pos.x; //destination.x = _pos.x;
//destination.y = _pos.y; //destination.y = _pos.y;
// //
//destination.w = _size.x; //destination.w = _size.x;
//destination.h = _size.y; //destination.h = _size.y;
//std::cout << "Sprite Rendered to: " << destination.x << "-" << destination.y << std::endl; //std::cout << "Sprite Rendered to: " << destination.x << "-" << destination.y << std::endl;
renderer->QueueDrawCall(_renderLayer, position, _texture->GetTexture(), *_actualTxRect); renderer->QueueDrawCall(_renderLayer, position, _texture->GetTexture(), *_actualTxRect);
} }
SDL_Rect UE::Sprite::getPositionRect() SDL_Rect UE::Sprite::getPositionRect()
{ {
SDL_Rect position = { _pos.x, _pos.y, _size.x, _size.y }; SDL_Rect position = { _pos.x, _pos.y, _size.x, _size.y };
return position; return position;
} }
+54 -53
View File
@@ -1,15 +1,16 @@
#pragma once #pragma once
#include <SDL.h> #include <SDL.h>
#include <string> #include <string>
#include <vector> #include <vector>
//#include <glm.hpp> //#include <glm.hpp>
#include <glm\vec2.hpp> #include <glm/vec2.hpp>
#include "Render\Drawable.h" #include "Render/Drawable.h"
#include "Render\Transformable.h" #include "Render/Transformable.h"
#include "Assets\Texture.h" #include "Assets/Texture.h"
// //
// TODO: // TODO:
@@ -20,80 +21,80 @@
namespace UE namespace UE
{ {
class Renderer; class Renderer;
class Sprite : public Drawable, public Transformable class Sprite : public Drawable, public Transformable
{ {
public: public:
/* /*
// -------------- // --------------
// Constructores. // Constructores.
// -------------- // --------------
*/ */
/* /*
Se establecen todos los parámetos. Se establecen todos los par�metos.
La textura es obligatoria, y puede ha de darse: La textura es obligatoria, y puede ha de darse:
- En SDL_Texture* -> Sin más, se entiende. - En SDL_Texture* -> Sin m�s, se entiende.
En ambos casos se llama al método SetTexturePtr. En ambos casos se llama al m�todo SetTexturePtr.
Los demás parámetros tienen un valor por defecto. Los dem�s par�metros tienen un valor por defecto.
\param texturePtr: El pointer a la textura de SDL. \param texturePtr: El pointer a la textura de SDL.
\param textureRects: El pointer al conjunto de SDL_Rects de la textura. \param textureRects: El pointer al conjunto de SDL_Rects de la textura.
\param textureRectID: El número de Rect del conjunto de rects. \param textureRectID: El n�mero de Rect del conjunto de rects.
\param renderLayer: La Layer en que se renderizará. \param renderLayer: La Layer en que se renderizar�.
*/ */
Sprite(UE::Texture* texture, Sprite(UE::Texture* texture,
int textureRectID = 0, int textureRectID = 0,
int renderLayer = 1, int renderLayer = 1,
glm::vec2 position = glm::vec2(0, 0), glm::vec2 position = glm::vec2(0, 0),
glm::vec2 size = glm::vec2(100, 100)) glm::vec2 size = glm::vec2(100, 100))
: _texture(texture) : _texture(texture)
{ {
SetTextureRect(textureRectID); SetTextureRect(textureRectID);
SetLayer(renderLayer); SetLayer(renderLayer);
SetPosition(position); SetPosition(position);
SetSize(size); SetSize(size);
} }
~Sprite() {} ~Sprite() {}
//----------- //-----------
//- Setters - //- Setters -
//----------- //-----------
void SetTextureRect(int textureID); void SetTextureRect(int textureID);
void SetActive(bool active); void SetActive(bool active);
bool IsActive(); bool IsActive();
//Implementa el Draw de Drawable. //Implementa el Draw de Drawable.
void Draw(Renderer* renderer) override; void Draw(Renderer* renderer) override;
SDL_Rect getPositionRect(); SDL_Rect getPositionRect();
private: private:
//Datos de la textura. Sirven para pedirla al AssetManager. //Datos de la textura. Sirven para pedirla al AssetManager.
UE::Texture* _texture = nullptr; UE::Texture* _texture = nullptr;
//El que se va a renderizar. //El que se va a renderizar.
SDL_Rect* _actualTxRect = nullptr; SDL_Rect* _actualTxRect = nullptr;
bool isActive = true; bool isActive = true;
}; };
} }
+49 -49
View File
@@ -1,32 +1,32 @@
#include "TextBox.h" #include "TextBox.h"
#include "Logging\Logger.h" #include "Logging/Logger.h"
#include "Render\Renderer.h" #include "Render/Renderer.h"
void UE::TextBox::SetText(std::string newText) void UE::TextBox::SetText(std::string newText)
{ {
_text = newText; _text = newText;
RenderTextTexture(); RenderTextTexture();
} }
void UE::TextBox::SetSize(int newSize) void UE::TextBox::SetSize(int newSize)
{ {
_textSize = newSize; _textSize = newSize;
RenderTextTexture(); RenderTextTexture();
} }
void UE::TextBox::SetColor(UE_Color newColor) void UE::TextBox::SetColor(UE_Color newColor)
{ {
_textColor = newColor; _textColor = newColor;
RenderTextTexture(); RenderTextTexture();
} }
void UE::TextBox::SetColor(int r, int g, int b, int a) void UE::TextBox::SetColor(int r, int g, int b, int a)
{ {
UE_Color c = UE_Color(r, g, b, a); UE_Color c = UE_Color(r, g, b, a);
_textColor = c; _textColor = c;
RenderTextTexture(); RenderTextTexture();
} }
@@ -34,56 +34,56 @@ void UE::TextBox::SetColor(int r, int g, int b, int a)
void UE::TextBox::Draw(Renderer* renderer) void UE::TextBox::Draw(Renderer* renderer)
{ {
//Si aún no tenemos renderer, lo guardamos y procesamos. //Si a�n no tenemos renderer, lo guardamos y procesamos.
if (_sdlRenderer == nullptr) if (_sdlRenderer == nullptr)
{ {
_sdlRenderer = renderer->GetSDLRenderer(); _sdlRenderer = renderer->GetSDLRenderer();
RenderTextTexture(); RenderTextTexture();
} }
if (_textTexture == nullptr) if (_textTexture == nullptr)
{ {
UE_LOG_WARN("El texto: {0} ; No se está renderizando. La textura no existe.", _text); UE_LOG_WARN("El texto: {0} ; No se est� renderizando. La textura no existe.", _text);
return; return;
} }
//Generamos el SDL_Rect destino. //Generamos el SDL_Rect destino.
SDL_Rect dest = { _pos.x, _pos.y, _size.x, _size.y }; SDL_Rect dest = { _pos.x, _pos.y, _size.x, _size.y };
renderer->QueueDrawCall(_renderLayer, dest, _textTexture); renderer->QueueDrawCall(_renderLayer, dest, _textTexture);
} }
void UE::TextBox::RenderTextTexture() void UE::TextBox::RenderTextTexture()
{ {
//No podemos continuar hasta que no tengamos un renderer. //No podemos continuar hasta que no tengamos un renderer.
if (_sdlRenderer == nullptr) { return; } if (_sdlRenderer == nullptr) { return; }
SDL_DestroyTexture(_textTexture); SDL_DestroyTexture(_textTexture);
//Creamos el SDL_Color a partir del vec4 que contiene el color. //Creamos el SDL_Color a partir del vec4 que contiene el color.
SDL_Color color = { _textColor.x,_textColor.y, _textColor.z, _textColor.w }; SDL_Color color = { _textColor.x,_textColor.y, _textColor.z, _textColor.w };
//Tomamos la TTF_Font del tamaño que queremos de UE::Font. //Tomamos la TTF_Font del tama�o que queremos de UE::Font.
TTF_Font* fn = _font->GetFont(_textSize); TTF_Font* fn = _font->GetFont(_textSize);
SDL_Surface* loader = TTF_RenderText_Solid(fn, _text.c_str(), color); SDL_Surface* loader = TTF_RenderText_Solid(fn, _text.c_str(), color);
if (loader == NULL) if (loader == NULL)
{ {
UE_LOG_ERROR("No se ha podido crear el texto: {0} ; Error: {1}", UE_LOG_ERROR("No se ha podido crear el texto: {0} ; Error: {1}",
_text, TTF_GetError()); _text, TTF_GetError());
return; return;
} }
_textTexture = SDL_CreateTextureFromSurface(_sdlRenderer, loader); _textTexture = SDL_CreateTextureFromSurface(_sdlRenderer, loader);
if (_textTexture == NULL) if (_textTexture == NULL)
{ {
UE_LOG_ERROR("No se ha podido crear la textura del texto: {0} ; Error: {1}", UE_LOG_ERROR("No se ha podido crear la textura del texto: {0} ; Error: {1}",
_text, SDL_GetError()); _text, SDL_GetError());
return; return;
} }
_size.x = loader->w; _size.x = loader->w;
_size.y = loader->h; _size.y = loader->h;
SDL_FreeSurface(loader); SDL_FreeSurface(loader);
} }
+42 -42
View File
@@ -2,69 +2,69 @@
#include <SDL.h> #include <SDL.h>
#include <SDL_ttf.h> #include <SDL_ttf.h>
#include <glm\vec4.hpp> #include <glm/vec4.hpp>
#include "Render\Drawable.h" #include "Render/Drawable.h"
#include "Render\Transformable.h" #include "Render/Transformable.h"
#include "Assets\Font.h" #include "Assets/Font.h"
namespace UE namespace UE
{ {
typedef glm::tvec4<int> UE_Color; typedef glm::tvec4<int> UE_Color;
class TextBox : public Drawable, public Transformable class TextBox : public Drawable, public Transformable
{ {
public: public:
TextBox(UE::Font* font, TextBox(UE::Font* font,
std::string text = "Texto por defecto", std::string text = "Texto por defecto",
int textSize = 18, int textSize = 18,
UE_Color textColor = UE_Color(0, 0, 0, 255), UE_Color textColor = UE_Color(0, 0, 0, 255),
int renderLayer = 1, int renderLayer = 1,
glm::vec2 position = glm::vec2(0, 0)) glm::vec2 position = glm::vec2(0, 0))
: _font(font), _text(text), _textSize(textSize) : _font(font), _text(text), _textSize(textSize)
{ {
SetColor(textColor); SetColor(textColor);
SetLayer(renderLayer); SetLayer(renderLayer);
SetPosition(position); SetPosition(position);
RenderTextTexture(); RenderTextTexture();
} }
//Se generará una textura y todo eso... //Se generar� una textura y todo eso...
void SetText(std::string newText); void SetText(std::string newText);
void SetSize(int newSize); void SetSize(int newSize);
void SetColor(UE_Color newColor); void SetColor(UE_Color newColor);
void SetColor(int r, int g, int b, int a); void SetColor(int r, int g, int b, int a);
//Implementa el Draw de Drawable. //Implementa el Draw de Drawable.
void Draw(Renderer* renderer) override; void Draw(Renderer* renderer) override;
private: private:
void RenderTextTexture(); void RenderTextTexture();
private: private:
UE::Font* _font = nullptr; UE::Font* _font = nullptr;
std::string _text = "Texto por defecto"; std::string _text = "Texto por defecto";
int _textSize = 18; int _textSize = 18;
UE_Color _textColor; UE_Color _textColor;
SDL_Texture* _textTexture = nullptr; SDL_Texture* _textTexture = nullptr;
//Esto está muy mal hecho, no debería de ser así. //Esto est� muy mal hecho, no deber�a de ser as�.
//Necesito un renderer para crear la textura del texto, pero no puedo conseguirlo con la arquitectura actual. //Necesito un renderer para crear la textura del texto, pero no puedo conseguirlo con la arquitectura actual.
//No quiero regenerar la textura en cada frame de forma innecesaria... //No quiero regenerar la textura en cada frame de forma innecesaria...
//Por ello, me toca forzar un poco el sistema. //Por ello, me toca forzar un poco el sistema.
SDL_Renderer* _sdlRenderer = nullptr; SDL_Renderer* _sdlRenderer = nullptr;
}; };
} }
+152
View File
@@ -0,0 +1,152 @@
#include "Engine.h"
#include "Logging/Logger.h"
#include "Render/Renderer.h"
#include "Assets/AssetManager.h"
#include "Scene/SceneManager.h"
namespace UE
{
//Le decimos a C++ que son objetos static y que los cree cuando vea.
Renderer* Engine::_renderer;
AssetManager* Engine::_assetManager;
SceneManager* Engine::_sceneManager;
int Engine::Init()
{
//Lo primero, es iniciar el Logger, para poder imprimir errores.
UE::Logger::InitLogger();
//Etapa de carga de librerías.
if(InitLibs() < 0) //Retorna negativos en caso de error.
{
UE_LOG_CRITICAL("Engine - Error al inicial las librerías");
return -1;
}
//Iniciamos los sistemas del motor.
if(InitRenderer() < 0)
{
UE_LOG_CRITICAL("Engine - Error al iniciar el renderer.");
return -2;
}
if(InitAssetManager() < 0)
{
UE_LOG_CRITICAL("Engine - Error al inicial el AssetManager.");
return -3;
}
if(InitSceneManager() < 0)
{
UE_LOG_CRITICAL("Engine - Error al inicial el SceneManager.");
return -4;
}
UE_LOG_INFO("Engine - El motor se ha iniciado correctamente.");
return 0;
}
void Engine::Clean()
{
//Etapa para limpiar los sistemas del motor.
_sceneManager->CleanSceneManager();
delete _sceneManager;
_assetManager->CleanAssetManager();
delete _assetManager;
_renderer->CleanRenderer();
delete _renderer;
//Etapa para desactivar y limpiar todas las librerías.
QuitLibs();
}
int Engine::InitLibs()
{
//Iniciamos SDL.
SDL_HINT_RENDER_DRIVER "opengl";
Uint32 SDL_Flags = SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_EVENTS;
if (SDL_Init(SDL_Flags) < 0)
{
UE_LOG_CRITICAL("Engine - SDL: Error al iniciar SDL: {0}", SDL_GetError());
return -1;
}
UE_LOG_TRACE("Engine - SDL se ha iniciado correctamente");
//Iniciamos SDL_Image
if (IMG_Init(IMG_INIT_PNG) == 0) //Retorna 0 en caso de fallo.
{
UE_LOG_ERROR("Engine - SDL_Image: Error al iniciarse: {0}", IMG_GetError());
return -2;
}
UE_LOG_TRACE("Engine - SDL_Image se ha iniciado correctamente");
//Iniciamos el SDL_TTF
if (TTF_Init() < 0) //Retorna -1 en caso de error.
{
UE_LOG_ERROR("Engine - SDL_TTF: Error al inicarse: {0}", TTF_GetError());
return -3;
}
UE_LOG_TRACE("Engine - SDL_TTF se ha iniciado correctamente");
return 0;
}
int Engine::InitRenderer()
{
//Cargamos el Renderer.
//Hay que implementar un sistema de flags o
// una struct de configuración para la inicialización del renderer.
_renderer = new UE::Renderer(640, 480, 5);
if(_renderer->InitRenderer() < 0)
{
return -1;
}
UE_LOG_TRACE("Engine - Renderer: Se ha iniciado correctamente");
return 0;
}
int Engine::InitAssetManager()
{
//Cargamos el AssetManager
//Faltaría control de errores en caso de haberlo.
_assetManager = new UE::AssetManager(_renderer->GetSDLRenderer());
_assetManager->InitAssetManager();
UE_LOG_TRACE("Engine - AssetManager: Se ha iniciado correctamente");
return 0;
}
int Engine::InitSceneManager()
{
//Cargamos el SceneManager
//Faltaría control de errores en caso de haberlo.
_sceneManager = new UE::SceneManager();
UE_LOG_TRACE("Engine - SceneManager: Se ha iniciado correctamente.");
return 0;
}
int Engine::QuitLibs()
{
TTF_Quit();
IMG_Quit();
SDL_Quit();
return 0;
}
}
+80
View File
@@ -0,0 +1,80 @@
#pragma once
namespace UE
{
//Declaraciones de clases de UberEngine
class Renderer;
class AssetManager;
class SceneManager;
/* Clase Principal del motor.
* Carga todas los sistemas y librerías al inicio y los descarga al final.
* Contiene ptrs a los sistemas principales.
*/
class Engine
{
public:
/*
* Inicia todos los sistemas y librerías necesarias.
* Retornará 0 o un código de error negativo.
*/
static int Init();
/*
* Limpia todas las cosas del motor.
*/
static void Clean();
inline static UE::Renderer* GetRenderer() { return _renderer; }
inline static UE::AssetManager* GetAssetManager() { return _assetManager; }
inline static UE::SceneManager* GetSceneManager() { return _sceneManager; }
private:
//Vamos a crear un método para la inicialización de cada sistema.
// de esta forma, debería ser más fácil modificar la inicialización cuando sea necesario.
/*
* Inicializa las librerías de SDL.
* Retorna códigos de error negativos.
*/
static int InitLibs();
/*
* Inicializa el renderer.
* En un futuro, debería ser configurable, además de soportar distintos backends.
*/
static int InitRenderer();
/*
* Inicializa el AssetManager.
* Es necesario iniciar primero el Renderer para poder acceder al SDL_Renderer.
* (al menos, mientras usemos el SDL_Renderer.)
*/
static int InitAssetManager();
/*
* Inicializa el SceneManager.
*/
static int InitSceneManager();
/*
* Al igual que se inician, hay que limpiar las libs.
*/
static int QuitLibs();
/*
* Ptrs de los sistemas.
*/
static Renderer* _renderer;
static AssetManager* _assetManager;
static SceneManager* _sceneManager;
};
}
+11 -11
View File
@@ -1,22 +1,22 @@
#include "Logger.h" #include "Logger.h"
#include "spdlog\sinks\stdout_color_sinks.h" #include "spdlog/sinks/stdout_color_sinks.h"
namespace UE namespace UE
{ {
std::shared_ptr<spdlog::logger> Logger::_engineLogger; std::shared_ptr<spdlog::logger> Logger::_engineLogger;
std::shared_ptr<spdlog::logger> Logger::_gameLogger; std::shared_ptr<spdlog::logger> Logger::_gameLogger;
void Logger::InitLogger() void Logger::InitLogger()
{ {
spdlog::set_pattern("%^[%T]: %l - %n: %v %$"); spdlog::set_pattern("%^[%T]: %l - %n: %v %$");
_engineLogger = spdlog::stdout_color_mt("UberEngine"); _engineLogger = spdlog::stdout_color_mt("UberEngine");
_engineLogger->set_level(spdlog::level::trace); _engineLogger->set_level(spdlog::level::trace);
_gameLogger = spdlog::stdout_color_mt("UberGame1"); _gameLogger = spdlog::stdout_color_mt("UberGame1");
_gameLogger->set_level(spdlog::level::trace); _gameLogger->set_level(spdlog::level::trace);
} }
} }
+24 -24
View File
@@ -1,41 +1,41 @@
#pragma once #pragma once
#include "spdlog\spdlog.h" #include "spdlog/spdlog.h"
#include <memory> #include <memory>
namespace UE namespace UE
{ {
class Logger class Logger
{ {
public: public:
static void InitLogger(); static void InitLogger();
inline static std::shared_ptr<spdlog::logger>& GetGameLogger() { return _gameLogger; } inline static std::shared_ptr<spdlog::logger>& GetGameLogger() { return _gameLogger; }
inline static std::shared_ptr<spdlog::logger>& GetEngineLogger() { return _engineLogger; } inline static std::shared_ptr<spdlog::logger>& GetEngineLogger() { return _engineLogger; }
private: private:
static std::shared_ptr<spdlog::logger> _engineLogger; static std::shared_ptr<spdlog::logger> _engineLogger;
static std::shared_ptr<spdlog::logger> _gameLogger; static std::shared_ptr<spdlog::logger> _gameLogger;
}; };
//Macros para el Logging. Es más cómodo que estar poniendo la línea entera cada vez... //Macros para el Logging. Es más cómodo que estar poniendo la línea entera cada vez...
#define UE_LOG_TRACE(...) ::UE::Logger::GetEngineLogger()->trace(__VA_ARGS__) #define UE_LOG_TRACE(...) ::UE::Logger::GetEngineLogger()->trace(__VA_ARGS__)
#define UE_LOG_DEBUG(...) ::UE::Logger::GetEngineLogger()->debug(__VA_ARGS__) #define UE_LOG_DEBUG(...) ::UE::Logger::GetEngineLogger()->debug(__VA_ARGS__)
#define UE_LOG_INFO(...) ::UE::Logger::GetEngineLogger()->info(__VA_ARGS__) #define UE_LOG_INFO(...) ::UE::Logger::GetEngineLogger()->info(__VA_ARGS__)
#define UE_LOG_WARN(...) ::UE::Logger::GetEngineLogger()->warn(__VA_ARGS__) #define UE_LOG_WARN(...) ::UE::Logger::GetEngineLogger()->warn(__VA_ARGS__)
#define UE_LOG_ERROR(...) ::UE::Logger::GetEngineLogger()->error(__VA_ARGS__) #define UE_LOG_ERROR(...) ::UE::Logger::GetEngineLogger()->error(__VA_ARGS__)
#define UE_LOG_CRITICAL(...) ::UE::Logger::GetEngineLogger()->critical(__VA_ARGS__) #define UE_LOG_CRITICAL(...) ::UE::Logger::GetEngineLogger()->critical(__VA_ARGS__)
#define GAME_LOG_TRACE(...) ::UE::Logger::GetEngineLogger()->trace(__VA_ARGS__) #define GAME_LOG_TRACE(...) ::UE::Logger::GetEngineLogger()->trace(__VA_ARGS__)
#define GAME_LOG_DEBUG(...) ::UE::Logger::GetEngineLogger()->debug(__VA_ARGS__) #define GAME_LOG_DEBUG(...) ::UE::Logger::GetEngineLogger()->debug(__VA_ARGS__)
#define GAME_LOG_INFO(...) ::UE::Logger::GetEngineLogger()->info(__VA_ARGS__) #define GAME_LOG_INFO(...) ::UE::Logger::GetEngineLogger()->info(__VA_ARGS__)
#define GAME_LOG_WARN(...) ::UE::Logger::GetEngineLogger()->warn(__VA_ARGS__) #define GAME_LOG_WARN(...) ::UE::Logger::GetEngineLogger()->warn(__VA_ARGS__)
#define GAME_LOG_ERROR(...) ::UE::Logger::GetEngineLogger()->error(__VA_ARGS__) #define GAME_LOG_ERROR(...) ::UE::Logger::GetEngineLogger()->error(__VA_ARGS__)
#define GAME_LOG_CRITICAL(...) ::UE::Logger::GetEngineLogger()->critical(__VA_ARGS__) #define GAME_LOG_CRITICAL(...) ::UE::Logger::GetEngineLogger()->critical(__VA_ARGS__)
} }
+16
View File
@@ -0,0 +1,16 @@
#include "Camera.h"
#include "Logging/Logger.h"
namespace UE
{
void Camera::SetCamPosition(int posX, int posY)
{
camPosition.x = posX;
camPosition.y = posY;
UE_LOG_TRACE("Cam position chaged to: {0}x{1}", posX, posY);
}
}
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include <glm/vec2.hpp>
//
// ToDO:
// - La cámara debería tener un tamaño definido.
// para hacer zoom y esas cosas.
//
namespace UE
{
class Camera
{
public:
Camera() {}
Camera(int posX, int posY)
: camPosition{posX, posY}
{}
inline glm::ivec2 GetCamPosition() { return camPosition; }
void SetCamPosition(int posX, int posY);
private:
glm::ivec2 camPosition { 0, 0 };
//glm::ivec2 camSize { 0, 0 };
};
}
+15 -15
View File
@@ -2,26 +2,26 @@
namespace UE namespace UE
{ {
class Renderer; class Renderer;
class Drawable class Drawable
{ {
public: public:
Drawable() {} Drawable() {}
virtual ~Drawable() {}; virtual ~Drawable() {};
//Get-Set del renderLayer. //Get-Set del renderLayer.
inline void SetLayer(int newLayer) { _renderLayer = newLayer; } inline void SetLayer(int newLayer) { _renderLayer = newLayer; }
inline int GetLayer() { return _renderLayer; } inline int GetLayer() { return _renderLayer; }
public: public:
virtual void Draw(Renderer* renderer) = 0; virtual void Draw(Renderer* renderer) = 0;
protected: protected:
//renderLayer usada en el renderer como "profundidad". //renderLayer usada en el renderer como "profundidad".
int _renderLayer = 0; int _renderLayer = 0;
}; };
} }
+185 -201
View File
@@ -1,269 +1,253 @@
#include <iostream> #include <iostream>
#include <ImGui\imgui.h> #include <ImGui/imgui.h>
#include <ImGui\imgui_impl_sdl.h> #include <ImGui/imgui_impl_sdl.h>
#include <ImGui\imgui_impl_sdlrenderer.h> #include <ImGui/imgui_impl_sdlrenderer.h>
//#include <ImGui\imgui_impl_opengl3.h> //#include <ImGui/imgui_impl_opengl3.h>
#include <SDL\include\SDL_opengl.h> #include <SDL_opengl.h>
#include "Renderer.h" #include "Renderer.h"
#include "Logging\Logger.h" #include "Logging/Logger.h"
namespace UE namespace UE
{ {
//class Game; int Renderer::InitRenderer()
{
//Configuramos los par�metros de la ventana de SDL.
Uint32 windowFlags = (SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE);
int Renderer::InitRenderer() //Creamos la ventana de SDL.
{ _window = SDL_CreateWindow("UberGame1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screenSize.x, screenSize.y, windowFlags);
//Iniciamos SDL. if (_window == NULL)
SDL_HINT_RENDER_DRIVER "opengl"; {
UE_LOG_CRITICAL("Renderer - CreateWindow: No se ha podido crear la ventana con OpenGL: {0}", SDL_GetError());
return -1;
}
Uint32 SDL_Flags = SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_EVENTS; //Creamos el Renderer de SDL.
if (SDL_Init(SDL_Flags) < 0) main_Renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
{ if (main_Renderer == NULL)
UE_LOG_CRITICAL("No se ha podido iniciar SDL, sufre mamón: {0}", SDL_GetError()); {
return 1; UE_LOG_CRITICAL("Renderer - SDL_Renderer: No se ha podido crear el Renderer de SDL: {0}", SDL_GetError());
} return -2;
}
//Configuramos los parámetros de la ventana de SDL. SDL_SetRenderDrawColor(main_Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
Uint32 windowFlags = (SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE);
//Creamos la ventana de SDL.
_window = SDL_CreateWindow("UberGame1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screenSize.x, screenSize.y, windowFlags);
if (_window == NULL)
{
UE_LOG_CRITICAL("No se ha podido crear la ventana de SDL con OpenGL y esas mierdas: {0}", SDL_GetError());
return 1;
}
//Creamos el Renderer de SDL.
main_Renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
if (main_Renderer == NULL)
{
UE_LOG_CRITICAL("No se ha podido crear el Renderer de SDL: {0}", SDL_GetError());
}
SDL_SetRenderDrawColor(main_Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
#pragma region ImGui. #pragma region ImGui.
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
ImGui::CreateContext(); ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
(void)io; //Evita que de un Warning por variable no usada. (void)io; //Evita que de un Warning por variable no usada.
ImGui::StyleColorsDark(); ImGui::StyleColorsDark();
ImGui_ImplSDL2_InitForSDLRenderer(_window); ImGui_ImplSDL2_InitForSDLRenderer(_window, main_Renderer);
ImGui_ImplSDLRenderer_Init(main_Renderer); ImGui_ImplSDLRenderer_Init(main_Renderer);
#pragma endregion #pragma endregion
//Init layers. //Init layers.
for (int i = 0; i < LAYER_AMOUNT; i++) for (int i = 0; i <= LAYER_AMOUNT; i++)
{ {
renderLayers.push_back(std::vector<DrawCall>()); renderLayers.push_back(std::vector<DrawCall>());
} }
}
void Renderer::CleanRenderer() }
{
renderQueue.empty();
ImGui_ImplSDLRenderer_Shutdown(); void Renderer::CleanRenderer()
ImGui_ImplSDL2_Shutdown(); {
ImGui::DestroyContext(); renderQueue.empty();
SDL_DestroyRenderer(main_Renderer); ImGui_ImplSDLRenderer_Shutdown();
SDL_DestroyWindow(_window); ImGui_ImplSDL2_Shutdown();
} ImGui::DestroyContext();
SDL_DestroyRenderer(main_Renderer);
SDL_DestroyWindow(_window);
}
void Renderer::RenderFrame() void Renderer::RenderFrame()
{ {
NewFrame(); NewFrame();
RenderData(); RenderData();
EndFrame(); EndFrame();
} }
void Renderer::NewFrame() void Renderer::NewFrame()
{ {
SDL_RenderClear(main_Renderer); SDL_RenderClear(main_Renderer);
ImGui_ImplSDLRenderer_NewFrame(); ImGui_ImplSDLRenderer_NewFrame();
ImGui_ImplSDL2_NewFrame(); ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame(); ImGui::NewFrame();
//Quizás deberíamos limpiar la cola y las Layers aquí para eliminar residuos... //Quiz�s deber�amos limpiar la cola y las Layers aqu� para eliminar residuos...
//callCounter = 0; //callCounter = 0;
//rendererCounter = 0; //rendererCounter = 0;
}
void Renderer::RenderData() //Actualizamos el rect que representa la pantalla.
{ glm::ivec2 camPos = activeCam->GetCamPosition();
//Add items to their layer. _screenRect = {camPos.x, camPos.y, screenSize.x, screenSize.y};
for (int i = 0; i < renderQueue.size(); i++) }
{
DrawCall item = renderQueue.at(i);
//Add item i to layer number i.layer. void Renderer::RenderData()
if (item.layer > LAYER_AMOUNT) {
{ //Add items to their layer.
UE_LOG_ERROR("Error rendering data: Can't render item to Layer {0} -> out of range\n", item.layer); for (int i = 0; i < renderQueue.size(); i++)
return; {
} DrawCall item = renderQueue.at(i);
renderLayers.at(item.layer).push_back(item);
} //Add item i to layer number i.layer.
renderQueue.clear(); if (item.layer > LAYER_AMOUNT)
{
UE_LOG_ERROR("Error rendering data: Can't render item to Layer {0} -> out of range\n", item.layer);
return;
}
renderLayers.at(item.layer).push_back(item);
//Iterate layers. }
for (int j = 0; j < renderLayers.size(); j++) renderQueue.clear();
{
std::vector<DrawCall>& layer = renderLayers.at(j);
//Render items from layer j.
for (int k = 0; k < layer.size(); k++)
{
DrawCall item = layer.at(k);
if (item.fullTexture)
{
SDL_RenderCopy(main_Renderer, item.tx, NULL, &item.pos_rect);
continue;
}
SDL_RenderCopy(main_Renderer, item.tx, &item.tx_rect, &item.pos_rect);
}
layer.clear();
}
} //Iterate layers.
for (int j = 0; j < renderLayers.size(); j++)
{
std::vector<DrawCall>& layer = renderLayers.at(j);
//Render items from layer j.
for (int k = 0; k < layer.size(); k++)
{
DrawCall item = layer.at(k);
if (item.fullTexture)
{
SDL_RenderCopy(main_Renderer, item.tx, NULL, &item.pos_rect);
continue;
}
SDL_RenderCopy(main_Renderer, item.tx, &item.tx_rect, &item.pos_rect);
}
layer.clear();
}
}
void Renderer::EndFrame() void Renderer::EndFrame()
{ {
//SDL_UpdateWindowSurface(window); //SDL_UpdateWindowSurface(window);
//SDL_RenderPresent(main_Renderer); //SDL_RenderPresent(main_Renderer);
//SDL_RenderClear(main_Renderer); //SDL_RenderClear(main_Renderer);
ImGui::Render(); ImGui::Render();
ImGui_ImplSDLRenderer_RenderDrawData(ImGui::GetDrawData()); ImGui_ImplSDLRenderer_RenderDrawData(ImGui::GetDrawData());
SDL_RenderPresent(main_Renderer); SDL_RenderPresent(main_Renderer);
//UE_LOG_INFO("CallCounter: {0} ; Renderer: {1}", callCounter, rendererCounter); //UE_LOG_INFO("CallCounter: {0} ; Renderer: {1}", callCounter, rendererCounter);
} }
void Renderer::SetScreenSize(int newWidth, int newHeight) void Renderer::SetScreenSize(int newWidth, int newHeight)
{ {
screenSize.x = newWidth; screenSize.x = newWidth;
screenSize.y = newHeight; screenSize.y = newHeight;
SDL_SetWindowSize(_window, newWidth, newHeight); SDL_SetWindowSize(_window, newWidth, newHeight);
glViewport(0, 0, newWidth, newHeight); glViewport(0, 0, newWidth, newHeight);
UE_LOG_TRACE("Screen size chaged to: {0}x{1}", newWidth, newHeight); UE_LOG_TRACE("Screen size chaged to: {0}x{1}", newWidth, newHeight);
} }
void Renderer::SetCamPosition(int posX, int posY) void Renderer::SetDrawingColor(SDL_Color& newColor)
{ {
camPosition.x = posX; SDL_SetRenderDrawColor(main_Renderer, newColor.r, newColor.g, newColor.b, newColor.a);
camPosition.y = posY; }
//UE_LOG_TRACE("Cam position chaged to: {0}x{1}", posX, posY);
}
glm::ivec2 Renderer::WorldToSreenCoords(glm::ivec2 worldCoord) glm::ivec2 Renderer::WorldToSreenCoords(glm::ivec2 worldCoord)
{ {
//Convertimos las coordenas de WorldCoords a ScreenCoords relativas a la camPosition. //Convertimos las coordenas de WorldCoords a ScreenCoords relativas a la camPosition.
glm::ivec2 fPos = worldCoord - camPosition; glm::ivec2 fPos = worldCoord - activeCam->GetCamPosition();
return fPos; return fPos;
} }
glm::ivec2 Renderer::ScreenToWorldCoords(glm::ivec2 screenCoord) glm::ivec2 Renderer::ScreenToWorldCoords(glm::ivec2 screenCoord)
{ {
//Convertimos las coordenas de ScreenCoords a WorldCoords relativas a la camPosition. //Convertimos las coordenas de ScreenCoords a WorldCoords relativas a la camPosition.
glm::ivec2 fPos = screenCoord + camPosition; glm::ivec2 fPos = screenCoord + activeCam->GetCamPosition();
return fPos; return fPos;
} }
//CREO QUE ESTE MÉTODO NO FUNCIONA. //CREO QUE ESTE M�TODO NO FUNCIONA.
//LAS COORDS QUE USAMOS EN LA COMPROBACIÓN NO SON LAS ADECUADAS. //LAS COORDS QUE USAMOS EN LA COMPROBACI�N NO SON LAS ADECUADAS.
bool Renderer::IsObjectVisible(SDL_Rect* objectRect) bool Renderer::IsObjectVisible(SDL_Rect* objectRect)
{ {
//Comprobamos si hay intersecci�n entre ambos.
//Generamos un rect que representa la pantalla. if (!SDL_HasIntersection(&_screenRect, objectRect))
SDL_Rect screen{ camPosition.x, camPosition.y, screenSize.x, screenSize.y }; {
//Comprobamos si hay intersección entre ambos. //UE_LOG_TRACE("Se omite el renderizado de un objeto al estar fuera de la c�mara.");
if (!SDL_HasIntersection(&screen, objectRect)) return false;
{ }
//UE_LOG_TRACE("Se omite el renderizado de un objeto al estar fuera de la cámara."); return true;
return false; }
}
return true;
}
//¿Deberíamos operar la posición para que tenga en cuenta la cámara? //�Deber�amos operar la posici�n para que tenga en cuenta la c�mara?
void Renderer::DrawObject(SDL_Rect* position, SDL_Rect* texture_pos, SDL_Texture* texture) void Renderer::DrawObject(SDL_Rect* position, SDL_Rect* texture_pos, SDL_Texture* texture)
{ {
SDL_RenderCopy(main_Renderer, texture, texture_pos, position); SDL_RenderCopy(main_Renderer, texture, texture_pos, position);
} }
void Renderer::QueueDrawCall(DrawCall drawCall) void Renderer::QueueDrawCall(DrawCall drawCall)
{ {
//callCounter++; //callCounter++;
//Add item i to layer number i.layer. //Add item i to layer number i.layer.
if (drawCall.layer > LAYER_AMOUNT) if (drawCall.layer > LAYER_AMOUNT)
{ {
UE_LOG_ERROR("Can't add DrawCall to Layer {0} -> out of range\n", drawCall.layer); UE_LOG_ERROR("Can't add DrawCall to Layer {0} -> out of range\n", drawCall.layer);
return; return;
} }
//Comprobamos si el objeto es visible. // //Comprobamos si el objeto es visible.
// // if(!IsObjectVisible(&drawCall.pos_rect))
//Generamos un rect que representa la pantalla. // {
SDL_Rect screen{ 0, 0, screenSize.x, screenSize.y }; // //Si no es visible, no lo renderizaríamos.
//Comprobamos si hay intersección entre ambos. // return;
if (!SDL_HasIntersection(&screen, &drawCall.pos_rect)) // }
{
//UE_LOG_TRACE("Se omite el renderizado de un objeto al estar fuera de la cámara.");
return;
}
renderLayers.at(drawCall.layer).push_back(drawCall); renderLayers.at(drawCall.layer).push_back(drawCall);
//rendererCounter++; //rendererCounter++;
//renderQueue.push_back(drawCall); //renderQueue.push_back(drawCall);
} }
void Renderer::QueueDrawCall(int layer, SDL_Rect& position, SDL_Texture* texture, SDL_Rect& texture_position) void Renderer::QueueDrawCall(int layer, SDL_Rect& position, SDL_Texture* texture, SDL_Rect& texture_position)
{ {
DrawCall dc = DrawCall(layer, position, texture, texture_position); DrawCall dc = DrawCall(layer, position, texture, texture_position);
QueueDrawCall(dc); QueueDrawCall(dc);
} }
void Renderer::QueueDrawCall(int layer, SDL_Rect & position, SDL_Texture* texture) void Renderer::QueueDrawCall(int layer, SDL_Rect & position, SDL_Texture* texture)
{ {
//std::cout << "Drawable added to queue"; //std::cout << "Drawable added to queue";
DrawCall dc = DrawCall(layer, position, texture); DrawCall dc = DrawCall(layer, position, texture);
QueueDrawCall(dc); QueueDrawCall(dc);
} }
void Renderer::Render(Drawable& drawable) void Renderer::Render(Drawable& drawable)
{ {
drawable.Draw(this); drawable.Draw(this);
} }
} }
+125 -114
View File
@@ -5,169 +5,180 @@
#include <stdio.h> #include <stdio.h>
#include <SDL.h> #include <SDL.h>
#include <glm\vec2.hpp> #include <glm/vec2.hpp>
#include "Drawable.h" #include "Drawable.h"
#include "Camera.h"
// //
// TODO: // TODO:
// - Optimizar RenderDraw moviendo la ordenación por capas a Queue, quitando renderQueue. // - Optimizar RenderDraw moviendo la ordenaci�n por capas a Queue, quitando renderQueue.
// - Limpiar las funciones moviendo código a otras funciones. // - Limpiar las funciones moviendo c�digo a otras funciones.
// - ¿Podría moverse todo a static? De esta forma, ya no harían falta instancias. // - �Podr�a moverse todo a static? De esta forma, ya no har�an falta instancias.
// //
namespace UE namespace UE
{ {
struct DrawCall; struct DrawCall;
class Renderer class Renderer
{ {
public: public:
/* Constructor */ /* Constructor */
Renderer(int windowWidth, Renderer(int windowWidth,
int windowHeight, int windowHeight,
int renderingLayers = 10) int renderingLayers = 10)
: LAYER_AMOUNT(renderingLayers) : LAYER_AMOUNT(renderingLayers)
{ {
screenSize.x = windowWidth; screenSize.x = windowWidth;
screenSize.y = windowHeight; screenSize.y = windowHeight;
//UE_LOG_INFO("Game Renderer Created."); //UE_LOG_INFO("Game Renderer Created.");
} }
/* Inicializa los componentes necesarios: /* Inicializa los componentes necesarios:
- Inicializa SDL - Inicializa SDL
- Crea la ventana. - Crea la ventana.
- Crea el renderer. - Crea el renderer.
- ... - ...
*/ */
int InitRenderer(); int InitRenderer();
/* Limpia todo antes de salir. */ /* Limpia todo antes de salir. */
void CleanRenderer(); void CleanRenderer();
//Hace el SDL_RenderClear() para limpiar el buffer al principio de un nuevo frame. //Hace el SDL_RenderClear() para limpiar el buffer al principio de un nuevo frame.
void NewFrame(); void NewFrame();
//Ordena por layer todos los objetos de la renderQueue y los dibuja en orden. //Ordena por layer todos los objetos de la renderQueue y los dibuja en orden.
//Se puede mover el proceso de ordenado a otra función, con el objeto de ir vaciando la Queue. //Se puede mover el proceso de ordenado a otra funci�n, con el objeto de ir vaciando la Queue.
void RenderData(); void RenderData();
//Hace el swap del render buffer (tras dibujar todos los objetos). Termina el renderizado. //Hace el swap del render buffer (tras dibujar todos los objetos). Termina el renderizado.
void EndFrame(); void EndFrame();
//Añade un DrawCall al renderQueue. //A�ade un DrawCall al renderQueue.
void QueueDrawCall(DrawCall drawCall); void QueueDrawCall(DrawCall drawCall);
void QueueDrawCall(int layer, SDL_Rect& position, SDL_Texture* texture, SDL_Rect& texture_position); void QueueDrawCall(int layer, SDL_Rect& position, SDL_Texture* texture, SDL_Rect& texture_position);
void QueueDrawCall(int layer, SDL_Rect & position, SDL_Texture* texture); void QueueDrawCall(int layer, SDL_Rect & position, SDL_Texture* texture);
//Le pasamos este renderer al Drawable para que haga lo que quiera. //Le pasamos este renderer al Drawable para que haga lo que quiera.
//Como si quiere usar el SDL_Renderer, es libre. //Como si quiere usar el SDL_Renderer, es libre.
void Render(Drawable& drawable); void Render(Drawable& drawable);
/* Get SDL Renderer. */ /* Get SDL Renderer. */
SDL_Renderer* GetSDLRenderer() { return main_Renderer; } SDL_Renderer* GetSDLRenderer() { return main_Renderer; }
inline glm::ivec2 GetScreenSize() { return screenSize; } inline glm::ivec2 GetScreenSize() { return screenSize; }
void SetScreenSize(int newWidth, int newHeight); void SetScreenSize(int newWidth, int newHeight);
inline glm::ivec2 GetCamPosition() { return camPosition; } //Permite cambiar el color de fondo.
void SetCamPosition(int posX, int posY); void SetDrawingColor(SDL_Color& newColor);
/* Métodos para transformar las coordenadas entre Screen y Wolrd. */ //Cambia la cámara que se utiliza en el renderizado.
//WorldCoords = ScreenPos + CamPos -> ScreenPos = WorldCoords - CamPos; inline void SetCamera(Camera* newCam) { activeCam = newCam; }
//Convierte coordenadas de mundo a la pantalla (en función de la cámara). inline Camera* GetCamera() { return activeCam; }
glm::ivec2 WorldToSreenCoords(glm::ivec2 worldCoord);
//Convierte coordenadas de la pantalla al mundo.
glm::ivec2 ScreenToWorldCoords(glm::ivec2 screenCoord);
//Comprueba si un objeto está dentro del rectángulo de la cámara.
//Usada para saber si un objeto se debería de renderizar o no.
bool IsObjectVisible(SDL_Rect* objectRect);
//DEBUG /* M�todos para transformar las coordenadas entre Screen y Wolrd. */
//Función para renderizar un objeto un objeto en concreto directamente en el SDL_Renderer. //WorldCoords = ScreenPos + CamPos -> ScreenPos = WorldCoords - CamPos;
void DrawObject(SDL_Rect* position, SDL_Rect* texture_pos, SDL_Texture* texture);
//Convierte coordenadas de mundo a la pantalla (en función de la cámara).
glm::ivec2 WorldToSreenCoords(glm::ivec2 worldCoord);
//Convierte coordenadas de la pantalla al mundo.
glm::ivec2 ScreenToWorldCoords(glm::ivec2 screenCoord);
//Comprueba si un objeto est� dentro del rect�ngulo de la c�mara.
//Usada para saber si un objeto se deber�a de renderizar o no.
bool IsObjectVisible(SDL_Rect* objectRect);
private: //DEBUG
//Realizar RenderClear(), RenderDraw() y RenderUpdate(); //Funci�n para renderizar un objeto un objeto en concreto directamente en el SDL_Renderer.
//Es decir, todo lo necesario para renderizar un frame. void DrawObject(SDL_Rect* position, SDL_Rect* texture_pos, SDL_Texture* texture);
void RenderFrame();
private: private:
/* Objetos de SDL para el rendering. */ //Realizar RenderClear(), RenderDraw() y RenderUpdate();
SDL_Window* _window = nullptr; //Es decir, todo lo necesario para renderizar un frame.
SDL_Surface* screenSurface = nullptr; void RenderFrame();
SDL_Renderer* main_Renderer = nullptr;
//SDL_GLContext _glContext = nullptr;
//Almacena todas las "draw calls" para luego ordenar los objetos por layers y dibujarlos.
//Se podría sustituir por un std::queue o std::deque si fuera necesario.
std::vector<DrawCall> renderQueue;
//Las capas en las que se organizan los diferentes objetos.
//Permite dibujar unos sprites sobre otros.
const int LAYER_AMOUNT = 10;
std::vector<std::vector<DrawCall>> renderLayers;
//int screenWidth = 640; private:
//int screenHeight = 480; /* Objetos de SDL para el rendering. */
SDL_Window* _window = nullptr;
SDL_Surface* screenSurface = nullptr;
SDL_Renderer* main_Renderer = nullptr;
glm::ivec2 screenSize{ 640,480 }; //SDL_GLContext _glContext = nullptr;
glm::ivec2 camPosition{ 0,0 };
//Almacena todas las "draw calls" para luego ordenar los objetos por layers y dibujarlos.
//Se podr�a sustituir por un std::queue o std::deque si fuera necesario.
std::vector<DrawCall> renderQueue;
//Las capas en las que se organizan los diferentes objetos.
//Permite dibujar unos sprites sobre otros.
const int LAYER_AMOUNT = 10;
std::vector<std::vector<DrawCall>> renderLayers;
//DEBUG //int screenWidth = 640;
int callCounter = 0; //int screenHeight = 480;
int rendererCounter = 0;
}; glm::ivec2 screenSize{ 640,480 };
/* //glm::ivec2 camPosition{ 0,0 };
Contiene los valores necesarios para realizar el renderizado con SDL_RenderCopy(); Camera* activeCam;
Se almacena en la renderQueue y luego son ordenados por las renderLayers.
*/
struct DrawCall
{
DrawCall(int layer,
SDL_Rect position,
SDL_Texture* texture,
SDL_Rect texture_position)
: layer(layer), tx(texture), tx_rect(texture_position), pos_rect(position) SDL_Rect _screenRect{ 0, 0, screenSize.x, screenSize.y};
{}
DrawCall(int layer,
SDL_Rect position,
SDL_Texture* texture)
: layer(layer), tx(texture), pos_rect(position)
{
tx_rect = SDL_Rect();
fullTexture = true;
}
int layer; //DEBUG
int callCounter = 0;
int rendererCounter = 0;
bool fullTexture = false; };
SDL_Texture* tx; /*
SDL_Rect tx_rect; Contiene los valores necesarios para realizar el renderizado con SDL_RenderCopy();
Se almacena en la renderQueue y luego son ordenados por las renderLayers.
*/
struct DrawCall
{
DrawCall(int layer,
SDL_Rect position,
SDL_Texture* texture,
SDL_Rect texture_position)
SDL_Rect pos_rect; : layer(layer), tx(texture), tx_rect(texture_position), pos_rect(position)
}; {}
DrawCall(int layer,
SDL_Rect position,
SDL_Texture* texture)
: layer(layer), tx(texture), pos_rect(position)
{
tx_rect = SDL_Rect();
fullTexture = true;
}
int layer;
bool fullTexture = false;
SDL_Texture* tx;
SDL_Rect tx_rect;
SDL_Rect pos_rect;
};
} }
+26 -26
View File
@@ -3,45 +3,45 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <glm\vec2.hpp> #include <glm/vec2.hpp>
namespace UE namespace UE
{ {
/* /*
Clase que contiene lo necesario para crear un objeto con posición en el espacio y modificarlo. Clase que contiene lo necesario para crear un objeto con posici�n en el espacio y modificarlo.
*/ */
class Transformable class Transformable
{ {
public: public:
//----------- //-----------
//- Setters - //- Setters -
//----------- //-----------
//Modifica la posición del Objeto. //Modifica la posici�n del Objeto.
inline void SetPosition(float x, float y) { _pos = glm::vec<2, float>(x, y); } inline void SetPosition(float x, float y) { _pos = glm::vec<2, float>(x, y); }
inline void SetPosition(glm::vec<2, float> newPosition) { _pos = newPosition; } inline void SetPosition(glm::vec<2, float> newPosition) { _pos = newPosition; }
//Modifica la escala de Objeto. //Modifica la escala de Objeto.
inline void SetSize(float x, float y) { _size = glm::vec<2, float>(x, y); } inline void SetSize(float x, float y) { _size = glm::vec<2, float>(x, y); }
inline void SetSize(glm::vec<2, float> newSize) { _size = newSize; } inline void SetSize(glm::vec<2, float> newSize) { _size = newSize; }
//----------- //-----------
//- Getters - //- Getters -
//----------- //-----------
inline glm::vec2 GetPosition() { return _pos; } inline glm::vec2 GetPosition() { return _pos; }
inline glm::vec2 GetSize() { return _size; } inline glm::vec2 GetSize() { return _size; }
protected: protected:
//Se almacena la posición y el tamaño del objeto. Con esto se puede crear un SDL_Rect. //Se almacena la posici�n y el tama�o del objeto. Con esto se puede crear un SDL_Rect.
glm::vec<2, float> _pos; glm::vec<2, float> _pos;
glm::vec<2, float> _size; glm::vec<2, float> _size;
}; };
} }
+15 -13
View File
@@ -1,23 +1,25 @@
#include "Scene.h" #include "Scene.h"
#include "Logging/Logger.h"
#include <iostream> #include <iostream>
namespace UE namespace UE
{ {
void Scene::SceneInit() void Scene::SceneInit()
{ {
//id = currentID++; UE_LOG_TRACE("Scene {0} has been init!", _sceneName);
std::cout << "Scene has been init!" << std::endl; }
}
void Scene::SceneClean() void Scene::SceneClean()
{ {
std::cout << "Scene has been cleaned!" << std::endl; UE_LOG_TRACE("Scene {0} has been Cleaned!", _sceneName);
if (loaded)
{ if (loaded)
SceneUnload(); {
} SceneUnload();
} }
}
} }
+66 -35
View File
@@ -5,7 +5,6 @@
/// ///
/// TODO: /// TODO:
/// - Scene debería ser serializable y cargable desde archivos, al menos para las clases derivadas. ( o quizás no....)
/// ///
/// ///
union SDL_Event; union SDL_Event;
@@ -13,49 +12,81 @@ union SDL_Event;
namespace UE namespace UE
{ {
/* /*
Estructura básica de una escena. Almacena los datos mínimos. Estructura básica de una escena.
Se utilizará como clase base para las clases Scene específicas. Se utiliza como clase base para las clases Scene específicas del Game.
Esta clase será heredada por las escenas del usuario. Esta clase será heredada por las escenas del usuario.
*/ */
class Scene class Scene
{ {
public: public:
Scene(std::string name) Scene(std::string name)
: _sceneName(name) : _sceneName(name)
{} {
SceneInit();
}
/* Funciones "internas" de la clase para inicialización y cierre. */ ~Scene()
void SceneInit(); //Te calienta y prepara la casa al llegar. {
void SceneClean(); //Te deja todo limpio y reluciente al salir. SceneClean();
}
/* Funciones que habrán de sobrecargar las escenas del usuario. */ /* Funciones "internas" de la clase para inicialización y cierre. */
virtual void SceneLoad() { std::cout << "EMPTY SCENE CREATED" << std::endl; } void SceneInit(); //Te calienta y prepara la casa al llegar.
virtual void SceneRender() {} void SceneClean(); //Te deja todo limpio y reluciente al salir.
virtual void SceneUpdate() {}
virtual void SceneHandleEvents(SDL_Event* event) {}
virtual void SceneUnload() { std::cout << "EMPTY SCENE DESCARGADA" << std::endl; }
// ¿Esto sirve para algo? /*
//void loadDataFromFile(std::string path); Métodos de los estados de la escena.
Habrán de ser sobrecargardos por las escenas del usuario.
*/
//Se crean todos los objetos y se carga todo lo necesario para la escena.
virtual void SceneLoad() = 0;
/*
* Render de los objetos de la escena.
* Se ejecuta en cada frame.
*/
virtual void SceneRender() = 0;
/*
* Update para los objetos de la escena.
* Utilizado para las físicas y otros componentes similares.
* Se ejecuta en cada frame.
*/
virtual void SceneUpdate() = 0;
/*
* Gestor de eventos para la escena.
* Utilizado para capturar los eventos que necesita la escena.
*/
virtual void SceneHandleEvents(SDL_Event* event) = 0;
/*
* Descarga y limpia todos los elementos de la escena.
* Utilizado también para guardado o lo que sea conveniente.
*/
virtual void SceneUnload() = 0;
//Obtener el nombre de la escena.
inline std::string GetName() { return _sceneName; }
/*
* Permite comprobar si la escena está cargada o no.
* TODO: Útil si queremos hacer carga asincrona o similar. Al menos para assets o algo.
*/
inline bool IsLoaded() { return loaded; }
inline std::string GetName() { return _sceneName; } protected:
inline bool IsLoaded() { return loaded; } //Nombre de la escena. Para identificarla en el SceneManager.
std::string _sceneName = "NullScene";
bool loaded = false;
protected: };
//Almacena el ID actual, permitiendo generar un ID nuevo para cada Scene que se instancie.
//static uint16_t currentID;
std::string _sceneName;
//std::vector<Entity> _entidades;
bool loaded = false;
};
} }
-18
View File
@@ -1,18 +0,0 @@
#pragma once
namespace UE
{
class Scene;
/*
Será sobrecargado por el juego, de tal forma que cuando se le pida crear una escena, sepa qué objeto crear.
*/
class SceneBuilder
{
public:
virtual inline Scene* InstanciateScene(int sceneID) { return nullptr; }
};
}
+120 -78
View File
@@ -1,100 +1,142 @@
#include "SceneManager.h" #include "SceneManager.h"
#include "Scene.h" #include "Logging/Logger.h"
#include "SceneBuilder.h"
#include "Logging\Logger.h"
#include <iostream> #include <iostream>
namespace UE namespace UE
{ {
void SceneManager::InitSceneManager(SceneBuilder* sceneBuilder) void SceneManager::InitSceneManager()
{ {
_sceneBuilder = sceneBuilder; UE_LOG_INFO("Se ha inicializado el SceneManager.");
}
UE_LOG_INFO("Se ha inicializado el SceneManager."); void SceneManager::CleanSceneManager()
} {
for (auto& it : _loadedScenes)
{
Scene* sc = it.second;
sc->SceneClean();
delete sc;
}
void SceneManager::CleanSceneManager() _loadedScenes.clear();
{
if (_currentScene != nullptr)
{
_currentScene->SceneUnload();
delete _currentScene;
}
//for (auto& it : _scenes) if (_currentScene != nullptr)
//{ {
// Scene* sc = it.second; _currentScene = nullptr;
// sc->SceneClean(); }
// delete sc;
//}
//_scenes.clear(); UE_LOG_INFO("El ScenenManager se ha descargado correctamente.");
}
void SceneManager::LoadScene(Scene* sceneToLoad)
{
std::string name = sceneToLoad->GetName();
//Comprobamos si la escena ya está cargada en la lista.
if(IsSceneLoaded(name))
{
//Si lo está, la descargamos para volverla a cargar.
//En caso de no estar activa, claro está.
UnloadScene(name);
}
//Cargamos la escena en cuestión.
sceneToLoad->SceneLoad();
//Añadimos la escena a la lista de escenas cargadas.
_loadedScenes.insert(std::make_pair(name, sceneToLoad));
}
void SceneManager::LoadAndSwitchScene(Scene* sceneToLoad)
{
LoadScene(sceneToLoad);
SwitchScene(sceneToLoad->GetName());
}
void SceneManager::SwitchScene(std::string name)
{
//Comprobamos si existe la escena indicada.
if(!IsSceneLoaded(name))
{
UE_LOG_WARN("SceneManager: Scene {0}, No se puede cambiar de escena. No está cargada.", name);
return;
}
//Cambiamos la escena actual por la indicada.
_currentScene = _loadedScenes.at(name);
}
void SceneManager::SwitchAndUnloadScene(std::string name)
{
//Comprobamos si existe la escena indicada.
if(!IsSceneLoaded(name))
{
UE_LOG_WARN("SceneManager: Scene {0}, No se puede cambiar de escena. No está cargada.", name);
return;
}
//Descargamos la escena anterior en caso de haberla.
if(_currentScene != nullptr && IsSceneLoaded(_currentScene->GetName()))
{
_currentScene->SceneUnload();
}
//Cambiamos la escena activa por la nueva.
_currentScene = _loadedScenes.at(name);
}
} void SceneManager::UnloadScene(std::string name)
{
//Comprobamos si existe la escena indicada.
if(!IsSceneLoaded(name))
{
UE_LOG_WARN("SceneManager: Scene {0}, no se puede descargar. No está cargada.", name);
return;
}
//Comprobamos si se trata de la escena actual.
if(GetCurrentSceneName() == name)
{
//No hacemos nada, no se puede recargar la escena actual así como así.
UE_LOG_WARN("SceneManager: Scene {0}, no se puede descargar. Es la escena actual.", name);
return;
}
//Si todo está correcto.
//Si tenemos campo libre, pista libre, punto rojo.
//Descargamos.
_loadedScenes.at(name)->SceneUnload();
_loadedScenes.erase(name);
}
bool SceneManager::IsSceneLoaded(std::string name)
//void SceneManager::AddScene(Scene* sceneToAdd) {
//{ //Comprobamos si existe la escena indicada.
// _scenes.insert(std::make_pair(sceneToAdd->GetName(), sceneToAdd)); if(_loadedScenes.find(name) != _loadedScenes.end())
// sceneToAdd->SceneInit(); {
//Si la encontramos, existe.
// UE_LOG_INFO("Se ha añadido la escena {0} al SceneManager.", sceneToAdd->GetName()); return true;
//} }
return false;
}
std::string SceneManager::GetCurrentSceneName()
{
return _currentScene->GetName();
}
//Scene* SceneManager::GetScenePtr(std::string sceneName) Scene* SceneManager::GetCurrentScenePtr()
//{ {
// if (_scenes.find(sceneName) == _scenes.end()) return _currentScene;
// { }
// UE_LOG_ERROR("No se ha encontrado la escena indicada.");
// return nullptr;
// }
// return _scenes.at(sceneName);
//}
void SceneManager::UpdateScene()
{
std::string SceneManager::GetActiveSceneName() _currentScene->SceneUpdate();
{ }
return _currentScene->GetName();
}
//void SceneManager::LoadScene(std::string sceneName)
//{
// if (_currentScene != nullptr)
// {
// _currentScene->SceneUnload();
// delete _currentScene;
// }
// _currentScene = _scenes.at(sceneName);
// _currentScene->SceneLoad();
//}
void SceneManager::NewLoadScene(int sceneID)
{
if (_currentScene != nullptr)
{
_currentScene->SceneUnload();
delete _currentScene;
}
_currentScene = _sceneBuilder->InstanciateScene(sceneID);
_currentScene->SceneLoad();
}
void SceneManager::UpdateScene()
{
_currentScene->SceneUpdate();
}
} }
+90 -51
View File
@@ -1,72 +1,111 @@
#pragma once #pragma once
#include "Scene/Scene.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
// //
// Habría que implemetar un sistema para cambiar de escena. // TODO:
// La cuestión sería almecenar el ID actual o algo así. // - Se podría plantear un sistema de carga asincrona para las escenas.
// Las escenas que no están cargadas se pueden mantener construidas en el vector, pues el espacio que ocupan en memoria debería ser mínimo. // - La variable "loaded" de las escenas no tiene mucha utilidad en este momento.
// Cuando cargas una escena, se descarga la anterior mediante Scene.unload y se carga la nueva con Scene.Load. De esta forma,
// si cada escena gestiona bien sus recursos en la carga y descarga, no debería generar ningún problema y no ocupar espacio cuando esté descargada.
// Quizás se puede añadir una opción para mantener cargada una escena o algo.
//
// Quizás es innecesaria la ID interna de la escena....
//
namespace UE namespace UE
{ {
class Scene;
class SceneBuilder;
/* Gestiona todas escenas. Las carga, descargar y ejecuta. */ /* Gestiona todas escenas. Las carga, descargar y ejecuta. */
class SceneManager class SceneManager
{ {
public: public:
/* Constructor */
SceneManager() {}
void InitSceneManager(SceneBuilder* sceneBuilder); /* Constructor */
void CleanSceneManager(); SceneManager()
{
InitSceneManager();
}
//Añade una escena a la lista y retorna su ID. Son Ptrs, por lo que poco importa donde los almacenamos. ~SceneManager()
//void AddScene(Scene* sceneToAdd); {
CleanSceneManager();
//Devuelve un ptr a la escena del ID especificado. }
//Scene* GetScenePtr(std::string sceneName);
std::string GetActiveSceneName();
//Devuelve la escena activa.
inline Scene* GetActiveScenePtr() { return _currentScene; }
//Descarga la escena activa y carga la escena indicada.
//void LoadScene(std::string sceneName);
//Descarga la escena activa y carga la escena indicada. Para ello llama al builder que tiene y este le devuelve un ptr a la nueva escena.
void NewLoadScene(int sceneID);
//Pasa el Update a la escena actual.
//¿Necesita hacer algo más?
void UpdateScene();
// ¿Esto sirve para algo?
//void LoadSceneDataFromFile(std::string filePath);
private: //Inicializa el ScenenManager (En caso de haber algo que iniciar.)
Scene* _currentScene = nullptr; void InitSceneManager();
//Limpia los contenedores de Scenes y descarga las escenas cargadas.
void CleanSceneManager();
SceneBuilder* _sceneBuilder = nullptr; /*
* Carga una nueva escena.
* Se almacena en la lista de escenas cargadas.
* Para cambiar de escena, usar SwitchScene();
* Si la escena ya estuvise cargada, se descargará la anterior y se cargará la nueva.
*/
void LoadScene(Scene* sceneToLoad);
//Almacenamos un ptr a las diferentes escenas disponibles. /*
//Otra opción es trabajar con Templates para instanciar la clase pretinente sin necesidad de almacenar nada. * Cambia la escena activa por la indicada.
//De cualquier forma, son ptr en el Stack y deberían de eliminar todo al hacer scene.Unload(). * Si la indicada no está cargada, no hace nada.
//std::unordered_map<std::string, Scene*> _scenes; */
//std::vector<Scene*> _scenes; void SwitchScene(std::string name);
/*
* Carga la escena indicada.
* Cambia la escena actual por la nueva escena.
*/
void LoadAndSwitchScene(Scene* sceneToLoad);
/*
* Cambia la escena activa por la indicada.
* Descarga completamente la escena activa anterior.
* Si la escena indicada no está cargarda, no hace nada.
* Si no hay una escena activa, no la descarga.
*/
void SwitchAndUnloadScene(std::string name);
}; /*
* Descarga la escena con el nombre indicado.
* Si la escena no está en la lista, no hace nada.
*/
void UnloadScene(std::string name);
/*
* Comprueba si la escena indicada está en la lista de escenas cargadas.
* Retorna true si está cargada, false si no.
*/
bool IsSceneLoaded(std::string name);
/*
* Devuelve el nombre de la escena activa.
*/
std::string GetCurrentSceneName();
/*
* Devuelve el ptr de la escena activa.
*/
Scene* GetCurrentScenePtr();
/*
* Update para la escena activa.
* Se ha de llamar en cada frame para pasar el update a la escena activa.
* TODO: No se usa... O añadimos para las otras fases o quitamos esta.
*/
void UpdateScene();
private:
//Ptr a la escena que está activa en ese momento.
Scene* _currentScene = nullptr;
//Almacenamos un ptr a todas las escenas cargadas en ese momento.
//o, al menos, lo intentamos.
std::unordered_map<std::string, Scene*> _loadedScenes;
};
} }
+18 -18
View File
@@ -8,36 +8,36 @@ uint32_t UE::Time::_startTime;
void UE::Time::StartFrame() void UE::Time::StartFrame()
{ {
_startTime = SDL_GetTicks(); _startTime = SDL_GetTicks();
} }
void UE::Time::EndFrame() void UE::Time::EndFrame()
{ {
// Calculamos el tiempo que llevamos de Frame, para que si nos quedamos cortos, esperemos. // Calculamos el tiempo que llevamos de Frame, para que si nos quedamos cortos, esperemos.
//FrameTime es el tiempo que ha tardado el frame (el deltaTime) en MS. //FrameTime es el tiempo que ha tardado el frame (el deltaTime) en MS.
uint32_t frameTime = SDL_GetTicks() - _startTime; uint32_t frameTime = SDL_GetTicks() - _startTime;
//Frames totales / segundos totales. //Frames totales / segundos totales.
//_avgFPS = countedFrames / (SDL_GetTicks() / 1000.f); //_avgFPS = countedFrames / (SDL_GetTicks() / 1000.f);
//std::cout << "FPS: " << avgFPS << " / " << "dT: " << deltaTime << std::endl; //std::cout << "FPS: " << avgFPS << " / " << "dT: " << deltaTime << std::endl;
//Limitamos los FPS haciendo esperar al programa el tiempo extra que quede. //Limitamos los FPS haciendo esperar al programa el tiempo extra que quede.
//En vez de sólo esperar, se podrían hacer tareas como cargar Assets o realizar cálculos pesados. //En vez de s�lo esperar, se podr�an hacer tareas como cargar Assets o realizar c�lculos pesados.
if (frameTime < MS_PER_FRAME) if (frameTime < MS_PER_FRAME)
{ {
SDL_Delay(MS_PER_FRAME - frameTime); SDL_Delay(MS_PER_FRAME - frameTime);
} }
//Calculamos el deltaTime, que sí será el tiempo real que ha pasado, pues hemos esperado. //Calculamos el deltaTime, que s� ser� el tiempo real que ha pasado, pues hemos esperado.
frameTime = SDL_GetTicks() - _startTime; frameTime = SDL_GetTicks() - _startTime;
//Convertimos deltaTime a segundos pues es lo usado en los cálculos. //Convertimos deltaTime a segundos pues es lo usado en los c�lculos.
deltaTime = frameTime / 1000.0f; deltaTime = frameTime / 1000.0f;
//++countedFrames; //++countedFrames;
} }
+22 -22
View File
@@ -2,42 +2,42 @@
#include <cstdint> #include <cstdint>
/* /*
TODO: TODO:
- Buscar una mejor forma de calcular la media de FPS. - Buscar una mejor forma de calcular la media de FPS.
*/ */
namespace UE namespace UE
{ {
class Time class Time
{ {
public: public:
//------------------- //-------------------
//---- Métodos ------ //---- Métodos ------
//------------------- //-------------------
static void StartFrame(); static void StartFrame();
static void EndFrame(); static void EndFrame();
//------------------- //-------------------
//---- Variables ---- //---- Variables ----
//------------------- //-------------------
static double deltaTime; static double deltaTime;
private: private:
static uint32_t _startTime; static uint32_t _startTime;
//uint16_t countedFrames = 0; //uint16_t countedFrames = 0;
float _avgFPS; float _avgFPS;
static const int FPS = 60; static const int FPS = 60;
//Milisegundos que tiene que tener un frame para poder hacer el número de FPS por segundo. //Milisegundos que tiene que tener un frame para poder hacer el número de FPS por segundo.
static const int MS_PER_FRAME = 1000 / FPS; static const int MS_PER_FRAME = 1000 / FPS;
}; };
} }
+8 -6
View File
@@ -1,12 +1,14 @@
#pragma once #pragma once
#include "Logging\Logger.h" #include "Logging/Logger.h"
#include "Render\Renderer.h" #include "Render/Renderer.h"
#include "Drawables\Sprite.h" #include "Render/Camera.h"
#include "Assets\AssetManager.h" #include "Drawables/Sprite.h"
#include "Scene\SceneManager.h" #include "Assets/AssetManager.h"
#include "Time\Time.h" #include "Scene/SceneManager.h"
#include "Time/Time.h"
+7
View File
@@ -0,0 +1,7 @@
/*
Aquí habrá que definir los tipos custom para UberEngine.
Por ejemplo:
- glm::ivec2 -> UE_Vec2
*/
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2014-2021 Omar Cornut Copyright (c) 2014-2022 Omar Cornut
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+13 -11
View File
@@ -28,12 +28,13 @@
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions.
//---- Disable all of Dear ImGui or don't implement standard windows. //---- Disable all of Dear ImGui or don't implement standard windows/tools.
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp. // It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended. //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger and other debug tools: ShowMetricsWindow() and ShowStackToolWindow() will be empty. //#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88).
//---- Don't implement some functions to reduce linkage requirements. //---- Don't implement some functions to reduce linkage requirements.
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
@@ -61,12 +62,13 @@
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if enabled
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) //---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf. // Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
// #define IMGUI_USE_STB_SPRINTF //#define IMGUI_USE_STB_SPRINTF
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
@@ -80,12 +82,12 @@
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
// This will be inlined as part of ImVec2 and ImVec4 class declarations. // This will be inlined as part of ImVec2 and ImVec4 class declarations.
/* /*
#define IM_VEC2_CLASS_EXTRA \ #define IM_VEC2_CLASS_EXTRA \
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
operator MyVec2() const { return MyVec2(x,y); } operator MyVec2() const { return MyVec2(x,y); }
#define IM_VEC4_CLASS_EXTRA \ #define IM_VEC4_CLASS_EXTRA \
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
operator MyVec4() const { return MyVec4(x,y,z,w); } operator MyVec4() const { return MyVec4(x,y,z,w); }
*/ */
+1483 -666
View File
File diff suppressed because it is too large Load Diff
+368 -219
View File
File diff suppressed because it is too large Load Diff
+183 -74
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.86 // dear imgui, v1.88
// (demo code) // (demo code)
// Help: // Help:
@@ -39,7 +39,7 @@
// Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp. // Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp.
// Navigating this file: // Navigating this file:
// - In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. // - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments.
/* /*
@@ -92,6 +92,7 @@ Index of this file:
// Visual Studio warnings // Visual Studio warnings
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning (disable: 4127) // condition expression is constant
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2). #pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
#endif #endif
@@ -228,7 +229,6 @@ void ImGui::ShowUserGuide()
ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste."); ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste.");
ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo."); ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
ImGui::BulletText("ESCAPE to revert."); ImGui::BulletText("ESCAPE to revert.");
ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
ImGui::Unindent(); ImGui::Unindent();
ImGui::BulletText("With keyboard navigation enabled:"); ImGui::BulletText("With keyboard navigation enabled:");
ImGui::Indent(); ImGui::Indent();
@@ -302,13 +302,19 @@ void ImGui::ShowDemoWindow(bool* p_open)
// Dear ImGui Apps (accessible from the "Tools" menu) // Dear ImGui Apps (accessible from the "Tools" menu)
static bool show_app_metrics = false; static bool show_app_metrics = false;
static bool show_app_debug_log = false;
static bool show_app_stack_tool = false; static bool show_app_stack_tool = false;
static bool show_app_style_editor = false;
static bool show_app_about = false; static bool show_app_about = false;
static bool show_app_style_editor = false;
if (show_app_metrics) { ImGui::ShowMetricsWindow(&show_app_metrics); } if (show_app_metrics)
if (show_app_stack_tool) { ImGui::ShowStackToolWindow(&show_app_stack_tool); } ImGui::ShowMetricsWindow(&show_app_metrics);
if (show_app_about) { ImGui::ShowAboutWindow(&show_app_about); } if (show_app_debug_log)
ImGui::ShowDebugLogWindow(&show_app_debug_log);
if (show_app_stack_tool)
ImGui::ShowStackToolWindow(&show_app_stack_tool);
if (show_app_about)
ImGui::ShowAboutWindow(&show_app_about);
if (show_app_style_editor) if (show_app_style_editor)
{ {
ImGui::Begin("Dear ImGui Style Editor", &show_app_style_editor); ImGui::Begin("Dear ImGui Style Editor", &show_app_style_editor);
@@ -395,10 +401,14 @@ void ImGui::ShowDemoWindow(bool* p_open)
if (ImGui::BeginMenu("Tools")) if (ImGui::BeginMenu("Tools"))
{ {
IMGUI_DEMO_MARKER("Menu/Tools"); IMGUI_DEMO_MARKER("Menu/Tools");
#ifndef IMGUI_DISABLE_METRICS_WINDOW #ifndef IMGUI_DISABLE_DEBUG_TOOLS
ImGui::MenuItem("Metrics/Debugger", NULL, &show_app_metrics); const bool has_debug_tools = true;
ImGui::MenuItem("Stack Tool", NULL, &show_app_stack_tool); #else
const bool has_debug_tools = false;
#endif #endif
ImGui::MenuItem("Metrics/Debugger", NULL, &show_app_metrics, has_debug_tools);
ImGui::MenuItem("Debug Log", NULL, &show_app_debug_log, has_debug_tools);
ImGui::MenuItem("Stack Tool", NULL, &show_app_stack_tool, has_debug_tools);
ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor); ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about); ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about);
ImGui::EndMenu(); ImGui::EndMenu();
@@ -406,7 +416,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::EndMenuBar(); ImGui::EndMenuBar();
} }
ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION); ImGui::Text("dear imgui says hello! (%s) (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
ImGui::Spacing(); ImGui::Spacing();
IMGUI_DEMO_MARKER("Help"); IMGUI_DEMO_MARKER("Help");
@@ -454,13 +464,15 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text("<<PRESS SPACE TO DISABLE>>"); ImGui::Text("<<PRESS SPACE TO DISABLE>>");
} }
if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Space))) if (ImGui::IsKeyPressed(ImGuiKey_Space))
io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse; io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
} }
ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", &io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange); ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", &io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
ImGui::SameLine(); HelpMarker("Instruct backend to not alter mouse cursor shape and visibility."); ImGui::SameLine(); HelpMarker("Instruct backend to not alter mouse cursor shape and visibility.");
ImGui::Checkbox("io.ConfigInputTrickleEventQueue", &io.ConfigInputTrickleEventQueue);
ImGui::SameLine(); HelpMarker("Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.");
ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink); ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting)"); ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting).");
ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText); ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText);
ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving)."); ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving).");
ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges); ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
@@ -481,6 +493,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
"Here we expose them as read-only fields to avoid breaking interactions with your backend."); "Here we expose them as read-only fields to avoid breaking interactions with your backend.");
// Make a local copy to avoid modifying actual backend flags. // Make a local copy to avoid modifying actual backend flags.
// FIXME: We don't use BeginDisabled() to keep label bright, maybe we need a BeginReadonly() equivalent..
ImGuiBackendFlags backend_flags = io.BackendFlags; ImGuiBackendFlags backend_flags = io.BackendFlags;
ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", &backend_flags, ImGuiBackendFlags_HasGamepad); ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", &backend_flags, ImGuiBackendFlags_HasGamepad);
ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &backend_flags, ImGuiBackendFlags_HasMouseCursors); ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &backend_flags, ImGuiBackendFlags_HasMouseCursors);
@@ -673,10 +686,6 @@ static void ShowDemoWindowWidgets()
IMGUI_DEMO_MARKER("Widgets/Basic/InputInt, InputFloat"); IMGUI_DEMO_MARKER("Widgets/Basic/InputInt, InputFloat");
static int i0 = 123; static int i0 = 123;
ImGui::InputInt("input int", &i0); ImGui::InputInt("input int", &i0);
ImGui::SameLine(); HelpMarker(
"You can apply arithmetic operators +,*,/ on numerical values.\n"
" e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\n"
"Use +- to subtract.");
static float f0 = 0.001f; static float f0 = 0.001f;
ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f"); ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f");
@@ -1856,10 +1865,9 @@ static void ShowDemoWindowWidgets()
ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0None\0RGB Only\0HSV Only\0Hex Only\0"); ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0None\0RGB Only\0HSV Only\0Hex Only\0");
ImGui::SameLine(); HelpMarker( ImGui::SameLine(); HelpMarker(
"ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, " "ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, "
"but the user can change it with a right-click.\n\nColorPicker defaults to displaying RGB+HSV+Hex " "but the user can change it with a right-click on those inputs.\n\nColorPicker defaults to displaying RGB+HSV+Hex "
"if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions()."); "if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions().");
ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0"); ImGui::SameLine(); HelpMarker("When not specified explicitly (Auto/Current mode), user can right-click the picker to change mode.");
ImGui::SameLine(); HelpMarker("User can right-click the picker to change mode.");
ImGuiColorEditFlags flags = misc_flags; ImGuiColorEditFlags flags = misc_flags;
if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4() if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4()
if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar; if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar;
@@ -1883,6 +1891,15 @@ static void ShowDemoWindowWidgets()
if (ImGui::Button("Default: Float + HDR + Hue Wheel")) if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel); ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
// Always both a small version of both types of pickers (to make it more visible in the demo to people who are skimming quickly through it)
ImGui::Text("Both types:");
float w = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.y) * 0.40f;
ImGui::SetNextItemWidth(w);
ImGui::ColorPicker3("##MyColor##5", (float*)&color, ImGuiColorEditFlags_PickerHueBar | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha);
ImGui::SameLine();
ImGui::SetNextItemWidth(w);
ImGui::ColorPicker3("##MyColor##6", (float*)&color, ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha);
// HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0) // HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0)
static ImVec4 color_hsv(0.23f, 1.0f, 1.0f, 1.0f); // Stored as HSV! static ImVec4 color_hsv(0.23f, 1.0f, 1.0f, 1.0f); // Stored as HSV!
ImGui::Spacing(); ImGui::Spacing();
@@ -2005,6 +2022,7 @@ static void ShowDemoWindowWidgets()
ImGui::DragScalar("drag s16", ImGuiDataType_S16, &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL); ImGui::DragScalar("drag s16", ImGuiDataType_S16, &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL);
ImGui::DragScalar("drag u16", ImGuiDataType_U16, &u16_v, drag_speed, drag_clamp ? &u16_zero : NULL, drag_clamp ? &u16_fifty : NULL, "%u ms"); ImGui::DragScalar("drag u16", ImGuiDataType_U16, &u16_v, drag_speed, drag_clamp ? &u16_zero : NULL, drag_clamp ? &u16_fifty : NULL, "%u ms");
ImGui::DragScalar("drag s32", ImGuiDataType_S32, &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL); ImGui::DragScalar("drag s32", ImGuiDataType_S32, &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL);
ImGui::DragScalar("drag s32 hex", ImGuiDataType_S32, &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL, "0x%08X");
ImGui::DragScalar("drag u32", ImGuiDataType_U32, &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms"); ImGui::DragScalar("drag u32", ImGuiDataType_U32, &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms");
ImGui::DragScalar("drag s64", ImGuiDataType_S64, &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL); ImGui::DragScalar("drag s64", ImGuiDataType_S64, &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL);
ImGui::DragScalar("drag u64", ImGuiDataType_U64, &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL); ImGui::DragScalar("drag u64", ImGuiDataType_U64, &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL);
@@ -2022,6 +2040,7 @@ static void ShowDemoWindowWidgets()
ImGui::SliderScalar("slider s32 low", ImGuiDataType_S32, &s32_v, &s32_zero, &s32_fifty,"%d"); ImGui::SliderScalar("slider s32 low", ImGuiDataType_S32, &s32_v, &s32_zero, &s32_fifty,"%d");
ImGui::SliderScalar("slider s32 high", ImGuiDataType_S32, &s32_v, &s32_hi_a, &s32_hi_b, "%d"); ImGui::SliderScalar("slider s32 high", ImGuiDataType_S32, &s32_v, &s32_hi_a, &s32_hi_b, "%d");
ImGui::SliderScalar("slider s32 full", ImGuiDataType_S32, &s32_v, &s32_min, &s32_max, "%d"); ImGui::SliderScalar("slider s32 full", ImGuiDataType_S32, &s32_v, &s32_min, &s32_max, "%d");
ImGui::SliderScalar("slider s32 hex", ImGuiDataType_S32, &s32_v, &s32_zero, &s32_fifty, "0x%04X");
ImGui::SliderScalar("slider u32 low", ImGuiDataType_U32, &u32_v, &u32_zero, &u32_fifty,"%u"); ImGui::SliderScalar("slider u32 low", ImGuiDataType_U32, &u32_v, &u32_zero, &u32_fifty,"%u");
ImGui::SliderScalar("slider u32 high", ImGuiDataType_U32, &u32_v, &u32_hi_a, &u32_hi_b, "%u"); ImGui::SliderScalar("slider u32 high", ImGuiDataType_U32, &u32_v, &u32_hi_a, &u32_hi_b, "%u");
ImGui::SliderScalar("slider u32 full", ImGuiDataType_U32, &u32_v, &u32_min, &u32_max, "%u"); ImGui::SliderScalar("slider u32 full", ImGuiDataType_U32, &u32_v, &u32_min, &u32_max, "%u");
@@ -2055,9 +2074,9 @@ static void ShowDemoWindowWidgets()
ImGui::InputScalar("input s16", ImGuiDataType_S16, &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d"); ImGui::InputScalar("input s16", ImGuiDataType_S16, &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d");
ImGui::InputScalar("input u16", ImGuiDataType_U16, &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u"); ImGui::InputScalar("input u16", ImGuiDataType_U16, &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u");
ImGui::InputScalar("input s32", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d"); ImGui::InputScalar("input s32", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d");
ImGui::InputScalar("input s32 hex", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal); ImGui::InputScalar("input s32 hex", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%04X");
ImGui::InputScalar("input u32", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u"); ImGui::InputScalar("input u32", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u");
ImGui::InputScalar("input u32 hex", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal); ImGui::InputScalar("input u32 hex", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X");
ImGui::InputScalar("input s64", ImGuiDataType_S64, &s64_v, inputs_step ? &s64_one : NULL); ImGui::InputScalar("input s64", ImGuiDataType_S64, &s64_v, inputs_step ? &s64_one : NULL);
ImGui::InputScalar("input u64", ImGuiDataType_U64, &u64_v, inputs_step ? &u64_one : NULL); ImGui::InputScalar("input u64", ImGuiDataType_U64, &u64_v, inputs_step ? &u64_one : NULL);
ImGui::InputScalar("input float", ImGuiDataType_Float, &f32_v, inputs_step ? &f32_one : NULL); ImGui::InputScalar("input float", ImGuiDataType_Float, &f32_v, inputs_step ? &f32_one : NULL);
@@ -3193,59 +3212,58 @@ static void ShowDemoWindowLayout()
ImGui::DragFloat2("size", (float*)&size, 0.5f, 1.0f, 200.0f, "%.0f"); ImGui::DragFloat2("size", (float*)&size, 0.5f, 1.0f, 200.0f, "%.0f");
ImGui::TextWrapped("(Click and drag to scroll)"); ImGui::TextWrapped("(Click and drag to scroll)");
HelpMarker(
"(Left) Using ImGui::PushClipRect():\n"
"Will alter ImGui hit-testing logic + ImDrawList rendering.\n"
"(use this if you want your clipping rectangle to affect interactions)\n\n"
"(Center) Using ImDrawList::PushClipRect():\n"
"Will alter ImDrawList rendering only.\n"
"(use this as a shortcut if you are only using ImDrawList calls)\n\n"
"(Right) Using ImDrawList::AddText() with a fine ClipRect:\n"
"Will alter only this specific ImDrawList::AddText() rendering.\n"
"This is often used internally to avoid altering the clipping rectangle and minimize draw calls.");
for (int n = 0; n < 3; n++) for (int n = 0; n < 3; n++)
{ {
if (n > 0) if (n > 0)
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushID(n);
ImGui::BeginGroup(); // Lock X position
ImGui::InvisibleButton("##empty", size); ImGui::PushID(n);
ImGui::InvisibleButton("##canvas", size);
if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left))
{ {
offset.x += ImGui::GetIO().MouseDelta.x; offset.x += ImGui::GetIO().MouseDelta.x;
offset.y += ImGui::GetIO().MouseDelta.y; offset.y += ImGui::GetIO().MouseDelta.y;
} }
ImGui::PopID();
if (!ImGui::IsItemVisible()) // Skip rendering as ImDrawList elements are not clipped.
continue;
const ImVec2 p0 = ImGui::GetItemRectMin(); const ImVec2 p0 = ImGui::GetItemRectMin();
const ImVec2 p1 = ImGui::GetItemRectMax(); const ImVec2 p1 = ImGui::GetItemRectMax();
const char* text_str = "Line 1 hello\nLine 2 clip me!"; const char* text_str = "Line 1 hello\nLine 2 clip me!";
const ImVec2 text_pos = ImVec2(p0.x + offset.x, p0.y + offset.y); const ImVec2 text_pos = ImVec2(p0.x + offset.x, p0.y + offset.y);
ImDrawList* draw_list = ImGui::GetWindowDrawList(); ImDrawList* draw_list = ImGui::GetWindowDrawList();
switch (n) switch (n)
{ {
case 0: case 0:
HelpMarker(
"Using ImGui::PushClipRect():\n"
"Will alter ImGui hit-testing logic + ImDrawList rendering.\n"
"(use this if you want your clipping rectangle to affect interactions)");
ImGui::PushClipRect(p0, p1, true); ImGui::PushClipRect(p0, p1, true);
draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255)); draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
draw_list->AddText(text_pos, IM_COL32_WHITE, text_str); draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
ImGui::PopClipRect(); ImGui::PopClipRect();
break; break;
case 1: case 1:
HelpMarker(
"Using ImDrawList::PushClipRect():\n"
"Will alter ImDrawList rendering only.\n"
"(use this as a shortcut if you are only using ImDrawList calls)");
draw_list->PushClipRect(p0, p1, true); draw_list->PushClipRect(p0, p1, true);
draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255)); draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
draw_list->AddText(text_pos, IM_COL32_WHITE, text_str); draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
draw_list->PopClipRect(); draw_list->PopClipRect();
break; break;
case 2: case 2:
HelpMarker(
"Using ImDrawList::AddText() with a fine ClipRect:\n"
"Will alter only this specific ImDrawList::AddText() rendering.\n"
"(this is often used internally to avoid altering the clipping rectangle and minimize draw calls)");
ImVec4 clip_rect(p0.x, p0.y, p1.x, p1.y); // AddText() takes a ImVec4* here so let's convert. ImVec4 clip_rect(p0.x, p0.y, p1.x, p1.y); // AddText() takes a ImVec4* here so let's convert.
draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255)); draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
draw_list->AddText(ImGui::GetFont(), ImGui::GetFontSize(), text_pos, IM_COL32_WHITE, text_str, NULL, 0.0f, &clip_rect); draw_list->AddText(ImGui::GetFont(), ImGui::GetFontSize(), text_pos, IM_COL32_WHITE, text_str, NULL, 0.0f, &clip_rect);
break; break;
} }
ImGui::EndGroup();
ImGui::PopID();
} }
ImGui::TreePop(); ImGui::TreePop();
@@ -3411,7 +3429,7 @@ static void ShowDemoWindowPopups()
{ {
HelpMarker("Text() elements don't have stable identifiers so we need to provide one."); HelpMarker("Text() elements don't have stable identifiers so we need to provide one.");
static float value = 0.5f; static float value = 0.5f;
ImGui::Text("Value = %.3f <-- (1) right-click this value", value); ImGui::Text("Value = %.3f <-- (1) right-click this text", value);
if (ImGui::BeginPopupContextItem("my popup")) if (ImGui::BeginPopupContextItem("my popup"))
{ {
if (ImGui::Selectable("Set to zero")) value = 0.0f; if (ImGui::Selectable("Set to zero")) value = 0.0f;
@@ -3538,19 +3556,12 @@ static void ShowDemoWindowPopups()
ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!"); ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
ImGui::Separator(); ImGui::Separator();
// Note: As a quirk in this very specific example, we want to differentiate the parent of this menu from the
// parent of the various popup menus above. To do so we are encloding the items in a PushID()/PopID() block
// to make them two different menusets. If we don't, opening any popup above and hovering our menu here would
// open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it,
// which is the desired behavior for regular menus.
ImGui::PushID("foo");
ImGui::MenuItem("Menu item", "CTRL+M"); ImGui::MenuItem("Menu item", "CTRL+M");
if (ImGui::BeginMenu("Menu inside a regular window")) if (ImGui::BeginMenu("Menu inside a regular window"))
{ {
ShowExampleMenuFile(); ShowExampleMenuFile();
ImGui::EndMenu(); ImGui::EndMenu();
} }
ImGui::PopID();
ImGui::Separator(); ImGui::Separator();
ImGui::TreePop(); ImGui::TreePop();
} }
@@ -3874,7 +3885,7 @@ static void ShowDemoWindowTables()
sprintf(buf, "Hello %d,%d", column, row); sprintf(buf, "Hello %d,%d", column, row);
if (contents_type == CT_Text) if (contents_type == CT_Text)
ImGui::TextUnformatted(buf); ImGui::TextUnformatted(buf);
else if (contents_type) else if (contents_type == CT_FillButton)
ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f)); ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
} }
} }
@@ -4418,14 +4429,16 @@ static void ShowDemoWindowTables()
{ {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::PushID(column); ImGui::PushID(column);
ImGui::AlignTextToFramePadding(); // FIXME-TABLE: Workaround for wrong text baseline propagation ImGui::AlignTextToFramePadding(); // FIXME-TABLE: Workaround for wrong text baseline propagation across columns
ImGui::Text("'%s'", column_names[column]); ImGui::Text("'%s'", column_names[column]);
ImGui::Spacing(); ImGui::Spacing();
ImGui::Text("Input flags:"); ImGui::Text("Input flags:");
EditTableColumnsFlags(&column_flags[column]); EditTableColumnsFlags(&column_flags[column]);
ImGui::Spacing(); ImGui::Spacing();
ImGui::Text("Output flags:"); ImGui::Text("Output flags:");
ImGui::BeginDisabled();
ShowTableColumnsStatusFlags(column_flags_out[column]); ShowTableColumnsStatusFlags(column_flags_out[column]);
ImGui::EndDisabled();
ImGui::PopID(); ImGui::PopID();
} }
PopStyleCompact(); PopStyleCompact();
@@ -4830,7 +4843,7 @@ static void ShowDemoWindowTables()
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
ImGui::SliderFloat("float1", &dummy_f, 0.0f, 1.0f); ImGui::SliderFloat("float1", &dummy_f, 0.0f, 1.0f);
ImGui::TableSetColumnIndex(2); ImGui::TableSetColumnIndex(2);
ImGui::SliderFloat("float2", &dummy_f, 0.0f, 1.0f); ImGui::SliderFloat("##float2", &dummy_f, 0.0f, 1.0f); // No visible label since right-aligned
ImGui::PopID(); ImGui::PopID();
} }
ImGui::EndTable(); ImGui::EndTable();
@@ -5639,6 +5652,8 @@ static void ShowDemoWindowColumns()
ImGui::TreePop(); ImGui::TreePop();
} }
namespace ImGui { extern ImGuiKeyData* GetKeyData(ImGuiKey key); }
static void ShowDemoWindowMisc() static void ShowDemoWindowMisc()
{ {
IMGUI_DEMO_MARKER("Filtering"); IMGUI_DEMO_MARKER("Filtering");
@@ -5665,12 +5680,18 @@ static void ShowDemoWindowMisc()
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
// Display ImGuiIO output flags // Display ImGuiIO output flags
ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse); IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Output");
ImGui::Text("WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose); ImGui::SetNextItemOpen(true, ImGuiCond_Once);
ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); if (ImGui::TreeNode("Output"))
ImGui::Text("WantTextInput: %d", io.WantTextInput); {
ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos); ImGui::Text("io.WantCaptureMouse: %d", io.WantCaptureMouse);
ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible); ImGui::Text("io.WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose);
ImGui::Text("io.WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
ImGui::Text("io.WantTextInput: %d", io.WantTextInput);
ImGui::Text("io.WantSetMousePos: %d", io.WantSetMousePos);
ImGui::Text("io.NavActive: %d, io.NavVisible: %d", io.NavActive, io.NavVisible);
ImGui::TreePop();
}
// Display Mouse state // Display Mouse state
IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Mouse State"); IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Mouse State");
@@ -5692,25 +5713,110 @@ static void ShowDemoWindowMisc()
} }
// Display Keyboard/Mouse state // Display Keyboard/Mouse state
IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Keyboard & Navigation State"); IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Keyboard, Gamepad & Navigation State");
if (ImGui::TreeNode("Keyboard & Navigation State")) if (ImGui::TreeNode("Keyboard, Gamepad & Navigation State"))
{ {
ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyDown(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X) (%.02f secs)", i, i, io.KeysDownDuration[i]); } // We iterate both legacy native range and named ImGuiKey ranges, which is a little odd but this allow displaying the data for old/new backends.
ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); } // User code should never have to go through such hoops: old code may use native keycodes, new code may use ImGuiKey codes.
ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); } #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } };
const ImGuiKey key_first = ImGuiKey_NamedKey_BEGIN;
#else
struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array
const ImGuiKey key_first = 0;
//ImGui::Text("Legacy raw:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (io.KeysDown[key]) { ImGui::SameLine(); ImGui::Text("\"%s\" %d", ImGui::GetKeyName(key), key); } }
#endif
ImGui::Text("Keys down:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (funcs::IsLegacyNativeDupe(key)) continue; if (ImGui::IsKeyDown(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d (%.02f secs)", ImGui::GetKeyName(key), key, ImGui::GetKeyData(key)->DownDuration); } }
ImGui::Text("Keys pressed:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (funcs::IsLegacyNativeDupe(key)) continue; if (ImGui::IsKeyPressed(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d", ImGui::GetKeyName(key), key); } }
ImGui::Text("Keys released:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (funcs::IsLegacyNativeDupe(key)) continue; if (ImGui::IsKeyReleased(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d", ImGui::GetKeyName(key), key); } }
ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public. ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f (%.02f secs)", i, io.NavInputs[i], io.NavInputsDownDuration[i]); } ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f (%.02f secs)", i, io.NavInputs[i], io.NavInputsDownDuration[i]); }
ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); } ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); }
ImGui::Button("Hovering me sets the\nkeyboard capture flag"); // Draw an arbitrary US keyboard layout to visualize translated keys
if (ImGui::IsItemHovered()) {
ImGui::CaptureKeyboardFromApp(true); const ImVec2 key_size = ImVec2(35.0f, 35.0f);
ImGui::SameLine(); const float key_rounding = 3.0f;
ImGui::Button("Holding me clears the\nthe keyboard capture flag"); const ImVec2 key_face_size = ImVec2(25.0f, 25.0f);
if (ImGui::IsItemActive()) const ImVec2 key_face_pos = ImVec2(5.0f, 3.0f);
ImGui::CaptureKeyboardFromApp(false); const float key_face_rounding = 2.0f;
const ImVec2 key_label_pos = ImVec2(7.0f, 4.0f);
const ImVec2 key_step = ImVec2(key_size.x - 1.0f, key_size.y - 1.0f);
const float key_row_offset = 9.0f;
ImVec2 board_min = ImGui::GetCursorScreenPos();
ImVec2 board_max = ImVec2(board_min.x + 3 * key_step.x + 2 * key_row_offset + 10.0f, board_min.y + 3 * key_step.y + 10.0f);
ImVec2 start_pos = ImVec2(board_min.x + 5.0f - key_step.x, board_min.y);
struct KeyLayoutData { int Row, Col; const char* Label; ImGuiKey Key; };
const KeyLayoutData keys_to_display[] =
{
{ 0, 0, "", ImGuiKey_Tab }, { 0, 1, "Q", ImGuiKey_Q }, { 0, 2, "W", ImGuiKey_W }, { 0, 3, "E", ImGuiKey_E }, { 0, 4, "R", ImGuiKey_R },
{ 1, 0, "", ImGuiKey_CapsLock }, { 1, 1, "A", ImGuiKey_A }, { 1, 2, "S", ImGuiKey_S }, { 1, 3, "D", ImGuiKey_D }, { 1, 4, "F", ImGuiKey_F },
{ 2, 0, "", ImGuiKey_LeftShift },{ 2, 1, "Z", ImGuiKey_Z }, { 2, 2, "X", ImGuiKey_X }, { 2, 3, "C", ImGuiKey_C }, { 2, 4, "V", ImGuiKey_V }
};
// Elements rendered manually via ImDrawList API are not clipped automatically.
// While not strictly necessary, here IsItemVisible() is used to avoid rendering these shapes when they are out of view.
ImGui::Dummy(ImVec2(board_max.x - board_min.x, board_max.y - board_min.y));
if (ImGui::IsItemVisible())
{
ImDrawList* draw_list = ImGui::GetWindowDrawList();
draw_list->PushClipRect(board_min, board_max, true);
for (int n = 0; n < IM_ARRAYSIZE(keys_to_display); n++)
{
const KeyLayoutData* key_data = &keys_to_display[n];
ImVec2 key_min = ImVec2(start_pos.x + key_data->Col * key_step.x + key_data->Row * key_row_offset, start_pos.y + key_data->Row * key_step.y);
ImVec2 key_max = ImVec2(key_min.x + key_size.x, key_min.y + key_size.y);
draw_list->AddRectFilled(key_min, key_max, IM_COL32(204, 204, 204, 255), key_rounding);
draw_list->AddRect(key_min, key_max, IM_COL32(24, 24, 24, 255), key_rounding);
ImVec2 face_min = ImVec2(key_min.x + key_face_pos.x, key_min.y + key_face_pos.y);
ImVec2 face_max = ImVec2(face_min.x + key_face_size.x, face_min.y + key_face_size.y);
draw_list->AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, ImDrawFlags_None, 2.0f);
draw_list->AddRectFilled(face_min, face_max, IM_COL32(252, 252, 252, 255), key_face_rounding);
ImVec2 label_min = ImVec2(key_min.x + key_label_pos.x, key_min.y + key_label_pos.y);
draw_list->AddText(label_min, IM_COL32(64, 64, 64, 255), key_data->Label);
if (ImGui::IsKeyDown(key_data->Key))
draw_list->AddRectFilled(key_min, key_max, IM_COL32(255, 0, 0, 128), key_rounding);
}
draw_list->PopClipRect();
}
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Capture override"))
{
HelpMarker(
"The value of io.WantCaptureMouse and io.WantCaptureKeyboard are normally set by Dear ImGui "
"to instruct your application of how to route inputs. Typically, when a value is true, it means "
"Dear ImGui wants the corresponding inputs and we expect the underlying application to ignore them.\n\n"
"The most typical case is: when hovering a window, Dear ImGui set io.WantCaptureMouse to true, "
"and underlying application should ignore mouse inputs (in practice there are many and more subtle "
"rules leading to how those flags are set).");
ImGui::Text("io.WantCaptureMouse: %d", io.WantCaptureMouse);
ImGui::Text("io.WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose);
ImGui::Text("io.WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
HelpMarker(
"Hovering the colored canvas will override io.WantCaptureXXX fields.\n"
"Notice how normally (when set to none), the value of io.WantCaptureKeyboard would be false when hovering and true when clicking.");
static int capture_override_mouse = -1;
static int capture_override_keyboard = -1;
const char* capture_override_desc[] = { "None", "Set to false", "Set to true" };
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
ImGui::SliderInt("SetNextFrameWantCaptureMouse()", &capture_override_mouse, -1, +1, capture_override_desc[capture_override_mouse + 1], ImGuiSliderFlags_AlwaysClamp);
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
ImGui::SliderInt("SetNextFrameWantCaptureKeyboard()", &capture_override_keyboard, -1, +1, capture_override_desc[capture_override_keyboard + 1], ImGuiSliderFlags_AlwaysClamp);
ImGui::ColorButton("##panel", ImVec4(0.7f, 0.1f, 0.7f, 1.0f), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop, ImVec2(256.0f, 192.0f)); // Dummy item
if (ImGui::IsItemHovered() && capture_override_mouse != -1)
ImGui::SetNextFrameWantCaptureMouse(capture_override_mouse == 1);
if (ImGui::IsItemHovered() && capture_override_keyboard != -1)
ImGui::SetNextFrameWantCaptureKeyboard(capture_override_keyboard == 1);
ImGui::TreePop(); ImGui::TreePop();
} }
@@ -5868,6 +5974,9 @@ void ImGui::ShowAboutWindow(bool* p_open)
#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS"); ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS");
#endif #endif
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_KEYIO");
#endif
#ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS #ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS"); ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS");
#endif #endif
@@ -5981,7 +6090,7 @@ void ImGui::ShowAboutWindow(bool* p_open)
namespace ImGui { IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); } namespace ImGui { IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); }
// Demo helper function to select among loaded fonts. // Demo helper function to select among loaded fonts.
// Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one. // Here we use the regular BeginCombo()/EndCombo() api which is the more flexible one.
void ImGui::ShowFontSelector(const char* label) void ImGui::ShowFontSelector(const char* label)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
@@ -7256,7 +7365,7 @@ static void ShowExampleAppSimpleOverlay(bool* p_open)
static void ShowExampleAppFullscreen(bool* p_open) static void ShowExampleAppFullscreen(bool* p_open)
{ {
static bool use_work_area = true; static bool use_work_area = true;
static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings; static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings;
// We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.) // We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.)
// Based on your use case you may want one of the other. // Based on your use case you may want one of the other.
@@ -7509,8 +7618,8 @@ static void ShowExampleAppCustomRendering(bool* p_open)
// Context menu (under default mouse threshold) // Context menu (under default mouse threshold)
ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right); ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
if (opt_enable_context_menu && ImGui::IsMouseReleased(ImGuiMouseButton_Right) && drag_delta.x == 0.0f && drag_delta.y == 0.0f) if (opt_enable_context_menu && drag_delta.x == 0.0f && drag_delta.y == 0.0f)
ImGui::OpenPopupOnItemClick("context"); ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight);
if (ImGui::BeginPopup("context")) if (ImGui::BeginPopup("context"))
{ {
if (adding_line) if (adding_line)
+46 -68
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.86 // dear imgui, v1.88
// (drawing and font code) // (drawing and font code)
/* /*
@@ -90,7 +90,7 @@ Index of this file:
#endif #endif
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// [SECTION] STB libraries implementation // [SECTION] STB libraries implementation (for stb_truetype and stb_rect_pack)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Compile time options: // Compile time options:
@@ -393,7 +393,7 @@ void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error)
for (int i = 0; i < IM_ARRAYSIZE(CircleSegmentCounts); i++) for (int i = 0; i < IM_ARRAYSIZE(CircleSegmentCounts); i++)
{ {
const float radius = (float)i; const float radius = (float)i;
CircleSegmentCounts[i] = (ImU8)((i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError) : 0); CircleSegmentCounts[i] = (ImU8)((i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError) : IM_DRAWLIST_ARCFAST_SAMPLE_MAX);
} }
ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError); ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError);
} }
@@ -402,10 +402,9 @@ void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error)
void ImDrawList::_ResetForNewFrame() void ImDrawList::_ResetForNewFrame()
{ {
// Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory. // Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory.
// (those should be IM_STATIC_ASSERT() in theory but with our pre C++11 setup the whole check doesn't compile with GCC) IM_STATIC_ASSERT(IM_OFFSETOF(ImDrawCmd, ClipRect) == 0);
IM_ASSERT(IM_OFFSETOF(ImDrawCmd, ClipRect) == 0); IM_STATIC_ASSERT(IM_OFFSETOF(ImDrawCmd, TextureId) == sizeof(ImVec4));
IM_ASSERT(IM_OFFSETOF(ImDrawCmd, TextureId) == sizeof(ImVec4)); IM_STATIC_ASSERT(IM_OFFSETOF(ImDrawCmd, VtxOffset) == sizeof(ImVec4) + sizeof(ImTextureID));
IM_ASSERT(IM_OFFSETOF(ImDrawCmd, VtxOffset) == sizeof(ImVec4) + sizeof(ImTextureID));
CmdBuffer.resize(0); CmdBuffer.resize(0);
IdxBuffer.resize(0); IdxBuffer.resize(0);
@@ -488,9 +487,10 @@ void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
} }
// Compare ClipRect, TextureId and VtxOffset with a single memcmp() // Compare ClipRect, TextureId and VtxOffset with a single memcmp()
#define ImDrawCmd_HeaderSize (IM_OFFSETOF(ImDrawCmd, VtxOffset) + sizeof(unsigned int)) #define ImDrawCmd_HeaderSize (IM_OFFSETOF(ImDrawCmd, VtxOffset) + sizeof(unsigned int))
#define ImDrawCmd_HeaderCompare(CMD_LHS, CMD_RHS) (memcmp(CMD_LHS, CMD_RHS, ImDrawCmd_HeaderSize)) // Compare ClipRect, TextureId, VtxOffset #define ImDrawCmd_HeaderCompare(CMD_LHS, CMD_RHS) (memcmp(CMD_LHS, CMD_RHS, ImDrawCmd_HeaderSize)) // Compare ClipRect, TextureId, VtxOffset
#define ImDrawCmd_HeaderCopy(CMD_DST, CMD_SRC) (memcpy(CMD_DST, CMD_SRC, ImDrawCmd_HeaderSize)) // Copy ClipRect, TextureId, VtxOffset #define ImDrawCmd_HeaderCopy(CMD_DST, CMD_SRC) (memcpy(CMD_DST, CMD_SRC, ImDrawCmd_HeaderSize)) // Copy ClipRect, TextureId, VtxOffset
#define ImDrawCmd_AreSequentialIdxOffset(CMD_0, CMD_1) (CMD_0->IdxOffset + CMD_0->ElemCount == CMD_1->IdxOffset)
// Try to merge two last draw commands // Try to merge two last draw commands
void ImDrawList::_TryMergeDrawCmds() void ImDrawList::_TryMergeDrawCmds()
@@ -498,7 +498,7 @@ void ImDrawList::_TryMergeDrawCmds()
IM_ASSERT_PARANOID(CmdBuffer.Size > 0); IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
ImDrawCmd* prev_cmd = curr_cmd - 1; ImDrawCmd* prev_cmd = curr_cmd - 1;
if (ImDrawCmd_HeaderCompare(curr_cmd, prev_cmd) == 0 && curr_cmd->UserCallback == NULL && prev_cmd->UserCallback == NULL) if (ImDrawCmd_HeaderCompare(curr_cmd, prev_cmd) == 0 && ImDrawCmd_AreSequentialIdxOffset(prev_cmd, curr_cmd) && curr_cmd->UserCallback == NULL && prev_cmd->UserCallback == NULL)
{ {
prev_cmd->ElemCount += curr_cmd->ElemCount; prev_cmd->ElemCount += curr_cmd->ElemCount;
CmdBuffer.pop_back(); CmdBuffer.pop_back();
@@ -521,7 +521,7 @@ void ImDrawList::_OnChangedClipRect()
// Try to merge with previous command if it matches, else use current command // Try to merge with previous command if it matches, else use current command
ImDrawCmd* prev_cmd = curr_cmd - 1; ImDrawCmd* prev_cmd = curr_cmd - 1;
if (curr_cmd->ElemCount == 0 && CmdBuffer.Size > 1 && ImDrawCmd_HeaderCompare(&_CmdHeader, prev_cmd) == 0 && prev_cmd->UserCallback == NULL) if (curr_cmd->ElemCount == 0 && CmdBuffer.Size > 1 && ImDrawCmd_HeaderCompare(&_CmdHeader, prev_cmd) == 0 && ImDrawCmd_AreSequentialIdxOffset(prev_cmd, curr_cmd) && prev_cmd->UserCallback == NULL)
{ {
CmdBuffer.pop_back(); CmdBuffer.pop_back();
return; return;
@@ -544,7 +544,7 @@ void ImDrawList::_OnChangedTextureID()
// Try to merge with previous command if it matches, else use current command // Try to merge with previous command if it matches, else use current command
ImDrawCmd* prev_cmd = curr_cmd - 1; ImDrawCmd* prev_cmd = curr_cmd - 1;
if (curr_cmd->ElemCount == 0 && CmdBuffer.Size > 1 && ImDrawCmd_HeaderCompare(&_CmdHeader, prev_cmd) == 0 && prev_cmd->UserCallback == NULL) if (curr_cmd->ElemCount == 0 && CmdBuffer.Size > 1 && ImDrawCmd_HeaderCompare(&_CmdHeader, prev_cmd) == 0 && ImDrawCmd_AreSequentialIdxOffset(prev_cmd, curr_cmd) && prev_cmd->UserCallback == NULL)
{ {
CmdBuffer.pop_back(); CmdBuffer.pop_back();
return; return;
@@ -580,7 +580,7 @@ int ImDrawList::_CalcCircleAutoSegmentCount(float radius) const
} }
// Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_current_clip_rect) void ImDrawList::PushClipRect(const ImVec2& cr_min, const ImVec2& cr_max, bool intersect_with_current_clip_rect)
{ {
ImVec4 cr(cr_min.x, cr_min.y, cr_max.x, cr_max.y); ImVec4 cr(cr_min.x, cr_min.y, cr_max.x, cr_max.y);
if (intersect_with_current_clip_rect) if (intersect_with_current_clip_rect)
@@ -973,7 +973,8 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
} }
} }
// We intentionally avoid using ImVec2 and its math operators here to reduce cost to a minimum for debug/non-inlined builds. // - We intentionally avoid using ImVec2 and its math operators here to reduce cost to a minimum for debug/non-inlined builds.
// - Filled shapes must always use clockwise winding order. The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing.
void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col) void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col)
{ {
if (points_count < 3) if (points_count < 3)
@@ -1057,7 +1058,7 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun
void ImDrawList::_PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step) void ImDrawList::_PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step)
{ {
if (radius <= 0.0f) if (radius < 0.5f)
{ {
_Path.push_back(center); _Path.push_back(center);
return; return;
@@ -1149,7 +1150,7 @@ void ImDrawList::_PathArcToFastEx(const ImVec2& center, float radius, int a_min_
void ImDrawList::_PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments) void ImDrawList::_PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments)
{ {
if (radius <= 0.0f) if (radius < 0.5f)
{ {
_Path.push_back(center); _Path.push_back(center);
return; return;
@@ -1168,7 +1169,7 @@ void ImDrawList::_PathArcToN(const ImVec2& center, float radius, float a_min, fl
// 0: East, 3: South, 6: West, 9: North, 12: East // 0: East, 3: South, 6: West, 9: North, 12: East
void ImDrawList::PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12) void ImDrawList::PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12)
{ {
if (radius <= 0.0f) if (radius < 0.5f)
{ {
_Path.push_back(center); _Path.push_back(center);
return; return;
@@ -1178,7 +1179,7 @@ void ImDrawList::PathArcToFast(const ImVec2& center, float radius, int a_min_of_
void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments) void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments)
{ {
if (radius <= 0.0f) if (radius < 0.5f)
{ {
_Path.push_back(center); _Path.push_back(center);
return; return;
@@ -1206,8 +1207,8 @@ void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, floa
const float a_min_segment_angle = a_min_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX; const float a_min_segment_angle = a_min_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
const float a_max_segment_angle = a_max_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX; const float a_max_segment_angle = a_max_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
const bool a_emit_start = (a_min_segment_angle - a_min) != 0.0f; const bool a_emit_start = ImAbs(a_min_segment_angle - a_min) >= 1e-5f;
const bool a_emit_end = (a_max - a_max_segment_angle) != 0.0f; const bool a_emit_end = ImAbs(a_max - a_max_segment_angle) >= 1e-5f;
_Path.reserve(_Path.Size + (a_mid_samples + 1 + (a_emit_start ? 1 : 0) + (a_emit_end ? 1 : 0))); _Path.reserve(_Path.Size + (a_mid_samples + 1 + (a_emit_start ? 1 : 0) + (a_emit_end ? 1 : 0)));
if (a_emit_start) if (a_emit_start)
@@ -1359,7 +1360,7 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDr
rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f ) - 1.0f); rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f ) - 1.0f);
rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((flags & ImDrawFlags_RoundCornersLeft) == ImDrawFlags_RoundCornersLeft) || ((flags & ImDrawFlags_RoundCornersRight) == ImDrawFlags_RoundCornersRight) ? 0.5f : 1.0f ) - 1.0f); rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((flags & ImDrawFlags_RoundCornersLeft) == ImDrawFlags_RoundCornersLeft) || ((flags & ImDrawFlags_RoundCornersRight) == ImDrawFlags_RoundCornersRight) ? 0.5f : 1.0f ) - 1.0f);
if (rounding <= 0.0f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone) if (rounding < 0.5f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
{ {
PathLineTo(a); PathLineTo(a);
PathLineTo(ImVec2(b.x, a.y)); PathLineTo(ImVec2(b.x, a.y));
@@ -1405,7 +1406,7 @@ void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 c
{ {
if ((col & IM_COL32_A_MASK) == 0) if ((col & IM_COL32_A_MASK) == 0)
return; return;
if (rounding <= 0.0f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone) if (rounding < 0.5f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
{ {
PrimReserve(6, 4); PrimReserve(6, 4);
PrimRect(p_min, p_max, col); PrimRect(p_min, p_max, col);
@@ -1481,7 +1482,7 @@ void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImV
void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness) void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness)
{ {
if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f) if ((col & IM_COL32_A_MASK) == 0 || radius < 0.5f)
return; return;
if (num_segments <= 0) if (num_segments <= 0)
@@ -1505,7 +1506,7 @@ void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int nu
void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments) void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments)
{ {
if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f) if ((col & IM_COL32_A_MASK) == 0 || radius < 0.5f)
return; return;
if (num_segments <= 0) if (num_segments <= 0)
@@ -1645,7 +1646,7 @@ void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_mi
return; return;
flags = FixRectCornerFlags(flags); flags = FixRectCornerFlags(flags);
if (rounding <= 0.0f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone) if (rounding < 0.5f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
{ {
AddImage(user_texture_id, p_min, p_max, uv_min, uv_max, col); AddImage(user_texture_id, p_min, p_max, uv_min, uv_max, col);
return; return;
@@ -1733,13 +1734,13 @@ void ImDrawListSplitter::Merge(ImDrawList* draw_list)
for (int i = 1; i < _Count; i++) for (int i = 1; i < _Count; i++)
{ {
ImDrawChannel& ch = _Channels[i]; ImDrawChannel& ch = _Channels[i];
if (ch._CmdBuffer.Size > 0 && ch._CmdBuffer.back().ElemCount == 0 && ch._CmdBuffer.back().UserCallback == NULL) // Equivalent of PopUnusedDrawCmd()
// Equivalent of PopUnusedDrawCmd() for this channel's cmdbuffer and except we don't need to test for UserCallback.
if (ch._CmdBuffer.Size > 0 && ch._CmdBuffer.back().ElemCount == 0)
ch._CmdBuffer.pop_back(); ch._CmdBuffer.pop_back();
if (ch._CmdBuffer.Size > 0 && last_cmd != NULL) if (ch._CmdBuffer.Size > 0 && last_cmd != NULL)
{ {
// Do not include ImDrawCmd_AreSequentialIdxOffset() in the compare as we rebuild IdxOffset values ourselves.
// Manipulating IdxOffset (e.g. by reordering draw commands like done by RenderDimmedBackgroundBehindWindow()) is not supported within a splitter.
ImDrawCmd* next_cmd = &ch._CmdBuffer[0]; ImDrawCmd* next_cmd = &ch._CmdBuffer[0];
if (ImDrawCmd_HeaderCompare(last_cmd, next_cmd) == 0 && last_cmd->UserCallback == NULL && next_cmd->UserCallback == NULL) if (ImDrawCmd_HeaderCompare(last_cmd, next_cmd) == 0 && last_cmd->UserCallback == NULL && next_cmd->UserCallback == NULL)
{ {
@@ -2637,8 +2638,8 @@ void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opa
for (int i = 0; i < pack_rects.Size; i++) for (int i = 0; i < pack_rects.Size; i++)
if (pack_rects[i].was_packed) if (pack_rects[i].was_packed)
{ {
user_rects[i].X = pack_rects[i].x; user_rects[i].X = (unsigned short)pack_rects[i].x;
user_rects[i].Y = pack_rects[i].y; user_rects[i].Y = (unsigned short)pack_rects[i].y;
IM_ASSERT(pack_rects[i].w == user_rects[i].Width && pack_rects[i].h == user_rects[i].Height); IM_ASSERT(pack_rects[i].w == user_rects[i].Width && pack_rects[i].h == user_rects[i].Height);
atlas->TexHeight = ImMax(atlas->TexHeight, pack_rects[i].y + pack_rects[i].h); atlas->TexHeight = ImMax(atlas->TexHeight, pack_rects[i].y + pack_rects[i].h);
} }
@@ -2738,13 +2739,13 @@ static void ImFontAtlasBuildRenderLinesTexData(ImFontAtlas* atlas)
{ {
unsigned int* write_ptr = &atlas->TexPixelsRGBA32[r->X + ((r->Y + y) * atlas->TexWidth)]; unsigned int* write_ptr = &atlas->TexPixelsRGBA32[r->X + ((r->Y + y) * atlas->TexWidth)];
for (unsigned int i = 0; i < pad_left; i++) for (unsigned int i = 0; i < pad_left; i++)
*(write_ptr + i) = IM_COL32_BLACK_TRANS; *(write_ptr + i) = IM_COL32(255, 255, 255, 0);
for (unsigned int i = 0; i < line_width; i++) for (unsigned int i = 0; i < line_width; i++)
*(write_ptr + pad_left + i) = IM_COL32_WHITE; *(write_ptr + pad_left + i) = IM_COL32_WHITE;
for (unsigned int i = 0; i < pad_right; i++) for (unsigned int i = 0; i < pad_right; i++)
*(write_ptr + pad_left + line_width + i) = IM_COL32_BLACK_TRANS; *(write_ptr + pad_left + line_width + i) = IM_COL32(255, 255, 255, 0);
} }
// Calculate UVs for this line // Calculate UVs for this line
@@ -3523,7 +3524,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
} }
// Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound.
void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, ImWchar c) const void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c) const
{ {
const ImFontGlyph* glyph = FindGlyph(c); const ImFontGlyph* glyph = FindGlyph(c);
if (!glyph || !glyph->Visible) if (!glyph || !glyph->Visible)
@@ -3531,26 +3532,25 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
if (glyph->Colored) if (glyph->Colored)
col |= ~IM_COL32_A_MASK; col |= ~IM_COL32_A_MASK;
float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f; float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f;
pos.x = IM_FLOOR(pos.x); float x = IM_FLOOR(pos.x);
pos.y = IM_FLOOR(pos.y); float y = IM_FLOOR(pos.y);
draw_list->PrimReserve(6, 4); draw_list->PrimReserve(6, 4);
draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); draw_list->PrimRectUV(ImVec2(x + glyph->X0 * scale, y + glyph->Y0 * scale), ImVec2(x + glyph->X1 * scale, y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col);
} }
// Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound.
void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const
{ {
if (!text_end) if (!text_end)
text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls.
// Align to be pixel perfect // Align to be pixel perfect
pos.x = IM_FLOOR(pos.x); float x = IM_FLOOR(pos.x);
pos.y = IM_FLOOR(pos.y); float y = IM_FLOOR(pos.y);
float x = pos.x;
float y = pos.y;
if (y > clip_rect.w) if (y > clip_rect.w)
return; return;
const float start_x = x;
const float scale = size / FontSize; const float scale = size / FontSize;
const float line_height = FontSize * scale; const float line_height = FontSize * scale;
const bool word_wrap_enabled = (wrap_width > 0.0f); const bool word_wrap_enabled = (wrap_width > 0.0f);
@@ -3602,14 +3602,14 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
// Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature. // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
if (!word_wrap_eol) if (!word_wrap_eol)
{ {
word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - pos.x)); word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - start_x));
if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity. if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below
} }
if (s >= word_wrap_eol) if (s >= word_wrap_eol)
{ {
x = pos.x; x = start_x;
y += line_height; y += line_height;
word_wrap_eol = NULL; word_wrap_eol = NULL;
@@ -3640,7 +3640,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
{ {
if (c == '\n') if (c == '\n')
{ {
x = pos.x; x = start_x;
y += line_height; y += line_height;
if (y > clip_rect.w) if (y > clip_rect.w)
break; // break out of main loop break; // break out of main loop
@@ -3736,7 +3736,6 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
// - RenderArrow() // - RenderArrow()
// - RenderBullet() // - RenderBullet()
// - RenderCheckMark() // - RenderCheckMark()
// - RenderMouseCursor()
// - RenderArrowPointingAt() // - RenderArrowPointingAt()
// - RenderRectFilledRangeH() // - RenderRectFilledRangeH()
// - RenderRectFilledWithHole() // - RenderRectFilledWithHole()
@@ -3797,27 +3796,6 @@ void ImGui::RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float
draw_list->PathStroke(col, 0, thickness); draw_list->PathStroke(col, 0, thickness);
} }
void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow)
{
if (mouse_cursor == ImGuiMouseCursor_None)
return;
IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT);
ImFontAtlas* font_atlas = draw_list->_Data->Font->ContainerAtlas;
ImVec2 offset, size, uv[4];
if (font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2]))
{
pos -= offset;
ImTextureID tex_id = font_atlas->TexID;
draw_list->PushTextureID(tex_id);
draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow);
draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow);
draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border);
draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill);
draw_list->PopTextureID();
}
}
// Render an arrow. 'pos' is position of the arrow tip. half_sz.x is length from base to tip. half_sz.y is length on each side. // Render an arrow. 'pos' is position of the arrow tip. half_sz.x is length from base to tip. half_sz.y is length on each side.
void ImGui::RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col) void ImGui::RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col)
{ {
@@ -3900,7 +3878,7 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im
draw_list->PathFillConvex(col); draw_list->PathFillConvex(col);
} }
void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect inner, ImU32 col, float rounding) void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding)
{ {
const bool fill_L = (inner.Min.x > outer.Min.x); const bool fill_L = (inner.Min.x > outer.Min.x);
const bool fill_R = (inner.Max.x < outer.Max.x); const bool fill_R = (inner.Max.x < outer.Max.x);
+94 -16
View File
@@ -14,6 +14,8 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2022-05-23: OpenGL: Reworking 2021-12-15 "Using buffer orphaning" so it only happens on Intel GPU, seems to cause problems otherwise. (#4468, #4825, #4832, #5127).
// 2022-05-13: OpenGL: Fix state corruption on OpenGL ES 2.0 due to not preserving GL_ELEMENT_ARRAY_BUFFER_BINDING and vertex attribute states.
// 2021-12-15: OpenGL: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers. // 2021-12-15: OpenGL: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers.
// 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions. // 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions.
// 2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader. // 2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader.
@@ -95,10 +97,27 @@
#else #else
#include <stdint.h> // intptr_t #include <stdint.h> // intptr_t
#endif #endif
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
// Clang warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
#if __has_warning("-Wzero-as-null-pointer-constant")
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#endif
#endif
// GL includes // GL includes
#if defined(IMGUI_IMPL_OPENGL_ES2) #if defined(IMGUI_IMPL_OPENGL_ES2)
#include <GLES2/gl2.h> #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV))
#include <OpenGLES/ES2/gl.h> // Use GL ES 2
#else
#include <GLES2/gl2.h> // Use GL ES 2
#endif
#if defined(__EMSCRIPTEN__) #if defined(__EMSCRIPTEN__)
#ifndef GL_GLEXT_PROTOTYPES #ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES
@@ -106,9 +125,6 @@
#include <GLES2/gl2ext.h> #include <GLES2/gl2ext.h>
#endif #endif
#elif defined(IMGUI_IMPL_OPENGL_ES3) #elif defined(IMGUI_IMPL_OPENGL_ES3)
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV))
#include <OpenGLES/ES3/gl.h> // Use GL ES 3 #include <OpenGLES/ES3/gl.h> // Use GL ES 3
#else #else
@@ -178,8 +194,9 @@ struct ImGui_ImplOpenGL3_Data
GLsizeiptr VertexBufferSize; GLsizeiptr VertexBufferSize;
GLsizeiptr IndexBufferSize; GLsizeiptr IndexBufferSize;
bool HasClipOrigin; bool HasClipOrigin;
bool UseBufferSubData;
ImGui_ImplOpenGL3_Data() { memset(this, 0, sizeof(*this)); } ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); }
}; };
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
@@ -189,6 +206,30 @@ static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : NULL; return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
} }
// OpenGL vertex attribute state (for ES 1.0 and ES 2.0 only)
#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
struct ImGui_ImplOpenGL3_VtxAttribState
{
GLint Enabled, Size, Type, Normalized, Stride;
GLvoid* Ptr;
void GetState(GLint index)
{
glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &Enabled);
glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &Size);
glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &Type);
glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &Normalized);
glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &Stride);
glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &Ptr);
}
void SetState(GLint index)
{
glVertexAttribPointer(index, Size, Type, (GLboolean)Normalized, Stride, Ptr);
if (Enabled) glEnableVertexAttribArray(index); else glDisableVertexAttribArray(index);
}
};
#endif
// Functions // Functions
bool ImGui_ImplOpenGL3_Init(const char* glsl_version) bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
{ {
@@ -222,6 +263,14 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
sscanf(gl_version, "%d.%d", &major, &minor); sscanf(gl_version, "%d.%d", &major, &minor);
} }
bd->GlVersion = (GLuint)(major * 100 + minor * 10); bd->GlVersion = (GLuint)(major * 100 + minor * 10);
// Query vendor to enable glBufferSubData kludge
#ifdef _WIN32
if (const char* vendor = (const char*)glGetString(GL_VENDOR))
if (strncmp(vendor, "Intel", 5) == 0)
bd->UseBufferSubData = true;
#endif
//printf("GL_MAJOR_VERSION = %d\nGL_MINOR_VERSION = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", major, minor, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
#else #else
bd->GlVersion = 200; // GLES 2 bd->GlVersion = 200; // GLES 2
#endif #endif
@@ -386,6 +435,13 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
GLuint last_sampler; if (bd->GlVersion >= 330) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; } GLuint last_sampler; if (bd->GlVersion >= 330) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; }
#endif #endif
GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer); GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer);
#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
// This is part of VAO on OpenGL 3.0+ and OpenGL ES 3.0+.
GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_pos; last_vtx_attrib_state_pos.GetState(bd->AttribLocationVtxPos);
ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_uv; last_vtx_attrib_state_uv.GetState(bd->AttribLocationVtxUV);
ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_color; last_vtx_attrib_state_color.GetState(bd->AttribLocationVtxColor);
#endif
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object); GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object);
#endif #endif
@@ -428,20 +484,31 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawList* cmd_list = draw_data->CmdLists[n];
// Upload vertex/index buffers // Upload vertex/index buffers
GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert); // - On Intel windows drivers we got reports that regular glBufferData() led to accumulating leaks when using multi-viewports, so we started using orphaning + glBufferSubData(). (See https://github.com/ocornut/imgui/issues/4468)
GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx); // - On NVIDIA drivers we got reports that using orphaning + glBufferSubData() led to glitches when using multi-viewports.
if (bd->VertexBufferSize < vtx_buffer_size) // - OpenGL drivers are in a very sorry state in 2022, for now we are switching code path based on vendors.
const GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
const GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
if (bd->UseBufferSubData)
{ {
bd->VertexBufferSize = vtx_buffer_size; if (bd->VertexBufferSize < vtx_buffer_size)
glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, NULL, GL_STREAM_DRAW); {
bd->VertexBufferSize = vtx_buffer_size;
glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, NULL, GL_STREAM_DRAW);
}
if (bd->IndexBufferSize < idx_buffer_size)
{
bd->IndexBufferSize = idx_buffer_size;
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, NULL, GL_STREAM_DRAW);
}
glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data);
} }
if (bd->IndexBufferSize < idx_buffer_size) else
{ {
bd->IndexBufferSize = idx_buffer_size; glBufferData(GL_ARRAY_BUFFER, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, NULL, GL_STREAM_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
} }
glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data);
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{ {
@@ -464,7 +531,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
continue; continue;
// Apply scissor/clipping rectangle (Y is inverted in OpenGL) // Apply scissor/clipping rectangle (Y is inverted in OpenGL)
glScissor((int)clip_min.x, (int)(fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y)); glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y));
// Bind texture, Draw // Bind texture, Draw
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()); glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
@@ -495,6 +562,12 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
glBindVertexArray(last_vertex_array_object); glBindVertexArray(last_vertex_array_object);
#endif #endif
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer);
last_vtx_attrib_state_pos.SetState(bd->AttribLocationVtxPos);
last_vtx_attrib_state_uv.SetState(bd->AttribLocationVtxUV);
last_vtx_attrib_state_color.SetState(bd->AttribLocationVtxColor);
#endif
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha); glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha); glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
@@ -525,6 +598,7 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture()
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
// Upload texture to graphics system // Upload texture to graphics system
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
GLint last_texture; GLint last_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGenTextures(1, &bd->FontTexture); glGenTextures(1, &bd->FontTexture);
@@ -791,3 +865,7 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects()
if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; } if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; }
ImGui_ImplOpenGL3_DestroyFontsTexture(); ImGui_ImplOpenGL3_DestroyFontsTexture();
} }
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
+1 -1
View File
@@ -46,7 +46,7 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
#endif #endif
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__)) #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__))
#define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" #define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es"
#elif defined(__EMSCRIPTEN__) #elif defined(__EMSCRIPTEN__) || defined(__amigaos4__)
#define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100" #define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100"
#else #else
// Otherwise imgui_impl_opengl3_loader.h will be used. // Otherwise imgui_impl_opengl3_loader.h will be used.
+138 -109
View File
@@ -164,6 +164,8 @@ typedef khronos_uint8_t GLubyte;
#define GL_FLOAT 0x1406 #define GL_FLOAT 0x1406
#define GL_RGBA 0x1908 #define GL_RGBA 0x1908
#define GL_FILL 0x1B02 #define GL_FILL 0x1B02
#define GL_VENDOR 0x1F00
#define GL_RENDERER 0x1F01
#define GL_VERSION 0x1F02 #define GL_VERSION 0x1F02
#define GL_EXTENSIONS 0x1F03 #define GL_EXTENSIONS 0x1F03
#define GL_LINEAR 0x2601 #define GL_LINEAR 0x2601
@@ -177,6 +179,7 @@ typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap); typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap); typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap);
typedef void (APIENTRYP PFNGLFLUSHPROC) (void);
typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param); typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void); typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
@@ -193,6 +196,7 @@ GLAPI void APIENTRY glClear (GLbitfield mask);
GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
GLAPI void APIENTRY glDisable (GLenum cap); GLAPI void APIENTRY glDisable (GLenum cap);
GLAPI void APIENTRY glEnable (GLenum cap); GLAPI void APIENTRY glEnable (GLenum cap);
GLAPI void APIENTRY glFlush (void);
GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param); GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param);
GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
GLAPI GLenum APIENTRY glGetError (void); GLAPI GLenum APIENTRY glGetError (void);
@@ -244,6 +248,7 @@ typedef khronos_intptr_t GLintptr;
#define GL_ARRAY_BUFFER 0x8892 #define GL_ARRAY_BUFFER 0x8892
#define GL_ELEMENT_ARRAY_BUFFER 0x8893 #define GL_ELEMENT_ARRAY_BUFFER 0x8893
#define GL_ARRAY_BUFFER_BINDING 0x8894 #define GL_ARRAY_BUFFER_BINDING 0x8894
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
#define GL_STREAM_DRAW 0x88E0 #define GL_STREAM_DRAW 0x88E0
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
@@ -264,7 +269,13 @@ typedef khronos_int16_t GLshort;
typedef khronos_int8_t GLbyte; typedef khronos_int8_t GLbyte;
typedef khronos_uint16_t GLushort; typedef khronos_uint16_t GLushort;
#define GL_BLEND_EQUATION_RGB 0x8009 #define GL_BLEND_EQUATION_RGB 0x8009
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
#define GL_BLEND_EQUATION_ALPHA 0x883D #define GL_BLEND_EQUATION_ALPHA 0x883D
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
#define GL_FRAGMENT_SHADER 0x8B30 #define GL_FRAGMENT_SHADER 0x8B30
#define GL_VERTEX_SHADER 0x8B31 #define GL_VERTEX_SHADER 0x8B31
#define GL_COMPILE_STATUS 0x8B81 #define GL_COMPILE_STATUS 0x8B81
@@ -280,6 +291,7 @@ typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader); typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
@@ -287,6 +299,8 @@ typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei buf
typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
@@ -302,6 +316,7 @@ GLAPI GLuint APIENTRY glCreateShader (GLenum type);
GLAPI void APIENTRY glDeleteProgram (GLuint program); GLAPI void APIENTRY glDeleteProgram (GLuint program);
GLAPI void APIENTRY glDeleteShader (GLuint shader); GLAPI void APIENTRY glDeleteShader (GLuint shader);
GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader); GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader);
GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index);
GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index); GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index);
GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
@@ -309,6 +324,8 @@ GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsize
GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
GLAPI void APIENTRY glLinkProgram (GLuint program); GLAPI void APIENTRY glLinkProgram (GLuint program);
GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
GLAPI void APIENTRY glUseProgram (GLuint program); GLAPI void APIENTRY glUseProgram (GLuint program);
@@ -437,122 +454,130 @@ GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);
/* gl3w internal state */ /* gl3w internal state */
union GL3WProcs { union GL3WProcs {
GL3WglProc ptr[53]; GL3WglProc ptr[58];
struct { struct {
PFNGLACTIVETEXTUREPROC ActiveTexture; PFNGLACTIVETEXTUREPROC ActiveTexture;
PFNGLATTACHSHADERPROC AttachShader; PFNGLATTACHSHADERPROC AttachShader;
PFNGLBINDBUFFERPROC BindBuffer; PFNGLBINDBUFFERPROC BindBuffer;
PFNGLBINDSAMPLERPROC BindSampler; PFNGLBINDSAMPLERPROC BindSampler;
PFNGLBINDTEXTUREPROC BindTexture; PFNGLBINDTEXTUREPROC BindTexture;
PFNGLBINDVERTEXARRAYPROC BindVertexArray; PFNGLBINDVERTEXARRAYPROC BindVertexArray;
PFNGLBLENDEQUATIONPROC BlendEquation; PFNGLBLENDEQUATIONPROC BlendEquation;
PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate; PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate;
PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate; PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate;
PFNGLBUFFERDATAPROC BufferData; PFNGLBUFFERDATAPROC BufferData;
PFNGLBUFFERSUBDATAPROC BufferSubData; PFNGLBUFFERSUBDATAPROC BufferSubData;
PFNGLCLEARPROC Clear; PFNGLCLEARPROC Clear;
PFNGLCLEARCOLORPROC ClearColor; PFNGLCLEARCOLORPROC ClearColor;
PFNGLCOMPILESHADERPROC CompileShader; PFNGLCOMPILESHADERPROC CompileShader;
PFNGLCREATEPROGRAMPROC CreateProgram; PFNGLCREATEPROGRAMPROC CreateProgram;
PFNGLCREATESHADERPROC CreateShader; PFNGLCREATESHADERPROC CreateShader;
PFNGLDELETEBUFFERSPROC DeleteBuffers; PFNGLDELETEBUFFERSPROC DeleteBuffers;
PFNGLDELETEPROGRAMPROC DeleteProgram; PFNGLDELETEPROGRAMPROC DeleteProgram;
PFNGLDELETESHADERPROC DeleteShader; PFNGLDELETESHADERPROC DeleteShader;
PFNGLDELETETEXTURESPROC DeleteTextures; PFNGLDELETETEXTURESPROC DeleteTextures;
PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays; PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays;
PFNGLDETACHSHADERPROC DetachShader; PFNGLDETACHSHADERPROC DetachShader;
PFNGLDISABLEPROC Disable; PFNGLDISABLEPROC Disable;
PFNGLDRAWELEMENTSPROC DrawElements; PFNGLDISABLEVERTEXATTRIBARRAYPROC DisableVertexAttribArray;
PFNGLDRAWELEMENTSBASEVERTEXPROC DrawElementsBaseVertex; PFNGLDRAWELEMENTSPROC DrawElements;
PFNGLENABLEPROC Enable; PFNGLDRAWELEMENTSBASEVERTEXPROC DrawElementsBaseVertex;
PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray; PFNGLENABLEPROC Enable;
PFNGLGENBUFFERSPROC GenBuffers; PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
PFNGLGENTEXTURESPROC GenTextures; PFNGLFLUSHPROC Flush;
PFNGLGENVERTEXARRAYSPROC GenVertexArrays; PFNGLGENBUFFERSPROC GenBuffers;
PFNGLGETATTRIBLOCATIONPROC GetAttribLocation; PFNGLGENTEXTURESPROC GenTextures;
PFNGLGETERRORPROC GetError; PFNGLGENVERTEXARRAYSPROC GenVertexArrays;
PFNGLGETINTEGERVPROC GetIntegerv; PFNGLGETATTRIBLOCATIONPROC GetAttribLocation;
PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog; PFNGLGETERRORPROC GetError;
PFNGLGETPROGRAMIVPROC GetProgramiv; PFNGLGETINTEGERVPROC GetIntegerv;
PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog; PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog;
PFNGLGETSHADERIVPROC GetShaderiv; PFNGLGETPROGRAMIVPROC GetProgramiv;
PFNGLGETSTRINGPROC GetString; PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog;
PFNGLGETSTRINGIPROC GetStringi; PFNGLGETSHADERIVPROC GetShaderiv;
PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation; PFNGLGETSTRINGPROC GetString;
PFNGLISENABLEDPROC IsEnabled; PFNGLGETSTRINGIPROC GetStringi;
PFNGLLINKPROGRAMPROC LinkProgram; PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation;
PFNGLPIXELSTOREIPROC PixelStorei; PFNGLGETVERTEXATTRIBPOINTERVPROC GetVertexAttribPointerv;
PFNGLPOLYGONMODEPROC PolygonMode; PFNGLGETVERTEXATTRIBIVPROC GetVertexAttribiv;
PFNGLREADPIXELSPROC ReadPixels; PFNGLISENABLEDPROC IsEnabled;
PFNGLSCISSORPROC Scissor; PFNGLLINKPROGRAMPROC LinkProgram;
PFNGLSHADERSOURCEPROC ShaderSource; PFNGLPIXELSTOREIPROC PixelStorei;
PFNGLTEXIMAGE2DPROC TexImage2D; PFNGLPOLYGONMODEPROC PolygonMode;
PFNGLTEXPARAMETERIPROC TexParameteri; PFNGLREADPIXELSPROC ReadPixels;
PFNGLUNIFORM1IPROC Uniform1i; PFNGLSCISSORPROC Scissor;
PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv; PFNGLSHADERSOURCEPROC ShaderSource;
PFNGLUSEPROGRAMPROC UseProgram; PFNGLTEXIMAGE2DPROC TexImage2D;
PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer; PFNGLTEXPARAMETERIPROC TexParameteri;
PFNGLVIEWPORTPROC Viewport; PFNGLUNIFORM1IPROC Uniform1i;
PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv;
PFNGLUSEPROGRAMPROC UseProgram;
PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer;
PFNGLVIEWPORTPROC Viewport;
} gl; } gl;
}; };
GL3W_API extern union GL3WProcs imgl3wProcs; GL3W_API extern union GL3WProcs imgl3wProcs;
/* OpenGL functions */ /* OpenGL functions */
#define glActiveTexture imgl3wProcs.gl.ActiveTexture #define glActiveTexture imgl3wProcs.gl.ActiveTexture
#define glAttachShader imgl3wProcs.gl.AttachShader #define glAttachShader imgl3wProcs.gl.AttachShader
#define glBindBuffer imgl3wProcs.gl.BindBuffer #define glBindBuffer imgl3wProcs.gl.BindBuffer
#define glBindSampler imgl3wProcs.gl.BindSampler #define glBindSampler imgl3wProcs.gl.BindSampler
#define glBindTexture imgl3wProcs.gl.BindTexture #define glBindTexture imgl3wProcs.gl.BindTexture
#define glBindVertexArray imgl3wProcs.gl.BindVertexArray #define glBindVertexArray imgl3wProcs.gl.BindVertexArray
#define glBlendEquation imgl3wProcs.gl.BlendEquation #define glBlendEquation imgl3wProcs.gl.BlendEquation
#define glBlendEquationSeparate imgl3wProcs.gl.BlendEquationSeparate #define glBlendEquationSeparate imgl3wProcs.gl.BlendEquationSeparate
#define glBlendFuncSeparate imgl3wProcs.gl.BlendFuncSeparate #define glBlendFuncSeparate imgl3wProcs.gl.BlendFuncSeparate
#define glBufferData imgl3wProcs.gl.BufferData #define glBufferData imgl3wProcs.gl.BufferData
#define glBufferSubData imgl3wProcs.gl.BufferSubData #define glBufferSubData imgl3wProcs.gl.BufferSubData
#define glClear imgl3wProcs.gl.Clear #define glClear imgl3wProcs.gl.Clear
#define glClearColor imgl3wProcs.gl.ClearColor #define glClearColor imgl3wProcs.gl.ClearColor
#define glCompileShader imgl3wProcs.gl.CompileShader #define glCompileShader imgl3wProcs.gl.CompileShader
#define glCreateProgram imgl3wProcs.gl.CreateProgram #define glCreateProgram imgl3wProcs.gl.CreateProgram
#define glCreateShader imgl3wProcs.gl.CreateShader #define glCreateShader imgl3wProcs.gl.CreateShader
#define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers #define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers
#define glDeleteProgram imgl3wProcs.gl.DeleteProgram #define glDeleteProgram imgl3wProcs.gl.DeleteProgram
#define glDeleteShader imgl3wProcs.gl.DeleteShader #define glDeleteShader imgl3wProcs.gl.DeleteShader
#define glDeleteTextures imgl3wProcs.gl.DeleteTextures #define glDeleteTextures imgl3wProcs.gl.DeleteTextures
#define glDeleteVertexArrays imgl3wProcs.gl.DeleteVertexArrays #define glDeleteVertexArrays imgl3wProcs.gl.DeleteVertexArrays
#define glDetachShader imgl3wProcs.gl.DetachShader #define glDetachShader imgl3wProcs.gl.DetachShader
#define glDisable imgl3wProcs.gl.Disable #define glDisable imgl3wProcs.gl.Disable
#define glDrawElements imgl3wProcs.gl.DrawElements #define glDisableVertexAttribArray imgl3wProcs.gl.DisableVertexAttribArray
#define glDrawElementsBaseVertex imgl3wProcs.gl.DrawElementsBaseVertex #define glDrawElements imgl3wProcs.gl.DrawElements
#define glEnable imgl3wProcs.gl.Enable #define glDrawElementsBaseVertex imgl3wProcs.gl.DrawElementsBaseVertex
#define glEnableVertexAttribArray imgl3wProcs.gl.EnableVertexAttribArray #define glEnable imgl3wProcs.gl.Enable
#define glGenBuffers imgl3wProcs.gl.GenBuffers #define glEnableVertexAttribArray imgl3wProcs.gl.EnableVertexAttribArray
#define glGenTextures imgl3wProcs.gl.GenTextures #define glFlush imgl3wProcs.gl.Flush
#define glGenVertexArrays imgl3wProcs.gl.GenVertexArrays #define glGenBuffers imgl3wProcs.gl.GenBuffers
#define glGetAttribLocation imgl3wProcs.gl.GetAttribLocation #define glGenTextures imgl3wProcs.gl.GenTextures
#define glGetError imgl3wProcs.gl.GetError #define glGenVertexArrays imgl3wProcs.gl.GenVertexArrays
#define glGetIntegerv imgl3wProcs.gl.GetIntegerv #define glGetAttribLocation imgl3wProcs.gl.GetAttribLocation
#define glGetProgramInfoLog imgl3wProcs.gl.GetProgramInfoLog #define glGetError imgl3wProcs.gl.GetError
#define glGetProgramiv imgl3wProcs.gl.GetProgramiv #define glGetIntegerv imgl3wProcs.gl.GetIntegerv
#define glGetShaderInfoLog imgl3wProcs.gl.GetShaderInfoLog #define glGetProgramInfoLog imgl3wProcs.gl.GetProgramInfoLog
#define glGetShaderiv imgl3wProcs.gl.GetShaderiv #define glGetProgramiv imgl3wProcs.gl.GetProgramiv
#define glGetString imgl3wProcs.gl.GetString #define glGetShaderInfoLog imgl3wProcs.gl.GetShaderInfoLog
#define glGetStringi imgl3wProcs.gl.GetStringi #define glGetShaderiv imgl3wProcs.gl.GetShaderiv
#define glGetUniformLocation imgl3wProcs.gl.GetUniformLocation #define glGetString imgl3wProcs.gl.GetString
#define glIsEnabled imgl3wProcs.gl.IsEnabled #define glGetStringi imgl3wProcs.gl.GetStringi
#define glLinkProgram imgl3wProcs.gl.LinkProgram #define glGetUniformLocation imgl3wProcs.gl.GetUniformLocation
#define glPixelStorei imgl3wProcs.gl.PixelStorei #define glGetVertexAttribPointerv imgl3wProcs.gl.GetVertexAttribPointerv
#define glPolygonMode imgl3wProcs.gl.PolygonMode #define glGetVertexAttribiv imgl3wProcs.gl.GetVertexAttribiv
#define glReadPixels imgl3wProcs.gl.ReadPixels #define glIsEnabled imgl3wProcs.gl.IsEnabled
#define glScissor imgl3wProcs.gl.Scissor #define glLinkProgram imgl3wProcs.gl.LinkProgram
#define glShaderSource imgl3wProcs.gl.ShaderSource #define glPixelStorei imgl3wProcs.gl.PixelStorei
#define glTexImage2D imgl3wProcs.gl.TexImage2D #define glPolygonMode imgl3wProcs.gl.PolygonMode
#define glTexParameteri imgl3wProcs.gl.TexParameteri #define glReadPixels imgl3wProcs.gl.ReadPixels
#define glUniform1i imgl3wProcs.gl.Uniform1i #define glScissor imgl3wProcs.gl.Scissor
#define glUniformMatrix4fv imgl3wProcs.gl.UniformMatrix4fv #define glShaderSource imgl3wProcs.gl.ShaderSource
#define glUseProgram imgl3wProcs.gl.UseProgram #define glTexImage2D imgl3wProcs.gl.TexImage2D
#define glVertexAttribPointer imgl3wProcs.gl.VertexAttribPointer #define glTexParameteri imgl3wProcs.gl.TexParameteri
#define glViewport imgl3wProcs.gl.Viewport #define glUniform1i imgl3wProcs.gl.Uniform1i
#define glUniformMatrix4fv imgl3wProcs.gl.UniformMatrix4fv
#define glUseProgram imgl3wProcs.gl.UseProgram
#define glVertexAttribPointer imgl3wProcs.gl.VertexAttribPointer
#define glViewport imgl3wProcs.gl.Viewport
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -709,10 +734,12 @@ static const char *proc_names[] = {
"glDeleteVertexArrays", "glDeleteVertexArrays",
"glDetachShader", "glDetachShader",
"glDisable", "glDisable",
"glDisableVertexAttribArray",
"glDrawElements", "glDrawElements",
"glDrawElementsBaseVertex", "glDrawElementsBaseVertex",
"glEnable", "glEnable",
"glEnableVertexAttribArray", "glEnableVertexAttribArray",
"glFlush",
"glGenBuffers", "glGenBuffers",
"glGenTextures", "glGenTextures",
"glGenVertexArrays", "glGenVertexArrays",
@@ -726,6 +753,8 @@ static const char *proc_names[] = {
"glGetString", "glGetString",
"glGetStringi", "glGetStringi",
"glGetUniformLocation", "glGetUniformLocation",
"glGetVertexAttribPointerv",
"glGetVertexAttribiv",
"glIsEnabled", "glIsEnabled",
"glLinkProgram", "glLinkProgram",
"glPixelStorei", "glPixelStorei",
+255 -140
View File
@@ -4,10 +4,10 @@
// (Prefer SDL 2.0.5+ for full feature support.) // (Prefer SDL 2.0.5+ for full feature support.)
// Implemented features: // Implemented features:
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Clipboard support. // [X] Platform: Clipboard support.
// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE). // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// Missing features: // Missing features:
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. // [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
@@ -18,6 +18,16 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2022-03-22: Inputs: Fix mouse position issues when dragging outside of boundaries. SDL_CaptureMouse() erroneously still gives out LEAVE events when hovering OS decorations.
// 2022-03-22: Inputs: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2).
// 2022-02-04: Added SDL_Renderer* parameter to ImGui_ImplSDL2_InitForSDLRenderer(), so we can use SDL_GetRendererOutputSize() instead of SDL_GL_GetDrawableSize() when bound to a SDL_Renderer.
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
// 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[].
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
// 2022-01-17: Inputs: always update key mods next and before key event (not in NewFrame) to fix input queue with very low framerates.
// 2022-01-12: Update mouse inputs using SDL_MOUSEMOTION/SDL_WINDOWEVENT_LEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API.
// 2022-01-12: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted.
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
// 2021-08-17: Calling io.AddFocusEvent() on SDL_WINDOWEVENT_FOCUS_GAINED/SDL_WINDOWEVENT_FOCUS_LOST. // 2021-08-17: Calling io.AddFocusEvent() on SDL_WINDOWEVENT_FOCUS_GAINED/SDL_WINDOWEVENT_FOCUS_LOST.
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using SDL_GetMouseFocus() + SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, requires SDL 2.0.5+) // 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using SDL_GetMouseFocus() + SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, requires SDL 2.0.5+)
// 2021-06-29: *BREAKING CHANGE* Removed 'SDL_Window* window' parameter to ImGui_ImplSDL2_NewFrame() which was unnecessary. // 2021-06-29: *BREAKING CHANGE* Removed 'SDL_Window* window' parameter to ImGui_ImplSDL2_NewFrame() which was unnecessary.
@@ -60,7 +70,7 @@
#include <TargetConditionals.h> #include <TargetConditionals.h>
#endif #endif
#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) #if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) && !defined(__amigaos4__)
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 1 #define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 1
#else #else
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0 #define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0
@@ -71,14 +81,16 @@
// SDL Data // SDL Data
struct ImGui_ImplSDL2_Data struct ImGui_ImplSDL2_Data
{ {
SDL_Window* Window; SDL_Window* Window;
Uint64 Time; SDL_Renderer* Renderer;
bool MousePressed[3]; Uint64 Time;
SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; int MouseButtonsDown;
char* ClipboardTextData; SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
bool MouseCanUseGlobalState; int PendingMouseLeaveFrame;
char* ClipboardTextData;
bool MouseCanUseGlobalState;
ImGui_ImplSDL2_Data() { memset(this, 0, sizeof(*this)); } ImGui_ImplSDL2_Data() { memset((void*)this, 0, sizeof(*this)); }
}; };
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts // Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
@@ -105,9 +117,131 @@ static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text)
SDL_SetClipboardText(text); SDL_SetClipboardText(text);
} }
static ImGuiKey ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode)
{
switch (keycode)
{
case SDLK_TAB: return ImGuiKey_Tab;
case SDLK_LEFT: return ImGuiKey_LeftArrow;
case SDLK_RIGHT: return ImGuiKey_RightArrow;
case SDLK_UP: return ImGuiKey_UpArrow;
case SDLK_DOWN: return ImGuiKey_DownArrow;
case SDLK_PAGEUP: return ImGuiKey_PageUp;
case SDLK_PAGEDOWN: return ImGuiKey_PageDown;
case SDLK_HOME: return ImGuiKey_Home;
case SDLK_END: return ImGuiKey_End;
case SDLK_INSERT: return ImGuiKey_Insert;
case SDLK_DELETE: return ImGuiKey_Delete;
case SDLK_BACKSPACE: return ImGuiKey_Backspace;
case SDLK_SPACE: return ImGuiKey_Space;
case SDLK_RETURN: return ImGuiKey_Enter;
case SDLK_ESCAPE: return ImGuiKey_Escape;
case SDLK_QUOTE: return ImGuiKey_Apostrophe;
case SDLK_COMMA: return ImGuiKey_Comma;
case SDLK_MINUS: return ImGuiKey_Minus;
case SDLK_PERIOD: return ImGuiKey_Period;
case SDLK_SLASH: return ImGuiKey_Slash;
case SDLK_SEMICOLON: return ImGuiKey_Semicolon;
case SDLK_EQUALS: return ImGuiKey_Equal;
case SDLK_LEFTBRACKET: return ImGuiKey_LeftBracket;
case SDLK_BACKSLASH: return ImGuiKey_Backslash;
case SDLK_RIGHTBRACKET: return ImGuiKey_RightBracket;
case SDLK_BACKQUOTE: return ImGuiKey_GraveAccent;
case SDLK_CAPSLOCK: return ImGuiKey_CapsLock;
case SDLK_SCROLLLOCK: return ImGuiKey_ScrollLock;
case SDLK_NUMLOCKCLEAR: return ImGuiKey_NumLock;
case SDLK_PRINTSCREEN: return ImGuiKey_PrintScreen;
case SDLK_PAUSE: return ImGuiKey_Pause;
case SDLK_KP_0: return ImGuiKey_Keypad0;
case SDLK_KP_1: return ImGuiKey_Keypad1;
case SDLK_KP_2: return ImGuiKey_Keypad2;
case SDLK_KP_3: return ImGuiKey_Keypad3;
case SDLK_KP_4: return ImGuiKey_Keypad4;
case SDLK_KP_5: return ImGuiKey_Keypad5;
case SDLK_KP_6: return ImGuiKey_Keypad6;
case SDLK_KP_7: return ImGuiKey_Keypad7;
case SDLK_KP_8: return ImGuiKey_Keypad8;
case SDLK_KP_9: return ImGuiKey_Keypad9;
case SDLK_KP_PERIOD: return ImGuiKey_KeypadDecimal;
case SDLK_KP_DIVIDE: return ImGuiKey_KeypadDivide;
case SDLK_KP_MULTIPLY: return ImGuiKey_KeypadMultiply;
case SDLK_KP_MINUS: return ImGuiKey_KeypadSubtract;
case SDLK_KP_PLUS: return ImGuiKey_KeypadAdd;
case SDLK_KP_ENTER: return ImGuiKey_KeypadEnter;
case SDLK_KP_EQUALS: return ImGuiKey_KeypadEqual;
case SDLK_LCTRL: return ImGuiKey_LeftCtrl;
case SDLK_LSHIFT: return ImGuiKey_LeftShift;
case SDLK_LALT: return ImGuiKey_LeftAlt;
case SDLK_LGUI: return ImGuiKey_LeftSuper;
case SDLK_RCTRL: return ImGuiKey_RightCtrl;
case SDLK_RSHIFT: return ImGuiKey_RightShift;
case SDLK_RALT: return ImGuiKey_RightAlt;
case SDLK_RGUI: return ImGuiKey_RightSuper;
case SDLK_APPLICATION: return ImGuiKey_Menu;
case SDLK_0: return ImGuiKey_0;
case SDLK_1: return ImGuiKey_1;
case SDLK_2: return ImGuiKey_2;
case SDLK_3: return ImGuiKey_3;
case SDLK_4: return ImGuiKey_4;
case SDLK_5: return ImGuiKey_5;
case SDLK_6: return ImGuiKey_6;
case SDLK_7: return ImGuiKey_7;
case SDLK_8: return ImGuiKey_8;
case SDLK_9: return ImGuiKey_9;
case SDLK_a: return ImGuiKey_A;
case SDLK_b: return ImGuiKey_B;
case SDLK_c: return ImGuiKey_C;
case SDLK_d: return ImGuiKey_D;
case SDLK_e: return ImGuiKey_E;
case SDLK_f: return ImGuiKey_F;
case SDLK_g: return ImGuiKey_G;
case SDLK_h: return ImGuiKey_H;
case SDLK_i: return ImGuiKey_I;
case SDLK_j: return ImGuiKey_J;
case SDLK_k: return ImGuiKey_K;
case SDLK_l: return ImGuiKey_L;
case SDLK_m: return ImGuiKey_M;
case SDLK_n: return ImGuiKey_N;
case SDLK_o: return ImGuiKey_O;
case SDLK_p: return ImGuiKey_P;
case SDLK_q: return ImGuiKey_Q;
case SDLK_r: return ImGuiKey_R;
case SDLK_s: return ImGuiKey_S;
case SDLK_t: return ImGuiKey_T;
case SDLK_u: return ImGuiKey_U;
case SDLK_v: return ImGuiKey_V;
case SDLK_w: return ImGuiKey_W;
case SDLK_x: return ImGuiKey_X;
case SDLK_y: return ImGuiKey_Y;
case SDLK_z: return ImGuiKey_Z;
case SDLK_F1: return ImGuiKey_F1;
case SDLK_F2: return ImGuiKey_F2;
case SDLK_F3: return ImGuiKey_F3;
case SDLK_F4: return ImGuiKey_F4;
case SDLK_F5: return ImGuiKey_F5;
case SDLK_F6: return ImGuiKey_F6;
case SDLK_F7: return ImGuiKey_F7;
case SDLK_F8: return ImGuiKey_F8;
case SDLK_F9: return ImGuiKey_F9;
case SDLK_F10: return ImGuiKey_F10;
case SDLK_F11: return ImGuiKey_F11;
case SDLK_F12: return ImGuiKey_F12;
}
return ImGuiKey_None;
}
static void ImGui_ImplSDL2_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
{
ImGuiIO& io = ImGui::GetIO();
io.AddKeyEvent(ImGuiKey_ModCtrl, (sdl_key_mods & KMOD_CTRL) != 0);
io.AddKeyEvent(ImGuiKey_ModShift, (sdl_key_mods & KMOD_SHIFT) != 0);
io.AddKeyEvent(ImGuiKey_ModAlt, (sdl_key_mods & KMOD_ALT) != 0);
io.AddKeyEvent(ImGuiKey_ModSuper, (sdl_key_mods & KMOD_GUI) != 0);
}
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field. // If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
@@ -117,45 +251,60 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
switch (event->type) switch (event->type)
{ {
case SDL_MOUSEWHEEL: case SDL_MOUSEMOTION:
{ {
if (event->wheel.x > 0) io.MouseWheelH += 1; io.AddMousePosEvent((float)event->motion.x, (float)event->motion.y);
if (event->wheel.x < 0) io.MouseWheelH -= 1;
if (event->wheel.y > 0) io.MouseWheel += 1;
if (event->wheel.y < 0) io.MouseWheel -= 1;
return true; return true;
} }
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEWHEEL:
{ {
if (event->button.button == SDL_BUTTON_LEFT) { bd->MousePressed[0] = true; } float wheel_x = (event->wheel.x > 0) ? 1.0f : (event->wheel.x < 0) ? -1.0f : 0.0f;
if (event->button.button == SDL_BUTTON_RIGHT) { bd->MousePressed[1] = true; } float wheel_y = (event->wheel.y > 0) ? 1.0f : (event->wheel.y < 0) ? -1.0f : 0.0f;
if (event->button.button == SDL_BUTTON_MIDDLE) { bd->MousePressed[2] = true; } io.AddMouseWheelEvent(wheel_x, wheel_y);
return true; return true;
} }
case SDL_TEXTINPUT: case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
{
int mouse_button = -1;
if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; }
if (event->button.button == SDL_BUTTON_RIGHT) { mouse_button = 1; }
if (event->button.button == SDL_BUTTON_MIDDLE) { mouse_button = 2; }
if (event->button.button == SDL_BUTTON_X1) { mouse_button = 3; }
if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; }
if (mouse_button == -1)
break;
io.AddMouseButtonEvent(mouse_button, (event->type == SDL_MOUSEBUTTONDOWN));
bd->MouseButtonsDown = (event->type == SDL_MOUSEBUTTONDOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button));
return true;
}
case SDL_TEXTINPUT:
{ {
io.AddInputCharactersUTF8(event->text.text); io.AddInputCharactersUTF8(event->text.text);
return true; return true;
} }
case SDL_KEYDOWN: case SDL_KEYDOWN:
case SDL_KEYUP: case SDL_KEYUP:
{ {
int key = event->key.keysym.scancode; ImGui_ImplSDL2_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod);
IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown)); ImGuiKey key = ImGui_ImplSDL2_KeycodeToImGuiKey(event->key.keysym.sym);
io.KeysDown[key] = (event->type == SDL_KEYDOWN); io.AddKeyEvent(key, (event->type == SDL_KEYDOWN));
io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0); io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions.
io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
#ifdef _WIN32
io.KeySuper = false;
#else
io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
#endif
return true; return true;
} }
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
{ {
if (event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED) // - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right.
// - However we won't get a correct LEAVE event for a captured window.
// - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late,
// causing SDL_WINDOWEVENT_LEAVE on previous frame to interrupt drag operation by clear mouse position. This is why
// we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See issue #5012 for details.
Uint8 window_event = event->window.event;
if (window_event == SDL_WINDOWEVENT_ENTER)
bd->PendingMouseLeaveFrame = 0;
if (window_event == SDL_WINDOWEVENT_LEAVE)
bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1;
if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED)
io.AddFocusEvent(true); io.AddFocusEvent(true);
else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST)
io.AddFocusEvent(false); io.AddFocusEvent(false);
@@ -165,7 +314,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
return false; return false;
} }
static bool ImGui_ImplSDL2_Init(SDL_Window* window) static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!"); IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!");
@@ -189,32 +338,9 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window)
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
bd->Window = window; bd->Window = window;
bd->Renderer = renderer;
bd->MouseCanUseGlobalState = mouse_can_use_global_state; bd->MouseCanUseGlobalState = mouse_can_use_global_state;
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP;
io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN;
io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP;
io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT;
io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE;
io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE;
io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE;
io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN;
io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE;
io.KeyMap[ImGuiKey_KeyPadEnter] = SDL_SCANCODE_KP_ENTER;
io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A;
io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C;
io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V;
io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X;
io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y;
io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z;
io.SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText; io.SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText; io.GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText;
io.ClipboardUserData = NULL; io.ClipboardUserData = NULL;
@@ -230,11 +356,12 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window)
bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
// Set platform dependent data in viewport
#ifdef _WIN32 #ifdef _WIN32
SDL_SysWMinfo info; SDL_SysWMinfo info;
SDL_VERSION(&info.version); SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(window, &info)) if (SDL_GetWindowWMInfo(window, &info))
io.ImeWindowHandle = info.info.win.window; ImGui::GetMainViewport()->PlatformHandleRaw = (void*)info.info.win.window;
#else #else
(void)window; (void)window;
#endif #endif
@@ -254,7 +381,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window)
bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context) bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
{ {
IM_UNUSED(sdl_gl_context); // Viewport branch will need this. IM_UNUSED(sdl_gl_context); // Viewport branch will need this.
return ImGui_ImplSDL2_Init(window); return ImGui_ImplSDL2_Init(window, NULL);
} }
bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window) bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
@@ -262,7 +389,7 @@ bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
#if !SDL_HAS_VULKAN #if !SDL_HAS_VULKAN
IM_ASSERT(0 && "Unsupported"); IM_ASSERT(0 && "Unsupported");
#endif #endif
return ImGui_ImplSDL2_Init(window); return ImGui_ImplSDL2_Init(window, NULL);
} }
bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window) bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window)
@@ -270,17 +397,17 @@ bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window)
#if !defined(_WIN32) #if !defined(_WIN32)
IM_ASSERT(0 && "Unsupported"); IM_ASSERT(0 && "Unsupported");
#endif #endif
return ImGui_ImplSDL2_Init(window); return ImGui_ImplSDL2_Init(window, NULL);
} }
bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window) bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window)
{ {
return ImGui_ImplSDL2_Init(window); return ImGui_ImplSDL2_Init(window, NULL);
} }
bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window) bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer)
{ {
return ImGui_ImplSDL2_Init(window); return ImGui_ImplSDL2_Init(window, renderer);
} }
void ImGui_ImplSDL2_Shutdown() void ImGui_ImplSDL2_Shutdown()
@@ -299,60 +426,34 @@ void ImGui_ImplSDL2_Shutdown()
IM_DELETE(bd); IM_DELETE(bd);
} }
static void ImGui_ImplSDL2_UpdateMousePosAndButtons() static void ImGui_ImplSDL2_UpdateMouseData()
{ {
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
ImVec2 mouse_pos_prev = io.MousePos; // We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below)
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
// Update mouse buttons
int mouse_x_local, mouse_y_local;
Uint32 mouse_buttons = SDL_GetMouseState(&mouse_x_local, &mouse_y_local);
io.MouseDown[0] = bd->MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
io.MouseDown[1] = bd->MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
io.MouseDown[2] = bd->MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
bd->MousePressed[0] = bd->MousePressed[1] = bd->MousePressed[2] = false;
// Obtain focused and hovered window. We forward mouse input when focused or when hovered (and no other window is capturing)
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
SDL_Window* focused_window = SDL_GetKeyboardFocus();
SDL_Window* hovered_window = SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH ? SDL_GetMouseFocus() : NULL; // This is better but is only reliably useful with SDL 2.0.5+ and SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH.
SDL_Window* mouse_window = NULL;
if (hovered_window && bd->Window == hovered_window)
mouse_window = hovered_window;
else if (focused_window && bd->Window == focused_window)
mouse_window = focused_window;
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside
SDL_CaptureMouse(ImGui::IsAnyMouseDown() ? SDL_TRUE : SDL_FALSE); SDL_CaptureMouse(bd->MouseButtonsDown != 0 ? SDL_TRUE : SDL_FALSE);
SDL_Window* focused_window = SDL_GetKeyboardFocus();
const bool is_app_focused = (bd->Window == focused_window);
#else #else
// SDL 2.0.3 and non-windowed systems: single-viewport only const bool is_app_focused = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) != 0; // SDL 2.0.3 and non-windowed systems: single-viewport only
SDL_Window* mouse_window = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) ? bd->Window : NULL;
#endif #endif
if (is_app_focused)
if (mouse_window == NULL)
return;
// Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
if (io.WantSetMousePos)
SDL_WarpMouseInWindow(bd->Window, (int)mouse_pos_prev.x, (int)mouse_pos_prev.y);
// Set Dear ImGui mouse position from OS position + get buttons. (this is the common behavior)
if (bd->MouseCanUseGlobalState)
{ {
// Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window) // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
// Unlike local position obtained earlier this will be valid when straying out of bounds. if (io.WantSetMousePos)
int mouse_x_global, mouse_y_global; SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y);
SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
int window_x, window_y; // (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured)
SDL_GetWindowPosition(mouse_window, &window_x, &window_y); if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0)
io.MousePos = ImVec2((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y)); {
} int window_x, window_y, mouse_x_global, mouse_y_global;
else SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
{ SDL_GetWindowPosition(bd->Window, &window_x, &window_y);
io.MousePos = ImVec2((float)mouse_x_local, (float)mouse_y_local); io.AddMousePosEvent((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y));
}
} }
} }
@@ -380,40 +481,45 @@ static void ImGui_ImplSDL2_UpdateMouseCursor()
static void ImGui_ImplSDL2_UpdateGamepads() static void ImGui_ImplSDL2_UpdateGamepads()
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
memset(io.NavInputs, 0, sizeof(io.NavInputs));
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return; return;
// Get gamepad // Get gamepad
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
SDL_GameController* game_controller = SDL_GameControllerOpen(0); SDL_GameController* game_controller = SDL_GameControllerOpen(0);
if (!game_controller) if (!game_controller)
{
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
return; return;
} io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
// Update gamepad inputs // Update gamepad inputs
#define MAP_BUTTON(NAV_NO, BUTTON_NO) { io.NavInputs[NAV_NO] = (SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0) ? 1.0f : 0.0f; } #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
#define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; } #define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0); }
#define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); }
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value. const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
MAP_BUTTON(ImGuiNavInput_Activate, SDL_CONTROLLER_BUTTON_A); // Cross / A MAP_BUTTON(ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START);
MAP_BUTTON(ImGuiNavInput_Cancel, SDL_CONTROLLER_BUTTON_B); // Circle / B MAP_BUTTON(ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK);
MAP_BUTTON(ImGuiNavInput_Menu, SDL_CONTROLLER_BUTTON_X); // Square / X MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross
MAP_BUTTON(ImGuiNavInput_Input, SDL_CONTROLLER_BUTTON_Y); // Triangle / Y MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle
MAP_BUTTON(ImGuiNavInput_DpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); // D-Pad Left MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square
MAP_BUTTON(ImGuiNavInput_DpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); // D-Pad Right MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle
MAP_BUTTON(ImGuiNavInput_DpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); // D-Pad Up MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
MAP_BUTTON(ImGuiNavInput_DpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); // D-Pad Down MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
MAP_BUTTON(ImGuiNavInput_FocusPrev, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP);
MAP_BUTTON(ImGuiNavInput_FocusNext, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB MAP_BUTTON(ImGuiKey_GamepadDpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
MAP_BUTTON(ImGuiNavInput_TweakSlow, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB MAP_BUTTON(ImGuiKey_GamepadL1, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
MAP_BUTTON(ImGuiNavInput_TweakFast, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB MAP_BUTTON(ImGuiKey_GamepadR1, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
MAP_ANALOG(ImGuiNavInput_LStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768); MAP_ANALOG(ImGuiKey_GamepadL2, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 0.0f, 32767);
MAP_ANALOG(ImGuiNavInput_LStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767); MAP_ANALOG(ImGuiKey_GamepadR2, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 0.0f, 32767);
MAP_ANALOG(ImGuiNavInput_LStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32767); MAP_BUTTON(ImGuiKey_GamepadL3, SDL_CONTROLLER_BUTTON_LEFTSTICK);
MAP_ANALOG(ImGuiNavInput_LStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767); MAP_BUTTON(ImGuiKey_GamepadR3, SDL_CONTROLLER_BUTTON_RIGHTSTICK);
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
io.BackendFlags |= ImGuiBackendFlags_HasGamepad; MAP_ANALOG(ImGuiKey_GamepadLStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadLStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadRStickLeft, SDL_CONTROLLER_AXIS_RIGHTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadRStickRight, SDL_CONTROLLER_AXIS_RIGHTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadRStickUp, SDL_CONTROLLER_AXIS_RIGHTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadRStickDown, SDL_CONTROLLER_AXIS_RIGHTY, +thumb_dead_zone, +32767);
#undef MAP_BUTTON #undef MAP_BUTTON
#undef MAP_ANALOG #undef MAP_ANALOG
} }
@@ -430,7 +536,10 @@ void ImGui_ImplSDL2_NewFrame()
SDL_GetWindowSize(bd->Window, &w, &h); SDL_GetWindowSize(bd->Window, &w, &h);
if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_MINIMIZED) if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_MINIMIZED)
w = h = 0; w = h = 0;
SDL_GL_GetDrawableSize(bd->Window, &display_w, &display_h); if (bd->Renderer != NULL)
SDL_GetRendererOutputSize(bd->Renderer, &display_w, &display_h);
else
SDL_GL_GetDrawableSize(bd->Window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)w, (float)h); io.DisplaySize = ImVec2((float)w, (float)h);
if (w > 0 && h > 0) if (w > 0 && h > 0)
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
@@ -441,7 +550,13 @@ void ImGui_ImplSDL2_NewFrame()
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f); io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
bd->Time = current_time; bd->Time = current_time;
ImGui_ImplSDL2_UpdateMousePosAndButtons(); if (bd->PendingMouseLeaveFrame && bd->PendingMouseLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0)
{
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
bd->PendingMouseLeaveFrame = 0;
}
ImGui_ImplSDL2_UpdateMouseData();
ImGui_ImplSDL2_UpdateMouseCursor(); ImGui_ImplSDL2_UpdateMouseCursor();
// Update game controllers (if enabled and available) // Update game controllers (if enabled and available)
+4 -3
View File
@@ -3,10 +3,10 @@
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.) // (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
// Implemented features: // Implemented features:
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Clipboard support. // [X] Platform: Clipboard support.
// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE). // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// Missing features: // Missing features:
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. // [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
@@ -19,13 +19,14 @@
#include "imgui.h" // IMGUI_IMPL_API #include "imgui.h" // IMGUI_IMPL_API
struct SDL_Window; struct SDL_Window;
struct SDL_Renderer;
typedef union SDL_Event SDL_Event; typedef union SDL_Event SDL_Event;
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer);
IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown(); IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(); IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame();
IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event); IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
+4 -2
View File
@@ -42,7 +42,7 @@ struct ImGui_ImplSDLRenderer_Data
{ {
SDL_Renderer* SDLRenderer; SDL_Renderer* SDLRenderer;
SDL_Texture* FontTexture; SDL_Texture* FontTexture;
ImGui_ImplSDLRenderer_Data() { memset(this, 0, sizeof(*this)); } ImGui_ImplSDLRenderer_Data() { memset((void*)this, 0, sizeof(*this)); }
}; };
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
@@ -210,7 +210,8 @@ bool ImGui_ImplSDLRenderer_CreateFontsTexture()
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
// Upload texture to graphics system // Upload texture to graphics system
bd->FontTexture = SDL_CreateTexture(bd->SDLRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, width, height); // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
bd->FontTexture = SDL_CreateTexture(bd->SDLRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, width, height);
if (bd->FontTexture == NULL) if (bd->FontTexture == NULL)
{ {
SDL_Log("error creating texture"); SDL_Log("error creating texture");
@@ -218,6 +219,7 @@ bool ImGui_ImplSDLRenderer_CreateFontsTexture()
} }
SDL_UpdateTexture(bd->FontTexture, NULL, pixels, 4 * width); SDL_UpdateTexture(bd->FontTexture, NULL, pixels, 4 * width);
SDL_SetTextureBlendMode(bd->FontTexture, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(bd->FontTexture, SDL_BLENDMODE_BLEND);
SDL_SetTextureScaleMode(bd->FontTexture, SDL_ScaleModeLinear);
// Store our identifier // Store our identifier
io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture); io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture);
+244 -126
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.86 // dear imgui, v1.88
// (internal structures/api) // (internal structures/api)
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
@@ -18,6 +18,7 @@ Index of this file:
// [SECTION] Generic helpers // [SECTION] Generic helpers
// [SECTION] ImDrawList support // [SECTION] ImDrawList support
// [SECTION] Widgets support: flags, enums, data structures // [SECTION] Widgets support: flags, enums, data structures
// [SECTION] Inputs support
// [SECTION] Clipper support // [SECTION] Clipper support
// [SECTION] Navigation support // [SECTION] Navigation support
// [SECTION] Columns support // [SECTION] Columns support
@@ -135,6 +136,7 @@ struct ImGuiTabBar; // Storage for a tab bar
struct ImGuiTabItem; // Storage for a tab item (within a tab bar) struct ImGuiTabItem; // Storage for a tab item (within a tab bar)
struct ImGuiTable; // Storage for a table struct ImGuiTable; // Storage for a table
struct ImGuiTableColumn; // Storage for one column of a table struct ImGuiTableColumn; // Storage for one column of a table
struct ImGuiTableInstanceData; // Storage for one instance of a same table
struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables. struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables.
struct ImGuiTableSettings; // Storage for a table .ini settings struct ImGuiTableSettings; // Storage for a table .ini settings
struct ImGuiTableColumnsSettings; // Storage for a column .ini settings struct ImGuiTableColumnsSettings; // Storage for a column .ini settings
@@ -145,6 +147,7 @@ struct ImGuiWindowSettings; // Storage for a window .ini settings (we ke
// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists. // Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical
typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later) typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later)
typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag() typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag()
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags
typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns() typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns()
@@ -191,23 +194,26 @@ namespace ImStb
// [SECTION] Macros // [SECTION] Macros
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Debug Logging // Debug Printing Into TTY
#ifndef IMGUI_DEBUG_LOG // (since IMGUI_VERSION_NUM >= 18729: IMGUI_DEBUG_LOG was reworked into IMGUI_DEBUG_PRINTF (and removed framecount from it). If you were using a #define IMGUI_DEBUG_LOG please rename)
#define IMGUI_DEBUG_LOG(_FMT,...) printf("[%05d] " _FMT, GImGui->FrameCount, __VA_ARGS__) #ifndef IMGUI_DEBUG_PRINTF
#ifndef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
#define IMGUI_DEBUG_PRINTF(_FMT,...) printf(_FMT, __VA_ARGS__)
#else
#define IMGUI_DEBUG_PRINTF(_FMT,...)
#endif
#endif #endif
// Debug Logging for selected systems. Remove the '((void)0) //' to enable. // Debug Logging for ShowDebugLogWindow(). This is designed for relatively rare events so please don't spam.
//#define IMGUI_DEBUG_LOG_POPUP IMGUI_DEBUG_LOG // Enable log #define IMGUI_DEBUG_LOG(...) ImGui::DebugLog(__VA_ARGS__);
//#define IMGUI_DEBUG_LOG_NAV IMGUI_DEBUG_LOG // Enable log #define IMGUI_DEBUG_LOG_ACTIVEID(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventActiveId) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_POPUP(...) ((void)0) // Disable log #define IMGUI_DEBUG_LOG_FOCUS(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_NAV(...) ((void)0) // Disable log #define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_NAV(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventNav) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
// Static Asserts // Static Asserts
#if (__cplusplus >= 201100) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201100)
#define IM_STATIC_ASSERT(_COND) static_assert(_COND, "") #define IM_STATIC_ASSERT(_COND) static_assert(_COND, "")
#else
#define IM_STATIC_ASSERT(_COND) typedef char static_assertion_##__line__[(_COND)?1:-1]
#endif
// "Paranoid" Debug Asserts are meant to only be enabled during specific debugging/work, otherwise would slow down the code too much. // "Paranoid" Debug Asserts are meant to only be enabled during specific debugging/work, otherwise would slow down the code too much.
// We currently don't have many of those so the effect is currently negligible, but onward intent to add more aggressive ones in the code. // We currently don't have many of those so the effect is currently negligible, but onward intent to add more aggressive ones in the code.
@@ -232,7 +238,7 @@ namespace ImStb
#define IM_NEWLINE "\n" #define IM_NEWLINE "\n"
#endif #endif
#define IM_TABSIZE (4) #define IM_TABSIZE (4)
#define IM_MEMALIGN(_OFF,_ALIGN) (((_OFF) + (_ALIGN - 1)) & ~(_ALIGN - 1)) // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8 #define IM_MEMALIGN(_OFF,_ALIGN) (((_OFF) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8
#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose #define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose
#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 #define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
#define IM_FLOOR(_VAL) ((float)(int)(_VAL)) // ImFloor() is not inlined in MSVC debug builds #define IM_FLOOR(_VAL) ((float)(int)(_VAL)) // ImFloor() is not inlined in MSVC debug builds
@@ -279,7 +285,8 @@ namespace ImStb
// - Helpers: Hashing // - Helpers: Hashing
// - Helpers: Sorting // - Helpers: Sorting
// - Helpers: Bit manipulation // - Helpers: Bit manipulation
// - Helpers: String, Formatting // - Helpers: String
// - Helpers: Formatting
// - Helpers: UTF-8 <> wchar conversions // - Helpers: UTF-8 <> wchar conversions
// - Helpers: ImVec2/ImVec4 operators // - Helpers: ImVec2/ImVec4 operators
// - Helpers: Maths // - Helpers: Maths
@@ -297,9 +304,6 @@ namespace ImStb
// Helpers: Hashing // Helpers: Hashing
IMGUI_API ImGuiID ImHashData(const void* data, size_t data_size, ImU32 seed = 0); IMGUI_API ImGuiID ImHashData(const void* data, size_t data_size, ImU32 seed = 0);
IMGUI_API ImGuiID ImHashStr(const char* data, size_t data_size = 0, ImU32 seed = 0); IMGUI_API ImGuiID ImHashStr(const char* data, size_t data_size = 0, ImU32 seed = 0);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
static inline ImGuiID ImHash(const void* data, int size, ImU32 seed = 0) { return size ? ImHashData(data, (size_t)size, seed) : ImHashStr((const char*)data, 0, seed); } // [moved to ImHashStr/ImHashData in 1.68]
#endif
// Helpers: Sorting // Helpers: Sorting
#ifndef ImQsort #ifndef ImQsort
@@ -314,7 +318,7 @@ static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v &
static inline bool ImIsPowerOfTwo(ImU64 v) { return v != 0 && (v & (v - 1)) == 0; } static inline bool ImIsPowerOfTwo(ImU64 v) { return v != 0 && (v & (v - 1)) == 0; }
static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; }
// Helpers: String, Formatting // Helpers: String
IMGUI_API int ImStricmp(const char* str1, const char* str2); IMGUI_API int ImStricmp(const char* str1, const char* str2);
IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count); IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count);
IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count); IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count);
@@ -327,14 +331,20 @@ IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* bu
IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end); IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end);
IMGUI_API void ImStrTrimBlanks(char* str); IMGUI_API void ImStrTrimBlanks(char* str);
IMGUI_API const char* ImStrSkipBlank(const char* str); IMGUI_API const char* ImStrSkipBlank(const char* str);
static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; }
static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; }
// Helpers: Formatting
IMGUI_API int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) IM_FMTARGS(3); IMGUI_API int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) IM_FMTARGS(3);
IMGUI_API int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) IM_FMTLIST(3); IMGUI_API int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) IM_FMTLIST(3);
IMGUI_API void ImFormatStringToTempBuffer(const char** out_buf, const char** out_buf_end, const char* fmt, ...) IM_FMTARGS(3);
IMGUI_API void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end, const char* fmt, va_list args) IM_FMTLIST(3);
IMGUI_API const char* ImParseFormatFindStart(const char* format); IMGUI_API const char* ImParseFormatFindStart(const char* format);
IMGUI_API const char* ImParseFormatFindEnd(const char* format); IMGUI_API const char* ImParseFormatFindEnd(const char* format);
IMGUI_API const char* ImParseFormatTrimDecorations(const char* format, char* buf, size_t buf_size); IMGUI_API const char* ImParseFormatTrimDecorations(const char* format, char* buf, size_t buf_size);
IMGUI_API void ImParseFormatSanitizeForPrinting(const char* fmt_in, char* fmt_out, size_t fmt_out_size);
IMGUI_API const char* ImParseFormatSanitizeForScanning(const char* fmt_in, char* fmt_out, size_t fmt_out_size);
IMGUI_API int ImParseFormatPrecision(const char* format, int default_value); IMGUI_API int ImParseFormatPrecision(const char* format, int default_value);
static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; }
static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; }
// Helpers: UTF-8 <> wchar conversions // Helpers: UTF-8 <> wchar conversions
IMGUI_API const char* ImTextCharToUtf8(char out_buf[5], unsigned int c); // return out_buf IMGUI_API const char* ImTextCharToUtf8(char out_buf[5], unsigned int c); // return out_buf
@@ -441,8 +451,9 @@ static inline float ImLengthSqr(const ImVec2& lhs)
static inline float ImLengthSqr(const ImVec4& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y) + (lhs.z * lhs.z) + (lhs.w * lhs.w); } static inline float ImLengthSqr(const ImVec4& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y) + (lhs.z * lhs.z) + (lhs.w * lhs.w); }
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return ImRsqrt(d); return fail_value; } static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return ImRsqrt(d); return fail_value; }
static inline float ImFloor(float f) { return (float)(int)(f); } static inline float ImFloor(float f) { return (float)(int)(f); }
static inline float ImFloorSigned(float f) { return (float)((f >= 0 || (int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf() static inline float ImFloorSigned(float f) { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); } static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); }
static inline ImVec2 ImFloorSigned(const ImVec2& v) { return ImVec2(ImFloorSigned(v.x), ImFloorSigned(v.y)); }
static inline int ImModPositive(int a, int b) { return (a + b) % b; } static inline int ImModPositive(int a, int b) { return (a + b) % b; }
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
@@ -469,17 +480,17 @@ IM_MSVC_RUNTIME_CHECKS_OFF
struct ImVec1 struct ImVec1
{ {
float x; float x;
ImVec1() { x = 0.0f; } constexpr ImVec1() : x(0.0f) { }
ImVec1(float _x) { x = _x; } constexpr ImVec1(float _x) : x(_x) { }
}; };
// Helper: ImVec2ih (2D vector, half-size integer, for long-term packed storage) // Helper: ImVec2ih (2D vector, half-size integer, for long-term packed storage)
struct ImVec2ih struct ImVec2ih
{ {
short x, y; short x, y;
ImVec2ih() { x = y = 0; } constexpr ImVec2ih() : x(0), y(0) {}
ImVec2ih(short _x, short _y) { x = _x; y = _y; } constexpr ImVec2ih(short _x, short _y) : x(_x), y(_y) {}
explicit ImVec2ih(const ImVec2& rhs) { x = (short)rhs.x; y = (short)rhs.y; } constexpr explicit ImVec2ih(const ImVec2& rhs) : x((short)rhs.x), y((short)rhs.y) {}
}; };
// Helper: ImRect (2D axis aligned bounding-box) // Helper: ImRect (2D axis aligned bounding-box)
@@ -489,10 +500,10 @@ struct IMGUI_API ImRect
ImVec2 Min; // Upper-left ImVec2 Min; // Upper-left
ImVec2 Max; // Lower-right ImVec2 Max; // Lower-right
ImRect() : Min(0.0f, 0.0f), Max(0.0f, 0.0f) {} constexpr ImRect() : Min(0.0f, 0.0f), Max(0.0f, 0.0f) {}
ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {} constexpr ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {}
ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {} constexpr ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {}
ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {} constexpr ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {}
ImVec2 GetCenter() const { return ImVec2((Min.x + Max.x) * 0.5f, (Min.y + Max.y) * 0.5f); } ImVec2 GetCenter() const { return ImVec2((Min.x + Max.x) * 0.5f, (Min.y + Max.y) * 0.5f); }
ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); } ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); }
@@ -540,17 +551,18 @@ inline void ImBitArraySetBitRange(ImU32* arr, int n, int n2) // Works on ran
// Helper: ImBitArray class (wrapper over ImBitArray functions) // Helper: ImBitArray class (wrapper over ImBitArray functions)
// Store 1-bit per value. // Store 1-bit per value.
template<int BITCOUNT> template<int BITCOUNT, int OFFSET = 0>
struct IMGUI_API ImBitArray struct ImBitArray
{ {
ImU32 Storage[(BITCOUNT + 31) >> 5]; ImU32 Storage[(BITCOUNT + 31) >> 5];
ImBitArray() { ClearAllBits(); } ImBitArray() { ClearAllBits(); }
void ClearAllBits() { memset(Storage, 0, sizeof(Storage)); } void ClearAllBits() { memset(Storage, 0, sizeof(Storage)); }
void SetAllBits() { memset(Storage, 255, sizeof(Storage)); } void SetAllBits() { memset(Storage, 255, sizeof(Storage)); }
bool TestBit(int n) const { IM_ASSERT(n < BITCOUNT); return ImBitArrayTestBit(Storage, n); } bool TestBit(int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return ImBitArrayTestBit(Storage, n); }
void SetBit(int n) { IM_ASSERT(n < BITCOUNT); ImBitArraySetBit(Storage, n); } void SetBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArraySetBit(Storage, n); }
void ClearBit(int n) { IM_ASSERT(n < BITCOUNT); ImBitArrayClearBit(Storage, n); } void ClearBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArrayClearBit(Storage, n); }
void SetBitRange(int n, int n2) { ImBitArraySetBitRange(Storage, n, n2); } // Works on range [n..n2) void SetBitRange(int n, int n2) { n += OFFSET; n2 += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT && n2 > n && n2 <= BITCOUNT); ImBitArraySetBitRange(Storage, n, n2); } // Works on range [n..n2)
bool operator[](int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return ImBitArrayTestBit(Storage, n); }
}; };
// Helper: ImBitVector // Helper: ImBitVector
@@ -621,7 +633,7 @@ struct ImSpanAllocator
// Honor constructor/destructor. Add/remove invalidate all pointers. Indexes have the same lifetime as the associated object. // Honor constructor/destructor. Add/remove invalidate all pointers. Indexes have the same lifetime as the associated object.
typedef int ImPoolIdx; typedef int ImPoolIdx;
template<typename T> template<typename T>
struct IMGUI_API ImPool struct ImPool
{ {
ImVector<T> Buf; // Contiguous data ImVector<T> Buf; // Contiguous data
ImGuiStorage Map; // ID->Index ImGuiStorage Map; // ID->Index
@@ -658,7 +670,7 @@ struct IMGUI_API ImPool
// We store the chunk size first, and align the final size on 4 bytes boundaries. // We store the chunk size first, and align the final size on 4 bytes boundaries.
// The tedious/zealous amount of casting is to avoid -Wcast-align warnings. // The tedious/zealous amount of casting is to avoid -Wcast-align warnings.
template<typename T> template<typename T>
struct IMGUI_API ImChunkStream struct ImChunkStream
{ {
ImVector<char> Buf; ImVector<char> Buf;
@@ -690,7 +702,6 @@ struct IMGUI_API ImChunkStream
// //
// Rendering circles with an odd number of segments, while mathematically correct will produce // Rendering circles with an odd number of segments, while mathematically correct will produce
// asymmetrical results on the raster grid. Therefore we're rounding N to next even number (7->8, 8->8, 9->10 etc.) // asymmetrical results on the raster grid. Therefore we're rounding N to next even number (7->8, 8->8, 9->10 etc.)
//
#define IM_ROUNDUP_TO_EVEN(_V) ((((_V) + 1) / 2) * 2) #define IM_ROUNDUP_TO_EVEN(_V) ((((_V) + 1) / 2) * 2)
#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN 4 #define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN 4
#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX 512 #define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX 512
@@ -774,9 +785,9 @@ enum ImGuiItemStatusFlags_
#ifdef IMGUI_ENABLE_TEST_ENGINE #ifdef IMGUI_ENABLE_TEST_ENGINE
, // [imgui_tests only] , // [imgui_tests only]
ImGuiItemStatusFlags_Openable = 1 << 20, // ImGuiItemStatusFlags_Openable = 1 << 20, // Item is an openable (e.g. TreeNode)
ImGuiItemStatusFlags_Opened = 1 << 21, // ImGuiItemStatusFlags_Opened = 1 << 21, //
ImGuiItemStatusFlags_Checkable = 1 << 22, // ImGuiItemStatusFlags_Checkable = 1 << 22, // Item is a checkable (e.g. CheckBox, MenuItem)
ImGuiItemStatusFlags_Checked = 1 << 23 // ImGuiItemStatusFlags_Checked = 1 << 23 //
#endif #endif
}; };
@@ -897,28 +908,6 @@ enum ImGuiPlotType
ImGuiPlotType_Histogram ImGuiPlotType_Histogram
}; };
enum ImGuiInputSource
{
ImGuiInputSource_None = 0,
ImGuiInputSource_Mouse,
ImGuiInputSource_Keyboard,
ImGuiInputSource_Gamepad,
ImGuiInputSource_Nav, // Stored in g.ActiveIdSource only
ImGuiInputSource_Clipboard, // Currently only used by InputText()
ImGuiInputSource_COUNT
};
// FIXME-NAV: Clarify/expose various repeat delay/rate
enum ImGuiInputReadMode
{
ImGuiInputReadMode_Down,
ImGuiInputReadMode_Pressed,
ImGuiInputReadMode_Released,
ImGuiInputReadMode_Repeat,
ImGuiInputReadMode_RepeatSlow,
ImGuiInputReadMode_RepeatFast
};
enum ImGuiPopupPositionPolicy enum ImGuiPopupPositionPolicy
{ {
ImGuiPopupPositionPolicy_Default, ImGuiPopupPositionPolicy_Default,
@@ -951,8 +940,8 @@ enum ImGuiDataTypePrivate_
// Stacked color modifier, backup of modified data so we can restore it // Stacked color modifier, backup of modified data so we can restore it
struct ImGuiColorMod struct ImGuiColorMod
{ {
ImGuiCol Col; ImGuiCol Col;
ImVec4 BackupValue; ImVec4 BackupValue;
}; };
// Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable. // Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable.
@@ -1055,12 +1044,13 @@ struct ImGuiPopupData
ImGuiID PopupId; // Set on OpenPopup() ImGuiID PopupId; // Set on OpenPopup()
ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
ImGuiWindow* SourceWindow; // Set on OpenPopup() copy of NavWindow at the time of opening the popup ImGuiWindow* SourceWindow; // Set on OpenPopup() copy of NavWindow at the time of opening the popup
int ParentNavLayer; // Resolved on BeginPopup(). Actually a ImGuiNavLayer type (declared down below), initialized to -1 which is not part of an enum, but serves well-enough as "not any of layers" value
int OpenFrameCount; // Set on OpenPopup() int OpenFrameCount; // Set on OpenPopup()
ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items)
ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse) ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse)
ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup
ImGuiPopupData() { memset(this, 0, sizeof(*this)); OpenFrameCount = -1; } ImGuiPopupData() { memset(this, 0, sizeof(*this)); ParentNavLayer = OpenFrameCount = -1; }
}; };
enum ImGuiNextWindowDataFlags_ enum ImGuiNextWindowDataFlags_
@@ -1160,6 +1150,7 @@ struct ImGuiShrinkWidthItem
{ {
int Index; int Index;
float Width; float Width;
float InitialWidth;
}; };
struct ImGuiPtrOrIndex struct ImGuiPtrOrIndex
@@ -1171,6 +1162,81 @@ struct ImGuiPtrOrIndex
ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; } ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; }
}; };
//-----------------------------------------------------------------------------
// [SECTION] Inputs support
//-----------------------------------------------------------------------------
typedef ImBitArray<ImGuiKey_NamedKey_COUNT, -ImGuiKey_NamedKey_BEGIN> ImBitArrayForNamedKeys;
enum ImGuiKeyPrivate_
{
ImGuiKey_LegacyNativeKey_BEGIN = 0,
ImGuiKey_LegacyNativeKey_END = 512,
ImGuiKey_Gamepad_BEGIN = ImGuiKey_GamepadStart,
ImGuiKey_Gamepad_END = ImGuiKey_GamepadRStickRight + 1
};
enum ImGuiInputEventType
{
ImGuiInputEventType_None = 0,
ImGuiInputEventType_MousePos,
ImGuiInputEventType_MouseWheel,
ImGuiInputEventType_MouseButton,
ImGuiInputEventType_Key,
ImGuiInputEventType_Text,
ImGuiInputEventType_Focus,
ImGuiInputEventType_COUNT
};
enum ImGuiInputSource
{
ImGuiInputSource_None = 0,
ImGuiInputSource_Mouse,
ImGuiInputSource_Keyboard,
ImGuiInputSource_Gamepad,
ImGuiInputSource_Clipboard, // Currently only used by InputText()
ImGuiInputSource_Nav, // Stored in g.ActiveIdSource only
ImGuiInputSource_COUNT
};
// FIXME: Structures in the union below need to be declared as anonymous unions appears to be an extension?
// Using ImVec2() would fail on Clang 'union member 'MousePos' has a non-trivial default constructor'
struct ImGuiInputEventMousePos { float PosX, PosY; };
struct ImGuiInputEventMouseWheel { float WheelX, WheelY; };
struct ImGuiInputEventMouseButton { int Button; bool Down; };
struct ImGuiInputEventKey { ImGuiKey Key; bool Down; float AnalogValue; };
struct ImGuiInputEventText { unsigned int Char; };
struct ImGuiInputEventAppFocused { bool Focused; };
struct ImGuiInputEvent
{
ImGuiInputEventType Type;
ImGuiInputSource Source;
union
{
ImGuiInputEventMousePos MousePos; // if Type == ImGuiInputEventType_MousePos
ImGuiInputEventMouseWheel MouseWheel; // if Type == ImGuiInputEventType_MouseWheel
ImGuiInputEventMouseButton MouseButton; // if Type == ImGuiInputEventType_MouseButton
ImGuiInputEventKey Key; // if Type == ImGuiInputEventType_Key
ImGuiInputEventText Text; // if Type == ImGuiInputEventType_Text
ImGuiInputEventAppFocused AppFocused; // if Type == ImGuiInputEventType_Focus
};
bool AddedByTestEngine;
ImGuiInputEvent() { memset(this, 0, sizeof(*this)); }
};
// FIXME-NAV: Clarify/expose various repeat delay/rate
enum ImGuiNavReadMode
{
ImGuiNavReadMode_Down,
ImGuiNavReadMode_Pressed,
ImGuiNavReadMode_Released,
ImGuiNavReadMode_Repeat,
ImGuiNavReadMode_RepeatSlow,
ImGuiNavReadMode_RepeatFast
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Clipper support // [SECTION] Clipper support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -1239,7 +1305,7 @@ enum ImGuiNavHighlightFlags_
enum ImGuiNavDirSourceFlags_ enum ImGuiNavDirSourceFlags_
{ {
ImGuiNavDirSourceFlags_None = 0, ImGuiNavDirSourceFlags_None = 0,
ImGuiNavDirSourceFlags_RawKeyboard = 1 << 0, // Raw keyboard (not pulled from nav), faciliate use of some functions before we can unify nav and keys ImGuiNavDirSourceFlags_RawKeyboard = 1 << 0, // Raw keyboard (not pulled from nav), facilitate use of some functions before we can unify nav and keys
ImGuiNavDirSourceFlags_Keyboard = 1 << 1, ImGuiNavDirSourceFlags_Keyboard = 1 << 1,
ImGuiNavDirSourceFlags_PadDPad = 1 << 2, ImGuiNavDirSourceFlags_PadDPad = 1 << 2,
ImGuiNavDirSourceFlags_PadLStick = 1 << 3 ImGuiNavDirSourceFlags_PadLStick = 1 << 3
@@ -1427,8 +1493,22 @@ struct ImGuiSettingsHandler
// [SECTION] Metrics, Debug Tools // [SECTION] Metrics, Debug Tools
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
enum ImGuiDebugLogFlags_
{
// Event types
ImGuiDebugLogFlags_None = 0,
ImGuiDebugLogFlags_EventActiveId = 1 << 0,
ImGuiDebugLogFlags_EventFocus = 1 << 1,
ImGuiDebugLogFlags_EventPopup = 1 << 2,
ImGuiDebugLogFlags_EventNav = 1 << 3,
ImGuiDebugLogFlags_EventIO = 1 << 4,
ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventIO,
ImGuiDebugLogFlags_OutputToTTY = 1 << 10 // Also send output to TTY
};
struct ImGuiMetricsConfig struct ImGuiMetricsConfig
{ {
bool ShowDebugLog;
bool ShowStackTool; bool ShowStackTool;
bool ShowWindowsRects; bool ShowWindowsRects;
bool ShowWindowsBeginOrder; bool ShowWindowsBeginOrder;
@@ -1440,14 +1520,10 @@ struct ImGuiMetricsConfig
ImGuiMetricsConfig() ImGuiMetricsConfig()
{ {
ShowStackTool = false; ShowDebugLog = ShowStackTool = ShowWindowsRects = ShowWindowsBeginOrder = ShowTablesRects = false;
ShowWindowsRects = false;
ShowWindowsBeginOrder = false;
ShowTablesRects = false;
ShowDrawCmdMesh = true; ShowDrawCmdMesh = true;
ShowDrawCmdBoundingBoxes = true; ShowDrawCmdBoundingBoxes = true;
ShowWindowsRectsType = -1; ShowWindowsRectsType = ShowTablesRectsType = -1;
ShowTablesRectsType = -1;
} }
}; };
@@ -1456,7 +1532,8 @@ struct ImGuiStackLevelInfo
ImGuiID ID; ImGuiID ID;
ImS8 QueryFrameCount; // >= 1: Query in progress ImS8 QueryFrameCount; // >= 1: Query in progress
bool QuerySuccess; // Obtained result from DebugHookIdInfo() bool QuerySuccess; // Obtained result from DebugHookIdInfo()
char Desc[58]; // Arbitrarily sized buffer to hold a result (FIXME: could replace Results[] with a chunk stream?) ImGuiDataType DataType : 8;
char Desc[57]; // Arbitrarily sized buffer to hold a result (FIXME: could replace Results[] with a chunk stream?) FIXME: Now that we added CTRL+C this should be fixed.
ImGuiStackLevelInfo() { memset(this, 0, sizeof(*this)); } ImGuiStackLevelInfo() { memset(this, 0, sizeof(*this)); }
}; };
@@ -1468,8 +1545,10 @@ struct ImGuiStackTool
int StackLevel; // -1: query stack and resize Results, >= 0: individual stack level int StackLevel; // -1: query stack and resize Results, >= 0: individual stack level
ImGuiID QueryId; // ID to query details for ImGuiID QueryId; // ID to query details for
ImVector<ImGuiStackLevelInfo> Results; ImVector<ImGuiStackLevelInfo> Results;
bool CopyToClipboardOnCtrlC;
float CopyToClipboardLastTime;
ImGuiStackTool() { memset(this, 0, sizeof(*this)); } ImGuiStackTool() { memset(this, 0, sizeof(*this)); CopyToClipboardLastTime = -FLT_MAX; }
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -1491,7 +1570,7 @@ struct ImGuiContextHook
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] ImGuiContext (main imgui context) // [SECTION] ImGuiContext (main Dear ImGui context)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
struct ImGuiContext struct ImGuiContext
@@ -1499,6 +1578,8 @@ struct ImGuiContext
bool Initialized; bool Initialized;
bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it. bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
ImGuiIO IO; ImGuiIO IO;
ImVector<ImGuiInputEvent> InputEventsQueue; // Input events which will be tricked/written into IO structure.
ImVector<ImGuiInputEvent> InputEventsTrail; // Past input events processed in NewFrame(). This is to allow domain-specific application to access e.g mouse/pen trail.
ImGuiStyle Style; ImGuiStyle Style;
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
@@ -1550,10 +1631,6 @@ struct ImGuiContext
bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch. bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch.
bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state. bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state.
bool ActiveIdHasBeenEditedThisFrame; bool ActiveIdHasBeenEditedThisFrame;
bool ActiveIdUsingMouseWheel; // Active widget will want to read mouse wheel. Blocks scrolling the underlying window.
ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it)
ImU32 ActiveIdUsingNavInputMask; // Active widget will want to read those nav inputs.
ImU64 ActiveIdUsingKeyInputMask; // Active widget will want to read those key inputs. When we grow the ImGuiKey enum we'll need to either to order the enum to make useful keys come first, either redesign this into e.g. a small array.
ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)
ImGuiWindow* ActiveIdWindow; ImGuiWindow* ActiveIdWindow;
ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard) ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard)
@@ -1565,6 +1642,12 @@ struct ImGuiContext
ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation. ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
// Input Ownership
bool ActiveIdUsingMouseWheel; // Active widget will want to read mouse wheel. Blocks scrolling the underlying window.
ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it)
ImU32 ActiveIdUsingNavInputMask; // Active widget will want to read those nav inputs.
ImBitArrayForNamedKeys ActiveIdUsingKeyInputMask; // Active widget will want to read those key inputs. When we grow the ImGuiKey enum we'll need to either to order the enum to make useful keys come first, either redesign this into e.g. a small array.
// Next window/item data // Next window/item data
ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back() ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back()
ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions
@@ -1586,7 +1669,7 @@ struct ImGuiContext
ImVector<ImGuiViewportP*> Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData. ImVector<ImGuiViewportP*> Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData.
// Gamepad/keyboard Navigation // Gamepad/keyboard Navigation
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow' ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
ImGuiID NavId; // Focused item for navigation ImGuiID NavId; // Focused item for navigation
ImGuiID NavFocusScopeId; // Identify a selection scope (selection code often wants to "clear other items" when landing on an item of the selection set) ImGuiID NavFocusScopeId; // Identify a selection scope (selection code often wants to "clear other items" when landing on an item of the selection set)
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0, also set when calling ActivateItem() ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0, also set when calling ActivateItem()
@@ -1596,7 +1679,7 @@ struct ImGuiContext
ImGuiActivateFlags NavActivateFlags; ImGuiActivateFlags NavActivateFlags;
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest). ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest). ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
ImGuiKeyModFlags NavJustMovedToKeyMods; ImGuiModFlags NavJustMovedToKeyMods;
ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame. ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame.
ImGuiActivateFlags NavNextActivateFlags; ImGuiActivateFlags NavNextActivateFlags;
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard. ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard.
@@ -1617,7 +1700,7 @@ struct ImGuiContext
bool NavMoveForwardToNextFrame; bool NavMoveForwardToNextFrame;
ImGuiNavMoveFlags NavMoveFlags; ImGuiNavMoveFlags NavMoveFlags;
ImGuiScrollFlags NavMoveScrollFlags; ImGuiScrollFlags NavMoveScrollFlags;
ImGuiKeyModFlags NavMoveKeyMods; ImGuiModFlags NavMoveKeyMods;
ImGuiDir NavMoveDir; // Direction of the move request (left/right/up/down) ImGuiDir NavMoveDir; // Direction of the move request (left/right/up/down)
ImGuiDir NavMoveDirForDebug; ImGuiDir NavMoveDirForDebug;
ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename? ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename?
@@ -1666,7 +1749,7 @@ struct ImGuiContext
int ClipperTempDataStacked; int ClipperTempDataStacked;
ImVector<ImGuiListClipperData> ClipperTempData; ImVector<ImGuiListClipperData> ClipperTempData;
// Table // Tables
ImGuiTable* CurrentTable; ImGuiTable* CurrentTable;
int TablesTempDataStacked; // Temporary table data size (because we leave previous instances undestructed, we generally don't use TablesTempData.Size) int TablesTempDataStacked; // Temporary table data size (because we leave previous instances undestructed, we generally don't use TablesTempData.Size)
ImVector<ImGuiTableTempData> TablesTempData; // Temporary table data (buffers reused/shared across instances, support nesting) ImVector<ImGuiTableTempData> TablesTempData; // Temporary table data (buffers reused/shared across instances, support nesting)
@@ -1691,6 +1774,7 @@ struct ImGuiContext
ImU32 ColorEditLastColor; // RGB value with alpha set to 0. ImU32 ColorEditLastColor; // RGB value with alpha set to 0.
ImVec4 ColorPickerRef; // Initial/reference color at the time of opening the color picker. ImVec4 ColorPickerRef; // Initial/reference color at the time of opening the color picker.
ImGuiComboPreviewData ComboPreviewData; ImGuiComboPreviewData ComboPreviewData;
float SliderGrabClickOffset;
float SliderCurrentAccum; // Accumulated slider delta when using navigation controls. float SliderCurrentAccum; // Accumulated slider delta when using navigation controls.
bool SliderCurrentAccumDirty; // Has the accumulated slider delta changed since last time we tried to apply it? bool SliderCurrentAccumDirty; // Has the accumulated slider delta changed since last time we tried to apply it?
bool DragCurrentAccumDirty; bool DragCurrentAccumDirty;
@@ -1705,8 +1789,8 @@ struct ImGuiContext
ImVector<ImGuiID> MenusIdSubmittedThisFrame; // A list of menu IDs that were rendered at least once ImVector<ImGuiID> MenusIdSubmittedThisFrame; // A list of menu IDs that were rendered at least once
// Platform support // Platform support
ImVec2 PlatformImePos; // Cursor position request & last passed to the OS Input Method Editor ImGuiPlatformImeData PlatformImeData; // Data updated by current frame
ImVec2 PlatformImeLastPos; ImGuiPlatformImeData PlatformImeDataPrev; // Previous frame data (when changing we will call io.SetPlatformImeDataFn
char PlatformLocaleDecimalPoint; // '.' or *localeconv()->decimal_point char PlatformLocaleDecimalPoint; // '.' or *localeconv()->decimal_point
// Settings // Settings
@@ -1733,6 +1817,8 @@ struct ImGuiContext
int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call. int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call.
// Debug Tools // Debug Tools
ImGuiDebugLogFlags DebugLogFlags;
ImGuiTextBuffer DebugLogBuf;
bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker()) bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker())
ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this ID ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this ID
ImGuiMetricsConfig DebugMetricsConfig; ImGuiMetricsConfig DebugMetricsConfig;
@@ -1743,10 +1829,10 @@ struct ImGuiContext
int FramerateSecPerFrameIdx; int FramerateSecPerFrameIdx;
int FramerateSecPerFrameCount; int FramerateSecPerFrameCount;
float FramerateSecPerFrameAccum; float FramerateSecPerFrameAccum;
int WantCaptureMouseNextFrame; // Explicit capture via CaptureKeyboardFromApp()/CaptureMouseFromApp() sets those flags int WantCaptureMouseNextFrame; // Explicit capture override via SetNextFrameWantCaptureMouse()/SetNextFrameWantCaptureKeyboard(). Default to -1.
int WantCaptureKeyboardNextFrame; int WantCaptureKeyboardNextFrame; // "
int WantTextInputNextFrame; int WantTextInputNextFrame;
char TempBuffer[1024 * 3 + 1]; // Temporary text buffer ImVector<char> TempBuffer; // Temporary text buffer
ImGuiContext(ImFontAtlas* shared_font_atlas) ImGuiContext(ImFontAtlas* shared_font_atlas)
{ {
@@ -1786,10 +1872,6 @@ struct ImGuiContext
ActiveIdHasBeenPressedBefore = false; ActiveIdHasBeenPressedBefore = false;
ActiveIdHasBeenEditedBefore = false; ActiveIdHasBeenEditedBefore = false;
ActiveIdHasBeenEditedThisFrame = false; ActiveIdHasBeenEditedThisFrame = false;
ActiveIdUsingMouseWheel = false;
ActiveIdUsingNavDirMask = 0x00;
ActiveIdUsingNavInputMask = 0x00;
ActiveIdUsingKeyInputMask = 0x00;
ActiveIdClickOffset = ImVec2(-1, -1); ActiveIdClickOffset = ImVec2(-1, -1);
ActiveIdWindow = NULL; ActiveIdWindow = NULL;
ActiveIdSource = ImGuiInputSource_None; ActiveIdSource = ImGuiInputSource_None;
@@ -1801,6 +1883,11 @@ struct ImGuiContext
LastActiveId = 0; LastActiveId = 0;
LastActiveIdTimer = 0.0f; LastActiveIdTimer = 0.0f;
ActiveIdUsingMouseWheel = false;
ActiveIdUsingNavDirMask = 0x00;
ActiveIdUsingNavInputMask = 0x00;
ActiveIdUsingKeyInputMask.ClearAllBits();
CurrentItemFlags = ImGuiItemFlags_None; CurrentItemFlags = ImGuiItemFlags_None;
BeginMenuCount = 0; BeginMenuCount = 0;
@@ -1808,7 +1895,7 @@ struct ImGuiContext
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0; NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0;
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0; NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None; NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavJustMovedToKeyMods = ImGuiKeyModFlags_None; NavJustMovedToKeyMods = ImGuiModFlags_None;
NavInputSource = ImGuiInputSource_None; NavInputSource = ImGuiInputSource_None;
NavLayer = ImGuiNavLayer_Main; NavLayer = ImGuiNavLayer_Main;
NavIdIsAlive = false; NavIdIsAlive = false;
@@ -1824,7 +1911,7 @@ struct ImGuiContext
NavMoveForwardToNextFrame = false; NavMoveForwardToNextFrame = false;
NavMoveFlags = ImGuiNavMoveFlags_None; NavMoveFlags = ImGuiNavMoveFlags_None;
NavMoveScrollFlags = ImGuiScrollFlags_None; NavMoveScrollFlags = ImGuiScrollFlags_None;
NavMoveKeyMods = ImGuiKeyModFlags_None; NavMoveKeyMods = ImGuiModFlags_None;
NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None; NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None;
NavScoringDebugCount = 0; NavScoringDebugCount = 0;
NavTabbingDir = 0; NavTabbingDir = 0;
@@ -1859,6 +1946,7 @@ struct ImGuiContext
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_; ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
ColorEditLastHue = ColorEditLastSat = 0.0f; ColorEditLastHue = ColorEditLastSat = 0.0f;
ColorEditLastColor = 0; ColorEditLastColor = 0;
SliderGrabClickOffset = 0.0f;
SliderCurrentAccum = 0.0f; SliderCurrentAccum = 0.0f;
SliderCurrentAccumDirty = false; SliderCurrentAccumDirty = false;
DragCurrentAccumDirty = false; DragCurrentAccumDirty = false;
@@ -1870,7 +1958,8 @@ struct ImGuiContext
TooltipOverrideCount = 0; TooltipOverrideCount = 0;
TooltipSlowDelay = 0.50f; TooltipSlowDelay = 0.50f;
PlatformImePos = PlatformImeLastPos = ImVec2(FLT_MAX, FLT_MAX); PlatformImeData.InputPos = ImVec2(0.0f, 0.0f);
PlatformImeDataPrev.InputPos = ImVec2(-1.0f, -1.0f); // Different to ensure initial submission
PlatformLocaleDecimalPoint = '.'; PlatformLocaleDecimalPoint = '.';
SettingsLoaded = false; SettingsLoaded = false;
@@ -1886,6 +1975,7 @@ struct ImGuiContext
LogDepthRef = 0; LogDepthRef = 0;
LogDepthToExpand = LogDepthToExpandDefault = 2; LogDepthToExpand = LogDepthToExpandDefault = 2;
DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY;
DebugItemPickerActive = false; DebugItemPickerActive = false;
DebugItemPickerBreakId = 0; DebugItemPickerBreakId = 0;
@@ -1893,7 +1983,6 @@ struct ImGuiContext
FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0; FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0;
FramerateSecPerFrameAccum = 0.0f; FramerateSecPerFrameAccum = 0.0f;
WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1; WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
memset(TempBuffer, 0, sizeof(TempBuffer));
} }
}; };
@@ -1916,6 +2005,7 @@ struct IMGUI_API ImGuiWindowTempData
ImVec2 PrevLineSize; ImVec2 PrevLineSize;
float CurrLineTextBaseOffset; // Baseline offset (0.0f by default on a new line, generally == style.FramePadding.y when a framed item has been added). float CurrLineTextBaseOffset; // Baseline offset (0.0f by default on a new line, generally == style.FramePadding.y when a framed item has been added).
float PrevLineTextBaseOffset; float PrevLineTextBaseOffset;
bool IsSameLine;
ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
ImVec1 GroupOffset; ImVec1 GroupOffset;
@@ -1956,6 +2046,7 @@ struct IMGUI_API ImGuiWindow
char* Name; // Window name, owned by the window. char* Name; // Window name, owned by the window.
ImGuiID ID; // == ImHashStr(Name) ImGuiID ID; // == ImHashStr(Name)
ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_ ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_
ImGuiViewportP* Viewport; // Always set in Begin(). Inactive windows may have a NULL value here if their viewport was discarded.
ImVec2 Pos; // Position (always rounded-up to nearest pixel) ImVec2 Pos; // Position (always rounded-up to nearest pixel)
ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) ImVec2 Size; // Current size (==SizeFull or collapsed title bar size)
ImVec2 SizeFull; // Size when non collapsed ImVec2 SizeFull; // Size when non collapsed
@@ -2053,9 +2144,6 @@ public:
ImGuiID GetID(const char* str, const char* str_end = NULL); ImGuiID GetID(const char* str, const char* str_end = NULL);
ImGuiID GetID(const void* ptr); ImGuiID GetID(const void* ptr);
ImGuiID GetID(int n); ImGuiID GetID(int n);
ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL);
ImGuiID GetIDNoKeepAlive(const void* ptr);
ImGuiID GetIDNoKeepAlive(int n);
ImGuiID GetIDFromRectangle(const ImRect& r_abs); ImGuiID GetIDFromRectangle(const ImRect& r_abs);
// We don't use g.FontSize because the window may be != g.CurrentWidow. // We don't use g.FontSize because the window may be != g.CurrentWidow.
@@ -2097,6 +2185,7 @@ struct ImGuiTabItem
float Offset; // Position relative to beginning of tab float Offset; // Position relative to beginning of tab
float Width; // Width currently displayed float Width; // Width currently displayed
float ContentWidth; // Width of label, stored during BeginTabItem() call float ContentWidth; // Width of label, stored during BeginTabItem() call
float RequestedWidth; // Width optionally requested by caller, -1.0f is unused
ImS32 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames ImS32 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames
ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable
ImS16 IndexDuringLayout; // Index only used during TabBarLayout() ImS16 IndexDuringLayout; // Index only used during TabBarLayout()
@@ -2230,6 +2319,15 @@ struct ImGuiTableCellData
ImGuiTableColumnIdx Column; // Column number ImGuiTableColumnIdx Column; // Column number
}; };
// Per-instance data that needs preserving across frames (seemingly most others do not need to be preserved aside from debug needs, does that needs they could be moved to ImGuiTableTempData ?)
struct ImGuiTableInstanceData
{
float LastOuterHeight; // Outer height from last frame // FIXME: multi-instance issue (#3955)
float LastFirstRowHeight; // Height of first row from last frame // FIXME: possible multi-instance issue?
ImGuiTableInstanceData() { LastOuterHeight = LastFirstRowHeight = 0.0f; }
};
// FIXME-TABLE: more transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData // FIXME-TABLE: more transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData
struct IMGUI_API ImGuiTable struct IMGUI_API ImGuiTable
{ {
@@ -2272,11 +2370,10 @@ struct IMGUI_API ImGuiTable
float CellPaddingY; float CellPaddingY;
float CellSpacingX1; // Spacing between non-bordered cells float CellSpacingX1; // Spacing between non-bordered cells
float CellSpacingX2; float CellSpacingX2;
float LastOuterHeight; // Outer height from last frame
float LastFirstRowHeight; // Height of first row from last frame
float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details. float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details.
float ColumnsGivenWidth; // Sum of current column width float ColumnsGivenWidth; // Sum of current column width
float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window
float ColumnsStretchSumWeights; // Sum of weight of all enabled stretching columns
float ResizedColumnNextWidth; float ResizedColumnNextWidth;
float ResizeLockMinContentsX2; // Lock minimum contents width while resizing down in order to not create feedback loops. But we allow growing the table. float ResizeLockMinContentsX2; // Lock minimum contents width while resizing down in order to not create feedback loops. But we allow growing the table.
float RefScale; // Reference scale to be able to rescale columns on font/dpi changes. float RefScale; // Reference scale to be able to rescale columns on font/dpi changes.
@@ -2284,7 +2381,7 @@ struct IMGUI_API ImGuiTable
ImRect InnerRect; // InnerRect but without decoration. As with OuterRect, for non-scrolling tables, InnerRect.Max.y is ImRect InnerRect; // InnerRect but without decoration. As with OuterRect, for non-scrolling tables, InnerRect.Max.y is
ImRect WorkRect; ImRect WorkRect;
ImRect InnerClipRect; ImRect InnerClipRect;
ImRect BgClipRect; // We use this to cpu-clip cell background color fill ImRect BgClipRect; // We use this to cpu-clip cell background color fill, evolve during the frame as we cross frozen rows boundaries
ImRect Bg0ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG0/1 channel. This tends to be == OuterWindow->ClipRect at BeginTable() because output in BG0/BG1 is cpu-clipped ImRect Bg0ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG0/1 channel. This tends to be == OuterWindow->ClipRect at BeginTable() because output in BG0/BG1 is cpu-clipped
ImRect Bg2ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG2 channel. This tends to be a correct, tight-fit, because output to BG2 are done by widgets relying on regular ClipRect. ImRect Bg2ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG2 channel. This tends to be a correct, tight-fit, because output to BG2 are done by widgets relying on regular ClipRect.
ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window. ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window.
@@ -2293,6 +2390,8 @@ struct IMGUI_API ImGuiTable
ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window) ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window)
ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names
ImDrawListSplitter* DrawSplitter; // Shortcut to TempData->DrawSplitter while in table. Isolate draw commands per columns to avoid switching clip rect constantly ImDrawListSplitter* DrawSplitter; // Shortcut to TempData->DrawSplitter while in table. Isolate draw commands per columns to avoid switching clip rect constantly
ImGuiTableInstanceData InstanceDataFirst;
ImVector<ImGuiTableInstanceData> InstanceDataExtra; // FIXME-OPT: Using a small-vector pattern would be good.
ImGuiTableColumnSortSpecs SortSpecsSingle; ImGuiTableColumnSortSpecs SortSpecsSingle;
ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good. ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good.
ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs() ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs()
@@ -2449,10 +2548,11 @@ namespace ImGui
IMGUI_API ImDrawList* GetForegroundDrawList(ImGuiViewport* viewport); // get foreground draw list for the given viewport. this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents. IMGUI_API ImDrawList* GetForegroundDrawList(ImGuiViewport* viewport); // get foreground draw list for the given viewport. this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents.
// Init // Init
IMGUI_API void Initialize(ImGuiContext* context); IMGUI_API void Initialize();
IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext(). IMGUI_API void Shutdown(); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext().
// NewFrame // NewFrame
IMGUI_API void UpdateInputEvents(bool trickle_fast_inputs);
IMGUI_API void UpdateHoveredWindowAndCaptureFlags(); IMGUI_API void UpdateHoveredWindowAndCaptureFlags();
IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window); IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
IMGUI_API void UpdateMouseMovingWindowNewFrame(); IMGUI_API void UpdateMouseMovingWindowNewFrame();
@@ -2463,6 +2563,9 @@ namespace ImGui
IMGUI_API void RemoveContextHook(ImGuiContext* context, ImGuiID hook_to_remove); IMGUI_API void RemoveContextHook(ImGuiContext* context, ImGuiID hook_to_remove);
IMGUI_API void CallContextHooks(ImGuiContext* context, ImGuiContextHookType type); IMGUI_API void CallContextHooks(ImGuiContext* context, ImGuiContextHookType type);
// Viewports
IMGUI_API void SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport);
// Settings // Settings
IMGUI_API void MarkIniSettingsDirty(); IMGUI_API void MarkIniSettingsDirty();
IMGUI_API void MarkIniSettingsDirty(ImGuiWindow* window); IMGUI_API void MarkIniSettingsDirty(ImGuiWindow* window);
@@ -2470,6 +2573,8 @@ namespace ImGui
IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(const char* name); IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(const char* name);
IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id); IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id);
IMGUI_API ImGuiWindowSettings* FindOrCreateWindowSettings(const char* name); IMGUI_API ImGuiWindowSettings* FindOrCreateWindowSettings(const char* name);
IMGUI_API void AddSettingsHandler(const ImGuiSettingsHandler* handler);
IMGUI_API void RemoveSettingsHandler(const char* type_name);
IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name);
// Scrolling // Scrolling
@@ -2505,7 +2610,7 @@ namespace ImGui
// Basic Helpers for widget code // Basic Helpers for widget code
IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f); IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f);
IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f); inline void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f) { ItemSize(bb.GetSize(), text_baseline_y); } // FIXME: This is a misleading API since we expect CursorPos to be bb.Min.
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemFlags extra_flags = 0); IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemFlags extra_flags = 0);
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id); IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id); IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id);
@@ -2573,10 +2678,12 @@ namespace ImGui
IMGUI_API void NavMoveRequestCancel(); IMGUI_API void NavMoveRequestCancel();
IMGUI_API void NavMoveRequestApplyResult(); IMGUI_API void NavMoveRequestApplyResult();
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode); IMGUI_API const char* GetNavInputName(ImGuiNavInput n);
IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiNavReadMode mode);
IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiNavReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f);
IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate); IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate);
IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again.
IMGUI_API void SetNavWindow(ImGuiWindow* window);
IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel); IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
// Focus Scope (WIP) // Focus Scope (WIP)
@@ -2589,18 +2696,26 @@ namespace ImGui
// Inputs // Inputs
// FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
inline bool IsNamedKey(ImGuiKey key) { return key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END; }
inline bool IsLegacyKey(ImGuiKey key) { return key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_LegacyNativeKey_END; }
inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; }
IMGUI_API ImGuiKeyData* GetKeyData(ImGuiKey key);
IMGUI_API void SetItemUsingMouseWheel(); IMGUI_API void SetItemUsingMouseWheel();
IMGUI_API void SetActiveIdUsingNavAndKeys(); IMGUI_API void SetActiveIdUsingNavAndKeys();
inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; } inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; }
inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; } inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; }
inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(key < 64); return (g.ActiveIdUsingKeyInputMask & ((ImU64)1 << key)) != 0; } inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; return g.ActiveIdUsingKeyInputMask[key]; }
inline void SetActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; g.ActiveIdUsingKeyInputMask.SetBit(key); }
IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f); IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f);
inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { ImGuiContext& g = *GImGui; const int key_index = g.IO.KeyMap[key]; return (key_index >= 0) ? IsKeyPressed(key_index, repeat) : false; }
inline bool IsNavInputDown(ImGuiNavInput n) { ImGuiContext& g = *GImGui; return g.IO.NavInputs[n] > 0.0f; } inline bool IsNavInputDown(ImGuiNavInput n) { ImGuiContext& g = *GImGui; return g.IO.NavInputs[n] > 0.0f; }
inline bool IsNavInputTest(ImGuiNavInput n, ImGuiInputReadMode rm) { return (GetNavInputAmount(n, rm) > 0.0f); } inline bool IsNavInputTest(ImGuiNavInput n, ImGuiNavReadMode rm) { return (GetNavInputAmount(n, rm) > 0.0f); }
IMGUI_API ImGuiKeyModFlags GetMergedKeyModFlags(); IMGUI_API ImGuiModFlags GetMergedModFlags();
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // [removed in 1.87]
#endif
// Drag and Drop // Drag and Drop
IMGUI_API bool IsDragDropActive();
IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id); IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id);
IMGUI_API void ClearDragDrop(); IMGUI_API void ClearDragDrop();
IMGUI_API bool IsDragDropPayloadBeingAccepted(); IMGUI_API bool IsDragDropPayloadBeingAccepted();
@@ -2639,6 +2754,7 @@ namespace ImGui
IMGUI_API void TableDrawBorders(ImGuiTable* table); IMGUI_API void TableDrawBorders(ImGuiTable* table);
IMGUI_API void TableDrawContextMenu(ImGuiTable* table); IMGUI_API void TableDrawContextMenu(ImGuiTable* table);
IMGUI_API void TableMergeDrawChannels(ImGuiTable* table); IMGUI_API void TableMergeDrawChannels(ImGuiTable* table);
inline ImGuiTableInstanceData* TableGetInstanceData(ImGuiTable* table, int instance_no) { if (instance_no == 0) return &table->InstanceDataFirst; return &table->InstanceDataExtra[instance_no - 1]; }
IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table); IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table);
IMGUI_API void TableSortSpecsBuild(ImGuiTable* table); IMGUI_API void TableSortSpecsBuild(ImGuiTable* table);
IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column); IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column);
@@ -2664,7 +2780,7 @@ namespace ImGui
IMGUI_API void TableSaveSettings(ImGuiTable* table); IMGUI_API void TableSaveSettings(ImGuiTable* table);
IMGUI_API void TableResetSettings(ImGuiTable* table); IMGUI_API void TableResetSettings(ImGuiTable* table);
IMGUI_API ImGuiTableSettings* TableGetBoundSettings(ImGuiTable* table); IMGUI_API ImGuiTableSettings* TableGetBoundSettings(ImGuiTable* table);
IMGUI_API void TableSettingsInstallHandler(ImGuiContext* context); IMGUI_API void TableSettingsAddSettingsHandler();
IMGUI_API ImGuiTableSettings* TableSettingsCreate(ImGuiID id, int columns_count); IMGUI_API ImGuiTableSettings* TableSettingsCreate(ImGuiID id, int columns_count);
IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id); IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id);
@@ -2694,21 +2810,15 @@ namespace ImGui
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0); IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_TypeDefault); // Navigation highlight IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_TypeDefault); // Navigation highlight
IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text.
IMGUI_API void RenderMouseCursor(ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow);
// Render helpers (those functions don't access any ImGui state!) // Render helpers (those functions don't access any ImGui state!)
IMGUI_API void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale = 1.0f); IMGUI_API void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale = 1.0f);
IMGUI_API void RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col); IMGUI_API void RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col);
IMGUI_API void RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz); IMGUI_API void RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz);
IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow);
IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col); IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col);
IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding);
IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect inner, ImU32 col, float rounding); IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// [1.71: 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while]
inline void RenderArrow(ImVec2 pos, ImGuiDir dir, float scale=1.0f) { ImGuiWindow* window = GetCurrentWindow(); RenderArrow(window->DrawList, pos, GetColorU32(ImGuiCol_Text), dir, scale); }
inline void RenderBullet(ImVec2 pos) { ImGuiWindow* window = GetCurrentWindow(); RenderBullet(window->DrawList, pos, GetColorU32(ImGuiCol_Text)); }
#endif
// Widgets // Widgets
IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0); IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0);
@@ -2743,14 +2853,14 @@ namespace ImGui
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API T ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size); template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API T ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size);
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, T v_min, T v_max, const char* format, ImGuiSliderFlags flags); template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, T v_min, T v_max, const char* format, ImGuiSliderFlags flags);
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, T v_min, T v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb); template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, T v_min, T v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb);
template<typename T, typename SIGNED_T> IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v); template<typename T> IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v);
template<typename T> IMGUI_API bool CheckboxFlagsT(const char* label, T* flags, T flags_value); template<typename T> IMGUI_API bool CheckboxFlagsT(const char* label, T* flags, T flags_value);
// Data type helpers // Data type helpers
IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type); IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type);
IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format); IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format);
IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg_1, const void* arg_2); IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg_1, const void* arg_2);
IMGUI_API bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format); IMGUI_API bool DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format);
IMGUI_API int DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2); IMGUI_API int DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2);
IMGUI_API bool DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max); IMGUI_API bool DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max);
@@ -2778,22 +2888,27 @@ namespace ImGui
IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window); IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window);
IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window); IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window);
// Debug Log
IMGUI_API void DebugLog(const char* fmt, ...) IM_FMTARGS(1);
IMGUI_API void DebugLogV(const char* fmt, va_list args) IM_FMTLIST(1);
// Debug Tools // Debug Tools
IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
IMGUI_API void ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, col); } inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, col); }
inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; }
IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas);
IMGUI_API void DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end); IMGUI_API void DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end);
IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns); IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns);
IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label); IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label);
IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb); IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);
IMGUI_API void DebugNodeFont(ImFont* font); IMGUI_API void DebugNodeFont(ImFont* font);
IMGUI_API void DebugNodeFontGlyph(ImFont* font, const ImFontGlyph* glyph);
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label); IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label); IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label);
IMGUI_API void DebugNodeTable(ImGuiTable* table); IMGUI_API void DebugNodeTable(ImGuiTable* table);
IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings); IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings);
IMGUI_API void DebugNodeInputTextState(ImGuiInputTextState* state);
IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label); IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label);
IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings); IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings);
IMGUI_API void DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label); IMGUI_API void DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label);
@@ -2815,7 +2930,9 @@ struct ImFontBuilderIO
}; };
// Helper for font builder // Helper for font builder
#ifdef IMGUI_ENABLE_STB_TRUETYPE
IMGUI_API const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype(); IMGUI_API const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype();
#endif
IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas);
IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent); IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent);
IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque); IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque);
@@ -2839,7 +2956,8 @@ extern const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx, ImGuiI
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional) #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional)
#define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log #define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log
#else #else
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)0) #define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) ((void)0)
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)g)
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
+49 -30
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.86 // dear imgui, v1.88
// (tables and columns code) // (tables and columns code)
/* /*
@@ -24,7 +24,7 @@ Index of this file:
*/ */
// Navigating this file: // Navigating this file:
// - In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. // - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -361,6 +361,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->IsLayoutLocked = false; table->IsLayoutLocked = false;
table->InnerWidth = inner_width; table->InnerWidth = inner_width;
temp_data->UserOuterSize = outer_size; temp_data->UserOuterSize = outer_size;
if (instance_no > 0 && table->InstanceDataExtra.Size < instance_no)
table->InstanceDataExtra.push_back(ImGuiTableInstanceData());
// When not using a child window, WorkRect.Max will grow as we append contents. // When not using a child window, WorkRect.Max will grow as we append contents.
if (use_child_window) if (use_child_window)
@@ -537,7 +539,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
if (table->RefScale != 0.0f && table->RefScale != new_ref_scale_unit) if (table->RefScale != 0.0f && table->RefScale != new_ref_scale_unit)
{ {
const float scale_factor = new_ref_scale_unit / table->RefScale; const float scale_factor = new_ref_scale_unit / table->RefScale;
//IMGUI_DEBUG_LOG("[table] %08X RefScaleUnit %.3f -> %.3f, scaling width by %.3f\n", table->ID, table->RefScaleUnit, new_ref_scale_unit, scale_factor); //IMGUI_DEBUG_PRINT("[table] %08X RefScaleUnit %.3f -> %.3f, scaling width by %.3f\n", table->ID, table->RefScaleUnit, new_ref_scale_unit, scale_factor);
for (int n = 0; n < columns_count; n++) for (int n = 0; n < columns_count; n++)
table->Columns[n].WidthRequest = table->Columns[n].WidthRequest * scale_factor; table->Columns[n].WidthRequest = table->Columns[n].WidthRequest * scale_factor;
} }
@@ -886,6 +888,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
sum_width_requests += table->CellPaddingX * 2.0f; sum_width_requests += table->CellPaddingX * 2.0f;
} }
table->ColumnsEnabledFixedCount = (ImGuiTableColumnIdx)count_fixed; table->ColumnsEnabledFixedCount = (ImGuiTableColumnIdx)count_fixed;
table->ColumnsStretchSumWeights = stretch_sum_weights;
// [Part 4] Apply final widths based on requested widths // [Part 4] Apply final widths based on requested widths
const ImRect work_rect = table->WorkRect; const ImRect work_rect = table->WorkRect;
@@ -933,9 +936,10 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
width_remaining_for_stretched_columns -= 1.0f; width_remaining_for_stretched_columns -= 1.0f;
} }
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
table->HoveredColumnBody = -1; table->HoveredColumnBody = -1;
table->HoveredColumnBorder = -1; table->HoveredColumnBorder = -1;
const ImRect mouse_hit_rect(table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.Max.x, ImMax(table->OuterRect.Max.y, table->OuterRect.Min.y + table->LastOuterHeight)); const ImRect mouse_hit_rect(table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.Max.x, ImMax(table->OuterRect.Max.y, table->OuterRect.Min.y + table_instance->LastOuterHeight));
const bool is_hovering_table = ItemHoverable(mouse_hit_rect, 0); const bool is_hovering_table = ItemHoverable(mouse_hit_rect, 0);
// [Part 6] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column // [Part 6] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column
@@ -1096,7 +1100,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// [Part 10] Hit testing on borders // [Part 10] Hit testing on borders
if (table->Flags & ImGuiTableFlags_Resizable) if (table->Flags & ImGuiTableFlags_Resizable)
TableUpdateBorders(table); TableUpdateBorders(table);
table->LastFirstRowHeight = 0.0f; table_instance->LastFirstRowHeight = 0.0f;
table->IsLayoutLocked = true; table->IsLayoutLocked = true;
table->IsUsingHeaders = false; table->IsUsingHeaders = false;
@@ -1141,10 +1145,11 @@ void ImGui::TableUpdateBorders(ImGuiTable* table)
// use the final height from last frame. Because this is only affecting _interaction_ with columns, it is not // use the final height from last frame. Because this is only affecting _interaction_ with columns, it is not
// really problematic (whereas the actual visual will be displayed in EndTable() and using the current frame height). // really problematic (whereas the actual visual will be displayed in EndTable() and using the current frame height).
// Actual columns highlight/render will be performed in EndTable() and not be affected. // Actual columns highlight/render will be performed in EndTable() and not be affected.
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
const float hit_half_width = TABLE_RESIZE_SEPARATOR_HALF_THICKNESS; const float hit_half_width = TABLE_RESIZE_SEPARATOR_HALF_THICKNESS;
const float hit_y1 = table->OuterRect.Min.y; const float hit_y1 = table->OuterRect.Min.y;
const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table->LastOuterHeight); const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table_instance->LastOuterHeight);
const float hit_y2_head = hit_y1 + table->LastFirstRowHeight; const float hit_y2_head = hit_y1 + table_instance->LastFirstRowHeight;
for (int order_n = 0; order_n < table->ColumnsCount; order_n++) for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
{ {
@@ -1223,6 +1228,7 @@ void ImGui::EndTable()
TableOpenContextMenu((int)table->HoveredColumnBody); TableOpenContextMenu((int)table->HoveredColumnBody);
// Finalize table height // Finalize table height
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
inner_window->DC.PrevLineSize = temp_data->HostBackupPrevLineSize; inner_window->DC.PrevLineSize = temp_data->HostBackupPrevLineSize;
inner_window->DC.CurrLineSize = temp_data->HostBackupCurrLineSize; inner_window->DC.CurrLineSize = temp_data->HostBackupCurrLineSize;
inner_window->DC.CursorMaxPos = temp_data->HostBackupCursorMaxPos; inner_window->DC.CursorMaxPos = temp_data->HostBackupCursorMaxPos;
@@ -1233,7 +1239,7 @@ void ImGui::EndTable()
else if (!(flags & ImGuiTableFlags_NoHostExtendY)) else if (!(flags & ImGuiTableFlags_NoHostExtendY))
table->OuterRect.Max.y = table->InnerRect.Max.y = ImMax(table->OuterRect.Max.y, inner_content_max_y); // Patch OuterRect/InnerRect height table->OuterRect.Max.y = table->InnerRect.Max.y = ImMax(table->OuterRect.Max.y, inner_content_max_y); // Patch OuterRect/InnerRect height
table->WorkRect.Max.y = ImMax(table->WorkRect.Max.y, table->OuterRect.Max.y); table->WorkRect.Max.y = ImMax(table->WorkRect.Max.y, table->OuterRect.Max.y);
table->LastOuterHeight = table->OuterRect.GetHeight(); table_instance->LastOuterHeight = table->OuterRect.GetHeight();
// Setup inner scrolling range // Setup inner scrolling range
// FIXME: This ideally should be done earlier, in BeginTable() SetNextWindowContentSize call, just like writing to inner_window->DC.CursorMaxPos.y, // FIXME: This ideally should be done earlier, in BeginTable() SetNextWindowContentSize call, just like writing to inner_window->DC.CursorMaxPos.y,
@@ -1279,17 +1285,23 @@ void ImGui::EndTable()
splitter->Merge(inner_window->DrawList); splitter->Merge(inner_window->DrawList);
// Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable() // Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable()
const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1); float auto_fit_width_for_fixed = 0.0f;
table->ColumnsAutoFitWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount; float auto_fit_width_for_stretched = 0.0f;
float auto_fit_width_for_stretched_min = 0.0f;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
if (table->EnabledMaskByIndex & ((ImU64)1 << column_n)) if (table->EnabledMaskByIndex & ((ImU64)1 << column_n))
{ {
ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiTableColumn* column = &table->Columns[column_n];
if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !(column->Flags & ImGuiTableColumnFlags_NoResize)) float column_width_request = ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !(column->Flags & ImGuiTableColumnFlags_NoResize)) ? column->WidthRequest : TableGetColumnWidthAuto(table, column);
table->ColumnsAutoFitWidth += column->WidthRequest; if (column->Flags & ImGuiTableColumnFlags_WidthFixed)
auto_fit_width_for_fixed += column_width_request;
else else
table->ColumnsAutoFitWidth += TableGetColumnWidthAuto(table, column); auto_fit_width_for_stretched += column_width_request;
if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) && (column->Flags & ImGuiTableColumnFlags_NoResize) != 0)
auto_fit_width_for_stretched_min = ImMax(auto_fit_width_for_stretched_min, column_width_request / (column->StretchWeight / table->ColumnsStretchSumWeights));
} }
const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1);
table->ColumnsAutoFitWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount + auto_fit_width_for_fixed + ImMax(auto_fit_width_for_stretched, auto_fit_width_for_stretched_min);
// Update scroll // Update scroll
if ((table->Flags & ImGuiTableFlags_ScrollX) == 0 && inner_window != outer_window) if ((table->Flags & ImGuiTableFlags_ScrollX) == 0 && inner_window != outer_window)
@@ -1569,18 +1581,21 @@ ImGuiTableColumnFlags ImGui::TableGetColumnFlags(int column_n)
// Return the cell rectangle based on currently known height. // Return the cell rectangle based on currently known height.
// - Important: we generally don't know our row height until the end of the row, so Max.y will be incorrect in many situations. // - Important: we generally don't know our row height until the end of the row, so Max.y will be incorrect in many situations.
// The only case where this is correct is if we provided a min_row_height to TableNextRow() and don't go below it. // The only case where this is correct is if we provided a min_row_height to TableNextRow() and don't go below it, or in TableEndRow() when we locked that height.
// - Important: if ImGuiTableFlags_PadOuterX is set but ImGuiTableFlags_PadInnerX is not set, the outer-most left and right // - Important: if ImGuiTableFlags_PadOuterX is set but ImGuiTableFlags_PadInnerX is not set, the outer-most left and right
// columns report a small offset so their CellBgRect can extend up to the outer border. // columns report a small offset so their CellBgRect can extend up to the outer border.
// FIXME: But the rendering code in TableEndRow() nullifies that with clamping required for scrolling.
ImRect ImGui::TableGetCellBgRect(const ImGuiTable* table, int column_n) ImRect ImGui::TableGetCellBgRect(const ImGuiTable* table, int column_n)
{ {
const ImGuiTableColumn* column = &table->Columns[column_n]; const ImGuiTableColumn* column = &table->Columns[column_n];
float x1 = column->MinX; float x1 = column->MinX;
float x2 = column->MaxX; float x2 = column->MaxX;
if (column->PrevEnabledColumn == -1) //if (column->PrevEnabledColumn == -1)
x1 -= table->CellSpacingX1; // x1 -= table->OuterPaddingX;
if (column->NextEnabledColumn == -1) //if (column->NextEnabledColumn == -1)
x2 += table->CellSpacingX2; // x2 += table->OuterPaddingX;
x1 = ImMax(x1, table->WorkRect.Min.x);
x2 = ImMin(x2, table->WorkRect.Max.x);
return ImRect(x1, table->RowPosY1, x2, table->RowPosY2); return ImRect(x1, table->RowPosY1, x2, table->RowPosY2);
} }
@@ -1746,7 +1761,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
const bool unfreeze_rows_actual = (table->CurrentRow + 1 == table->FreezeRowsCount); const bool unfreeze_rows_actual = (table->CurrentRow + 1 == table->FreezeRowsCount);
const bool unfreeze_rows_request = (table->CurrentRow + 1 == table->FreezeRowsRequest); const bool unfreeze_rows_request = (table->CurrentRow + 1 == table->FreezeRowsRequest);
if (table->CurrentRow == 0) if (table->CurrentRow == 0)
table->LastFirstRowHeight = bg_y2 - bg_y1; TableGetInstanceData(table, table->InstanceCurrent)->LastFirstRowHeight = bg_y2 - bg_y1;
const bool is_visible = (bg_y2 >= table->InnerClipRect.Min.y && bg_y1 <= table->InnerClipRect.Max.y); const bool is_visible = (bg_y2 >= table->InnerClipRect.Min.y && bg_y1 <= table->InnerClipRect.Max.y);
if (is_visible) if (is_visible)
@@ -1797,10 +1812,12 @@ void ImGui::TableEndRow(ImGuiTable* table)
ImGuiTableCellData* cell_data_end = &table->RowCellData[table->RowCellDataCurrent]; ImGuiTableCellData* cell_data_end = &table->RowCellData[table->RowCellDataCurrent];
for (ImGuiTableCellData* cell_data = &table->RowCellData[0]; cell_data <= cell_data_end; cell_data++) for (ImGuiTableCellData* cell_data = &table->RowCellData[0]; cell_data <= cell_data_end; cell_data++)
{ {
// As we render the BG here we need to clip things (for layout we would not)
// FIXME: This cancels the OuterPadding addition done by TableGetCellBgRect(), need to keep it while rendering correctly while scrolling.
const ImGuiTableColumn* column = &table->Columns[cell_data->Column]; const ImGuiTableColumn* column = &table->Columns[cell_data->Column];
ImRect cell_bg_rect = TableGetCellBgRect(table, cell_data->Column); ImRect cell_bg_rect = TableGetCellBgRect(table, cell_data->Column);
cell_bg_rect.ClipWith(table->BgClipRect); cell_bg_rect.ClipWith(table->BgClipRect);
cell_bg_rect.Min.x = ImMax(cell_bg_rect.Min.x, column->ClipRect.Min.x); // So that first column after frozen one gets clipped cell_bg_rect.Min.x = ImMax(cell_bg_rect.Min.x, column->ClipRect.Min.x); // So that first column after frozen one gets clipped when scrolling
cell_bg_rect.Max.x = ImMin(cell_bg_rect.Max.x, column->MaxX); cell_bg_rect.Max.x = ImMin(cell_bg_rect.Max.x, column->MaxX);
window->DrawList->AddRectFilled(cell_bg_rect.Min, cell_bg_rect.Max, cell_data->BgColor); window->DrawList->AddRectFilled(cell_bg_rect.Min, cell_bg_rect.Max, cell_data->BgColor);
} }
@@ -2083,7 +2100,7 @@ void ImGui::TableSetColumnWidth(int column_n, float width)
if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width) if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width)
return; return;
//IMGUI_DEBUG_LOG("TableSetColumnWidth(%d, %.1f->%.1f)\n", column_0_idx, column_0->WidthGiven, column_0_width); //IMGUI_DEBUG_PRINT("TableSetColumnWidth(%d, %.1f->%.1f)\n", column_0_idx, column_0->WidthGiven, column_0_width);
ImGuiTableColumn* column_1 = (column_0->NextEnabledColumn != -1) ? &table->Columns[column_0->NextEnabledColumn] : NULL; ImGuiTableColumn* column_1 = (column_0->NextEnabledColumn != -1) ? &table->Columns[column_0->NextEnabledColumn] : NULL;
// In this surprisingly not simple because of how we support mixing Fixed and multiple Stretch columns. // In this surprisingly not simple because of how we support mixing Fixed and multiple Stretch columns.
@@ -2353,7 +2370,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
// Don't attempt to merge if there are multiple draw calls within the column // Don't attempt to merge if there are multiple draw calls within the column
ImDrawChannel* src_channel = &splitter->_Channels[channel_no]; ImDrawChannel* src_channel = &splitter->_Channels[channel_no];
if (src_channel->_CmdBuffer.Size > 0 && src_channel->_CmdBuffer.back().ElemCount == 0) if (src_channel->_CmdBuffer.Size > 0 && src_channel->_CmdBuffer.back().ElemCount == 0 && src_channel->_CmdBuffer.back().UserCallback == NULL) // Equivalent of PopUnusedDrawCmd()
src_channel->_CmdBuffer.pop_back(); src_channel->_CmdBuffer.pop_back();
if (src_channel->_CmdBuffer.Size != 1) if (src_channel->_CmdBuffer.Size != 1)
continue; continue;
@@ -2497,10 +2514,11 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false); inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false);
// Draw inner border and resizing feedback // Draw inner border and resizing feedback
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
const float border_size = TABLE_BORDER_SIZE; const float border_size = TABLE_BORDER_SIZE;
const float draw_y1 = table->InnerRect.Min.y; const float draw_y1 = table->InnerRect.Min.y;
const float draw_y2_body = table->InnerRect.Max.y; const float draw_y2_body = table->InnerRect.Max.y;
const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table->LastFirstRowHeight) : draw_y1; const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table_instance->LastFirstRowHeight) : draw_y1;
if (table->Flags & ImGuiTableFlags_BordersInnerV) if (table->Flags & ImGuiTableFlags_BordersInnerV)
{ {
for (int order_n = 0; order_n < table->ColumnsCount; order_n++) for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
@@ -3422,9 +3440,8 @@ static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandle
} }
} }
void ImGui::TableSettingsInstallHandler(ImGuiContext* context) void ImGui::TableSettingsAddSettingsHandler()
{ {
ImGuiContext& g = *context;
ImGuiSettingsHandler ini_handler; ImGuiSettingsHandler ini_handler;
ini_handler.TypeName = "Table"; ini_handler.TypeName = "Table";
ini_handler.TypeHash = ImHashStr("Table"); ini_handler.TypeHash = ImHashStr("Table");
@@ -3433,7 +3450,7 @@ void ImGui::TableSettingsInstallHandler(ImGuiContext* context)
ini_handler.ReadLineFn = TableSettingsHandler_ReadLine; ini_handler.ReadLineFn = TableSettingsHandler_ReadLine;
ini_handler.ApplyAllFn = TableSettingsHandler_ApplyAll; ini_handler.ApplyAllFn = TableSettingsHandler_ApplyAll;
ini_handler.WriteAllFn = TableSettingsHandler_WriteAll; ini_handler.WriteAllFn = TableSettingsHandler_WriteAll;
g.SettingsHandlers.push_back(ini_handler); AddSettingsHandler(&ini_handler);
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@@ -3447,7 +3464,7 @@ void ImGui::TableSettingsInstallHandler(ImGuiContext* context)
// Remove Table (currently only used by TestEngine) // Remove Table (currently only used by TestEngine)
void ImGui::TableRemove(ImGuiTable* table) void ImGui::TableRemove(ImGuiTable* table)
{ {
//IMGUI_DEBUG_LOG("TableRemove() id=0x%08X\n", table->ID); //IMGUI_DEBUG_PRINT("TableRemove() id=0x%08X\n", table->ID);
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
int table_idx = g.Tables.GetIndex(table); int table_idx = g.Tables.GetIndex(table);
//memset(table->RawData.Data, 0, table->RawData.size_in_bytes()); //memset(table->RawData.Data, 0, table->RawData.size_in_bytes());
@@ -3459,7 +3476,7 @@ void ImGui::TableRemove(ImGuiTable* table)
// Free up/compact internal Table buffers for when it gets unused // Free up/compact internal Table buffers for when it gets unused
void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table) void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table)
{ {
//IMGUI_DEBUG_LOG("TableGcCompactTransientBuffers() id=0x%08X\n", table->ID); //IMGUI_DEBUG_PRINT("TableGcCompactTransientBuffers() id=0x%08X\n", table->ID);
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(table->MemoryCompacted == false); IM_ASSERT(table->MemoryCompacted == false);
table->SortSpecs.Specs = NULL; table->SortSpecs.Specs = NULL;
@@ -3503,7 +3520,7 @@ void ImGui::TableGcCompactSettings()
// - DebugNodeTable() [Internal] // - DebugNodeTable() [Internal]
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
#ifndef IMGUI_DISABLE_METRICS_WINDOW #ifndef IMGUI_DISABLE_DEBUG_TOOLS
static const char* DebugNodeTableGetSizingPolicyDesc(ImGuiTableFlags sizing_policy) static const char* DebugNodeTableGetSizingPolicyDesc(ImGuiTableFlags sizing_policy)
{ {
@@ -3531,6 +3548,8 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
GetForegroundDrawList()->AddRect(GetItemRectMin(), GetItemRectMax(), IM_COL32(255, 255, 0, 255)); GetForegroundDrawList()->AddRect(GetItemRectMin(), GetItemRectMax(), IM_COL32(255, 255, 0, 255));
if (!open) if (!open)
return; return;
if (table->InstanceCurrent > 0)
ImGui::Text("** %d instances of same table! Some data below will refer to last instance.", table->InstanceCurrent + 1);
bool clear_settings = SmallButton("Clear settings"); bool clear_settings = SmallButton("Clear settings");
BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags)); BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags));
BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : ""); BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "");
@@ -3595,7 +3614,7 @@ void ImGui::DebugNodeTableSettings(ImGuiTableSettings* settings)
TreePop(); TreePop();
} }
#else // #ifndef IMGUI_DISABLE_METRICS_WINDOW #else // #ifndef IMGUI_DISABLE_DEBUG_TOOLS
void ImGui::DebugNodeTable(ImGuiTable*) {} void ImGui::DebugNodeTable(ImGuiTable*) {}
void ImGui::DebugNodeTableSettings(ImGuiTableSettings*) {} void ImGui::DebugNodeTableSettings(ImGuiTableSettings*) {}
File diff suppressed because it is too large Load Diff
+15 -27
View File
@@ -1,15 +1,19 @@
// [DEAR IMGUI] // [DEAR IMGUI]
// This is a slightly modified version of stb_rect_pack.h 1.00. // This is a slightly modified version of stb_rect_pack.h 1.01.
// Those changes would need to be pushed into nothings/stb:
// - Added STBRP__CDECL
// Grep for [DEAR IMGUI] to find the changes. // Grep for [DEAR IMGUI] to find the changes.
//
// stb_rect_pack.h - v1.00 - public domain - rectangle packing // stb_rect_pack.h - v1.01 - public domain - rectangle packing
// Sean Barrett 2014 // Sean Barrett 2014
// //
// Useful for e.g. packing rectangular textures into an atlas. // Useful for e.g. packing rectangular textures into an atlas.
// Does not do rotation. // Does not do rotation.
// //
// Before #including,
//
// #define STB_RECT_PACK_IMPLEMENTATION
//
// in the file that you want to have the implementation.
//
// Not necessarily the awesomest packing method, but better than // Not necessarily the awesomest packing method, but better than
// the totally naive one in stb_truetype (which is primarily what // the totally naive one in stb_truetype (which is primarily what
// this is meant to replace). // this is meant to replace).
@@ -41,6 +45,7 @@
// //
// Version history: // Version history:
// //
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
// 0.99 (2019-02-07) warning fixes // 0.99 (2019-02-07) warning fixes
// 0.11 (2017-03-03) return packing success/fail result // 0.11 (2017-03-03) return packing success/fail result
@@ -81,11 +86,10 @@ typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node; typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect; typedef struct stbrp_rect stbrp_rect;
#ifdef STBRP_LARGE_RECTS
typedef int stbrp_coord; typedef int stbrp_coord;
#else
typedef unsigned short stbrp_coord; #define STBRP__MAXVAL 0x7fffffff
#endif // Mostly for internal use, but this is the maximum supported coordinate value.
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
// Assign packed locations to rectangles. The rectangles are of type // Assign packed locations to rectangles. The rectangles are of type
@@ -213,10 +217,9 @@ struct stbrp_context
#define STBRP_ASSERT assert #define STBRP_ASSERT assert
#endif #endif
// [DEAR IMGUI] Added STBRP__CDECL
#ifdef _MSC_VER #ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v) #define STBRP__NOTUSED(v) (void)(v)
#define STBRP__CDECL __cdecl #define STBRP__CDECL __cdecl
#else #else
#define STBRP__NOTUSED(v) (void)sizeof(v) #define STBRP__NOTUSED(v) (void)sizeof(v)
#define STBRP__CDECL #define STBRP__CDECL
@@ -262,9 +265,6 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_ou
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{ {
int i; int i;
#ifndef STBRP_LARGE_RECTS
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
#endif
for (i=0; i < num_nodes-1; ++i) for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1]; nodes[i].next = &nodes[i+1];
@@ -283,11 +283,7 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
context->extra[0].y = 0; context->extra[0].y = 0;
context->extra[0].next = &context->extra[1]; context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width; context->extra[1].x = (stbrp_coord) width;
#ifdef STBRP_LARGE_RECTS
context->extra[1].y = (1<<30); context->extra[1].y = (1<<30);
#else
context->extra[1].y = 65535;
#endif
context->extra[1].next = NULL; context->extra[1].next = NULL;
} }
@@ -433,7 +429,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
if (y <= best_y) { if (y <= best_y) {
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
best_x = xpos; best_x = xpos;
STBRP_ASSERT(y <= best_y); //STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
best_y = y; best_y = y;
best_waste = waste; best_waste = waste;
best = prev; best = prev;
@@ -529,7 +525,6 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
return res; return res;
} }
// [DEAR IMGUI] Added STBRP__CDECL
static int STBRP__CDECL rect_height_compare(const void *a, const void *b) static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
{ {
const stbrp_rect *p = (const stbrp_rect *) a; const stbrp_rect *p = (const stbrp_rect *) a;
@@ -541,7 +536,6 @@ static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
return (p->w > q->w) ? -1 : (p->w < q->w); return (p->w > q->w) ? -1 : (p->w < q->w);
} }
// [DEAR IMGUI] Added STBRP__CDECL
static int STBRP__CDECL rect_original_order(const void *a, const void *b) static int STBRP__CDECL rect_original_order(const void *a, const void *b)
{ {
const stbrp_rect *p = (const stbrp_rect *) a; const stbrp_rect *p = (const stbrp_rect *) a;
@@ -549,12 +543,6 @@ static int STBRP__CDECL rect_original_order(const void *a, const void *b)
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
} }
#ifdef STBRP_LARGE_RECTS
#define STBRP__MAXVAL 0xffffffff
#else
#define STBRP__MAXVAL 0xffff
#endif
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{ {
int i, all_rects_packed = 1; int i, all_rects_packed = 1;
+6 -8
View File
@@ -1,10 +1,10 @@
// [DEAR IMGUI] // [DEAR IMGUI]
// This is a slightly modified version of stb_textedit.h 1.13. // This is a slightly modified version of stb_textedit.h 1.14.
// Those changes would need to be pushed into nothings/stb: // Those changes would need to be pushed into nothings/stb:
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
// Grep for [DEAR IMGUI] to find the changes. // Grep for [DEAR IMGUI] to find the changes.
// stb_textedit.h - v1.13 - public domain - Sean Barrett // stb_textedit.h - v1.14 - public domain - Sean Barrett
// Development of this library was sponsored by RAD Game Tools // Development of this library was sponsored by RAD Game Tools
// //
// This C header file implements the guts of a multi-line text-editing // This C header file implements the guts of a multi-line text-editing
@@ -35,6 +35,7 @@
// //
// VERSION HISTORY // VERSION HISTORY
// //
// 1.14 (2021-07-11) page up/down, various fixes
// 1.13 (2019-02-07) fix bug in undo size management // 1.13 (2019-02-07) fix bug in undo size management
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash // 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield // 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
@@ -58,6 +59,7 @@
// Ulf Winklemann: move-by-word in 1.1 // Ulf Winklemann: move-by-word in 1.1
// Fabian Giesen: secondary key inputs in 1.5 // Fabian Giesen: secondary key inputs in 1.5
// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6 // Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6
// Louis Schnellbach: page up/down in 1.14
// //
// Bugfixes: // Bugfixes:
// Scott Graham // Scott Graham
@@ -93,8 +95,8 @@
// moderate sizes. The undo system does no memory allocations, so // moderate sizes. The undo system does no memory allocations, so
// it grows STB_TexteditState by the worst-case storage which is (in bytes): // it grows STB_TexteditState by the worst-case storage which is (in bytes):
// //
// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT // [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATECOUNT
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT // + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHARCOUNT
// //
// //
// Implementation mode: // Implementation mode:
@@ -716,10 +718,6 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
state->has_preferred_x = 0; state->has_preferred_x = 0;
return 1; return 1;
} }
// [DEAR IMGUI]
//// remove the undo since we didn't actually insert the characters
//if (state->undostate.undo_point)
// --state->undostate.undo_point;
// note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details) // note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details)
return 0; return 0;
} }
+481 -299
View File
File diff suppressed because it is too large Load Diff
-48
View File
@@ -1,48 +0,0 @@
#pragma once
#include "Scene\SceneBuilder.h"
#include "Scene\Scene.h"
#include "Scenes\MainScene.hpp"
#include "Scenes\TestScene2.hpp"
//#include "Logging\Logger.h"
enum LasEscenas
{
mainMenu = 0, nivel1
};
class GameScenes : public UE::SceneBuilder
{
public:
GameScenes()
{
}
UE::Scene* InstanciateScene(int sceneID) override
{
switch (sceneID)
{
case LasEscenas::mainMenu:
{
UE::Scene* sc = new MainScene("Main");
return sc;
break;
}
case LasEscenas::nivel1:
{
UE::Scene* sc = new TestScene2("Test2");
return sc;
break;
}
default:
return nullptr;
break;
}
}
};
+50 -39
View File
@@ -1,23 +1,22 @@
#include <iostream> #include <iostream>
#include <glm\glm.hpp> #include <glm/glm.hpp>
#include <ImGui\imgui.h> #include <ImGui/imgui.h>
#include <ImGui\imgui_impl_sdl.h> #include <ImGui/imgui_impl_sdl.h>
#include <ImGui\imgui_impl_opengl3.h> #include <ImGui/imgui_impl_opengl3.h>
#include "UberGame1.h"
#include "GameScenes.hpp"
#include "Engine.h"
#include "UberEngine.h" #include "UberEngine.h"
#include "Scenes\MainScene.hpp" #include "Scenes/MainScene.hpp"
#include "Scenes\TestScene2.hpp" #include "Scenes/TestScene2.hpp"
static bool _quit = false; static bool _quit = false;
void Init(); int Init();
void Load(); void Load();
void Loop(); void Loop();
void Clean(); void Clean();
@@ -25,7 +24,9 @@ void Clean();
int main(int argc, char* args[]) int main(int argc, char* args[])
{ {
Init(); //Si falla la inicialización, terminamos el juego.
if(Init() < 0) { return -1; }
Load(); Load();
Loop(); Loop();
Clean(); Clean();
@@ -33,25 +34,28 @@ int main(int argc, char* args[])
return 0; return 0;
} }
int Init()
void Init()
{ {
UE::Logger::InitLogger(); if(UE::Engine::Init() < 0)
{
Game::InitGame(); GAME_LOG_CRITICAL("No se ha podido cargar el motor.");
return -1;
}
return 0;
} }
void Load() void Load()
{ {
Game::GetAssetManager()->LoadAssetsFromFile("resources\\AssetList\\MainAssets.json"); UE::Engine::GetAssetManager()->LoadAssetsFromFile("resources/AssetList/MainAssets.json");
Game::GetAssetManager()->ProcessAssetQueue(); UE::Engine::GetAssetManager()->ProcessAssetQueue();
//Cargamos la escena que queramos tras tener todos los Assets pertinentes cargados. //Cargamos la escena que queramos tras tener todos los Assets pertinentes cargados.
//Si la escena contiene su propio AssetManager y los carga ella misma, no ser� necesario. //Si la escena contiene su propio AssetManager y los carga ella misma, no ser� necesario.
//Game::GetSceneManager()->LoadScene("Main"); //Game::GetSceneManager()->LoadScene("Main");
Game::GetSceneManager()->NewLoadScene(LasEscenas::mainMenu); UE::Engine::GetSceneManager()->LoadScene(new MainScene());
UE::Engine::GetSceneManager()->SwitchScene("MainScene");
} }
@@ -83,10 +87,17 @@ void Loop()
#pragma endregion #pragma endregion
//Almacenamos el renderer para ya tenerlo por aquí.
UE::Renderer* UE_Renderer = UE::Engine::GetRenderer();
while (!_quit) while (!_quit)
{ {
UE::Time::StartFrame(); UE::Time::StartFrame();
//Almacenamos la escena actual.
UE::Scene* currentScene = UE::Engine::GetSceneManager()->GetCurrentScenePtr();
//TEMP Event Handler: //TEMP Event Handler:
SDL_Event eventHandler; SDL_Event eventHandler;
while (SDL_PollEvent(&eventHandler) != 0) while (SDL_PollEvent(&eventHandler) != 0)
@@ -98,25 +109,25 @@ void Loop()
if (io.WantCaptureMouse) { continue; } if (io.WantCaptureMouse) { continue; }
Game::GetSceneManager()->GetActiveScenePtr()->SceneHandleEvents(&eventHandler); currentScene->SceneHandleEvents(&eventHandler);
if (eventHandler.type == SDL_QUIT) if (eventHandler.type == SDL_QUIT)
{ {
_quit = true; _quit = true;
} }
if (eventHandler.type == SDL_WINDOWEVENT && eventHandler.window.event == SDL_WINDOWEVENT_RESIZED) if (eventHandler.type == SDL_WINDOWEVENT && eventHandler.window.event == SDL_WINDOWEVENT_RESIZED)
{ {
//GAME_LOG_CRITICAL("Window Size chaged {0}x{1}", eventHandler.window.data1, eventHandler.window.data2); GAME_LOG_INFO("Window Size chaged {0}x{1}", eventHandler.window.data1, eventHandler.window.data2);
Game::GetRenderer()->SetScreenSize(eventHandler.window.data1, eventHandler.window.data2); UE_Renderer->SetScreenSize(eventHandler.window.data1, eventHandler.window.data2);
} }
if (eventHandler.type == SDL_KEYDOWN) if (eventHandler.type == SDL_KEYDOWN)
{ {
switch (eventHandler.key.keysym.sym) switch (eventHandler.key.keysym.sym)
{ {
case SDLK_1: case SDLK_1:
Game::GetSceneManager()->NewLoadScene(LasEscenas::mainMenu); UE::Engine::GetSceneManager()->LoadAndSwitchScene(new MainScene());
break; break;
case SDLK_2: case SDLK_2:
Game::GetSceneManager()->NewLoadScene(LasEscenas::nivel1); UE::Engine::GetSceneManager()->LoadAndSwitchScene(new TestScene2());
break; break;
default: default:
break; break;
@@ -134,32 +145,34 @@ void Loop()
GAME_LOG_TRACE("FPS: NULL / dT: {1}", UE::Time::deltaTime); GAME_LOG_TRACE("FPS: NULL / dT: {1}", UE::Time::deltaTime);
} }
UE::Camera* cam = UE_Renderer->GetCamera();
if (keyStates[SDL_SCANCODE_W]) if (keyStates[SDL_SCANCODE_W])
{ {
glm::ivec2 camPos = Game::GetRenderer()->GetCamPosition(); glm::ivec2 camPos = cam->GetCamPosition();
camPos.y -= 5; camPos.y -= 5;
Game::GetRenderer()->SetCamPosition(camPos.x, camPos.y); cam->SetCamPosition(camPos.x, camPos.y);
} }
if (keyStates[SDL_SCANCODE_S]) if (keyStates[SDL_SCANCODE_S])
{ {
glm::ivec2 camPos = Game::GetRenderer()->GetCamPosition(); glm::ivec2 camPos = cam->GetCamPosition();
camPos.y += 5; camPos.y += 5;
Game::GetRenderer()->SetCamPosition(camPos.x, camPos.y); cam->SetCamPosition(camPos.x, camPos.y);
} }
if (keyStates[SDL_SCANCODE_D]) if (keyStates[SDL_SCANCODE_D])
{ {
glm::ivec2 camPos = Game::GetRenderer()->GetCamPosition(); glm::ivec2 camPos = cam->GetCamPosition();
camPos.x += 5; camPos.x += 5;
Game::GetRenderer()->SetCamPosition(camPos.x, camPos.y); cam->SetCamPosition(camPos.x, camPos.y);
} }
if (keyStates[SDL_SCANCODE_A]) if (keyStates[SDL_SCANCODE_A])
{ {
glm::ivec2 camPos = Game::GetRenderer()->GetCamPosition(); glm::ivec2 camPos = cam->GetCamPosition();
camPos.x -= 5; camPos.x -= 5;
Game::GetRenderer()->SetCamPosition(camPos.x, camPos.y); cam->SetCamPosition(camPos.x, camPos.y);
} }
Game::GetSceneManager()->GetActiveScenePtr()->SceneUpdate(); currentScene->SceneUpdate();
//Game::GetRenderer()->QueueDrawCall(4, DestR2, test1); //Game::GetRenderer()->QueueDrawCall(4, DestR2, test1);
//Game::GetRenderer()->QueueDrawCall(1, DestR, background); //Game::GetRenderer()->QueueDrawCall(1, DestR, background);
@@ -170,20 +183,20 @@ void Loop()
// //
//Iniciamos un nuevo Frame. //Iniciamos un nuevo Frame.
Game::GetRenderer()->NewFrame(); UE_Renderer->NewFrame();
//Renderiza la escena. //Renderiza la escena.
Game::GetSceneManager()->GetActiveScenePtr()->SceneRender(); currentScene->SceneRender();
//As� podemos renderizar cosas de ImGui cuando estemos entre NewFrame y EndFrame. //As� podemos renderizar cosas de ImGui cuando estemos entre NewFrame y EndFrame.
bool show = true; bool show = true;
ImGui::ShowDemoWindow(&show); ImGui::ShowDemoWindow(&show);
//Dibuja las cosas del Renderer. //Dibuja las cosas del Renderer.
Game::GetRenderer()->RenderData(); UE_Renderer->RenderData();
//Terminamos el Frame. //Terminamos el Frame.
Game::GetRenderer()->EndFrame(); UE_Renderer->EndFrame();
UE::Time::EndFrame(); UE::Time::EndFrame();
@@ -194,7 +207,5 @@ void Loop()
void Clean() void Clean()
{ {
Game::CleanGame(); UE::Engine::Clean();
SDL_Quit();
} }
+28 -17
View File
@@ -1,15 +1,16 @@
//#include "UberEngine.h" //#include "UberEngine.h"
#pragma once #pragma once
#include "Scene\Scene.h" #include "Engine.h"
#include "Render\Renderer.h" #include "Scene/Scene.h"
#include "Assets\AssetManager.h" #include "Render/Renderer.h"
#include "Logging\Logger.h" #include "Assets/AssetManager.h"
#include "Logging/Logger.h"
#include "Drawables\Sprite.h" #include "Drawables/Sprite.h"
#include "Drawables\TextBox.h" #include "Drawables/TextBox.h"
#include "Time\Time.h" #include "Time/Time.h"
#include <iostream> #include <iostream>
@@ -17,27 +18,37 @@
#include <SDL.h> #include <SDL.h>
#include <SDL_ttf.h> #include <SDL_ttf.h>
#include <ImGui\imgui.h> #include <ImGui/imgui.h>
class MainScene : public UE::Scene class MainScene : public UE::Scene
{ {
public: public:
MainScene(std::string sceneName) : Scene(sceneName) {} MainScene() : Scene("MainScene")
{
//_sceneName = "MainScene";
}
void SceneLoad() override void SceneLoad() override
{ {
UE_LOG_INFO("Escena {0} ha sido cargada", _sceneName); UE_LOG_INFO("Escena {0} ha sido cargada", _sceneName);
UE::AssetManager* as = Game::GetAssetManager(); //Configuramos las cosas del Renderer.
//UE::Engine::GetRenderer()->SetCamPosition(150, 25);
SDL_Color newColor{40, 160, 195, 255};
UE::Engine::GetRenderer()->SetDrawingColor(newColor);
UE::AssetManager* as = UE::Engine::GetAssetManager();
UE::Texture* test1Texture = as->getTexture("test1"); UE::Texture* test1Texture = as->getTexture("test1");
UE::Sprite sp1(test1Texture, 0, 2, glm::vec2(55, 60), glm::vec2(100, 100)); UE::Sprite sp1(test1Texture, 0, 2, glm::vec2(55, 60), glm::vec2(100, 100));
UE::Sprite sp2(test1Texture, 0, 1, glm::vec2(50, 45), glm::vec2(145, 145)); UE::Sprite sp2(test1Texture, 0, 1, glm::vec2(50, 45), glm::vec2(145, 145));
UE::Sprite bg(as->getTexture("bg1"), 1, 0, glm::vec2(0, 0), Game::GetRenderer()->GetScreenSize()); UE::Sprite bg(as->getTexture("bg1"), 1, 0, glm::vec2(0, 0), UE::Engine::GetRenderer()->GetScreenSize());
UE::Sprite mapSP(as->getTexture("PruebaMap"), 0, 2, glm::vec2(50, 45), glm::vec2(145, 145)); UE::Sprite mapSP(as->getTexture("PruebaMap"), 0, 2, glm::vec2(50, 45), glm::vec2(145, 145));
@@ -62,9 +73,9 @@ public:
//UE_LOG_INFO("Escena {0} UPDATE", _sceneName); //UE_LOG_INFO("Escena {0} UPDATE", _sceneName);
UE::Renderer* renderer; UE::Renderer* renderer;
renderer = Game::GetRenderer(); renderer = UE::Engine::GetRenderer();
glm::vec2 screenSize = Game::GetRenderer()->GetScreenSize(); glm::vec2 screenSize = UE::Engine::GetRenderer()->GetScreenSize();
UE::Sprite& sp1 = sprites.at(0); UE::Sprite& sp1 = sprites.at(0);
glm::vec2 pos = sp1.GetPosition(); glm::vec2 pos = sp1.GetPosition();
@@ -78,11 +89,11 @@ public:
void SceneRender() override void SceneRender() override
{ {
UE::Renderer* renderer; UE::Renderer* renderer;
renderer = Game::GetRenderer(); renderer = UE::Engine::GetRenderer();
for (UE::Sprite& sp : sprites) for (UE::Sprite& sp : sprites)
{ {
//Si el obj. no está activo, lo saltamos. //Si el obj. no est� activo, lo saltamos.
if (sp.IsActive()) if (sp.IsActive())
{ {
renderer->Render(sp); renderer->Render(sp);
@@ -210,7 +221,7 @@ private:
{ {
sp.SetTextureRect(textRect); sp.SetTextureRect(textRect);
} }
//Añadir un input para modificar la layer. //A�adir un input para modificar la layer.
} }
@@ -236,7 +247,7 @@ private:
void AssetMngGUI() void AssetMngGUI()
{ {
UE::AssetManager* asmng = Game::GetAssetManager(); UE::AssetManager* asmng = UE::Engine::GetAssetManager();
ImGui::Begin("Asset Manager Inspector", &assetMngGUI); ImGui::Begin("Asset Manager Inspector", &assetMngGUI);
+18 -14
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "Scene\Scene.h" #include "Scene/Scene.h"
#include "Render\Renderer.h" #include "Render/Renderer.h"
#include "Logging\Logger.h" #include "Logging/Logger.h"
#include "Assets\AssetManager.h" #include "Assets/AssetManager.h"
#include "Assets\Texture.h" #include "Assets/Texture.h"
#include "Drawables\Sprite.h" #include "Drawables/Sprite.h"
#include <iostream> #include <iostream>
@@ -18,7 +18,10 @@ class TestScene2 : public UE::Scene
{ {
public: public:
TestScene2(std::string sceneName) : Scene(sceneName) {} TestScene2() : Scene("TestScene")
{
//_sceneName = "TestScene";
}
void SceneLoad() override void SceneLoad() override
{ {
@@ -26,7 +29,7 @@ public:
srand(255); srand(255);
UE::AssetManager* as = Game::GetAssetManager(); UE::AssetManager* as = UE::Engine::GetAssetManager();
UE::Texture* tx = as->getTexture("PruebaMap"); UE::Texture* tx = as->getTexture("PruebaMap");
@@ -55,11 +58,11 @@ public:
void SceneRender() override void SceneRender() override
{ {
UE::Renderer* renderer; UE::Renderer* renderer;
renderer = Game::GetRenderer(); renderer = UE::Engine::GetRenderer();
for (UE::Sprite& sp : sprites) for (UE::Sprite& sp : sprites)
{ {
//Si el obj. no está activo, lo saltamos. //Si el obj. no est� activo, lo saltamos.
if (sp.IsActive()) if (sp.IsActive())
{ {
renderer->Render(sp); renderer->Render(sp);
@@ -85,7 +88,7 @@ public:
} }
if (event->type == SDL_MOUSEBUTTONDOWN) if (event->type == SDL_MOUSEBUTTONDOWN)
{ {
UE::Renderer* rend = Game::GetRenderer(); UE::Renderer* rend = UE::Engine::GetRenderer();
glm::ivec2 mPos(event->button.x, event->button.y); glm::ivec2 mPos(event->button.x, event->button.y);
glm::ivec2 wPos = rend->ScreenToWorldCoords(mPos); glm::ivec2 wPos = rend->ScreenToWorldCoords(mPos);
GAME_LOG_TRACE("Posicion del raton: \n\tPantalla: {0}x{1}, Mundo: {2}x{3}: ", mPos.x, mPos.y, wPos.x, wPos.y); GAME_LOG_TRACE("Posicion del raton: \n\tPantalla: {0}x{1}, Mundo: {2}x{3}: ", mPos.x, mPos.y, wPos.x, wPos.y);
@@ -105,11 +108,12 @@ private:
{ {
SDL_Rect mouseRect = { wPos.x, wPos.y, 2, 2 }; SDL_Rect mouseRect = { wPos.x, wPos.y, 2, 2 };
//Esto hay que optimizarlo calculando el ID con la posición del ratón.
for (int i = 0; i < sprites.size(); i++) for (int i = 0; i < sprites.size(); i++)
{ {
UE::Sprite& sp = sprites.at(i); UE::Sprite& sp = sprites.at(i);
SDL_Rect sp_Pos = sp.getPositionRect();
if (SDL_HasIntersection(&mouseRect, &sp.getPositionRect())) if (SDL_HasIntersection(&mouseRect, &sp_Pos))
{ {
int i = rand() % 5; int i = rand() % 5;
sp.SetTextureRect(i); sp.SetTextureRect(i);
@@ -179,7 +183,7 @@ private:
{ {
sp.SetTextureRect(textRect); sp.SetTextureRect(textRect);
} }
//Añadir un input para modificar la layer. //A�adir un input para modificar la layer.
} }
-49
View File
@@ -1,49 +0,0 @@
#include "UberGame1.h"
#include "Logging\Logger.h"
#include "Render\Renderer.h"
#include "Assets\AssetManager.h"
#include "Scene\SceneManager.h"
#include "Scene\SceneBuilder.h"
#include "GameScenes.hpp"
//Sobrecarga de SceneBuilder que devuelve las escenas correctas para este juego.
//#include "GameScenes.hpp"
UE::Renderer* Game::mainRenderer;
UE::AssetManager* Game::asManager;
UE::SceneManager* Game::scManager;
GameScenes Game::_sceneBuilder;
void Game::InitGame()
{
mainRenderer = new UE::Renderer(640, 480, 5);
mainRenderer->InitRenderer();
UE_LOG_INFO("Renderer Created.");
asManager = new UE::AssetManager(mainRenderer->GetSDLRenderer());
asManager->InitAssetManager();
UE_LOG_INFO("AssetManager Created.");
//Creamos el SceneBuilder de este juego.
_sceneBuilder = GameScenes();
scManager = new UE::SceneManager();
scManager->InitSceneManager(&_sceneBuilder);
}
void Game::CleanGame()
{
asManager->CleanAssetManager();
delete asManager;
mainRenderer->CleanRenderer();
delete mainRenderer;
scManager->CleanSceneManager();
delete scManager;
}
-30
View File
@@ -1,30 +0,0 @@
#pragma once
namespace UE
{
class Renderer;
class AssetManager;
class SceneManager;
class SceneBuilder;
}
class GameScenes;
class Game
{
public:
static void InitGame();
static void CleanGame();
inline static UE::Renderer* GetRenderer() { return mainRenderer; }
inline static UE::AssetManager* GetAssetManager() { return asManager; }
inline static UE::SceneManager* GetSceneManager() { return scManager; }
private:
static UE::Renderer* mainRenderer;
static UE::AssetManager* asManager;
static UE::SceneManager* scManager;
static GameScenes _sceneBuilder;
};
+1
View File
@@ -0,0 +1 @@
null.o: /dev/null
BIN
View File
Binary file not shown.
Binary file not shown.
+51 -34
View File
@@ -6,13 +6,14 @@ GameName = "UberGame1"
workspace (""..GameName.."") workspace (""..GameName.."")
configurations {"Debug", "Release"} configurations { "Debug", "Release" }
architecture "x64" architecture "x64"
project (""..GameName.."") project (""..GameName.."")
kind "ConsoleApp" kind "ConsoleApp"
language "C++" language "C++"
cppdialect "C++17"
location "" location ""
@@ -38,47 +39,63 @@ project (""..GameName.."")
-- "UberEngine/vendor/glm", -- "UberEngine/vendor/glm",
-- "UberEngine/vendor/ImGui", -- "UberEngine/vendor/ImGui",
-- "UberEngine/vendor/json", --Header-Only -- "UberEngine/vendor/json", --Header-Only
"UberEngine/vendor/SDL/include",
"UberEngine/vendor/SDL2_image/include",
"UberEngine/vendor/SDL2_ttf/include",
"UberEngine/vendor/spdlog/include", "UberEngine/vendor/spdlog/include",
"UberEngine/vendor", "UberEngine/vendor",
"UberEngine/src" "UberEngine/src"
} }
libdirs { "UberEngine/vendor/SDL/lib/x64", "UberEngine/vendor/SDL2_image/lib/x64", "UberEngine/vendor/SDL2_ttf/lib/x64" }
links { "opengl32.lib", "SDL2.lib", "SDL2main.lib", "SDL2_image.lib", "SDL2_ttf.lib" }
filter "configurations:Debug"
defines { "DEBUG" }
symbols "On"
postbuildcommands
{
"{COPYDIR} UberEngine/vendor/SDL/lib/x64/*.dll bin/Debug/",
"{COPYDIR} UberEngine/vendor/SDL2_image/lib/x64/*.dll bin/Debug/",
"{COPYDIR} UberEngine/vendor/SDL2_ttf/lib/x64/*.dll bin/Debug/",
"{COPYDIR} resources/ bin/Debug/resources/"
}
filter "configurations:Release"
defines { "NDEBUG" }
optimize "On"
postbuildcommands
{
"{COPYDIR} UberEngine/vendor/SDL/lib/x64/*.dll bin/Release/",
"{COPYDIR} UberEngine/vendor/SDL2_image/lib/x64/*.dll bin/Release/",
"{COPYDIR} UberEngine/vendor/SDL2_ttf/lib/x64/*.dll bin/Release/",
"{COPYDIR} resources/ bin/Release/resources/"
}
-------------------------------------------------
-- Opciones de Windows.
-------------------------------------------------
filter "system:windows" filter "system:windows"
cppdialect "C++17"
systemversion "latest" systemversion "latest"
includedirs
{
"UberEngine/vendor/SDL/include",
"UberEngine/vendor/SDL2_image/include",
"UberEngine/vendor/SDL2_ttf/include",
}
libdirs { "UberEngine/vendor/SDL/lib/x64", "UberEngine/vendor/SDL2_image/lib/x64", "UberEngine/vendor/SDL2_ttf/lib/x64" }
links { "opengl32.lib", "SDL2.lib", "SDL2main.lib", "SDL2_image.lib", "SDL2_ttf.lib" }
defines { "SDL_VIDEO_DRIVER_WINDOWS" }
filter "configurations:Debug" -------------------------------------------------
defines { "DEBUG" } -- Opciones de Linux.
symbols "On" -------------------------------------------------
filter "system:linux"
includedirs
{
"/usr/include/SDL2/"
}
--libdirs { "UberEngine/vendor/SFML/lib/Debug" } links { "SDL2", "SDL2main", "SDL2_image", "SDL2_ttf", "dl", "GL", "GLEW"}
--links { "sfml-audio-d.lib", "sfml-graphics-d.lib", "sfml-network-d.lib", "sfml-main-d.lib", "sfml-system-d.lib", "sfml-window-d.lib" } defines { "SDL_VIDEO_DRIVER_X11" }
postbuildcommands
{
"xcopy UberEngine\\vendor\\SDL\\lib\\x64\\*.dll bin\\Debug\\ /y /f",
"xcopy UberEngine\\vendor\\SDL2_image\\lib\\x64\\*.dll bin\\Debug\\ /y /f",
"xcopy UberEngine\\vendor\\SDL2_ttf\\lib\\x64\\*.dll bin\\Debug\\ /y /f",
"xcopy resources\\ bin\\Debug\\resources\\ /e /y /f"
}
filter "configurations:Release"
defines { "NDEBUG" }
optimize "On"
--libdirs { "UberEngine/vendor/SFML/lib/Release" }
--links { "sfml-audio.lib", "sfml-graphics.lib", "sfml-network.lib", "sfml-main.lib", "sfml-system.lib", "sfml-window.lib" }
postbuildcommands
{
"xcopy UberEngine\\vendor\\SDL\\lib\\x64\\*.dll bin\\Release\\ /y /f",
"xcopy UberEngine\\vendor\\SDL2_image\\lib\\x64\\*.dll bin\\Release\\ /y /f",
"xcopy UberEngine\\vendor\\SDL2_ttf\\lib\\x64\\*.dll bin\\Release\\ /y /f",
"xcopy resources\\ bin\\Release\\resources\\ /e /y /f"
}