123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913 |
- #include "testUtils.h"
- #include <map>
- using namespace irr;
- namespace
- {
- // don't use this code! It lacks many checks and is for testing
- // purposes only!!!
- // based on code and media from SuperTuxKart
- class ScalableFont : public gui::IGUIFontBitmap
- {
- float m_scale;
- struct TextureInfo
- {
- irr::core::stringc m_file_name;
- bool m_has_alpha;
- float m_scale;
- TextureInfo()
- {
- m_has_alpha = false;
- m_scale = 1.0f;
- }
- };
- std::map<int /* texture file ID */, TextureInfo> m_texture_files;
- void lazyLoadTexture(int texID)
- {
- const bool mipmap = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
- Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
- // load texture
- SpriteBank->setTexture(texID, Driver->getTexture( m_texture_files[texID].m_file_name ));
- // set previous mip-map+filter state
- Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap);
- // couldn't load texture, abort.
- if (!SpriteBank->getTexture(texID))
- {
- return;
- }
- else
- {
- // colorkey texture rather than alpha channel?
- if (! m_texture_files[texID].m_has_alpha)
- {
- Driver->makeColorKeyTexture(SpriteBank->getTexture(texID), core::position2di(0,0));
- }
- }
- }
- void doReadXmlFile(io::IXMLReader* xml)
- {
- while (xml->read())
- {
- if (io::EXN_ELEMENT == xml->getNodeType())
- {
- if (core::stringw(L"include") == xml->getNodeName())
- {
- core::stringc filename = xml->getAttributeValue(L"file");
- io::IXMLReader* included = Environment->getFileSystem()->createXMLReader(filename.c_str());
- if (included != NULL)
- {
- doReadXmlFile(included);
- included->drop();
- }
- }
- else if (core::stringw(L"Texture") == xml->getNodeName())
- {
- // add a texture
- core::stringc filename = xml->getAttributeValue(L"filename");
- core::stringc fn = filename;
- u32 i = (u32)xml->getAttributeValueAsInt(L"index");
- float scale=1.0f;
- if (xml->getAttributeValue(L"scale"))
- scale = xml->getAttributeValueAsFloat(L"scale");
- //std::cout << "scale = " << scale << std::endl;
- core::stringw alpha = xml->getAttributeValue(L"hasAlpha");
- //std::cout << "---- Adding font texture " << fn.c_str() << "; alpha=" << alpha.c_str() << std::endl;
- // make sure the sprite bank has enough textures in it
- while (i+1 > SpriteBank->getTextureCount())
- {
- SpriteBank->addTexture(NULL);
- }
- TextureInfo info;
- info.m_file_name = fn;
- info.m_has_alpha = (alpha == core::stringw("true"));
- info.m_scale = scale;
- m_texture_files[i] = info;
- }
- else if (core::stringw(L"c") == xml->getNodeName())
- {
- // adding a character to this font
- SFontArea a;
- gui::SGUISpriteFrame f;
- gui::SGUISprite s;
- core::rect<s32> rectangle;
- a.underhang = xml->getAttributeValueAsInt(L"u");
- a.overhang = xml->getAttributeValueAsInt(L"o");
- a.spriteno = SpriteBank->getSprites().size();
- s32 texno = xml->getAttributeValueAsInt(L"i");
- // parse rectangle
- core::stringc rectstr = xml->getAttributeValue(L"r");
- wchar_t ch = xml->getAttributeValue(L"c")[0];
- const c8 *c = rectstr.c_str();
- s32 val;
- val = 0;
- while (*c >= '0' && *c <= '9')
- {
- val *= 10;
- val += *c - '0';
- c++;
- }
- rectangle.UpperLeftCorner.X = val;
- while (*c == L' ' || *c == L',') c++;
- val = 0;
- while (*c >= '0' && *c <= '9')
- {
- val *= 10;
- val += *c - '0';
- c++;
- }
- rectangle.UpperLeftCorner.Y = val;
- while (*c == L' ' || *c == L',') c++;
- val = 0;
- while (*c >= '0' && *c <= '9')
- {
- val *= 10;
- val += *c - '0';
- c++;
- }
- rectangle.LowerRightCorner.X = val;
- while (*c == L' ' || *c == L',') c++;
- val = 0;
- while (*c >= '0' && *c <= '9')
- {
- val *= 10;
- val += *c - '0';
- c++;
- }
- rectangle.LowerRightCorner.Y = val;
- CharacterMap[ch] = Areas.size();
- // make frame
- f.rectNumber = SpriteBank->getPositions().size();
- f.textureNumber = texno;
- // add frame to sprite
- s.Frames.push_back(f);
- s.frameTime = 0;
- // add rectangle to sprite bank
- SpriteBank->getPositions().push_back(rectangle);
- a.width = rectangle.getWidth();
- // add sprite to sprite bank
- SpriteBank->getSprites().push_back(s);
- // add character to font
- Areas.push_back(a);
- }
- }
- }
- }
- public:
- bool m_black_border;
- ScalableFont* m_fallback_font;
- float m_fallback_font_scale;
- int m_fallback_kerning_width;
- //! constructor
- ScalableFont(gui::IGUIEnvironment *env, const io::path& filename)
- : Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0),
- MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
- {
- #ifdef _DEBUG
- setDebugName("ScalableFont");
- #endif
- m_fallback_font = NULL;
- m_fallback_kerning_width = 0;
- m_fallback_font_scale = 1.0f;
- m_scale = 0.37f;
- m_black_border = false;
- if (Environment)
- {
- // don't grab environment, to avoid circular references
- Driver = Environment->getVideoDriver();
- SpriteBank = Environment->addEmptySpriteBank(filename);
- if (SpriteBank)
- SpriteBank->grab();
- }
- if (Driver)
- Driver->grab();
- setInvisibleCharacters ( L" " );
- io::IXMLReader* reader = env->getFileSystem()->createXMLReader(filename.c_str());
- if (reader)
- {
- load( reader );
- reader->drop();
- }
- assert_log(Areas.size() > 0);
- }
- //! destructor
- virtual ~ScalableFont()
- {
- if (Driver)
- Driver->drop();
- if (SpriteBank)
- SpriteBank->drop();
- }
- //! loads a font from an XML file
- bool load(io::IXMLReader* xml)
- {
- if (!SpriteBank)
- return false;
- doReadXmlFile(xml);
- // set bad character
- WrongCharacter = getAreaIDFromCharacter(L' ', NULL);
- setMaxHeight();
- for(wchar_t c='0'; c<='9'; c++)
- {
- SFontArea a = getAreaFromCharacter(c, NULL);
- if (a.overhang > m_max_digit_area.overhang ) m_max_digit_area.overhang = a.overhang;
- if (a.underhang > m_max_digit_area.underhang) m_max_digit_area.underhang = a.underhang;
- if (a.width > m_max_digit_area.width) m_max_digit_area.width = a.width;
- }
- m_max_digit_area.overhang = 0;
- m_max_digit_area.underhang=0;
- return true;
- }
- //! draws an text and clips it to the specified rectangle if wanted
- virtual void draw(const core::stringw& text, const core::rect<s32>& position,
- video::SColor color, bool hcenter=false,
- bool vcenter=false, const core::rect<s32>* clip=0)
- {
- if (!Driver) return;
- core::position2d<s32> offset = position.UpperLeftCorner;
- core::dimension2d<s32> text_dimension;
- // When we use the "tab" hack, disable right-alignment, it messes up everything
- // bool has_tab = (text.findFirst(L'\t') != -1);
- // ---- collect character locations
- const unsigned int text_size = text.size();
- core::array<s32> indices(text_size);
- core::array<core::position2di> offsets(text_size);
- core::array<bool> fallback;
- fallback.set_used(text_size);
- for (u32 i = 0; i<text_size; i++)
- {
- wchar_t c = text[i];
- //hack: one tab character is supported, it moves the cursor to the middle of the area
- if (c == L'\t')
- {
- offset.X = position.UpperLeftCorner.X + position.getWidth()/2;
- continue;
- }
- if (c == L'\r' || // Windows breaks
- c == L'\n') // Unix breaks
- {
- if (c==L'\r' && text[i+1]==L'\n')
- c = text[++i];
- offset.Y += (int)(MaxHeight*m_scale);
- offset.X = position.UpperLeftCorner.X;
- if (hcenter)
- offset.X += (position.getWidth() - text_dimension.Width) >> 1;
- continue;
- } // if lineBreak
- bool use_fallback_font = false;
- const SFontArea &area = getAreaFromCharacter(c, &use_fallback_font);
- fallback[i] = use_fallback_font;
- offset.X += area.underhang;
- offsets.push_back(offset);
- // Invisible character. add something to the array anyway so that
- // indices from the various arrays remain in sync
- indices.push_back((Invisible.findFirst(c) < 0) ? (int)area.spriteno
- : -1);
- offset.X += getCharWidth(area, fallback[i]);
- } // for i<text_size
- // ---- do the actual rendering
- const int indiceAmount = indices.size();
- core::array< gui::SGUISprite >& sprites = SpriteBank->getSprites();
- core::array< core::rect<s32> >& positions = SpriteBank->getPositions();
- core::array< gui::SGUISprite >* fallback_sprites;
- core::array< core::rect<s32> >* fallback_positions;
- if (m_fallback_font!=NULL)
- {
- fallback_sprites = &m_fallback_font->SpriteBank->getSprites();
- fallback_positions = &m_fallback_font->SpriteBank->getPositions();
- }
- else
- {
- fallback_sprites = NULL;
- fallback_positions = NULL;
- }
- video::IVideoDriver* driver = Environment->getVideoDriver();
- const int spriteAmount = sprites.size();
- for (int n=0; n<indiceAmount; n++)
- {
- const int spriteID = indices[n];
- if (!fallback[n] && (spriteID < 0 || spriteID >= spriteAmount))
- continue;
- if (indices[n] == -1)
- continue;
- //assert_log(sprites[spriteID].Frames.size() > 0);
- const int texID = (fallback[n] ?
- (*fallback_sprites)[spriteID].Frames[0].textureNumber :
- sprites[spriteID].Frames[0].textureNumber);
- core::rect<s32> source = (fallback[n] ?
- (*fallback_positions)[(*fallback_sprites)[spriteID].Frames[0].rectNumber] :
- positions[sprites[spriteID].Frames[0].rectNumber]);
- const TextureInfo& info = (fallback[n] ?
- (*(m_fallback_font->m_texture_files.find(texID))).second :
- (*(m_texture_files.find(texID))).second);
- float char_scale = info.m_scale;
- core::dimension2d<s32> size = source.getSize();
- float scale = (fallback[n] ? m_scale*m_fallback_font_scale : m_scale);
- size.Width = (int)(size.Width * scale * char_scale);
- size.Height = (int)(size.Height * scale * char_scale);
- // align vertically if character is smaller
- int y_shift = (size.Height < MaxHeight*m_scale ? (int)((MaxHeight*m_scale - size.Height)/2.0f) : 0);
- core::rect<s32> dest(offsets[n] + core::position2di(0, y_shift), size);
- video::SColor colors[] = {color, color, color, color};
- video::ITexture* texture = (fallback[n] ?
- m_fallback_font->SpriteBank->getTexture(texID) :
- SpriteBank->getTexture(texID) );
- if (texture == NULL)
- {
- // perform lazy loading
- if (fallback[n])
- {
- m_fallback_font->lazyLoadTexture(texID);
- texture = m_fallback_font->SpriteBank->getTexture(texID);
- }
- else
- {
- lazyLoadTexture(texID);
- texture = SpriteBank->getTexture(texID);
- }
- if (texture == NULL)
- {
- continue; // no such character
- }
- }
- if (m_black_border)
- {
- // draw black border
- video::SColor black(color.getAlpha(),0,0,0);
- video::SColor black_colors[] = {black, black, black, black};
- for (int x_delta=-2; x_delta<=2; x_delta++)
- {
- for (int y_delta=-2; y_delta<=2; y_delta++)
- {
- if (x_delta == 0 || y_delta == 0) continue;
- driver->draw2DImage(texture,
- dest + core::position2d<s32>(x_delta, y_delta),
- source,
- clip,
- black_colors, true);
- }
- }
- }
- if (fallback[n])
- {
- // draw text over
- static video::SColor orange(color.getAlpha(), 255, 100, 0);
- static video::SColor yellow(color.getAlpha(), 255, 220, 15);
- video::SColor title_colors[] = {yellow, orange, orange, yellow};
- driver->draw2DImage(texture,
- dest,
- source,
- clip,
- title_colors, true);
- }
- else
- {
- driver->draw2DImage(texture,
- dest,
- source,
- clip,
- colors, true);
- }
- }
- }
- //! returns the dimension of a text
- virtual core::dimension2d<u32> getDimension(const wchar_t* text) const
- {
- assert_log(Areas.size() > 0);
- core::dimension2d<u32> dim(0, 0);
- core::dimension2d<u32> thisLine(0, (int)(MaxHeight*m_scale));
- for (const wchar_t* p = text; *p; ++p)
- {
- if (*p == L'\r' || // Windows breaks
- *p == L'\n') // Unix breaks
- {
- if (*p==L'\r' && p[1] == L'\n') // Windows breaks
- ++p;
- dim.Height += thisLine.Height;
- if (dim.Width < thisLine.Width)
- dim.Width = thisLine.Width;
- thisLine.Width = 0;
- continue;
- }
- bool fallback = false;
- const SFontArea &area = getAreaFromCharacter(*p, &fallback);
- thisLine.Width += area.underhang;
- thisLine.Width += getCharWidth(area, fallback);
- }
- dim.Height += thisLine.Height;
- if (dim.Width < thisLine.Width) dim.Width = thisLine.Width;
- // std::cout << "ScalableFont::getDimension returns : " << dim.Width << ", " << dim.Height << " --> ";
- dim.Width = (int)(dim.Width + 0.9f); // round up
- dim.Height = (int)(dim.Height + 0.9f);
- //std::cout << dim.Width << ", " << dim.Height << std::endl;
- return dim;
- }
- //! Calculates the index of the character in the text which is on a specific position.
- virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
- {
- s32 x = 0;
- s32 idx = 0;
- while (text[idx])
- {
- const SFontArea& a = Areas[getAreaIDFromCharacter(text[idx], NULL)];
- x += a.width + a.overhang + a.underhang + GlobalKerningWidth;
- if (x >= pixel_x)
- return idx;
- ++idx;
- }
- return -1;
- }
- //! Returns the type of this font
- virtual gui::EGUI_FONT_TYPE getType() const { return gui::EGFT_BITMAP; }
- //! set an Pixel Offset on Drawing ( scale position on width )
- virtual void setKerningWidth (s32 kerning)
- {
- GlobalKerningWidth = kerning;
- }
- virtual void setKerningHeight (s32 kerning)
- {
- GlobalKerningHeight = kerning;
- }
- //! set an Pixel Offset on Drawing ( scale position on width )
- virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const
- {
- s32 ret = GlobalKerningWidth;
- if (thisLetter)
- {
- ret += Areas[getAreaIDFromCharacter(*thisLetter, NULL)].overhang;
- if (previousLetter)
- {
- ret += Areas[getAreaIDFromCharacter(*previousLetter, NULL)].underhang;
- }
- }
- return ret;
- }
- virtual s32 getKerningHeight() const
- {
- return GlobalKerningHeight;
- }
- //! gets the sprite bank
- virtual gui::IGUISpriteBank* getSpriteBank() const
- {
- return SpriteBank;
- }
- //! returns the sprite number from a given character
- virtual u32 getSpriteNoFromChar(const wchar_t *c) const
- {
- return Areas[getAreaIDFromCharacter(*c, NULL)].spriteno;
- }
- virtual void setInvisibleCharacters( const wchar_t *s )
- {
- Invisible = s;
- }
- private:
- struct SFontArea
- {
- SFontArea() : underhang(0), overhang(0), width(0), spriteno(0) {}
- s32 underhang;
- s32 overhang;
- s32 width;
- u32 spriteno;
- };
- int getCharWidth(const SFontArea& area, const bool fallback) const
- {
- core::array< gui::SGUISprite >& sprites = SpriteBank->getSprites();
- core::array< gui::SGUISprite >* fallback_sprites = (m_fallback_font != NULL ?
- &m_fallback_font->SpriteBank->getSprites() :
- NULL);
- const int texID = (fallback ?
- (*fallback_sprites)[area.spriteno].Frames[0].textureNumber :
- sprites[area.spriteno].Frames[0].textureNumber);
- const TextureInfo& info = (fallback ?
- (*(m_fallback_font->m_texture_files.find(texID))).second :
- (*(m_texture_files.find(texID))).second);
- const float char_scale = info.m_scale;
- //std::cout << "area.spriteno=" << area.spriteno << ", char_scale=" << char_scale << std::endl;
- if (fallback)
- return (int)(((area.width + area.overhang)*m_fallback_font_scale + m_fallback_kerning_width) * m_scale * char_scale);
- else
- return (int)((area.width + area.overhang + GlobalKerningWidth) * m_scale * char_scale);
- }
- s32 getAreaIDFromCharacter(const wchar_t c, bool* fallback_font) const
- {
- std::map<wchar_t, s32>::const_iterator n = CharacterMap.find(c);
- if (n != CharacterMap.end())
- {
- if (fallback_font != NULL)
- *fallback_font = false;
- return (*n).second;
- }
- else if (m_fallback_font != NULL && fallback_font != NULL)
- {
- *fallback_font = true;
- return m_fallback_font->getAreaIDFromCharacter(c, NULL);
- }
- else
- {
- // std::cout << "The font does not have this character : <" << (int)c << ">" << std::endl;
- if (fallback_font != NULL)
- *fallback_font = false;
- return WrongCharacter;
- }
- }
- const SFontArea &getAreaFromCharacter(const wchar_t c, bool* fallback_font) const
- {
- const int area_id = getAreaIDFromCharacter(c, fallback_font);
- const bool use_fallback_font = (fallback_font && *fallback_font);
- // Note: fallback_font can be NULL
- return ( use_fallback_font ? m_fallback_font->Areas[area_id] : Areas[area_id]);
- } // getAreaFromCharacter
- void setMaxHeight()
- {
- // FIXME: should consider per-texture scaling
- MaxHeight = 0;
- s32 t;
- core::array< core::rect<s32> >& p = SpriteBank->getPositions();
- for (u32 i=0; i<p.size(); ++i)
- {
- t = p[i].getHeight();
- if (t>MaxHeight)
- MaxHeight = t;
- }
- }
- core::array<SFontArea> Areas;
- /** The maximum values of all digits, used in monospace_digits. */
- mutable SFontArea m_max_digit_area;
- std::map<wchar_t, s32> CharacterMap;
- video::IVideoDriver* Driver;
- gui::IGUISpriteBank* SpriteBank;
- gui::IGUIEnvironment* Environment;
- u32 WrongCharacter;
- s32 MaxHeight;
- s32 GlobalKerningWidth, GlobalKerningHeight;
- core::stringw Invisible;
- };
- }
- // The actual bug that was behind this issue was the combination of
- // 2d rendering and mipmaps. The issue was reproduced using the special
- // draw2dimage version, hence the name.
- static bool draw2DImage4c(video::E_DRIVER_TYPE type)
- {
- IrrlichtDevice *device = createDevice(type, core::dimension2d<u32>(240, 120));
- if (!device)
- return true; // could not create selected driver.
- video::IVideoDriver* driver = device->getVideoDriver();
- if (!driver->queryFeature(video::EVDF_BILINEAR_FILTER))
- {
- device->closeDevice();
- device->run();
- device->drop();
- return true;
- }
- stabilizeScreenBackground(driver);
- logTestString("Testing driver %ls\n", driver->getName());
- driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS,true);
- driver->setTextureCreationFlag(video::ETCF_OPTIMIZED_FOR_QUALITY,true);
- video::ITexture* images = driver->getTexture("../media/2ddemo.png");
- driver->makeColorKeyTexture(images, core::position2d<s32>(0,0));
- core::rect<s32> imp1(349,15,385,78);
- core::rect<s32> imp2(387,15,423,78);
- // font cannot handle loading from sub-dirs
- io::path cwd = device->getFileSystem()->getWorkingDirectory();
- device->getFileSystem()->changeWorkingDirectoryTo("media");
- ScalableFont* font = new ScalableFont(device->getGUIEnvironment(), "title_font.xml");
- font->m_fallback_font_scale = 4.0f;
- font->m_fallback_kerning_width = 15;
- font->setKerningWidth(-18);
- font->m_black_border = true;
- /*
- Prepare a nicely filtering 2d render mode for special cases.
- */
- driver->getMaterial2D().UseMipMaps = true;
- driver->getMaterial2D().TextureLayer[0].BilinearFilter = true;
- {
- driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,120,102,136));
- driver->enableMaterial2D();
- // draw fire & dragons background world
- driver->draw2DImage(images, core::position2di(),
- core::rect<s32>(0,0,342,224), 0,
- video::SColor(255,255,255,255), true);
- // draw flying imp
- driver->draw2DImage(images, core::position2d<s32>(114,75),
- imp1, 0, video::SColor(255,255,255,255), true);
- // draw second flying imp
- driver->draw2DImage(images, core::position2d<s32>(220,55),
- imp2, 0, video::SColor(255,255,255,255), true);
- driver->draw2DImage(images, core::rect<s32>(10,10,108,48),
- core::rect<s32>(354,87,442,118));
- video::SColor colors[] = {0xff00ffff, 0xff00ffff, 0xffffff00, 0xffffff00};
- driver->draw2DImage(images, core::recti(10,50,108,88),
- core::recti(354,87,442,118), 0, colors, true);
- font->draw( L"WXYZsSdDrRjJbB", core::rect<s32>(30,20,300,300),
- video::SColor(255,255,255,255) );
- driver->enableMaterial2D(false);
- driver->draw2DImage(images, core::recti(10,90,108,128),
- core::recti(354,87,442,118), 0, colors, true);
- font->draw( L"WXYZsSdDrRjJbB", core::rect<s32>(30,60,300,400),
- video::SColor(255,255,255,255) );
- driver->endScene();
- }
- font->drop();
- device->getFileSystem()->changeWorkingDirectoryTo(cwd);
- // don't go under 99% as the difference is not very large
- bool result = takeScreenshotAndCompareAgainstReference(driver, "-draw2DImage4cFilter.png");
- device->closeDevice();
- device->run();
- device->drop();
- return result;
- }
- // This test renders a 3d scene and a gui on top of it. The GUI is
- // filtered via 2dmaterial (blurred).
- // TODO: Works only for OpenGL right now
- static bool addBlend2d(video::E_DRIVER_TYPE type)
- {
- SIrrlichtCreationParameters params;
- params.AntiAlias = 0;
- params.Bits = 32;
- params.WindowSize = core::dimension2d<u32>(160, 120);
- params.DriverType = type;
- IrrlichtDevice *device = createDeviceEx(params);
- if (!device)
- return true; // in case the driver type does not exist
- video::IVideoDriver* driver = device->getVideoDriver();
- scene::ISceneManager* smgr = device->getSceneManager();
- if (!driver->queryFeature(video::EVDF_BILINEAR_FILTER))
- {
- device->closeDevice();
- device->run();
- device->drop();
- return true;
- }
- logTestString("Testing driver %ls\n", driver->getName());
- scene::IAnimatedMesh* mesh = smgr->getMesh("../media/sydney.md2");
- if (!mesh)
- {
- device->closeDevice();
- device->run();
- device->drop();
- return false;
- }
- stabilizeScreenBackground(driver);
- scene::IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh );
- if (node)
- {
- node->setMaterialFlag(video::EMF_LIGHTING, false);
- node->setMD2Animation(scene::EMAT_STAND);
- node->setMaterialTexture( 0, driver->getTexture("../media/sydney.bmp") );
- }
- smgr->addCameraSceneNode(0, core::vector3df(0,30,-40), core::vector3df(0,5,0));
- gui::IGUIEnvironment* env = device->getGUIEnvironment();
- {
- // create the toolbox window
- gui::IGUIWindow* wnd = env->addWindow(core::rect<s32>(0,0,800,480),
- false, L"Toolset", 0, 100);
- // create tab control and tabs
- gui::IGUITabControl* tab = env->addTabControl(
- core::rect<s32>(2,20,800-602,480-7), wnd, true, true);
- gui::IGUITab* t1 = tab->addTab(L"Config");
- // add some edit boxes and a button to tab one
- env->addImage(driver->getTexture("../media/tools.png"), core::vector2d<s32>(10,20), true, t1);
- env->addStaticText(L"X:", core::rect<s32>(22,48,40,66), false, false, t1);
- env->addEditBox(L"1.0", core::rect<s32>(40,46,130,66), true, t1, 201);
- // quick scale buttons
- env->addButton(core::rect<s32>(65,20,95,40), t1, 102, L"* 10");
- env->addButton(core::rect<s32>(100,20,130,40), t1, 103, L"* 0.1");
- }
- video::SMaterial& material2D = driver->getMaterial2D();
- for (unsigned int n=0; n<video::MATERIAL_MAX_TEXTURES; n++)
- {
- material2D.TextureLayer[n].BilinearFilter = true;
- material2D.TextureLayer[n].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
- material2D.TextureLayer[n].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
- }
- material2D.AntiAliasing=video::EAAM_FULL_BASIC;
- driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,100,101,140));
- smgr->drawAll();
- driver->enableMaterial2D();
- env->drawAll();
- driver->enableMaterial2D(false);
- driver->endScene();
- bool result = takeScreenshotAndCompareAgainstReference(driver, "-addBlend2D.png", 98.2f);
- device->closeDevice();
- device->run();
- device->drop();
- return result;
- }
- // This test renders 4 times the same image. Two via IGUIImage, two via draw2DImage
- // 3 of the 4 images are filtered via 2dmaterial and bilinear filter, only the one
- // at the bottom left is not.
- static bool moreFilterTests(video::E_DRIVER_TYPE type)
- {
- IrrlichtDevice* device = irr::createDevice(type, core::dimension2du(160,120));
- if (!device)
- return true;
- video::IVideoDriver* driver = device->getVideoDriver();
- gui::IGUIEnvironment* gui = device->getGUIEnvironment();
- if (!driver->queryFeature(video::EVDF_BILINEAR_FILTER))
- {
- device->closeDevice();
- device->run();
- device->drop();
- return true;
- }
- stabilizeScreenBackground(driver);
- logTestString("Testing driver %ls\n", driver->getName());
- driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
- video::ITexture* tex = driver->getTexture("../media/irrlichtlogo.jpg");
- gui::IGUIImage* image = gui->addImage(core::recti(0,0,64,64));
- image->setScaleImage(true);
- image->setImage(tex);
- image->setUseAlphaChannel(true);
- driver->getMaterial2D().TextureLayer[0].BilinearFilter=true;
- driver->getMaterial2D().TextureLayer[0].TrilinearFilter=true;
- {
- driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, irr::video::SColor(255,255,255,255));
- // all three logos should be with filtering
- driver->enableMaterial2D();
- driver->getMaterial2D().setTexture(0, 0);
- driver->draw2DImage(tex, irr::core::rect<irr::s32>(64, 64, 128, 128), irr::core::rect<irr::s32>(0, 0, 88, 31));
- driver->getMaterial2D().setTexture(0, tex);
- driver->draw2DImage(tex, irr::core::rect<irr::s32>(64, 0, 128, 64), irr::core::rect<irr::s32>(0, 0, 88, 31));
- gui->drawAll();
- // the next gui image should be without filter
- driver->enableMaterial2D(false);
- image->setRelativePosition(core::recti(0,64,64,128));
- gui->drawAll();
- driver->endScene();
- }
- bool result = takeScreenshotAndCompareAgainstReference(driver, "-2dmatFilter.png");
- device->closeDevice();
- device->run();
- device->drop();
- return result;
- }
- bool twodmaterial()
- {
- bool result = true;
- TestWithAllDrivers(addBlend2d);
- TestWithAllDrivers(moreFilterTests);
- #ifdef _IRR_COMPILE_WITH_XML_
- TestWithAllDrivers(draw2DImage4c);
- #endif
- return result;
- }
|