2015-10-09 04:38:37 +08:00
// ImGui Marmalade binding with IwGx
// Copyright (C) 2015 by Giovanni Zito
// This file is part of ImGui
// https://github.com/ocornut/imgui
# include <imgui.h>
# include "imgui_impl_marmalade.h"
# include <s3eClipboard.h>
# include <s3ePointer.h>
# include <s3eKeyboard.h>
# include <IwTexture.h>
# include <IwGx.h>
// Data
static double g_Time = 0.0f ;
static bool g_MousePressed [ 3 ] = { false , false , false } ;
static float g_MouseWheel = 0.0f ;
static CIwTexture * g_FontTexture = 0 ;
2015-10-15 05:01:52 +08:00
static char * g_ClipboardText = 0 ;
static bool g_osdKeyboardEnabled = false ;
// use this setting to scale the interface - e.g. on device you could use 2 or 3 scale factor
static ImVec2 g_scale = ImVec2 ( 1.0f , 1.0f ) ;
2015-10-09 04:38:37 +08:00
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
void ImGui_Marmalade_RenderDrawLists ( ImDrawData * draw_data )
{
2015-10-15 05:01:52 +08:00
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
ImGuiIO & io = ImGui : : GetIO ( ) ;
draw_data - > ScaleClipRects ( io . DisplayFramebufferScale ) ;
// Render command lists
for ( int n = 0 ; n < draw_data - > CmdListsCount ; n + + )
{
const ImDrawList * cmd_list = draw_data - > CmdLists [ n ] ;
const unsigned char * vtx_buffer = ( const unsigned char * ) & cmd_list - > VtxBuffer . front ( ) ;
const ImDrawIdx * idx_buffer = & cmd_list - > IdxBuffer . front ( ) ;
int nVert = cmd_list - > VtxBuffer . size ( ) ;
CIwFVec2 * pVertStream = IW_GX_ALLOC ( CIwFVec2 , nVert ) ;
CIwFVec2 * pUVStream = IW_GX_ALLOC ( CIwFVec2 , nVert ) ;
CIwColour * pColStream = IW_GX_ALLOC ( CIwColour , nVert ) ;
for ( int i = 0 ; i < nVert ; i + + ) {
// todo - optimize multiplication on gpu using vertex shader
pVertStream [ i ] . x = cmd_list - > VtxBuffer [ i ] . pos . x * g_scale . x ;
pVertStream [ i ] . y = cmd_list - > VtxBuffer [ i ] . pos . y * g_scale . y ;
pUVStream [ i ] . x = cmd_list - > VtxBuffer [ i ] . uv . x ;
pUVStream [ i ] . y = cmd_list - > VtxBuffer [ i ] . uv . y ;
pColStream [ i ] = cmd_list - > VtxBuffer [ i ] . col ;
}
IwGxSetVertStreamScreenSpace ( pVertStream , nVert ) ;
IwGxSetUVStream ( pUVStream ) ;
IwGxSetColStream ( pColStream , nVert ) ;
IwGxSetNormStream ( 0 ) ;
for ( int cmd_i = 0 ; cmd_i < cmd_list - > CmdBuffer . size ( ) ; cmd_i + + )
{
const ImDrawCmd * pcmd = & cmd_list - > CmdBuffer [ cmd_i ] ;
if ( pcmd - > UserCallback )
{
pcmd - > UserCallback ( cmd_list , pcmd ) ;
}
else
{
CIwMaterial * pCurrentMaterial = IW_GX_ALLOC_MATERIAL ( ) ;
pCurrentMaterial - > SetShadeMode ( CIwMaterial : : SHADE_FLAT ) ;
pCurrentMaterial - > SetCullMode ( CIwMaterial : : CULL_NONE ) ;
pCurrentMaterial - > SetFiltering ( false ) ;
pCurrentMaterial - > SetAlphaMode ( CIwMaterial : : ALPHA_BLEND ) ;
pCurrentMaterial - > SetDepthWriteMode ( CIwMaterial : : DEPTH_WRITE_NORMAL ) ;
pCurrentMaterial - > SetAlphaTestMode ( CIwMaterial : : ALPHATEST_DISABLED ) ;
pCurrentMaterial - > SetTexture ( ( CIwTexture * ) pcmd - > TextureId ) ;
IwGxSetMaterial ( pCurrentMaterial ) ;
IwGxDrawPrims ( IW_GX_TRI_LIST , ( uint16 * ) idx_buffer , pcmd - > ElemCount ) ;
}
idx_buffer + = pcmd - > ElemCount ;
}
IwGxFlush ( ) ;
}
// TODO restore modified state (i.e. mvp matrix)
2015-10-09 04:38:37 +08:00
}
static const char * ImGui_Marmalade_GetClipboardText ( )
{
2015-10-15 05:01:52 +08:00
if ( s3eClipboardAvailable ( ) ) {
int size = s3eClipboardGetText ( NULL , 0 ) ;
if ( size > 0 ) {
if ( g_ClipboardText ) {
delete [ ] g_ClipboardText ;
g_ClipboardText = 0 ;
}
g_ClipboardText = new char [ size ] ;
g_ClipboardText [ 0 ] = ' \0 ' ;
s3eClipboardGetText ( g_ClipboardText , size ) ;
}
}
return g_ClipboardText ;
2015-10-09 04:38:37 +08:00
}
static void ImGui_Marmalade_SetClipboardText ( const char * text )
{
2015-10-15 05:01:52 +08:00
if ( s3eClipboardAvailable ( ) ) {
s3eClipboardSetText ( text ) ;
}
2015-10-09 04:38:37 +08:00
}
int32 ImGui_Marmalade_PointerButtonEventCallback ( void * SystemData , void * pUserData )
{
2015-10-15 05:01:52 +08:00
// pEvent->m_Button is of type s3ePointerButton and indicates which mouse
// button was pressed. For touchscreens this should always have the value
// S3E_POINTER_BUTTON_SELECT
s3ePointerEvent * pEvent = ( s3ePointerEvent * ) SystemData ;
if ( pEvent - > m_Pressed = = 1 ) {
if ( pEvent - > m_Button = = S3E_POINTER_BUTTON_LEFTMOUSE ) {
g_MousePressed [ 0 ] = true ;
}
if ( pEvent - > m_Button = = S3E_POINTER_BUTTON_RIGHTMOUSE ) {
g_MousePressed [ 1 ] = true ;
}
if ( pEvent - > m_Button = = S3E_POINTER_BUTTON_MIDDLEMOUSE ) {
g_MousePressed [ 2 ] = true ;
}
if ( pEvent - > m_Button = = S3E_POINTER_BUTTON_MOUSEWHEELUP ) {
g_MouseWheel + = pEvent - > m_y ;
}
if ( pEvent - > m_Button = = S3E_POINTER_BUTTON_MOUSEWHEELDOWN ) {
g_MouseWheel + = pEvent - > m_y ;
}
}
return 0 ;
2015-10-09 04:38:37 +08:00
}
2015-10-15 05:01:52 +08:00
//void ImGui_Marmalade_ScrollCallback(double /*xoffset*/,double yoffset)
2015-10-09 04:38:37 +08:00
//{
2015-10-15 05:01:52 +08:00
// g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines.
2015-10-09 04:38:37 +08:00
//}
int32 ImGui_Marmalade_KeyCallback ( void * SystemData , void * userData )
{
2015-10-15 05:01:52 +08:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
s3eKeyboardEvent * e = ( s3eKeyboardEvent * ) SystemData ;
if ( e - > m_Pressed = = 1 ) {
io . KeysDown [ e - > m_Key ] = true ;
}
if ( e - > m_Pressed = = 0 ) {
io . KeysDown [ e - > m_Key ] = false ;
}
io . KeyCtrl = s3eKeyboardGetState ( s3eKeyLeftControl ) = = S3E_KEY_STATE_DOWN | | s3eKeyboardGetState ( s3eKeyRightControl ) = = S3E_KEY_STATE_DOWN ;
io . KeyShift = s3eKeyboardGetState ( s3eKeyLeftShift ) = = S3E_KEY_STATE_DOWN | | s3eKeyboardGetState ( s3eKeyRightShift ) = = S3E_KEY_STATE_DOWN ;
io . KeyAlt = s3eKeyboardGetState ( s3eKeyLeftAlt ) = = S3E_KEY_STATE_DOWN | | s3eKeyboardGetState ( s3eKeyRightAlt ) = = S3E_KEY_STATE_DOWN ;
return 0 ;
2015-10-09 04:38:37 +08:00
}
int32 ImGui_Marmalade_CharCallback ( void * SystemData , void * userData )
{
2015-10-15 05:01:52 +08:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
2015-10-09 04:38:37 +08:00
2015-10-15 05:01:52 +08:00
s3eKeyboardCharEvent * e = ( s3eKeyboardCharEvent * ) SystemData ;
if ( ( e - > m_Char > 0 & & e - > m_Char < 0x10000 ) ) {
io . AddInputCharacter ( ( unsigned short ) e - > m_Char ) ;
}
2015-10-09 04:38:37 +08:00
2015-10-15 05:01:52 +08:00
return 0 ;
2015-10-09 04:38:37 +08:00
}
bool ImGui_Marmalade_CreateDeviceObjects ( )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
// Build texture atlas
unsigned char * pixels ;
int width , height ;
io . Fonts - > GetTexDataAsRGBA32 ( & pixels , & width , & height ) ;
// Create texture
2015-10-15 05:01:52 +08:00
g_FontTexture = new CIwTexture ( ) ;
g_FontTexture - > SetModifiable ( true ) ;
CIwImage & image = g_FontTexture - > GetImage ( ) ;
image . SetFormat ( CIwImage : : ARGB_8888 ) ;
image . SetWidth ( width ) ;
image . SetHeight ( height ) ;
image . SetBuffers ( ) ; // allocates and own buffers
image . ReadTexels ( pixels ) ;
g_FontTexture - > SetMipMapping ( false ) ;
g_FontTexture - > SetFiltering ( false ) ;
g_FontTexture - > Upload ( ) ;
2015-10-09 04:38:37 +08:00
// Store the pointer
io . Fonts - > TexID = ( void * ) g_FontTexture ;
// Cleanup (don't clear the input data if you want to append new fonts later)
io . Fonts - > ClearInputData ( ) ;
io . Fonts - > ClearTexData ( ) ;
return true ;
}
void ImGui_Marmalade_InvalidateDeviceObjects ( )
{
2015-10-15 05:01:52 +08:00
if ( g_ClipboardText ) {
delete [ ] g_ClipboardText ;
g_ClipboardText = 0 ;
}
2015-10-09 04:38:37 +08:00
if ( g_FontTexture )
{
delete g_FontTexture ;
ImGui : : GetIO ( ) . Fonts - > TexID = 0 ;
g_FontTexture = 0 ;
}
}
bool ImGui_Marmalade_Init ( bool install_callbacks )
{
2015-10-15 05:01:52 +08:00
IwGxInit ( ) ;
2015-10-09 04:38:37 +08:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . KeyMap [ ImGuiKey_Tab ] = s3eKeyTab ; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
io . KeyMap [ ImGuiKey_LeftArrow ] = s3eKeyLeft ;
io . KeyMap [ ImGuiKey_RightArrow ] = s3eKeyRight ;
io . KeyMap [ ImGuiKey_UpArrow ] = s3eKeyUp ;
io . KeyMap [ ImGuiKey_DownArrow ] = s3eKeyDown ;
io . KeyMap [ ImGuiKey_PageUp ] = s3eKeyPageUp ;
io . KeyMap [ ImGuiKey_PageDown ] = s3eKeyPageDown ;
io . KeyMap [ ImGuiKey_Home ] = s3eKeyHome ;
io . KeyMap [ ImGuiKey_End ] = s3eKeyEnd ;
io . KeyMap [ ImGuiKey_Delete ] = s3eKeyDelete ;
io . KeyMap [ ImGuiKey_Backspace ] = s3eKeyBackspace ;
io . KeyMap [ ImGuiKey_Enter ] = s3eKeyEnter ;
io . KeyMap [ ImGuiKey_Escape ] = s3eKeyEsc ;
io . KeyMap [ ImGuiKey_A ] = s3eKeyA ;
io . KeyMap [ ImGuiKey_C ] = s3eKeyC ;
io . KeyMap [ ImGuiKey_V ] = s3eKeyV ;
io . KeyMap [ ImGuiKey_X ] = s3eKeyX ;
io . KeyMap [ ImGuiKey_Y ] = s3eKeyY ;
io . KeyMap [ ImGuiKey_Z ] = s3eKeyZ ;
io . RenderDrawListsFn = ImGui_Marmalade_RenderDrawLists ; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.
io . SetClipboardTextFn = ImGui_Marmalade_SetClipboardText ;
io . GetClipboardTextFn = ImGui_Marmalade_GetClipboardText ;
if ( install_callbacks )
{
2015-10-15 05:01:52 +08:00
s3ePointerRegister ( S3E_POINTER_BUTTON_EVENT , ImGui_Marmalade_PointerButtonEventCallback , 0 ) ;
s3eKeyboardRegister ( S3E_KEYBOARD_KEY_EVENT , ImGui_Marmalade_KeyCallback , 0 ) ;
s3eKeyboardRegister ( S3E_KEYBOARD_CHAR_EVENT , ImGui_Marmalade_CharCallback , 0 ) ;
}
2015-10-09 04:38:37 +08:00
return true ;
}
void ImGui_Marmalade_Shutdown ( )
{
ImGui_Marmalade_InvalidateDeviceObjects ( ) ;
ImGui : : Shutdown ( ) ;
2015-10-15 05:01:52 +08:00
IwGxTerminate ( ) ;
2015-10-09 04:38:37 +08:00
}
void ImGui_Marmalade_NewFrame ( )
{
2015-10-15 05:01:52 +08:00
if ( ! g_FontTexture ) {
2015-10-09 04:38:37 +08:00
ImGui_Marmalade_CreateDeviceObjects ( ) ;
2015-10-15 05:01:52 +08:00
}
2015-10-09 04:38:37 +08:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
// Setup display size (every frame to accommodate for window resizing)
int w = IwGxGetScreenWidth ( ) , h = IwGxGetScreenHeight ( ) ;
io . DisplaySize = ImVec2 ( ( float ) w , ( float ) h ) ;
2015-10-15 05:01:52 +08:00
// For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui.
io . DisplayFramebufferScale = g_scale ;
2015-10-09 04:38:37 +08:00
// Setup time step
double current_time = s3eTimerGetUST ( ) / 1000.0f ;
io . DeltaTime = g_Time > 0.0 ? ( float ) ( current_time - g_Time ) : ( float ) ( 1.0f / 60.0f ) ;
g_Time = current_time ;
2015-10-15 05:01:52 +08:00
double mouse_x , mouse_y ;
mouse_x = s3ePointerGetX ( ) ;
mouse_y = s3ePointerGetY ( ) ;
io . MousePos = ImVec2 ( ( float ) mouse_x / g_scale . x , ( float ) mouse_y / g_scale . y ) ; // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.)
2015-10-09 04:38:37 +08:00
2015-10-15 05:01:52 +08:00
for ( int i = 0 ; i < 3 ; i + + ) {
2015-10-09 04:38:37 +08:00
io . MouseDown [ i ] = g_MousePressed [ i ] | | s3ePointerGetState ( ( s3ePointerButton ) i ) ! = S3E_POINTER_STATE_UP ; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
g_MousePressed [ i ] = false ;
}
io . MouseWheel = g_MouseWheel ;
g_MouseWheel = 0.0f ;
// Hide OS mouse cursor if ImGui is drawing it
2015-10-15 05:01:52 +08:00
// s3ePointerSetInt(S3E_POINTER_HIDE_CURSOR,(io.MouseDrawCursor ? 0 : 1));
2015-10-09 04:38:37 +08:00
// Start the frame
ImGui : : NewFrame ( ) ;
2015-10-15 05:01:52 +08:00
// show/hide OSD keyboard
if ( io . WantTextInput ) { // some text input widget is active?
if ( ! g_osdKeyboardEnabled ) {
g_osdKeyboardEnabled = true ;
s3eKeyboardSetInt ( S3E_KEYBOARD_GET_CHAR , 1 ) ; // show OSD keyboard
}
}
else { // no text input widget is active
if ( g_osdKeyboardEnabled ) {
g_osdKeyboardEnabled = false ;
s3eKeyboardSetInt ( S3E_KEYBOARD_GET_CHAR , 0 ) ; // hide OSD keyboard
}
}
2015-10-09 04:38:37 +08:00
}