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:
-----------------------------
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.
- 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
- Add integer template specialization for vector3d::getSphericalCoordinateAngles which rounds angles to nearest integer now.
......
......@@ -147,8 +147,7 @@ void updateScaleInfo(scene::ISceneNode* model)
}
/*
The three following functions do several stuff used by the mesh viewer. The
first function showAboutText() simply displays a messagebox with a caption and
Function showAboutText() displays a messagebox with a caption and
a message text. The texts will be stored in the MessageText and Caption
variables at startup.
*/
......@@ -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
displays a short message box, if the model could not be loaded.
*/
......@@ -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
changing the scale of the displayed model.
*/
......@@ -323,6 +322,10 @@ void createToolBox()
scrollbar->setSmallStep(1);
}
/*
Function updateToolBox() is called each frame to update dynamic information in
the toolbox.
*/
void updateToolBox()
{
IGUIEnvironment* env = Device->getGUIEnvironment();
......@@ -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
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
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
{
......@@ -503,6 +522,11 @@ public:
*/
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 (Device)
......
......@@ -788,7 +788,7 @@ funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename)
#endif
/*
get the current collision respone camera animator
get the current collision response camera animator
*/
ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * device )
{
......
......@@ -69,9 +69,9 @@ namespace gui
//! Sets text justification mode
/** \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,
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;
//! Enables or disables word wrap.
......
......@@ -141,10 +141,20 @@ namespace irr
KEY_RCONTROL = 0xA3, // Right CONTROL key
KEY_LMENU = 0xA4, // Left MENU key
KEY_RMENU = 0xA5, // Right MENU key
KEY_PLUS = 0xBB, // Plus Key (+)
KEY_COMMA = 0xBC, // Comma Key (,)
KEY_MINUS = 0xBD, // Minus Key (-)
KEY_PERIOD = 0xBE, // Period Key (.)
KEY_OEM_1 = 0xBA, // for US ";:"
KEY_PLUS = 0xBB, // Plus Key "+"
KEY_COMMA = 0xBC, // Comma 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_CRSEL = 0xF7, // CrSel key
KEY_EXSEL = 0xF8, // ExSel key
......
......@@ -82,10 +82,27 @@ namespace core
}
//! 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.
\return True if the point is inside the triangle, otherwise false. */
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> b = pointB - pointA;
......@@ -105,38 +122,7 @@ namespace core
// 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.
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:
vector2d<T>& normalize()
{
f32 length = (f32)(X*X + Y*Y);
if (core::equals(length, 0.f))
if ( length == 0 )
return *this;
length = core::reciprocal_squareroot ( length );
X = (T)(X * length);
......
......@@ -168,7 +168,7 @@ namespace core
vector3d<T>& normalize()
{
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;
length = core::reciprocal_squareroot(length);
......
......@@ -94,9 +94,10 @@ The Irrlicht Engine SDK version 1.8
* Linux:
* Needed: XServer with include files
* Optional: OpenGL headers and libraries (libGL.so), for OpenGL support
* GLX + XF86VidMode or XRandr extension (X11 support libraries,
the latter two for fullscreen mode)
* Optional: OpenGL headers and libraries (libGL.so) for OpenGL support
GLX +
XF86VidMode [package x11proto-xf86vidmode-dev] or XRandr
(X11 support libraries, the latter two for fullscreen mode)
* OSX:
* Needed: XCode and Cocoa framework
......
......@@ -155,13 +155,13 @@ void CGUIEditBox::setWordWrap(bool enable)
void CGUIEditBox::updateAbsolutePosition()
{
core::rect<s32> oldAbsoluteRect(AbsoluteRect);
core::rect<s32> oldAbsoluteRect(AbsoluteRect);
IGUIElement::updateAbsolutePosition();
if ( oldAbsoluteRect != AbsoluteRect )
{
calculateFrameRect();
breakText();
calculateScrollPos();
breakText();
calculateScrollPos();
}
}
......@@ -466,7 +466,7 @@ bool CGUIEditBox::processKey(const SEvent& event)
}
else
{
sendGuiEvent( EGET_EDITBOX_ENTER );
sendGuiEvent( EGET_EDITBOX_ENTER );
}
break;
case KEY_LEFT:
......@@ -687,8 +687,8 @@ bool CGUIEditBox::processKey(const SEvent& event)
return true;
}
// Set new text markers
setTextMarkers( newMarkBegin, newMarkEnd );
// Set new text markers
setTextMarkers( newMarkBegin, newMarkEnd );
// break the text if it has changed
if (textChanged)
......@@ -871,25 +871,27 @@ void CGUIEditBox::draw()
}
// draw cursor
if (WordWrap || MultiLine)
if ( IsEnabled )
{
cursorLine = getLineFromPos(CursorPos);
txtLine = &BrokenText[cursorLine];
startPos = BrokenTextPositions[cursorLine];
}
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 (WordWrap || MultiLine)
{
cursorLine = getLineFromPos(CursorPos);
txtLine = &BrokenText[cursorLine];
startPos = BrokenTextPositions[cursorLine];
}
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)
{
setTextRect(cursorLine);
CurrentTextRect.UpperLeftCorner.X += charcursorpos;
if (focus && (os::Timer::getTime() - BlinkStartTime) % 700 < 350)
{
setTextRect(cursorLine);
CurrentTextRect.UpperLeftCorner.X += charcursorpos;
font->draw(L"_", CurrentTextRect,
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
false, true, &localClipRect);
font->draw(L"_", CurrentTextRect,
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
false, true, &localClipRect);
}
}
}
......@@ -975,7 +977,7 @@ bool CGUIEditBox::processMouse(const SEvent& event)
CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
if (MouseMarking)
{
setTextMarkers( MarkBegin, CursorPos );
setTextMarkers( MarkBegin, CursorPos );
}
MouseMarking = false;
calculateScrollPos();
......@@ -1015,7 +1017,7 @@ bool CGUIEditBox::processMouse(const SEvent& event)
// move cursor
CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
s32 newMarkBegin = MarkBegin;
s32 newMarkBegin = MarkBegin;
if (!MouseMarking)
newMarkBegin = CursorPos;
......@@ -1113,8 +1115,13 @@ void CGUIEditBox::breakText()
c = 0;
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);
--size;
if ( CursorPos > i )
--CursorPos;
}
}
else if (c == L'\n') // Unix breaks
......@@ -1186,7 +1193,10 @@ void CGUIEditBox::breakText()
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)
{
if ( line < 0 )
......@@ -1317,54 +1327,129 @@ void CGUIEditBox::inputChar(wchar_t c)
calculateScrollPos();
}
// calculate autoscroll
void CGUIEditBox::calculateScrollPos()
{
if (!AutoScroll)
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);
if ( cursLine < 0 )
return;
setTextRect(cursLine);
const bool hasBrokenText = MultiLine || WordWrap;
// don't do horizontal scrolling when wordwrap is enabled.
if (!WordWrap)
// Check horizonal scrolling
// NOTE: Calculations different to vertical scrolling because setTextRect interprets VAlign relative to line but HAlign not relative to row
{
// get cursor position
IGUIFont* font = getActiveFont();
if (!font)
return;
core::stringw *txtLine = MultiLine ? &BrokenText[cursLine] : &Text;
s32 cPos = MultiLine ? CursorPos - BrokenTextPositions[cursLine] : CursorPos;
// get cursor area
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 +
font->getDimension(txtLine->subString(0, cPos).c_str()).Width;
s32 cEnd = cStart + font->getDimension(L"_ ").Width;
if ( txtWidth < FrameRect.getWidth() )
{
// TODO: Needs a clean left and right gap removal depending on HAlign, similar to vertical scrolling tests for top/bottom.
// 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;
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
if (FrameRect.LowerRightCorner.Y < CurrentTextRect.LowerRightCorner.Y + VScrollPos)
VScrollPos = CurrentTextRect.LowerRightCorner.Y - FrameRect.LowerRightCorner.Y + VScrollPos;
// TODO: should show more characters to the left when we're scrolling left
// and the cursor reaches the border.
}
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)
VScrollPos = CurrentTextRect.UpperLeftCorner.Y - FrameRect.UpperLeftCorner.Y + VScrollPos;
else
VScrollPos = 0;
// calculate vertical scrolling
if (hasBrokenText)
{
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()
......@@ -1385,12 +1470,12 @@ void CGUIEditBox::calculateFrameRect()
//! set text markers
void CGUIEditBox::setTextMarkers(s32 begin, s32 end)
{
if ( begin != MarkBegin || end != MarkEnd )
{
MarkBegin = begin;
MarkEnd = end;
sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED);
}
if ( begin != MarkBegin || end != MarkEnd )
{
MarkBegin = begin;
MarkEnd = end;
sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED);
}
}
//! send some gui event to parent
......@@ -1398,13 +1483,13 @@ void CGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type)
{
if ( Parent )
{
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this;
e.GUIEvent.Element = 0;
e.GUIEvent.EventType = type;
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this;
e.GUIEvent.Element = 0;
e.GUIEvent.EventType = type;
Parent->OnEvent(e);
Parent->OnEvent(e);
}
}
......@@ -1413,21 +1498,21 @@ void CGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWr
{
// IGUIEditBox::serializeAttributes(out,options);
out->addBool ("Border", Border);
out->addBool ("Background", Background);
out->addBool ("OverrideColorEnabled",OverrideColorEnabled );
out->addColor ("OverrideColor", OverrideColor);
// out->addFont("OverrideFont",OverrideFont);
out->addInt ("MaxChars", Max);
out->addBool ("WordWrap", WordWrap);
out->addBool ("MultiLine", MultiLine);
out->addBool ("AutoScroll", AutoScroll);
out->addBool ("PasswordBox", PasswordBox);
out->addBool ("Border", Border);
out->addBool ("Background", Background);
out->addBool ("OverrideColorEnabled", OverrideColorEnabled );
out->addColor ("OverrideColor", OverrideColor);
// out->addFont("OverrideFont", OverrideFont);
out->addInt ("MaxChars", Max);
out->addBool ("WordWrap", WordWrap);
out->addBool ("MultiLine", MultiLine);
out->addBool ("AutoScroll", AutoScroll);
out->addBool ("PasswordBox", PasswordBox);
core::stringw ch = L" ";
ch[0] = PasswordChar;
out->addString("PasswordChar", ch.c_str());
out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
out->addString("PasswordChar", ch.c_str());
out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
IGUIEditBox::serializeAttributes(out,options);
}
......
......@@ -70,7 +70,7 @@ const char* wmDeleteWindow = "WM_DELETE_WINDOW";
//! constructor
CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param)
: CIrrDeviceStub(param),
: CIrrDeviceStub(param),
#ifdef _IRR_COMPILE_WITH_X11_
display(0), visual(0), screennr(0), window(0), StdHints(0), SoftwareImage(0),
#ifdef _IRR_COMPILE_WITH_OPENGL_
......@@ -179,9 +179,9 @@ CIrrDeviceLinux::~CIrrDeviceLinux()
#endif // #ifdef _IRR_COMPILE_WITH_X11_
#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);
}
......@@ -658,7 +658,7 @@ bool CIrrDeviceLinux::createWindow()
XSetWMProtocols(display, window, &wmDelete, 1);
if (CreationParams.Fullscreen)
{
XSetInputFocus(display, window, RevertToParent, CurrentTime);
XSetInputFocus(display, window, RevertToParent, CurrentTime);
int grabKb = XGrabKeyboard(display, window, True, GrabModeAsync,
GrabModeAsync, CurrentTime);
IrrPrintXGrabError(grabKb, "XGrabKeyboard");
......@@ -690,8 +690,8 @@ bool CIrrDeviceLinux::createWindow()
}
WindowMinimized=false;
// Currently broken in X, see Bug ID 2795321
// XkbSetDetectableAutoRepeat(display, True, &AutorepeatSupport);
// Currently broken in X, see Bug ID 2795321
// XkbSetDetectableAutoRepeat(display, True, &AutorepeatSupport);
#ifdef _IRR_COMPILE_WITH_OPENGL_
......@@ -1022,22 +1022,42 @@ bool CIrrDeviceLinux::run()
char buf[8]={0};
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)
{
irrevent.KeyInput.Key = (EKEY_CODE)KeyMap[idx].Win32Key;
}
else
{
// Usually you will check keysymdef.h and add the corresponding key to createKeyMap.
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;
irrevent.KeyInput.PressedDown = (event.type == KeyPress);
// mbtowc(&irrevent.KeyInput.Char, buf, sizeof(buf));
irrevent.KeyInput.Char = (reinterpret_cast<wchar_t*>(buf))[0];
irrevent.KeyInput.Control = (event.xkey.state & ControlMask) != 0;
irrevent.KeyInput.Shift = (event.xkey.state & ShiftMask) != 0;
if (irrevent.KeyInput.Key == 0)
{
// 1:1 mapping to windows-keys would require testing for keyboard type (us, ger, ...)
// So unless we do that we will have some unknown keys here.
if (idx == -1)
{
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);
}
break;
......@@ -1071,7 +1091,7 @@ bool CIrrDeviceLinux::run()
XChangeProperty (display,
req->requestor,
req->property, req->target,
8, // format
8, // format
PropModeReplace,
(unsigned char*) Clipboard.c_str(),
Clipboard.size());
......@@ -1114,7 +1134,7 @@ bool CIrrDeviceLinux::run()
}
#endif //_IRR_COMPILE_WITH_X11_
if(!Close)
if (!Close)
pollJoysticks();
return !Close;
......@@ -1494,11 +1514,11 @@ void CIrrDeviceLinux::createKeyMap()
KeyMap.push_back(SKeyMap(XK_exclam, 0)); //?
KeyMap.push_back(SKeyMap(XK_quotedbl, 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_percent, 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_parenright, 0)); //?
KeyMap.push_back(SKeyMap(XK_asterisk, 0)); //?
......@@ -1506,7 +1526,7 @@ void CIrrDeviceLinux::createKeyMap()
KeyMap.push_back(SKeyMap(XK_comma, KEY_COMMA)); //?
KeyMap.push_back(SKeyMap(XK_minus, KEY_MINUS)); //?
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_1, KEY_KEY_1));
KeyMap.push_back(SKeyMap(XK_2, KEY_KEY_2));
......@@ -1518,12 +1538,12 @@ void CIrrDeviceLinux::createKeyMap()
KeyMap.push_back(SKeyMap(XK_8, KEY_KEY_8));
KeyMap.push_back(SKeyMap(XK_9, KEY_KEY_9));
KeyMap.push_back(SKeyMap(XK_colon, 0)); //?
KeyMap.push_back(SKeyMap(XK_semicolon, 0)); //?
KeyMap.push_back(SKeyMap(XK_less, 0)); //?
KeyMap.push_back(SKeyMap(XK_equal, 0)); //?
KeyMap.push_back(SKeyMap(XK_semicolon, KEY_OEM_1));
KeyMap.push_back(SKeyMap(XK_less, KEY_OEM_102));
KeyMap.push_back(SKeyMap(XK_equal, KEY_PLUS));
KeyMap.push_back(SKeyMap(XK_greater, 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_EuroSign, 0)); //?
KeyMap.push_back(SKeyMap(XK_A, KEY_KEY_A));
......@@ -1552,18 +1572,14 @@ void CIrrDeviceLinux::createKeyMap()
KeyMap.push_back(SKeyMap(XK_X, KEY_KEY_X));
KeyMap.push_back(SKeyMap(XK_Y, KEY_KEY_Y));
KeyMap.push_back(SKeyMap(XK_Z, KEY_KEY_Z));
KeyMap.push_back(SKeyMap(XK_Adiaeresis, 0)); //?
KeyMap.push_back(SKeyMap(XK_Odiaeresis, 0)); //?
KeyMap.push_back(SKeyMap(XK_Udiaeresis, 0)); //?
KeyMap.push_back(SKeyMap(XK_bracketleft, 0)); //?
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_bracketleft, KEY_OEM_4));
KeyMap.push_back(SKeyMap(XK_backslash, KEY_OEM_5));
KeyMap.push_back(SKeyMap(XK_bracketright, KEY_OEM_6));
KeyMap.push_back(SKeyMap(XK_asciicircum, KEY_OEM_5));
KeyMap.push_back(SKeyMap(XK_degree, 0)); //?
KeyMap.push_back(SKeyMap(XK_underscore, 0)); //?
KeyMap.push_back(SKeyMap(XK_grave, 0)); //?
KeyMap.push_back(SKeyMap(XK_acute, 0)); //?
KeyMap.push_back(SKeyMap(XK_quoteleft, 0)); //?
KeyMap.push_back(SKeyMap(XK_underscore, KEY_MINUS)); //?
KeyMap.push_back(SKeyMap(XK_grave, KEY_OEM_3));
KeyMap.push_back(SKeyMap(XK_acute, KEY_OEM_6));
KeyMap.push_back(SKeyMap(XK_a, KEY_KEY_A));
KeyMap.push_back(SKeyMap(XK_b, KEY_KEY_B));
KeyMap.push_back(SKeyMap(XK_c, KEY_KEY_C));
......@@ -1590,10 +1606,12 @@ void CIrrDeviceLinux::createKeyMap()
KeyMap.push_back(SKeyMap(XK_x, KEY_KEY_X));
KeyMap.push_back(SKeyMap(XK_y, KEY_KEY_Y));
KeyMap.push_back(SKeyMap(XK_z, KEY_KEY_Z));
KeyMap.push_back(SKeyMap(XK_ssharp, 0)); //?
KeyMap.push_back(SKeyMap(XK_adiaeresis, 0)); //?
KeyMap.push_back(SKeyMap(XK_odiaeresis, 0)); //?
KeyMap.push_back(SKeyMap(XK_udiaeresis, 0)); //?
KeyMap.push_back(SKeyMap(XK_ssharp, KEY_OEM_4));
KeyMap.push_back(SKeyMap(XK_adiaeresis, KEY_OEM_7));
KeyMap.push_back(SKeyMap(XK_odiaeresis, KEY_OEM_3));
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();
#endif
......@@ -1606,7 +1624,7 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf
joystickInfo.clear();
u32 joystick;
for(joystick = 0; joystick < 32; ++joystick)
for (joystick = 0; joystick < 32; ++joystick)
{
// The joystick device could be here...
core::stringc devName = "/dev/js";
......@@ -1616,14 +1634,14 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf
JoystickInfo info;
info.fd = open(devName.c_str(), O_RDONLY);
if(-1 == info.fd)
if (-1 == info.fd)
{
// ...but Ubuntu and possibly other distros
// create the devices in /dev/input
devName = "/dev/input/js";
devName += joystick;
info.fd = open(devName.c_str(), O_RDONLY);
if(-1 == info.fd)
if (-1 == info.fd)
{
// and BSD here
devName = "/dev/joy";
......@@ -1632,7 +1650,7 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf
}
}
if(-1 == info.fd)
if (-1 == info.fd)
continue;
#ifdef __FREE_BSD_
......@@ -1668,7 +1686,7 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf
joystickInfo.push_back(returnInfo);
}
for(joystick = 0; joystick < joystickInfo.size(); ++joystick)
for (joystick = 0; joystick < joystickInfo.size(); ++joystick)
{
char logString[256];
(void)sprintf(logString, "Found joystick %u, %u axes, %u buttons '%s'",
......@@ -1687,36 +1705,36 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf
void CIrrDeviceLinux::pollJoysticks()
{
#if defined (_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
if(0 == ActiveJoysticks.size())
if (0 == ActiveJoysticks.size())
return;
u32 j;
for(j= 0; j< ActiveJoysticks.size(); ++j)
for (u32 j= 0; j< ActiveJoysticks.size(); ++j)
{
JoystickInfo & info = ActiveJoysticks[j];
#ifdef __FREE_BSD_
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.Axis[0] = js.x; /* X axis */
info.persistentData.JoystickEvent.Axis[1] = js.y; /* Y axis */
#else
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)
{
case JS_EVENT_BUTTON:
if (event.value)
info.persistentData.JoystickEvent.ButtonStates |= (1 << event.number);
else
info.persistentData.JoystickEvent.ButtonStates &= ~(1 << event.number);
else
info.persistentData.JoystickEvent.ButtonStates &= ~(1 << event.number);
break;
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;
default:
......@@ -1845,16 +1863,16 @@ const c8* CIrrDeviceLinux::getTextFromClipboard() const
unsigned long numItems, bytesLeft, dummy;
unsigned char *data;
XGetWindowProperty (display, ownerWindow,
XA_STRING, // property name
0, // offset
0, // length (we only check for data, so 0)
0, // Delete 0==false
AnyPropertyType, // AnyPropertyType or property identifier
&type, // return type
&format, // return format
&numItems, // number items
&bytesLeft, // remaining bytes for partial reads
&data); // data
XA_STRING, // property name
0, // offset
0, // length (we only check for data, so 0)
0, // Delete 0==false
AnyPropertyType, // AnyPropertyType or property identifier
&type, // return type
&format, // return format
&numItems, // number items
&bytesLeft, // remaining bytes for partial reads
&data); // data
if ( bytesLeft > 0 )
{
// there is some data to get
......@@ -1907,15 +1925,15 @@ void CIrrDeviceLinux::clearSystemMessages()
{
XEvent event;
int usrArg = ButtonPress;
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
usrArg = ButtonRelease;
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
usrArg = MotionNotify;
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
usrArg = KeyRelease;
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
usrArg = KeyPress;
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {}
}
#endif //_IRR_COMPILE_WITH_X11_
}
......@@ -1940,7 +1958,7 @@ Cursor CIrrDeviceLinux::TextureToMonochromeCursor(irr::video::ITexture * tex, co
ZPixmap, // XYBitmap (depth=1), ZPixmap(depth=x)
0, 0, sourceRect.getWidth(), sourceRect.getHeight(),
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];
XImage * maskImage = XCreateImage(display, visual->visual,
......@@ -1948,7 +1966,7 @@ Cursor CIrrDeviceLinux::TextureToMonochromeCursor(irr::video::ITexture * tex, co
ZPixmap,
0, 0, sourceRect.getWidth(), sourceRect.getHeight(),
32, // bitmap_pad,
0 // bytes_per_line
0 // bytes_per_line
);
maskImage->data = new char[maskImage->height * maskImage->bytes_per_line];
......
......@@ -458,7 +458,7 @@ bool CIrrDeviceSDL::run()
#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
// 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
SDL_JoystickUpdate();
......@@ -478,7 +478,7 @@ bool CIrrDeviceSDL::run()
joyevent.JoystickEvent.ButtonStates |= (SDL_JoystickGetButton(joystick, j)<<j);
// 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_Y]=0;
joyevent.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_Z]=0;
......@@ -570,8 +570,8 @@ bool CIrrDeviceSDL::activateJoysticks(core::array<SJoystickInfo> & joystickInfo)
{
char logString[256];
(void)sprintf(logString, "Found joystick %d, %d axes, %d buttons '%s'",
joystick, joystickInfo[joystick].Axes,
joystickInfo[joystick].Buttons, joystickInfo[joystick].Name.c_str());
joystick, joystickInfo[joystick].Axes,
joystickInfo[joystick].Buttons, joystickInfo[joystick].Name.c_str());
os::Printer::log(logString, ELL_INFORMATION);
}
......
......@@ -138,13 +138,13 @@ struct SJoystickWin32Control
}
if (FAILED(activeJoystick.lpdijoy->SetCooperativeLevel(Device->HWnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE)))
{
{
os::Printer::log("Could not set DirectInput device cooperative level", ELL_WARNING);
return;
}
if (FAILED(activeJoystick.lpdijoy->SetDataFormat(&c_dfDIJoystick2)))
{
{
os::Printer::log("Could not set DirectInput device data format", ELL_WARNING);
return;
}
......@@ -191,41 +191,41 @@ void pollJoysticks()
{
#if defined _IRR_COMPILE_WITH_JOYSTICK_EVENTS_
#ifdef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_
if(0 == ActiveJoysticks.size())
return;
u32 joystick;
if(0 == ActiveJoysticks.size())
return;
u32 joystick;
DIJOYSTATE2 info;
for(joystick = 0; joystick < ActiveJoysticks.size(); ++joystick)
{
// needs to be reset for each joystick
// request ALL values and POV as continuous if possible
for(joystick = 0; joystick < ActiveJoysticks.size(); ++joystick)
{
// needs to be reset for each joystick
// request ALL values and POV as continuous if possible
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)))
{
SEvent event;
event.EventType = irr::EET_JOYSTICK_INPUT_EVENT;
event.JoystickEvent.Joystick = (u8)joystick;
{
SEvent event;
event.EventType = irr::EET_JOYSTICK_INPUT_EVENT;
event.JoystickEvent.Joystick = (u8)joystick;
event.JoystickEvent.POV = (u16)info.rgdwPOV[0];
// set to undefined if no POV value was returned or the value
// is out of range
// set to undefined if no POV value was returned or the value
// is out of range
if ((caps.dwPOVs==0) || (event.JoystickEvent.POV > 35900))
event.JoystickEvent.POV = 65535;
for(int axis = 0; axis < SEvent::SJoystickEvent::NUMBER_OF_AXES; ++axis)
event.JoystickEvent.Axis[axis] = 0;
event.JoystickEvent.POV = 65535;
for(int axis = 0; axis < SEvent::SJoystickEvent::NUMBER_OF_AXES; ++axis)
event.JoystickEvent.Axis[axis] = 0;
u16 dxAxis=0;
u16 irrAxis=0;
while (dxAxis < 6 && irrAxis <caps.dwAxes)
{
{
bool axisFound=0;
s32 axisValue=0;
......@@ -286,9 +286,9 @@ void pollJoysticks()
}
event.JoystickEvent.ButtonStates = buttons;
(void)Device->postEventFromUser(event);
}
}
(void)Device->postEventFromUser(event);
}
}
#else
if (0 == ActiveJoysticks.size())
return;
......@@ -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
static unsigned int LocaleIdToCodepage(unsigned int lcid)
{
switch ( lcid )
{
case 1098: // Telugu
case 1095: // Gujarati
case 1094: // Punjabi
case 1103: // Sanskrit
case 1111: // Konkani
case 1114: // Syriac
case 1099: // Kannada
case 1102: // Marathi
case 1125: // Divehi
case 1067: // Armenian
case 1081: // Hindi
case 1079: // Georgian
case 1097: // Tamil
return 0;
case 1054: // Thai
return 874;
case 1041: // Japanese
return 932;
case 2052: // Chinese (PRC)
case 4100: // Chinese (Singapore)
return 936;
case 1042: // Korean
return 949;
case 5124: // Chinese (Macau S.A.R.)
case 3076: // Chinese (Hong Kong S.A.R.)
case 1028: // Chinese (Taiwan)
return 950;
case 1048: // Romanian
case 1060: // Slovenian
case 1038: // Hungarian
case 1051: // Slovak
case 1045: // Polish
case 1052: // Albanian
case 2074: // Serbian (Latin)
case 1050: // Croatian
case 1029: // Czech
return 1250;
case 1104: // Mongolian (Cyrillic)
case 1071: // FYRO Macedonian
case 2115: // Uzbek (Cyrillic)
case 1058: // Ukrainian
case 2092: // Azeri (Cyrillic)
case 1092: // Tatar
case 1087: // Kazakh
case 1059: // Belarusian
case 1088: // Kyrgyz (Cyrillic)
case 1026: // Bulgarian
case 3098: // Serbian (Cyrillic)
case 1049: // Russian
return 1251;
case 8201: // English (Jamaica)
case 3084: // French (Canada)
case 1036: // French (France)
case 5132: // French (Luxembourg)
case 5129: // English (New Zealand)
case 6153: // English (Ireland)
case 1043: // Dutch (Netherlands)
case 9225: // English (Caribbean)
case 4108: // French (Switzerland)
case 4105: // English (Canada)
case 1110: // Galician
case 10249: // English (Belize)
case 3079: // German (Austria)
case 6156: // French (Monaco)
case 12297: // English (Zimbabwe)
case 1069: // Basque
case 2067: // Dutch (Belgium)
case 2060: // French (Belgium)
case 1035: // Finnish
case 1080: // Faroese
case 1031: // German (Germany)
case 3081: // English (Australia)
case 1033: // English (United States)
case 2057: // English (United Kingdom)
case 1027: // Catalan
case 11273: // English (Trinidad)
case 7177: // English (South Africa)
case 1030: // Danish
case 13321: // English (Philippines)
case 15370: // Spanish (Paraguay)
case 9226: // Spanish (Colombia)
case 5130: // Spanish (Costa Rica)
case 7178: // Spanish (Dominican Republic)
case 12298: // Spanish (Ecuador)
case 17418: // Spanish (El Salvador)
case 4106: // Spanish (Guatemala)
case 18442: // Spanish (Honduras)
case 3082: // Spanish (International Sort)
case 13322: // Spanish (Chile)
case 19466: // Spanish (Nicaragua)
case 2058: // Spanish (Mexico)
case 10250: // Spanish (Peru)
case 20490: // Spanish (Puerto Rico)
case 1034: // Spanish (Traditional Sort)
case 14346: // Spanish (Uruguay)
case 8202: // Spanish (Venezuela)
case 1089: // Swahili
case 1053: // Swedish
case 2077: // Swedish (Finland)
case 5127: // German (Liechtenstein)
case 1078: // Afrikaans
case 6154: // Spanish (Panama)
case 4103: // German (Luxembourg)
case 16394: // Spanish (Bolivia)
case 2055: // German (Switzerland)
case 1039: // Icelandic
case 1057: // Indonesian
case 1040: // Italian (Italy)
case 2064: // Italian (Switzerland)
case 2068: // Norwegian (Nynorsk)
case 11274: // Spanish (Argentina)
case 1046: // Portuguese (Brazil)
case 1044: // Norwegian (Bokmal)
case 1086: // Malay (Malaysia)
case 2110: // Malay (Brunei Darussalam)
case 2070: // Portuguese (Portugal)
return 1252;
case 1032: // Greek
return 1253;
case 1091: // Uzbek (Latin)
case 1068: // Azeri (Latin)
case 1055: // Turkish
return 1254;
case 1037: // Hebrew
return 1255;
case 5121: // Arabic (Algeria)
case 15361: // Arabic (Bahrain)
case 9217: // Arabic (Yemen)
case 3073: // Arabic (Egypt)
case 2049: // Arabic (Iraq)
case 11265: // Arabic (Jordan)
case 13313: // Arabic (Kuwait)
case 12289: // Arabic (Lebanon)
case 4097: // Arabic (Libya)
case 6145: // Arabic (Morocco)
case 8193: // Arabic (Oman)
case 16385: // Arabic (Qatar)
case 1025: // Arabic (Saudi Arabia)
case 10241: // Arabic (Syria)
case 14337: // Arabic (U.A.E.)
case 1065: // Farsi
case 1056: // Urdu
case 7169: // Arabic (Tunisia)
return 1256;
case 1061: // Estonian
case 1062: // Latvian
case 1063: // Lithuanian
return 1257;
case 1066: // Vietnamese
return 1258;
}
return 65001; // utf-8
switch ( lcid )
{
case 1098: // Telugu
case 1095: // Gujarati
case 1094: // Punjabi
case 1103: // Sanskrit
case 1111: // Konkani
case 1114: // Syriac
case 1099: // Kannada
case 1102: // Marathi
case 1125: // Divehi
case 1067: // Armenian
case 1081: // Hindi
case 1079: // Georgian
case 1097: // Tamil
return 0;
case 1054: // Thai
return 874;
case 1041: // Japanese
return 932;
case 2052: // Chinese (PRC)
case 4100: // Chinese (Singapore)
return 936;
case 1042: // Korean
return 949;
case 5124: // Chinese (Macau S.A.R.)
case 3076: // Chinese (Hong Kong S.A.R.)
case 1028: // Chinese (Taiwan)
return 950;
case 1048: // Romanian
case 1060: // Slovenian
case 1038: // Hungarian
case 1051: // Slovak
case 1045: // Polish
case 1052: // Albanian
case 2074: // Serbian (Latin)
case 1050: // Croatian
case 1029: // Czech
return 1250;
case 1104: // Mongolian (Cyrillic)
case 1071: // FYRO Macedonian
case 2115: // Uzbek (Cyrillic)
case 1058: // Ukrainian
case 2092: // Azeri (Cyrillic)
case 1092: // Tatar
case 1087: // Kazakh
case 1059: // Belarusian
case 1088: // Kyrgyz (Cyrillic)
case 1026: // Bulgarian
case 3098: // Serbian (Cyrillic)
case 1049: // Russian
return 1251;
case 8201: // English (Jamaica)
case 3084: // French (Canada)
case 1036: // French (France)
case 5132: // French (Luxembourg)
case 5129: // English (New Zealand)
case 6153: // English (Ireland)
case 1043: // Dutch (Netherlands)
case 9225: // English (Caribbean)
case 4108: // French (Switzerland)
case 4105: // English (Canada)
case 1110: // Galician
case 10249: // English (Belize)
case 3079: // German (Austria)
case 6156: // French (Monaco)
case 12297: // English (Zimbabwe)
case 1069: // Basque
case 2067: // Dutch (Belgium)
case 2060: // French (Belgium)
case 1035: // Finnish
case 1080: // Faroese
case 1031: // German (Germany)
case 3081: // English (Australia)
case 1033: // English (United States)
case 2057: // English (United Kingdom)
case 1027: // Catalan
case 11273: // English (Trinidad)
case 7177: // English (South Africa)
case 1030: // Danish
case 13321: // English (Philippines)
case 15370: // Spanish (Paraguay)
case 9226: // Spanish (Colombia)
case 5130: // Spanish (Costa Rica)
case 7178: // Spanish (Dominican Republic)
case 12298: // Spanish (Ecuador)
case 17418: // Spanish (El Salvador)
case 4106: // Spanish (Guatemala)
case 18442: // Spanish (Honduras)
case 3082: // Spanish (International Sort)
case 13322: // Spanish (Chile)
case 19466: // Spanish (Nicaragua)
case 2058: // Spanish (Mexico)
case 10250: // Spanish (Peru)
case 20490: // Spanish (Puerto Rico)
case 1034: // Spanish (Traditional Sort)
case 14346: // Spanish (Uruguay)
case 8202: // Spanish (Venezuela)
case 1089: // Swahili
case 1053: // Swedish
case 2077: // Swedish (Finland)
case 5127: // German (Liechtenstein)
case 1078: // Afrikaans
case 6154: // Spanish (Panama)
case 4103: // German (Luxembourg)
case 16394: // Spanish (Bolivia)
case 2055: // German (Switzerland)
case 1039: // Icelandic
case 1057: // Indonesian
case 1040: // Italian (Italy)
case 2064: // Italian (Switzerland)
case 2068: // Norwegian (Nynorsk)
case 11274: // Spanish (Argentina)
case 1046: // Portuguese (Brazil)
case 1044: // Norwegian (Bokmal)
case 1086: // Malay (Malaysia)
case 2110: // Malay (Brunei Darussalam)
case 2070: // Portuguese (Portugal)
return 1252;
case 1032: // Greek
return 1253;
case 1091: // Uzbek (Latin)
case 1068: // Azeri (Latin)
case 1055: // Turkish
return 1254;
case 1037: // Hebrew
return 1255;
case 5121: // Arabic (Algeria)
case 15361: // Arabic (Bahrain)
case 9217: // Arabic (Yemen)
case 3073: // Arabic (Egypt)
case 2049: // Arabic (Iraq)
case 11265: // Arabic (Jordan)
case 13313: // Arabic (Kuwait)
case 12289: // Arabic (Lebanon)
case 4097: // Arabic (Libya)
case 6145: // Arabic (Morocco)
case 8193: // Arabic (Oman)
case 16385: // Arabic (Qatar)
case 1025: // Arabic (Saudi Arabia)
case 10241: // Arabic (Syria)
case 14337: // Arabic (U.A.E.)
case 1065: // Farsi
case 1056: // Urdu
case 7169: // Arabic (Tunisia)
return 1256;
case 1061: // Estonian
case 1062: // Latvian
case 1063: // Lithuanian
return 1257;
case 1066: // Vietnamese
return 1258;
}
return 65001; // utf-8
}
namespace
......@@ -885,10 +885,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
break;
case WM_INPUTLANGCHANGE:
// get the new codepage used for keyboard input
KEYBOARD_INPUT_HKL = GetKeyboardLayout(0);
KEYBOARD_INPUT_CODEPAGE = LocaleIdToCodepage( LOWORD(KEYBOARD_INPUT_HKL) );
return 0;
// get the new codepage used for keyboard input
KEYBOARD_INPUT_HKL = GetKeyboardLayout(0);
KEYBOARD_INPUT_CODEPAGE = LocaleIdToCodepage( LOWORD(KEYBOARD_INPUT_HKL) );
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
......@@ -1148,7 +1148,7 @@ bool CIrrDeviceWin32::run()
{
os::Timer::tick();
static_cast<CCursorControl*>(CursorControl)->update();
static_cast<CCursorControl*>(CursorControl)->update();
MSG msg;
......@@ -1270,16 +1270,16 @@ bool CIrrDeviceWin32::present(video::IImage* image, void* windowId, core::rect<s
BITMAPV4HEADER bi;
ZeroMemory (&bi, sizeof(bi));
bi.bV4Size = sizeof(BITMAPINFOHEADER);
bi.bV4BitCount = (WORD)image->getBitsPerPixel();
bi.bV4Planes = 1;
bi.bV4Width = image->getDimension().Width;
bi.bV4Height = -((s32)image->getDimension().Height);
bi.bV4Size = sizeof(BITMAPINFOHEADER);
bi.bV4BitCount = (WORD)image->getBitsPerPixel();
bi.bV4Planes = 1;
bi.bV4Width = image->getDimension().Width;
bi.bV4Height = -((s32)image->getDimension().Height);
bi.bV4V4Compression = BI_BITFIELDS;
bi.bV4AlphaMask = image->getAlphaMask();
bi.bV4RedMask = image->getRedMask();
bi.bV4GreenMask = image->getGreenMask();
bi.bV4BlueMask = image->getBlueMask();
bi.bV4AlphaMask = image->getAlphaMask();
bi.bV4RedMask = image->getRedMask();
bi.bV4GreenMask = image->getGreenMask();
bi.bV4BlueMask = image->getBlueMask();
if ( src )
{
......@@ -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
// or not
#ifndef PRODUCT_ULTIMATE
#define PRODUCT_ULTIMATE 0x00000001
#define PRODUCT_HOME_BASIC 0x00000002
#define PRODUCT_HOME_PREMIUM 0x00000003
#define PRODUCT_ENTERPRISE 0x00000004
#define PRODUCT_HOME_BASIC_N 0x00000005
#define PRODUCT_BUSINESS 0x00000006
#define PRODUCT_STARTER 0x0000000B
#define PRODUCT_ULTIMATE 0x00000001
#define PRODUCT_HOME_BASIC 0x00000002
#define PRODUCT_HOME_PREMIUM 0x00000003
#define PRODUCT_ENTERPRISE 0x00000004
#define PRODUCT_HOME_BASIC_N 0x00000005
#define PRODUCT_BUSINESS 0x00000006
#define PRODUCT_STARTER 0x0000000B
#endif
#ifndef PRODUCT_ULTIMATE_N
#define PRODUCT_BUSINESS_N 0x00000010
#define PRODUCT_HOME_PREMIUM_N 0x0000001A
#define PRODUCT_ENTERPRISE_N 0x0000001B
#define PRODUCT_ULTIMATE_N 0x0000001C
#define PRODUCT_STARTER_N 0x0000002F
#define PRODUCT_BUSINESS_N 0x00000010
#define PRODUCT_HOME_PREMIUM_N 0x0000001A
#define PRODUCT_ENTERPRISE_N 0x0000001B
#define PRODUCT_ULTIMATE_N 0x0000001C
#endif
#ifndef PRODUCT_STARTER_N
#define PRODUCT_STARTER_N 0x0000002F
#endif
#ifndef PRODUCT_PROFESSIONAL
#define PRODUCT_PROFESSIONAL 0x00000030
#define PRODUCT_PROFESSIONAL_N 0x00000031
#define PRODUCT_PROFESSIONAL 0x00000030
#define PRODUCT_PROFESSIONAL_N 0x00000031
#endif
#ifndef PRODUCT_ULTIMATE_E
#define PRODUCT_STARTER_E 0x00000042
#define PRODUCT_HOME_BASIC_E 0x00000043
#define PRODUCT_HOME_PREMIUM_E 0x00000044
#define PRODUCT_PROFESSIONAL_E 0x00000045
#define PRODUCT_ENTERPRISE_E 0x00000046
#define PRODUCT_ULTIMATE_E 0x00000047
#define PRODUCT_STARTER_E 0x00000042
#define PRODUCT_HOME_BASIC_E 0x00000043
#define PRODUCT_HOME_PREMIUM_E 0x00000044
#define PRODUCT_PROFESSIONAL_E 0x00000045
#define PRODUCT_ENTERPRISE_E 0x00000046
#define PRODUCT_ULTIMATE_E 0x00000047
#endif
void CIrrDeviceWin32::getWindowsVersion(core::stringc& out)
{
OSVERSIONINFOEX osvi;
PGPI pGPI;
BOOL bOsVersionInfoEx;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi);
if (!bOsVersionInfoEx)
{
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (! GetVersionEx((OSVERSIONINFO *) &osvi))
return;
}
switch (osvi.dwPlatformId)
{
case VER_PLATFORM_WIN32_NT:
if (osvi.dwMajorVersion <= 4)
out.append("Microsoft Windows NT ");
else
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
out.append("Microsoft Windows 2000 ");
else
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
out.append("Microsoft Windows XP ");
else
if (osvi.dwMajorVersion == 6 )
{
if (osvi.dwMinorVersion == 0)
{
if (osvi.wProductType == VER_NT_WORKSTATION)
out.append("Microsoft Windows Vista ");
else
out.append("Microsoft Windows Server 2008 ");
}
else if (osvi.dwMinorVersion == 1)
{
if (osvi.wProductType == VER_NT_WORKSTATION)
out.append("Microsoft Windows 7 ");
else
out.append("Microsoft Windows Server 2008 R2 ");
}
}
if (bOsVersionInfoEx)
{
if (osvi.dwMajorVersion == 6)
{
DWORD dwType;
pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo");
pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
switch (dwType)
{
case PRODUCT_ULTIMATE:
case PRODUCT_ULTIMATE_E:
case PRODUCT_ULTIMATE_N:
out.append("Ultimate Edition ");
break;
case PRODUCT_PROFESSIONAL:
case PRODUCT_PROFESSIONAL_E:
case PRODUCT_PROFESSIONAL_N:
out.append("Professional Edition ");
break;
case PRODUCT_HOME_BASIC:
case PRODUCT_HOME_BASIC_E:
case PRODUCT_HOME_BASIC_N:
out.append("Home Basic Edition ");
break;
case PRODUCT_HOME_PREMIUM:
case PRODUCT_HOME_PREMIUM_E:
case PRODUCT_HOME_PREMIUM_N:
out.append("Home Premium Edition ");
break;
case PRODUCT_ENTERPRISE:
case PRODUCT_ENTERPRISE_E:
case PRODUCT_ENTERPRISE_N:
out.append("Enterprise Edition ");
break;
case PRODUCT_BUSINESS:
case PRODUCT_BUSINESS_N:
out.append("Business Edition ");
break;
case PRODUCT_STARTER:
case PRODUCT_STARTER_E:
case PRODUCT_STARTER_N:
out.append("Starter Edition ");
break;
}
}
OSVERSIONINFOEX osvi;
PGPI pGPI;
BOOL bOsVersionInfoEx;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi);
if (!bOsVersionInfoEx)
{
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (! GetVersionEx((OSVERSIONINFO *) &osvi))
return;
}
switch (osvi.dwPlatformId)
{
case VER_PLATFORM_WIN32_NT:
if (osvi.dwMajorVersion <= 4)
out.append("Microsoft Windows NT ");
else
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
out.append("Microsoft Windows 2000 ");
else
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
out.append("Microsoft Windows XP ");
else
if (osvi.dwMajorVersion == 6 )
{
if (osvi.dwMinorVersion == 0)
{
if (osvi.wProductType == VER_NT_WORKSTATION)
out.append("Microsoft Windows Vista ");
else
out.append("Microsoft Windows Server 2008 ");
}
else if (osvi.dwMinorVersion == 1)
{
if (osvi.wProductType == VER_NT_WORKSTATION)
out.append("Microsoft Windows 7 ");
else
out.append("Microsoft Windows Server 2008 R2 ");
}
}
if (bOsVersionInfoEx)
{
if (osvi.dwMajorVersion == 6)
{
DWORD dwType;
pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo");
pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
switch (dwType)
{
case PRODUCT_ULTIMATE:
case PRODUCT_ULTIMATE_E:
case PRODUCT_ULTIMATE_N:
out.append("Ultimate Edition ");
break;
case PRODUCT_PROFESSIONAL:
case PRODUCT_PROFESSIONAL_E:
case PRODUCT_PROFESSIONAL_N:
out.append("Professional Edition ");
break;
case PRODUCT_HOME_BASIC:
case PRODUCT_HOME_BASIC_E:
case PRODUCT_HOME_BASIC_N:
out.append("Home Basic Edition ");
break;
case PRODUCT_HOME_PREMIUM:
case PRODUCT_HOME_PREMIUM_E:
case PRODUCT_HOME_PREMIUM_N:
out.append("Home Premium Edition ");
break;
case PRODUCT_ENTERPRISE:
case PRODUCT_ENTERPRISE_E:
case PRODUCT_ENTERPRISE_N:
out.append("Enterprise Edition ");
break;
case PRODUCT_BUSINESS:
case PRODUCT_BUSINESS_N:
out.append("Business Edition ");
break;
case PRODUCT_STARTER:
case PRODUCT_STARTER_E:
case PRODUCT_STARTER_N:
out.append("Starter Edition ");
break;
}
}
#ifdef VER_SUITE_ENTERPRISE
else
if (osvi.wProductType == VER_NT_WORKSTATION)
{
else
if (osvi.wProductType == VER_NT_WORKSTATION)
{
#ifndef __BORLANDC__
if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
out.append("Personal ");
else
out.append("Professional ");
if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
out.append("Personal ");
else
out.append("Professional ");
#endif
}
else if (osvi.wProductType == VER_NT_SERVER)
{
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
out.append("DataCenter Server ");
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
out.append("Advanced Server ");
else
out.append("Server ");
}
}
else if (osvi.wProductType == VER_NT_SERVER)
{
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
out.append("DataCenter Server ");
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
out.append("Advanced Server ");
else
out.append("Server ");
}
#endif
}
else
{
HKEY hKey;
char szProductType[80];
DWORD dwBufLen;
RegOpenKeyEx( HKEY_LOCAL_MACHINE,
__TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"),
0, KEY_QUERY_VALUE, &hKey );
RegQueryValueEx( hKey, __TEXT("ProductType"), NULL, NULL,
(LPBYTE) szProductType, &dwBufLen);
RegCloseKey( hKey );
if (_strcmpi( "WINNT", szProductType) == 0 )
out.append("Professional ");
if (_strcmpi( "LANMANNT", szProductType) == 0)
out.append("Server ");
if (_strcmpi( "SERVERNT", szProductType) == 0)
out.append("Advanced Server ");
}
// Display version, service pack (if any), and build number.
char tmp[255];
if (osvi.dwMajorVersion <= 4 )
{
sprintf(tmp, "version %ld.%ld %s (Build %ld)",
osvi.dwMajorVersion,
osvi.dwMinorVersion,
osvi.szCSDVersion,
osvi.dwBuildNumber & 0xFFFF);
}
else
{
sprintf(tmp, "%s (Build %ld)", osvi.szCSDVersion,
osvi.dwBuildNumber & 0xFFFF);
}
out.append(tmp);
break;
case VER_PLATFORM_WIN32_WINDOWS:
IsNonNTWindows = true;
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
{
out.append("Microsoft Windows 95 ");
if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
out.append("OSR2 " );
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
{
out.append("Microsoft Windows 98 ");
if ( osvi.szCSDVersion[1] == 'A' )
out.append( "SE " );
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
out.append("Microsoft Windows Me ");
break;
case VER_PLATFORM_WIN32s:
IsNonNTWindows = true;
out.append("Microsoft Win32s ");
break;
}
}
else
{
HKEY hKey;
char szProductType[80];
DWORD dwBufLen;
RegOpenKeyEx( HKEY_LOCAL_MACHINE,
__TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"),
0, KEY_QUERY_VALUE, &hKey );
RegQueryValueEx( hKey, __TEXT("ProductType"), NULL, NULL,
(LPBYTE) szProductType, &dwBufLen);
RegCloseKey( hKey );
if (_strcmpi( "WINNT", szProductType) == 0 )
out.append("Professional ");
if (_strcmpi( "LANMANNT", szProductType) == 0)
out.append("Server ");
if (_strcmpi( "SERVERNT", szProductType) == 0)
out.append("Advanced Server ");
}
// Display version, service pack (if any), and build number.
char tmp[255];
if (osvi.dwMajorVersion <= 4 )
{
sprintf(tmp, "version %ld.%ld %s (Build %ld)",
osvi.dwMajorVersion,
osvi.dwMinorVersion,
osvi.szCSDVersion,
osvi.dwBuildNumber & 0xFFFF);
}
else
{
sprintf(tmp, "%s (Build %ld)", osvi.szCSDVersion,
osvi.dwBuildNumber & 0xFFFF);
}
out.append(tmp);
break;
case VER_PLATFORM_WIN32_WINDOWS:
IsNonNTWindows = true;
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
{
out.append("Microsoft Windows 95 ");
if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
out.append("OSR2 " );
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
{
out.append("Microsoft Windows 98 ");
if ( osvi.szCSDVersion[1] == 'A' )
out.append( "SE " );
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
out.append("Microsoft Windows Me ");
break;
case VER_PLATFORM_WIN32s:
IsNonNTWindows = true;
out.append("Microsoft Win32s ");
break;
}
}
//! Notifies the device, that it has been resized
......@@ -1807,7 +1809,7 @@ void CIrrDeviceWin32::ReportLastWinApiError()
{
// (based on code from ovidiucucu from http://www.codeguru.com/forum/showthread.php?t=318721)
LPCTSTR pszCaption = __TEXT("Windows SDK Error Report");
DWORD dwError = GetLastError();
DWORD dwError = GetLastError();
if(NOERROR == dwError)
{
......@@ -1866,7 +1868,7 @@ HCURSOR CIrrDeviceWin32::TextureToCursor(HWND hwnd, irr::video::ITexture * tex,
{
data += bytesLeftGap;
for ( s32 x = 0; x < sourceRect.getWidth(); ++x )
{
{
video::SColor pixelCol;
pixelCol.setData((const void*)data, format);
data += bytesPerPixel;
......@@ -1907,27 +1909,27 @@ HCURSOR CIrrDeviceWin32::TextureToCursor(HWND hwnd, irr::video::ITexture * tex,
HCURSOR cursor = CreateIconIndirect(&iconinfo);
DeleteObject(andBitmap);
DeleteObject(xorBitmap);
DeleteObject(andBitmap);
DeleteObject(xorBitmap);
return cursor;
}
CIrrDeviceWin32::CCursorControl::CCursorControl(CIrrDeviceWin32* device, const core::dimension2d<u32>& wsize, HWND hwnd, bool fullscreen)
: Device(device), WindowSize(wsize), InvWindowSize(0.0f, 0.0f),
HWnd(hwnd), BorderX(0), BorderY(0),
UseReferenceRect(false), IsVisible(true)
, ActiveIcon(gui::ECI_NORMAL), ActiveIconStartTime(0)
: Device(device), WindowSize(wsize), InvWindowSize(0.0f, 0.0f),
HWnd(hwnd), BorderX(0), BorderY(0),
UseReferenceRect(false), IsVisible(true)
, ActiveIcon(gui::ECI_NORMAL), ActiveIconStartTime(0)
{
if (WindowSize.Width!=0)
InvWindowSize.Width = 1.0f / WindowSize.Width;
if (WindowSize.Width!=0)
InvWindowSize.Width = 1.0f / WindowSize.Width;
if (WindowSize.Height!=0)
InvWindowSize.Height = 1.0f / WindowSize.Height;
if (WindowSize.Height!=0)
InvWindowSize.Height = 1.0f / WindowSize.Height;
updateBorderSize(fullscreen, false);
initCursors();
updateBorderSize(fullscreen, false);
initCursors();
}
CIrrDeviceWin32::CCursorControl::~CCursorControl()
......@@ -1944,19 +1946,19 @@ CIrrDeviceWin32::CCursorControl::~CCursorControl()
void CIrrDeviceWin32::CCursorControl::initCursors()
{
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_ARROW)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_CROSS)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_HAND)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_HELP)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_IBEAM)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_NO)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_WAIT)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZEALL)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENESW)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENWSE)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENS)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZEWE)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_UPARROW)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_ARROW)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_CROSS)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_HAND)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_HELP)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_IBEAM)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_NO)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_WAIT)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZEALL)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENESW)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENWSE)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENS)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZEWE)) );
Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_UPARROW)) );
}
......@@ -1974,13 +1976,13 @@ void CIrrDeviceWin32::CCursorControl::update()
//! Sets the active cursor icon
void CIrrDeviceWin32::CCursorControl::setActiveIcon(gui::ECURSOR_ICON iconId)
{
if ( iconId >= (s32)Cursors.size() )
return;
if ( iconId >= (s32)Cursors.size() )
return;
ActiveIcon = iconId;
ActiveIconStartTime = Device->getTimer()->getRealTime();
if ( Cursors[ActiveIcon].Frames.size() )
SetCursor( Cursors[ActiveIcon].Frames[0].IconHW );
ActiveIcon = iconId;
ActiveIconStartTime = Device->getTimer()->getRealTime();
if ( Cursors[ActiveIcon].Frames.size() )
SetCursor( Cursors[ActiveIcon].Frames[0].IconHW );
}
......@@ -1989,7 +1991,7 @@ gui::ECURSOR_ICON CIrrDeviceWin32::CCursorControl::addIcon(const gui::SCursorSpr
{
if ( icon.SpriteId >= 0 )
{
CursorW32 cW32;
CursorW32 cW32;
cW32.FrameTime = icon.SpriteBank->getSprites()[icon.SpriteId].frameTime;
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
irr::u32 rectId = icon.SpriteBank->getSprites()[icon.SpriteId].Frames[i].rectNumber;
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) );
}
......@@ -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.
core::dimension2di CIrrDeviceWin32::CCursorControl::getSupportedIconSize() const
{
core::dimension2di result;
core::dimension2di result;
result.Width = GetSystemMetrics(SM_CXCURSOR);
result.Height = GetSystemMetrics(SM_CYCURSOR);
result.Width = GetSystemMetrics(SM_CXCURSOR);
result.Height = GetSystemMetrics(SM_CYCURSOR);
return result;
return result;
}
......
......@@ -68,8 +68,7 @@ int main(int argumentCount, char * arguments[])
TEST(testS3DVertex);
TEST(testaabbox3d);
TEST(color);
// TODO: Needs to be fixed first
// TEST(testTriangle3d);
TEST(testTriangle3d);
TEST(vectorPositionDimension2d);
// file system checks (with null driver)
TEST(filesystem);
......
......@@ -431,6 +431,10 @@
RelativePath=".\triangleSelector.cpp"
>
</File>
<File
RelativePath=".\triangle3d.cpp"
>
</File>
<File
RelativePath=".\vectorPositionDimension2d.cpp"
>
......
......@@ -102,7 +102,7 @@ static void stageModifications(int stage, vector3d<T>& point)
}
template<class T>
static bool isPointInside(triangle3d<T> triangleOrig)
static bool isPointInside(triangle3d<T> triangleOrig, bool testIsInside, bool testIsInsideFast)
{
bool allExpected=true;
......@@ -124,18 +124,24 @@ static bool isPointInside(triangle3d<T> triangleOrig)
vector3d<T> point = pointsInside[i];
stageModifications(stage, point);
allExpected &= triangle.isPointInside( point );
if ( !allExpected )
if ( testIsInside )
{
logTestString("triangle3d::isPointInside pointsInside test failed in stage %d point %d\n", stage, i);
return false;
allExpected &= triangle.isPointInside( point );
if ( !allExpected )
{
logTestString("triangle3d::isPointInside pointsInside test failed in stage %d point %d\n", stage, i);
return false;
}
}
allExpected &= triangle.isPointInsideFast( point );
if ( !allExpected )
if ( testIsInsideFast )
{
logTestString("triangle3d::isPointInsideFast pointsInside test failed in stage %d point %d\n", stage, i);
return false;
allExpected &= triangle.isPointInsideFast( point );
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)
vector3d<T> point = pointsOutside[i];
stageModifications(stage, point);
allExpected &= !triangle.isPointInside( point );
if ( !allExpected )
if ( testIsInside )
{
logTestString("triangle3d::isPointInside pointsOutside test failed in stage %d point %d\n", stage, i);
return false;
allExpected &= !triangle.isPointInside( point );
if ( !allExpected )
{
logTestString("triangle3d::isPointInside pointsOutside test failed in stage %d point %d\n", stage, i);
return false;
}
}
allExpected &= !triangle.isPointInsideFast( point );
if ( !allExpected )
if ( testIsInsideFast )
{
logTestString("triangle3d::isPointInsideFast pointsOutside test failed in stage %d point %d\n", stage, i);
return false;
allExpected &= !triangle.isPointInsideFast( point );
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)
vector3d<T> point = pointsBorder[i];
stageModifications(stage, point);
allExpected &= triangle.isPointInside( point );
if ( !allExpected )
if ( testIsInside )
{
logTestString("triangle3d::isPointInside pointsBorder test failed in stage %d point %d\n", stage, i);
return false;
allExpected &= triangle.isPointInside( point );
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 ( triangle.isPointInsideFast( point ) )
logTestString("+ triangle3d::isPointInsideFast pointsBorder stage %d point %d is INSIDE\n", stage, i);
else
logTestString("- triangle3d::isPointInsideFast pointsBorder stage %d point %d is NOT inside\n", stage, i);
*/
if ( testIsInsideFast )
{
allExpected &= triangle.isPointInsideFast( point );
if ( !allExpected )
{
logTestString("triangle3d::isPointInsideFast pointsBorder test failed in stage %d point %d\n", stage, i);
return false;
}
}
}
}
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>
/** Validation is done with asserts() against expected results. */
......@@ -224,6 +278,9 @@ bool testTriangle3d(void)
{
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");
{
triangle3df triangle(
......@@ -246,28 +303,38 @@ bool testTriangle3d(void)
ray.end = vector3d<f64>(11250.000000, -1000.000000, 250.000000);
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));
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");
allExpected &= testEigen;
*/
logTestString("Test isPointInside with f32\n");
{
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");
{
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");
{
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)
......
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