Commit 40480a78 authored by hybrid's avatar hybrid

Merged revisions 4001-4056 from 1.7 branch. Keycode updates, fix compilation...

Merged revisions 4001-4056 from 1.7 branch. Keycode updates, fix compilation errors, vector normalize error case fixed, joystick safety fixes, editbox updates, meshviewer modal window fix, isPointInsideFast changes.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4057 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 66a6bbde
...@@ -293,12 +293,30 @@ The following names can be queried for the given types: ...@@ -293,12 +293,30 @@ The following names can be queried for the given types:
----------------------------- -----------------------------
Changes in 1.7.3 (??.??.2011) Changes in 1.7.3 (??.??.2011)
- Document that triangle3d::isPointInside should not be used with int's.
- triangle3d::isPointInsideFast handles 'on-border' cases now consistently.
- Bugfix: vector2d.normalize() and vector3d.normalize() had returned wrong results with very short vectors since Irrlicht 1.5. Thanks to Willem Swart for Bugreport + testcase.
- Unknown keymappings now use the X11 keycode instead of 0 to make such keys at least usable in games.
- KeyMapping for KeyInput.Key on X11 ignores states like shift&ctrl now like on Windows.
- Additional keymappings for X11 (tested with german and us keyboards which seem to work now in all cases).
- Fix crash in multiline editbox when pasting several lines into it on Windows.
- example 09.Meshviewer no longer catches keys while a modal dialog is open
- editbox no longer displays cursor when disabled
- editbox autoscrolling now at least works good enough to actually show the text which the user is typing in.
- editbox no longer moves text into next line when it fails wrapping creating senseless empty lines which mess up scrolling. - editbox no longer moves text into next line when it fails wrapping creating senseless empty lines which mess up scrolling.
- Fix crash in editbox when scrolling up with empty first lines caused by textwrapping. - Fix crash in editbox when scrolling up with empty first lines caused by textwrapping.
- triangle3d::isPointInside can now work with larger integers, old version failed already with values in the 3-digit range. It got also faster. (thx @ Eigen for report + testcase and REDDemon for patch proposal).
- Fix focus problem when removing an unfocused modal dialog reported by Reiko here: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=44358 - Fix focus problem when removing an unfocused modal dialog reported by Reiko here: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=44358
- Add integer template specialization for vector3d::getSphericalCoordinateAngles which rounds angles to nearest integer now. - Add integer template specialization for vector3d::getSphericalCoordinateAngles which rounds angles to nearest integer now.
......
...@@ -147,8 +147,7 @@ void updateScaleInfo(scene::ISceneNode* model) ...@@ -147,8 +147,7 @@ void updateScaleInfo(scene::ISceneNode* model)
} }
/* /*
The three following functions do several stuff used by the mesh viewer. The Function showAboutText() displays a messagebox with a caption and
first function showAboutText() simply displays a messagebox with a caption and
a message text. The texts will be stored in the MessageText and Caption a message text. The texts will be stored in the MessageText and Caption
variables at startup. variables at startup.
*/ */
...@@ -162,7 +161,7 @@ void showAboutText() ...@@ -162,7 +161,7 @@ void showAboutText()
/* /*
The second function loadModel() loads a model and displays it using an Function loadModel() loads a model and displays it using an
addAnimatedMeshSceneNode and the scene manager. Nothing difficult. It also addAnimatedMeshSceneNode and the scene manager. Nothing difficult. It also
displays a short message box, if the model could not be loaded. displays a short message box, if the model could not be loaded.
*/ */
...@@ -259,7 +258,7 @@ void loadModel(const c8* fn) ...@@ -259,7 +258,7 @@ void loadModel(const c8* fn)
/* /*
Finally, the third function creates a toolbox window. In this simple mesh Function createToolBox() creates a toolbox window. In this simple mesh
viewer, this toolbox only contains a tab control with three edit boxes for viewer, this toolbox only contains a tab control with three edit boxes for
changing the scale of the displayed model. changing the scale of the displayed model.
*/ */
...@@ -323,6 +322,10 @@ void createToolBox() ...@@ -323,6 +322,10 @@ void createToolBox()
scrollbar->setSmallStep(1); scrollbar->setSmallStep(1);
} }
/*
Function updateToolBox() is called each frame to update dynamic information in
the toolbox.
*/
void updateToolBox() void updateToolBox()
{ {
IGUIEnvironment* env = Device->getGUIEnvironment(); IGUIEnvironment* env = Device->getGUIEnvironment();
...@@ -375,11 +378,27 @@ void onKillFocus() ...@@ -375,11 +378,27 @@ void onKillFocus()
} }
} }
/*
Function hasModalDialog() checks if we currently have a modal dialog open.
*/
bool hasModalDialog()
{
IGUIEnvironment* env = Device->getGUIEnvironment();
IGUIElement * focused = env->getFocus();
while ( focused )
{
if ( focused->isVisible() && focused->hasType(EGUIET_MODAL_SCREEN) )
return true;
focused = focused->getParent();
}
return false;
}
/* /*
To get all the events sent by the GUI Elements, we need to create an event To get all the events sent by the GUI Elements, we need to create an event
receiver. This one is really simple. If an event occurs, it checks the id of receiver. This one is really simple. If an event occurs, it checks the id of
the caller and the event type, and starts an action based on these values. For the caller and the event type, and starts an action based on these values. For
example, if a menu item with id GUI_ID_OPEN_MODEL was selected, if opens a file-open-dialog. example, if a menu item with id GUI_ID_OPEN_MODEL was selected, it opens a file-open-dialog.
*/ */
class MyEventReceiver : public IEventReceiver class MyEventReceiver : public IEventReceiver
{ {
...@@ -503,6 +522,11 @@ public: ...@@ -503,6 +522,11 @@ public:
*/ */
bool OnKeyUp(irr::EKEY_CODE keyCode) bool OnKeyUp(irr::EKEY_CODE keyCode)
{ {
// Don't handle keys if we have a modal dialog open as it would lead
// to unexpected application behaviour for the user.
if ( hasModalDialog() )
return false;
if (keyCode == irr::KEY_ESCAPE) if (keyCode == irr::KEY_ESCAPE)
{ {
if (Device) if (Device)
......
...@@ -788,7 +788,7 @@ funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename) ...@@ -788,7 +788,7 @@ funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename)
#endif #endif
/* /*
get the current collision respone camera animator get the current collision response camera animator
*/ */
ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * device ) ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * device )
{ {
......
...@@ -69,9 +69,9 @@ namespace gui ...@@ -69,9 +69,9 @@ namespace gui
//! Sets text justification mode //! Sets text justification mode
/** \param horizontal: EGUIA_UPPERLEFT for left justified (default), /** \param horizontal: EGUIA_UPPERLEFT for left justified (default),
EGUIA_LOWEERRIGHT for right justified, or EGUIA_CENTER for centered text. EGUIA_LOWERRIGHT for right justified, or EGUIA_CENTER for centered text.
\param vertical: EGUIA_UPPERLEFT to align with top edge, \param vertical: EGUIA_UPPERLEFT to align with top edge,
EGUIA_LOWEERRIGHT for bottom edge, or EGUIA_CENTER for centered text (default). */ EGUIA_LOWERRIGHT for bottom edge, or EGUIA_CENTER for centered text (default). */
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0; virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0;
//! Enables or disables word wrap. //! Enables or disables word wrap.
......
...@@ -141,10 +141,20 @@ namespace irr ...@@ -141,10 +141,20 @@ namespace irr
KEY_RCONTROL = 0xA3, // Right CONTROL key KEY_RCONTROL = 0xA3, // Right CONTROL key
KEY_LMENU = 0xA4, // Left MENU key KEY_LMENU = 0xA4, // Left MENU key
KEY_RMENU = 0xA5, // Right MENU key KEY_RMENU = 0xA5, // Right MENU key
KEY_PLUS = 0xBB, // Plus Key (+) KEY_OEM_1 = 0xBA, // for US ";:"
KEY_COMMA = 0xBC, // Comma Key (,) KEY_PLUS = 0xBB, // Plus Key "+"
KEY_MINUS = 0xBD, // Minus Key (-) KEY_COMMA = 0xBC, // Comma Key ","
KEY_PERIOD = 0xBE, // Period Key (.) KEY_MINUS = 0xBD, // Minus Key "-"
KEY_PERIOD = 0xBE, // Period Key "."
KEY_OEM_2 = 0xBF, // for US "/?"
KEY_OEM_3 = 0xC0, // for US "`~"
KEY_OEM_4 = 0xDB, // for US "[{"
KEY_OEM_5 = 0xDC, // for US "\|"
KEY_OEM_6 = 0xDD, // for US "]}"
KEY_OEM_7 = 0xDE, // for US "'""
KEY_OEM_8 = 0xDF, // None
KEY_OEM_AX = 0xE1, // for Japan "AX"
KEY_OEM_102 = 0xE2, // "<>" or "\|"
KEY_ATTN = 0xF6, // Attn key KEY_ATTN = 0xF6, // Attn key
KEY_CRSEL = 0xF7, // CrSel key KEY_CRSEL = 0xF7, // CrSel key
KEY_EXSEL = 0xF8, // ExSel key KEY_EXSEL = 0xF8, // ExSel key
......
...@@ -82,10 +82,27 @@ namespace core ...@@ -82,10 +82,27 @@ namespace core
} }
//! Check if a point is inside the triangle (border-points count also as inside) //! Check if a point is inside the triangle (border-points count also as inside)
/** \param p Point to test. Assumes that this point is already /** NOTE: When working with T='int' you should prefer isPointInsideFast, as
isPointInside will run into number-overflows already with coordinates in the 3-digit-range.
\param p Point to test. Assumes that this point is already
on the plane of the triangle. on the plane of the triangle.
\return True if the point is inside the triangle, otherwise false. */ \return True if the point is inside the triangle, otherwise false. */
bool isPointInside(const vector3d<T>& p) const bool isPointInside(const vector3d<T>& p) const
{
return (isOnSameSide(p, pointA, pointB, pointC) &&
isOnSameSide(p, pointB, pointA, pointC) &&
isOnSameSide(p, pointC, pointA, pointB));
}
//! Check if a point is inside the triangle (border-points count also as inside)
/** This method uses a barycentric coordinate system.
It is faster than isPointInside but is more susceptible to floating point rounding
errors. This will especially be noticable when the FPU is in single precision mode
(which is for example set on default by Direct3D).
\param p Point to test. Assumes that this point is already
on the plane of the triangle.
\return True if point is inside the triangle, otherwise false. */
bool isPointInsideFast(const vector3d<T>& p) const
{ {
const vector3d<T> a = pointC - pointA; const vector3d<T> a = pointC - pointA;
const vector3d<T> b = pointB - pointA; const vector3d<T> b = pointB - pointA;
...@@ -105,38 +122,7 @@ namespace core ...@@ -105,38 +122,7 @@ namespace core
// We count border-points as inside to keep downward compatibility. // We count border-points as inside to keep downward compatibility.
// That's why we use >= and <= instead of > and < as more commonly seen on the web. // That's why we use >= and <= instead of > and < as more commonly seen on the web.
return (u >= 0) && (v >= 0) && (u + v <= 1); return (u >= 0) && (v >= 0) && (u + v <= 1);
}
//! Check if a point is inside the triangle.
/** This method is an implementation of the example used in a
paper by Kasper Fauerby original written by Keidy from
Mr-Gamemaker.
This was once faster than an old isPointInside implementation, but the
current isPointInside is usualy as fast, sometimes even faster.
Border-points in isPointInsideFast are not defined, some are inside and some outside.
\param p Point to test. Assumes that this point is already
on the plane of the triangle.
\return True if point is inside the triangle, otherwise false. */
bool isPointInsideFast(const vector3d<T>& p) const
{
const vector3d<T> f = pointB - pointA;
const vector3d<T> g = pointC - pointA;
const f32 a = f.dotProduct(f);
const f32 b = f.dotProduct(g);
const f32 c = g.dotProduct(g);
const vector3d<T> vp = p - pointA;
const f32 d = vp.dotProduct(f);
const f32 e = vp.dotProduct(g);
f32 x = (d*c)-(e*b);
f32 y = (e*a)-(d*b);
const f32 ac_bb = (a*c)-(b*b);
f32 z = x+y-ac_bb;
// return sign(z) && !(sign(x)||sign(y))
return (( (IR(z)) & ~((IR(x))|(IR(y))) ) & 0x80000000)!=0;
} }
......
...@@ -170,7 +170,7 @@ public: ...@@ -170,7 +170,7 @@ public:
vector2d<T>& normalize() vector2d<T>& normalize()
{ {
f32 length = (f32)(X*X + Y*Y); f32 length = (f32)(X*X + Y*Y);
if (core::equals(length, 0.f)) if ( length == 0 )
return *this; return *this;
length = core::reciprocal_squareroot ( length ); length = core::reciprocal_squareroot ( length );
X = (T)(X * length); X = (T)(X * length);
......
...@@ -168,7 +168,7 @@ namespace core ...@@ -168,7 +168,7 @@ namespace core
vector3d<T>& normalize() vector3d<T>& normalize()
{ {
f64 length = X*X + Y*Y + Z*Z; f64 length = X*X + Y*Y + Z*Z;
if (core::equals(length, 0.0)) // this check isn't an optimization but prevents getting NAN in the sqrt. if (length == 0 ) // this check isn't an optimization but prevents getting NAN in the sqrt.
return *this; return *this;
length = core::reciprocal_squareroot(length); length = core::reciprocal_squareroot(length);
......
...@@ -94,9 +94,10 @@ The Irrlicht Engine SDK version 1.8 ...@@ -94,9 +94,10 @@ The Irrlicht Engine SDK version 1.8
* Linux: * Linux:
* Needed: XServer with include files * Needed: XServer with include files
* Optional: OpenGL headers and libraries (libGL.so), for OpenGL support * Optional: OpenGL headers and libraries (libGL.so) for OpenGL support
* GLX + XF86VidMode or XRandr extension (X11 support libraries, GLX +
the latter two for fullscreen mode) XF86VidMode [package x11proto-xf86vidmode-dev] or XRandr
(X11 support libraries, the latter two for fullscreen mode)
* OSX: * OSX:
* Needed: XCode and Cocoa framework * Needed: XCode and Cocoa framework
......
...@@ -155,13 +155,13 @@ void CGUIEditBox::setWordWrap(bool enable) ...@@ -155,13 +155,13 @@ void CGUIEditBox::setWordWrap(bool enable)
void CGUIEditBox::updateAbsolutePosition() void CGUIEditBox::updateAbsolutePosition()
{ {
core::rect<s32> oldAbsoluteRect(AbsoluteRect); core::rect<s32> oldAbsoluteRect(AbsoluteRect);
IGUIElement::updateAbsolutePosition(); IGUIElement::updateAbsolutePosition();
if ( oldAbsoluteRect != AbsoluteRect ) if ( oldAbsoluteRect != AbsoluteRect )
{ {
calculateFrameRect(); calculateFrameRect();
breakText(); breakText();
calculateScrollPos(); calculateScrollPos();
} }
} }
...@@ -466,7 +466,7 @@ bool CGUIEditBox::processKey(const SEvent& event) ...@@ -466,7 +466,7 @@ bool CGUIEditBox::processKey(const SEvent& event)
} }
else else
{ {
sendGuiEvent( EGET_EDITBOX_ENTER ); sendGuiEvent( EGET_EDITBOX_ENTER );
} }
break; break;
case KEY_LEFT: case KEY_LEFT:
...@@ -687,8 +687,8 @@ bool CGUIEditBox::processKey(const SEvent& event) ...@@ -687,8 +687,8 @@ bool CGUIEditBox::processKey(const SEvent& event)
return true; return true;
} }
// Set new text markers // Set new text markers
setTextMarkers( newMarkBegin, newMarkEnd ); setTextMarkers( newMarkBegin, newMarkEnd );
// break the text if it has changed // break the text if it has changed
if (textChanged) if (textChanged)
...@@ -871,25 +871,27 @@ void CGUIEditBox::draw() ...@@ -871,25 +871,27 @@ void CGUIEditBox::draw()
} }
// draw cursor // draw cursor
if ( IsEnabled )
if (WordWrap || MultiLine)
{ {
cursorLine = getLineFromPos(CursorPos); if (WordWrap || MultiLine)
txtLine = &BrokenText[cursorLine]; {
startPos = BrokenTextPositions[cursorLine]; cursorLine = getLineFromPos(CursorPos);
} txtLine = &BrokenText[cursorLine];
s = txtLine->subString(0,CursorPos-startPos); startPos = BrokenTextPositions[cursorLine];
charcursorpos = font->getDimension(s.c_str()).Width + }
font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0); s = txtLine->subString(0,CursorPos-startPos);
charcursorpos = font->getDimension(s.c_str()).Width +
font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0);
if (focus && (os::Timer::getTime() - BlinkStartTime) % 700 < 350) if (focus && (os::Timer::getTime() - BlinkStartTime) % 700 < 350)
{ {
setTextRect(cursorLine); setTextRect(cursorLine);
CurrentTextRect.UpperLeftCorner.X += charcursorpos; CurrentTextRect.UpperLeftCorner.X += charcursorpos;
font->draw(L"_", CurrentTextRect, font->draw(L"_", CurrentTextRect,
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT), OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
false, true, &localClipRect); false, true, &localClipRect);
}
} }
} }
...@@ -975,7 +977,7 @@ bool CGUIEditBox::processMouse(const SEvent& event) ...@@ -975,7 +977,7 @@ bool CGUIEditBox::processMouse(const SEvent& event)
CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
if (MouseMarking) if (MouseMarking)
{ {
setTextMarkers( MarkBegin, CursorPos ); setTextMarkers( MarkBegin, CursorPos );
} }
MouseMarking = false; MouseMarking = false;
calculateScrollPos(); calculateScrollPos();
...@@ -1015,7 +1017,7 @@ bool CGUIEditBox::processMouse(const SEvent& event) ...@@ -1015,7 +1017,7 @@ bool CGUIEditBox::processMouse(const SEvent& event)
// move cursor // move cursor
CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
s32 newMarkBegin = MarkBegin; s32 newMarkBegin = MarkBegin;
if (!MouseMarking) if (!MouseMarking)
newMarkBegin = CursorPos; newMarkBegin = CursorPos;
...@@ -1113,8 +1115,13 @@ void CGUIEditBox::breakText() ...@@ -1113,8 +1115,13 @@ void CGUIEditBox::breakText()
c = 0; c = 0;
if (Text[i+1] == L'\n') // Windows breaks if (Text[i+1] == L'\n') // Windows breaks
{ {
// TODO: I (Michael) think that we shouldn't change the text given by the user for whatever reason.
// Instead rework the cursor positioning to be able to handle this (but not in stable release
// branch as users might already expect this behaviour).
Text.erase(i+1); Text.erase(i+1);
--size; --size;
if ( CursorPos > i )
--CursorPos;
} }
} }
else if (c == L'\n') // Unix breaks else if (c == L'\n') // Unix breaks
...@@ -1186,7 +1193,10 @@ void CGUIEditBox::breakText() ...@@ -1186,7 +1193,10 @@ void CGUIEditBox::breakText()
BrokenTextPositions.push_back(lastLineStart); BrokenTextPositions.push_back(lastLineStart);
} }
// TODO: that function does interpret VAlign according to line-index (indexed line is placed on top-center-bottom)
// but HAlign according to line-width (pixels) and not by row.
// Intuitively I suppose HAlign handling is better as VScrollPos should handle the line-scrolling.
// But please no one change this without also rewriting (and this time fucking testing!!!) autoscrolling (I noticed this when fixing the old autoscrolling).
void CGUIEditBox::setTextRect(s32 line) void CGUIEditBox::setTextRect(s32 line)
{ {
if ( line < 0 ) if ( line < 0 )
...@@ -1317,54 +1327,129 @@ void CGUIEditBox::inputChar(wchar_t c) ...@@ -1317,54 +1327,129 @@ void CGUIEditBox::inputChar(wchar_t c)
calculateScrollPos(); calculateScrollPos();
} }
// calculate autoscroll
void CGUIEditBox::calculateScrollPos() void CGUIEditBox::calculateScrollPos()
{ {
if (!AutoScroll) if (!AutoScroll)
return; return;
// calculate horizontal scroll position IGUISkin* skin = Environment->getSkin();
if (!skin)
return;
IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont();
if (!font)
return;
s32 cursLine = getLineFromPos(CursorPos); s32 cursLine = getLineFromPos(CursorPos);
if ( cursLine < 0 ) if ( cursLine < 0 )
return; return;
setTextRect(cursLine); setTextRect(cursLine);
const bool hasBrokenText = MultiLine || WordWrap;
// don't do horizontal scrolling when wordwrap is enabled. // Check horizonal scrolling
if (!WordWrap) // NOTE: Calculations different to vertical scrolling because setTextRect interprets VAlign relative to line but HAlign not relative to row
{ {
// get cursor position // get cursor position
IGUIFont* font = getActiveFont(); IGUIFont* font = getActiveFont();
if (!font) if (!font)
return; return;
core::stringw *txtLine = MultiLine ? &BrokenText[cursLine] : &Text; // get cursor area
s32 cPos = MultiLine ? CursorPos - BrokenTextPositions[cursLine] : CursorPos; irr::u32 cursorWidth = font->getDimension(L"_").Width;
core::stringw *txtLine = hasBrokenText ? &BrokenText[cursLine] : &Text;
s32 cPos = hasBrokenText ? CursorPos - BrokenTextPositions[cursLine] : CursorPos; // column
s32 cStart = font->getDimension(txtLine->subString(0, cPos).c_str()).Width; // pixels from text-start
s32 cEnd = cStart + cursorWidth;
s32 txtWidth = font->getDimension(txtLine->c_str()).Width;
s32 cStart = CurrentTextRect.UpperLeftCorner.X + HScrollPos + if ( txtWidth < FrameRect.getWidth() )
font->getDimension(txtLine->subString(0, cPos).c_str()).Width; {
// TODO: Needs a clean left and right gap removal depending on HAlign, similar to vertical scrolling tests for top/bottom.
s32 cEnd = cStart + font->getDimension(L"_ ").Width; // This check just fixes the case where it was most noticable (text smaller than clipping area).
if (FrameRect.LowerRightCorner.X < cEnd)
HScrollPos = cEnd - FrameRect.LowerRightCorner.X;
else if (FrameRect.UpperLeftCorner.X > cStart)
HScrollPos = cStart - FrameRect.UpperLeftCorner.X;
else
HScrollPos = 0; HScrollPos = 0;
setTextRect(cursLine);
}
// todo: adjust scrollbar if ( CurrentTextRect.UpperLeftCorner.X+cStart < FrameRect.UpperLeftCorner.X )
} {
// cursor to the left of the clipping area
HScrollPos -= FrameRect.UpperLeftCorner.X-(CurrentTextRect.UpperLeftCorner.X+cStart);
setTextRect(cursLine);
// vertical scroll position // TODO: should show more characters to the left when we're scrolling left
if (FrameRect.LowerRightCorner.Y < CurrentTextRect.LowerRightCorner.Y + VScrollPos) // and the cursor reaches the border.
VScrollPos = CurrentTextRect.LowerRightCorner.Y - FrameRect.LowerRightCorner.Y + VScrollPos; }
else if ( CurrentTextRect.UpperLeftCorner.X+cEnd > FrameRect.LowerRightCorner.X)
{
// cursor to the right of the clipping area
HScrollPos += (CurrentTextRect.UpperLeftCorner.X+cEnd)-FrameRect.LowerRightCorner.X;
setTextRect(cursLine);
}
}
else if (FrameRect.UpperLeftCorner.Y > CurrentTextRect.UpperLeftCorner.Y + VScrollPos) // calculate vertical scrolling
VScrollPos = CurrentTextRect.UpperLeftCorner.Y - FrameRect.UpperLeftCorner.Y + VScrollPos; if (hasBrokenText)
else {
VScrollPos = 0; irr::u32 lineHeight = font->getDimension(L"A").Height + font->getKerningHeight();
// only up to 1 line fits?
if ( lineHeight >= (irr::u32)FrameRect.getHeight() )
{
VScrollPos = 0;
setTextRect(cursLine);
s32 unscrolledPos = CurrentTextRect.UpperLeftCorner.Y;
s32 pivot = FrameRect.UpperLeftCorner.Y;
switch (VAlign)
{
case EGUIA_CENTER:
pivot += FrameRect.getHeight()/2;
unscrolledPos += lineHeight/2;
break;
case EGUIA_LOWERRIGHT:
pivot += FrameRect.getHeight();
unscrolledPos += lineHeight;
break;
default:
break;
}
VScrollPos = unscrolledPos-pivot;
setTextRect(cursLine);
}
else
{
// First 2 checks are necessary when people delete lines
setTextRect(0);
if ( CurrentTextRect.UpperLeftCorner.Y > FrameRect.UpperLeftCorner.Y && VAlign != EGUIA_LOWERRIGHT)
{
// first line is leaving a gap on top
VScrollPos = 0;
}
else if (VAlign != EGUIA_UPPERLEFT)
{
u32 lastLine = BrokenTextPositions.empty() ? 0 : BrokenTextPositions.size()-1;
setTextRect(lastLine);
if ( CurrentTextRect.LowerRightCorner.Y < FrameRect.LowerRightCorner.Y)
{
// last line is leaving a gap on bottom
VScrollPos -= FrameRect.LowerRightCorner.Y-CurrentTextRect.LowerRightCorner.Y;
}
}
// todo: adjust scrollbar setTextRect(cursLine);
if ( CurrentTextRect.UpperLeftCorner.Y < FrameRect.UpperLeftCorner.Y )
{
// text above valid area
VScrollPos -= FrameRect.UpperLeftCorner.Y-CurrentTextRect.UpperLeftCorner.Y;
setTextRect(cursLine);
}
else if ( CurrentTextRect.LowerRightCorner.Y > FrameRect.LowerRightCorner.Y)
{
// text below valid area
VScrollPos += CurrentTextRect.LowerRightCorner.Y-FrameRect.LowerRightCorner.Y;
setTextRect(cursLine);
}
}
}
} }
void CGUIEditBox::calculateFrameRect() void CGUIEditBox::calculateFrameRect()
...@@ -1385,12 +1470,12 @@ void CGUIEditBox::calculateFrameRect() ...@@ -1385,12 +1470,12 @@ void CGUIEditBox::calculateFrameRect()
//! set text markers //! set text markers
void CGUIEditBox::setTextMarkers(s32 begin, s32 end) void CGUIEditBox::setTextMarkers(s32 begin, s32 end)
{ {
if ( begin != MarkBegin || end != MarkEnd ) if ( begin != MarkBegin || end != MarkEnd )
{ {
MarkBegin = begin; MarkBegin = begin;
MarkEnd = end; MarkEnd = end;
sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED); sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED);
} }
} }
//! send some gui event to parent //! send some gui event to parent
...@@ -1398,13 +1483,13 @@ void CGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type) ...@@ -1398,13 +1483,13 @@ void CGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type)
{ {
if ( Parent ) if ( Parent )
{ {
SEvent e; SEvent e;
e.EventType = EET_GUI_EVENT; e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this; e.GUIEvent.Caller = this;
e.GUIEvent.Element = 0; e.GUIEvent.Element = 0;
e.GUIEvent.EventType = type; e.GUIEvent.EventType = type;
Parent->OnEvent(e); Parent->OnEvent(e);
} }
} }
...@@ -1413,21 +1498,21 @@ void CGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWr ...@@ -1413,21 +1498,21 @@ void CGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWr
{ {
// IGUIEditBox::serializeAttributes(out,options); // IGUIEditBox::serializeAttributes(out,options);
out->addBool ("Border", Border); out->addBool ("Border", Border);
out->addBool ("Background", Background); out->addBool ("Background", Background);
out->addBool ("OverrideColorEnabled",OverrideColorEnabled ); out->addBool ("OverrideColorEnabled", OverrideColorEnabled );
out->addColor ("OverrideColor", OverrideColor); out->addColor ("OverrideColor", OverrideColor);
// out->addFont("OverrideFont",OverrideFont); // out->addFont("OverrideFont", OverrideFont);
out->addInt ("MaxChars", Max); out->addInt ("MaxChars", Max);
out->addBool ("WordWrap", WordWrap); out->addBool ("WordWrap", WordWrap);
out->addBool ("MultiLine", MultiLine); out->addBool ("MultiLine", MultiLine);
out->addBool ("AutoScroll", AutoScroll); out->addBool ("AutoScroll", AutoScroll);
out->addBool ("PasswordBox", PasswordBox); out->addBool ("PasswordBox", PasswordBox);
core::stringw ch = L" "; core::stringw ch = L" ";
ch[0] = PasswordChar; ch[0] = PasswordChar;
out->addString("PasswordChar", ch.c_str()); out->addString("PasswordChar", ch.c_str());
out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames); out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames); out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
IGUIEditBox::serializeAttributes(out,options); IGUIEditBox::serializeAttributes(out,options);
} }
......
...@@ -70,7 +70,7 @@ const char* wmDeleteWindow = "WM_DELETE_WINDOW"; ...@@ -70,7 +70,7 @@ const char* wmDeleteWindow = "WM_DELETE_WINDOW";
//! constructor //! constructor
CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param) CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param)
: CIrrDeviceStub(param), : CIrrDeviceStub(param),
#ifdef _IRR_COMPILE_WITH_X11_ #ifdef _IRR_COMPILE_WITH_X11_
display(0), visual(0), screennr(0), window(0), StdHints(0), SoftwareImage(0), display(0), visual(0), screennr(0), window(0), StdHints(0), SoftwareImage(0),
#ifdef _IRR_COMPILE_WITH_OPENGL_ #ifdef _IRR_COMPILE_WITH_OPENGL_
...@@ -179,9 +179,9 @@ CIrrDeviceLinux::~CIrrDeviceLinux() ...@@ -179,9 +179,9 @@ CIrrDeviceLinux::~CIrrDeviceLinux()
#endif // #ifdef _IRR_COMPILE_WITH_X11_ #endif // #ifdef _IRR_COMPILE_WITH_X11_
#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
for(u32 joystick = 0; joystick < ActiveJoysticks.size(); ++joystick) for (u32 joystick = 0; joystick < ActiveJoysticks.size(); ++joystick)
{ {
if(ActiveJoysticks[joystick].fd >= 0) if (ActiveJoysticks[joystick].fd >= 0)
{ {
close(ActiveJoysticks[joystick].fd); close(ActiveJoysticks[joystick].fd);
} }
...@@ -658,7 +658,7 @@ bool CIrrDeviceLinux::createWindow() ...@@ -658,7 +658,7 @@ bool CIrrDeviceLinux::createWindow()
XSetWMProtocols(display, window, &wmDelete, 1); XSetWMProtocols(display, window, &wmDelete, 1);
if (CreationParams.Fullscreen) if (CreationParams.Fullscreen)
{ {
XSetInputFocus(display, window, RevertToParent, CurrentTime); XSetInputFocus(display, window, RevertToParent, CurrentTime);
int grabKb = XGrabKeyboard(display, window, True, GrabModeAsync, int grabKb = XGrabKeyboard(display, window, True, GrabModeAsync,
GrabModeAsync, CurrentTime); GrabModeAsync, CurrentTime);
IrrPrintXGrabError(grabKb, "XGrabKeyboard"); IrrPrintXGrabError(grabKb, "XGrabKeyboard");
...@@ -690,8 +690,8 @@ bool CIrrDeviceLinux::createWindow() ...@@ -690,8 +690,8 @@ bool CIrrDeviceLinux::createWindow()
} }
WindowMinimized=false; WindowMinimized=false;
// Currently broken in X, see Bug ID 2795321 // Currently broken in X, see Bug ID 2795321
// XkbSetDetectableAutoRepeat(display, True, &AutorepeatSupport); // XkbSetDetectableAutoRepeat(display, True, &AutorepeatSupport);
#ifdef _IRR_COMPILE_WITH_OPENGL_ #ifdef _IRR_COMPILE_WITH_OPENGL_
...@@ -1022,22 +1022,42 @@ bool CIrrDeviceLinux::run() ...@@ -1022,22 +1022,42 @@ bool CIrrDeviceLinux::run()
char buf[8]={0}; char buf[8]={0};
XLookupString(&event.xkey, buf, sizeof(buf), &mp.X11Key, NULL); XLookupString(&event.xkey, buf, sizeof(buf), &mp.X11Key, NULL);
const s32 idx = KeyMap.binary_search(mp); irrevent.EventType = irr::EET_KEY_INPUT_EVENT;
irrevent.KeyInput.PressedDown = (event.type == KeyPress);
// mbtowc(&irrevent.KeyInput.Char, buf, sizeof(buf));
irrevent.KeyInput.Char = ((wchar_t*)(buf))[0];
irrevent.KeyInput.Control = (event.xkey.state & ControlMask) != 0;
irrevent.KeyInput.Shift = (event.xkey.state & ShiftMask) != 0;
event.xkey.state = 0; // ignore shift-ctrl states for figuring out the key
XLookupString(&event.xkey, buf, sizeof(buf), &mp.X11Key, NULL);
const s32 idx = KeyMap.binary_search(mp);
if (idx != -1) if (idx != -1)
{
irrevent.KeyInput.Key = (EKEY_CODE)KeyMap[idx].Win32Key; irrevent.KeyInput.Key = (EKEY_CODE)KeyMap[idx].Win32Key;
}
else else
{ {
// Usually you will check keysymdef.h and add the corresponding key to createKeyMap.
irrevent.KeyInput.Key = (EKEY_CODE)0; irrevent.KeyInput.Key = (EKEY_CODE)0;
os::Printer::log("Could not find win32 key for x11 key.", core::stringc((int)mp.X11Key).c_str(), ELL_WARNING);
} }
irrevent.EventType = irr::EET_KEY_INPUT_EVENT; if (irrevent.KeyInput.Key == 0)
irrevent.KeyInput.PressedDown = (event.type == KeyPress); {
// mbtowc(&irrevent.KeyInput.Char, buf, sizeof(buf)); // 1:1 mapping to windows-keys would require testing for keyboard type (us, ger, ...)
irrevent.KeyInput.Char = (reinterpret_cast<wchar_t*>(buf))[0]; // So unless we do that we will have some unknown keys here.
irrevent.KeyInput.Control = (event.xkey.state & ControlMask) != 0; if (idx == -1)
irrevent.KeyInput.Shift = (event.xkey.state & ShiftMask) != 0; {
os::Printer::log("Could not find EKEY_CODE, using orig. X11 keycode instead", core::stringc(event.xkey.keycode).c_str(), ELL_INFORMATION);
}
else
{
os::Printer::log("EKEY_CODE is 0, using orig. X11 keycode instead", core::stringc(event.xkey.keycode).c_str(), ELL_INFORMATION);
}
// Any value is better than none, that allows at least using the keys.
// Worst case is that some keys will be identical, still better than _all_
// unknown keys being identical.
irrevent.KeyInput.Key = (EKEY_CODE)event.xkey.keycode;
}
postEventFromUser(irrevent); postEventFromUser(irrevent);
} }
break; break;
...@@ -1071,7 +1091,7 @@ bool CIrrDeviceLinux::run() ...@@ -1071,7 +1091,7 @@ bool CIrrDeviceLinux::run()
XChangeProperty (display, XChangeProperty (display,
req->requestor, req->requestor,
req->property, req->target, req->property, req->target,
8, // format 8, // format
PropModeReplace, PropModeReplace,
(unsigned char*) Clipboard.c_str(), (unsigned char*) Clipboard.c_str(),
Clipboard.size()); Clipboard.size());
...@@ -1114,7 +1134,7 @@ bool CIrrDeviceLinux::run() ...@@ -1114,7 +1134,7 @@ bool CIrrDeviceLinux::run()
} }
#endif //_IRR_COMPILE_WITH_X11_ #endif //_IRR_COMPILE_WITH_X11_
if(!Close) if (!Close)
pollJoysticks(); pollJoysticks();
return !Close; return !Close;
...@@ -1494,11 +1514,11 @@ void CIrrDeviceLinux::createKeyMap() ...@@ -1494,11 +1514,11 @@ void CIrrDeviceLinux::createKeyMap()
KeyMap.push_back(SKeyMap(XK_exclam, 0)); //? KeyMap.push_back(SKeyMap(XK_exclam, 0)); //?
KeyMap.push_back(SKeyMap(XK_quotedbl, 0)); //? KeyMap.push_back(SKeyMap(XK_quotedbl, 0)); //?
KeyMap.push_back(SKeyMap(XK_section, 0)); //? KeyMap.push_back(SKeyMap(XK_section, 0)); //?
KeyMap.push_back(SKeyMap(XK_numbersign, 0)); //? KeyMap.push_back(SKeyMap(XK_numbersign, KEY_OEM_2));
KeyMap.push_back(SKeyMap(XK_dollar, 0)); //? KeyMap.push_back(SKeyMap(XK_dollar, 0)); //?
KeyMap.push_back(SKeyMap(XK_percent, 0)); //? KeyMap.push_back(SKeyMap(XK_percent, 0)); //?
KeyMap.push_back(SKeyMap(XK_ampersand, 0)); //? KeyMap.push_back(SKeyMap(XK_ampersand, 0)); //?
KeyMap.push_back(SKeyMap(XK_apostrophe, 0)); //? KeyMap.push_back(SKeyMap(XK_apostrophe, KEY_OEM_7));
KeyMap.push_back(SKeyMap(XK_parenleft, 0)); //? KeyMap.push_back(SKeyMap(XK_parenleft, 0)); //?
KeyMap.push_back(SKeyMap(XK_parenright, 0)); //? KeyMap.push_back(SKeyMap(XK_parenright, 0)); //?
KeyMap.push_back(SKeyMap(XK_asterisk, 0)); //? KeyMap.push_back(SKeyMap(XK_asterisk, 0)); //?
...@@ -1506,7 +1526,7 @@ void CIrrDeviceLinux::createKeyMap() ...@@ -1506,7 +1526,7 @@ void CIrrDeviceLinux::createKeyMap()
KeyMap.push_back(SKeyMap(XK_comma, KEY_COMMA)); //? KeyMap.push_back(SKeyMap(XK_comma, KEY_COMMA)); //?
KeyMap.push_back(SKeyMap(XK_minus, KEY_MINUS)); //? KeyMap.push_back(SKeyMap(XK_minus, KEY_MINUS)); //?
KeyMap.push_back(SKeyMap(XK_period, KEY_PERIOD)); //? KeyMap.push_back(SKeyMap(XK_period, KEY_PERIOD)); //?
KeyMap.push_back(SKeyMap(XK_slash, 0)); //? KeyMap.push_back(SKeyMap(XK_slash, KEY_OEM_2)); //?
KeyMap.push_back(SKeyMap(XK_0, KEY_KEY_0)); KeyMap.push_back(SKeyMap(XK_0, KEY_KEY_0));
KeyMap.push_back(SKeyMap(XK_1, KEY_KEY_1)); KeyMap.push_back(SKeyMap(XK_1, KEY_KEY_1));
KeyMap.push_back(SKeyMap(XK_2, KEY_KEY_2)); KeyMap.push_back(SKeyMap(XK_2, KEY_KEY_2));
...@@ -1518,12 +1538,12 @@ void CIrrDeviceLinux::createKeyMap() ...@@ -1518,12 +1538,12 @@ void CIrrDeviceLinux::createKeyMap()
KeyMap.push_back(SKeyMap(XK_8, KEY_KEY_8)); KeyMap.push_back(SKeyMap(XK_8, KEY_KEY_8));
KeyMap.push_back(SKeyMap(XK_9, KEY_KEY_9)); KeyMap.push_back(SKeyMap(XK_9, KEY_KEY_9));
KeyMap.push_back(SKeyMap(XK_colon, 0)); //? KeyMap.push_back(SKeyMap(XK_colon, 0)); //?
KeyMap.push_back(SKeyMap(XK_semicolon, 0)); //? KeyMap.push_back(SKeyMap(XK_semicolon, KEY_OEM_1));
KeyMap.push_back(SKeyMap(XK_less, 0)); //? KeyMap.push_back(SKeyMap(XK_less, KEY_OEM_102));
KeyMap.push_back(SKeyMap(XK_equal, 0)); //? KeyMap.push_back(SKeyMap(XK_equal, KEY_PLUS));
KeyMap.push_back(SKeyMap(XK_greater, 0)); //? KeyMap.push_back(SKeyMap(XK_greater, 0)); //?
KeyMap.push_back(SKeyMap(XK_question, 0)); //? KeyMap.push_back(SKeyMap(XK_question, 0)); //?
KeyMap.push_back(SKeyMap(XK_at, 0)); //? KeyMap.push_back(SKeyMap(XK_at, KEY_KEY_2)); //?
KeyMap.push_back(SKeyMap(XK_mu, 0)); //? KeyMap.push_back(SKeyMap(XK_mu, 0)); //?
KeyMap.push_back(SKeyMap(XK_EuroSign, 0)); //? KeyMap.push_back(SKeyMap(XK_EuroSign, 0)); //?
KeyMap.push_back(SKeyMap(XK_A, KEY_KEY_A)); KeyMap.push_back(SKeyMap(XK_A, KEY_KEY_A));
...@@ -1552,18 +1572,14 @@ void CIrrDeviceLinux::createKeyMap() ...@@ -1552,18 +1572,14 @@ void CIrrDeviceLinux::createKeyMap()
KeyMap.push_back(SKeyMap(XK_X, KEY_KEY_X)); KeyMap.push_back(SKeyMap(XK_X, KEY_KEY_X));
KeyMap.push_back(SKeyMap(XK_Y, KEY_KEY_Y)); KeyMap.push_back(SKeyMap(XK_Y, KEY_KEY_Y));
KeyMap.push_back(SKeyMap(XK_Z, KEY_KEY_Z)); KeyMap.push_back(SKeyMap(XK_Z, KEY_KEY_Z));
KeyMap.push_back(SKeyMap(XK_Adiaeresis, 0)); //? KeyMap.push_back(SKeyMap(XK_bracketleft, KEY_OEM_4));
KeyMap.push_back(SKeyMap(XK_Odiaeresis, 0)); //? KeyMap.push_back(SKeyMap(XK_backslash, KEY_OEM_5));
KeyMap.push_back(SKeyMap(XK_Udiaeresis, 0)); //? KeyMap.push_back(SKeyMap(XK_bracketright, KEY_OEM_6));
KeyMap.push_back(SKeyMap(XK_bracketleft, 0)); //? KeyMap.push_back(SKeyMap(XK_asciicircum, KEY_OEM_5));
KeyMap.push_back(SKeyMap(XK_backslash, 0)); //?
KeyMap.push_back(SKeyMap(XK_bracketright, 0)); //?
KeyMap.push_back(SKeyMap(XK_asciicircum, 0)); //?
KeyMap.push_back(SKeyMap(XK_degree, 0)); //? KeyMap.push_back(SKeyMap(XK_degree, 0)); //?
KeyMap.push_back(SKeyMap(XK_underscore, 0)); //? KeyMap.push_back(SKeyMap(XK_underscore, KEY_MINUS)); //?
KeyMap.push_back(SKeyMap(XK_grave, 0)); //? KeyMap.push_back(SKeyMap(XK_grave, KEY_OEM_3));
KeyMap.push_back(SKeyMap(XK_acute, 0)); //? KeyMap.push_back(SKeyMap(XK_acute, KEY_OEM_6));
KeyMap.push_back(SKeyMap(XK_quoteleft, 0)); //?
KeyMap.push_back(SKeyMap(XK_a, KEY_KEY_A)); KeyMap.push_back(SKeyMap(XK_a, KEY_KEY_A));
KeyMap.push_back(SKeyMap(XK_b, KEY_KEY_B)); KeyMap.push_back(SKeyMap(XK_b, KEY_KEY_B));
KeyMap.push_back(SKeyMap(XK_c, KEY_KEY_C)); KeyMap.push_back(SKeyMap(XK_c, KEY_KEY_C));
...@@ -1590,10 +1606,12 @@ void CIrrDeviceLinux::createKeyMap() ...@@ -1590,10 +1606,12 @@ void CIrrDeviceLinux::createKeyMap()
KeyMap.push_back(SKeyMap(XK_x, KEY_KEY_X)); KeyMap.push_back(SKeyMap(XK_x, KEY_KEY_X));
KeyMap.push_back(SKeyMap(XK_y, KEY_KEY_Y)); KeyMap.push_back(SKeyMap(XK_y, KEY_KEY_Y));
KeyMap.push_back(SKeyMap(XK_z, KEY_KEY_Z)); KeyMap.push_back(SKeyMap(XK_z, KEY_KEY_Z));
KeyMap.push_back(SKeyMap(XK_ssharp, 0)); //? KeyMap.push_back(SKeyMap(XK_ssharp, KEY_OEM_4));
KeyMap.push_back(SKeyMap(XK_adiaeresis, 0)); //? KeyMap.push_back(SKeyMap(XK_adiaeresis, KEY_OEM_7));
KeyMap.push_back(SKeyMap(XK_odiaeresis, 0)); //? KeyMap.push_back(SKeyMap(XK_odiaeresis, KEY_OEM_3));
KeyMap.push_back(SKeyMap(XK_udiaeresis, 0)); //? KeyMap.push_back(SKeyMap(XK_udiaeresis, KEY_OEM_1));
KeyMap.push_back(SKeyMap(XK_Super_L, KEY_LWIN));
KeyMap.push_back(SKeyMap(XK_Super_R, KEY_RWIN));
KeyMap.sort(); KeyMap.sort();
#endif #endif
...@@ -1606,7 +1624,7 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf ...@@ -1606,7 +1624,7 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf
joystickInfo.clear(); joystickInfo.clear();
u32 joystick; u32 joystick;
for(joystick = 0; joystick < 32; ++joystick) for (joystick = 0; joystick < 32; ++joystick)
{ {
// The joystick device could be here... // The joystick device could be here...
core::stringc devName = "/dev/js"; core::stringc devName = "/dev/js";
...@@ -1616,14 +1634,14 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf ...@@ -1616,14 +1634,14 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf
JoystickInfo info; JoystickInfo info;
info.fd = open(devName.c_str(), O_RDONLY); info.fd = open(devName.c_str(), O_RDONLY);
if(-1 == info.fd) if (-1 == info.fd)
{ {
// ...but Ubuntu and possibly other distros // ...but Ubuntu and possibly other distros
// create the devices in /dev/input // create the devices in /dev/input
devName = "/dev/input/js"; devName = "/dev/input/js";
devName += joystick; devName += joystick;
info.fd = open(devName.c_str(), O_RDONLY); info.fd = open(devName.c_str(), O_RDONLY);
if(-1 == info.fd) if (-1 == info.fd)
{ {
// and BSD here // and BSD here
devName = "/dev/joy"; devName = "/dev/joy";
...@@ -1632,7 +1650,7 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf ...@@ -1632,7 +1650,7 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf
} }
} }
if(-1 == info.fd) if (-1 == info.fd)
continue; continue;
#ifdef __FREE_BSD_ #ifdef __FREE_BSD_
...@@ -1668,7 +1686,7 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf ...@@ -1668,7 +1686,7 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf
joystickInfo.push_back(returnInfo); joystickInfo.push_back(returnInfo);
} }
for(joystick = 0; joystick < joystickInfo.size(); ++joystick) for (joystick = 0; joystick < joystickInfo.size(); ++joystick)
{ {
char logString[256]; char logString[256];
(void)sprintf(logString, "Found joystick %u, %u axes, %u buttons '%s'", (void)sprintf(logString, "Found joystick %u, %u axes, %u buttons '%s'",
...@@ -1687,36 +1705,36 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf ...@@ -1687,36 +1705,36 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf
void CIrrDeviceLinux::pollJoysticks() void CIrrDeviceLinux::pollJoysticks()
{ {
#if defined (_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) #if defined (_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
if(0 == ActiveJoysticks.size()) if (0 == ActiveJoysticks.size())
return; return;
u32 j; for (u32 j= 0; j< ActiveJoysticks.size(); ++j)
for(j= 0; j< ActiveJoysticks.size(); ++j)
{ {
JoystickInfo & info = ActiveJoysticks[j]; JoystickInfo & info = ActiveJoysticks[j];
#ifdef __FREE_BSD_ #ifdef __FREE_BSD_
struct joystick js; struct joystick js;
if( read( info.fd, &js, JS_RETURN ) == JS_RETURN ) if (read(info.fd, &js, JS_RETURN) == JS_RETURN)
{ {
info.persistentData.JoystickEvent.ButtonStates = js.buttons; /* should be a two-bit field */ info.persistentData.JoystickEvent.ButtonStates = js.buttons; /* should be a two-bit field */
info.persistentData.JoystickEvent.Axis[0] = js.x; /* X axis */ info.persistentData.JoystickEvent.Axis[0] = js.x; /* X axis */
info.persistentData.JoystickEvent.Axis[1] = js.y; /* Y axis */ info.persistentData.JoystickEvent.Axis[1] = js.y; /* Y axis */
#else #else
struct js_event event; struct js_event event;
while(sizeof(event) == read(info.fd, &event, sizeof(event))) while (sizeof(event) == read(info.fd, &event, sizeof(event)))
{ {
switch(event.type & ~JS_EVENT_INIT) switch(event.type & ~JS_EVENT_INIT)
{ {
case JS_EVENT_BUTTON: case JS_EVENT_BUTTON:
if (event.value) if (event.value)
info.persistentData.JoystickEvent.ButtonStates |= (1 << event.number); info.persistentData.JoystickEvent.ButtonStates |= (1 << event.number);
else else
info.persistentData.JoystickEvent.ButtonStates &= ~(1 << event.number); info.persistentData.JoystickEvent.ButtonStates &= ~(1 << event.number);
break; break;
case JS_EVENT_AXIS: case JS_EVENT_AXIS:
info.persistentData.JoystickEvent.Axis[event.number] = event.value; if (event.number < SEvent::SJoystickEvent::NUMBER_OF_AXES)
info.persistentData.JoystickEvent.Axis[event.number] = event.value;
break; break;
default: default:
...@@ -1845,16 +1863,16 @@ const c8* CIrrDeviceLinux::getTextFromClipboard() const ...@@ -1845,16 +1863,16 @@ const c8* CIrrDeviceLinux::getTextFromClipboard() const
unsigned long numItems, bytesLeft, dummy; unsigned long numItems, bytesLeft, dummy;
unsigned char *data; unsigned char *data;
XGetWindowProperty (display, ownerWindow, XGetWindowProperty (display, ownerWindow,
XA_STRING, // property name XA_STRING, // property name
0, // offset 0, // offset
0, // length (we only check for data, so 0) 0, // length (we only check for data, so 0)
0, // Delete 0==false 0, // Delete 0==false
AnyPropertyType, // AnyPropertyType or property identifier AnyPropertyType, // AnyPropertyType or property identifier
&type, // return type &type, // return type
&format, // return format &format, // return format
&numItems, // number items &numItems, // number items
&bytesLeft, // remaining bytes for partial reads &bytesLeft, // remaining bytes for partial reads
&data); // data &data); // data
if ( bytesLeft > 0 ) if ( bytesLeft > 0 )
{ {
// there is some data to get // there is some data to get
...@@ -1907,15 +1925,15 @@ void CIrrDeviceLinux::clearSystemMessages() ...@@ -1907,15 +1925,15 @@ void CIrrDeviceLinux::clearSystemMessages()
{ {
XEvent event; XEvent event;
int usrArg = ButtonPress; int usrArg = ButtonPress;
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
usrArg = ButtonRelease; usrArg = ButtonRelease;
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
usrArg = MotionNotify; usrArg = MotionNotify;
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
usrArg = KeyRelease; usrArg = KeyRelease;
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
usrArg = KeyPress; usrArg = KeyPress;
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
} }
#endif //_IRR_COMPILE_WITH_X11_ #endif //_IRR_COMPILE_WITH_X11_
} }
...@@ -1940,7 +1958,7 @@ Cursor CIrrDeviceLinux::TextureToMonochromeCursor(irr::video::ITexture * tex, co ...@@ -1940,7 +1958,7 @@ Cursor CIrrDeviceLinux::TextureToMonochromeCursor(irr::video::ITexture * tex, co
ZPixmap, // XYBitmap (depth=1), ZPixmap(depth=x) ZPixmap, // XYBitmap (depth=1), ZPixmap(depth=x)
0, 0, sourceRect.getWidth(), sourceRect.getHeight(), 0, 0, sourceRect.getWidth(), sourceRect.getHeight(),
32, // bitmap_pad, 32, // bitmap_pad,
0// bytes_per_line (0 means continuos in memory) 0// bytes_per_line (0 means continuos in memory)
); );
sourceImage->data = new char[sourceImage->height * sourceImage->bytes_per_line]; sourceImage->data = new char[sourceImage->height * sourceImage->bytes_per_line];
XImage * maskImage = XCreateImage(display, visual->visual, XImage * maskImage = XCreateImage(display, visual->visual,
...@@ -1948,7 +1966,7 @@ Cursor CIrrDeviceLinux::TextureToMonochromeCursor(irr::video::ITexture * tex, co ...@@ -1948,7 +1966,7 @@ Cursor CIrrDeviceLinux::TextureToMonochromeCursor(irr::video::ITexture * tex, co
ZPixmap, ZPixmap,
0, 0, sourceRect.getWidth(), sourceRect.getHeight(), 0, 0, sourceRect.getWidth(), sourceRect.getHeight(),
32, // bitmap_pad, 32, // bitmap_pad,
0 // bytes_per_line 0 // bytes_per_line
); );
maskImage->data = new char[maskImage->height * maskImage->bytes_per_line]; maskImage->data = new char[maskImage->height * maskImage->bytes_per_line];
......
...@@ -458,7 +458,7 @@ bool CIrrDeviceSDL::run() ...@@ -458,7 +458,7 @@ bool CIrrDeviceSDL::run()
#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
// TODO: Check if the multiple open/close calls are too expensive, then // TODO: Check if the multiple open/close calls are too expensive, then
// open/close in the constructor/destructor instead // open/close in the constructor/destructor instead
// update joystick states manually // update joystick states manually
SDL_JoystickUpdate(); SDL_JoystickUpdate();
...@@ -478,7 +478,7 @@ bool CIrrDeviceSDL::run() ...@@ -478,7 +478,7 @@ bool CIrrDeviceSDL::run()
joyevent.JoystickEvent.ButtonStates |= (SDL_JoystickGetButton(joystick, j)<<j); joyevent.JoystickEvent.ButtonStates |= (SDL_JoystickGetButton(joystick, j)<<j);
// query all axes, already in correct range // query all axes, already in correct range
const int numAxes = core::min_(SDL_JoystickNumAxes(joystick), 6); const int numAxes = core::min_(SDL_JoystickNumAxes(joystick), SEvent::SJoystickEvent::NUMBER_OF_AXES);
joyevent.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_X]=0; joyevent.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_X]=0;
joyevent.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_Y]=0; joyevent.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_Y]=0;
joyevent.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_Z]=0; joyevent.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_Z]=0;
...@@ -570,8 +570,8 @@ bool CIrrDeviceSDL::activateJoysticks(core::array<SJoystickInfo> & joystickInfo) ...@@ -570,8 +570,8 @@ bool CIrrDeviceSDL::activateJoysticks(core::array<SJoystickInfo> & joystickInfo)
{ {
char logString[256]; char logString[256];
(void)sprintf(logString, "Found joystick %d, %d axes, %d buttons '%s'", (void)sprintf(logString, "Found joystick %d, %d axes, %d buttons '%s'",
joystick, joystickInfo[joystick].Axes, joystick, joystickInfo[joystick].Axes,
joystickInfo[joystick].Buttons, joystickInfo[joystick].Name.c_str()); joystickInfo[joystick].Buttons, joystickInfo[joystick].Name.c_str());
os::Printer::log(logString, ELL_INFORMATION); os::Printer::log(logString, ELL_INFORMATION);
} }
......
...@@ -138,13 +138,13 @@ struct SJoystickWin32Control ...@@ -138,13 +138,13 @@ struct SJoystickWin32Control
} }
if (FAILED(activeJoystick.lpdijoy->SetCooperativeLevel(Device->HWnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE))) if (FAILED(activeJoystick.lpdijoy->SetCooperativeLevel(Device->HWnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE)))
{ {
os::Printer::log("Could not set DirectInput device cooperative level", ELL_WARNING); os::Printer::log("Could not set DirectInput device cooperative level", ELL_WARNING);
return; return;
} }
if (FAILED(activeJoystick.lpdijoy->SetDataFormat(&c_dfDIJoystick2))) if (FAILED(activeJoystick.lpdijoy->SetDataFormat(&c_dfDIJoystick2)))
{ {
os::Printer::log("Could not set DirectInput device data format", ELL_WARNING); os::Printer::log("Could not set DirectInput device data format", ELL_WARNING);
return; return;
} }
...@@ -191,41 +191,41 @@ void pollJoysticks() ...@@ -191,41 +191,41 @@ void pollJoysticks()
{ {
#if defined _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ #if defined _IRR_COMPILE_WITH_JOYSTICK_EVENTS_
#ifdef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ #ifdef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_
if(0 == ActiveJoysticks.size()) if(0 == ActiveJoysticks.size())
return; return;
u32 joystick; u32 joystick;
DIJOYSTATE2 info; DIJOYSTATE2 info;
for(joystick = 0; joystick < ActiveJoysticks.size(); ++joystick) for(joystick = 0; joystick < ActiveJoysticks.size(); ++joystick)
{ {
// needs to be reset for each joystick // needs to be reset for each joystick
// request ALL values and POV as continuous if possible // request ALL values and POV as continuous if possible
const DIDEVCAPS & caps = ActiveJoysticks[joystick].devcaps; const DIDEVCAPS & caps = ActiveJoysticks[joystick].devcaps;
// if no POV is available don't ask for POV values // if no POV is available don't ask for POV values
if (!FAILED(ActiveJoysticks[joystick].lpdijoy->GetDeviceState(sizeof(info),&info))) if (!FAILED(ActiveJoysticks[joystick].lpdijoy->GetDeviceState(sizeof(info),&info)))
{ {
SEvent event; SEvent event;
event.EventType = irr::EET_JOYSTICK_INPUT_EVENT; event.EventType = irr::EET_JOYSTICK_INPUT_EVENT;
event.JoystickEvent.Joystick = (u8)joystick; event.JoystickEvent.Joystick = (u8)joystick;
event.JoystickEvent.POV = (u16)info.rgdwPOV[0]; event.JoystickEvent.POV = (u16)info.rgdwPOV[0];
// set to undefined if no POV value was returned or the value // set to undefined if no POV value was returned or the value
// is out of range // is out of range
if ((caps.dwPOVs==0) || (event.JoystickEvent.POV > 35900)) if ((caps.dwPOVs==0) || (event.JoystickEvent.POV > 35900))
event.JoystickEvent.POV = 65535; event.JoystickEvent.POV = 65535;
for(int axis = 0; axis < SEvent::SJoystickEvent::NUMBER_OF_AXES; ++axis) for(int axis = 0; axis < SEvent::SJoystickEvent::NUMBER_OF_AXES; ++axis)
event.JoystickEvent.Axis[axis] = 0; event.JoystickEvent.Axis[axis] = 0;
u16 dxAxis=0; u16 dxAxis=0;
u16 irrAxis=0; u16 irrAxis=0;
while (dxAxis < 6 && irrAxis <caps.dwAxes) while (dxAxis < 6 && irrAxis <caps.dwAxes)
{ {
bool axisFound=0; bool axisFound=0;
s32 axisValue=0; s32 axisValue=0;
...@@ -286,9 +286,9 @@ void pollJoysticks() ...@@ -286,9 +286,9 @@ void pollJoysticks()
} }
event.JoystickEvent.ButtonStates = buttons; event.JoystickEvent.ButtonStates = buttons;
(void)Device->postEventFromUser(event); (void)Device->postEventFromUser(event);
} }
} }
#else #else
if (0 == ActiveJoysticks.size()) if (0 == ActiveJoysticks.size())
return; return;
...@@ -441,160 +441,160 @@ bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) ...@@ -441,160 +441,160 @@ bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo)
// Based on the table from http://www.science.co.il/Language/Locale-Codes.asp?s=decimal // Based on the table from http://www.science.co.il/Language/Locale-Codes.asp?s=decimal
static unsigned int LocaleIdToCodepage(unsigned int lcid) static unsigned int LocaleIdToCodepage(unsigned int lcid)
{ {
switch ( lcid ) switch ( lcid )
{ {
case 1098: // Telugu case 1098: // Telugu
case 1095: // Gujarati case 1095: // Gujarati
case 1094: // Punjabi case 1094: // Punjabi
case 1103: // Sanskrit case 1103: // Sanskrit
case 1111: // Konkani case 1111: // Konkani
case 1114: // Syriac case 1114: // Syriac
case 1099: // Kannada case 1099: // Kannada
case 1102: // Marathi case 1102: // Marathi
case 1125: // Divehi case 1125: // Divehi
case 1067: // Armenian case 1067: // Armenian
case 1081: // Hindi case 1081: // Hindi
case 1079: // Georgian case 1079: // Georgian
case 1097: // Tamil case 1097: // Tamil
return 0; return 0;
case 1054: // Thai case 1054: // Thai
return 874; return 874;
case 1041: // Japanese case 1041: // Japanese
return 932; return 932;
case 2052: // Chinese (PRC) case 2052: // Chinese (PRC)
case 4100: // Chinese (Singapore) case 4100: // Chinese (Singapore)
return 936; return 936;
case 1042: // Korean case 1042: // Korean
return 949; return 949;
case 5124: // Chinese (Macau S.A.R.) case 5124: // Chinese (Macau S.A.R.)
case 3076: // Chinese (Hong Kong S.A.R.) case 3076: // Chinese (Hong Kong S.A.R.)
case 1028: // Chinese (Taiwan) case 1028: // Chinese (Taiwan)
return 950; return 950;
case 1048: // Romanian case 1048: // Romanian
case 1060: // Slovenian case 1060: // Slovenian
case 1038: // Hungarian case 1038: // Hungarian
case 1051: // Slovak case 1051: // Slovak
case 1045: // Polish case 1045: // Polish
case 1052: // Albanian case 1052: // Albanian
case 2074: // Serbian (Latin) case 2074: // Serbian (Latin)
case 1050: // Croatian case 1050: // Croatian
case 1029: // Czech case 1029: // Czech
return 1250; return 1250;
case 1104: // Mongolian (Cyrillic) case 1104: // Mongolian (Cyrillic)
case 1071: // FYRO Macedonian case 1071: // FYRO Macedonian
case 2115: // Uzbek (Cyrillic) case 2115: // Uzbek (Cyrillic)
case 1058: // Ukrainian case 1058: // Ukrainian
case 2092: // Azeri (Cyrillic) case 2092: // Azeri (Cyrillic)
case 1092: // Tatar case 1092: // Tatar
case 1087: // Kazakh case 1087: // Kazakh
case 1059: // Belarusian case 1059: // Belarusian
case 1088: // Kyrgyz (Cyrillic) case 1088: // Kyrgyz (Cyrillic)
case 1026: // Bulgarian case 1026: // Bulgarian
case 3098: // Serbian (Cyrillic) case 3098: // Serbian (Cyrillic)
case 1049: // Russian case 1049: // Russian
return 1251; return 1251;
case 8201: // English (Jamaica) case 8201: // English (Jamaica)
case 3084: // French (Canada) case 3084: // French (Canada)
case 1036: // French (France) case 1036: // French (France)
case 5132: // French (Luxembourg) case 5132: // French (Luxembourg)
case 5129: // English (New Zealand) case 5129: // English (New Zealand)
case 6153: // English (Ireland) case 6153: // English (Ireland)
case 1043: // Dutch (Netherlands) case 1043: // Dutch (Netherlands)
case 9225: // English (Caribbean) case 9225: // English (Caribbean)
case 4108: // French (Switzerland) case 4108: // French (Switzerland)
case 4105: // English (Canada) case 4105: // English (Canada)
case 1110: // Galician case 1110: // Galician
case 10249: // English (Belize) case 10249: // English (Belize)
case 3079: // German (Austria) case 3079: // German (Austria)
case 6156: // French (Monaco) case 6156: // French (Monaco)
case 12297: // English (Zimbabwe) case 12297: // English (Zimbabwe)
case 1069: // Basque case 1069: // Basque
case 2067: // Dutch (Belgium) case 2067: // Dutch (Belgium)
case 2060: // French (Belgium) case 2060: // French (Belgium)
case 1035: // Finnish case 1035: // Finnish
case 1080: // Faroese case 1080: // Faroese
case 1031: // German (Germany) case 1031: // German (Germany)
case 3081: // English (Australia) case 3081: // English (Australia)
case 1033: // English (United States) case 1033: // English (United States)
case 2057: // English (United Kingdom) case 2057: // English (United Kingdom)
case 1027: // Catalan case 1027: // Catalan
case 11273: // English (Trinidad) case 11273: // English (Trinidad)
case 7177: // English (South Africa) case 7177: // English (South Africa)
case 1030: // Danish case 1030: // Danish
case 13321: // English (Philippines) case 13321: // English (Philippines)
case 15370: // Spanish (Paraguay) case 15370: // Spanish (Paraguay)
case 9226: // Spanish (Colombia) case 9226: // Spanish (Colombia)
case 5130: // Spanish (Costa Rica) case 5130: // Spanish (Costa Rica)
case 7178: // Spanish (Dominican Republic) case 7178: // Spanish (Dominican Republic)
case 12298: // Spanish (Ecuador) case 12298: // Spanish (Ecuador)
case 17418: // Spanish (El Salvador) case 17418: // Spanish (El Salvador)
case 4106: // Spanish (Guatemala) case 4106: // Spanish (Guatemala)
case 18442: // Spanish (Honduras) case 18442: // Spanish (Honduras)
case 3082: // Spanish (International Sort) case 3082: // Spanish (International Sort)
case 13322: // Spanish (Chile) case 13322: // Spanish (Chile)
case 19466: // Spanish (Nicaragua) case 19466: // Spanish (Nicaragua)
case 2058: // Spanish (Mexico) case 2058: // Spanish (Mexico)
case 10250: // Spanish (Peru) case 10250: // Spanish (Peru)
case 20490: // Spanish (Puerto Rico) case 20490: // Spanish (Puerto Rico)
case 1034: // Spanish (Traditional Sort) case 1034: // Spanish (Traditional Sort)
case 14346: // Spanish (Uruguay) case 14346: // Spanish (Uruguay)
case 8202: // Spanish (Venezuela) case 8202: // Spanish (Venezuela)
case 1089: // Swahili case 1089: // Swahili
case 1053: // Swedish case 1053: // Swedish
case 2077: // Swedish (Finland) case 2077: // Swedish (Finland)
case 5127: // German (Liechtenstein) case 5127: // German (Liechtenstein)
case 1078: // Afrikaans case 1078: // Afrikaans
case 6154: // Spanish (Panama) case 6154: // Spanish (Panama)
case 4103: // German (Luxembourg) case 4103: // German (Luxembourg)
case 16394: // Spanish (Bolivia) case 16394: // Spanish (Bolivia)
case 2055: // German (Switzerland) case 2055: // German (Switzerland)
case 1039: // Icelandic case 1039: // Icelandic
case 1057: // Indonesian case 1057: // Indonesian
case 1040: // Italian (Italy) case 1040: // Italian (Italy)
case 2064: // Italian (Switzerland) case 2064: // Italian (Switzerland)
case 2068: // Norwegian (Nynorsk) case 2068: // Norwegian (Nynorsk)
case 11274: // Spanish (Argentina) case 11274: // Spanish (Argentina)
case 1046: // Portuguese (Brazil) case 1046: // Portuguese (Brazil)
case 1044: // Norwegian (Bokmal) case 1044: // Norwegian (Bokmal)
case 1086: // Malay (Malaysia) case 1086: // Malay (Malaysia)
case 2110: // Malay (Brunei Darussalam) case 2110: // Malay (Brunei Darussalam)
case 2070: // Portuguese (Portugal) case 2070: // Portuguese (Portugal)
return 1252; return 1252;
case 1032: // Greek case 1032: // Greek
return 1253; return 1253;
case 1091: // Uzbek (Latin) case 1091: // Uzbek (Latin)
case 1068: // Azeri (Latin) case 1068: // Azeri (Latin)
case 1055: // Turkish case 1055: // Turkish
return 1254; return 1254;
case 1037: // Hebrew case 1037: // Hebrew
return 1255; return 1255;
case 5121: // Arabic (Algeria) case 5121: // Arabic (Algeria)
case 15361: // Arabic (Bahrain) case 15361: // Arabic (Bahrain)
case 9217: // Arabic (Yemen) case 9217: // Arabic (Yemen)
case 3073: // Arabic (Egypt) case 3073: // Arabic (Egypt)
case 2049: // Arabic (Iraq) case 2049: // Arabic (Iraq)
case 11265: // Arabic (Jordan) case 11265: // Arabic (Jordan)
case 13313: // Arabic (Kuwait) case 13313: // Arabic (Kuwait)
case 12289: // Arabic (Lebanon) case 12289: // Arabic (Lebanon)
case 4097: // Arabic (Libya) case 4097: // Arabic (Libya)
case 6145: // Arabic (Morocco) case 6145: // Arabic (Morocco)
case 8193: // Arabic (Oman) case 8193: // Arabic (Oman)
case 16385: // Arabic (Qatar) case 16385: // Arabic (Qatar)
case 1025: // Arabic (Saudi Arabia) case 1025: // Arabic (Saudi Arabia)
case 10241: // Arabic (Syria) case 10241: // Arabic (Syria)
case 14337: // Arabic (U.A.E.) case 14337: // Arabic (U.A.E.)
case 1065: // Farsi case 1065: // Farsi
case 1056: // Urdu case 1056: // Urdu
case 7169: // Arabic (Tunisia) case 7169: // Arabic (Tunisia)
return 1256; return 1256;
case 1061: // Estonian case 1061: // Estonian
case 1062: // Latvian case 1062: // Latvian
case 1063: // Lithuanian case 1063: // Lithuanian
return 1257; return 1257;
case 1066: // Vietnamese case 1066: // Vietnamese
return 1258; return 1258;
} }
return 65001; // utf-8 return 65001; // utf-8
} }
namespace namespace
...@@ -885,10 +885,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) ...@@ -885,10 +885,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
break; break;
case WM_INPUTLANGCHANGE: case WM_INPUTLANGCHANGE:
// get the new codepage used for keyboard input // get the new codepage used for keyboard input
KEYBOARD_INPUT_HKL = GetKeyboardLayout(0); KEYBOARD_INPUT_HKL = GetKeyboardLayout(0);
KEYBOARD_INPUT_CODEPAGE = LocaleIdToCodepage( LOWORD(KEYBOARD_INPUT_HKL) ); KEYBOARD_INPUT_CODEPAGE = LocaleIdToCodepage( LOWORD(KEYBOARD_INPUT_HKL) );
return 0; return 0;
} }
return DefWindowProc(hWnd, message, wParam, lParam); return DefWindowProc(hWnd, message, wParam, lParam);
} }
...@@ -1148,7 +1148,7 @@ bool CIrrDeviceWin32::run() ...@@ -1148,7 +1148,7 @@ bool CIrrDeviceWin32::run()
{ {
os::Timer::tick(); os::Timer::tick();
static_cast<CCursorControl*>(CursorControl)->update(); static_cast<CCursorControl*>(CursorControl)->update();
MSG msg; MSG msg;
...@@ -1270,16 +1270,16 @@ bool CIrrDeviceWin32::present(video::IImage* image, void* windowId, core::rect<s ...@@ -1270,16 +1270,16 @@ bool CIrrDeviceWin32::present(video::IImage* image, void* windowId, core::rect<s
BITMAPV4HEADER bi; BITMAPV4HEADER bi;
ZeroMemory (&bi, sizeof(bi)); ZeroMemory (&bi, sizeof(bi));
bi.bV4Size = sizeof(BITMAPINFOHEADER); bi.bV4Size = sizeof(BITMAPINFOHEADER);
bi.bV4BitCount = (WORD)image->getBitsPerPixel(); bi.bV4BitCount = (WORD)image->getBitsPerPixel();
bi.bV4Planes = 1; bi.bV4Planes = 1;
bi.bV4Width = image->getDimension().Width; bi.bV4Width = image->getDimension().Width;
bi.bV4Height = -((s32)image->getDimension().Height); bi.bV4Height = -((s32)image->getDimension().Height);
bi.bV4V4Compression = BI_BITFIELDS; bi.bV4V4Compression = BI_BITFIELDS;
bi.bV4AlphaMask = image->getAlphaMask(); bi.bV4AlphaMask = image->getAlphaMask();
bi.bV4RedMask = image->getRedMask(); bi.bV4RedMask = image->getRedMask();
bi.bV4GreenMask = image->getGreenMask(); bi.bV4GreenMask = image->getGreenMask();
bi.bV4BlueMask = image->getBlueMask(); bi.bV4BlueMask = image->getBlueMask();
if ( src ) if ( src )
{ {
...@@ -1451,220 +1451,222 @@ typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD); ...@@ -1451,220 +1451,222 @@ typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
// depending on the SDK version and compilers some defines might be available // depending on the SDK version and compilers some defines might be available
// or not // or not
#ifndef PRODUCT_ULTIMATE #ifndef PRODUCT_ULTIMATE
#define PRODUCT_ULTIMATE 0x00000001 #define PRODUCT_ULTIMATE 0x00000001
#define PRODUCT_HOME_BASIC 0x00000002 #define PRODUCT_HOME_BASIC 0x00000002
#define PRODUCT_HOME_PREMIUM 0x00000003 #define PRODUCT_HOME_PREMIUM 0x00000003
#define PRODUCT_ENTERPRISE 0x00000004 #define PRODUCT_ENTERPRISE 0x00000004
#define PRODUCT_HOME_BASIC_N 0x00000005 #define PRODUCT_HOME_BASIC_N 0x00000005
#define PRODUCT_BUSINESS 0x00000006 #define PRODUCT_BUSINESS 0x00000006
#define PRODUCT_STARTER 0x0000000B #define PRODUCT_STARTER 0x0000000B
#endif #endif
#ifndef PRODUCT_ULTIMATE_N #ifndef PRODUCT_ULTIMATE_N
#define PRODUCT_BUSINESS_N 0x00000010 #define PRODUCT_BUSINESS_N 0x00000010
#define PRODUCT_HOME_PREMIUM_N 0x0000001A #define PRODUCT_HOME_PREMIUM_N 0x0000001A
#define PRODUCT_ENTERPRISE_N 0x0000001B #define PRODUCT_ENTERPRISE_N 0x0000001B
#define PRODUCT_ULTIMATE_N 0x0000001C #define PRODUCT_ULTIMATE_N 0x0000001C
#define PRODUCT_STARTER_N 0x0000002F #endif
#ifndef PRODUCT_STARTER_N
#define PRODUCT_STARTER_N 0x0000002F
#endif #endif
#ifndef PRODUCT_PROFESSIONAL #ifndef PRODUCT_PROFESSIONAL
#define PRODUCT_PROFESSIONAL 0x00000030 #define PRODUCT_PROFESSIONAL 0x00000030
#define PRODUCT_PROFESSIONAL_N 0x00000031 #define PRODUCT_PROFESSIONAL_N 0x00000031
#endif #endif
#ifndef PRODUCT_ULTIMATE_E #ifndef PRODUCT_ULTIMATE_E
#define PRODUCT_STARTER_E 0x00000042 #define PRODUCT_STARTER_E 0x00000042
#define PRODUCT_HOME_BASIC_E 0x00000043 #define PRODUCT_HOME_BASIC_E 0x00000043
#define PRODUCT_HOME_PREMIUM_E 0x00000044 #define PRODUCT_HOME_PREMIUM_E 0x00000044
#define PRODUCT_PROFESSIONAL_E 0x00000045 #define PRODUCT_PROFESSIONAL_E 0x00000045
#define PRODUCT_ENTERPRISE_E 0x00000046 #define PRODUCT_ENTERPRISE_E 0x00000046
#define PRODUCT_ULTIMATE_E 0x00000047 #define PRODUCT_ULTIMATE_E 0x00000047
#endif #endif
void CIrrDeviceWin32::getWindowsVersion(core::stringc& out) void CIrrDeviceWin32::getWindowsVersion(core::stringc& out)
{ {
OSVERSIONINFOEX osvi; OSVERSIONINFOEX osvi;
PGPI pGPI; PGPI pGPI;
BOOL bOsVersionInfoEx; BOOL bOsVersionInfoEx;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi); bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi);
if (!bOsVersionInfoEx) if (!bOsVersionInfoEx)
{ {
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (! GetVersionEx((OSVERSIONINFO *) &osvi)) if (! GetVersionEx((OSVERSIONINFO *) &osvi))
return; return;
} }
switch (osvi.dwPlatformId) switch (osvi.dwPlatformId)
{ {
case VER_PLATFORM_WIN32_NT: case VER_PLATFORM_WIN32_NT:
if (osvi.dwMajorVersion <= 4) if (osvi.dwMajorVersion <= 4)
out.append("Microsoft Windows NT "); out.append("Microsoft Windows NT ");
else else
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
out.append("Microsoft Windows 2000 "); out.append("Microsoft Windows 2000 ");
else else
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
out.append("Microsoft Windows XP "); out.append("Microsoft Windows XP ");
else else
if (osvi.dwMajorVersion == 6 ) if (osvi.dwMajorVersion == 6 )
{ {
if (osvi.dwMinorVersion == 0) if (osvi.dwMinorVersion == 0)
{ {
if (osvi.wProductType == VER_NT_WORKSTATION) if (osvi.wProductType == VER_NT_WORKSTATION)
out.append("Microsoft Windows Vista "); out.append("Microsoft Windows Vista ");
else else
out.append("Microsoft Windows Server 2008 "); out.append("Microsoft Windows Server 2008 ");
} }
else if (osvi.dwMinorVersion == 1) else if (osvi.dwMinorVersion == 1)
{ {
if (osvi.wProductType == VER_NT_WORKSTATION) if (osvi.wProductType == VER_NT_WORKSTATION)
out.append("Microsoft Windows 7 "); out.append("Microsoft Windows 7 ");
else else
out.append("Microsoft Windows Server 2008 R2 "); out.append("Microsoft Windows Server 2008 R2 ");
} }
} }
if (bOsVersionInfoEx) if (bOsVersionInfoEx)
{ {
if (osvi.dwMajorVersion == 6) if (osvi.dwMajorVersion == 6)
{ {
DWORD dwType; DWORD dwType;
pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo"); pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo");
pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType); pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
switch (dwType) switch (dwType)
{ {
case PRODUCT_ULTIMATE: case PRODUCT_ULTIMATE:
case PRODUCT_ULTIMATE_E: case PRODUCT_ULTIMATE_E:
case PRODUCT_ULTIMATE_N: case PRODUCT_ULTIMATE_N:
out.append("Ultimate Edition "); out.append("Ultimate Edition ");
break; break;
case PRODUCT_PROFESSIONAL: case PRODUCT_PROFESSIONAL:
case PRODUCT_PROFESSIONAL_E: case PRODUCT_PROFESSIONAL_E:
case PRODUCT_PROFESSIONAL_N: case PRODUCT_PROFESSIONAL_N:
out.append("Professional Edition "); out.append("Professional Edition ");
break; break;
case PRODUCT_HOME_BASIC: case PRODUCT_HOME_BASIC:
case PRODUCT_HOME_BASIC_E: case PRODUCT_HOME_BASIC_E:
case PRODUCT_HOME_BASIC_N: case PRODUCT_HOME_BASIC_N:
out.append("Home Basic Edition "); out.append("Home Basic Edition ");
break; break;
case PRODUCT_HOME_PREMIUM: case PRODUCT_HOME_PREMIUM:
case PRODUCT_HOME_PREMIUM_E: case PRODUCT_HOME_PREMIUM_E:
case PRODUCT_HOME_PREMIUM_N: case PRODUCT_HOME_PREMIUM_N:
out.append("Home Premium Edition "); out.append("Home Premium Edition ");
break; break;
case PRODUCT_ENTERPRISE: case PRODUCT_ENTERPRISE:
case PRODUCT_ENTERPRISE_E: case PRODUCT_ENTERPRISE_E:
case PRODUCT_ENTERPRISE_N: case PRODUCT_ENTERPRISE_N:
out.append("Enterprise Edition "); out.append("Enterprise Edition ");
break; break;
case PRODUCT_BUSINESS: case PRODUCT_BUSINESS:
case PRODUCT_BUSINESS_N: case PRODUCT_BUSINESS_N:
out.append("Business Edition "); out.append("Business Edition ");
break; break;
case PRODUCT_STARTER: case PRODUCT_STARTER:
case PRODUCT_STARTER_E: case PRODUCT_STARTER_E:
case PRODUCT_STARTER_N: case PRODUCT_STARTER_N:
out.append("Starter Edition "); out.append("Starter Edition ");
break; break;
} }
} }
#ifdef VER_SUITE_ENTERPRISE #ifdef VER_SUITE_ENTERPRISE
else else
if (osvi.wProductType == VER_NT_WORKSTATION) if (osvi.wProductType == VER_NT_WORKSTATION)
{ {
#ifndef __BORLANDC__ #ifndef __BORLANDC__
if( osvi.wSuiteMask & VER_SUITE_PERSONAL ) if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
out.append("Personal "); out.append("Personal ");
else else
out.append("Professional "); out.append("Professional ");
#endif #endif
} }
else if (osvi.wProductType == VER_NT_SERVER) else if (osvi.wProductType == VER_NT_SERVER)
{ {
if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
out.append("DataCenter Server "); out.append("DataCenter Server ");
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
out.append("Advanced Server "); out.append("Advanced Server ");
else else
out.append("Server "); out.append("Server ");
} }
#endif #endif
} }
else else
{ {
HKEY hKey; HKEY hKey;
char szProductType[80]; char szProductType[80];
DWORD dwBufLen; DWORD dwBufLen;
RegOpenKeyEx( HKEY_LOCAL_MACHINE, RegOpenKeyEx( HKEY_LOCAL_MACHINE,
__TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"), __TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"),
0, KEY_QUERY_VALUE, &hKey ); 0, KEY_QUERY_VALUE, &hKey );
RegQueryValueEx( hKey, __TEXT("ProductType"), NULL, NULL, RegQueryValueEx( hKey, __TEXT("ProductType"), NULL, NULL,
(LPBYTE) szProductType, &dwBufLen); (LPBYTE) szProductType, &dwBufLen);
RegCloseKey( hKey ); RegCloseKey( hKey );
if (_strcmpi( "WINNT", szProductType) == 0 ) if (_strcmpi( "WINNT", szProductType) == 0 )
out.append("Professional "); out.append("Professional ");
if (_strcmpi( "LANMANNT", szProductType) == 0) if (_strcmpi( "LANMANNT", szProductType) == 0)
out.append("Server "); out.append("Server ");
if (_strcmpi( "SERVERNT", szProductType) == 0) if (_strcmpi( "SERVERNT", szProductType) == 0)
out.append("Advanced Server "); out.append("Advanced Server ");
} }
// Display version, service pack (if any), and build number. // Display version, service pack (if any), and build number.
char tmp[255]; char tmp[255];
if (osvi.dwMajorVersion <= 4 ) if (osvi.dwMajorVersion <= 4 )
{ {
sprintf(tmp, "version %ld.%ld %s (Build %ld)", sprintf(tmp, "version %ld.%ld %s (Build %ld)",
osvi.dwMajorVersion, osvi.dwMajorVersion,
osvi.dwMinorVersion, osvi.dwMinorVersion,
osvi.szCSDVersion, osvi.szCSDVersion,
osvi.dwBuildNumber & 0xFFFF); osvi.dwBuildNumber & 0xFFFF);
} }
else else
{ {
sprintf(tmp, "%s (Build %ld)", osvi.szCSDVersion, sprintf(tmp, "%s (Build %ld)", osvi.szCSDVersion,
osvi.dwBuildNumber & 0xFFFF); osvi.dwBuildNumber & 0xFFFF);
} }
out.append(tmp); out.append(tmp);
break; break;
case VER_PLATFORM_WIN32_WINDOWS: case VER_PLATFORM_WIN32_WINDOWS:
IsNonNTWindows = true; IsNonNTWindows = true;
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
{ {
out.append("Microsoft Windows 95 "); out.append("Microsoft Windows 95 ");
if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' ) if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
out.append("OSR2 " ); out.append("OSR2 " );
} }
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
{ {
out.append("Microsoft Windows 98 "); out.append("Microsoft Windows 98 ");
if ( osvi.szCSDVersion[1] == 'A' ) if ( osvi.szCSDVersion[1] == 'A' )
out.append( "SE " ); out.append( "SE " );
} }
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
out.append("Microsoft Windows Me "); out.append("Microsoft Windows Me ");
break; break;
case VER_PLATFORM_WIN32s: case VER_PLATFORM_WIN32s:
IsNonNTWindows = true; IsNonNTWindows = true;
out.append("Microsoft Win32s "); out.append("Microsoft Win32s ");
break; break;
} }
} }
//! Notifies the device, that it has been resized //! Notifies the device, that it has been resized
...@@ -1807,7 +1809,7 @@ void CIrrDeviceWin32::ReportLastWinApiError() ...@@ -1807,7 +1809,7 @@ void CIrrDeviceWin32::ReportLastWinApiError()
{ {
// (based on code from ovidiucucu from http://www.codeguru.com/forum/showthread.php?t=318721) // (based on code from ovidiucucu from http://www.codeguru.com/forum/showthread.php?t=318721)
LPCTSTR pszCaption = __TEXT("Windows SDK Error Report"); LPCTSTR pszCaption = __TEXT("Windows SDK Error Report");
DWORD dwError = GetLastError(); DWORD dwError = GetLastError();
if(NOERROR == dwError) if(NOERROR == dwError)
{ {
...@@ -1866,7 +1868,7 @@ HCURSOR CIrrDeviceWin32::TextureToCursor(HWND hwnd, irr::video::ITexture * tex, ...@@ -1866,7 +1868,7 @@ HCURSOR CIrrDeviceWin32::TextureToCursor(HWND hwnd, irr::video::ITexture * tex,
{ {
data += bytesLeftGap; data += bytesLeftGap;
for ( s32 x = 0; x < sourceRect.getWidth(); ++x ) for ( s32 x = 0; x < sourceRect.getWidth(); ++x )
{ {
video::SColor pixelCol; video::SColor pixelCol;
pixelCol.setData((const void*)data, format); pixelCol.setData((const void*)data, format);
data += bytesPerPixel; data += bytesPerPixel;
...@@ -1907,27 +1909,27 @@ HCURSOR CIrrDeviceWin32::TextureToCursor(HWND hwnd, irr::video::ITexture * tex, ...@@ -1907,27 +1909,27 @@ HCURSOR CIrrDeviceWin32::TextureToCursor(HWND hwnd, irr::video::ITexture * tex,
HCURSOR cursor = CreateIconIndirect(&iconinfo); HCURSOR cursor = CreateIconIndirect(&iconinfo);
DeleteObject(andBitmap); DeleteObject(andBitmap);
DeleteObject(xorBitmap); DeleteObject(xorBitmap);
return cursor; return cursor;
} }
CIrrDeviceWin32::CCursorControl::CCursorControl(CIrrDeviceWin32* device, const core::dimension2d<u32>& wsize, HWND hwnd, bool fullscreen) CIrrDeviceWin32::CCursorControl::CCursorControl(CIrrDeviceWin32* device, const core::dimension2d<u32>& wsize, HWND hwnd, bool fullscreen)
: Device(device), WindowSize(wsize), InvWindowSize(0.0f, 0.0f), : Device(device), WindowSize(wsize), InvWindowSize(0.0f, 0.0f),
HWnd(hwnd), BorderX(0), BorderY(0), HWnd(hwnd), BorderX(0), BorderY(0),
UseReferenceRect(false), IsVisible(true) UseReferenceRect(false), IsVisible(true)
, ActiveIcon(gui::ECI_NORMAL), ActiveIconStartTime(0) , ActiveIcon(gui::ECI_NORMAL), ActiveIconStartTime(0)
{ {
if (WindowSize.Width!=0) if (WindowSize.Width!=0)
InvWindowSize.Width = 1.0f / WindowSize.Width; InvWindowSize.Width = 1.0f / WindowSize.Width;
if (WindowSize.Height!=0) if (WindowSize.Height!=0)
InvWindowSize.Height = 1.0f / WindowSize.Height; InvWindowSize.Height = 1.0f / WindowSize.Height;
updateBorderSize(fullscreen, false); updateBorderSize(fullscreen, false);
initCursors(); initCursors();
} }
CIrrDeviceWin32::CCursorControl::~CCursorControl() CIrrDeviceWin32::CCursorControl::~CCursorControl()
...@@ -1944,19 +1946,19 @@ CIrrDeviceWin32::CCursorControl::~CCursorControl() ...@@ -1944,19 +1946,19 @@ CIrrDeviceWin32::CCursorControl::~CCursorControl()
void CIrrDeviceWin32::CCursorControl::initCursors() void CIrrDeviceWin32::CCursorControl::initCursors()
{ {
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_ARROW)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_ARROW)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_CROSS)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_CROSS)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_HAND)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_HAND)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_HELP)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_HELP)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_IBEAM)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_IBEAM)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_NO)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_NO)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_WAIT)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_WAIT)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZEALL)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZEALL)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENESW)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENESW)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENWSE)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENWSE)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENS)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENS)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZEWE)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZEWE)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_UPARROW)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_UPARROW)) );
} }
...@@ -1974,13 +1976,13 @@ void CIrrDeviceWin32::CCursorControl::update() ...@@ -1974,13 +1976,13 @@ void CIrrDeviceWin32::CCursorControl::update()
//! Sets the active cursor icon //! Sets the active cursor icon
void CIrrDeviceWin32::CCursorControl::setActiveIcon(gui::ECURSOR_ICON iconId) void CIrrDeviceWin32::CCursorControl::setActiveIcon(gui::ECURSOR_ICON iconId)
{ {
if ( iconId >= (s32)Cursors.size() ) if ( iconId >= (s32)Cursors.size() )
return; return;
ActiveIcon = iconId; ActiveIcon = iconId;
ActiveIconStartTime = Device->getTimer()->getRealTime(); ActiveIconStartTime = Device->getTimer()->getRealTime();
if ( Cursors[ActiveIcon].Frames.size() ) if ( Cursors[ActiveIcon].Frames.size() )
SetCursor( Cursors[ActiveIcon].Frames[0].IconHW ); SetCursor( Cursors[ActiveIcon].Frames[0].IconHW );
} }
...@@ -1989,7 +1991,7 @@ gui::ECURSOR_ICON CIrrDeviceWin32::CCursorControl::addIcon(const gui::SCursorSpr ...@@ -1989,7 +1991,7 @@ gui::ECURSOR_ICON CIrrDeviceWin32::CCursorControl::addIcon(const gui::SCursorSpr
{ {
if ( icon.SpriteId >= 0 ) if ( icon.SpriteId >= 0 )
{ {
CursorW32 cW32; CursorW32 cW32;
cW32.FrameTime = icon.SpriteBank->getSprites()[icon.SpriteId].frameTime; cW32.FrameTime = icon.SpriteBank->getSprites()[icon.SpriteId].frameTime;
for ( u32 i=0; i < icon.SpriteBank->getSprites()[icon.SpriteId].Frames.size(); ++i ) for ( u32 i=0; i < icon.SpriteBank->getSprites()[icon.SpriteId].Frames.size(); ++i )
...@@ -1998,7 +2000,7 @@ gui::ECURSOR_ICON CIrrDeviceWin32::CCursorControl::addIcon(const gui::SCursorSpr ...@@ -1998,7 +2000,7 @@ gui::ECURSOR_ICON CIrrDeviceWin32::CCursorControl::addIcon(const gui::SCursorSpr
irr::u32 rectId = icon.SpriteBank->getSprites()[icon.SpriteId].Frames[i].rectNumber; irr::u32 rectId = icon.SpriteBank->getSprites()[icon.SpriteId].Frames[i].rectNumber;
irr::core::rect<s32> rectIcon = icon.SpriteBank->getPositions()[rectId]; irr::core::rect<s32> rectIcon = icon.SpriteBank->getPositions()[rectId];
HCURSOR hc = Device->TextureToCursor(HWnd, icon.SpriteBank->getTexture(texId), rectIcon, icon.HotSpot); HCURSOR hc = Device->TextureToCursor(HWnd, icon.SpriteBank->getTexture(texId), rectIcon, icon.HotSpot);
cW32.Frames.push_back( CursorFrameW32(hc) ); cW32.Frames.push_back( CursorFrameW32(hc) );
} }
...@@ -2040,12 +2042,12 @@ void CIrrDeviceWin32::CCursorControl::changeIcon(gui::ECURSOR_ICON iconId, const ...@@ -2040,12 +2042,12 @@ void CIrrDeviceWin32::CCursorControl::changeIcon(gui::ECURSOR_ICON iconId, const
//! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work. //! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work.
core::dimension2di CIrrDeviceWin32::CCursorControl::getSupportedIconSize() const core::dimension2di CIrrDeviceWin32::CCursorControl::getSupportedIconSize() const
{ {
core::dimension2di result; core::dimension2di result;
result.Width = GetSystemMetrics(SM_CXCURSOR); result.Width = GetSystemMetrics(SM_CXCURSOR);
result.Height = GetSystemMetrics(SM_CYCURSOR); result.Height = GetSystemMetrics(SM_CYCURSOR);
return result; return result;
} }
......
...@@ -68,8 +68,7 @@ int main(int argumentCount, char * arguments[]) ...@@ -68,8 +68,7 @@ int main(int argumentCount, char * arguments[])
TEST(testS3DVertex); TEST(testS3DVertex);
TEST(testaabbox3d); TEST(testaabbox3d);
TEST(color); TEST(color);
// TODO: Needs to be fixed first TEST(testTriangle3d);
// TEST(testTriangle3d);
TEST(vectorPositionDimension2d); TEST(vectorPositionDimension2d);
// file system checks (with null driver) // file system checks (with null driver)
TEST(filesystem); TEST(filesystem);
......
...@@ -431,6 +431,10 @@ ...@@ -431,6 +431,10 @@
RelativePath=".\triangleSelector.cpp" RelativePath=".\triangleSelector.cpp"
> >
</File> </File>
<File
RelativePath=".\triangle3d.cpp"
>
</File>
<File <File
RelativePath=".\vectorPositionDimension2d.cpp" RelativePath=".\vectorPositionDimension2d.cpp"
> >
......
...@@ -102,7 +102,7 @@ static void stageModifications(int stage, vector3d<T>& point) ...@@ -102,7 +102,7 @@ static void stageModifications(int stage, vector3d<T>& point)
} }
template<class T> template<class T>
static bool isPointInside(triangle3d<T> triangleOrig) static bool isPointInside(triangle3d<T> triangleOrig, bool testIsInside, bool testIsInsideFast)
{ {
bool allExpected=true; bool allExpected=true;
...@@ -124,18 +124,24 @@ static bool isPointInside(triangle3d<T> triangleOrig) ...@@ -124,18 +124,24 @@ static bool isPointInside(triangle3d<T> triangleOrig)
vector3d<T> point = pointsInside[i]; vector3d<T> point = pointsInside[i];
stageModifications(stage, point); stageModifications(stage, point);
allExpected &= triangle.isPointInside( point ); if ( testIsInside )
if ( !allExpected )
{ {
logTestString("triangle3d::isPointInside pointsInside test failed in stage %d point %d\n", stage, i); allExpected &= triangle.isPointInside( point );
return false; if ( !allExpected )
{
logTestString("triangle3d::isPointInside pointsInside test failed in stage %d point %d\n", stage, i);
return false;
}
} }
allExpected &= triangle.isPointInsideFast( point ); if ( testIsInsideFast )
if ( !allExpected )
{ {
logTestString("triangle3d::isPointInsideFast pointsInside test failed in stage %d point %d\n", stage, i); allExpected &= triangle.isPointInsideFast( point );
return false; if ( !allExpected )
{
logTestString("triangle3d::isPointInsideFast pointsInside test failed in stage %d point %d\n", stage, i);
return false;
}
} }
} }
} }
...@@ -163,18 +169,24 @@ static bool isPointInside(triangle3d<T> triangleOrig) ...@@ -163,18 +169,24 @@ static bool isPointInside(triangle3d<T> triangleOrig)
vector3d<T> point = pointsOutside[i]; vector3d<T> point = pointsOutside[i];
stageModifications(stage, point); stageModifications(stage, point);
allExpected &= !triangle.isPointInside( point ); if ( testIsInside )
if ( !allExpected )
{ {
logTestString("triangle3d::isPointInside pointsOutside test failed in stage %d point %d\n", stage, i); allExpected &= !triangle.isPointInside( point );
return false; if ( !allExpected )
{
logTestString("triangle3d::isPointInside pointsOutside test failed in stage %d point %d\n", stage, i);
return false;
}
} }
allExpected &= !triangle.isPointInsideFast( point ); if ( testIsInsideFast )
if ( !allExpected )
{ {
logTestString("triangle3d::isPointInsideFast pointsOutside test failed in stage %d point %d\n", stage, i); allExpected &= !triangle.isPointInsideFast( point );
return false; if ( !allExpected )
{
logTestString("triangle3d::isPointInsideFast pointsOutside test failed in stage %d point %d\n", stage, i);
return false;
}
} }
} }
} }
...@@ -198,25 +210,67 @@ static bool isPointInside(triangle3d<T> triangleOrig) ...@@ -198,25 +210,67 @@ static bool isPointInside(triangle3d<T> triangleOrig)
vector3d<T> point = pointsBorder[i]; vector3d<T> point = pointsBorder[i];
stageModifications(stage, point); stageModifications(stage, point);
allExpected &= triangle.isPointInside( point ); if ( testIsInside )
if ( !allExpected )
{ {
logTestString("triangle3d::isPointInside pointsBorder test failed in stage %d point %d\n", stage, i); allExpected &= triangle.isPointInside( point );
return false; if ( !allExpected )
{
logTestString("triangle3d::isPointInside pointsBorder test failed in stage %d point %d\n", stage, i);
return false;
}
} }
/* results for isPointInsideFast are mixed for border cases, but I guess that's fine. if ( testIsInsideFast )
if ( triangle.isPointInsideFast( point ) ) {
logTestString("+ triangle3d::isPointInsideFast pointsBorder stage %d point %d is INSIDE\n", stage, i); allExpected &= triangle.isPointInsideFast( point );
else if ( !allExpected )
logTestString("- triangle3d::isPointInsideFast pointsBorder stage %d point %d is NOT inside\n", stage, i); {
*/ logTestString("triangle3d::isPointInsideFast pointsBorder test failed in stage %d point %d\n", stage, i);
return false;
}
}
} }
} }
return allExpected; return allExpected;
} }
// Checking behaviour when FPU is set to single precision mode.
// This is somewhat important as Direct3D does by default set the FPU into that mode.
static bool isPointInsideWithSinglePrecision()
{
#ifdef _MSC_VER
int original = _control87( 0, 0 );
_control87(_PC_24, MCW_PC); // single precision (double precision would be _PC_53)
// Testcase just some example which popped up wwhic shows the difference between single precision and double precision
irr::core::triangle3d<irr::f64> t;
irr::core::vector3d<irr::f64> point;
t.pointA.X = 3.7237894e+002f;
t.pointA.Y = -1.0025123e+003f;
t.pointA.Z = 0;
t.pointB.X = 2.6698560e+002f;
t.pointB.Y = -9.8957166e+002f;
t.pointB.Z = 0;
t.pointC.X = 2.6981503e+002f;
t.pointC.Y = -9.3992731e+002f;
t.pointC.Z = 0;
point.X = 2.6981500e+002f;
point.Y = -9.3992743e+002f;
point.Z = 0;
bool ok = !t.isPointInside( point );
_control87(original, 0xfffff); // restore
return ok;
#else
// TODO: Be free to try changing the fpu for other systems.
// I think for MinGW it's still easy, but for Linux this probably also needs changed linker flags.
return true;
#endif
}
// Test the functionality of triangle3d<T> // Test the functionality of triangle3d<T>
/** Validation is done with asserts() against expected results. */ /** Validation is done with asserts() against expected results. */
...@@ -224,6 +278,9 @@ bool testTriangle3d(void) ...@@ -224,6 +278,9 @@ bool testTriangle3d(void)
{ {
bool allExpected = true; bool allExpected = true;
/* TODO: disabled for now. I (aka CuteAlien) have by now an example which allows debugging
that problem easier and also found some workaround (which needs an interface change
and a behaviour change and won't get into 1.7 therefore).
logTestString("Test getIntersectionWithLine with f32\n"); logTestString("Test getIntersectionWithLine with f32\n");
{ {
triangle3df triangle( triangle3df triangle(
...@@ -246,28 +303,38 @@ bool testTriangle3d(void) ...@@ -246,28 +303,38 @@ bool testTriangle3d(void)
ray.end = vector3d<f64>(11250.000000, -1000.000000, 250.000000); ray.end = vector3d<f64>(11250.000000, -1000.000000, 250.000000);
allExpected &= testGetIntersectionWithLine(triangle, ray); allExpected &= testGetIntersectionWithLine(triangle, ray);
} }
*/
/* For now we have no solution yet to fix isPointInside for large integers without
getting worse floating-point precision at the same time.
So instead isPointInsideFast got fixed and should be used for int's.
bool testEigen = triangle3di(vector3di(250, 0, 0), vector3di(0, 0, 500), vector3di(500, 0, 500)).isPointInside(vector3di(300,0,300)); bool testEigen = triangle3di(vector3di(250, 0, 0), vector3di(0, 0, 500), vector3di(500, 0, 500)).isPointInside(vector3di(300,0,300));
if ( !testEigen ) // test from Eigen from here: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=44372&p=254331#p254331 if ( !testEigen ) // test from Eigen from here: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=44372&p=254331#p254331
logTestString("Test isPointInside fails with integers\n"); logTestString("Test isPointInside fails with integers\n");
allExpected &= testEigen; allExpected &= testEigen;
*/
logTestString("Test isPointInside with f32\n"); logTestString("Test isPointInside with f32\n");
{ {
triangle3d<f32> t(vector3d<f32>(-1000,-1000,0), vector3d<f32>(1000,-1000,0), vector3d<f32>(0,1000,0)); triangle3d<f32> t(vector3d<f32>(-1000,-1000,0), vector3d<f32>(1000,-1000,0), vector3d<f32>(0,1000,0));
allExpected &= isPointInside(t); allExpected &= isPointInside(t, true, true);
} }
logTestString("Test isPointInside with f64\n"); logTestString("Test isPointInside with f64\n");
{ {
triangle3d<f64> t(vector3d<f64>(-1000,-1000,0), vector3d<f64>(1000,-1000,0), vector3d<f64>(0,1000,0)); triangle3d<f64> t(vector3d<f64>(-1000,-1000,0), vector3d<f64>(1000,-1000,0), vector3d<f64>(0,1000,0));
allExpected &= isPointInside(t); allExpected &= isPointInside(t, true, true);
} }
logTestString("Test isPointInside with s32\n"); logTestString("Test isPointInside with s32\n");
{ {
triangle3d<s32> t(vector3d<s32>(-1000,-1000,0), vector3d<s32>(1000,-1000,0), vector3d<s32>(0,1000,0)); triangle3d<s32> t(vector3d<s32>(-1000,-1000,0), vector3d<s32>(1000,-1000,0), vector3d<s32>(0,1000,0));
allExpected &= isPointInside(t); allExpected &= isPointInside(t, false, true);
}
logTestString("Test isPointInsideWithSinglePrecision\n");
{
allExpected &= isPointInsideWithSinglePrecision();
} }
if(allExpected) if(allExpected)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment