Another code cleanup and code documentation update.

This commit is contained in:
Leon Styhre 2020-06-26 17:17:35 +02:00
parent ee4a55e9d6
commit 1f74723533
36 changed files with 2254 additions and 1984 deletions

View file

@ -25,6 +25,7 @@ v1.0.0
* All required fonts bundled with the application, no dependencies on the OS to provide them any longer * All required fonts bundled with the application, no dependencies on the OS to provide them any longer
* Made pugixml an external dependency instead of bundling it * Made pugixml an external dependency instead of bundling it
* Updated the cmake/cpack install and package build script to work as expected (can now generate .deb and .rpm installation packages) * Updated the cmake/cpack install and package build script to work as expected (can now generate .deb and .rpm installation packages)
* Added support for Clang/LLVM, made the application build with no errors or warnings using this compiler
* License files included for all the libraries and resources that are bundled with the application * License files included for all the libraries and resources that are bundled with the application
* Updated the MAME ROM index files to include ROMs up to MAME version 0.221 (and created scripts to easily generate these index files in the future) * Updated the MAME ROM index files to include ROMs up to MAME version 0.221 (and created scripts to easily generate these index files in the future)

View file

@ -273,7 +273,7 @@ bool SystemData::loadConfig()
// If there appears to be an actual platform ID supplied // If there appears to be an actual platform ID supplied
// but it didn't match the list, generate a warning. // but it didn't match the list, generate a warning.
if (str != nullptr && str[0] != '\0' && platformId == PlatformIds::PLATFORM_UNKNOWN) if (str != nullptr && str[0] != '\0' && platformId == PlatformIds::PLATFORM_UNKNOWN)
LOG(LogWarning) << " Unknown platform for system \"" << name << "\" (platform \"" LOG(LogWarning) << "Unknown platform for system \"" << name << "\" (platform \""
<< str << "\" from list \"" << platformList << "\")"; << str << "\" from list \"" << platformList << "\")";
else if (platformId != PlatformIds::PLATFORM_UNKNOWN) else if (platformId != PlatformIds::PLATFORM_UNKNOWN)
platformIds.push_back(platformId); platformIds.push_back(platformId);

View file

@ -1,9 +1,16 @@
//
// CECInput.cpp
//
// CEC (Consumer Electronics Control).
//
#include "CECInput.h" #include "CECInput.h"
#ifdef HAVE_LIBCEC #ifdef HAVE_LIBCEC
#include "Log.h" #include "Log.h"
#include <iostream> // Bad bad cecloader.
#include <libcec/cec.h> #include <libcec/cec.h>
#include <iostream> // bad bad cecloader
#include <libcec/cecloader.h> #include <libcec/cecloader.h>
#include <SDL_events.h> #include <SDL_events.h>
#ifdef _RPI_ #ifdef _RPI_
@ -15,362 +22,338 @@ extern "C" {
#endif // _RPI_ #endif // _RPI_
#endif // HAVE_LIBCEC #endif // HAVE_LIBCEC
// hack for cec support // Hack for CEC support.
extern int SDL_USER_CECBUTTONDOWN; extern int SDL_USER_CECBUTTONDOWN;
extern int SDL_USER_CECBUTTONUP; extern int SDL_USER_CECBUTTONUP;
CECInput* CECInput::sInstance = nullptr; CECInput* CECInput::sInstance = nullptr;
#ifdef HAVE_LIBCEC #ifdef HAVE_LIBCEC
static void onAlert(void* /*cbParam*/, const CEC::libcec_alert type, const CEC::libcec_parameter param) static void onAlert(void* /*cbParam*/, const CEC::libcec_alert type,
const CEC::libcec_parameter param)
{ {
LOG(LogDebug) << "CECInput::onAlert type: " << CECInput::getAlertTypeString(type) << " parameter: " << (char*)(param.paramData); LOG(LogDebug) << "CECInput::onAlert type: " << CECInput::getAlertTypeString(type) <<
" parameter: " << (char*)(param.paramData);
} // onAlert }
static void onCommand(void* /*cbParam*/, const CEC::cec_command* command) static void onCommand(void* /*cbParam*/, const CEC::cec_command* command)
{ {
LOG(LogDebug) << "CECInput::onCommand opcode: " << CECInput::getOpCodeString(command->opcode); LOG(LogDebug) << "CECInput::onCommand opcode: " << CECInput::getOpCodeString(command->opcode);
}
} // onCommand
static void onKeyPress(void* /*cbParam*/, const CEC::cec_keypress* key) static void onKeyPress(void* /*cbParam*/, const CEC::cec_keypress* key)
{ {
LOG(LogDebug) << "CECInput::onKeyPress keycode: " << CECInput::getKeyCodeString(key->keycode); LOG(LogDebug) << "CECInput::onKeyPress keycode: " << CECInput::getKeyCodeString(key->keycode);
SDL_Event event; SDL_Event event;
event.type = (key->duration > 0) ? SDL_USER_CECBUTTONUP : SDL_USER_CECBUTTONDOWN; event.type = (key->duration > 0) ? SDL_USER_CECBUTTONUP : SDL_USER_CECBUTTONDOWN;
event.user.code = key->keycode; event.user.code = key->keycode;
SDL_PushEvent(&event); SDL_PushEvent(&event);
}
} // onKeyPress
static void onLogMessage(void* /*cbParam*/, const CEC::cec_log_message* message) static void onLogMessage(void* /*cbParam*/, const CEC::cec_log_message* message)
{ {
LOG(LogDebug) << "CECInput::onLogMessage message: " << message->message; LOG(LogDebug) << "CECInput::onLogMessage message: " << message->message;
}
} // onLogMessage
#ifdef _RPI_ #ifdef _RPI_
static void vchi_tv_and_cec_init() static void vchi_tv_and_cec_init()
{ {
VCHI_INSTANCE_T vchi_instance; VCHI_INSTANCE_T vchi_instance;
VCHI_CONNECTION_T* vchi_connection; VCHI_CONNECTION_T* vchi_connection;
vc_host_get_vchi_state(&vchi_instance, &vchi_connection); vc_host_get_vchi_state(&vchi_instance, &vchi_connection);
vc_vchi_tv_init(vchi_instance, &vchi_connection, 1); vc_vchi_tv_init(vchi_instance, &vchi_connection, 1);
vc_vchi_cec_init(vchi_instance, &vchi_connection, 1); vc_vchi_cec_init(vchi_instance, &vchi_connection, 1);
}
} // vchi_tv_and_cec_init
static void vchi_tv_and_cec_deinit() static void vchi_tv_and_cec_deinit()
{ {
vc_vchi_cec_stop(); vc_vchi_cec_stop();
vc_vchi_tv_stop(); vc_vchi_tv_stop();
}
} // vchi_tv_and_cec_deinit
#endif // _RPI_ #endif // _RPI_
#endif // HAVE_LIBCEC #endif // HAVE_LIBCEC
void CECInput::init() void CECInput::init()
{ {
if(!sInstance) if (!sInstance)
sInstance = new CECInput(); sInstance = new CECInput();
}
} // init
void CECInput::deinit() void CECInput::deinit()
{ {
if(sInstance) if (sInstance) {
{ delete sInstance;
delete sInstance; sInstance = nullptr;
sInstance = nullptr; }
} }
} // deinit
CECInput::CECInput() : mlibCEC(nullptr) CECInput::CECInput() : mlibCEC(nullptr)
{ {
#ifdef HAVE_LIBCEC #ifdef HAVE_LIBCEC
#ifdef _RPI_ #ifdef _RPI_
// restart vchi tv and cec in case we just came back from another app using cec (like Kodi) // Restart vchi tv and CEC in case we just came back from another app using CEC (like Kodi).
vchi_tv_and_cec_deinit(); vchi_tv_and_cec_deinit();
vchi_tv_and_cec_init(); vchi_tv_and_cec_init();
#endif // _RPI_ #endif // _RPI_
CEC::ICECCallbacks callbacks; CEC::ICECCallbacks callbacks;
CEC::libcec_configuration config; CEC::libcec_configuration config;
callbacks.Clear(); callbacks.Clear();
config.Clear(); config.Clear();
callbacks.alert = &onAlert; callbacks.alert = &onAlert;
callbacks.commandReceived = &onCommand; callbacks.commandReceived = &onCommand;
callbacks.keyPress = &onKeyPress; callbacks.keyPress = &onKeyPress;
callbacks.logMessage = &onLogMessage; callbacks.logMessage = &onLogMessage;
sprintf(config.strDeviceName, "RetroPie ES"); sprintf(config.strDeviceName, "RetroPie ES");
config.clientVersion = CEC::LIBCEC_VERSION_CURRENT; config.clientVersion = CEC::LIBCEC_VERSION_CURRENT;
config.bActivateSource = 0; config.bActivateSource = 0;
config.callbacks = &callbacks; config.callbacks = &callbacks;
config.deviceTypes.Add(CEC::CEC_DEVICE_TYPE_PLAYBACK_DEVICE); config.deviceTypes.Add(CEC::CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
mlibCEC = LibCecInitialise(&config); mlibCEC = LibCecInitialise(&config);
if(!mlibCEC) if (!mlibCEC) {
{ LOG(LogError) << "CECInput::LibCecInitialise failed";
LOG(LogError) << "CECInput::LibCecInitialise failed"; return;
return; }
}
CEC::cec_adapter_descriptor adapters[10]; CEC::cec_adapter_descriptor adapters[10];
int numAdapters = mlibCEC->DetectAdapters(adapters, 10, nullptr, true); int numAdapters = mlibCEC->DetectAdapters(adapters, 10, nullptr, true);
if(numAdapters <= 0) if (numAdapters <= 0) {
{ LOG(LogError) << "CECInput::mAdapter->DetectAdapters failed";
LOG(LogError) << "CECInput::mAdapter->DetectAdapters failed"; UnloadLibCec(mlibCEC);
UnloadLibCec(mlibCEC); mlibCEC = nullptr;
mlibCEC = nullptr; return;
return; }
}
for(int i = 0; i < numAdapters; ++i) for (int i = 0; i < numAdapters; ++i)
LOG(LogDebug) << "CEC adapter: " << i << " path: " << adapters[i].strComPath << " name: " << adapters[i].strComName; LOG(LogDebug) << "CEC adapter: " << i << " path: " << adapters[i].strComPath <<
" name: " << adapters[i].strComName;
if(!mlibCEC->Open(adapters[0].strComName)) if (!mlibCEC->Open(adapters[0].strComName)) {
{ LOG(LogError) << "CECInput::mAdapter->Open failed";
LOG(LogError) << "CECInput::mAdapter->Open failed"; UnloadLibCec(mlibCEC);
UnloadLibCec(mlibCEC); mlibCEC = nullptr;
mlibCEC = nullptr; return;
return; }
} #endif // HAVE_LIBCEC
#endif // HAVE_LIBCEC }
} // CECInput
CECInput::~CECInput() CECInput::~CECInput()
{ {
#ifdef HAVE_LIBCEC #ifdef HAVE_LIBCEC
if(mlibCEC) if (mlibCEC) {
{ mlibCEC->Close();
mlibCEC->Close(); UnloadLibCec(mlibCEC);
UnloadLibCec(mlibCEC); mlibCEC = nullptr;
mlibCEC = nullptr; }
}
#ifdef _RPI_ #ifdef _RPI_
// deinit vchi tv and cec in case we are going to launch another app using cec (like Kodi) // Deinit vchi tv and CEC in case we are going to launch another app using CEC (like Kodi).
vchi_tv_and_cec_deinit(); vchi_tv_and_cec_deinit();
#endif // _RPI_ #endif // _RPI_
#endif // HAVE_LIBCEC #endif // HAVE_LIBCEC
}
} // ~CECInput
std::string CECInput::getAlertTypeString(const unsigned int _type) std::string CECInput::getAlertTypeString(const unsigned int _type)
{ {
switch(_type) switch (_type) {
{ #ifdef HAVE_LIBCEC
case CEC::CEC_ALERT_SERVICE_DEVICE: { return "Service-Device"; } break;
#ifdef HAVE_LIBCEC case CEC::CEC_ALERT_CONNECTION_LOST: { return "Connection-Lost"; } break;
case CEC::CEC_ALERT_SERVICE_DEVICE: { return "Service-Device"; } break; case CEC::CEC_ALERT_PERMISSION_ERROR: { return "Permission-Error"; } break;
case CEC::CEC_ALERT_CONNECTION_LOST: { return "Connection-Lost"; } break; case CEC::CEC_ALERT_PORT_BUSY: { return "Port-Busy"; } break;
case CEC::CEC_ALERT_PERMISSION_ERROR: { return "Permission-Error"; } break; case CEC::CEC_ALERT_PHYSICAL_ADDRESS_ERROR: { return "Physical-Address-Error"; } break;
case CEC::CEC_ALERT_PORT_BUSY: { return "Port-Busy"; } break; case CEC::CEC_ALERT_TV_POLL_FAILED: { return "TV-Poll-Failed"; } break;
case CEC::CEC_ALERT_PHYSICAL_ADDRESS_ERROR: { return "Physical-Address-Error"; } break; #else // HAVE_LIBCEC
case CEC::CEC_ALERT_TV_POLL_FAILED: { return "TV-Poll-Failed"; } break; case 0:
#else // HAVE_LIBCEC #endif // HAVE_LIBCEC
case 0: default: { return "Unknown"; } break;
#endif // HAVE_LIBCEC }
}
default: { return "Unknown"; } break;
}
} // getAlertTypeString
std::string CECInput::getOpCodeString(const unsigned int _opCode) std::string CECInput::getOpCodeString(const unsigned int _opCode)
{ {
switch(_opCode) switch (_opCode) {
{ #ifdef HAVE_LIBCEC
case CEC::CEC_OPCODE_ACTIVE_SOURCE: { return "Active-Source"; } break;
#ifdef HAVE_LIBCEC case CEC::CEC_OPCODE_IMAGE_VIEW_ON: { return "Image-View-On"; } break;
case CEC::CEC_OPCODE_ACTIVE_SOURCE: { return "Active-Source"; } break; case CEC::CEC_OPCODE_TEXT_VIEW_ON: { return "Text-View-On"; } break;
case CEC::CEC_OPCODE_IMAGE_VIEW_ON: { return "Image-View-On"; } break; case CEC::CEC_OPCODE_INACTIVE_SOURCE: { return "Inactive-Source"; } break;
case CEC::CEC_OPCODE_TEXT_VIEW_ON: { return "Text-View-On"; } break; case CEC::CEC_OPCODE_REQUEST_ACTIVE_SOURCE: { return "Request-Active-Source"; } break;
case CEC::CEC_OPCODE_INACTIVE_SOURCE: { return "Inactive-Source"; } break; case CEC::CEC_OPCODE_ROUTING_CHANGE: { return "Routing-Change"; } break;
case CEC::CEC_OPCODE_REQUEST_ACTIVE_SOURCE: { return "Request-Active-Source"; } break; case CEC::CEC_OPCODE_ROUTING_INFORMATION: { return "Routing-Information"; } break;
case CEC::CEC_OPCODE_ROUTING_CHANGE: { return "Routing-Change"; } break; case CEC::CEC_OPCODE_SET_STREAM_PATH: { return "Set-Stream-Path"; } break;
case CEC::CEC_OPCODE_ROUTING_INFORMATION: { return "Routing-Information"; } break; case CEC::CEC_OPCODE_STANDBY: { return "Standby"; } break;
case CEC::CEC_OPCODE_SET_STREAM_PATH: { return "Set-Stream-Path"; } break; case CEC::CEC_OPCODE_RECORD_OFF: { return "Record-Off"; } break;
case CEC::CEC_OPCODE_STANDBY: { return "Standby"; } break; case CEC::CEC_OPCODE_RECORD_ON: { return "Record-On"; } break;
case CEC::CEC_OPCODE_RECORD_OFF: { return "Record-Off"; } break; case CEC::CEC_OPCODE_RECORD_STATUS: { return "Record-Status"; } break;
case CEC::CEC_OPCODE_RECORD_ON: { return "Record-On"; } break; case CEC::CEC_OPCODE_RECORD_TV_SCREEN: { return "Record-TV-Screen"; } break;
case CEC::CEC_OPCODE_RECORD_STATUS: { return "Record-Status"; } break; case CEC::CEC_OPCODE_CLEAR_ANALOGUE_TIMER: { return "Clear-Analogue-Timer"; } break;
case CEC::CEC_OPCODE_RECORD_TV_SCREEN: { return "Record-TV-Screen"; } break; case CEC::CEC_OPCODE_CLEAR_DIGITAL_TIMER: { return "Clear-Digital-Timer"; } break;
case CEC::CEC_OPCODE_CLEAR_ANALOGUE_TIMER: { return "Clear-Analogue-Timer"; } break; case CEC::CEC_OPCODE_CLEAR_EXTERNAL_TIMER: { return "Clear-External-Timer"; } break;
case CEC::CEC_OPCODE_CLEAR_DIGITAL_TIMER: { return "Clear-Digital-Timer"; } break; case CEC::CEC_OPCODE_SET_ANALOGUE_TIMER: { return "Set-Analogue-Timer"; } break;
case CEC::CEC_OPCODE_CLEAR_EXTERNAL_TIMER: { return "Clear-External-Timer"; } break; case CEC::CEC_OPCODE_SET_DIGITAL_TIMER: { return "Set-Digital-Timer"; } break;
case CEC::CEC_OPCODE_SET_ANALOGUE_TIMER: { return "Set-Analogue-Timer"; } break; case CEC::CEC_OPCODE_SET_EXTERNAL_TIMER: { return "Set-External-Timer"; } break;
case CEC::CEC_OPCODE_SET_DIGITAL_TIMER: { return "Set-Digital-Timer"; } break; case CEC::CEC_OPCODE_SET_TIMER_PROGRAM_TITLE: { return "Set-Timer-Program-Title"; } break;
case CEC::CEC_OPCODE_SET_EXTERNAL_TIMER: { return "Set-External-Timer"; } break; case CEC::CEC_OPCODE_TIMER_CLEARED_STATUS: { return "Timer-Cleared-Status"; } break;
case CEC::CEC_OPCODE_SET_TIMER_PROGRAM_TITLE: { return "Set-Timer-Program-Title"; } break; case CEC::CEC_OPCODE_TIMER_STATUS: { return "Timer-Status"; } break;
case CEC::CEC_OPCODE_TIMER_CLEARED_STATUS: { return "Timer-Cleared-Status"; } break; case CEC::CEC_OPCODE_CEC_VERSION: { return "CEC-Version"; } break;
case CEC::CEC_OPCODE_TIMER_STATUS: { return "Timer-Status"; } break; case CEC::CEC_OPCODE_GET_CEC_VERSION: { return "Get-CEC-Version"; } break;
case CEC::CEC_OPCODE_CEC_VERSION: { return "CEC-Version"; } break; case CEC::CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: { return "Give-Physical-Address"; } break;
case CEC::CEC_OPCODE_GET_CEC_VERSION: { return "Get-CEC-Version"; } break; case CEC::CEC_OPCODE_GET_MENU_LANGUAGE: { return "Get-Menu-Language"; } break;
case CEC::CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: { return "Give-Physical-Address"; } break; case CEC::CEC_OPCODE_REPORT_PHYSICAL_ADDRESS: { return "Report-Physical-Address"; } break;
case CEC::CEC_OPCODE_GET_MENU_LANGUAGE: { return "Get-Menu-Language"; } break; case CEC::CEC_OPCODE_SET_MENU_LANGUAGE: { return "Set-Menu-Language"; } break;
case CEC::CEC_OPCODE_REPORT_PHYSICAL_ADDRESS: { return "Report-Physical-Address"; } break; case CEC::CEC_OPCODE_DECK_CONTROL: { return "Deck-Control"; } break;
case CEC::CEC_OPCODE_SET_MENU_LANGUAGE: { return "Set-Menu-Language"; } break; case CEC::CEC_OPCODE_DECK_STATUS: { return "Deck-Status"; } break;
case CEC::CEC_OPCODE_DECK_CONTROL: { return "Deck-Control"; } break; case CEC::CEC_OPCODE_GIVE_DECK_STATUS: { return "Give-Deck-Status"; } break;
case CEC::CEC_OPCODE_DECK_STATUS: { return "Deck-Status"; } break; case CEC::CEC_OPCODE_PLAY: { return "Play"; } break;
case CEC::CEC_OPCODE_GIVE_DECK_STATUS: { return "Give-Deck-Status"; } break; case CEC::CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS: { return "Give-Tuner-Device-Status"; } break;
case CEC::CEC_OPCODE_PLAY: { return "Play"; } break; case CEC::CEC_OPCODE_SELECT_ANALOGUE_SERVICE: { return "Select-Analogue-Service"; } break;
case CEC::CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS: { return "Give-Tuner-Device-Status"; } break; case CEC::CEC_OPCODE_SELECT_DIGITAL_SERVICE: { return "Select-Digital-Service"; } break;
case CEC::CEC_OPCODE_SELECT_ANALOGUE_SERVICE: { return "Select-Analogue-Service"; } break; case CEC::CEC_OPCODE_TUNER_DEVICE_STATUS: { return "Tuner-Device-Status"; } break;
case CEC::CEC_OPCODE_SELECT_DIGITAL_SERVICE: { return "Select-Digital-Service"; } break; case CEC::CEC_OPCODE_TUNER_STEP_DECREMENT: { return "Tuner-Step-Decrement"; } break;
case CEC::CEC_OPCODE_TUNER_DEVICE_STATUS: { return "Tuner-Device-Status"; } break; case CEC::CEC_OPCODE_TUNER_STEP_INCREMENT: { return "Tuner-Step-Increment"; } break;
case CEC::CEC_OPCODE_TUNER_STEP_DECREMENT: { return "Tuner-Step-Decrement"; } break; case CEC::CEC_OPCODE_DEVICE_VENDOR_ID: { return "Device-Vendor-ID"; } break;
case CEC::CEC_OPCODE_TUNER_STEP_INCREMENT: { return "Tuner-Step-Increment"; } break; case CEC::CEC_OPCODE_GIVE_DEVICE_VENDOR_ID: { return "Give-Device-Vendor-ID"; } break;
case CEC::CEC_OPCODE_DEVICE_VENDOR_ID: { return "Device-Vendor-ID"; } break; case CEC::CEC_OPCODE_VENDOR_COMMAND: { return "Vendor-Command"; } break;
case CEC::CEC_OPCODE_GIVE_DEVICE_VENDOR_ID: { return "Give-Device-Vendor-ID"; } break; case CEC::CEC_OPCODE_VENDOR_COMMAND_WITH_ID: { return "Vendor-Command-With-ID"; } break;
case CEC::CEC_OPCODE_VENDOR_COMMAND: { return "Vendor-Command"; } break; case CEC::CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN: { return "Vendor-Remote-Button-Down"; } break;
case CEC::CEC_OPCODE_VENDOR_COMMAND_WITH_ID: { return "Vendor-Command-With-ID"; } break; case CEC::CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP: { return "Vendor-Remote-Button-Up"; } break;
case CEC::CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN: { return "Vendor-Remote-Button-Down"; } break; case CEC::CEC_OPCODE_SET_OSD_STRING: { return "Set-OSD-String"; } break;
case CEC::CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP: { return "Vendor-Remote-Button-Up"; } break; case CEC::CEC_OPCODE_GIVE_OSD_NAME: { return "Give-OSD-Name"; } break;
case CEC::CEC_OPCODE_SET_OSD_STRING: { return "Set-OSD-String"; } break; case CEC::CEC_OPCODE_SET_OSD_NAME: { return "Set-OSD-Name"; } break;
case CEC::CEC_OPCODE_GIVE_OSD_NAME: { return "Give-OSD-Name"; } break; case CEC::CEC_OPCODE_MENU_REQUEST: { return "Menu-Request"; } break;
case CEC::CEC_OPCODE_SET_OSD_NAME: { return "Set-OSD-Name"; } break; case CEC::CEC_OPCODE_MENU_STATUS: { return "Menu-Status"; } break;
case CEC::CEC_OPCODE_MENU_REQUEST: { return "Menu-Request"; } break; case CEC::CEC_OPCODE_USER_CONTROL_PRESSED: { return "User-Control-Pressed"; } break;
case CEC::CEC_OPCODE_MENU_STATUS: { return "Menu-Status"; } break; case CEC::CEC_OPCODE_USER_CONTROL_RELEASE: { return "User-Control-Release"; } break;
case CEC::CEC_OPCODE_USER_CONTROL_PRESSED: { return "User-Control-Pressed"; } break; case CEC::CEC_OPCODE_GIVE_DEVICE_POWER_STATUS: { return "Give-Device-Power-Status"; } break;
case CEC::CEC_OPCODE_USER_CONTROL_RELEASE: { return "User-Control-Release"; } break; case CEC::CEC_OPCODE_REPORT_POWER_STATUS: { return "Report-Power-Status"; } break;
case CEC::CEC_OPCODE_GIVE_DEVICE_POWER_STATUS: { return "Give-Device-Power-Status"; } break; case CEC::CEC_OPCODE_FEATURE_ABORT: { return "Feature-Abort"; } break;
case CEC::CEC_OPCODE_REPORT_POWER_STATUS: { return "Report-Power-Status"; } break; case CEC::CEC_OPCODE_ABORT: { return "Abort"; } break;
case CEC::CEC_OPCODE_FEATURE_ABORT: { return "Feature-Abort"; } break; case CEC::CEC_OPCODE_GIVE_AUDIO_STATUS: { return "Give-Audio-Status"; } break;
case CEC::CEC_OPCODE_ABORT: { return "Abort"; } break; case CEC::CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS: { return "Give-System-Audio-Mode-Status"; } break;
case CEC::CEC_OPCODE_GIVE_AUDIO_STATUS: { return "Give-Audio-Status"; } break; case CEC::CEC_OPCODE_REPORT_AUDIO_STATUS: { return "Report-Audio-Status"; } break;
case CEC::CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS: { return "Give-System-Audio-Mode-Status"; } break; case CEC::CEC_OPCODE_SET_SYSTEM_AUDIO_MODE: { return "Set-System-Audio-Mode"; } break;
case CEC::CEC_OPCODE_REPORT_AUDIO_STATUS: { return "Report-Audio-Status"; } break; case CEC::CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST: { return "System-Audio-Mode-Request"; } break;
case CEC::CEC_OPCODE_SET_SYSTEM_AUDIO_MODE: { return "Set-System-Audio-Mode"; } break; case CEC::CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS: { return "System-Audio-Mode-Status"; } break;
case CEC::CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST: { return "System-Audio-Mode-Request"; } break; case CEC::CEC_OPCODE_SET_AUDIO_RATE: { return "Set-Audio-Rate"; } break;
case CEC::CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS: { return "System-Audio-Mode-Status"; } break; case CEC::CEC_OPCODE_START_ARC: { return "Start-Arc"; } break;
case CEC::CEC_OPCODE_SET_AUDIO_RATE: { return "Set-Audio-Rate"; } break; case CEC::CEC_OPCODE_REPORT_ARC_STARTED: { return "Report-Arc-Started"; } break;
case CEC::CEC_OPCODE_START_ARC: { return "Start-Arc"; } break; case CEC::CEC_OPCODE_REPORT_ARC_ENDED: { return "Report-Arc-Ended"; } break;
case CEC::CEC_OPCODE_REPORT_ARC_STARTED: { return "Report-Arc-Started"; } break; case CEC::CEC_OPCODE_REQUEST_ARC_START: { return "Request-Arc-Start"; } break;
case CEC::CEC_OPCODE_REPORT_ARC_ENDED: { return "Report-Arc-Ended"; } break; case CEC::CEC_OPCODE_REQUEST_ARC_END: { return "Request-Arc-End"; } break;
case CEC::CEC_OPCODE_REQUEST_ARC_START: { return "Request-Arc-Start"; } break; case CEC::CEC_OPCODE_END_ARC: { return "End-Arc"; } break;
case CEC::CEC_OPCODE_REQUEST_ARC_END: { return "Request-Arc-End"; } break; case CEC::CEC_OPCODE_CDC: { return "CDC"; } break;
case CEC::CEC_OPCODE_END_ARC: { return "End-Arc"; } break; case CEC::CEC_OPCODE_NONE: { return "None"; } break;
case CEC::CEC_OPCODE_CDC: { return "CDC"; } break; #else // HAVE_LIBCEC
case CEC::CEC_OPCODE_NONE: { return "None"; } break; case 0:
#else // HAVE_LIBCEC #endif // HAVE_LIBCEC
case 0: default: { return "Unknown"; } break;
#endif // HAVE_LIBCEC }
}
default: { return "Unknown"; } break;
}
} // getOpCodeString
std::string CECInput::getKeyCodeString(const unsigned int _keyCode) std::string CECInput::getKeyCodeString(const unsigned int _keyCode)
{ {
switch(_keyCode) switch (_keyCode) {
{ #ifdef HAVE_LIBCEC
case CEC::CEC_USER_CONTROL_CODE_SELECT: { return "Select"; } break;
#ifdef HAVE_LIBCEC case CEC::CEC_USER_CONTROL_CODE_UP: { return "Up"; } break;
case CEC::CEC_USER_CONTROL_CODE_SELECT: { return "Select"; } break; case CEC::CEC_USER_CONTROL_CODE_DOWN: { return "Down"; } break;
case CEC::CEC_USER_CONTROL_CODE_UP: { return "Up"; } break; case CEC::CEC_USER_CONTROL_CODE_LEFT: { return "Left"; } break;
case CEC::CEC_USER_CONTROL_CODE_DOWN: { return "Down"; } break; case CEC::CEC_USER_CONTROL_CODE_RIGHT: { return "Right"; } break;
case CEC::CEC_USER_CONTROL_CODE_LEFT: { return "Left"; } break; case CEC::CEC_USER_CONTROL_CODE_RIGHT_UP: { return "Right-Up"; } break;
case CEC::CEC_USER_CONTROL_CODE_RIGHT: { return "Right"; } break; case CEC::CEC_USER_CONTROL_CODE_RIGHT_DOWN: { return "Right-Down"; } break;
case CEC::CEC_USER_CONTROL_CODE_RIGHT_UP: { return "Right-Up"; } break; case CEC::CEC_USER_CONTROL_CODE_LEFT_UP: { return "Left-Up"; } break;
case CEC::CEC_USER_CONTROL_CODE_RIGHT_DOWN: { return "Right-Down"; } break; case CEC::CEC_USER_CONTROL_CODE_LEFT_DOWN: { return "Left-Down"; } break;
case CEC::CEC_USER_CONTROL_CODE_LEFT_UP: { return "Left-Up"; } break; case CEC::CEC_USER_CONTROL_CODE_ROOT_MENU: { return "Root-Menu"; } break;
case CEC::CEC_USER_CONTROL_CODE_LEFT_DOWN: { return "Left-Down"; } break; case CEC::CEC_USER_CONTROL_CODE_SETUP_MENU: { return "Setup-Menu"; } break;
case CEC::CEC_USER_CONTROL_CODE_ROOT_MENU: { return "Root-Menu"; } break; case CEC::CEC_USER_CONTROL_CODE_CONTENTS_MENU: { return "Contents-Menu"; } break;
case CEC::CEC_USER_CONTROL_CODE_SETUP_MENU: { return "Setup-Menu"; } break; case CEC::CEC_USER_CONTROL_CODE_FAVORITE_MENU: { return "Favorite-Menu"; } break;
case CEC::CEC_USER_CONTROL_CODE_CONTENTS_MENU: { return "Contents-Menu"; } break; case CEC::CEC_USER_CONTROL_CODE_EXIT: { return "Exit"; } break;
case CEC::CEC_USER_CONTROL_CODE_FAVORITE_MENU: { return "Favorite-Menu"; } break; case CEC::CEC_USER_CONTROL_CODE_TOP_MENU: { return "Top-Menu"; } break;
case CEC::CEC_USER_CONTROL_CODE_EXIT: { return "Exit"; } break; case CEC::CEC_USER_CONTROL_CODE_DVD_MENU: { return "DVD-Menu"; } break;
case CEC::CEC_USER_CONTROL_CODE_TOP_MENU: { return "Top-Menu"; } break; case CEC::CEC_USER_CONTROL_CODE_NUMBER_ENTRY_MODE: { return "Number-Entry-Mode"; } break;
case CEC::CEC_USER_CONTROL_CODE_DVD_MENU: { return "DVD-Menu"; } break; case CEC::CEC_USER_CONTROL_CODE_NUMBER11: { return "Number11"; } break;
case CEC::CEC_USER_CONTROL_CODE_NUMBER_ENTRY_MODE: { return "Number-Entry-Mode"; } break; case CEC::CEC_USER_CONTROL_CODE_NUMBER12: { return "Number12"; } break;
case CEC::CEC_USER_CONTROL_CODE_NUMBER11: { return "Number11"; } break; case CEC::CEC_USER_CONTROL_CODE_NUMBER0: { return "Number0"; } break;
case CEC::CEC_USER_CONTROL_CODE_NUMBER12: { return "Number12"; } break; case CEC::CEC_USER_CONTROL_CODE_NUMBER1: { return "Number1"; } break;
case CEC::CEC_USER_CONTROL_CODE_NUMBER0: { return "Number0"; } break; case CEC::CEC_USER_CONTROL_CODE_NUMBER2: { return "Number2"; } break;
case CEC::CEC_USER_CONTROL_CODE_NUMBER1: { return "Number1"; } break; case CEC::CEC_USER_CONTROL_CODE_NUMBER3: { return "Number3"; } break;
case CEC::CEC_USER_CONTROL_CODE_NUMBER2: { return "Number2"; } break; case CEC::CEC_USER_CONTROL_CODE_NUMBER4: { return "Number4"; } break;
case CEC::CEC_USER_CONTROL_CODE_NUMBER3: { return "Number3"; } break; case CEC::CEC_USER_CONTROL_CODE_NUMBER5: { return "Number5"; } break;
case CEC::CEC_USER_CONTROL_CODE_NUMBER4: { return "Number4"; } break; case CEC::CEC_USER_CONTROL_CODE_NUMBER6: { return "Number6"; } break;
case CEC::CEC_USER_CONTROL_CODE_NUMBER5: { return "Number5"; } break; case CEC::CEC_USER_CONTROL_CODE_NUMBER7: { return "Number7"; } break;
case CEC::CEC_USER_CONTROL_CODE_NUMBER6: { return "Number6"; } break; case CEC::CEC_USER_CONTROL_CODE_NUMBER8: { return "Number8"; } break;
case CEC::CEC_USER_CONTROL_CODE_NUMBER7: { return "Number7"; } break; case CEC::CEC_USER_CONTROL_CODE_NUMBER9: { return "Number9"; } break;
case CEC::CEC_USER_CONTROL_CODE_NUMBER8: { return "Number8"; } break; case CEC::CEC_USER_CONTROL_CODE_DOT: { return "Dot"; } break;
case CEC::CEC_USER_CONTROL_CODE_NUMBER9: { return "Number9"; } break; case CEC::CEC_USER_CONTROL_CODE_ENTER: { return "Enter"; } break;
case CEC::CEC_USER_CONTROL_CODE_DOT: { return "Dot"; } break; case CEC::CEC_USER_CONTROL_CODE_CLEAR: { return "Clear"; } break;
case CEC::CEC_USER_CONTROL_CODE_ENTER: { return "Enter"; } break; case CEC::CEC_USER_CONTROL_CODE_NEXT_FAVORITE: { return "Next-Favorite"; } break;
case CEC::CEC_USER_CONTROL_CODE_CLEAR: { return "Clear"; } break; case CEC::CEC_USER_CONTROL_CODE_CHANNEL_UP: { return "Channel-Up"; } break;
case CEC::CEC_USER_CONTROL_CODE_NEXT_FAVORITE: { return "Next-Favorite"; } break; case CEC::CEC_USER_CONTROL_CODE_CHANNEL_DOWN: { return "Channel-Down"; } break;
case CEC::CEC_USER_CONTROL_CODE_CHANNEL_UP: { return "Channel-Up"; } break; case CEC::CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL: { return "Previous-Channel"; } break;
case CEC::CEC_USER_CONTROL_CODE_CHANNEL_DOWN: { return "Channel-Down"; } break; case CEC::CEC_USER_CONTROL_CODE_SOUND_SELECT: { return "Sound-Select"; } break;
case CEC::CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL: { return "Previous-Channel"; } break; case CEC::CEC_USER_CONTROL_CODE_INPUT_SELECT: { return "Input-Select"; } break;
case CEC::CEC_USER_CONTROL_CODE_SOUND_SELECT: { return "Sound-Select"; } break; case CEC::CEC_USER_CONTROL_CODE_DISPLAY_INFORMATION: { return "Display-Information"; } break;
case CEC::CEC_USER_CONTROL_CODE_INPUT_SELECT: { return "Input-Select"; } break; case CEC::CEC_USER_CONTROL_CODE_HELP: { return "Help"; } break;
case CEC::CEC_USER_CONTROL_CODE_DISPLAY_INFORMATION: { return "Display-Information"; } break; case CEC::CEC_USER_CONTROL_CODE_PAGE_UP: { return "Page-Up"; } break;
case CEC::CEC_USER_CONTROL_CODE_HELP: { return "Help"; } break; case CEC::CEC_USER_CONTROL_CODE_PAGE_DOWN: { return "Page-Down"; } break;
case CEC::CEC_USER_CONTROL_CODE_PAGE_UP: { return "Page-Up"; } break; case CEC::CEC_USER_CONTROL_CODE_POWER: { return "Power"; } break;
case CEC::CEC_USER_CONTROL_CODE_PAGE_DOWN: { return "Page-Down"; } break; case CEC::CEC_USER_CONTROL_CODE_VOLUME_UP: { return "Volume-Up"; } break;
case CEC::CEC_USER_CONTROL_CODE_POWER: { return "Power"; } break; case CEC::CEC_USER_CONTROL_CODE_VOLUME_DOWN: { return "Volume-Down"; } break;
case CEC::CEC_USER_CONTROL_CODE_VOLUME_UP: { return "Volume-Up"; } break; case CEC::CEC_USER_CONTROL_CODE_MUTE: { return "Mute"; } break;
case CEC::CEC_USER_CONTROL_CODE_VOLUME_DOWN: { return "Volume-Down"; } break; case CEC::CEC_USER_CONTROL_CODE_PLAY: { return "Play"; } break;
case CEC::CEC_USER_CONTROL_CODE_MUTE: { return "Mute"; } break; case CEC::CEC_USER_CONTROL_CODE_STOP: { return "Stop"; } break;
case CEC::CEC_USER_CONTROL_CODE_PLAY: { return "Play"; } break; case CEC::CEC_USER_CONTROL_CODE_PAUSE: { return "Pause"; } break;
case CEC::CEC_USER_CONTROL_CODE_STOP: { return "Stop"; } break; case CEC::CEC_USER_CONTROL_CODE_RECORD: { return "Record"; } break;
case CEC::CEC_USER_CONTROL_CODE_PAUSE: { return "Pause"; } break; case CEC::CEC_USER_CONTROL_CODE_REWIND: { return "Rewind"; } break;
case CEC::CEC_USER_CONTROL_CODE_RECORD: { return "Record"; } break; case CEC::CEC_USER_CONTROL_CODE_FAST_FORWARD: { return "Fast-Forward"; } break;
case CEC::CEC_USER_CONTROL_CODE_REWIND: { return "Rewind"; } break; case CEC::CEC_USER_CONTROL_CODE_EJECT: { return "Eject"; } break;
case CEC::CEC_USER_CONTROL_CODE_FAST_FORWARD: { return "Fast-Forward"; } break; case CEC::CEC_USER_CONTROL_CODE_FORWARD: { return "Forward"; } break;
case CEC::CEC_USER_CONTROL_CODE_EJECT: { return "Eject"; } break; case CEC::CEC_USER_CONTROL_CODE_BACKWARD: { return "Backward"; } break;
case CEC::CEC_USER_CONTROL_CODE_FORWARD: { return "Forward"; } break; case CEC::CEC_USER_CONTROL_CODE_STOP_RECORD: { return "Stop-Record"; } break;
case CEC::CEC_USER_CONTROL_CODE_BACKWARD: { return "Backward"; } break; case CEC::CEC_USER_CONTROL_CODE_PAUSE_RECORD: { return "Pause-Record"; } break;
case CEC::CEC_USER_CONTROL_CODE_STOP_RECORD: { return "Stop-Record"; } break; case CEC::CEC_USER_CONTROL_CODE_ANGLE: { return "Angle"; } break;
case CEC::CEC_USER_CONTROL_CODE_PAUSE_RECORD: { return "Pause-Record"; } break; case CEC::CEC_USER_CONTROL_CODE_SUB_PICTURE: { return "Sub-Picture"; } break;
case CEC::CEC_USER_CONTROL_CODE_ANGLE: { return "Angle"; } break; case CEC::CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND: { return "Video-On-Demand"; } break;
case CEC::CEC_USER_CONTROL_CODE_SUB_PICTURE: { return "Sub-Picture"; } break; case CEC::CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE: { return "Electronic-Program-Guide"; } break;
case CEC::CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND: { return "Video-On-Demand"; } break; case CEC::CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING: { return "Timer-Programming"; } break;
case CEC::CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE: { return "Electronic-Program-Guide"; } break; case CEC::CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION: { return "Initial-Configuration"; } break;
case CEC::CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING: { return "Timer-Programming"; } break; case CEC::CEC_USER_CONTROL_CODE_SELECT_BROADCAST_TYPE: { return "Select-Broadcast-Type"; } break;
case CEC::CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION: { return "Initial-Configuration"; } break; case CEC::CEC_USER_CONTROL_CODE_SELECT_SOUND_PRESENTATION: { return "Select-Sound-Presentation"; } break;
case CEC::CEC_USER_CONTROL_CODE_SELECT_BROADCAST_TYPE: { return "Select-Broadcast-Type"; } break; case CEC::CEC_USER_CONTROL_CODE_PLAY_FUNCTION: { return "Play-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_SELECT_SOUND_PRESENTATION: { return "Select-Sound-Presentation"; } break; case CEC::CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION: { return "Pause-Play-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_PLAY_FUNCTION: { return "Play-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_RECORD_FUNCTION: { return "Record-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION: { return "Pause-Play-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_PAUSE_RECORD_FUNCTION: { return "Pause-Record-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_RECORD_FUNCTION: { return "Record-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_STOP_FUNCTION: { return "Stop-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_PAUSE_RECORD_FUNCTION: { return "Pause-Record-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_MUTE_FUNCTION: { return "Mute-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_STOP_FUNCTION: { return "Stop-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_RESTORE_VOLUME_FUNCTION: { return "Restore-Volume-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_MUTE_FUNCTION: { return "Mute-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_TUNE_FUNCTION: { return "Tune-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_RESTORE_VOLUME_FUNCTION: { return "Restore-Volume-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_SELECT_MEDIA_FUNCTION: { return "Select-Media-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_TUNE_FUNCTION: { return "Tune-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_SELECT_AV_INPUT_FUNCTION: { return "Select-AV-Input-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_SELECT_MEDIA_FUNCTION: { return "Select-Media-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_SELECT_AUDIO_INPUT_FUNCTION: { return "Select-Audio-Input-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_SELECT_AV_INPUT_FUNCTION: { return "Select-AV-Input-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION: { return "Power-Toggle-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_SELECT_AUDIO_INPUT_FUNCTION: { return "Select-Audio-Input-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION: { return "Power-Off-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION: { return "Power-Toggle-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION: { return "Power-On-Function"; } break;
case CEC::CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION: { return "Power-Off-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_F1_BLUE: { return "F1-Blue"; } break;
case CEC::CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION: { return "Power-On-Function"; } break; case CEC::CEC_USER_CONTROL_CODE_F2_RED: { return "F2-Red"; } break;
case CEC::CEC_USER_CONTROL_CODE_F1_BLUE: { return "F1-Blue"; } break; case CEC::CEC_USER_CONTROL_CODE_F3_GREEN: { return "F3-Green"; } break;
case CEC::CEC_USER_CONTROL_CODE_F2_RED: { return "F2-Red"; } break; case CEC::CEC_USER_CONTROL_CODE_F4_YELLOW: { return "F4-Yellow"; } break;
case CEC::CEC_USER_CONTROL_CODE_F3_GREEN: { return "F3-Green"; } break; case CEC::CEC_USER_CONTROL_CODE_F5: { return "F5"; } break;
case CEC::CEC_USER_CONTROL_CODE_F4_YELLOW: { return "F4-Yellow"; } break; case CEC::CEC_USER_CONTROL_CODE_DATA: { return "Data"; } break;
case CEC::CEC_USER_CONTROL_CODE_F5: { return "F5"; } break; case CEC::CEC_USER_CONTROL_CODE_AN_RETURN: { return "AN-Return"; } break;
case CEC::CEC_USER_CONTROL_CODE_DATA: { return "Data"; } break; case CEC::CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST: { return "AN-Channels-List"; } break;
case CEC::CEC_USER_CONTROL_CODE_AN_RETURN: { return "AN-Return"; } break; #else // HAVE_LIBCEC
case CEC::CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST: { return "AN-Channels-List"; } break; case 0:
#else // HAVE_LIBCEC #endif // HAVE_LIBCEC
case 0: default: { return "Unknown"; } break;
#endif // HAVE_LIBCEC }
}
default: { return "Unknown"; } break;
}
} // getKeyCodeString

View file

@ -1,3 +1,9 @@
//
// CECInput.h
//
// CEC (Consumer Electronics Control).
//
#pragma once #pragma once
#ifndef ES_CORE_CECINPUT_H #ifndef ES_CORE_CECINPUT_H
#define ES_CORE_CECINPUT_H #define ES_CORE_CECINPUT_H
@ -9,22 +15,19 @@ namespace CEC { class ICECAdapter; }
class CECInput class CECInput
{ {
public: public:
static void init();
static void init (); static void deinit();
static void deinit (); static std::string getAlertTypeString(const unsigned int _type);
static std::string getAlertTypeString(const unsigned int _type); static std::string getOpCodeString(const unsigned int _opCode);
static std::string getOpCodeString (const unsigned int _opCode); static std::string getKeyCodeString(const unsigned int _keyCode);
static std::string getKeyCodeString (const unsigned int _keyCode);
private: private:
CECInput();
~CECInput();
CECInput(); static CECInput* sInstance;
~CECInput();
static CECInput* sInstance; CEC::ICECAdapter* mlibCEC;
};
CEC::ICECAdapter* mlibCEC;
}; // CECInput
#endif // ES_CORE_CECINPUT_H #endif // ES_CORE_CECINPUT_H

View file

@ -1,3 +1,9 @@
//
// HelpPrompt.h
//
// Definition of the pair used by help prompts to display a button and its mapped function.
//
#pragma once #pragma once
#ifndef ES_CORE_HELP_PROMPT_H #ifndef ES_CORE_HELP_PROMPT_H
#define ES_CORE_HELP_PROMPT_H #define ES_CORE_HELP_PROMPT_H

View file

@ -1,38 +1,46 @@
//
// HelpStyle.cpp
//
// Style (default colors, position and origin) for the help system.
// Also theme handling.
//
#include "HelpStyle.h" #include "HelpStyle.h"
#include "resources/Font.h" #include "resources/Font.h"
HelpStyle::HelpStyle() HelpStyle::HelpStyle()
{ {
position = Vector2f(Renderer::getScreenWidth() * 0.012f, Renderer::getScreenHeight() * 0.9515f); position = Vector2f(Renderer::getScreenWidth() * 0.012f, Renderer::getScreenHeight() * 0.9515f);
origin = Vector2f(0.0f, 0.0f); origin = Vector2f(0.0f, 0.0f);
iconColor = 0x777777FF; iconColor = 0x777777FF;
textColor = 0x777777FF; textColor = 0x777777FF;
if(FONT_SIZE_SMALL != 0) if(FONT_SIZE_SMALL != 0)
font = Font::get(FONT_SIZE_SMALL); font = Font::get(FONT_SIZE_SMALL);
else else
font = nullptr; font = nullptr;
} }
void HelpStyle::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view) void HelpStyle::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view)
{ {
auto elem = theme->getElement(view, "help", "helpsystem"); auto elem = theme->getElement(view, "help", "helpsystem");
if(!elem) if(!elem)
return; return;
if(elem->has("pos")) if(elem->has("pos"))
position = elem->get<Vector2f>("pos") * Vector2f((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight()); position = elem->get<Vector2f>("pos") *
Vector2f((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
if(elem->has("origin")) if(elem->has("origin"))
origin = elem->get<Vector2f>("origin"); origin = elem->get<Vector2f>("origin");
if(elem->has("textColor")) if(elem->has("textColor"))
textColor = elem->get<unsigned int>("textColor"); textColor = elem->get<unsigned int>("textColor");
if(elem->has("iconColor")) if(elem->has("iconColor"))
iconColor = elem->get<unsigned int>("iconColor"); iconColor = elem->get<unsigned int>("iconColor");
if(elem->has("fontPath") || elem->has("fontSize")) if(elem->has("fontPath") || elem->has("fontSize"))
font = Font::getFromTheme(elem, ThemeFlags::ALL, font); font = Font::getFromTheme(elem, ThemeFlags::ALL, font);
} }

View file

@ -1,3 +1,10 @@
//
// HelpStyle.h
//
// Style (default colors, position and origin) for the help system.
// Also theme handling.
//
#pragma once #pragma once
#ifndef ES_CORE_HELP_STYLE_H #ifndef ES_CORE_HELP_STYLE_H
#define ES_CORE_HELP_STYLE_H #define ES_CORE_HELP_STYLE_H
@ -9,16 +16,15 @@
class Font; class Font;
class ThemeData; class ThemeData;
struct HelpStyle struct HelpStyle {
{ Vector2f position;
Vector2f position; Vector2f origin;
Vector2f origin; unsigned int iconColor;
unsigned int iconColor; unsigned int textColor;
unsigned int textColor; std::shared_ptr<Font> font;
std::shared_ptr<Font> font;
HelpStyle(); // default values HelpStyle(); // Default values.
void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view); void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view);
}; };
#endif // ES_CORE_HELP_STYLE_H #endif // ES_CORE_HELP_STYLE_H

View file

@ -1,90 +1,88 @@
//
// ImageIO.cpp
//
// Image I/O functions.
//
#include "ImageIO.h" #include "ImageIO.h"
#include "Log.h" #include "Log.h"
#include <FreeImage.h> #include <FreeImage.h>
#include <string.h> #include <string.h>
std::vector<unsigned char> ImageIO::loadFromMemoryRGBA32(const unsigned char * data, const size_t size, size_t & width, size_t & height) std::vector<unsigned char> ImageIO::loadFromMemoryRGBA32(const unsigned char * data,
const size_t size, size_t & width, size_t & height)
{ {
std::vector<unsigned char> rawData; std::vector<unsigned char> rawData;
width = 0; width = 0;
height = 0; height = 0;
FIMEMORY * fiMemory = FreeImage_OpenMemory((BYTE *)data, (DWORD)size); FIMEMORY * fiMemory = FreeImage_OpenMemory((BYTE *)data, (DWORD)size);
if (fiMemory != nullptr) {
//detect the filetype from data if (fiMemory != nullptr) {
FREE_IMAGE_FORMAT format = FreeImage_GetFileTypeFromMemory(fiMemory); // Detect the filetype from data.
if (format != FIF_UNKNOWN && FreeImage_FIFSupportsReading(format)) FREE_IMAGE_FORMAT format = FreeImage_GetFileTypeFromMemory(fiMemory);
{ if (format != FIF_UNKNOWN && FreeImage_FIFSupportsReading(format)) {
//file type is supported. load image // File type is supported. load image,
FIBITMAP * fiBitmap = FreeImage_LoadFromMemory(format, fiMemory); FIBITMAP * fiBitmap = FreeImage_LoadFromMemory(format, fiMemory);
if (fiBitmap != nullptr) if (fiBitmap != nullptr) {
{ // Loaded. convert to 32bit if necessary.
//loaded. convert to 32bit if necessary if (FreeImage_GetBPP(fiBitmap) != 32) {
if (FreeImage_GetBPP(fiBitmap) != 32) FIBITMAP * fiConverted = FreeImage_ConvertTo32Bits(fiBitmap);
{ if (fiConverted != nullptr) {
FIBITMAP * fiConverted = FreeImage_ConvertTo32Bits(fiBitmap); //free original bitmap data
if (fiConverted != nullptr) FreeImage_Unload(fiBitmap);
{ fiBitmap = fiConverted;
//free original bitmap data }
FreeImage_Unload(fiBitmap); }
fiBitmap = fiConverted; if (fiBitmap != nullptr) {
} width = FreeImage_GetWidth(fiBitmap);
} height = FreeImage_GetHeight(fiBitmap);
if (fiBitmap != nullptr) // Loop through scanlines and add all pixel data to the return vector.
{ // This is necessary, because width*height*bpp might not be == pitch.
width = FreeImage_GetWidth(fiBitmap); unsigned char * tempData = new unsigned char[width * height * 4];
height = FreeImage_GetHeight(fiBitmap); for (size_t i = 0; i < height; i++) {
//loop through scanlines and add all pixel data to the return vector const BYTE * scanLine = FreeImage_GetScanLine(fiBitmap, (int)i);
//this is necessary, because width*height*bpp might not be == pitch memcpy(tempData + (i * width * 4), scanLine, width * 4);
unsigned char * tempData = new unsigned char[width * height * 4]; }
for (size_t i = 0; i < height; i++) // Convert from BGRA to RGBA.
{ for (size_t i = 0; i < width*height; i++) {
const BYTE * scanLine = FreeImage_GetScanLine(fiBitmap, (int)i); RGBQUAD bgra = ((RGBQUAD *)tempData)[i];
memcpy(tempData + (i * width * 4), scanLine, width * 4); RGBQUAD rgba;
} rgba.rgbBlue = bgra.rgbRed;
//convert from BGRA to RGBA rgba.rgbGreen = bgra.rgbGreen;
for(size_t i = 0; i < width*height; i++) rgba.rgbRed = bgra.rgbBlue;
{ rgba.rgbReserved = bgra.rgbReserved;
RGBQUAD bgra = ((RGBQUAD *)tempData)[i]; ((RGBQUAD *)tempData)[i] = rgba;
RGBQUAD rgba; }
rgba.rgbBlue = bgra.rgbRed; rawData = std::vector<unsigned char>(tempData, tempData + width * height * 4);
rgba.rgbGreen = bgra.rgbGreen; // Free bitmap data.
rgba.rgbRed = bgra.rgbBlue; FreeImage_Unload(fiBitmap);
rgba.rgbReserved = bgra.rgbReserved; delete[] tempData;
((RGBQUAD *)tempData)[i] = rgba; }
} }
rawData = std::vector<unsigned char>(tempData, tempData + width * height * 4); else {
//free bitmap data LOG(LogError) << "Error - Failed to load image from memory!";
FreeImage_Unload(fiBitmap); }
delete[] tempData; }
} else {
} LOG(LogError) << "Error - File type " <<
else (format == FIF_UNKNOWN ? "unknown" : "unsupported") << "!";
{ }
LOG(LogError) << "Error - Failed to load image from memory!"; // Free fiMemory again
} FreeImage_CloseMemory(fiMemory);
} }
else return rawData;
{
LOG(LogError) << "Error - File type " << (format == FIF_UNKNOWN ? "unknown" : "unsupported") << "!";
}
//free FIMEMORY again
FreeImage_CloseMemory(fiMemory);
}
return rawData;
} }
void ImageIO::flipPixelsVert(unsigned char* imagePx, const size_t& width, const size_t& height) void ImageIO::flipPixelsVert(unsigned char* imagePx, const size_t& width, const size_t& height)
{ {
unsigned int temp; unsigned int temp;
unsigned int* arr = (unsigned int*)imagePx; unsigned int* arr = (unsigned int*)imagePx;
for(size_t y = 0; y < height / 2; y++) for (size_t y = 0; y < height / 2; y++) {
{ for (size_t x = 0; x < width; x++) {
for(size_t x = 0; x < width; x++) temp = arr[x + (y * width)];
{ arr[x + (y * width)] = arr[x + (height * width) - ((y + 1) * width)];
temp = arr[x + (y * width)]; arr[x + (height * width) - ((y + 1) * width)] = temp;
arr[x + (y * width)] = arr[x + (height * width) - ((y + 1) * width)]; }
arr[x + (height * width) - ((y + 1) * width)] = temp; }
}
}
} }

View file

@ -1,3 +1,9 @@
//
// ImageIO.h
//
// Image I/O functions.
//
#pragma once #pragma once
#ifndef ES_CORE_IMAGE_IO #ifndef ES_CORE_IMAGE_IO
#define ES_CORE_IMAGE_IO #define ES_CORE_IMAGE_IO
@ -8,8 +14,9 @@
class ImageIO class ImageIO
{ {
public: public:
static std::vector<unsigned char> loadFromMemoryRGBA32(const unsigned char * data, const size_t size, size_t & width, size_t & height); static std::vector<unsigned char> loadFromMemoryRGBA32(const unsigned char * data,
static void flipPixelsVert(unsigned char* imagePx, const size_t& width, const size_t& height); const size_t size, size_t & width, size_t & height);
static void flipPixelsVert(unsigned char* imagePx, const size_t& width, const size_t& height);
}; };
#endif // ES_CORE_IMAGE_IO #endif // ES_CORE_IMAGE_IO

View file

@ -1,3 +1,4 @@
//
// InputManager.cpp // InputManager.cpp
// //
// Low-level input handling. // Low-level input handling.

View file

@ -1,83 +1,89 @@
//
// Log.cpp
//
// Log handling.
//
#include "Log.h" #include "Log.h"
#include "utils/FileSystemUtil.h" #include "utils/FileSystemUtil.h"
#include "Platform.h" #include "Platform.h"
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
LogLevel Log::reportingLevel = LogInfo; LogLevel Log::reportingLevel = LogInfo;
FILE* Log::file = NULL; //fopen(getLogPath().c_str(), "w"); FILE* Log::file = nullptr; // fopen(getLogPath().c_str(), "w");
LogLevel Log::getReportingLevel() LogLevel Log::getReportingLevel()
{ {
return reportingLevel; return reportingLevel;
} }
std::string Log::getLogPath() std::string Log::getLogPath()
{ {
std::string home = Utils::FileSystem::getHomePath(); return Utils::FileSystem::getHomePath() + "/.emulationstation/es_log.txt";
return home + "/.emulationstation/es_log.txt";
} }
void Log::setReportingLevel(LogLevel level) void Log::setReportingLevel(LogLevel level)
{ {
reportingLevel = level; reportingLevel = level;
} }
void Log::init() void Log::init()
{ {
remove((getLogPath() + ".bak").c_str()); remove((getLogPath() + ".bak").c_str());
// rename previous log file // Rename previous log file.
rename(getLogPath().c_str(), (getLogPath() + ".bak").c_str()); rename(getLogPath().c_str(), (getLogPath() + ".bak").c_str());
return; return;
} }
void Log::open() void Log::open()
{ {
file = fopen(getLogPath().c_str(), "w"); file = fopen(getLogPath().c_str(), "w");
} }
std::ostringstream& Log::get(LogLevel level) std::ostringstream& Log::get(LogLevel level)
{ {
time_t t = time(nullptr); time_t t = time(nullptr);
os << std::put_time(localtime(&t), "%b %d %T ") << "lvl" << level << ": \t"; os << std::put_time(localtime(&t), "%b %d %T ") << "lvl" << level << ": \t";
messageLevel = level; messageLevel = level;
return os; return os;
} }
void Log::flush() void Log::flush()
{ {
fflush(getOutput()); fflush(getOutput());
} }
void Log::close() void Log::close()
{ {
fclose(file); fclose(file);
file = NULL; file = nullptr;
} }
FILE* Log::getOutput() FILE* Log::getOutput()
{ {
return file; return file;
} }
Log::~Log() Log::~Log()
{ {
os << std::endl; os << std::endl;
if(getOutput() == NULL) if (getOutput() == nullptr) {
{ // not open yet, print to stdout
// not open yet, print to stdout std::cerr << "ERROR - tried to write to log file before it was open! "
std::cerr << "ERROR - tried to write to log file before it was open! The following won't be logged:\n"; "The following won't be logged:\n";
std::cerr << os.str(); std::cerr << os.str();
return; return;
} }
fprintf(getOutput(), "%s", os.str().c_str()); fprintf(getOutput(), "%s", os.str().c_str());
//if it's an error, also print to console // If it's an error, also print to console.
//print all messages if using --debug // Print all messages if using --debug.
if(messageLevel == LogError || reportingLevel >= LogDebug) if (messageLevel == LogError || reportingLevel >= LogDebug)
fprintf(stderr, "%s", os.str().c_str()); fprintf(stderr, "%s", os.str().c_str());
} }

View file

@ -1,3 +1,9 @@
//
// Log.h
//
// Log handling.
//
#pragma once #pragma once
#ifndef ES_CORE_LOG_H #ifndef ES_CORE_LOG_H
#define ES_CORE_LOG_H #define ES_CORE_LOG_H
@ -8,31 +14,38 @@
if(level > Log::getReportingLevel()); \ if(level > Log::getReportingLevel()); \
else Log().get(level) else Log().get(level)
enum LogLevel { LogError, LogWarning, LogInfo, LogDebug }; enum LogLevel {
LogError,
LogWarning,
LogInfo,
LogDebug
};
class Log class Log
{ {
public: public:
//Log(); //Log();
~Log(); ~Log();
std::ostringstream& get(LogLevel level = LogInfo); std::ostringstream& get(LogLevel level = LogInfo);
static LogLevel getReportingLevel(); static LogLevel getReportingLevel();
static void setReportingLevel(LogLevel level); static void setReportingLevel(LogLevel level);
static std::string getLogPath(); static std::string getLogPath();
static void flush();
static void init();
static void open();
static void close();
static void flush();
static void init();
static void open();
static void close();
protected: protected:
std::ostringstream os; std::ostringstream os;
static FILE* file; static FILE* file;
private: private:
static LogLevel reportingLevel; static LogLevel reportingLevel;
static FILE* getOutput(); static FILE* getOutput();
LogLevel messageLevel; LogLevel messageLevel;
}; };
#endif // ES_CORE_LOG_H #endif // ES_CORE_LOG_H

View file

@ -89,7 +89,7 @@ MameNames::MameNames()
mMameBioses.push_back(bios); mMameBioses.push_back(bios);
} }
// Read devices file. // Read device file.
xmlpath = ResourceManager::getInstance()->getResourcePath(":/MAME/mamedevices.xml"); xmlpath = ResourceManager::getInstance()->getResourcePath(":/MAME/mamedevices.xml");
if (!Utils::FileSystem::exists(xmlpath)) if (!Utils::FileSystem::exists(xmlpath))
@ -110,8 +110,7 @@ MameNames::MameNames()
std::string device = deviceNode.text().get(); std::string device = deviceNode.text().get();
mMameDevices.push_back(device); mMameDevices.push_back(device);
} }
}
} // MameNames.
MameNames::~MameNames() MameNames::~MameNames()
{ {

View file

@ -18,17 +18,15 @@
class MameNames class MameNames
{ {
public: public:
static void init();
static void init (); static void deinit();
static void deinit ();
static MameNames* getInstance(); static MameNames* getInstance();
std::string getRealName(const std::string& _mameName); std::string getRealName(const std::string& _mameName);
std::string getCleanName(const std::string& _mameName); std::string getCleanName(const std::string& _mameName);
const bool isBios(const std::string& _biosName); const bool isBios(const std::string& _biosName);
const bool isDevice(const std::string& _deviceName); const bool isDevice(const std::string& _deviceName);
private: private:
struct NamePair { struct NamePair {
std::string mameName; std::string mameName;
std::string realName; std::string realName;
@ -46,7 +44,6 @@ private:
std::vector<std::string> mMameDevices; std::vector<std::string> mMameDevices;
const bool find(const std::vector<std::string> devices, const std::string& name); const bool find(const std::vector<std::string> devices, const std::string& name);
};
}; // MameNames
#endif // ES_CORE_MAMENAMES_H #endif // ES_CORE_MAMENAMES_H

View file

@ -1,3 +1,9 @@
//
// PowerSaver.cpp
//
// Power saving functions.
//
#include "PowerSaver.h" #include "PowerSaver.h"
#include "AudioManager.h" #include "AudioManager.h"
@ -12,81 +18,83 @@ PowerSaver::mode PowerSaver::mMode = PowerSaver::DISABLED;
void PowerSaver::init() void PowerSaver::init()
{ {
setState(true); setState(true);
updateMode(); updateMode();
} }
int PowerSaver::getTimeout() int PowerSaver::getTimeout()
{ {
if (SDL_GetAudioStatus() == SDL_AUDIO_PAUSED) if (SDL_GetAudioStatus() == SDL_AUDIO_PAUSED)
AudioManager::getInstance()->deinit(); AudioManager::getInstance()->deinit();
// Used only for SDL_WaitEventTimeout. Use `getMode()` for modes. // Used only for SDL_WaitEventTimeout. Use `getMode()` for modes.
return mRunningScreenSaver ? mWakeupTimeout : mScreenSaverTimeout; return mRunningScreenSaver ? mWakeupTimeout : mScreenSaverTimeout;
} }
void PowerSaver::loadWakeupTime() void PowerSaver::loadWakeupTime()
{ {
// TODO : Move this to Screensaver Class // TODO : Move this to Screensaver Class.
std::string behaviour = Settings::getInstance()->getString("ScreenSaverBehavior"); std::string behaviour = Settings::getInstance()->getString("ScreenSaverBehavior");
if (behaviour == "random video") if (behaviour == "random video")
mWakeupTimeout = Settings::getInstance()->getInt("ScreenSaverSwapVideoTimeout") - getMode(); mWakeupTimeout = Settings::getInstance()->getInt("ScreenSaverSwapVideoTimeout") - getMode();
else if (behaviour == "slideshow") else if (behaviour == "slideshow")
mWakeupTimeout = Settings::getInstance()->getInt("ScreenSaverSwapImageTimeout") - getMode(); mWakeupTimeout = Settings::getInstance()->getInt("ScreenSaverSwapImageTimeout") - getMode();
else // Dim and Blank else // Dim and Blank.
mWakeupTimeout = -1; mWakeupTimeout = -1;
} }
void PowerSaver::updateTimeouts() void PowerSaver::updateTimeouts()
{ {
mScreenSaverTimeout = (unsigned int) Settings::getInstance()->getInt("ScreenSaverTime"); mScreenSaverTimeout = (unsigned int) Settings::getInstance()->getInt("ScreenSaverTime");
mScreenSaverTimeout = mScreenSaverTimeout > 0 ? mScreenSaverTimeout - getMode() : -1; mScreenSaverTimeout = mScreenSaverTimeout > 0 ? mScreenSaverTimeout - getMode() : -1;
loadWakeupTime(); loadWakeupTime();
} }
PowerSaver::mode PowerSaver::getMode() PowerSaver::mode PowerSaver::getMode()
{ {
return mMode; return mMode;
} }
void PowerSaver::updateMode() void PowerSaver::updateMode()
{ {
std::string mode = Settings::getInstance()->getString("PowerSaverMode"); std::string mode = Settings::getInstance()->getString("PowerSaverMode");
if (mode == "disabled") { if (mode == "disabled") {
mMode = DISABLED; mMode = DISABLED;
} else if (mode == "instant") { }
mMode = INSTANT; else if (mode == "instant") {
} else if (mode == "enhanced") { mMode = INSTANT;
mMode = ENHANCED; }
} else { else if (mode == "enhanced") {
mMode = DEFAULT; mMode = ENHANCED;
} }
updateTimeouts(); else {
mMode = DEFAULT;
}
updateTimeouts();
} }
bool PowerSaver::getState() bool PowerSaver::getState()
{ {
return mState; return mState;
} }
void PowerSaver::setState(bool state) void PowerSaver::setState(bool state)
{ {
bool ps_enabled = Settings::getInstance()->getString("PowerSaverMode") != "disabled"; bool ps_enabled = Settings::getInstance()->getString("PowerSaverMode") != "disabled";
mState = ps_enabled && state; mState = ps_enabled && state;
} }
void PowerSaver::runningScreenSaver(bool state) void PowerSaver::runningScreenSaver(bool state)
{ {
mRunningScreenSaver = state; mRunningScreenSaver = state;
if (mWakeupTimeout < mMode) if (mWakeupTimeout < mMode) {
{ // Disable PS if wake up time is less than mode as PS will never trigger.
// Disable PS if wake up time is less than mode as PS will never trigger setState(!state);
setState(!state); }
}
} }
bool PowerSaver::isScreenSaverActive() bool PowerSaver::isScreenSaverActive()
{ {
return mRunningScreenSaver; return mRunningScreenSaver;
} }

View file

@ -1,3 +1,9 @@
//
// PowerSaver.h
//
// Power saving functions.
//
#pragma once #pragma once
#ifndef ES_CORE_POWER_SAVER_H #ifndef ES_CORE_POWER_SAVER_H
#define ES_CORE_POWER_SAVER_H #define ES_CORE_POWER_SAVER_H
@ -5,44 +11,49 @@
class PowerSaver class PowerSaver
{ {
public: public:
enum mode : int { DISABLED = -1, INSTANT = 200, ENHANCED = 3000, DEFAULT = 10000 }; enum mode : int {
DISABLED = -1,
INSTANT = 200,
ENHANCED = 3000,
DEFAULT = 10000
};
// Call when you want PS to reload all state and settings // Call when you want PS to reload all states and settings.
static void init(); static void init();
// Get timeout to wake up from for the next event // Get timeout to wake up from for the next event.
static int getTimeout(); static int getTimeout();
// Update currently set timeouts after User changes Timeout settings // Update currently set timeouts after user changes timeout settings.
static void updateTimeouts(); static void updateTimeouts();
// Use this to check which mode you are in or get the mode timeout // Use this to check which mode you are in or get the mode timeout.
static mode getMode(); static mode getMode();
// Called when user changes mode from Settings // Called when user changes mode from settings menu.
static void updateMode(); static void updateMode();
// Get current state of PS. Not to be confused with Mode // Get current state of PS. Not to be confused with mode.
static bool getState(); static bool getState();
// State is used to temporarily pause and resume PS // State is used to temporarily pause and resume PS.
static void setState(bool state); static void setState(bool state);
// Paired calls when you want to pause PS briefly till you finish animating // Paired calls when you want to pause PS briefly until you finish animating
// or processing over cycles // or processing over cycles.
static void pause() { setState(false); } static void pause() { setState(false); }
static void resume() { setState(true); } static void resume() { setState(true); }
// This is used by ScreenSaver to let PS know when to switch to SS timeouts // This is used by ScreenSaver to let PS know when to switch to SS timeouts.
static void runningScreenSaver(bool state); static void runningScreenSaver(bool state);
static bool isScreenSaverActive(); static bool isScreenSaverActive();
private: private:
static bool mState; static bool mState;
static bool mRunningScreenSaver; static bool mRunningScreenSaver;
static mode mMode; static mode mMode;
static int mWakeupTimeout; static int mWakeupTimeout;
static int mScreenSaverTimeout; static int mScreenSaverTimeout;
static void loadWakeupTime(); static void loadWakeupTime();
}; };
#endif // ES_CORE_POWER_SAVER_H #endif // ES_CORE_POWER_SAVER_H

View file

@ -1,3 +1,9 @@
//
// Animation.h
//
// Animation base class.
//
#pragma once #pragma once
#ifndef ES_CORE_ANIMATIONS_ANIMATION_H #ifndef ES_CORE_ANIMATIONS_ANIMATION_H
#define ES_CORE_ANIMATIONS_ANIMATION_H #define ES_CORE_ANIMATIONS_ANIMATION_H
@ -5,9 +11,9 @@
class Animation class Animation
{ {
public: public:
virtual ~Animation() {}; virtual ~Animation() {};
virtual int getDuration() const = 0; virtual int getDuration() const = 0;
virtual void apply(float t) = 0; virtual void apply(float t) = 0;
}; };
#endif // ES_CORE_ANIMATIONS_ANIMATION_H #endif // ES_CORE_ANIMATIONS_ANIMATION_H

View file

@ -1,38 +1,52 @@
//
// AnimationController.cpp
//
// Basic animation controls.
//
#include "animations/AnimationController.h" #include "animations/AnimationController.h"
#include "animations/Animation.h" #include "animations/Animation.h"
AnimationController::AnimationController(Animation* anim, int delay, std::function<void()> finishedCallback, bool reverse) AnimationController::AnimationController(
: mAnimation(anim), mFinishedCallback(finishedCallback), mReverse(reverse), mTime(-delay), mDelay(delay) Animation* anim,
int delay,
std::function<void()> finishedCallback,
bool reverse)
: mAnimation(anim),
mFinishedCallback(finishedCallback),
mReverse(reverse),
mTime(-delay),
mDelay(delay)
{ {
} }
AnimationController::~AnimationController() AnimationController::~AnimationController()
{ {
if(mFinishedCallback) if (mFinishedCallback)
mFinishedCallback(); mFinishedCallback();
delete mAnimation; delete mAnimation;
} }
bool AnimationController::update(int deltaTime) bool AnimationController::update(int deltaTime)
{ {
mTime += deltaTime; mTime += deltaTime;
if(mTime < 0) // are we still in delay? if(mTime < 0) // Are we still in delay?
return false; return false;
float t = (float)mTime / mAnimation->getDuration(); float t = (float)mTime / mAnimation->getDuration();
if(t > 1.0f) if (t > 1.0f)
t = 1.0f; t = 1.0f;
else if(t < 0.0f) else if (t < 0.0f)
t = 0.0f; t = 0.0f;
mAnimation->apply(mReverse ? 1.0f - t : t); mAnimation->apply(mReverse ? 1.0f - t : t);
if(t == 1.0f) if(t == 1.0f)
return true; return true;
return false; return false;
} }

View file

@ -1,3 +1,9 @@
//
// AnimationController.h
//
// Basic animation controls.
//
#pragma once #pragma once
#ifndef ES_CORE_ANIMATIONS_ANIMATION_CONTROLLER_H #ifndef ES_CORE_ANIMATIONS_ANIMATION_CONTROLLER_H
#define ES_CORE_ANIMATIONS_ANIMATION_CONTROLLER_H #define ES_CORE_ANIMATIONS_ANIMATION_CONTROLLER_H
@ -9,27 +15,28 @@ class Animation;
class AnimationController class AnimationController
{ {
public: public:
// Takes ownership of anim (will delete in destructor). // Takes ownership of anim (will delete in destructor).
AnimationController(Animation* anim, int delay = 0, std::function<void()> finishedCallback = nullptr, bool reverse = false); AnimationController(Animation* anim, int delay = 0,
virtual ~AnimationController(); std::function<void()> finishedCallback = nullptr, bool reverse = false);
virtual ~AnimationController();
// Returns true if the animation is complete. // Returns true if the animation is complete.
bool update(int deltaTime); bool update(int deltaTime);
inline bool isReversed() const { return mReverse; } inline bool isReversed() const { return mReverse; }
inline int getTime() const { return mTime; } inline int getTime() const { return mTime; }
inline int getDelay() const { return mDelay; } inline int getDelay() const { return mDelay; }
inline const std::function<void()>& getFinishedCallback() const { return mFinishedCallback; } inline const std::function<void()>& getFinishedCallback() const { return mFinishedCallback; }
inline Animation* getAnimation() const { return mAnimation; } inline Animation* getAnimation() const { return mAnimation; }
inline void removeFinishedCallback() { mFinishedCallback = nullptr; } inline void removeFinishedCallback() { mFinishedCallback = nullptr; }
private: private:
Animation* mAnimation; Animation* mAnimation;
std::function<void()> mFinishedCallback; std::function<void()> mFinishedCallback;
bool mReverse; bool mReverse;
int mTime; int mTime;
int mDelay; int mDelay;
}; };
#endif // ES_CORE_ANIMATIONS_ANIMATION_CONTROLLER_H #endif // ES_CORE_ANIMATIONS_ANIMATION_CONTROLLER_H

View file

@ -1,27 +1,35 @@
//
// LambdaAnimation.h
//
// Basic animation controls, to be used in lambda expressions.
//
#pragma once #pragma once
#ifndef ES_CORE_ANIMATIONS_LAMBDA_ANIMATION_H #ifndef ES_CORE_ANIMATIONS_LAMBDA_ANIMATION_H
#define ES_CORE_ANIMATIONS_LAMBDA_ANIMATION_H #define ES_CORE_ANIMATIONS_LAMBDA_ANIMATION_H
#include "animations/Animation.h" #include "animations/Animation.h"
// Useful for simple one-off animations, you can supply the animation's apply(t) method right in the constructor as a lambda. // Useful for simple one-off animations, you can supply the animation's apply(t)
// function directly in the constructor as a lambda.
class LambdaAnimation : public Animation class LambdaAnimation : public Animation
{ {
public: public:
LambdaAnimation(const std::function<void(float t)>& func, int duration) : mFunction(func), mDuration(duration) {} LambdaAnimation(const std::function<void(float t)>& func, int duration)
: mFunction(func), mDuration(duration) {}
virtual ~LambdaAnimation() = default; virtual ~LambdaAnimation() = default;
int getDuration() const override { return mDuration; } int getDuration() const override { return mDuration; }
void apply(float t) override void apply(float t) override
{ {
mFunction(t); mFunction(t);
} }
private: private:
std::function<void(float t)> mFunction; std::function<void(float t)> mFunction;
int mDuration; int mDuration;
}; };
#endif // ES_CORE_ANIMATIONS_LAMBDA_ANIMATION_H #endif // ES_CORE_ANIMATIONS_LAMBDA_ANIMATION_H

View file

@ -1,141 +1,127 @@
//
// Misc.cpp
//
// Miscellaneous math functions.
//
#include "math/Misc.h" #include "math/Misc.h"
#include <math.h> #include <math.h>
namespace Math namespace Math
{ {
// added here to avoid including math.h whenever these are used // Added here to avoid including math.h whenever these are used.
float cosf(const float _num) float cosf(const float _num)
{ {
return ::cosf(_num); return ::cosf(_num);
}
} // Math::cos float sinf(const float _num)
{
return ::sinf(_num);
}
float sinf(const float _num) float floorf(const float _num)
{ {
return ::sinf(_num); return ::floorf(_num);
}
} // Math::sin float ceilf(const float _num)
{
return ::ceilf(_num);
}
float floorf(const float _num) int min(const int _num1, const int _num2)
{ {
return ::floorf(_num); return (_num1 < _num2) ? _num1 : _num2;
}
} // Math::floor int max(const int _num1, const int _num2)
{
return (_num1 > _num2) ? _num1 : _num2;
}
float ceilf(const float _num) float min(const float _num1, const float _num2)
{ {
return ::ceilf(_num); return (_num1 < _num2) ? _num1 : _num2;
}
} // Math::ceil float max(const float _num1, const float _num2)
{
return (_num1 > _num2) ? _num1 : _num2;
}
int min(const int _num1, const int _num2) float clamp(const float _min, const float _max, const float _num)
{ {
return (_num1 < _num2) ? _num1 : _num2; return max(min(_num, _max), _min);
}
} // Math::min float round(const float _num)
{
return (float)(int)(_num + 0.5);
}
int max(const int _num1, const int _num2) float lerp(const float _start, const float _end, const float _fraction)
{ {
return (_num1 > _num2) ? _num1 : _num2; return (_start + ((_end - _start) * clamp(0, 1, _fraction)));
}
} // Math::max float smoothStep(const float _left, const float _right, const float _x)
{
const float x = clamp(0, 1, (_x - _left)/(_right - _left));
return x * x * (3 - (2 * x));
}
float min(const float _num1, const float _num2) float smootherStep(const float _left, const float _right, const float _x)
{ {
return (_num1 < _num2) ? _num1 : _num2; const float x = clamp(0, 1, (_x - _left)/(_right - _left));
return x * x * x * (x * ((x * 6) - 15) + 10);
}
} // Math::min namespace Scroll
{
float bounce(const float _delayTime, const float _scrollTime,
const float _currentTime, const float _scrollLength)
{
if(_currentTime < _delayTime) {
// Wait.
return 0;
}
else if(_currentTime < (_delayTime + _scrollTime)) {
// Lerp from 0 to scrollLength.
const float fraction = (_currentTime - _delayTime) / _scrollTime;
return lerp(0.0f, _scrollLength, smootherStep(0, 1, fraction));
}
else if(_currentTime < (_delayTime + _scrollTime + _delayTime)) {
// Wait some more.
return _scrollLength;
}
else if(_currentTime < (_delayTime + _scrollTime + _delayTime + _scrollTime)) {
// Lerp back from scrollLength to 0.
const float fraction = (_currentTime - _delayTime - _scrollTime -
_delayTime) / _scrollTime;
return lerp(_scrollLength, 0.0f, smootherStep(0, 1, fraction));
}
// And back to waiting.
return 0;
}
float max(const float _num1, const float _num2) float loop(const float _delayTime, const float _scrollTime,
{ const float _currentTime, const float _scrollLength)
return (_num1 > _num2) ? _num1 : _num2; {
if(_currentTime < _delayTime) {
// Wait.
return 0;
}
else if(_currentTime < (_delayTime + _scrollTime)) {
// Lerp from 0 to scrollLength.
const float fraction = (_currentTime - _delayTime) / _scrollTime;
return lerp(0.0f, _scrollLength, fraction);
}
} // Math::max // And back to waiting.
return 0;
float clamp(const float _min, const float _max, const float _num)
{
return max(min(_num, _max), _min);
} // Math::clamp
float round(const float _num)
{
return (float)(int)(_num + 0.5);
} // Math::round
float lerp(const float _start, const float _end, const float _fraction)
{
return (_start + ((_end - _start) * clamp(0, 1, _fraction)));
} // Math::lerp
float smoothStep(const float _left, const float _right, const float _x)
{
const float x = clamp(0, 1, (_x - _left)/(_right - _left));
return x * x * (3 - (2 * x));
} // Math::smoothStep
float smootherStep(const float _left, const float _right, const float _x)
{
const float x = clamp(0, 1, (_x - _left)/(_right - _left));
return x * x * x * (x * ((x * 6) - 15) + 10);
} // Math::smootherStep
namespace Scroll
{
float bounce(const float _delayTime, const float _scrollTime, const float _currentTime, const float _scrollLength)
{
if(_currentTime < _delayTime)
{
// wait
return 0;
}
else if(_currentTime < (_delayTime + _scrollTime))
{
// lerp from 0 to scrollLength
const float fraction = (_currentTime - _delayTime) / _scrollTime;
return lerp(0.0f, _scrollLength, smootherStep(0, 1, fraction));
}
else if(_currentTime < (_delayTime + _scrollTime + _delayTime))
{
// wait some more
return _scrollLength;
}
else if(_currentTime < (_delayTime + _scrollTime + _delayTime + _scrollTime))
{
// lerp back from scrollLength to 0
const float fraction = (_currentTime - _delayTime - _scrollTime - _delayTime) / _scrollTime;
return lerp(_scrollLength, 0.0f, smootherStep(0, 1, fraction));
}
// and back to waiting
return 0;
} // Math::Scroll::bounce
float loop(const float _delayTime, const float _scrollTime, const float _currentTime, const float _scrollLength)
{
if(_currentTime < _delayTime)
{
// wait
return 0;
}
else if(_currentTime < (_delayTime + _scrollTime))
{
// lerp from 0 to scrollLength
const float fraction = (_currentTime - _delayTime) / _scrollTime;
return lerp(0.0f, _scrollLength, fraction);
}
// and back to waiting
return 0;
} // Math::Scroll::loop
} // Math::Scroll::
} // Math::Scroll::loop
} // Math::Scroll::
} // Math:: } // Math::

View file

@ -1,3 +1,9 @@
//
// Misc.h
//
// Miscellaneous math functions.
//
#pragma once #pragma once
#ifndef ES_CORE_MATH_MISC_H #ifndef ES_CORE_MATH_MISC_H
#define ES_CORE_MATH_MISC_H #define ES_CORE_MATH_MISC_H
@ -8,29 +14,29 @@
namespace Math namespace Math
{ {
// added here to avoid including math.h whenever these are used // Added here to avoid including math.h whenever these are used.
float cosf (const float _num); float cosf(const float _num);
float sinf (const float _num); float sinf(const float _num);
float floorf (const float _num); float floorf(const float _num);
float ceilf (const float _num); float ceilf(const float _num);
int min (const int _num1, const int _num2); int min(const int _num1, const int _num2);
int max (const int _num1, const int _num2); int max(const int _num1, const int _num2);
float min (const float _num1, const float _num2); float min(const float _num1, const float _num2);
float max (const float _num1, const float _num2); float max(const float _num1, const float _num2);
float clamp (const float _num, const float _min, const float _max); float clamp(const float _num, const float _min, const float _max);
float round (const float _num); float round(const float _num);
float lerp (const float _start, const float _end, const float _fraction); float lerp(const float _start, const float _end, const float _fraction);
float smoothStep (const float _left, const float _right, const float _x); float smoothStep(const float _left, const float _right, const float _x);
float smootherStep(const float _left, const float _right, const float _x); float smootherStep(const float _left, const float _right, const float _x);
namespace Scroll namespace Scroll
{ {
float bounce(const float _delayTime, const float _scrollTime, const float _currentTime, const float _scrollLength); float bounce(const float _delayTime, const float _scrollTime,
float loop (const float _delayTime, const float _scrollTime, const float _currentTime, const float _scrollLength); const float _currentTime, const float _scrollLength);
float loop(const float _delayTime, const float _scrollTime,
} // Scroll:: const float _currentTime, const float _scrollLength);
}
} // Math:: }
#endif // ES_CORE_MATH_MISC_H #endif // ES_CORE_MATH_MISC_H

View file

@ -1,317 +1,318 @@
//
// Transform4x4f.cpp
//
// 4x4 transform functions.
//
#include "math/Transform4x4f.h" #include "math/Transform4x4f.h"
const Transform4x4f Transform4x4f::operator*(const Transform4x4f& _other) const const Transform4x4f Transform4x4f::operator*(const Transform4x4f& _other) const
{ {
const float* tm = (float*)this; const float* tm = (float*)this;
const float* om = (float*)&_other; const float* om = (float*)&_other;
return return
{ {
{ {
tm[ 0] * om[ 0] + tm[ 4] * om[ 1] + tm[ 8] * om[ 2], tm[ 0] * om[ 0] + tm[ 4] * om[ 1] + tm[ 8] * om[ 2],
tm[ 1] * om[ 0] + tm[ 5] * om[ 1] + tm[ 9] * om[ 2], tm[ 1] * om[ 0] + tm[ 5] * om[ 1] + tm[ 9] * om[ 2],
tm[ 2] * om[ 0] + tm[ 6] * om[ 1] + tm[10] * om[ 2], tm[ 2] * om[ 0] + tm[ 6] * om[ 1] + tm[10] * om[ 2],
0 0
}, },
{ {
tm[ 0] * om[ 4] + tm[ 4] * om[ 5] + tm[ 8] * om[ 6], tm[ 0] * om[ 4] + tm[ 4] * om[ 5] + tm[ 8] * om[ 6],
tm[ 1] * om[ 4] + tm[ 5] * om[ 5] + tm[ 9] * om[ 6], tm[ 1] * om[ 4] + tm[ 5] * om[ 5] + tm[ 9] * om[ 6],
tm[ 2] * om[ 4] + tm[ 6] * om[ 5] + tm[10] * om[ 6], tm[ 2] * om[ 4] + tm[ 6] * om[ 5] + tm[10] * om[ 6],
0 0
}, },
{ {
tm[ 0] * om[ 8] + tm[ 4] * om[ 9] + tm[ 8] * om[10], tm[ 0] * om[ 8] + tm[ 4] * om[ 9] + tm[ 8] * om[10],
tm[ 1] * om[ 8] + tm[ 5] * om[ 9] + tm[ 9] * om[10], tm[ 1] * om[ 8] + tm[ 5] * om[ 9] + tm[ 9] * om[10],
tm[ 2] * om[ 8] + tm[ 6] * om[ 9] + tm[10] * om[10], tm[ 2] * om[ 8] + tm[ 6] * om[ 9] + tm[10] * om[10],
0 0
}, },
{ {
tm[ 0] * om[12] + tm[ 4] * om[13] + tm[ 8] * om[14] + tm[12], tm[ 0] * om[12] + tm[ 4] * om[13] + tm[ 8] * om[14] + tm[12],
tm[ 1] * om[12] + tm[ 5] * om[13] + tm[ 9] * om[14] + tm[13], tm[ 1] * om[12] + tm[ 5] * om[13] + tm[ 9] * om[14] + tm[13],
tm[ 2] * om[12] + tm[ 6] * om[13] + tm[10] * om[14] + tm[14], tm[ 2] * om[12] + tm[ 6] * om[13] + tm[10] * om[14] + tm[14],
1 1
} }
}; };
}
} // operator*
const Vector3f Transform4x4f::operator*(const Vector3f& _other) const const Vector3f Transform4x4f::operator*(const Vector3f& _other) const
{ {
const float* tm = (float*)this; const float* tm = (float*)this;
const float* ov = (float*)&_other; const float* ov = (float*)&_other;
return return
{ {
tm[ 0] * ov[0] + tm[ 4] * ov[1] + tm[ 8] * ov[2] + tm[12], tm[ 0] * ov[0] + tm[ 4] * ov[1] + tm[ 8] * ov[2] + tm[12],
tm[ 1] * ov[0] + tm[ 5] * ov[1] + tm[ 9] * ov[2] + tm[13], tm[ 1] * ov[0] + tm[ 5] * ov[1] + tm[ 9] * ov[2] + tm[13],
tm[ 2] * ov[0] + tm[ 6] * ov[1] + tm[10] * ov[2] + tm[14] tm[ 2] * ov[0] + tm[ 6] * ov[1] + tm[10] * ov[2] + tm[14]
}; };
}
} // operator* Transform4x4f& Transform4x4f::orthoProjection(
float _left,
Transform4x4f& Transform4x4f::orthoProjection(float _left, float _right, float _bottom, float _top, float _near, float _far) float _right,
float _bottom,
float _top,
float _near,
float _far)
{ {
float* tm = (float*)this; float* tm = (float*)this;
const float o[6] = { 2 / (_right - _left), const float o[6] = { 2 / (_right - _left),
2 / (_top - _bottom), 2 / (_top - _bottom),
-2 / (_far - _near), -2 / (_far - _near),
-(_right + _left) / (_right - _left), -(_right + _left) / (_right - _left),
-(_top + _bottom) / (_top - _bottom), -(_top + _bottom) / (_top - _bottom),
-(_far + _near) / (_far - _near) }; -(_far + _near) / (_far - _near) };
const float temp[12] = { tm[ 0] * o[0], const float temp[12] = { tm[ 0] * o[0],
tm[ 1] * o[0], tm[ 1] * o[0],
tm[ 2] * o[0], tm[ 2] * o[0],
tm[ 4] * o[1], tm[ 4] * o[1],
tm[ 5] * o[1], tm[ 5] * o[1],
tm[ 6] * o[1], tm[ 6] * o[1],
tm[ 8] * o[2], tm[ 8] * o[2],
tm[ 9] * o[2], tm[ 9] * o[2],
tm[10] * o[2], tm[10] * o[2],
tm[ 0] * o[3] + tm[ 4] * o[4] + tm[ 8] * o[5] + tm[12], tm[ 0] * o[3] + tm[ 4] * o[4] + tm[ 8] * o[5] + tm[12],
tm[ 1] * o[3] + tm[ 5] * o[4] + tm[ 9] * o[5] + tm[13], tm[ 1] * o[3] + tm[ 5] * o[4] + tm[ 9] * o[5] + tm[13],
tm[ 2] * o[3] + tm[ 6] * o[4] + tm[10] * o[5] + tm[14] }; tm[ 2] * o[3] + tm[ 6] * o[4] + tm[10] * o[5] + tm[14] };
tm[ 0] = temp[ 0]; tm[ 0] = temp[ 0];
tm[ 1] = temp[ 1]; tm[ 1] = temp[ 1];
tm[ 2] = temp[ 2]; tm[ 2] = temp[ 2];
tm[ 4] = temp[ 3]; tm[ 4] = temp[ 3];
tm[ 5] = temp[ 4]; tm[ 5] = temp[ 4];
tm[ 6] = temp[ 5]; tm[ 6] = temp[ 5];
tm[ 8] = temp[ 6]; tm[ 8] = temp[ 6];
tm[ 9] = temp[ 7]; tm[ 9] = temp[ 7];
tm[10] = temp[ 8]; tm[10] = temp[ 8];
tm[12] = temp[ 9]; tm[12] = temp[ 9];
tm[13] = temp[10]; tm[13] = temp[10];
tm[14] = temp[11]; tm[14] = temp[11];
return *this; return *this;
}
} // orthoProjection
Transform4x4f& Transform4x4f::invert(const Transform4x4f& _other) Transform4x4f& Transform4x4f::invert(const Transform4x4f& _other)
{ {
float* tm = (float*)this; float* tm = (float*)this;
const float* om = (float*)&_other; const float* om = (float*)&_other;
// Full invert // Full invert
// tm[ 0] = ((om[ 5] * (om[10] * om[15] - om[11] * om[14])) - (om[ 9] * (om[ 6] * om[15] - om[ 7] * om[14])) + (om[13] * (om[ 6] * om[11] - om[ 7] * om[10]))); // tm[ 0] = ((om[ 5] * (om[10] * om[15] - om[11] * om[14])) - (om[ 9] * (om[ 6] * om[15] - om[ 7] * om[14])) + (om[13] * (om[ 6] * om[11] - om[ 7] * om[10])));
// tm[ 1] = -((om[ 1] * (om[10] * om[15] - om[11] * om[14])) - (om[ 9] * (om[ 2] * om[15] - om[ 3] * om[14])) + (om[13] * (om[ 2] * om[11] - om[ 3] * om[10]))); // tm[ 1] = -((om[ 1] * (om[10] * om[15] - om[11] * om[14])) - (om[ 9] * (om[ 2] * om[15] - om[ 3] * om[14])) + (om[13] * (om[ 2] * om[11] - om[ 3] * om[10])));
// tm[ 2] = ((om[ 1] * (om[ 6] * om[15] - om[ 7] * om[14])) - (om[ 5] * (om[ 2] * om[15] - om[ 3] * om[14])) + (om[13] * (om[ 2] * om[ 7] - om[ 3] * om[ 6]))); // tm[ 2] = ((om[ 1] * (om[ 6] * om[15] - om[ 7] * om[14])) - (om[ 5] * (om[ 2] * om[15] - om[ 3] * om[14])) + (om[13] * (om[ 2] * om[ 7] - om[ 3] * om[ 6])));
// tm[ 3] = -((om[ 1] * (om[ 6] * om[11] - om[ 7] * om[10])) - (om[ 5] * (om[ 2] * om[11] - om[ 3] * om[10])) + (om[ 9] * (om[ 2] * om[ 7] - om[ 3] * om[ 6]))); // tm[ 3] = -((om[ 1] * (om[ 6] * om[11] - om[ 7] * om[10])) - (om[ 5] * (om[ 2] * om[11] - om[ 3] * om[10])) + (om[ 9] * (om[ 2] * om[ 7] - om[ 3] * om[ 6])));
// tm[ 4] = -((om[ 4] * (om[10] * om[15] - om[11] * om[14])) - (om[ 8] * (om[ 6] * om[15] - om[ 7] * om[14])) + (om[12] * (om[ 6] * om[11] - om[ 7] * om[10]))); // tm[ 4] = -((om[ 4] * (om[10] * om[15] - om[11] * om[14])) - (om[ 8] * (om[ 6] * om[15] - om[ 7] * om[14])) + (om[12] * (om[ 6] * om[11] - om[ 7] * om[10])));
// tm[ 5] = ((om[ 0] * (om[10] * om[15] - om[11] * om[14])) - (om[ 8] * (om[ 2] * om[15] - om[ 3] * om[14])) + (om[12] * (om[ 2] * om[11] - om[ 3] * om[10]))); // tm[ 5] = ((om[ 0] * (om[10] * om[15] - om[11] * om[14])) - (om[ 8] * (om[ 2] * om[15] - om[ 3] * om[14])) + (om[12] * (om[ 2] * om[11] - om[ 3] * om[10])));
// tm[ 6] = -((om[ 0] * (om[ 6] * om[15] - om[ 7] * om[14])) - (om[ 4] * (om[ 2] * om[15] - om[ 3] * om[14])) + (om[12] * (om[ 2] * om[ 7] - om[ 3] * om[ 6]))); // tm[ 6] = -((om[ 0] * (om[ 6] * om[15] - om[ 7] * om[14])) - (om[ 4] * (om[ 2] * om[15] - om[ 3] * om[14])) + (om[12] * (om[ 2] * om[ 7] - om[ 3] * om[ 6])));
// tm[ 7] = ((om[ 0] * (om[ 6] * om[11] - om[ 7] * om[10])) - (om[ 4] * (om[ 2] * om[11] - om[ 3] * om[10])) + (om[ 8] * (om[ 2] * om[ 7] - om[ 3] * om[ 6]))); // tm[ 7] = ((om[ 0] * (om[ 6] * om[11] - om[ 7] * om[10])) - (om[ 4] * (om[ 2] * om[11] - om[ 3] * om[10])) + (om[ 8] * (om[ 2] * om[ 7] - om[ 3] * om[ 6])));
// tm[ 8] = ((om[ 4] * (om[ 9] * om[15] - om[11] * om[13])) - (om[ 8] * (om[ 5] * om[15] - om[ 7] * om[13])) + (om[12] * (om[ 5] * om[11] - om[ 7] * om[ 9]))); // tm[ 8] = ((om[ 4] * (om[ 9] * om[15] - om[11] * om[13])) - (om[ 8] * (om[ 5] * om[15] - om[ 7] * om[13])) + (om[12] * (om[ 5] * om[11] - om[ 7] * om[ 9])));
// tm[ 9] = -((om[ 0] * (om[ 9] * om[15] - om[11] * om[13])) - (om[ 8] * (om[ 1] * om[15] - om[ 3] * om[13])) + (om[12] * (om[ 1] * om[11] - om[ 3] * om[ 9]))); // tm[ 9] = -((om[ 0] * (om[ 9] * om[15] - om[11] * om[13])) - (om[ 8] * (om[ 1] * om[15] - om[ 3] * om[13])) + (om[12] * (om[ 1] * om[11] - om[ 3] * om[ 9])));
// tm[10] = ((om[ 0] * (om[ 5] * om[15] - om[ 7] * om[13])) - (om[ 4] * (om[ 1] * om[15] - om[ 3] * om[13])) + (om[12] * (om[ 1] * om[ 7] - om[ 3] * om[ 5]))); // tm[10] = ((om[ 0] * (om[ 5] * om[15] - om[ 7] * om[13])) - (om[ 4] * (om[ 1] * om[15] - om[ 3] * om[13])) + (om[12] * (om[ 1] * om[ 7] - om[ 3] * om[ 5])));
// tm[11] = -((om[ 0] * (om[ 5] * om[11] - om[ 7] * om[ 9])) - (om[ 4] * (om[ 1] * om[11] - om[ 3] * om[ 9])) + (om[ 8] * (om[ 1] * om[ 7] - om[ 3] * om[ 5]))); // tm[11] = -((om[ 0] * (om[ 5] * om[11] - om[ 7] * om[ 9])) - (om[ 4] * (om[ 1] * om[11] - om[ 3] * om[ 9])) + (om[ 8] * (om[ 1] * om[ 7] - om[ 3] * om[ 5])));
// tm[12] = -((om[ 4] * (om[ 9] * om[14] - om[10] * om[13])) - (om[ 8] * (om[ 5] * om[14] - om[ 6] * om[13])) + (om[12] * (om[ 5] * om[10] - om[ 6] * om[ 9]))); // tm[12] = -((om[ 4] * (om[ 9] * om[14] - om[10] * om[13])) - (om[ 8] * (om[ 5] * om[14] - om[ 6] * om[13])) + (om[12] * (om[ 5] * om[10] - om[ 6] * om[ 9])));
// tm[13] = ((om[ 0] * (om[ 9] * om[14] - om[10] * om[13])) - (om[ 8] * (om[ 1] * om[14] - om[ 2] * om[13])) + (om[12] * (om[ 1] * om[10] - om[ 2] * om[ 9]))); // tm[13] = ((om[ 0] * (om[ 9] * om[14] - om[10] * om[13])) - (om[ 8] * (om[ 1] * om[14] - om[ 2] * om[13])) + (om[12] * (om[ 1] * om[10] - om[ 2] * om[ 9])));
// tm[14] = -((om[ 0] * (om[ 5] * om[14] - om[ 6] * om[13])) - (om[ 4] * (om[ 1] * om[14] - om[ 2] * om[13])) + (om[12] * (om[ 1] * om[ 6] - om[ 2] * om[ 5]))); // tm[14] = -((om[ 0] * (om[ 5] * om[14] - om[ 6] * om[13])) - (om[ 4] * (om[ 1] * om[14] - om[ 2] * om[13])) + (om[12] * (om[ 1] * om[ 6] - om[ 2] * om[ 5])));
// tm[15] = ((om[ 0] * (om[ 5] * om[10] - om[ 6] * om[ 9])) - (om[ 4] * (om[ 1] * om[10] - om[ 2] * om[ 9])) + (om[ 8] * (om[ 1] * om[ 6] - om[ 2] * om[ 5]))); // tm[15] = ((om[ 0] * (om[ 5] * om[10] - om[ 6] * om[ 9])) - (om[ 4] * (om[ 1] * om[10] - om[ 2] * om[ 9])) + (om[ 8] * (om[ 1] * om[ 6] - om[ 2] * om[ 5])));
// Optimized invert ( om[3, 7 and 11] is always 0, and om[15] is always 1 ) // Optimized invert ( om[3, 7 and 11] is always 0, and om[15] is always 1 ).
tm[ 0] = ((om[ 5] * om[10]) - (om[ 9] * om[ 6])); tm[ 0] = ((om[ 5] * om[10]) - (om[ 9] * om[ 6]));
tm[ 1] = -((om[ 1] * om[10]) - (om[ 9] * om[ 2])); tm[ 1] = -((om[ 1] * om[10]) - (om[ 9] * om[ 2]));
tm[ 2] = ((om[ 1] * om[ 6]) - (om[ 5] * om[ 2])); tm[ 2] = ((om[ 1] * om[ 6]) - (om[ 5] * om[ 2]));
tm[ 3] = 0; tm[ 3] = 0;
tm[ 4] = -((om[ 4] * om[10]) - (om[ 8] * om[ 6])); tm[ 4] = -((om[ 4] * om[10]) - (om[ 8] * om[ 6]));
tm[ 5] = ((om[ 0] * om[10]) - (om[ 8] * om[ 2])); tm[ 5] = ((om[ 0] * om[10]) - (om[ 8] * om[ 2]));
tm[ 6] = -((om[ 0] * om[ 6]) - (om[ 4] * om[ 2])); tm[ 6] = -((om[ 0] * om[ 6]) - (om[ 4] * om[ 2]));
tm[ 7] = 0; tm[ 7] = 0;
tm[ 8] = ((om[ 4] * om[ 9]) - (om[ 8] * om[ 5])); tm[ 8] = ((om[ 4] * om[ 9]) - (om[ 8] * om[ 5]));
tm[ 9] = -((om[ 0] * om[ 9]) - (om[ 8] * om[ 1])); tm[ 9] = -((om[ 0] * om[ 9]) - (om[ 8] * om[ 1]));
tm[10] = ((om[ 0] * om[ 5]) - (om[ 4] * om[ 1])); tm[10] = ((om[ 0] * om[ 5]) - (om[ 4] * om[ 1]));
tm[11] = 0; tm[11] = 0;
tm[12] = -((om[ 4] * (om[ 9] * om[14] - om[10] * om[13])) - (om[ 8] * (om[ 5] * om[14] - om[ 6] * om[13])) + (om[12] * (om[ 5] * om[10] - om[ 6] * om[ 9]))); tm[12] = -((om[ 4] * (om[ 9] * om[14] - om[10] * om[13])) - (om[ 8] * (om[ 5] * om[14] - om[ 6] * om[13])) + (om[12] * (om[ 5] * om[10] - om[ 6] * om[ 9])));
tm[13] = ((om[ 0] * (om[ 9] * om[14] - om[10] * om[13])) - (om[ 8] * (om[ 1] * om[14] - om[ 2] * om[13])) + (om[12] * (om[ 1] * om[10] - om[ 2] * om[ 9]))); tm[13] = ((om[ 0] * (om[ 9] * om[14] - om[10] * om[13])) - (om[ 8] * (om[ 1] * om[14] - om[ 2] * om[13])) + (om[12] * (om[ 1] * om[10] - om[ 2] * om[ 9])));
tm[14] = -((om[ 0] * (om[ 5] * om[14] - om[ 6] * om[13])) - (om[ 4] * (om[ 1] * om[14] - om[ 2] * om[13])) + (om[12] * (om[ 1] * om[ 6] - om[ 2] * om[ 5]))); tm[14] = -((om[ 0] * (om[ 5] * om[14] - om[ 6] * om[13])) - (om[ 4] * (om[ 1] * om[14] - om[ 2] * om[13])) + (om[12] * (om[ 1] * om[ 6] - om[ 2] * om[ 5])));
tm[15] = 1; tm[15] = 1;
float Determinant = om[ 0] * tm[ 0] + float Determinant = om[ 0] * tm[ 0] +
om[ 4] * tm[ 1] + om[ 4] * tm[ 1] +
om[ 8] * tm[ 2] + om[ 8] * tm[ 2] +
om[12] * tm[ 3]; om[12] * tm[ 3];
if(Determinant != 0) if(Determinant != 0)
Determinant = 1 / Determinant; Determinant = 1 / Determinant;
tm[ 0] *= Determinant; tm[ 0] *= Determinant;
tm[ 1] *= Determinant; tm[ 1] *= Determinant;
tm[ 2] *= Determinant; tm[ 2] *= Determinant;
tm[ 4] *= Determinant; tm[ 4] *= Determinant;
tm[ 5] *= Determinant; tm[ 5] *= Determinant;
tm[ 6] *= Determinant; tm[ 6] *= Determinant;
tm[ 8] *= Determinant; tm[ 8] *= Determinant;
tm[ 9] *= Determinant; tm[ 9] *= Determinant;
tm[10] *= Determinant; tm[10] *= Determinant;
tm[12] *= Determinant; tm[12] *= Determinant;
tm[13] *= Determinant; tm[13] *= Determinant;
tm[14] *= Determinant; tm[14] *= Determinant;
return *this; return *this;
}
} // invert
Transform4x4f& Transform4x4f::scale(const Vector3f& _scale) Transform4x4f& Transform4x4f::scale(const Vector3f& _scale)
{ {
float* tm = (float*)this; float* tm = (float*)this;
const float* sv = (float*)&_scale; const float* sv = (float*)&_scale;
tm[ 0] *= sv[0]; tm[ 0] *= sv[0];
tm[ 1] *= sv[0]; tm[ 1] *= sv[0];
tm[ 2] *= sv[0]; tm[ 2] *= sv[0];
tm[ 4] *= sv[1]; tm[ 4] *= sv[1];
tm[ 5] *= sv[1]; tm[ 5] *= sv[1];
tm[ 6] *= sv[1]; tm[ 6] *= sv[1];
tm[ 8] *= sv[2]; tm[ 8] *= sv[2];
tm[ 9] *= sv[2]; tm[ 9] *= sv[2];
tm[10] *= sv[2]; tm[10] *= sv[2];
return *this; return *this;
}
} // scale
Transform4x4f& Transform4x4f::rotate(const float _angle, const Vector3f& _axis) Transform4x4f& Transform4x4f::rotate(const float _angle, const Vector3f& _axis)
{ {
float* tm = (float*)this; float* tm = (float*)this;
const float* av = (float*)&_axis; const float* av = (float*)&_axis;
const float s = Math::sinf(-_angle); const float s = Math::sinf(-_angle);
const float c = Math::cosf(-_angle); const float c = Math::cosf(-_angle);
const float t = 1 - c; const float t = 1 - c;
const float x = av[0]; const float x = av[0];
const float y = av[1]; const float y = av[1];
const float z = av[2]; const float z = av[2];
const float tx = t * x; const float tx = t * x;
const float ty = t * y; const float ty = t * y;
const float tz = t * z; const float tz = t * z;
const float sx = s * x; const float sx = s * x;
const float sy = s * y; const float sy = s * y;
const float sz = s * z; const float sz = s * z;
const float r[9] = { tx * x + c, const float r[9] = { tx * x + c,
tx * y - sz, tx * y - sz,
tx * z + sy, tx * z + sy,
ty * x + sz, ty * x + sz,
ty * y + c, ty * y + c,
ty * z - sx, ty * z - sx,
tz * x - sy, tz * x - sy,
tz * y + sx, tz * y + sx,
tz * z + c }; tz * z + c };
const float temp[9] = { tm[ 0] * r[0] + tm[ 4] * r[1] + tm[ 8] * r[2], const float temp[9] = { tm[ 0] * r[0] + tm[ 4] * r[1] + tm[ 8] * r[2],
tm[ 1] * r[0] + tm[ 5] * r[1] + tm[ 9] * r[2], tm[ 1] * r[0] + tm[ 5] * r[1] + tm[ 9] * r[2],
tm[ 2] * r[0] + tm[ 6] * r[1] + tm[10] * r[2], tm[ 2] * r[0] + tm[ 6] * r[1] + tm[10] * r[2],
tm[ 0] * r[3] + tm[ 4] * r[4] + tm[ 8] * r[5], tm[ 0] * r[3] + tm[ 4] * r[4] + tm[ 8] * r[5],
tm[ 1] * r[3] + tm[ 5] * r[4] + tm[ 9] * r[5], tm[ 1] * r[3] + tm[ 5] * r[4] + tm[ 9] * r[5],
tm[ 2] * r[3] + tm[ 6] * r[4] + tm[ 0] * r[5], tm[ 2] * r[3] + tm[ 6] * r[4] + tm[ 0] * r[5],
tm[ 0] * r[6] + tm[ 4] * r[7] + tm[ 8] * r[8], tm[ 0] * r[6] + tm[ 4] * r[7] + tm[ 8] * r[8],
tm[ 1] * r[6] + tm[ 5] * r[7] + tm[ 9] * r[8], tm[ 1] * r[6] + tm[ 5] * r[7] + tm[ 9] * r[8],
tm[ 2] * r[6] + tm[ 6] * r[7] + tm[10] * r[8] }; tm[ 2] * r[6] + tm[ 6] * r[7] + tm[10] * r[8] };
tm[ 0] = temp[0]; tm[ 0] = temp[0];
tm[ 1] = temp[1]; tm[ 1] = temp[1];
tm[ 2] = temp[2]; tm[ 2] = temp[2];
tm[ 4] = temp[3]; tm[ 4] = temp[3];
tm[ 5] = temp[4]; tm[ 5] = temp[4];
tm[ 6] = temp[5]; tm[ 6] = temp[5];
tm[ 8] = temp[6]; tm[ 8] = temp[6];
tm[ 9] = temp[7]; tm[ 9] = temp[7];
tm[10] = temp[8]; tm[10] = temp[8];
return *this; return *this;
}
}; // rotate
Transform4x4f& Transform4x4f::rotateX(const float _angle) Transform4x4f& Transform4x4f::rotateX(const float _angle)
{ {
float* tm = (float*)this; float* tm = (float*)this;
const float s = Math::sinf(-_angle); const float s = Math::sinf(-_angle);
const float c = Math::cosf(-_angle); const float c = Math::cosf(-_angle);
const float temp[6] = { tm[ 4] * c + tm[ 8] * -s, const float temp[6] = { tm[ 4] * c + tm[ 8] * -s,
tm[ 5] * c + tm[ 9] * -c, tm[ 5] * c + tm[ 9] * -c,
tm[ 6] * c + tm[10] * -s, tm[ 6] * c + tm[10] * -s,
tm[ 4] * s + tm[ 8] * c, tm[ 4] * s + tm[ 8] * c,
tm[ 5] * s + tm[ 9] * c, tm[ 5] * s + tm[ 9] * c,
tm[ 6] * s + tm[10] * c }; tm[ 6] * s + tm[10] * c };
tm[ 4] = temp[0]; tm[ 4] = temp[0];
tm[ 5] = temp[1]; tm[ 5] = temp[1];
tm[ 6] = temp[2]; tm[ 6] = temp[2];
tm[ 8] = temp[3]; tm[ 8] = temp[3];
tm[ 9] = temp[4]; tm[ 9] = temp[4];
tm[10] = temp[5]; tm[10] = temp[5];
return *this; return *this;
}
}; // rotateX
Transform4x4f& Transform4x4f::rotateY(const float _angle) Transform4x4f& Transform4x4f::rotateY(const float _angle)
{ {
float* tm = (float*)this; float* tm = (float*)this;
const float s = Math::sinf(-_angle); const float s = Math::sinf(-_angle);
const float c = Math::cosf(-_angle); const float c = Math::cosf(-_angle);
const float temp[6] = { tm[ 0] * c + tm[ 8] * s, const float temp[6] = { tm[ 0] * c + tm[ 8] * s,
tm[ 1] * c + tm[ 9] * s, tm[ 1] * c + tm[ 9] * s,
tm[ 2] * c + tm[10] * s, tm[ 2] * c + tm[10] * s,
tm[ 0] * -s + tm[ 8] * c, tm[ 0] * -s + tm[ 8] * c,
tm[ 1] * -s + tm[ 9] * c, tm[ 1] * -s + tm[ 9] * c,
tm[ 2] * -s + tm[10] * c }; tm[ 2] * -s + tm[10] * c };
tm[ 0] = temp[0]; tm[ 0] = temp[0];
tm[ 1] = temp[1]; tm[ 1] = temp[1];
tm[ 2] = temp[2]; tm[ 2] = temp[2];
tm[ 8] = temp[3]; tm[ 8] = temp[3];
tm[ 9] = temp[4]; tm[ 9] = temp[4];
tm[10] = temp[5]; tm[10] = temp[5];
return *this; return *this;
}
}; // rotateY
Transform4x4f& Transform4x4f::rotateZ(const float _angle) Transform4x4f& Transform4x4f::rotateZ(const float _angle)
{ {
float* tm = (float*)this; float* tm = (float*)this;
const float s = Math::sinf(-_angle); const float s = Math::sinf(-_angle);
const float c = Math::cosf(-_angle); const float c = Math::cosf(-_angle);
const float temp[6] = { tm[ 0] * c + tm[ 4] * -s, const float temp[6] = { tm[ 0] * c + tm[ 4] * -s,
tm[ 1] * c + tm[ 5] * -s, tm[ 1] * c + tm[ 5] * -s,
tm[ 2] * c + tm[ 6] * -s, tm[ 2] * c + tm[ 6] * -s,
tm[ 0] * s + tm[ 4] * c, tm[ 0] * s + tm[ 4] * c,
tm[ 1] * s + tm[ 5] * c, tm[ 1] * s + tm[ 5] * c,
tm[ 2] * s + tm[ 6] * c }; tm[ 2] * s + tm[ 6] * c };
tm[ 0] = temp[0]; tm[ 0] = temp[0];
tm[ 1] = temp[1]; tm[ 1] = temp[1];
tm[ 2] = temp[2]; tm[ 2] = temp[2];
tm[ 4] = temp[3]; tm[ 4] = temp[3];
tm[ 5] = temp[4]; tm[ 5] = temp[4];
tm[ 6] = temp[5]; tm[ 6] = temp[5];
return *this; return *this;
}
}; // rotateZ
Transform4x4f& Transform4x4f::translate(const Vector3f& _translation) Transform4x4f& Transform4x4f::translate(const Vector3f& _translation)
{ {
float* tm = (float*)this; float* tm = (float*)this;
const float* tv = (float*)&_translation; const float* tv = (float*)&_translation;
tm[12] += tm[ 0] * tv[0] + tm[ 4] * tv[1] + tm[ 8] * tv[2]; tm[12] += tm[ 0] * tv[0] + tm[ 4] * tv[1] + tm[ 8] * tv[2];
tm[13] += tm[ 1] * tv[0] + tm[ 5] * tv[1] + tm[ 9] * tv[2]; tm[13] += tm[ 1] * tv[0] + tm[ 5] * tv[1] + tm[ 9] * tv[2];
tm[14] += tm[ 2] * tv[0] + tm[ 6] * tv[1] + tm[10] * tv[2]; tm[14] += tm[ 2] * tv[0] + tm[ 6] * tv[1] + tm[10] * tv[2];
return *this; return *this;
}
} // translate
Transform4x4f& Transform4x4f::round() Transform4x4f& Transform4x4f::round()
{ {
float* tm = (float*)this; float* tm = (float*)this;
tm[12] = (float)(int)(tm[12] + 0.5f); tm[12] = (float)(int)(tm[12] + 0.5f);
tm[13] = (float)(int)(tm[13] + 0.5f); tm[13] = (float)(int)(tm[13] + 0.5f);
tm[14] = (float)(int)(tm[14] + 0.5f); tm[14] = (float)(int)(tm[14] + 0.5f);
return *this; return *this;
}
} // round

View file

@ -1,3 +1,9 @@
//
// Transform4x4f.h
//
// 4x4 transform functions.
//
#pragma once #pragma once
#ifndef ES_CORE_MATH_TRANSFORM4X4F_H #ifndef ES_CORE_MATH_TRANSFORM4X4F_H
#define ES_CORE_MATH_TRANSFORM4X4F_H #define ES_CORE_MATH_TRANSFORM4X4F_H
@ -8,45 +14,58 @@
class Transform4x4f class Transform4x4f
{ {
public: public:
Transform4x4f() {}
Transform4x4f(
const Vector4f& _r0,
const Vector4f& _r1,
const Vector4f& _r2,
const Vector4f& _r3)
: mR0(_r0),
mR1(_r1),
mR2(_r2),
mR3(_r3) {}
Transform4x4f() { } const Transform4x4f operator*(const Transform4x4f& _other) const;
Transform4x4f(const Vector4f& _r0, const Vector4f& _r1, const Vector4f& _r2, const Vector4f& _r3) : mR0(_r0), mR1(_r1), mR2(_r2), mR3(_r3) { } const Vector3f operator*(const Vector3f& _other) const;
Transform4x4f& operator*=(const Transform4x4f& _other)
{ *this = *this * _other; return *this; }
const Transform4x4f operator* (const Transform4x4f& _other) const; inline Vector4f& r0() { return mR0; }
const Vector3f operator* (const Vector3f& _other) const; inline Vector4f& r1() { return mR1; }
Transform4x4f& operator*=(const Transform4x4f& _other) { *this = *this * _other; return *this; } inline Vector4f& r2() { return mR2; }
inline Vector4f& r3() { return mR3; }
inline const Vector4f& r0() const { return mR0; }
inline const Vector4f& r1() const { return mR1; }
inline const Vector4f& r2() const { return mR2; }
inline const Vector4f& r3() const { return mR3; }
inline Vector4f& r0() { return mR0; } Transform4x4f& orthoProjection(
inline Vector4f& r1() { return mR1; } float _left,
inline Vector4f& r2() { return mR2; } float _right,
inline Vector4f& r3() { return mR3; } float _bottom,
inline const Vector4f& r0() const { return mR0; } float _top,
inline const Vector4f& r1() const { return mR1; } float _near,
inline const Vector4f& r2() const { return mR2; } float _far);
inline const Vector4f& r3() const { return mR3; } Transform4x4f& invert(const Transform4x4f& _other);
Transform4x4f& scale(const Vector3f& _scale);
Transform4x4f& rotate(const float _angle, const Vector3f& _axis);
Transform4x4f& rotateX(const float _angle);
Transform4x4f& rotateY(const float _angle);
Transform4x4f& rotateZ(const float _angle);
Transform4x4f& translate(const Vector3f& _translation);
Transform4x4f& round();
Transform4x4f& orthoProjection(float _left, float _right, float _bottom, float _top, float _near, float _far); inline Vector3f& translation() { return mR3.v3(); }
Transform4x4f& invert (const Transform4x4f& _other); inline const Vector3f& translation() const { return mR3.v3(); }
Transform4x4f& scale (const Vector3f& _scale);
Transform4x4f& rotate (const float _angle, const Vector3f& _axis);
Transform4x4f& rotateX (const float _angle);
Transform4x4f& rotateY (const float _angle);
Transform4x4f& rotateZ (const float _angle);
Transform4x4f& translate (const Vector3f& _translation);
Transform4x4f& round ();
inline Vector3f& translation() { return mR3.v3(); } static const Transform4x4f Identity()
inline const Vector3f& translation() const { return mR3.v3(); } { return { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; }
static const Transform4x4f Identity() { return { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; }
protected: protected:
Vector4f mR0;
Vector4f mR0; Vector4f mR1;
Vector4f mR1; Vector4f mR2;
Vector4f mR2; Vector4f mR3;
Vector4f mR3; };
}; // Transform4x4f
#endif // ES_CORE_MATH_TRANSFORM4X4F_H #endif // ES_CORE_MATH_TRANSFORM4X4F_H

View file

@ -1,19 +1,23 @@
//
// Vector2f.cpp
//
// 2-dimensional floating point vector functions.
//
#include "math/Vector2f.h" #include "math/Vector2f.h"
Vector2f& Vector2f::round() Vector2f& Vector2f::round()
{ {
mX = (float)(int)(mX + 0.5f); mX = (float)(int)(mX + 0.5f);
mY = (float)(int)(mY + 0.5f); mY = (float)(int)(mY + 0.5f);
return *this; return *this;
}
} // round
Vector2f& Vector2f::lerp(const Vector2f& _start, const Vector2f& _end, const float _fraction) Vector2f& Vector2f::lerp(const Vector2f& _start, const Vector2f& _end, const float _fraction)
{ {
mX = Math::lerp(_start.x(), _end.x(), _fraction); mX = Math::lerp(_start.x(), _end.x(), _fraction);
mY = Math::lerp(_start.y(), _end.y(), _fraction); mY = Math::lerp(_start.y(), _end.y(), _fraction);
return *this; return *this;
}
} // lerp

View file

@ -1,8 +1,15 @@
//
// Vector2f.h
//
// 2-dimensional floating point vector functions.
//
#pragma once #pragma once
#ifndef ES_CORE_MATH_VECTOR2F_H #ifndef ES_CORE_MATH_VECTOR2F_H
#define ES_CORE_MATH_VECTOR2F_H #define ES_CORE_MATH_VECTOR2F_H
#include "math/Misc.h" #include "math/Misc.h"
#include <assert.h> #include <assert.h>
class Vector3f; class Vector3f;
@ -11,58 +18,63 @@ class Vector4f;
class Vector2f class Vector2f
{ {
public: public:
Vector2f() {}
Vector2f(const float _f) : mX(_f), mY(_f) {}
Vector2f(const float _x, const float _y) : mX(_x), mY(_y) {}
explicit Vector2f(const Vector3f& _v) : mX(((Vector2f&)_v).mX), mY(((Vector2f&)_v).mY) {}
explicit Vector2f(const Vector4f& _v) : mX(((Vector2f&)_v).mX), mY(((Vector2f&)_v).mY) {}
Vector2f() { } const bool operator==(const Vector2f& _other) const
Vector2f(const float _f) : mX(_f), mY(_f) { } { return ((mX == _other.mX) && (mY == _other.mY)); }
Vector2f(const float _x, const float _y) : mX(_x), mY(_y) { } const bool operator!=(const Vector2f& _other) const
explicit Vector2f(const Vector3f& _v) : mX(((Vector2f&)_v).mX), mY(((Vector2f&)_v).mY) { } { return ((mX != _other.mX) || (mY != _other.mY)); }
explicit Vector2f(const Vector4f& _v) : mX(((Vector2f&)_v).mX), mY(((Vector2f&)_v).mY) { }
const bool operator==(const Vector2f& _other) const { return ((mX == _other.mX) && (mY == _other.mY)); } const Vector2f operator+(const Vector2f& _other) const
const bool operator!=(const Vector2f& _other) const { return ((mX != _other.mX) || (mY != _other.mY)); } { return { mX + _other.mX, mY + _other.mY }; }
const Vector2f operator-(const Vector2f& _other) const
{ return { mX - _other.mX, mY - _other.mY }; }
const Vector2f operator*(const Vector2f& _other) const
{ return { mX * _other.mX, mY * _other.mY }; }
const Vector2f operator/(const Vector2f& _other) const
{ return { mX / _other.mX, mY / _other.mY }; }
const Vector2f operator+ (const Vector2f& _other) const { return { mX + _other.mX, mY + _other.mY }; } const Vector2f operator+(const float& _other) const { return { mX + _other, mY + _other }; }
const Vector2f operator- (const Vector2f& _other) const { return { mX - _other.mX, mY - _other.mY }; } const Vector2f operator-(const float& _other) const { return { mX - _other, mY - _other }; }
const Vector2f operator* (const Vector2f& _other) const { return { mX * _other.mX, mY * _other.mY }; } const Vector2f operator*(const float& _other) const { return { mX * _other, mY * _other }; }
const Vector2f operator/ (const Vector2f& _other) const { return { mX / _other.mX, mY / _other.mY }; } const Vector2f operator/(const float& _other) const { return { mX / _other, mY / _other }; }
const Vector2f operator+ (const float& _other) const { return { mX + _other, mY + _other }; } const Vector2f operator-() const { return { -mX , -mY }; }
const Vector2f operator- (const float& _other) const { return { mX - _other, mY - _other }; }
const Vector2f operator* (const float& _other) const { return { mX * _other, mY * _other }; }
const Vector2f operator/ (const float& _other) const { return { mX / _other, mY / _other }; }
const Vector2f operator- () const { return { -mX , -mY }; } Vector2f& operator+=(const Vector2f& _other) { *this = *this + _other; return *this; }
Vector2f& operator-=(const Vector2f& _other) { *this = *this - _other; return *this; }
Vector2f& operator*=(const Vector2f& _other) { *this = *this * _other; return *this; }
Vector2f& operator/=(const Vector2f& _other) { *this = *this / _other; return *this; }
Vector2f& operator+=(const Vector2f& _other) { *this = *this + _other; return *this; } Vector2f& operator+=(const float& _other) { *this = *this + _other; return *this; }
Vector2f& operator-=(const Vector2f& _other) { *this = *this - _other; return *this; } Vector2f& operator-=(const float& _other) { *this = *this - _other; return *this; }
Vector2f& operator*=(const Vector2f& _other) { *this = *this * _other; return *this; } Vector2f& operator*=(const float& _other) { *this = *this * _other; return *this; }
Vector2f& operator/=(const Vector2f& _other) { *this = *this / _other; return *this; } Vector2f& operator/=(const float& _other) { *this = *this / _other; return *this; }
Vector2f& operator+=(const float& _other) { *this = *this + _other; return *this; } float& operator[](const int _index)
Vector2f& operator-=(const float& _other) { *this = *this - _other; return *this; } { assert(_index < 2 && "index out of range"); return (&mX)[_index]; }
Vector2f& operator*=(const float& _other) { *this = *this * _other; return *this; } const float& operator[](const int _index) const
Vector2f& operator/=(const float& _other) { *this = *this / _other; return *this; } { assert(_index < 2 && "index out of range"); return (&mX)[_index]; }
float& operator[](const int _index) { assert(_index < 2 && "index out of range"); return (&mX)[_index]; } inline float& x() { return mX; }
const float& operator[](const int _index) const { assert(_index < 2 && "index out of range"); return (&mX)[_index]; } inline float& y() { return mY; }
inline const float& x() const { return mX; }
inline const float& y() const { return mY; }
inline float& x() { return mX; } Vector2f& round();
inline float& y() { return mY; } Vector2f& lerp (const Vector2f& _start, const Vector2f& _end, const float _fraction);
inline const float& x() const { return mX; }
inline const float& y() const { return mY; }
Vector2f& round(); static const Vector2f Zero() { return { 0, 0 }; }
Vector2f& lerp (const Vector2f& _start, const Vector2f& _end, const float _fraction); static const Vector2f UnitX() { return { 1, 0 }; }
static const Vector2f UnitY() { return { 0, 1 }; }
static const Vector2f Zero () { return { 0, 0 }; }
static const Vector2f UnitX() { return { 1, 0 }; }
static const Vector2f UnitY() { return { 0, 1 }; }
private: private:
float mX;
float mX; float mY;
float mY; };
}; // Vector2f
#endif // ES_CORE_MATH_VECTOR2F_H #endif // ES_CORE_MATH_VECTOR2F_H

View file

@ -1 +1,7 @@
//
// Vector2i.cpp
//
// 2-dimensional integer vector functions.
//
#include "math/Vector2i.h" #include "math/Vector2i.h"

View file

@ -1,3 +1,9 @@
//
// Vector2i.h
//
// 2-dimensional integer vector functions.
//
#pragma once #pragma once
#ifndef ES_CORE_MATH_VECTOR2I_H #ifndef ES_CORE_MATH_VECTOR2I_H
#define ES_CORE_MATH_VECTOR2I_H #define ES_CORE_MATH_VECTOR2I_H
@ -7,53 +13,58 @@
class Vector2i class Vector2i
{ {
public: public:
Vector2i() {}
Vector2i(const int _i) : mX(_i), mY(_i) {}
Vector2i(const int _x, const int _y) : mX(_x), mY(_y) {}
Vector2i() { } const bool operator==(const Vector2i& _other) const
Vector2i(const int _i) : mX(_i), mY(_i) { } { return ((mX == _other.mX) && (mY == _other.mY)); }
Vector2i(const int _x, const int _y) : mX(_x), mY(_y) { } const bool operator!=(const Vector2i& _other) const
{ return ((mX != _other.mX) || (mY != _other.mY)); }
const bool operator==(const Vector2i& _other) const { return ((mX == _other.mX) && (mY == _other.mY)); } const Vector2i operator+(const Vector2i& _other) const
const bool operator!=(const Vector2i& _other) const { return ((mX != _other.mX) || (mY != _other.mY)); } { return { mX + _other.mX, mY + _other.mY }; }
const Vector2i operator-(const Vector2i& _other) const
{ return { mX - _other.mX, mY - _other.mY }; }
const Vector2i operator*(const Vector2i& _other) const
{ return { mX * _other.mX, mY * _other.mY }; }
const Vector2i operator/(const Vector2i& _other) const
{ return { mX / _other.mX, mY / _other.mY }; }
const Vector2i operator+ (const Vector2i& _other) const { return { mX + _other.mX, mY + _other.mY }; } const Vector2i operator+(const int& _other) const { return { mX + _other, mY + _other }; }
const Vector2i operator- (const Vector2i& _other) const { return { mX - _other.mX, mY - _other.mY }; } const Vector2i operator-(const int& _other) const { return { mX - _other, mY - _other }; }
const Vector2i operator* (const Vector2i& _other) const { return { mX * _other.mX, mY * _other.mY }; } const Vector2i operator*(const int& _other) const { return { mX * _other, mY * _other }; }
const Vector2i operator/ (const Vector2i& _other) const { return { mX / _other.mX, mY / _other.mY }; } const Vector2i operator/(const int& _other) const { return { mX / _other, mY / _other }; }
const Vector2i operator+ (const int& _other) const { return { mX + _other, mY + _other }; } const Vector2i operator-() const { return { -mX , -mY }; }
const Vector2i operator- (const int& _other) const { return { mX - _other, mY - _other }; }
const Vector2i operator* (const int& _other) const { return { mX * _other, mY * _other }; }
const Vector2i operator/ (const int& _other) const { return { mX / _other, mY / _other }; }
const Vector2i operator- () const { return { -mX , -mY }; } Vector2i& operator+=(const Vector2i& _other) { *this = *this + _other; return *this; }
Vector2i& operator-=(const Vector2i& _other) { *this = *this - _other; return *this; }
Vector2i& operator*=(const Vector2i& _other) { *this = *this * _other; return *this; }
Vector2i& operator/=(const Vector2i& _other) { *this = *this / _other; return *this; }
Vector2i& operator+=(const Vector2i& _other) { *this = *this + _other; return *this; } Vector2i& operator+=(const int& _other) { *this = *this + _other; return *this; }
Vector2i& operator-=(const Vector2i& _other) { *this = *this - _other; return *this; } Vector2i& operator-=(const int& _other) { *this = *this - _other; return *this; }
Vector2i& operator*=(const Vector2i& _other) { *this = *this * _other; return *this; } Vector2i& operator*=(const int& _other) { *this = *this * _other; return *this; }
Vector2i& operator/=(const Vector2i& _other) { *this = *this / _other; return *this; } Vector2i& operator/=(const int& _other) { *this = *this / _other; return *this; }
Vector2i& operator+=(const int& _other) { *this = *this + _other; return *this; } int& operator[](const int _index)
Vector2i& operator-=(const int& _other) { *this = *this - _other; return *this; } { assert(_index < 2 && "index out of range"); return (&mX)[_index]; }
Vector2i& operator*=(const int& _other) { *this = *this * _other; return *this; } const int& operator[](const int _index) const
Vector2i& operator/=(const int& _other) { *this = *this / _other; return *this; } { assert(_index < 2 && "index out of range"); return (&mX)[_index]; }
int& operator[](const int _index) { assert(_index < 2 && "index out of range"); return (&mX)[_index]; } inline int& x() { return mX; }
const int& operator[](const int _index) const { assert(_index < 2 && "index out of range"); return (&mX)[_index]; } inline int& y() { return mY; }
inline const int& x() const { return mX; }
inline const int& y() const { return mY; }
inline int& x() { return mX; } static const Vector2i Zero() { return { 0, 0 }; }
inline int& y() { return mY; } static const Vector2i UnitX() { return { 1, 0 }; }
inline const int& x() const { return mX; } static const Vector2i UnitY() { return { 0, 1 }; }
inline const int& y() const { return mY; }
static const Vector2i Zero () { return { 0, 0 }; }
static const Vector2i UnitX() { return { 1, 0 }; }
static const Vector2i UnitY() { return { 0, 1 }; }
private: private:
int mX;
int mX; int mY;
int mY; };
}; // Vector2i
#endif // ES_CORE_MATH_VECTOR2I_H #endif // ES_CORE_MATH_VECTOR2I_H

View file

@ -1,21 +1,25 @@
//
// Vector3f.cpp
//
// 3-dimensional floating point vector functions.
//
#include "math/Vector3f.h" #include "math/Vector3f.h"
Vector3f& Vector3f::round() Vector3f& Vector3f::round()
{ {
mX = (float)(int)(mX + 0.5f); mX = (float)(int)(mX + 0.5f);
mY = (float)(int)(mY + 0.5f); mY = (float)(int)(mY + 0.5f);
mZ = (float)(int)(mZ + 0.5f); mZ = (float)(int)(mZ + 0.5f);
return *this; return *this;
}
} // round
Vector3f& Vector3f::lerp(const Vector3f& _start, const Vector3f& _end, const float _fraction) Vector3f& Vector3f::lerp(const Vector3f& _start, const Vector3f& _end, const float _fraction)
{ {
mX = Math::lerp(_start.x(), _end.x(), _fraction); mX = Math::lerp(_start.x(), _end.x(), _fraction);
mY = Math::lerp(_start.y(), _end.y(), _fraction); mY = Math::lerp(_start.y(), _end.y(), _fraction);
mZ = Math::lerp(_start.z(), _end.z(), _fraction); mZ = Math::lerp(_start.z(), _end.z(), _fraction);
return *this; return *this;
}
} // lerp

View file

@ -1,8 +1,15 @@
//
// Vector3f.h
//
// 3-dimensional floating point vector functions.
//
#pragma once #pragma once
#ifndef ES_CORE_MATH_VECTOR3F_H #ifndef ES_CORE_MATH_VECTOR3F_H
#define ES_CORE_MATH_VECTOR3F_H #define ES_CORE_MATH_VECTOR3F_H
#include "math/Misc.h" #include "math/Misc.h"
#include <assert.h> #include <assert.h>
class Vector2f; class Vector2f;
@ -11,66 +18,78 @@ class Vector4f;
class Vector3f class Vector3f
{ {
public: public:
Vector3f() {}
Vector3f(const float _f) : mX(_f), mY(_f), mZ(_f) {}
Vector3f(const float _x, const float _y, const float _z) : mX(_x), mY(_y), mZ(_z) {}
explicit Vector3f(const Vector2f& _v)
: mX(((Vector3f&)_v).mX), mY(((Vector3f&)_v).mY), mZ(0) {}
explicit Vector3f(const Vector2f& _v, const float _z)
: mX(((Vector3f&)_v).mX), mY(((Vector3f&)_v).mY), mZ(_z) {}
explicit Vector3f(const Vector4f& _v)
: mX(((Vector3f&)_v).mX), mY(((Vector3f&)_v).mY), mZ(((Vector3f&)_v).mZ) {}
Vector3f() { } const bool operator==(const Vector3f& _other) const
Vector3f(const float _f) : mX(_f), mY(_f), mZ(_f) { } { return ((mX == _other.mX) && (mY == _other.mY) && (mZ == _other.mZ)); }
Vector3f(const float _x, const float _y, const float _z) : mX(_x), mY(_y), mZ(_z) { } const bool operator!=(const Vector3f& _other) const
explicit Vector3f(const Vector2f& _v) : mX(((Vector3f&)_v).mX), mY(((Vector3f&)_v).mY), mZ(0) { } { return ((mX != _other.mX) || (mY != _other.mY) || (mZ != _other.mZ)); }
explicit Vector3f(const Vector2f& _v, const float _z) : mX(((Vector3f&)_v).mX), mY(((Vector3f&)_v).mY), mZ(_z) { }
explicit Vector3f(const Vector4f& _v) : mX(((Vector3f&)_v).mX), mY(((Vector3f&)_v).mY), mZ(((Vector3f&)_v).mZ) { }
const bool operator==(const Vector3f& _other) const { return ((mX == _other.mX) && (mY == _other.mY) && (mZ == _other.mZ)); } const Vector3f operator+(const Vector3f& _other) const
const bool operator!=(const Vector3f& _other) const { return ((mX != _other.mX) || (mY != _other.mY) || (mZ != _other.mZ)); } { return { mX + _other.mX, mY + _other.mY, mZ + _other.mZ }; }
const Vector3f operator-(const Vector3f& _other) const
{ return { mX - _other.mX, mY - _other.mY, mZ - _other.mZ }; }
const Vector3f operator*(const Vector3f& _other) const
{ return { mX * _other.mX, mY * _other.mY, mZ * _other.mZ }; }
const Vector3f operator/(const Vector3f& _other) const
{ return { mX / _other.mX, mY / _other.mY, mZ / _other.mZ }; }
const Vector3f operator+ (const Vector3f& _other) const { return { mX + _other.mX, mY + _other.mY, mZ + _other.mZ }; } const Vector3f operator+(const float& _other) const
const Vector3f operator- (const Vector3f& _other) const { return { mX - _other.mX, mY - _other.mY, mZ - _other.mZ }; } { return { mX + _other, mY + _other, mZ + _other }; }
const Vector3f operator* (const Vector3f& _other) const { return { mX * _other.mX, mY * _other.mY, mZ * _other.mZ }; } const Vector3f operator-(const float& _other) const
const Vector3f operator/ (const Vector3f& _other) const { return { mX / _other.mX, mY / _other.mY, mZ / _other.mZ }; } { return { mX - _other, mY - _other, mZ - _other }; }
const Vector3f operator*(const float& _other) const
{ return { mX * _other, mY * _other, mZ * _other }; }
const Vector3f operator/(const float& _other) const
{ return { mX / _other, mY / _other, mZ / _other }; }
const Vector3f operator+ (const float& _other) const { return { mX + _other, mY + _other, mZ + _other }; } const Vector3f operator-() const { return { -mX , -mY, -mZ }; }
const Vector3f operator- (const float& _other) const { return { mX - _other, mY - _other, mZ - _other }; }
const Vector3f operator* (const float& _other) const { return { mX * _other, mY * _other, mZ * _other }; }
const Vector3f operator/ (const float& _other) const { return { mX / _other, mY / _other, mZ / _other }; }
const Vector3f operator- () const { return { -mX , -mY, -mZ }; } Vector3f& operator+=(const Vector3f& _other) { *this = *this + _other; return *this; }
Vector3f& operator-=(const Vector3f& _other) { *this = *this - _other; return *this; }
Vector3f& operator*=(const Vector3f& _other) { *this = *this * _other; return *this; }
Vector3f& operator/=(const Vector3f& _other) { *this = *this / _other; return *this; }
Vector3f& operator+=(const Vector3f& _other) { *this = *this + _other; return *this; } Vector3f& operator+=(const float& _other) { *this = *this + _other; return *this; }
Vector3f& operator-=(const Vector3f& _other) { *this = *this - _other; return *this; } Vector3f& operator-=(const float& _other) { *this = *this - _other; return *this; }
Vector3f& operator*=(const Vector3f& _other) { *this = *this * _other; return *this; } Vector3f& operator*=(const float& _other) { *this = *this * _other; return *this; }
Vector3f& operator/=(const Vector3f& _other) { *this = *this / _other; return *this; } Vector3f& operator/=(const float& _other) { *this = *this / _other; return *this; }
Vector3f& operator+=(const float& _other) { *this = *this + _other; return *this; } float& operator[](const int _index)
Vector3f& operator-=(const float& _other) { *this = *this - _other; return *this; } { assert(_index < 3 && "index out of range"); return (&mX)[_index]; }
Vector3f& operator*=(const float& _other) { *this = *this * _other; return *this; } const float& operator[](const int _index) const
Vector3f& operator/=(const float& _other) { *this = *this / _other; return *this; } { assert(_index < 3 && "index out of range"); return (&mX)[_index]; }
float& operator[](const int _index) { assert(_index < 3 && "index out of range"); return (&mX)[_index]; } inline float& x() { return mX; }
const float& operator[](const int _index) const { assert(_index < 3 && "index out of range"); return (&mX)[_index]; } inline float& y() { return mY; }
inline float& z() { return mZ; }
inline const float& x() const { return mX; }
inline const float& y() const { return mY; }
inline const float& z() const { return mZ; }
inline float& x() { return mX; } inline Vector2f& v2() { return *(Vector2f*)this; }
inline float& y() { return mY; } inline const Vector2f& v2() const { return *(Vector2f*)this; }
inline float& z() { return mZ; }
inline const float& x() const { return mX; }
inline const float& y() const { return mY; }
inline const float& z() const { return mZ; }
inline Vector2f& v2() { return *(Vector2f*)this; } Vector3f& round();
inline const Vector2f& v2() const { return *(Vector2f*)this; } Vector3f& lerp(const Vector3f& _start, const Vector3f& _end, const float _fraction);
Vector3f& round(); static const Vector3f Zero() { return { 0, 0, 0 }; }
Vector3f& lerp (const Vector3f& _start, const Vector3f& _end, const float _fraction); static const Vector3f UnitX() { return { 1, 0, 0 }; }
static const Vector3f UnitY() { return { 0, 1, 0 }; }
static const Vector3f Zero () { return { 0, 0, 0 }; } static const Vector3f UnitZ() { return { 0, 0, 1 }; }
static const Vector3f UnitX() { return { 1, 0, 0 }; }
static const Vector3f UnitY() { return { 0, 1, 0 }; }
static const Vector3f UnitZ() { return { 0, 0, 1 }; }
private: private:
float mX;
float mX; float mY;
float mY; float mZ;
float mZ; };
}; // Vector3f
#endif // ES_CORE_MATH_VECTOR3F_H #endif // ES_CORE_MATH_VECTOR3F_H

View file

@ -1,23 +1,27 @@
//
// Vector4f.cpp
//
// 4-dimensional floating point vector functions.
//
#include "math/Vector4f.h" #include "math/Vector4f.h"
Vector4f& Vector4f::round() Vector4f& Vector4f::round()
{ {
mX = (float)(int)(mX + 0.5f); mX = (float)(int)(mX + 0.5f);
mY = (float)(int)(mY + 0.5f); mY = (float)(int)(mY + 0.5f);
mZ = (float)(int)(mZ + 0.5f); mZ = (float)(int)(mZ + 0.5f);
mW = (float)(int)(mW + 0.5f); mW = (float)(int)(mW + 0.5f);
return *this; return *this;
}
} // round
Vector4f& Vector4f::lerp(const Vector4f& _start, const Vector4f& _end, const float _fraction) Vector4f& Vector4f::lerp(const Vector4f& _start, const Vector4f& _end, const float _fraction)
{ {
mX = Math::lerp(_start.x(), _end.x(), _fraction); mX = Math::lerp(_start.x(), _end.x(), _fraction);
mY = Math::lerp(_start.y(), _end.y(), _fraction); mY = Math::lerp(_start.y(), _end.y(), _fraction);
mZ = Math::lerp(_start.z(), _end.z(), _fraction); mZ = Math::lerp(_start.z(), _end.z(), _fraction);
mW = Math::lerp(_start.w(), _end.w(), _fraction); mW = Math::lerp(_start.w(), _end.w(), _fraction);
return *this; return *this;
}
} // lerp

View file

@ -1,8 +1,15 @@
//
// Vector4f.h
//
// 4-dimensional floating point vector functions.
//
#pragma once #pragma once
#ifndef ES_CORE_MATH_VECTOR4F_H #ifndef ES_CORE_MATH_VECTOR4F_H
#define ES_CORE_MATH_VECTOR4F_H #define ES_CORE_MATH_VECTOR4F_H
#include "math/Misc.h" #include "math/Misc.h"
#include <assert.h> #include <assert.h>
class Vector2f; class Vector2f;
@ -11,75 +18,92 @@ class Vector3f;
class Vector4f class Vector4f
{ {
public: public:
Vector4f() {}
Vector4f(const float _f) : mX(_f), mY(_f), mZ(_f), mW(_f) {}
Vector4f(const float _x, const float _y, const float _z, const float _w)
: mX(_x), mY(_y), mZ(_z), mW(_w) {}
explicit Vector4f(const Vector2f& _v)
: mX(((Vector4f&)_v).mX), mY(((Vector4f&)_v).mY), mZ(0), mW(0) {}
explicit Vector4f(const Vector2f& _v, const float _z)
: mX(((Vector4f&)_v).mX), mY(((Vector4f&)_v).mY), mZ(_z), mW(0) {}
explicit Vector4f(const Vector2f& _v, const float _z, const float _w)
: mX(((Vector4f&)_v).mX), mY(((Vector4f&)_v).mY), mZ(_z), mW(_w) {}
explicit Vector4f(const Vector3f& _v)
: mX(((Vector4f&)_v).mX), mY(((Vector4f&)_v).mY), mZ(((Vector4f&)_v).mZ), mW(0) {}
explicit Vector4f(const Vector3f& _v, const float _w)
: mX(((Vector4f&)_v).mX), mY(((Vector4f&)_v).mY), mZ(((Vector4f&)_v).mZ), mW(_w) {}
Vector4f() { } const bool operator==(const Vector4f& _other) const
Vector4f(const float _f) : mX(_f), mY(_f), mZ(_f), mW(_f) { } { return ((mX == _other.mX) && (mY == _other.mY) &&
Vector4f(const float _x, const float _y, const float _z, const float _w) : mX(_x), mY(_y), mZ(_z), mW(_w) { } (mZ == _other.mZ) && (mW == _other.mW)); }
explicit Vector4f(const Vector2f& _v) : mX(((Vector4f&)_v).mX), mY(((Vector4f&)_v).mY), mZ(0), mW(0) { } const bool operator!=(const Vector4f& _other) const
explicit Vector4f(const Vector2f& _v, const float _z) : mX(((Vector4f&)_v).mX), mY(((Vector4f&)_v).mY), mZ(_z), mW(0) { } { return ((mX != _other.mX) || (mY != _other.mY) ||
explicit Vector4f(const Vector2f& _v, const float _z, const float _w) : mX(((Vector4f&)_v).mX), mY(((Vector4f&)_v).mY), mZ(_z), mW(_w) { } (mZ != _other.mZ) || (mW != _other.mW)); }
explicit Vector4f(const Vector3f& _v) : mX(((Vector4f&)_v).mX), mY(((Vector4f&)_v).mY), mZ(((Vector4f&)_v).mZ), mW(0) { }
explicit Vector4f(const Vector3f& _v, const float _w) : mX(((Vector4f&)_v).mX), mY(((Vector4f&)_v).mY), mZ(((Vector4f&)_v).mZ), mW(_w) { }
const bool operator==(const Vector4f& _other) const { return ((mX == _other.mX) && (mY == _other.mY) && (mZ == _other.mZ) && (mW == _other.mW)); } const Vector4f operator+(const Vector4f& _other) const
const bool operator!=(const Vector4f& _other) const { return ((mX != _other.mX) || (mY != _other.mY) || (mZ != _other.mZ) || (mW != _other.mW)); } { return { mX + _other.mX, mY + _other.mY, mZ + _other.mZ, mW + _other.mW }; }
const Vector4f operator-(const Vector4f& _other) const
{ return { mX - _other.mX, mY - _other.mY, mZ - _other.mZ, mW - _other.mW }; }
const Vector4f operator*(const Vector4f& _other) const
{ return { mX * _other.mX, mY * _other.mY, mZ * _other.mZ, mW * _other.mW }; }
const Vector4f operator/(const Vector4f& _other) const
{ return { mX / _other.mX, mY / _other.mY, mZ / _other.mZ, mW / _other.mW }; }
const Vector4f operator+ (const Vector4f& _other) const { return { mX + _other.mX, mY + _other.mY, mZ + _other.mZ, mW + _other.mW }; } const Vector4f operator+(const float& _other) const
const Vector4f operator- (const Vector4f& _other) const { return { mX - _other.mX, mY - _other.mY, mZ - _other.mZ, mW - _other.mW }; } { return { mX + _other, mY + _other, mZ + _other, mW + _other }; }
const Vector4f operator* (const Vector4f& _other) const { return { mX * _other.mX, mY * _other.mY, mZ * _other.mZ, mW * _other.mW }; } const Vector4f operator-(const float& _other) const
const Vector4f operator/ (const Vector4f& _other) const { return { mX / _other.mX, mY / _other.mY, mZ / _other.mZ, mW / _other.mW }; } { return { mX - _other, mY - _other, mZ - _other, mW - _other }; }
const Vector4f operator*(const float& _other) const
{ return { mX * _other, mY * _other, mZ * _other, mW * _other }; }
const Vector4f operator/(const float& _other) const
{ return { mX / _other, mY / _other, mZ / _other, mW / _other }; }
const Vector4f operator+ (const float& _other) const { return { mX + _other, mY + _other, mZ + _other, mW + _other }; } const Vector4f operator-() const { return {-mX , -mY, -mZ, -mW }; }
const Vector4f operator- (const float& _other) const { return { mX - _other, mY - _other, mZ - _other, mW - _other }; }
const Vector4f operator* (const float& _other) const { return { mX * _other, mY * _other, mZ * _other, mW * _other }; }
const Vector4f operator/ (const float& _other) const { return { mX / _other, mY / _other, mZ / _other, mW / _other }; }
const Vector4f operator- () const { return {-mX , -mY, -mZ, -mW }; } Vector4f& operator+=(const Vector4f& _other) { *this = *this + _other; return *this; }
Vector4f& operator-=(const Vector4f& _other) { *this = *this - _other; return *this; }
Vector4f& operator*=(const Vector4f& _other) { *this = *this * _other; return *this; }
Vector4f& operator/=(const Vector4f& _other) { *this = *this / _other; return *this; }
Vector4f& operator+=(const Vector4f& _other) { *this = *this + _other; return *this; } Vector4f& operator+=(const float& _other) { *this = *this + _other; return *this; }
Vector4f& operator-=(const Vector4f& _other) { *this = *this - _other; return *this; } Vector4f& operator-=(const float& _other) { *this = *this - _other; return *this; }
Vector4f& operator*=(const Vector4f& _other) { *this = *this * _other; return *this; } Vector4f& operator*=(const float& _other) { *this = *this * _other; return *this; }
Vector4f& operator/=(const Vector4f& _other) { *this = *this / _other; return *this; } Vector4f& operator/=(const float& _other) { *this = *this / _other; return *this; }
Vector4f& operator+=(const float& _other) { *this = *this + _other; return *this; } float& operator[](const int _index)
Vector4f& operator-=(const float& _other) { *this = *this - _other; return *this; } { assert(_index < 4 && "index out of range"); return (&mX)[_index]; }
Vector4f& operator*=(const float& _other) { *this = *this * _other; return *this; } const float& operator[](const int _index) const
Vector4f& operator/=(const float& _other) { *this = *this / _other; return *this; } { assert(_index < 4 && "index out of range"); return (&mX)[_index]; }
float& operator[](const int _index) { assert(_index < 4 && "index out of range"); return (&mX)[_index]; } inline float& x() { return mX; }
const float& operator[](const int _index) const { assert(_index < 4 && "index out of range"); return (&mX)[_index]; } inline float& y() { return mY; }
inline float& z() { return mZ; }
inline float& w() { return mW; }
inline const float& x() const { return mX; }
inline const float& y() const { return mY; }
inline const float& z() const { return mZ; }
inline const float& w() const { return mW; }
inline float& x() { return mX; } inline Vector2f& v2() { return *(Vector2f*)this; }
inline float& y() { return mY; } inline const Vector2f& v2() const { return *(Vector2f*)this; }
inline float& z() { return mZ; }
inline float& w() { return mW; }
inline const float& x() const { return mX; }
inline const float& y() const { return mY; }
inline const float& z() const { return mZ; }
inline const float& w() const { return mW; }
inline Vector2f& v2() { return *(Vector2f*)this; } inline Vector3f& v3() { return *(Vector3f*)this; }
inline const Vector2f& v2() const { return *(Vector2f*)this; } inline const Vector3f& v3() const { return *(Vector3f*)this; }
inline Vector3f& v3() { return *(Vector3f*)this; } Vector4f& round();
inline const Vector3f& v3() const { return *(Vector3f*)this; } Vector4f& lerp (const Vector4f& _start, const Vector4f& _end, const float _fraction);
Vector4f& round(); static const Vector4f Zero() { return { 0, 0, 0, 0 }; }
Vector4f& lerp (const Vector4f& _start, const Vector4f& _end, const float _fraction); static const Vector4f UnitX() { return { 1, 0, 0, 0 }; }
static const Vector4f UnitY() { return { 0, 1, 0, 0 }; }
static const Vector4f Zero () { return { 0, 0, 0, 0 }; } static const Vector4f UnitZ() { return { 0, 0, 1, 0 }; }
static const Vector4f UnitX() { return { 1, 0, 0, 0 }; } static const Vector4f UnitW() { return { 0, 0, 0, 1 }; }
static const Vector4f UnitY() { return { 0, 1, 0, 0 }; }
static const Vector4f UnitZ() { return { 0, 0, 1, 0 }; }
static const Vector4f UnitW() { return { 0, 0, 0, 1 }; }
private: private:
float mX;
float mX; float mY;
float mY; float mZ;
float mZ; float mW;
float mW; };
}; // Vector4f
#endif // ES_CORE_MATH_VECTOR4F_H #endif // ES_CORE_MATH_VECTOR4F_H

View file

@ -1,3 +1,9 @@
//
// Renderer.cpp
//
// Rendering functions.
//
#include "renderers/Renderer.h" #include "renderers/Renderer.h"
#include "math/Transform4x4f.h" #include "math/Transform4x4f.h"
@ -12,275 +18,280 @@
namespace Renderer namespace Renderer
{ {
static std::stack<Rect> clipStack; static std::stack<Rect> clipStack;
static SDL_Window* sdlWindow = nullptr; static SDL_Window* sdlWindow = nullptr;
static int windowWidth = 0; static int windowWidth = 0;
static int windowHeight = 0; static int windowHeight = 0;
static int screenWidth = 0; static int screenWidth = 0;
static int screenHeight = 0; static int screenHeight = 0;
static int screenOffsetX = 0; static int screenOffsetX = 0;
static int screenOffsetY = 0; static int screenOffsetY = 0;
static int screenRotate = 0; static int screenRotate = 0;
static bool initialCursorState = 1; static bool initialCursorState = 1;
static void setIcon() static void setIcon()
{ {
size_t width = 0; size_t width = 0;
size_t height = 0; size_t height = 0;
ResourceData resData = ResourceManager::getInstance()->getFileData(":/graphics/window_icon_256.png"); ResourceData resData =
std::vector<unsigned char> rawData = ImageIO::loadFromMemoryRGBA32(resData.ptr.get(), resData.length, width, height); ResourceManager::getInstance()->getFileData(":/graphics/window_icon_256.png");
std::vector<unsigned char> rawData =
ImageIO::loadFromMemoryRGBA32(resData.ptr.get(), resData.length, width, height);
if(!rawData.empty()) if (!rawData.empty()) {
{ ImageIO::flipPixelsVert(rawData.data(), width, height);
ImageIO::flipPixelsVert(rawData.data(), width, height);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN #if SDL_BYTEORDER == SDL_BIG_ENDIAN
unsigned int rmask = 0xFF000000; unsigned int rmask = 0xFF000000;
unsigned int gmask = 0x00FF0000; unsigned int gmask = 0x00FF0000;
unsigned int bmask = 0x0000FF00; unsigned int bmask = 0x0000FF00;
unsigned int amask = 0x000000FF; unsigned int amask = 0x000000FF;
#else #else
unsigned int rmask = 0x000000FF; unsigned int rmask = 0x000000FF;
unsigned int gmask = 0x0000FF00; unsigned int gmask = 0x0000FF00;
unsigned int bmask = 0x00FF0000; unsigned int bmask = 0x00FF0000;
unsigned int amask = 0xFF000000; unsigned int amask = 0xFF000000;
#endif #endif
// try creating SDL surface from logo data
SDL_Surface* logoSurface = SDL_CreateRGBSurfaceFrom((void*)rawData.data(), (int)width, (int)height, 32, (int)(width * 4), rmask, gmask, bmask, amask);
if(logoSurface != nullptr) // Try creating SDL surface from logo data.
{ SDL_Surface* logoSurface = SDL_CreateRGBSurfaceFrom((void*)rawData.data(),
SDL_SetWindowIcon(sdlWindow, logoSurface); (int)width, (int)height, 32, (int)(width * 4), rmask, gmask, bmask, amask);
SDL_FreeSurface(logoSurface);
}
}
} // setIcon if (logoSurface != nullptr) {
SDL_SetWindowIcon(sdlWindow, logoSurface);
SDL_FreeSurface(logoSurface);
}
}
}
static bool createWindow() static bool createWindow()
{ {
LOG(LogInfo) << "Creating window..."; LOG(LogInfo) << "Creating window...";
if(SDL_Init(SDL_INIT_VIDEO) != 0) if (SDL_Init(SDL_INIT_VIDEO) != 0) {
{ LOG(LogError) << "Error initializing SDL!\n " << SDL_GetError();
LOG(LogError) << "Error initializing SDL!\n " << SDL_GetError(); return false;
return false; }
}
initialCursorState = (SDL_ShowCursor(0) != 0); initialCursorState = (SDL_ShowCursor(0) != 0);
SDL_DisplayMode dispMode; SDL_DisplayMode dispMode;
SDL_GetDesktopDisplayMode(0, &dispMode); SDL_GetDesktopDisplayMode(0, &dispMode);
windowWidth = Settings::getInstance()->getInt("WindowWidth") ? Settings::getInstance()->getInt("WindowWidth") : dispMode.w; windowWidth = Settings::getInstance()->getInt("WindowWidth") ?
windowHeight = Settings::getInstance()->getInt("WindowHeight") ? Settings::getInstance()->getInt("WindowHeight") : dispMode.h; Settings::getInstance()->getInt("WindowWidth") : dispMode.w;
screenWidth = Settings::getInstance()->getInt("ScreenWidth") ? Settings::getInstance()->getInt("ScreenWidth") : windowWidth; windowHeight = Settings::getInstance()->getInt("WindowHeight") ?
screenHeight = Settings::getInstance()->getInt("ScreenHeight") ? Settings::getInstance()->getInt("ScreenHeight") : windowHeight; Settings::getInstance()->getInt("WindowHeight") : dispMode.h;
screenOffsetX = Settings::getInstance()->getInt("ScreenOffsetX") ? Settings::getInstance()->getInt("ScreenOffsetX") : 0; screenWidth = Settings::getInstance()->getInt("ScreenWidth") ?
screenOffsetY = Settings::getInstance()->getInt("ScreenOffsetY") ? Settings::getInstance()->getInt("ScreenOffsetY") : 0; Settings::getInstance()->getInt("ScreenWidth") : windowWidth;
screenRotate = Settings::getInstance()->getInt("ScreenRotate") ? Settings::getInstance()->getInt("ScreenRotate") : 0; screenHeight = Settings::getInstance()->getInt("ScreenHeight") ?
Settings::getInstance()->getInt("ScreenHeight") : windowHeight;
screenOffsetX = Settings::getInstance()->getInt("ScreenOffsetX") ?
Settings::getInstance()->getInt("ScreenOffsetX") : 0;
screenOffsetY = Settings::getInstance()->getInt("ScreenOffsetY") ?
Settings::getInstance()->getInt("ScreenOffsetY") : 0;
screenRotate = Settings::getInstance()->getInt("ScreenRotate") ?
Settings::getInstance()->getInt("ScreenRotate") : 0;
// Prevent ES window from minimizing when switching windows // Prevent ES window from minimizing when switching windows (when launching
// (when launching games or when manually switching windows using task switcher) // games or when manually switching windows using task switcher).
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
setupWindow(); setupWindow();
unsigned int windowFlags; unsigned int windowFlags;
if (Settings::getInstance()->getBool("Windowed")) if (Settings::getInstance()->getBool("Windowed"))
{ windowFlags = getWindowFlags();
windowFlags = getWindowFlags(); else if (Settings::getInstance()->getString("FullscreenMode") == "borderless")
windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALWAYS_ON_TOP | getWindowFlags();
else
windowFlags = SDL_WINDOW_FULLSCREEN | getWindowFlags();
} if ((sdlWindow = SDL_CreateWindow("EmulationStation", SDL_WINDOWPOS_UNDEFINED,
else if (Settings::getInstance()->getString("FullscreenMode") == "borderless") SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, windowFlags)) == nullptr) {
{ LOG(LogError) << "Error creating SDL window!\n\t" << SDL_GetError();
windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALWAYS_ON_TOP | getWindowFlags(); return false;
} }
else
{
windowFlags = SDL_WINDOW_FULLSCREEN | getWindowFlags();
}
if((sdlWindow = SDL_CreateWindow("EmulationStation", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, windowFlags)) == nullptr) LOG(LogInfo) << "Created window successfully.";
{
LOG(LogError) << "Error creating SDL window!\n\t" << SDL_GetError();
return false;
}
LOG(LogInfo) << "Created window successfully."; createContext();
setIcon();
setSwapInterval();
createContext(); return true;
setIcon(); }
setSwapInterval();
return true; static void destroyWindow()
{
destroyContext();
SDL_DestroyWindow(sdlWindow);
} // createWindow sdlWindow = nullptr;
static void destroyWindow() SDL_ShowCursor(initialCursorState);
{ SDL_Quit();
destroyContext(); }
SDL_DestroyWindow(sdlWindow); bool init()
sdlWindow = nullptr; {
if (!createWindow())
return false;
SDL_ShowCursor(initialCursorState); Transform4x4f projection = Transform4x4f::Identity();
Rect viewport = Rect(0, 0, 0, 0);
SDL_Quit(); switch (screenRotate) {
case 0: {
viewport.x = screenOffsetX;
viewport.y = screenOffsetY;
viewport.w = screenWidth;
viewport.h = screenHeight;
projection.orthoProjection(0, screenWidth, screenHeight, 0, -1.0, 1.0);
}
break;
case 1: {
viewport.x = windowWidth - screenOffsetY - screenHeight;
viewport.y = screenOffsetX;
viewport.w = screenHeight;
viewport.h = screenWidth;
projection.orthoProjection(0, screenHeight, screenWidth, 0, -1.0, 1.0);
projection.rotate((float)ES_DEG_TO_RAD(90), {0, 0, 1});
projection.translate({0, screenHeight * -1.0f, 0});
}
break;
case 2: {
viewport.x = windowWidth - screenOffsetX - screenWidth;
viewport.y = windowHeight - screenOffsetY - screenHeight;
viewport.w = screenWidth;
viewport.h = screenHeight;
projection.orthoProjection(0, screenWidth, screenHeight, 0, -1.0, 1.0);
projection.rotate((float)ES_DEG_TO_RAD(180), {0, 0, 1});
projection.translate({screenWidth * -1.0f, screenHeight * -1.0f, 0});
}
break;
case 3: {
viewport.x = screenOffsetY;
viewport.y = windowHeight - screenOffsetX - screenWidth;
viewport.w = screenHeight;
viewport.h = screenWidth;
projection.orthoProjection(0, screenHeight, screenWidth, 0, -1.0, 1.0);
projection.rotate((float)ES_DEG_TO_RAD(270), {0, 0, 1});
projection.translate({screenWidth * -1.0f, 0, 0});
}
break;
}
} // destroyWindow setViewport(viewport);
setProjection(projection);
swapBuffers();
bool init() return true;
{ }
if(!createWindow())
return false;
Transform4x4f projection = Transform4x4f::Identity(); void deinit()
Rect viewport = Rect(0, 0, 0, 0); {
destroyWindow();
}
switch(screenRotate) void pushClipRect(const Vector2i& _pos, const Vector2i& _size)
{ {
case 0: Rect box(_pos.x(), _pos.y(), _size.x(), _size.y());
{
viewport.x = screenOffsetX;
viewport.y = screenOffsetY;
viewport.w = screenWidth;
viewport.h = screenHeight;
projection.orthoProjection(0, screenWidth, screenHeight, 0, -1.0, 1.0); if (box.w == 0)
} box.w = screenWidth - box.x;
break; if (box.h == 0)
box.h = screenHeight - box.y;
case 1: switch (screenRotate) {
{ case 0: {
viewport.x = windowWidth - screenOffsetY - screenHeight; box = Rect(screenOffsetX + box.x, screenOffsetY + box.y, box.w, box.h);
viewport.y = screenOffsetX; }
viewport.w = screenHeight; break;
viewport.h = screenWidth; case 1: {
box = Rect(windowWidth - screenOffsetY - box.y - box.h, screenOffsetX +
box.x, box.h, box.w);
}
break;
case 2: {
box = Rect(windowWidth - screenOffsetX - box.x - box.w, windowHeight -
screenOffsetY - box.y - box.h, box.w, box.h);
}
break;
case 3: {
box = Rect(screenOffsetY + box.y, windowHeight - screenOffsetX - box.x -
box.w, box.h, box.w);
}
break;
}
projection.orthoProjection(0, screenHeight, screenWidth, 0, -1.0, 1.0); // Make sure the box fits within clipStack.top(), and clip further accordingly.
projection.rotate((float)ES_DEG_TO_RAD(90), {0, 0, 1}); if (clipStack.size()) {
projection.translate({0, screenHeight * -1.0f, 0}); const Rect& top = clipStack.top();
} if ( top.x > box.x) box.x = top.x;
break; if ( top.y > box.y) box.y = top.y;
if ((top.x + top.w) < (box.x + box.w)) box.w = (top.x + top.w) - box.x;
if ((top.y + top.h) < (box.y + box.h)) box.h = (top.y + top.h) - box.y;
}
case 2: if (box.w < 0) box.w = 0;
{ if (box.h < 0) box.h = 0;
viewport.x = windowWidth - screenOffsetX - screenWidth;
viewport.y = windowHeight - screenOffsetY - screenHeight;
viewport.w = screenWidth;
viewport.h = screenHeight;
projection.orthoProjection(0, screenWidth, screenHeight, 0, -1.0, 1.0); clipStack.push(box);
projection.rotate((float)ES_DEG_TO_RAD(180), {0, 0, 1});
projection.translate({screenWidth * -1.0f, screenHeight * -1.0f, 0});
}
break;
case 3: setScissor(box);
{ }
viewport.x = screenOffsetY;
viewport.y = windowHeight - screenOffsetX - screenWidth;
viewport.w = screenHeight;
viewport.h = screenWidth;
projection.orthoProjection(0, screenHeight, screenWidth, 0, -1.0, 1.0); void popClipRect()
projection.rotate((float)ES_DEG_TO_RAD(270), {0, 0, 1}); {
projection.translate({screenWidth * -1.0f, 0, 0}); if (clipStack.empty()) {
} LOG(LogError) << "Tried to popClipRect while the stack was empty!";
break; return;
} }
setViewport(viewport); clipStack.pop();
setProjection(projection);
swapBuffers();
return true; if (clipStack.empty())
setScissor(Rect(0, 0, 0, 0));
else
setScissor(clipStack.top());
}
} // init void drawRect(
const float _x,
const float _y,
const float _w,
const float _h,
const unsigned int _color,
const unsigned int _colorEnd,
bool horizontalGradient,
const Blend::Factor _srcBlendFactor,
const Blend::Factor _dstBlendFactor)
{
const unsigned int color = convertColor(_color);
const unsigned int colorEnd = convertColor(_colorEnd);
Vertex vertices[4];
void deinit() vertices[0] = { { _x ,_y }, { 0.0f, 0.0f }, color };
{ vertices[1] = { { _x ,_y + _h }, { 0.0f, 0.0f }, horizontalGradient ? colorEnd : color };
destroyWindow(); vertices[2] = { { _x + _w,_y }, { 0.0f, 0.0f }, horizontalGradient ? color : colorEnd };
vertices[3] = { { _x + _w,_y + _h }, { 0.0f, 0.0f }, colorEnd };
} // deinit // Round vertices.
for (int i = 0; i < 4; ++i)
vertices[i].pos.round();
void pushClipRect(const Vector2i& _pos, const Vector2i& _size) bindTexture(0);
{ drawTriangleStrips(vertices, 4, _srcBlendFactor, _dstBlendFactor);
Rect box(_pos.x(), _pos.y(), _size.x(), _size.y()); }
if(box.w == 0) box.w = screenWidth - box.x; SDL_Window* getSDLWindow() { return sdlWindow; }
if(box.h == 0) box.h = screenHeight - box.y; int getWindowWidth() { return windowWidth; }
int getWindowHeight() { return windowHeight; }
switch(screenRotate) int getScreenWidth() { return screenWidth; }
{ int getScreenHeight() { return screenHeight; }
case 0: { box = Rect(screenOffsetX + box.x, screenOffsetY + box.y, box.w, box.h); } break; int getScreenOffsetX() { return screenOffsetX; }
case 1: { box = Rect(windowWidth - screenOffsetY - box.y - box.h, screenOffsetX + box.x, box.h, box.w); } break; int getScreenOffsetY() { return screenOffsetY; }
case 2: { box = Rect(windowWidth - screenOffsetX - box.x - box.w, windowHeight - screenOffsetY - box.y - box.h, box.w, box.h); } break; int getScreenRotate() { return screenRotate; }
case 3: { box = Rect(screenOffsetY + box.y, windowHeight - screenOffsetX - box.x - box.w, box.h, box.w); } break;
}
// make sure the box fits within clipStack.top(), and clip further accordingly
if(clipStack.size())
{
const Rect& top = clipStack.top();
if( top.x > box.x) box.x = top.x;
if( top.y > box.y) box.y = top.y;
if((top.x + top.w) < (box.x + box.w)) box.w = (top.x + top.w) - box.x;
if((top.y + top.h) < (box.y + box.h)) box.h = (top.y + top.h) - box.y;
}
if(box.w < 0) box.w = 0;
if(box.h < 0) box.h = 0;
clipStack.push(box);
setScissor(box);
} // pushClipRect
void popClipRect()
{
if(clipStack.empty())
{
LOG(LogError) << "Tried to popClipRect while the stack was empty!";
return;
}
clipStack.pop();
if(clipStack.empty()) setScissor(Rect(0, 0, 0, 0));
else setScissor(clipStack.top());
} // popClipRect
void drawRect(const float _x, const float _y, const float _w, const float _h, const unsigned int _color, const unsigned int _colorEnd, bool horizontalGradient, const Blend::Factor _srcBlendFactor, const Blend::Factor _dstBlendFactor)
{
const unsigned int color = convertColor(_color);
const unsigned int colorEnd = convertColor(_colorEnd);
Vertex vertices[4];
vertices[0] = { { _x ,_y }, { 0.0f, 0.0f }, color };
vertices[1] = { { _x ,_y + _h }, { 0.0f, 0.0f }, horizontalGradient ? colorEnd : color };
vertices[2] = { { _x + _w,_y }, { 0.0f, 0.0f }, horizontalGradient ? color : colorEnd };
vertices[3] = { { _x + _w,_y + _h }, { 0.0f, 0.0f }, colorEnd };
// round vertices
for(int i = 0; i < 4; ++i)
vertices[i].pos.round();
bindTexture(0);
drawTriangleStrips(vertices, 4, _srcBlendFactor, _dstBlendFactor);
} // drawRect
SDL_Window* getSDLWindow() { return sdlWindow; }
int getWindowWidth() { return windowWidth; }
int getWindowHeight() { return windowHeight; }
int getScreenWidth() { return screenWidth; }
int getScreenHeight() { return screenHeight; }
int getScreenOffsetX() { return screenOffsetX; }
int getScreenOffsetY() { return screenOffsetY; }
int getScreenRotate() { return screenRotate; }
} // Renderer:: } // Renderer::

View file

@ -1,3 +1,9 @@
//
// Renderer.h
//
// Rendering functions.
//
#pragma once #pragma once
#ifndef ES_CORE_RENDERER_RENDERER_H #ifndef ES_CORE_RENDERER_RENDERER_H
#define ES_CORE_RENDERER_RENDERER_H #define ES_CORE_RENDERER_RENDERER_H
@ -10,92 +16,124 @@ struct SDL_Window;
namespace Renderer namespace Renderer
{ {
namespace Blend namespace Blend
{ {
enum Factor enum Factor {
{ ZERO = 0,
ZERO = 0, ONE = 1,
ONE = 1, SRC_COLOR = 2,
SRC_COLOR = 2, ONE_MINUS_SRC_COLOR = 3,
ONE_MINUS_SRC_COLOR = 3, SRC_ALPHA = 4,
SRC_ALPHA = 4, ONE_MINUS_SRC_ALPHA = 5,
ONE_MINUS_SRC_ALPHA = 5, DST_COLOR = 6,
DST_COLOR = 6, ONE_MINUS_DST_COLOR = 7,
ONE_MINUS_DST_COLOR = 7, DST_ALPHA = 8,
DST_ALPHA = 8, ONE_MINUS_DST_ALPHA = 9
ONE_MINUS_DST_ALPHA = 9 };
}
}; // Factor namespace Texture
{
enum Type {
RGBA = 0,
ALPHA = 1
};
}
} // Blend:: struct Rect {
Rect(
const int _x,
const int _y,
const int _w,
const int _h)
: x(_x),
y(_y),
w(_w),
h(_h) {}
int x;
int y;
int w;
int h;
};
namespace Texture struct Vertex
{ {
enum Type Vertex() {}
{ Vertex(
RGBA = 0, const Vector2f& _pos,
ALPHA = 1 const Vector2f& _tex,
const unsigned int _col)
: pos(_pos),
tex(_tex),
col(_col) { }
Vector2f pos;
Vector2f tex;
unsigned int col;
};
}; // Type bool init();
void deinit();
void pushClipRect(const Vector2i& _pos, const Vector2i& _size);
void popClipRect();
void drawRect(
const float _x,
const float _y,
const float _w,
const float _h,
const unsigned int _color,
const unsigned int _colorEnd,
bool horizontalGradient = false,
const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA,
const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA);
SDL_Window* getSDLWindow();
int getWindowWidth();
int getWindowHeight();
int getScreenWidth();
int getScreenHeight();
int getScreenOffsetX();
int getScreenOffsetY();
int getScreenRotate();
} // Texture:: // API specific.
unsigned int convertColor(const unsigned int _color);
unsigned int getWindowFlags();
void setupWindow();
void createContext();
void destroyContext();
unsigned int createTexture(
const Texture::Type _type,
const bool _linear,
const bool _repeat,
const unsigned int _width,
const unsigned int _height,
void* _data);
void destroyTexture(const unsigned int _texture);
void updateTexture(
const unsigned int _texture,
const Texture::Type _type,
const unsigned int _x,
const unsigned _y,
const unsigned int _width,
const unsigned int _height,
void* _data);
void bindTexture(const unsigned int _texture);
void drawLines(
const Vertex* _vertices,
const unsigned int _numVertices,
const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA,
const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA);
void drawTriangleStrips(
const Vertex* _vertices,
const unsigned int _numVertices,
const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA,
const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA);
void setProjection(const Transform4x4f& _projection);
void setMatrix(const Transform4x4f& _matrix);
void setViewport(const Rect& _viewport);
void setScissor(const Rect& _scissor);
void setSwapInterval();
void swapBuffers();
struct Rect }
{
Rect(const int _x, const int _y, const int _w, const int _h) : x(_x), y(_y), w(_w), h(_h) { }
int x;
int y;
int w;
int h;
}; // Rect
struct Vertex
{
Vertex() { }
Vertex(const Vector2f& _pos, const Vector2f& _tex, const unsigned int _col) : pos(_pos), tex(_tex), col(_col) { }
Vector2f pos;
Vector2f tex;
unsigned int col;
}; // Vertex
bool init ();
void deinit ();
void pushClipRect (const Vector2i& _pos, const Vector2i& _size);
void popClipRect ();
void drawRect (const float _x, const float _y, const float _w, const float _h, const unsigned int _color, const unsigned int _colorEnd, bool horizontalGradient = false, const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA, const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA);
SDL_Window* getSDLWindow ();
int getWindowWidth ();
int getWindowHeight ();
int getScreenWidth ();
int getScreenHeight ();
int getScreenOffsetX();
int getScreenOffsetY();
int getScreenRotate ();
// API specific
unsigned int convertColor (const unsigned int _color);
unsigned int getWindowFlags ();
void setupWindow ();
void createContext ();
void destroyContext ();
unsigned int createTexture (const Texture::Type _type, const bool _linear, const bool _repeat, const unsigned int _width, const unsigned int _height, void* _data);
void destroyTexture (const unsigned int _texture);
void updateTexture (const unsigned int _texture, const Texture::Type _type, const unsigned int _x, const unsigned _y, const unsigned int _width, const unsigned int _height, void* _data);
void bindTexture (const unsigned int _texture);
void drawLines (const Vertex* _vertices, const unsigned int _numVertices, const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA, const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA);
void drawTriangleStrips(const Vertex* _vertices, const unsigned int _numVertices, const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA, const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA);
void setProjection (const Transform4x4f& _projection);
void setMatrix (const Transform4x4f& _matrix);
void setViewport (const Rect& _viewport);
void setScissor (const Rect& _scissor);
void setSwapInterval ();
void swapBuffers ();
} // Renderer::
#endif // ES_CORE_RENDERER_RENDERER_H #endif // ES_CORE_RENDERER_RENDERER_H

View file

@ -1,3 +1,9 @@
//
// Renderer_GL21.cpp
//
// OpenGL 2.1 rendering functions.
//
#if defined(USE_OPENGL_21) #if defined(USE_OPENGL_21)
#include "renderers/Renderer.h" #include "renderers/Renderer.h"
@ -10,258 +16,272 @@
namespace Renderer namespace Renderer
{ {
#if defined(_DEBUG)
#define GL_CHECK_ERROR(Function) (Function, _GLCheckError(#Function))
#if defined(_DEBUG) static void _GLCheckError(const char* _funcName)
#define GL_CHECK_ERROR(Function) (Function, _GLCheckError(#Function)) {
const GLenum errorCode = glGetError();
static void _GLCheckError(const char* _funcName) if (errorCode != GL_NO_ERROR) {
{ LOG(LogError) << "OpenGLES error: " << _funcName <<
const GLenum errorCode = glGetError(); " failed with error code: " << errorCode;
}
}
#else
#define GL_CHECK_ERROR(Function) (Function)
#endif
if(errorCode != GL_NO_ERROR) { static SDL_GLContext sdlContext = nullptr;
LOG(LogError) << "OpenGLES error: " << _funcName << " failed with error code: " << errorCode; static GLuint whiteTexture = 0;
}
}
#else
#define GL_CHECK_ERROR(Function) (Function)
#endif
static SDL_GLContext sdlContext = nullptr; static GLenum convertBlendFactor(const Blend::Factor _blendFactor)
static GLuint whiteTexture = 0; {
switch (_blendFactor) {
case Blend::ZERO: { return GL_ZERO; } break;
case Blend::ONE: { return GL_ONE; } break;
case Blend::SRC_COLOR: { return GL_SRC_COLOR; } break;
case Blend::ONE_MINUS_SRC_COLOR: { return GL_ONE_MINUS_SRC_COLOR; } break;
case Blend::SRC_ALPHA: { return GL_SRC_ALPHA; } break;
case Blend::ONE_MINUS_SRC_ALPHA: { return GL_ONE_MINUS_SRC_ALPHA; } break;
case Blend::DST_COLOR: { return GL_DST_COLOR; } break;
case Blend::ONE_MINUS_DST_COLOR: { return GL_ONE_MINUS_DST_COLOR; } break;
case Blend::DST_ALPHA: { return GL_DST_ALPHA; } break;
case Blend::ONE_MINUS_DST_ALPHA: { return GL_ONE_MINUS_DST_ALPHA; } break;
default: { return GL_ZERO; }
}
}
static GLenum convertBlendFactor(const Blend::Factor _blendFactor) static GLenum convertTextureType(const Texture::Type _type)
{ {
switch(_blendFactor) switch (_type) {
{ case Texture::RGBA: { return GL_RGBA; } break;
case Blend::ZERO: { return GL_ZERO; } break; case Texture::ALPHA: { return GL_ALPHA; } break;
case Blend::ONE: { return GL_ONE; } break; default: { return GL_ZERO; }
case Blend::SRC_COLOR: { return GL_SRC_COLOR; } break; }
case Blend::ONE_MINUS_SRC_COLOR: { return GL_ONE_MINUS_SRC_COLOR; } break; }
case Blend::SRC_ALPHA: { return GL_SRC_ALPHA; } break;
case Blend::ONE_MINUS_SRC_ALPHA: { return GL_ONE_MINUS_SRC_ALPHA; } break;
case Blend::DST_COLOR: { return GL_DST_COLOR; } break;
case Blend::ONE_MINUS_DST_COLOR: { return GL_ONE_MINUS_DST_COLOR; } break;
case Blend::DST_ALPHA: { return GL_DST_ALPHA; } break;
case Blend::ONE_MINUS_DST_ALPHA: { return GL_ONE_MINUS_DST_ALPHA; } break;
default: { return GL_ZERO; }
}
} // convertBlendFactor unsigned int convertColor(const unsigned int _color)
{
// Convert from rgba to abgr.
unsigned char r = ((_color & 0xff000000) >> 24) & 255;
unsigned char g = ((_color & 0x00ff0000) >> 16) & 255;
unsigned char b = ((_color & 0x0000ff00) >> 8) & 255;
unsigned char a = ((_color & 0x000000ff) ) & 255;
static GLenum convertTextureType(const Texture::Type _type) return ((a << 24) | (b << 16) | (g << 8) | (r));
{ }
switch(_type)
{
case Texture::RGBA: { return GL_RGBA; } break;
case Texture::ALPHA: { return GL_ALPHA; } break;
default: { return GL_ZERO; }
}
} // convertTextureType unsigned int getWindowFlags()
{
return SDL_WINDOW_OPENGL;
}
unsigned int convertColor(const unsigned int _color) void setupWindow()
{ {
// convert from rgba to abgr SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
unsigned char r = ((_color & 0xff000000) >> 24) & 255; SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
unsigned char g = ((_color & 0x00ff0000) >> 16) & 255; SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
unsigned char b = ((_color & 0x0000ff00) >> 8) & 255;
unsigned char a = ((_color & 0x000000ff) ) & 255;
return ((a << 24) | (b << 16) | (g << 8) | (r)); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
}
} // convertColor void createContext()
{
sdlContext = SDL_GL_CreateContext(getSDLWindow());
SDL_GL_MakeCurrent(getSDLWindow(), sdlContext);
unsigned int getWindowFlags() std::string vendor = glGetString(GL_VENDOR) ?
{ (const char*)glGetString(GL_VENDOR) : "";
return SDL_WINDOW_OPENGL; std::string renderer = glGetString(GL_RENDERER) ?
(const char*)glGetString(GL_RENDERER) : "";
std::string version = glGetString(GL_VERSION) ?
(const char*)glGetString(GL_VERSION) : "";
std::string extensions = glGetString(GL_EXTENSIONS) ?
(const char*)glGetString(GL_EXTENSIONS) : "";
} // getWindowFlags LOG(LogInfo) << "GL vendor: " << vendor;
LOG(LogInfo) << "GL renderer: " << renderer;
LOG(LogInfo) << "GL version: " << version;
LOG(LogInfo) << "Checking available OpenGL extensions...";
std::string glExts = glGetString(GL_EXTENSIONS) ?
(const char*)glGetString(GL_EXTENSIONS) : "";
LOG(LogInfo) << "ARB_texture_non_power_of_two: " <<
(extensions.find("ARB_texture_non_power_of_two") !=
std::string::npos ? "ok" : "MISSING");
void setupWindow() uint8_t data[4] = {255, 255, 255, 255};
{ whiteTexture = createTexture(Texture::RGBA, false, true, 1, 1, data);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); GL_CHECK_ERROR(glEnable(GL_TEXTURE_2D));
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); GL_CHECK_ERROR(glEnable(GL_BLEND));
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); GL_CHECK_ERROR(glPixelStorei(GL_PACK_ALIGNMENT, 1));
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); GL_CHECK_ERROR(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); GL_CHECK_ERROR(glEnableClientState(GL_VERTEX_ARRAY));
GL_CHECK_ERROR(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_CHECK_ERROR(glEnableClientState(GL_COLOR_ARRAY));
}
} // setupWindow void destroyContext()
{
SDL_GL_DeleteContext(sdlContext);
sdlContext = nullptr;
}
void createContext() unsigned int createTexture(
{ const Texture::Type _type,
sdlContext = SDL_GL_CreateContext(getSDLWindow()); const bool _linear,
SDL_GL_MakeCurrent(getSDLWindow(), sdlContext); const bool _repeat,
const unsigned int _width,
const unsigned int _height,
void* _data)
{
const GLenum type = convertTextureType(_type);
unsigned int texture;
std::string vendor = glGetString(GL_VENDOR) ? (const char*)glGetString(GL_VENDOR) : ""; GL_CHECK_ERROR(glGenTextures(1, &texture));
std::string renderer = glGetString(GL_RENDERER) ? (const char*)glGetString(GL_RENDERER) : ""; GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture));
std::string version = glGetString(GL_VERSION) ? (const char*)glGetString(GL_VERSION) : "";
std::string extensions = glGetString(GL_EXTENSIONS) ? (const char*)glGetString(GL_EXTENSIONS) : "";
LOG(LogInfo) << "GL vendor: " << vendor; GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _repeat ?
LOG(LogInfo) << "GL renderer: " << renderer; GL_REPEAT : GL_CLAMP_TO_EDGE));
LOG(LogInfo) << "GL version: " << version; GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _repeat ?
LOG(LogInfo) << "Checking available OpenGL extensions..."; GL_REPEAT : GL_CLAMP_TO_EDGE));
std::string glExts = glGetString(GL_EXTENSIONS) ? (const char*)glGetString(GL_EXTENSIONS) : ""; GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _linear ?
LOG(LogInfo) << "ARB_texture_non_power_of_two: " << (extensions.find("ARB_texture_non_power_of_two") != std::string::npos ? "ok" : "MISSING"); GL_LINEAR : GL_NEAREST));
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
uint8_t data[4] = {255, 255, 255, 255}; GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, type, _width, _height, 0, type,
whiteTexture = createTexture(Texture::RGBA, false, true, 1, 1, data); GL_UNSIGNED_BYTE, _data));
GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); return texture;
GL_CHECK_ERROR(glEnable(GL_TEXTURE_2D)); }
GL_CHECK_ERROR(glEnable(GL_BLEND));
GL_CHECK_ERROR(glPixelStorei(GL_PACK_ALIGNMENT, 1));
GL_CHECK_ERROR(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
GL_CHECK_ERROR(glEnableClientState(GL_VERTEX_ARRAY));
GL_CHECK_ERROR(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_CHECK_ERROR(glEnableClientState(GL_COLOR_ARRAY));
} // createContext void destroyTexture(const unsigned int _texture)
{
GL_CHECK_ERROR(glDeleteTextures(1, &_texture));
}
void destroyContext() void updateTexture(
{ const unsigned int _texture,
SDL_GL_DeleteContext(sdlContext); const Texture::Type _type,
sdlContext = nullptr; const unsigned int _x,
const unsigned _y,
const unsigned int _width,
const unsigned int _height,
void* _data)
{
const GLenum type = convertTextureType(_type);
} // destroyContext GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, _texture));
GL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0, _x, _y, _width, _height,
type, GL_UNSIGNED_BYTE, _data));
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture));
}
unsigned int createTexture(const Texture::Type _type, const bool _linear, const bool _repeat, const unsigned int _width, const unsigned int _height, void* _data) void bindTexture(const unsigned int _texture)
{ {
const GLenum type = convertTextureType(_type); if (_texture == 0)
unsigned int texture; GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture));
else
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, _texture));
}
GL_CHECK_ERROR(glGenTextures(1, &texture)); void drawLines(
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); const Vertex* _vertices,
const unsigned int _numVertices,
const Blend::Factor _srcBlendFactor,
const Blend::Factor _dstBlendFactor)
{
GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos));
GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex));
GL_CHECK_ERROR(glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col));
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE)); GL_CHECK_ERROR(glBlendFunc(convertBlendFactor(_srcBlendFactor),
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE)); convertBlendFactor(_dstBlendFactor)));
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _linear ? GL_LINEAR : GL_NEAREST)); GL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, _numVertices));
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); }
GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, type, _width, _height, 0, type, GL_UNSIGNED_BYTE, _data)); void drawTriangleStrips(
const Vertex* _vertices,
const unsigned int _numVertices,
const Blend::Factor _srcBlendFactor,
const Blend::Factor _dstBlendFactor)
{
GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos));
GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex));
GL_CHECK_ERROR(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col));
return texture; GL_CHECK_ERROR(glBlendFunc(convertBlendFactor(_srcBlendFactor),
convertBlendFactor(_dstBlendFactor)));
} // createTexture GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
}
void destroyTexture(const unsigned int _texture) void setProjection(const Transform4x4f& _projection)
{ {
GL_CHECK_ERROR(glDeleteTextures(1, &_texture)); GL_CHECK_ERROR(glMatrixMode(GL_PROJECTION));
GL_CHECK_ERROR(glLoadMatrixf((GLfloat*)&_projection));
}
} // destroyTexture void setMatrix(const Transform4x4f& _matrix)
{
Transform4x4f matrix = _matrix;
matrix.round();
void updateTexture(const unsigned int _texture, const Texture::Type _type, const unsigned int _x, const unsigned _y, const unsigned int _width, const unsigned int _height, void* _data) GL_CHECK_ERROR(glMatrixMode(GL_MODELVIEW));
{ GL_CHECK_ERROR(glLoadMatrixf((GLfloat*)&matrix));
const GLenum type = convertTextureType(_type); }
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, _texture)); void setViewport(const Rect& _viewport)
GL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0, _x, _y, _width, _height, type, GL_UNSIGNED_BYTE, _data)); {
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture)); // glViewport starts at the bottom left of the window.
GL_CHECK_ERROR(glViewport( _viewport.x, getWindowHeight() -
_viewport.y - _viewport.h, _viewport.w, _viewport.h));
}
} // updateTexture void setScissor(const Rect& _scissor)
{
if ((_scissor.x == 0) && (_scissor.y == 0) && (_scissor.w == 0) && (_scissor.h == 0)) {
GL_CHECK_ERROR(glDisable(GL_SCISSOR_TEST));
}
else {
// glScissor starts at the bottom left of the window.
GL_CHECK_ERROR(glScissor(_scissor.x, getWindowHeight() -
_scissor.y - _scissor.h, _scissor.w, _scissor.h));
GL_CHECK_ERROR(glEnable(GL_SCISSOR_TEST));
}
}
void bindTexture(const unsigned int _texture) void setSwapInterval()
{ {
if(_texture == 0) GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture)); // vsync.
else GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, _texture)); if (Settings::getInstance()->getBool("VSync")) {
// SDL_GL_SetSwapInterval(0) for immediate updates (no vsync, default),
// 1 for updates synchronized with the vertical retrace,
// or -1 for late swap tearing.
// SDL_GL_SetSwapInterval returns 0 on success, -1 on error.
// if vsync is requested, try normal vsync; if that doesn't work, try late swap tearing
// if that doesn't work, report an error.
if (SDL_GL_SetSwapInterval(1) != 0 && SDL_GL_SetSwapInterval(-1) != 0) {
LOG(LogWarning) << "Tried to enable vsync, but failed! (" << SDL_GetError() << ")";
}
}
else
SDL_GL_SetSwapInterval(0);
}
} // bindTexture void swapBuffers()
{
void drawLines(const Vertex* _vertices, const unsigned int _numVertices, const Blend::Factor _srcBlendFactor, const Blend::Factor _dstBlendFactor) SDL_GL_SwapWindow(getSDLWindow());
{ GL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
GL_CHECK_ERROR(glVertexPointer( 2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos)); }
GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex));
GL_CHECK_ERROR(glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col));
GL_CHECK_ERROR(glBlendFunc(convertBlendFactor(_srcBlendFactor), convertBlendFactor(_dstBlendFactor)));
GL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, _numVertices));
} // drawLines
void drawTriangleStrips(const Vertex* _vertices, const unsigned int _numVertices, const Blend::Factor _srcBlendFactor, const Blend::Factor _dstBlendFactor)
{
GL_CHECK_ERROR(glVertexPointer( 2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos));
GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex));
GL_CHECK_ERROR(glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col));
GL_CHECK_ERROR(glBlendFunc(convertBlendFactor(_srcBlendFactor), convertBlendFactor(_dstBlendFactor)));
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
} // drawTriangleStrips
void setProjection(const Transform4x4f& _projection)
{
GL_CHECK_ERROR(glMatrixMode(GL_PROJECTION));
GL_CHECK_ERROR(glLoadMatrixf((GLfloat*)&_projection));
} // setProjection
void setMatrix(const Transform4x4f& _matrix)
{
Transform4x4f matrix = _matrix;
matrix.round();
GL_CHECK_ERROR(glMatrixMode(GL_MODELVIEW));
GL_CHECK_ERROR(glLoadMatrixf((GLfloat*)&matrix));
} // setMatrix
void setViewport(const Rect& _viewport)
{
// glViewport starts at the bottom left of the window
GL_CHECK_ERROR(glViewport( _viewport.x, getWindowHeight() - _viewport.y - _viewport.h, _viewport.w, _viewport.h));
} // setViewport
void setScissor(const Rect& _scissor)
{
if((_scissor.x == 0) && (_scissor.y == 0) && (_scissor.w == 0) && (_scissor.h == 0))
{
GL_CHECK_ERROR(glDisable(GL_SCISSOR_TEST));
}
else
{
// glScissor starts at the bottom left of the window
GL_CHECK_ERROR(glScissor(_scissor.x, getWindowHeight() - _scissor.y - _scissor.h, _scissor.w, _scissor.h));
GL_CHECK_ERROR(glEnable(GL_SCISSOR_TEST));
}
} // setScissor
void setSwapInterval()
{
// vsync
if(Settings::getInstance()->getBool("VSync"))
{
// SDL_GL_SetSwapInterval(0) for immediate updates (no vsync, default),
// 1 for updates synchronized with the vertical retrace,
// or -1 for late swap tearing.
// SDL_GL_SetSwapInterval returns 0 on success, -1 on error.
// if vsync is requested, try normal vsync; if that doesn't work, try late swap tearing
// if that doesn't work, report an error
if(SDL_GL_SetSwapInterval(1) != 0 && SDL_GL_SetSwapInterval(-1) != 0) {
LOG(LogWarning) << "Tried to enable vsync, but failed! (" << SDL_GetError() << ")";
}
}
else
SDL_GL_SetSwapInterval(0);
} // setSwapInterval
void swapBuffers()
{
SDL_GL_SwapWindow(getSDLWindow());
GL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
} // swapBuffers
} // Renderer:: } // Renderer::

View file

@ -1,3 +1,9 @@
//
// Renderer_GLES10.cpp
//
// OpenGL ES 1.0 rendering functions.
//
#if defined(USE_OPENGLES_10) #if defined(USE_OPENGLES_10)
#include "renderers/Renderer.h" #include "renderers/Renderer.h"
@ -10,256 +16,273 @@
namespace Renderer namespace Renderer
{ {
#if defined(_DEBUG)
#define GL_CHECK_ERROR(Function) (Function, _GLCheckError(#Function))
#if defined(_DEBUG) static void _GLCheckError(const char* _funcName)
#define GL_CHECK_ERROR(Function) (Function, _GLCheckError(#Function)) {
const GLenum errorCode = glGetError();
static void _GLCheckError(const char* _funcName) if (errorCode != GL_NO_ERROR) {
{ LOG(LogError) << "OpenGLES error: " << _funcName <<
const GLenum errorCode = glGetError(); " failed with error code: " << errorCode;
}
}
#else
#define GL_CHECK_ERROR(Function) (Function)
#endif
if(errorCode != GL_NO_ERROR) static SDL_GLContext sdlContext = nullptr;
LOG(LogError) << "OpenGLES error: " << _funcName << " failed with error code: " << errorCode; static GLuint whiteTexture = 0;
}
#else
#define GL_CHECK_ERROR(Function) (Function)
#endif
static SDL_GLContext sdlContext = nullptr; static GLenum convertBlendFactor(const Blend::Factor _blendFactor)
static GLuint whiteTexture = 0; {
switch (_blendFactor) {
case Blend::ZERO: { return GL_ZERO; } break;
case Blend::ONE: { return GL_ONE; } break;
case Blend::SRC_COLOR: { return GL_SRC_COLOR; } break;
case Blend::ONE_MINUS_SRC_COLOR: { return GL_ONE_MINUS_SRC_COLOR; } break;
case Blend::SRC_ALPHA: { return GL_SRC_ALPHA; } break;
case Blend::ONE_MINUS_SRC_ALPHA: { return GL_ONE_MINUS_SRC_ALPHA; } break;
case Blend::DST_COLOR: { return GL_DST_COLOR; } break;
case Blend::ONE_MINUS_DST_COLOR: { return GL_ONE_MINUS_DST_COLOR; } break;
case Blend::DST_ALPHA: { return GL_DST_ALPHA; } break;
case Blend::ONE_MINUS_DST_ALPHA: { return GL_ONE_MINUS_DST_ALPHA; } break;
default: { return GL_ZERO; }
}
}
static GLenum convertBlendFactor(const Blend::Factor _blendFactor) static GLenum convertTextureType(const Texture::Type _type)
{ {
switch(_blendFactor) switch (_type) {
{ case Texture::RGBA: { return GL_RGBA; } break;
case Blend::ZERO: { return GL_ZERO; } break; case Texture::ALPHA: { return GL_ALPHA; } break;
case Blend::ONE: { return GL_ONE; } break; default: { return GL_ZERO; }
case Blend::SRC_COLOR: { return GL_SRC_COLOR; } break; }
case Blend::ONE_MINUS_SRC_COLOR: { return GL_ONE_MINUS_SRC_COLOR; } break; }
case Blend::SRC_ALPHA: { return GL_SRC_ALPHA; } break;
case Blend::ONE_MINUS_SRC_ALPHA: { return GL_ONE_MINUS_SRC_ALPHA; } break;
case Blend::DST_COLOR: { return GL_DST_COLOR; } break;
case Blend::ONE_MINUS_DST_COLOR: { return GL_ONE_MINUS_DST_COLOR; } break;
case Blend::DST_ALPHA: { return GL_DST_ALPHA; } break;
case Blend::ONE_MINUS_DST_ALPHA: { return GL_ONE_MINUS_DST_ALPHA; } break;
default: { return GL_ZERO; }
}
} // convertBlendFactor unsigned int convertColor(const unsigned int _color)
{
// Convert from rgba to abgr.
unsigned char r = ((_color & 0xff000000) >> 24) & 255;
unsigned char g = ((_color & 0x00ff0000) >> 16) & 255;
unsigned char b = ((_color & 0x0000ff00) >> 8) & 255;
unsigned char a = ((_color & 0x000000ff) ) & 255;
static GLenum convertTextureType(const Texture::Type _type) return ((a << 24) | (b << 16) | (g << 8) | (r));
{ }
switch(_type)
{
case Texture::RGBA: { return GL_RGBA; } break;
case Texture::ALPHA: { return GL_ALPHA; } break;
default: { return GL_ZERO; }
}
} // convertTextureType unsigned int getWindowFlags()
{
return SDL_WINDOW_OPENGL;
}
unsigned int convertColor(const unsigned int _color) void setupWindow()
{ {
// convert from rgba to abgr SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
unsigned char r = ((_color & 0xff000000) >> 24) & 255; SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
unsigned char g = ((_color & 0x00ff0000) >> 16) & 255; SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
unsigned char b = ((_color & 0x0000ff00) >> 8) & 255;
unsigned char a = ((_color & 0x000000ff) ) & 255;
return ((a << 24) | (b << 16) | (g << 8) | (r)); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
}
} // convertColor void createContext()
{
sdlContext = SDL_GL_CreateContext(getSDLWindow());
SDL_GL_MakeCurrent(getSDLWindow(), sdlContext);
unsigned int getWindowFlags() std::string vendor = glGetString(GL_VENDOR) ?
{ (const char*)glGetString(GL_VENDOR) : "";
return SDL_WINDOW_OPENGL; std::string renderer = glGetString(GL_RENDERER) ?
(const char*)glGetString(GL_RENDERER) : "";
std::string version = glGetString(GL_VERSION) ?
(const char*)glGetString(GL_VERSION) : "";
std::string extensions = glGetString(GL_EXTENSIONS) ?
(const char*)glGetString(GL_EXTENSIONS) : "";
} // getWindowFlags LOG(LogInfo) << "GL vendor: " << vendor;
LOG(LogInfo) << "GL renderer: " << renderer;
LOG(LogInfo) << "GL version: " << version;
LOG(LogInfo) << "Checking available OpenGL extensions...";
std::string glExts = glGetString(GL_EXTENSIONS) ?
(const char*)glGetString(GL_EXTENSIONS) : "";
LOG(LogInfo) << "ARB_texture_non_power_of_two: " <<
(extensions.find("ARB_texture_non_power_of_two") !=
std::string::npos ? "ok" : "MISSING");
void setupWindow() uint8_t data[4] = {255, 255, 255, 255};
{ whiteTexture = createTexture(Texture::RGBA, false, true, 1, 1, data);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); GL_CHECK_ERROR(glEnable(GL_TEXTURE_2D));
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); GL_CHECK_ERROR(glEnable(GL_BLEND));
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); GL_CHECK_ERROR(glPixelStorei(GL_PACK_ALIGNMENT, 1));
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); GL_CHECK_ERROR(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); GL_CHECK_ERROR(glEnableClientState(GL_VERTEX_ARRAY));
GL_CHECK_ERROR(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_CHECK_ERROR(glEnableClientState(GL_COLOR_ARRAY));
}
} // setupWindow void destroyContext()
{
SDL_GL_DeleteContext(sdlContext);
sdlContext = nullptr;
}
void createContext() unsigned int createTexture(
{ const Texture::Type _type,
sdlContext = SDL_GL_CreateContext(getSDLWindow()); const bool _linear,
SDL_GL_MakeCurrent(getSDLWindow(), sdlContext); const bool _repeat,
const unsigned int _width,
const unsigned int _height,
void* _data)
{
const GLenum type = convertTextureType(_type);
unsigned int texture;
std::string vendor = glGetString(GL_VENDOR) ? (const char*)glGetString(GL_VENDOR) : ""; GL_CHECK_ERROR(glGenTextures(1, &texture));
std::string renderer = glGetString(GL_RENDERER) ? (const char*)glGetString(GL_RENDERER) : ""; GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture));
std::string version = glGetString(GL_VERSION) ? (const char*)glGetString(GL_VERSION) : "";
std::string extensions = glGetString(GL_EXTENSIONS) ? (const char*)glGetString(GL_EXTENSIONS) : "";
LOG(LogInfo) << "GL vendor: " << vendor; GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _repeat ?
LOG(LogInfo) << "GL renderer: " << renderer; GL_REPEAT : GL_CLAMP_TO_EDGE));
LOG(LogInfo) << "GL version: " << version; GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _repeat ?
LOG(LogInfo) << "Checking available OpenGL extensions..."; GL_REPEAT : GL_CLAMP_TO_EDGE));
std::string glExts = glGetString(GL_EXTENSIONS) ? (const char*)glGetString(GL_EXTENSIONS) : ""; GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _linear ?
LOG(LogInfo) << "ARB_texture_non_power_of_two: " << (extensions.find("ARB_texture_non_power_of_two") != std::string::npos ? "ok" : "MISSING"); GL_LINEAR : GL_NEAREST));
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
uint8_t data[4] = {255, 255, 255, 255}; GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, type, _width, _height, 0, type,
whiteTexture = createTexture(Texture::RGBA, false, true, 1, 1, data); GL_UNSIGNED_BYTE, _data));
GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); return texture;
GL_CHECK_ERROR(glEnable(GL_TEXTURE_2D)); }
GL_CHECK_ERROR(glEnable(GL_BLEND));
GL_CHECK_ERROR(glPixelStorei(GL_PACK_ALIGNMENT, 1));
GL_CHECK_ERROR(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
GL_CHECK_ERROR(glEnableClientState(GL_VERTEX_ARRAY));
GL_CHECK_ERROR(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_CHECK_ERROR(glEnableClientState(GL_COLOR_ARRAY));
} // createContext void destroyTexture(const unsigned int _texture)
{
GL_CHECK_ERROR(glDeleteTextures(1, &_texture));
}
void destroyContext() void updateTexture(
{ const unsigned int _texture,
SDL_GL_DeleteContext(sdlContext); const Texture::Type _type,
sdlContext = nullptr; const unsigned int _x,
const unsigned _y,
const unsigned int _width,
const unsigned int _height,
void* _data)
{
const GLenum type = convertTextureType(_type);
} // destroyContext GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, _texture));
GL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0, _x, _y, _width, _height, type,
GL_UNSIGNED_BYTE, _data));
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture));
}
unsigned int createTexture(const Texture::Type _type, const bool _linear, const bool _repeat, const unsigned int _width, const unsigned int _height, void* _data) void bindTexture(const unsigned int _texture)
{ {
const GLenum type = convertTextureType(_type); if (_texture == 0)
unsigned int texture; GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture));
else
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, _texture));
}
GL_CHECK_ERROR(glGenTextures(1, &texture)); void drawLines(
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); const Vertex* _vertices,
const unsigned int _numVertices,
const Blend::Factor _srcBlendFactor,
const Blend::Factor _dstBlendFactor)
{
GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos));
GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex));
GL_CHECK_ERROR(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col));
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE)); GL_CHECK_ERROR(glBlendFunc(convertBlendFactor(_srcBlendFactor),
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE)); convertBlendFactor(_dstBlendFactor)));
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _linear ? GL_LINEAR : GL_NEAREST)); GL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, _numVertices));
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); }
GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, type, _width, _height, 0, type, GL_UNSIGNED_BYTE, _data)); void drawTriangleStrips(
const Vertex* _vertices,
const unsigned int _numVertices,
const Blend::Factor _srcBlendFactor,
const Blend::Factor _dstBlendFactor)
{
GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos));
GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex));
GL_CHECK_ERROR(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col));
return texture; GL_CHECK_ERROR(glBlendFunc(convertBlendFactor(_srcBlendFactor),
convertBlendFactor(_dstBlendFactor)));
} // createTexture GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
}
void destroyTexture(const unsigned int _texture) void setProjection(const Transform4x4f& _projection)
{ {
GL_CHECK_ERROR(glDeleteTextures(1, &_texture)); GL_CHECK_ERROR(glMatrixMode(GL_PROJECTION));
GL_CHECK_ERROR(glLoadMatrixf((GLfloat*)&_projection));
}
} // destroyTexture void setMatrix(const Transform4x4f& _matrix)
{
Transform4x4f matrix = _matrix;
matrix.round();
void updateTexture(const unsigned int _texture, const Texture::Type _type, const unsigned int _x, const unsigned _y, const unsigned int _width, const unsigned int _height, void* _data) GL_CHECK_ERROR(glMatrixMode(GL_MODELVIEW));
{ GL_CHECK_ERROR(glLoadMatrixf((GLfloat*)&matrix));
const GLenum type = convertTextureType(_type); }
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, _texture)); void setViewport(const Rect& _viewport)
GL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0, _x, _y, _width, _height, type, GL_UNSIGNED_BYTE, _data)); {
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture)); // glViewport starts at the bottom left of the window.
GL_CHECK_ERROR(glViewport( _viewport.x, getWindowHeight() -
_viewport.y - _viewport.h, _viewport.w, _viewport.h));
}
} // updateTexture void setScissor(const Rect& _scissor)
{
if ((_scissor.x == 0) && (_scissor.y == 0) && (_scissor.w == 0) && (_scissor.h == 0)) {
GL_CHECK_ERROR(glDisable(GL_SCISSOR_TEST));
}
else {
// glScissor starts at the bottom left of the window.
GL_CHECK_ERROR(glScissor(_scissor.x, getWindowHeight() -
_scissor.y - _scissor.h, _scissor.w, _scissor.h));
GL_CHECK_ERROR(glEnable(GL_SCISSOR_TEST));
}
}
void bindTexture(const unsigned int _texture) void setSwapInterval()
{ {
if(_texture == 0) GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture)); // vsync.
else GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, _texture)); if (Settings::getInstance()->getBool("VSync")) {
// SDL_GL_SetSwapInterval(0) for immediate updates (no vsync, default),
// 1 for updates synchronized with the vertical retrace,
// or -1 for late swap tearing.
// SDL_GL_SetSwapInterval returns 0 on success, -1 on error.
// if vsync is requested, try normal vsync; if that doesn't work, try late swap tearing
// if that doesn't work, report an error.
if (SDL_GL_SetSwapInterval(1) != 0 && SDL_GL_SetSwapInterval(-1) != 0) {
LOG(LogWarning) << "Tried to enable vsync, but failed! (" << SDL_GetError() << ")";
}
}
else {
SDL_GL_SetSwapInterval(0);
}
}
} // bindTexture void swapBuffers()
{
void drawLines(const Vertex* _vertices, const unsigned int _numVertices, const Blend::Factor _srcBlendFactor, const Blend::Factor _dstBlendFactor) SDL_GL_SwapWindow(getSDLWindow());
{ GL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
GL_CHECK_ERROR(glVertexPointer( 2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos)); }
GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex));
GL_CHECK_ERROR(glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col));
GL_CHECK_ERROR(glBlendFunc(convertBlendFactor(_srcBlendFactor), convertBlendFactor(_dstBlendFactor)));
GL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, _numVertices));
} // drawLines
void drawTriangleStrips(const Vertex* _vertices, const unsigned int _numVertices, const Blend::Factor _srcBlendFactor, const Blend::Factor _dstBlendFactor)
{
GL_CHECK_ERROR(glVertexPointer( 2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos));
GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex));
GL_CHECK_ERROR(glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col));
GL_CHECK_ERROR(glBlendFunc(convertBlendFactor(_srcBlendFactor), convertBlendFactor(_dstBlendFactor)));
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
} // drawTriangleStrips
void setProjection(const Transform4x4f& _projection)
{
GL_CHECK_ERROR(glMatrixMode(GL_PROJECTION));
GL_CHECK_ERROR(glLoadMatrixf((GLfloat*)&_projection));
} // setProjection
void setMatrix(const Transform4x4f& _matrix)
{
Transform4x4f matrix = _matrix;
matrix.round();
GL_CHECK_ERROR(glMatrixMode(GL_MODELVIEW));
GL_CHECK_ERROR(glLoadMatrixf((GLfloat*)&matrix));
} // setMatrix
void setViewport(const Rect& _viewport)
{
// glViewport starts at the bottom left of the window
GL_CHECK_ERROR(glViewport( _viewport.x, getWindowHeight() - _viewport.y - _viewport.h, _viewport.w, _viewport.h));
} // setViewport
void setScissor(const Rect& _scissor)
{
if((_scissor.x == 0) && (_scissor.y == 0) && (_scissor.w == 0) && (_scissor.h == 0))
{
GL_CHECK_ERROR(glDisable(GL_SCISSOR_TEST));
}
else
{
// glScissor starts at the bottom left of the window
GL_CHECK_ERROR(glScissor(_scissor.x, getWindowHeight() - _scissor.y - _scissor.h, _scissor.w, _scissor.h));
GL_CHECK_ERROR(glEnable(GL_SCISSOR_TEST));
}
} // setScissor
void setSwapInterval()
{
// vsync
if(Settings::getInstance()->getBool("VSync"))
{
// SDL_GL_SetSwapInterval(0) for immediate updates (no vsync, default),
// 1 for updates synchronized with the vertical retrace,
// or -1 for late swap tearing.
// SDL_GL_SetSwapInterval returns 0 on success, -1 on error.
// if vsync is requested, try normal vsync; if that doesn't work, try late swap tearing
// if that doesn't work, report an error
if(SDL_GL_SetSwapInterval(1) != 0 && SDL_GL_SetSwapInterval(-1) != 0)
LOG(LogWarning) << "Tried to enable vsync, but failed! (" << SDL_GetError() << ")";
}
else
SDL_GL_SetSwapInterval(0);
} // setSwapInterval
void swapBuffers()
{
SDL_GL_SwapWindow(getSDLWindow());
GL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
} // swapBuffers
} // Renderer:: } // Renderer::