need to add streaming because memory is too small to store all lines initial test of PD control in physics server, need to switch to PD control for motor constraint, instead of using external forces.
631 lines
15 KiB
C++
631 lines
15 KiB
C++
|
|
#include "gwenUserInterface.h"
|
|
#include "gwenInternalData.h"
|
|
#include "Gwen/Controls/ImagePanel.h"
|
|
#include "Gwen/Controls/ColorPicker.h"
|
|
//#include "Gwen/Controls/HSVColorPicker.h"
|
|
|
|
class MyGraphWindow* graphWindow = 0;
|
|
|
|
|
|
|
|
GwenUserInterface::GwenUserInterface()
|
|
{
|
|
m_data = new GwenInternalData();
|
|
m_data->m_toggleButtonCallback = 0;
|
|
m_data->m_comboBoxCallback = 0;
|
|
|
|
}
|
|
|
|
GwenUserInterface::~GwenUserInterface()
|
|
{
|
|
for (int i=0;i<m_data->m_handlers.size();i++)
|
|
{
|
|
delete m_data->m_handlers[i];
|
|
}
|
|
|
|
m_data->m_handlers.clear();
|
|
|
|
|
|
delete m_data->pCanvas;
|
|
|
|
|
|
delete m_data;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MyMenuItems : public Gwen::Controls::Base
|
|
{
|
|
public:
|
|
|
|
b3FileOpenCallback m_fileOpenCallback;
|
|
b3QuitCallback m_quitCallback;
|
|
|
|
MyMenuItems() :Gwen::Controls::Base(0),m_fileOpenCallback(0)
|
|
{
|
|
}
|
|
void myQuitApp( Gwen::Controls::Base* pControl )
|
|
{
|
|
if (m_quitCallback)
|
|
{
|
|
(*m_quitCallback)();
|
|
}
|
|
}
|
|
void fileOpen( Gwen::Controls::Base* pControl )
|
|
{
|
|
if (m_fileOpenCallback)
|
|
{
|
|
(*m_fileOpenCallback)();
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
struct MyTestMenuBar : public Gwen::Controls::MenuStrip
|
|
{
|
|
|
|
Gwen::Controls::MenuItem* m_fileMenu;
|
|
Gwen::Controls::MenuItem* m_viewMenu;
|
|
MyMenuItems* m_menuItems;
|
|
|
|
MyTestMenuBar(Gwen::Controls::Base* pParent)
|
|
:Gwen::Controls::MenuStrip(pParent)
|
|
{
|
|
// Gwen::Controls::MenuStrip* menu = new Gwen::Controls::MenuStrip( pParent );
|
|
{
|
|
m_menuItems = new MyMenuItems();
|
|
m_menuItems->m_fileOpenCallback = 0;
|
|
m_menuItems->m_quitCallback = 0;
|
|
|
|
m_fileMenu = AddItem( L"File" );
|
|
|
|
m_fileMenu->GetMenu()->AddItem(L"Open",m_menuItems,(Gwen::Event::Handler::Function)&MyMenuItems::fileOpen);
|
|
m_fileMenu->GetMenu()->AddItem(L"Quit",m_menuItems,(Gwen::Event::Handler::Function)&MyMenuItems::myQuitApp);
|
|
m_viewMenu = AddItem( L"View" );
|
|
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
void GwenUserInterface::resize(int width, int height)
|
|
{
|
|
m_data->pCanvas->SetSize(width,height);
|
|
}
|
|
|
|
|
|
struct MyComboBoxHander :public Gwen::Event::Handler
|
|
{
|
|
GwenInternalData* m_data;
|
|
int m_buttonId;
|
|
|
|
MyComboBoxHander (GwenInternalData* data, int buttonId)
|
|
:m_data(data),
|
|
m_buttonId(buttonId)
|
|
{
|
|
}
|
|
|
|
void onSelect( Gwen::Controls::Base* pControl )
|
|
{
|
|
Gwen::Controls::ComboBox* but = (Gwen::Controls::ComboBox*) pControl;
|
|
|
|
|
|
|
|
Gwen::String str = Gwen::Utility::UnicodeToString( but->GetSelectedItem()->GetText());
|
|
|
|
if (m_data->m_comboBoxCallback)
|
|
(*m_data->m_comboBoxCallback)(m_buttonId,str.c_str());
|
|
}
|
|
|
|
};
|
|
|
|
struct MyButtonHander :public Gwen::Event::Handler
|
|
{
|
|
GwenInternalData* m_data;
|
|
int m_buttonId;
|
|
|
|
MyButtonHander (GwenInternalData* data, int buttonId)
|
|
:m_data(data),
|
|
m_buttonId(buttonId)
|
|
{
|
|
}
|
|
|
|
void onButtonA( Gwen::Controls::Base* pControl )
|
|
{
|
|
Gwen::Controls::Button* but = (Gwen::Controls::Button*) pControl;
|
|
// int dep = but->IsDepressed();
|
|
int tog = but->GetToggleState();
|
|
if (m_data->m_toggleButtonCallback)
|
|
(*m_data->m_toggleButtonCallback)(m_buttonId,tog);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
void GwenUserInterface::textOutput(const char* message)
|
|
{
|
|
Gwen::UnicodeString msg = Gwen::Utility::StringToUnicode(message);
|
|
m_data->m_TextOutput->AddItem( msg );
|
|
m_data->m_TextOutput->Scroller()->ScrollToBottom();
|
|
}
|
|
|
|
|
|
void GwenUserInterface::setExampleDescription(const char* message)
|
|
{
|
|
//Gwen apparently doesn't have text/word wrap, so do rudimentary brute-force implementation here.
|
|
|
|
std::string wrapmessage=message;
|
|
int startPos = 0;
|
|
|
|
std::string lastFit = "";
|
|
bool hasSpace = false;
|
|
std::string lastFitSpace = "";
|
|
int spacePos = 0;
|
|
|
|
m_data->m_exampleInfoTextOutput->Clear();
|
|
int fixedWidth = m_data->m_exampleInfoTextOutput->GetBounds().w-25;
|
|
int wrapLen = int(wrapmessage.length());
|
|
for (int endPos=0;endPos<=wrapLen;endPos++)
|
|
{
|
|
std::string sub = wrapmessage.substr(startPos,(endPos-startPos));
|
|
Gwen::Point pt = m_data->pRenderer->MeasureText(m_data->pCanvas->GetSkin()->GetDefaultFont(),sub);
|
|
|
|
if (pt.x <= fixedWidth)
|
|
{
|
|
lastFit = sub;
|
|
|
|
if (message[endPos]==' ' ||message[endPos]=='.' || message[endPos]==',' )
|
|
{
|
|
hasSpace = true;
|
|
lastFitSpace = sub;
|
|
spacePos = endPos;
|
|
}
|
|
} else
|
|
{
|
|
//submit and
|
|
if (hasSpace)
|
|
{
|
|
endPos = spacePos+1;
|
|
hasSpace = false;
|
|
lastFit = lastFitSpace;
|
|
startPos = endPos;
|
|
} else
|
|
{
|
|
startPos = endPos-1;
|
|
}
|
|
Gwen::UnicodeString msg = Gwen::Utility::StringToUnicode(lastFit);
|
|
|
|
m_data->m_exampleInfoTextOutput->AddItem( msg );
|
|
m_data->m_exampleInfoTextOutput->Scroller()->ScrollToBottom();
|
|
|
|
}
|
|
}
|
|
|
|
if (lastFit.length())
|
|
{
|
|
Gwen::UnicodeString msg = Gwen::Utility::StringToUnicode(lastFit);
|
|
m_data->m_exampleInfoTextOutput->AddItem( msg );
|
|
m_data->m_exampleInfoTextOutput->Scroller()->ScrollToBottom();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GwenUserInterface::setStatusBarMessage(const char* message, bool isLeft)
|
|
{
|
|
Gwen::UnicodeString msg = Gwen::Utility::StringToUnicode(message);
|
|
if (isLeft)
|
|
{
|
|
m_data->m_leftStatusBar->SetText( msg);
|
|
} else
|
|
{
|
|
m_data->m_rightStatusBar->SetText( msg);
|
|
|
|
}
|
|
}
|
|
|
|
void GwenUserInterface::registerFileOpenCallback(b3FileOpenCallback callback)
|
|
{
|
|
m_data->m_menuItems->m_fileOpenCallback = callback;
|
|
}
|
|
|
|
void GwenUserInterface::registerQuitCallback(b3QuitCallback callback)
|
|
{
|
|
m_data->m_menuItems->m_quitCallback = callback;
|
|
}
|
|
|
|
void GwenUserInterface::init(int width, int height,Gwen::Renderer::Base* renderer,float retinaScale)
|
|
{
|
|
m_data->m_curYposition = 20;
|
|
//m_data->m_primRenderer = new GLPrimitiveRenderer(width,height);
|
|
m_data->pRenderer = renderer;//new GwenOpenGL3CoreRenderer(m_data->m_primRenderer,stash,width,height,retinaScale);
|
|
|
|
m_data->skin.SetRender( m_data->pRenderer );
|
|
|
|
m_data->pCanvas= new Gwen::Controls::Canvas( &m_data->skin );
|
|
m_data->pCanvas->SetSize( width,height);
|
|
m_data->pCanvas->SetDrawBackground( false);
|
|
m_data->pCanvas->SetBackgroundColor( Gwen::Color( 150, 170, 170, 255 ) );
|
|
|
|
|
|
|
|
MyTestMenuBar* menubar = new MyTestMenuBar(m_data->pCanvas);
|
|
m_data->m_viewMenu = menubar->m_viewMenu;
|
|
m_data->m_menuItems = menubar->m_menuItems;
|
|
|
|
|
|
|
|
|
|
Gwen::Controls::StatusBar* bar = new Gwen::Controls::StatusBar(m_data->pCanvas);
|
|
m_data->m_rightStatusBar = new Gwen::Controls::Label( bar );
|
|
m_data->m_rightStatusBar->SetWidth(width/2);
|
|
//m_data->m_rightStatusBar->SetText( L"Label Added to Right" );
|
|
bar->AddControl( m_data->m_rightStatusBar, true );
|
|
|
|
m_data->m_TextOutput = new Gwen::Controls::ListBox( m_data->pCanvas );
|
|
m_data->m_TextOutput->Dock( Gwen::Pos::Bottom );
|
|
m_data->m_TextOutput->SetHeight( 100 );
|
|
|
|
m_data->m_leftStatusBar = new Gwen::Controls::Label( bar );
|
|
//m_data->m_leftStatusBar->SetText( L"Label Added to Left" );
|
|
m_data->m_leftStatusBar->SetWidth(width/2);
|
|
bar->AddControl( m_data->m_leftStatusBar,false);
|
|
//Gwen::KeyboardFocus
|
|
/*Gwen::Controls::GroupBox* box = new Gwen::Controls::GroupBox(m_data->pCanvas);
|
|
box->SetText("text");
|
|
box->SetName("name");
|
|
box->SetHeight(500);
|
|
*/
|
|
Gwen::Controls::ScrollControl* windowRight= new Gwen::Controls::ScrollControl(m_data->pCanvas);
|
|
windowRight->Dock(Gwen::Pos::Right);
|
|
windowRight->SetWidth(250);
|
|
windowRight->SetHeight(250);
|
|
windowRight->SetScroll(false,true);
|
|
|
|
|
|
|
|
//windowLeft->SetSkin(
|
|
Gwen::Controls::TabControl* tab = new Gwen::Controls::TabControl(windowRight);
|
|
|
|
//tab->SetHeight(300);
|
|
tab->SetWidth(240);
|
|
tab->SetHeight(1250);
|
|
//tab->Dock(Gwen::Pos::Left);
|
|
tab->Dock( Gwen::Pos::Fill );
|
|
//tab->SetMargin( Gwen::Margin( 2, 2, 2, 2 ) );
|
|
|
|
Gwen::UnicodeString str1(L"Params");
|
|
m_data->m_demoPage = tab->AddPage(str1);
|
|
|
|
|
|
|
|
|
|
// Gwen::UnicodeString str2(L"OpenCL");
|
|
// tab->AddPage(str2);
|
|
//Gwen::UnicodeString str3(L"page3");
|
|
// tab->AddPage(str3);
|
|
|
|
|
|
|
|
//but->onPress.Add(handler, &MyHander::onButtonA);
|
|
|
|
|
|
|
|
//box->Dock(Gwen::Pos::Left);
|
|
|
|
/*Gwen::Controls::WindowControl* windowBottom = new Gwen::Controls::WindowControl(m_data->pCanvas);
|
|
windowBottom->SetHeight(100);
|
|
windowBottom->Dock(Gwen::Pos::Bottom);
|
|
windowBottom->SetTitle("bottom");
|
|
*/
|
|
// Gwen::Controls::Property::Text* prop = new Gwen::Controls::Property::Text(m_data->pCanvas);
|
|
//prop->Dock(Gwen::Pos::Bottom);
|
|
/*Gwen::Controls::SplitterBar* split = new Gwen::Controls::SplitterBar(m_data->pCanvas);
|
|
split->Dock(Gwen::Pos::Center);
|
|
split->SetHeight(300);
|
|
split->SetWidth(300);
|
|
*/
|
|
/*
|
|
|
|
|
|
*/
|
|
|
|
Gwen::Controls::ScrollControl* windowLeft = new Gwen::Controls::ScrollControl(m_data->pCanvas);
|
|
windowLeft->Dock(Gwen::Pos::Left);
|
|
// windowLeft->SetTitle("title");
|
|
windowLeft->SetScroll(false, false);
|
|
windowLeft->SetWidth(250);
|
|
windowLeft->SetPos(50, 50);
|
|
windowLeft->SetHeight(500);
|
|
//windowLeft->SetClosable(false);
|
|
// windowLeft->SetShouldDrawBackground(true);
|
|
windowLeft->SetTabable(true);
|
|
|
|
Gwen::Controls::TabControl* explorerTab = new Gwen::Controls::TabControl(windowLeft);
|
|
|
|
//tab->SetHeight(300);
|
|
// explorerTab->SetWidth(230);
|
|
explorerTab->SetHeight(250);
|
|
//tab->Dock(Gwen::Pos::Left);
|
|
explorerTab->Dock(Gwen::Pos::Fill);
|
|
|
|
|
|
|
|
|
|
|
|
//m_data->m_exampleInfoTextOutput->SetBounds(2, 10, 236, 400);
|
|
|
|
//windowRight
|
|
|
|
Gwen::UnicodeString explorerStr1(L"Explorer");
|
|
m_data->m_explorerPage = explorerTab->AddPage(explorerStr1);
|
|
Gwen::UnicodeString shapesStr1(L"Test");
|
|
Gwen::Controls::TabButton* shapes = explorerTab->AddPage(shapesStr1);
|
|
|
|
///todo(erwincoumans) figure out why the HSV color picker is extremely slow
|
|
//Gwen::Controls::HSVColorPicker* color = new Gwen::Controls::HSVColorPicker(shapes->GetPage());
|
|
Gwen::Controls::ColorPicker* color = new Gwen::Controls::ColorPicker(shapes->GetPage());
|
|
color->SetKeyboardInputEnabled(true);
|
|
|
|
Gwen::Controls::TreeControl* ctrl = new Gwen::Controls::TreeControl(m_data->m_explorerPage->GetPage());
|
|
m_data->m_explorerTreeCtrl = ctrl;
|
|
ctrl->SetKeyboardInputEnabled(true);
|
|
ctrl->Focus();
|
|
ctrl->SetBounds(2, 10, 236, 300);
|
|
|
|
m_data->m_exampleInfoGroupBox = new Gwen::Controls::Label( m_data->m_explorerPage->GetPage() );
|
|
m_data->m_exampleInfoGroupBox->SetPos(2, 314);
|
|
m_data->m_exampleInfoGroupBox->SetHeight( 15 );
|
|
m_data->m_exampleInfoGroupBox->SetWidth(234);
|
|
m_data->m_exampleInfoGroupBox->SetText("Example Description");
|
|
|
|
m_data->m_exampleInfoTextOutput = new Gwen::Controls::ListBox(m_data->m_explorerPage->GetPage());
|
|
|
|
|
|
//m_data->m_exampleInfoTextOutput->Dock( Gwen::Pos::Bottom );
|
|
m_data->m_exampleInfoTextOutput->SetPos(2, 332);
|
|
m_data->m_exampleInfoTextOutput->SetHeight( 150 );
|
|
m_data->m_exampleInfoTextOutput->SetWidth(233);
|
|
|
|
|
|
|
|
}
|
|
|
|
void GwenUserInterface::forceUpdateScrollBars()
|
|
{
|
|
b3Assert(m_data);
|
|
b3Assert(m_data->m_explorerTreeCtrl);
|
|
if (m_data && m_data->m_explorerTreeCtrl)
|
|
{
|
|
m_data->m_explorerTreeCtrl->ForceUpdateScrollBars();
|
|
}
|
|
}
|
|
|
|
void GwenUserInterface::setFocus()
|
|
{
|
|
b3Assert(m_data);
|
|
b3Assert(m_data->m_explorerTreeCtrl);
|
|
if (m_data && m_data->m_explorerTreeCtrl)
|
|
{
|
|
m_data->m_explorerTreeCtrl->Focus();
|
|
}
|
|
}
|
|
|
|
b3ToggleButtonCallback GwenUserInterface::getToggleButtonCallback()
|
|
{
|
|
return m_data->m_toggleButtonCallback;
|
|
}
|
|
|
|
void GwenUserInterface::setToggleButtonCallback(b3ToggleButtonCallback callback)
|
|
{
|
|
m_data->m_toggleButtonCallback = callback;
|
|
}
|
|
void GwenUserInterface::registerToggleButton(int buttonId, const char* name)
|
|
{
|
|
assert(m_data);
|
|
assert(m_data->m_demoPage);
|
|
|
|
Gwen::Controls::Button* but = new Gwen::Controls::Button(m_data->m_demoPage->GetPage());
|
|
|
|
///some heuristic to find the button location
|
|
int ypos = m_data->m_curYposition;
|
|
but->SetPos(10, ypos );
|
|
but->SetWidth( 200 );
|
|
//but->SetBounds( 200, 30, 300, 200 );
|
|
|
|
MyButtonHander* handler = new MyButtonHander(m_data, buttonId);
|
|
m_data->m_handlers.push_back(handler);
|
|
m_data->m_curYposition+=22;
|
|
but->onToggle.Add(handler, &MyButtonHander::onButtonA);
|
|
but->SetIsToggle(true);
|
|
but->SetToggleState(false);
|
|
but->SetText(name);
|
|
|
|
}
|
|
|
|
void GwenUserInterface::setComboBoxCallback(b3ComboBoxCallback callback)
|
|
{
|
|
m_data->m_comboBoxCallback = callback;
|
|
}
|
|
|
|
b3ComboBoxCallback GwenUserInterface::getComboBoxCallback()
|
|
{
|
|
return m_data->m_comboBoxCallback;
|
|
}
|
|
void GwenUserInterface::registerComboBox(int comboboxId, int numItems, const char** items, int startItem)
|
|
{
|
|
Gwen::Controls::ComboBox* combobox = new Gwen::Controls::ComboBox(m_data->m_demoPage->GetPage());
|
|
MyComboBoxHander* handler = new MyComboBoxHander(m_data, comboboxId);
|
|
m_data->m_handlers.push_back(handler);
|
|
|
|
combobox->onSelection.Add(handler,&MyComboBoxHander::onSelect);
|
|
int ypos = m_data->m_curYposition;
|
|
combobox->SetPos(10, ypos );
|
|
combobox->SetWidth( 100 );
|
|
//box->SetPos(120,130);
|
|
for (int i=0;i<numItems;i++)
|
|
{
|
|
Gwen::Controls::MenuItem* item = combobox->AddItem(Gwen::Utility::StringToUnicode(items[i]));
|
|
if (i==startItem)
|
|
combobox->OnItemSelected(item);
|
|
}
|
|
|
|
m_data->m_curYposition+=22;
|
|
|
|
|
|
|
|
}
|
|
|
|
void GwenUserInterface::draw(int width, int height)
|
|
{
|
|
|
|
// printf("width = %d, height=%d\n", width,height);
|
|
if (m_data->pCanvas)
|
|
{
|
|
m_data->pCanvas->SetSize(width,height);
|
|
//m_data->m_primRenderer->setScreenSize(width,height);
|
|
m_data->pRenderer->Resize(width,height);
|
|
m_data->pCanvas->RenderCanvas();
|
|
//restoreOpenGLState();
|
|
}
|
|
|
|
}
|
|
|
|
bool GwenUserInterface::mouseMoveCallback( float x, float y)
|
|
{
|
|
bool handled = false;
|
|
|
|
static int m_lastmousepos[2] = {0,0};
|
|
static bool isInitialized = false;
|
|
if (m_data->pCanvas)
|
|
{
|
|
if (!isInitialized)
|
|
{
|
|
isInitialized = true;
|
|
m_lastmousepos[0] = x+1;
|
|
m_lastmousepos[1] = y+1;
|
|
}
|
|
handled = m_data->pCanvas->InputMouseMoved(x,y,m_lastmousepos[0],m_lastmousepos[1]);
|
|
}
|
|
return handled;
|
|
|
|
}
|
|
#include "../CommonInterfaces/CommonWindowInterface.h"
|
|
|
|
bool GwenUserInterface::keyboardCallback(int bulletKey, int state)
|
|
{
|
|
int gwenKey = -1;
|
|
if (m_data->pCanvas)
|
|
{
|
|
//convert 'Bullet' keys into 'Gwen' keys
|
|
switch (bulletKey)
|
|
{
|
|
case B3G_RETURN:
|
|
{
|
|
gwenKey = Gwen::Key::Return;
|
|
break;
|
|
}
|
|
case B3G_LEFT_ARROW:
|
|
{
|
|
gwenKey = Gwen::Key::Left;
|
|
break;
|
|
}
|
|
case B3G_RIGHT_ARROW:
|
|
{
|
|
gwenKey = Gwen::Key::Right;
|
|
break;
|
|
}
|
|
case B3G_UP_ARROW:
|
|
{
|
|
gwenKey = Gwen::Key::Up;
|
|
break;
|
|
}
|
|
case B3G_DOWN_ARROW:
|
|
{
|
|
gwenKey = Gwen::Key::Down;
|
|
break;
|
|
}
|
|
case B3G_BACKSPACE:
|
|
{
|
|
gwenKey = Gwen::Key::Backspace;
|
|
break;
|
|
}
|
|
case B3G_DELETE:
|
|
{
|
|
gwenKey = Gwen::Key::Delete;
|
|
break;
|
|
}
|
|
case B3G_HOME:
|
|
{
|
|
gwenKey = Gwen::Key::Home;
|
|
break;
|
|
}
|
|
case B3G_END:
|
|
{
|
|
gwenKey = Gwen::Key::End;
|
|
break;
|
|
}
|
|
case B3G_SHIFT:
|
|
{
|
|
gwenKey = Gwen::Key::Shift;
|
|
break;
|
|
}
|
|
case B3G_CONTROL:
|
|
{
|
|
gwenKey = Gwen::Key::Control;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
}
|
|
};
|
|
bool bDown = (state == 1);
|
|
|
|
if (gwenKey>=0)
|
|
{
|
|
return m_data->pCanvas->InputKey(gwenKey,state==1);
|
|
} else
|
|
{
|
|
if (bulletKey<256 && state)
|
|
{
|
|
Gwen::UnicodeChar c = ( Gwen::UnicodeChar ) bulletKey;
|
|
return m_data->pCanvas->InputCharacter(c);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool GwenUserInterface::mouseButtonCallback(int button, int state, float x, float y)
|
|
{
|
|
bool handled = false;
|
|
if (m_data->pCanvas)
|
|
{
|
|
handled = m_data->pCanvas->InputMouseMoved(x,y,x, y);
|
|
|
|
if (button>=0)
|
|
{
|
|
handled = m_data->pCanvas->InputMouseButton(button,(bool)state);
|
|
if (handled)
|
|
{
|
|
//if (!state)
|
|
// return false;
|
|
}
|
|
}
|
|
}
|
|
return handled;
|
|
}
|