Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > Coding Releases
You last visited: Today at 03:05

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



D3DShark - A DirectX Component Library

Discussion on D3DShark - A DirectX Component Library within the Coding Releases forum part of the Coders Den category.

Reply
 
Old   #1
 
Master674b's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
Exclamation D3DShark - A DirectX Component Library

Hallo zusammen,

vor einiger Zeit kam mir in den Sinn mein DirectX Interface welches ich damals in WoWPlus verwendet hatte komplett neu aufzusetzen. Diesmal richtig mit HLSL, C++11 etc.

Die Entwicklung ist mittlerweile soweit, dass ich erste Bilder davon präsentieren kann. Die Komponenten sind aufgrund des aktuellen Aufbaus sehr leicht zu implementieren und stellen daher eigentlich kein Problem dar. Momentane Features:

- Farbmanipulation (Container können die Farben von Kindern beeinflussen)
- Unendliche Verschachtelbarkeit von Fenstern / Containern etc.
- Fade Effekte (Jede Komponente kann über einen linearen Fade seinen Farbmodifizierer verändern).
- Rendering und Logik komplett getrennt (leichte Erweiterbarkeit auf DirectX 10, 11, OpenGL).
- Sehr hohe Effizienz: Caching von Fonts / Clipping von nicht sichtbarem.
- In bislang jedem getesteten Spiel funktionsfähig (Skyrim, WoW, Diablo 3, Call of Duty, uvm.)

Beispiel Event Handling:
Code:
auto pWindow = UI::Components::Frame::Create(100.0f, 100.0f);
auto pButton = UI::Components::Button::Create(L"Some Button");
pButton->GetCaption()->SetColor(Utils::Color(0xFF, 0x90, 0x50, 0x70));
pWindow->PushChild(pButton);

pButton->SetPosition(Utils::Vector2(20.0f, 20.0f));
pButton->OnClickEvent += [] (std::shared_ptr<UI::Components::Button> pSender) {
        auto pWindow = std::dynamic_pointer_cast<UI::Components::Frame>(pSender->GetUIParent());
        float4 glow = {1.1f, 1.25f, 1.25f, 1.45f};
        pWindow->FadeTo(200, glow);

        // In 200 ms -> remove glow
        sD3DMgr->FrameTimer.AddTimer(200, [=] (const Utils::STimerDispatchEvt&) {
                float4 normal = {1.0f, 1.0f, 1.0f, 1.0f};
                pWindow->FadeTo(200, normal);
                return TIMER_STOP_EXECUTION;
        });
};
Screenshot:



Aufgrund der vielen Hover / Fadeeffekte und dem dynamischen Schatten hinter den Fenstern (immer zur mitte des Bildschirms hin) werde ich eventuell später noch ein Video davon machen.

Das Projekt ist momentan OpenSource und kann hier gefunden werden:


Jeder kann mitmachen, momentan arbeite ich mit einem Kollegen daran.

Viele Grüße
Master674b is offline  
Thanks
7 Users
Old 03/17/2013, 19:25   #2


 
Ende!'s Avatar
 
elite*gold: 1
Join Date: Feb 2009
Posts: 6,379
Received Thanks: 7,998
Sieht doch schon richtig nett aus! Diesen stilistischen Ansatz hatte ich bei meinem UI-FW Anfang 2011 auch mal ausprobiert, aber irgendwie musste ich dann feststellen, dass mir eckige Fenster doch eigentlich viel besser gefallen. Inzwischen bin ich nun bei etwas raus gekommen, was ein wenig Ähnlichkeit mit Steam hat - zumindest im Default-Modus - hab bei mir eh praktisch alles justierbar gehalten.

Das UI von WoW+ hat mich immer total an das alte Mist-UI meines alten WoW-Hacks erinnert - hat Cen da zufällig etwas Einfluss auf dich gehabt? :P Vermutlich ist dieser Stil aber einfach das Erste, was einem in den Sinn kommt, wenn man mit minimalem Aufwand ein UI erstellen will.


Mit ID3DXFont wirst du noch Krämpfe kriegen, die hat so einige Macken. Das Font-Measurement funktioniert nur bei 'n paar Holz-Fonts korrekt und beim Rendern in ein Off-Screen-Surface "schlägt" die Font am Rand der Buchstaben "Löcher" in den Alpha-Kanal - ersteres ist ein dokumentiertes "Feature", letzteres wohl ein Fehler der Font-Klasse. Hab das Ganze inzwischen so gelöst, dass ich eine eigene Font-Klasse habe, die auf meinen abstrakten Sprites basiert und somit auch unabhängig vom verwendeten Graphics-Framework funktioniert. Solltest du auf die selben Probleme stoßen, meld' dich einfach bei mir; ich bin durchaus bereit, meine Klasse für das Projekt zur Verfügung zu stellen.
Ende! is offline  
Thanks
2 Users
Old 03/17/2013, 19:55   #3
 
Master674b's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
Hey, das Video kannte ich schon
Mir ist aufgefallen dir fehlte irgendwo ein Blend Renderstate (Mob Aggro).

Naja jedenfalls dachte ich schon daran eine eigene Font einzubauen war bisher aber immer zu faul. Der Fehler mit den "Löchern" in Offscreen Rendertargets ist mir auch schon aufgefallen und momentan präsent, eigentlich gehören die Texte alle ein wenig dicker, wenn ich das Caching weglasse stimmts.

Ich denke es liegt daran, dass da irgendwo intern Halfpixel entstehen. Die behebe ich in meinen Vertex Shadern einfach so:

Code:
output.position.x -= 1.0f / (viewportSize.x * 2.0f);
output.position.y -= 1.0f / (viewportSize.y * 2.0f);
Die Effizienz der Fontklasse ist mir im übrigen vollkommen egal weil eh alles in eine Cache gerendert wird. Ich nehme an du zeichnest jeden Buchstaben in eine Textur (GDI+) und speicherst dazu die Breite der einzelnen Buchstaben?

Wäre jedenfalls interessant zu sehen wie du das implementiert hast. Ich hab um ehrlich zu sein auch keine Ahnung wie ein Sprite aufgebaut ist :0

Whitespaces werden auch nie richtig kalkuliert das hab ich über nen dreckigen Hack gelöst gehabt:
Code:
// Replace whitespaces with a underscore to fix calculation issues.
for (auto itr = swText.begin(), end = swText.end(); itr != end; ++itr) {
        if (*itr == L' ')
                     *itr = L'_';
}
EDIT:

Hier sieht man es beim großen Fenster (die Font erscheint dicker als beim Rest):


Das rechts soll ein TabControl darstellen mit nem Frame auf Page 2 :0
Master674b is offline  
Old 03/17/2013, 20:10   #4


 
Ende!'s Avatar
 
elite*gold: 1
Join Date: Feb 2009
Posts: 6,379
Received Thanks: 7,998
Quote:
Mir ist aufgefallen dir fehlte irgendwo ein Blend Renderstate (Mob Aggro).
Jaa, das war damals noch alles ziemlich hacky. Hatte davon irgendwann die Schnauze voll und hab nun Tabellen von JEDEM Render-State, Blend-State und Texture-Stage-State mit den jeweiligen Default-Values und erstelle mir zu Anfang einen Stateblock damit. Jetzt läuft das Ganze auch tatsächlich in jedem Game ohne Probleme.

Die Möglichkeit mit den Vertex-Shadern ist natürlich auch nicht schlecht.

Sprites sind im Grunde nur Rechtecke mit einer Textur drüber.

NSprite.hpp
Code:
/*****************************************************************************
Narea project - NextGen gamehacking framework (c) [removed url here]
------------------------------------------------------------------------------
Author:        Ende!
UpdateV:       v2.0
Compatibility: Crossplattform
******************************************************************************/

/**
 * \file This file contains the NSprite class
 */

#ifndef NSPRITE_H
#define NSPRITE_H

#include "NTypes.hpp"
#include "NColor.hpp"

namespace Narea
{

   // =========================================================================

   /**
    * \brief   Pure virtual base class for sprites
    */

   class NSprite : public _NResource
   { 

      // ----------------------------------------------------------------------
      // Private variables
      
      uint           m_width;
      uint           m_height;
      NSimpleColor   m_diffuseColor;
      bool           m_alphaAsStencil;

   public:

      // ----------------------------------------------------------------------
      // Virtual destructor & constructor
      
      NSprite(NSimpleColor diffuseColor, bool useAlphaAsStencil);
      virtual ~NSprite() {}

      // ----------------------------------------------------------------------
      // Public inlined getters and setters
      
      uint           width                () const { return m_width;          }
      uint           height               () const { return m_height;         }
      NSimpleColor   diffuseColor         () const { return m_diffuseColor;   }
      bool           isAlphaUsedAsStencil () const { return m_alphaAsStencil; }

      void diffuseColor(NSimpleColor color) { m_diffuseColor = color; }  

      // ----------------------------------------------------------------------
      // Public pure virtual methods
      
      virtual void draw(float x,
                        float y,
                        float w,
                        float h,
                        float rot   = 0.f,
                        short alpha = 255) const = 0;
      virtual void draw(float x, float y, short alpha = 255) const = 0;

   protected:

      // ----------------------------------------------------------------------
      // Protected setters
      
      void width  (uint width)   { m_width = width;   }
      void height (uint height)  { m_height = height; }

      // ----------------------------------------------------------------------

   }; // ==> NSprite

   // =========================================================================
   // Implementation of inline methods

   /**
    * \brief   Constructor
    * \param   diffuseColor      The diffuse color
    * \param   useAlphaAsStencil true to use alpha as stencil for diffuse
    * 									color
    */

   inline NSprite::NSprite(NSimpleColor diffuseColor, bool useAlphaAsStencil)
      : m_diffuseColor(diffuseColor)
      , m_alphaAsStencil(useAlphaAsStencil)
   {} // ==> ctor

   // =========================================================================

} // ==> Narea

#endif // ==> NSPRITE_H
NFont.hpp
Code:
/*****************************************************************************
Narea project - NextGen gamehacking framework (c) [removed url here]
------------------------------------------------------------------------------
Author:        Ende!
UpdateV:       v2.0
Compatibility: Win32
******************************************************************************/

#ifndef NFONT_H
#define NFONT_H

#ifndef _WIN32
#  error This part of Narea can only be used in a windows environment
#endif

#include "NGFWObjectFactory.hpp"
#include "NCritSec.hpp"

#include <map>
#include <list>

namespace Narea
{

   // =========================================================================

   /**
    * \brief   Cross-GFW font class implementation
    * 			
    * Thread-safe.
    */

   class NFont
   {

      // ----------------------------------------------------------------------
      // Private attributes
      
      uint                 m_height;
      uint32_t             m_flags;
      std::wstring         m_fontFace;

   protected:

      // ----------------------------------------------------------------------
      // Protected POD structure(s)
      
      /// POD container struct describing a cached glyph
      struct CachedGlyph
      {
         /// Ptr to glyph image if printable, else nullptr
         NSprite       *pSprite;
         /// Size of a box exactly wrapping the glyph
         NDimensions    glyphDimensions;
         /// Size of the whole glyph cell
         NDimensions    cellDimensions;
         /// Relative position offset of the glyph-wrapping box
         NPos           relGlyphPosition;
         /// true in case the character is present in this font, else false
         bool           presentInFont;
      }; // ==> CachedGlyph

      // ----------------------------------------------------------------------
      // Protected constructors
      
      NFont(const std::wstring &rFontFace,
            uint height,
            uint32_t flags = Normal);
      NFont(const NFont &rCopyFrom);

      // ----------------------------------------------------------------------
      // Protected attributes

      HFONT                                           m_hFont;
      HDC                                             m_hDC;
      mutable std::map<wchar_t, const CachedGlyph>    m_cachedGlyphs;
      mutable NCritSec                                m_lock;

      // ----------------------------------------------------------------------
      // Static stuff
      
      static NCritSec                        m_cacheLock;
      static std::list<std::weak_ptr<NFont>> m_fontCache;

   public:

      // ----------------------------------------------------------------------
      // Public enumeration
      
      enum FontFlags : uint32_t
      {
         Normal      = 0x00,  ///< Default font mode
         Bold        = 0x01,  ///< Bold (fat) text
         Underlined  = 0x02,  ///< Underlined text
         Italic      = 0x04   ///< Italic text
      }; // ==> FontFlags

      // ----------------------------------------------------------------------
      // Public destructor and factory methods
      
      static NShared<NFont> get(const std::wstring &rFontFace,
                                uint height,
                                uint32_t flags = Normal);
      virtual ~NFont();

      // ----------------------------------------------------------------------
      // Public methods and overloaded operators
      
      // Visible
      void draw               (const NPos &rPos,
                               wchar_t ch,
                               NSimpleColor color) const;
      void draw               (const NPos &rPos, 
                               const std::string &rText, 
                               NSimpleColor color) const;
      void draw               (const NPos &rPos,
                               const std::wstring &rText, 
                               NSimpleColor color) const;

      // Measurement
      uint getGlyphWidth      (wchar_t ch                            ) const;
      uint calcTextLen        (const std::wstring &rText             ) const;
      uint calcTextLen        (const std::string &rText              ) const;
      int  textOffsFromPxOffs (const std::wstring &rText, uint pxOffs) const;
      int  textOffsFromPxOffs (const std::string &rText, uint pxOffs ) const;

      // Operators
      bool     operator == (const NFont &rhs) const;
      NFont&   operator =  (const NFont &rhs);

      // ----------------------------------------------------------------------
      // Public getters and setters
      
      const std::wstring&  fontFace       () const;
      uint                 height         () const;
      bool                 isBold         () const;
      bool                 isItalic       () const;
      bool                 isUnderlined   () const;
      uint32_t             flags          () const;

      void fontFace     (const std::wstring &rFontFace);
      void height       (uint height                  );
      void isBold       (bool bold                    );
      void isItalic     (bool italic                  );
      void isUnderlined (bool underlined              );
      void flags        (uint32_t flags               );

   protected:

      // ----------------------------------------------------------------------
      // Helpers
      
      void                 _createFont             (                 );
      bool                 _cacheGlyph             (wchar_t character) const;
      const CachedGlyph&   _getCachedGlyph         (wchar_t character) const;
      const CachedGlyph*   _getActualGlyph         (wchar_t character) const;
      bool                 _isGlyphPresentInFont   (wchar_t character) const;

      // ----------------------------------------------------------------------

   }; // ==> NFont

   // =========================================================================
   // Implementation of inline methods [NFont]

   /**
    * \brief   Sets the font face
    * \param   rFontFace   The new font face
    */

   inline void NFont::fontFace(const std::wstring &rFontFace)
   {
      NScopedLock lock(&m_lock);
      m_fontFace = rFontFace;
      _createFont();
   } // ==> fontFace

   // -------------------------------------------------------------------------

   /**
    * \brief   Sets the font height
    * \param   height   The new height
    */

   inline void NFont::height(uint height)
   {
      NScopedLock lock(&m_lock);
      m_height = height;
      _createFont();
   } // ==> height(uint)

   // -------------------------------------------------------------------------

   /**
    * \brief   Sets if the font's glyphs are bold
    * \param   bold  true if bold, else false
    */

   inline void NFont::isBold(bool bold)
   {
      NScopedLock lock(&m_lock);
      m_flags = bold ? (m_flags | Bold) : (m_flags & ~Bold);
      _createFont();
   } // ==> isBold(bool)

   // -------------------------------------------------------------------------

   /**
    * \brief   Sets if the font's glyphs are italic
    * \param   bold  true if italic, else false
    */

   inline void NFont::isItalic(bool italic)
   {
      NScopedLock lock(&m_lock);
      m_flags = italic ? (m_flags | Italic) : (m_flags & ~Italic);
      _createFont();
   } // ==> isItalic(bool)

   // -------------------------------------------------------------------------

   /**
    * \brief   Sets if the font's glyphs are underlined
    * \param   bold  true if underlined, else false
    */

   inline void NFont::isUnderlined(bool underlined)
   {
      NScopedLock lock(&m_lock);
      m_flags = underlined ? (m_flags | Underlined) : (m_flags & ~Underlined);
   } // ==> isUnderlined(bool)

   // -------------------------------------------------------------------------

   /**
    * \brief   Sets new font flags
    * \param   flags The flags
    * \see     FontFlags
    */

   inline void NFont::flags(uint32_t flags)
   {
      NScopedLock lock(&m_lock);
      m_flags = flags;
      _createFont();
   } // ==> flags(uint32_t)

   // -------------------------------------------------------------------------
   
   /**
    * \copydoc NFont::draw
    */

   inline void NFont::draw(const NPos &rPos,
                           const std::string &rText, 
                           NSimpleColor color) const
   {
      draw(rPos, multiByteToWide(rText), color);
   } // ==> draw(const NPos&, const std::string&, NSimpleColor)

   // -------------------------------------------------------------------------

   /**
    * \copydoc NFont::calcTextLen
    */

   inline uint NFont::calcTextLen(const std::string &rText) const
   {
      return calcTextLen(multiByteToWide(rText));
   } // ==> calcTextLen(const std::string&)

   // -------------------------------------------------------------------------

   /**
    * \brief   Returns the width of the glyph representation of a character
    * \param   character   The character to query the width for
    * \return  The glyph width
    */

   inline uint NFont::getGlyphWidth(wchar_t character) const
   {
      NScopedLock lock(&m_lock);
      const CachedGlyph *pGlyph = _getActualGlyph(character);
      return (pGlyph == nullptr) ? 0 : pGlyph->cellDimensions.width;
   } // ==> getGlyphWidth

   // -------------------------------------------------------------------------

   /**
    * \brief   Gets the font face
    * \return  The font face
    */

   inline const std::wstring& NFont::fontFace() const
   {
      NScopedLock lock(&m_lock);
      return m_fontFace;
   } // ==> fontFace()

   // -------------------------------------------------------------------------

   /**
    * \brief   Gets the height
    * \return  The height
    */

   inline uint NFont::height() const
   {
      return m_height;
   } // ==> height()

   // -------------------------------------------------------------------------

   /**
    * \brief   Query if this font is bold
    * \return  true if bold, false if not
    */

   inline bool NFont::isBold() const
   {
      return (m_flags & Bold) ? true : false;
   } // ==> isBold() const

   // -------------------------------------------------------------------------

   /**
    * \brief   Query if this font is italic
    * \return  true if italic, false if not
    */

   inline bool NFont::isItalic() const
   {
      return (m_flags & Italic) ? true : false;
   } // ==> isItalic() const

   // -------------------------------------------------------------------------

   /**
    * \brief   Query if this font is underlined
    * \return  true if underlined, false if not
    */

   inline bool NFont::isUnderlined() const
   {
      return (m_flags & Underlined) ? true : false;
   } // ==> isUnderlined() const

   // -------------------------------------------------------------------------

   /**
    * \brief   Gets the font flags
    * \return  The font flags
    * \see     FontFlags
    */

   inline uint32_t NFont::flags() const
   {
      return m_flags;
   } // ==> flags() const

   // -------------------------------------------------------------------------

   /**
    * \brief   Equality operator
    * \param   rhs   The right hand side
    * \return  true if equal, else false
    */

   inline bool NFont::operator == (const NFont &rhs) const
   {
      NScopedLock lock(&m_lock);
      NScopedLock lockRhs(&rhs.m_lock);

      return (m_fontFace == rhs.m_fontFace
              && m_flags == rhs.m_flags
              && m_height == rhs.m_height);
   } // ==> operator ==
   
   // -------------------------------------------------------------------------

   /**
    * \brief   Assignment operator
    * \param   rhs   The right hand side
    * \return  This instance
    */

   inline NFont& NFont::operator = (const NFont &rhs)
   {
      NScopedLock lock(&m_lock);
      NScopedLock lockRhs(&rhs.m_lock);

      // Copy core attributes
      m_height    = rhs.m_height;
      m_flags     = rhs.m_flags;
      m_fontFace  = rhs.m_fontFace;

      // Generate rest
      _createFont();

      return *this;
   } // ==> operator =

   // -------------------------------------------------------------------------

   /**
    * \copydoc NFont::testOffsFromPxOffs
    */

   inline int NFont::textOffsFromPxOffs(const std::string &rText, 
                                        uint pxOffs) const
   {
      return textOffsFromPxOffs(multiByteToWide(rText), pxOffs);
   } // ==> textOffsFromPxOffs

   // =========================================================================
   
} // ==> Narea

#endif // ==> NFONT_H
NFont.cpp
Code:
/*****************************************************************************
Narea project - NextGen gamehacking framework (c) [removed url here]
------------------------------------------------------------------------------
Author:        Ende!
UpdateV:       v2.0
Compatibility: Win32
******************************************************************************/

#include "NFont.hpp"
#include "NException.hpp"
#include "NAlgorithm.hpp"
#include "NConfig.hpp"
#include "NByteBuffer.hpp"

#include <vector>
#include <numeric>
#include <functional>

namespace Narea
{

   // =========================================================================
   
   // Static data initialization
   std::list<std::weak_ptr<NFont>>  NFont::m_fontCache;
   NCritSec                         NFont::m_cacheLock;

   // -------------------------------------------------------------------------

   /**
    * \brief   Constructor
    * 			
    * \param   rFontFace   The font face
    * \param   height      The font height
    * \param   flags       The font flags
    * 							
    * \throws  NXGeneral   Thrown if the font couldn't be created
    */

   NFont::NFont(const std::wstring &rFontFace, 
                uint height, 
                uint32_t flags)
      : m_height(height)
      , m_flags(flags)
      , m_fontFace(rFontFace)
      , m_hFont(NULL)
      , m_hDC(NULL)
   {
      _createFont();
   } // ==> ctor(const std::wstring&, uint, bool, bool, bool)

   // -------------------------------------------------------------------------

   /**
    * \brief   Copy constructor
    * \param   rCopyFrom   The object to copy from
    */

   NFont::NFont(const NFont &rCopyFrom)
      : m_height(rCopyFrom.m_height)
      , m_flags(rCopyFrom.m_flags)
      , m_fontFace(rCopyFrom.m_fontFace)
      , m_hFont(NULL)
      , m_hDC(NULL)
   {
      _createFont();
   } // ==> ctor(const NFont&)

   // -------------------------------------------------------------------------

   /**
    * \brief   Destructor
    */

   NFont::~NFont()
   {
      NScopedLock lock(&m_lock);

      if (m_hFont)
         DeleteObject(m_hFont);
      if (m_hDC)
         DeleteDC(m_hDC);

      walk_map(m_cachedGlyphs, [&](wchar_t, const CachedGlyph &rCur) 
      {
         safeDelete(rCur.pSprite);
      });
   } // ==> dtor

   // -------------------------------------------------------------------------

   /**
    * \brief   Creates the font
    * \throws  NXGeneral   Thrown if the font couldn't be created
    */

   void NFont::_createFont()
   {
      NScopedLock lock(&m_lock);

      // Create device context
      HDC hDC = CreateCompatibleDC(NULL);
      if (!hDC)
         throw NX(NXGeneral, "could not create dc");

      // Initialize font creation attribute struct
      LOGFONTW lf =
      {
         /* .lfHeight         = */ -MulDiv(height(), 
                                           GetDeviceCaps(hDC, LOGPIXELSY), 
                                           72),
         /* .lfWidth          = */ 0,
         /* .lfEscapement     = */ 0,
         /* .lfOrientation    = */ 0,
         /* .lfWeight         = */ isBold()     ? FW_BOLD   : FW_NORMAL,
         /* .lfItalic         = */ isItalic()   ? TRUE      : FALSE,
         /* .lfUnderline      = */ FALSE, // GetGlyphOutline ignores this
         /* .lfStrikeOut      = */ FALSE, // two values ;(
         /* .lfCharSet        = */ ANSI_CHARSET,                  
         /* .lfOutPrecision   = */ OUT_TT_ONLY_PRECIS,
         /* .lfClipPrecision  = */ CLIP_DEFAULT_PRECIS,
         /* .lfQuality        = */ CLEARTYPE_QUALITY,
         /* .lfPitchAndFamily = */ FF_DONTCARE,
         /* .lfFaceName       = */ NULL
      };
      fontFace().copy(lf.lfFaceName, LF_FACESIZE, 0);

      // Create font
      HFONT hFont = CreateFontIndirectW(&lf);
      if (!hFont)
      {
         DeleteDC(hDC);
         throw NX(NXGeneral, "could not create font");
      }

      // Create device context and select object
      if (!SelectObject(hDC, hFont))
      {
         DeleteDC(hDC);
         DeleteObject(hFont);
         throw NX(NXGeneral, "could not select font into DC");
      }

      // Everything fine so far, free old handles (if any) and copy new handles
      // into attributes
      if (m_hFont)
      {
         DeleteObject(m_hFont);
         m_hFont = NULL;
      }
      if (m_hDC)
      {
         DeleteDC(m_hDC);
         m_hDC = NULL;
      }

      m_hFont  = hFont;
      m_hDC    = hDC;

      // Cache all printable characters in ASCII range
      for (wchar_t i = '!'; i <= '~'; ++i)
         _cacheGlyph(i);
   } // ==> _createFont

   // -------------------------------------------------------------------------

   /**
    * \brief   Caches a glyph
    * \param   ch The character to cache
    * \return  true if it succeeds, false if it fails
    */

   bool NFont::_cacheGlyph(wchar_t ch) const
   {
      NScopedLock lock(&m_lock);

      // Already cached?
      if (m_cachedGlyphs.find(ch) != m_cachedGlyphs.end())
         return true;

      // Not present in font?
      if (!_isGlyphPresentInFont(ch))
      {
         const CachedGlyph glyph =
         {
            nullptr,
            NDimensions(),
            NDimensions(),
            NPos(),
            false
         };
         m_cachedGlyphs.insert(std::make_pair(ch, glyph));
         return true;
      }

      // Initialize parameters
      GLYPHMETRICS   gm = { 0 };
      MAT2           matrix =
      {
         {0, 1}, {0, 0},
         {0, 0}, {0, 1}
      };

      // Query data length
      DWORD len = GetGlyphOutlineW(m_hDC, 
                                   UINT(ch), 
                                   GGO_GRAY8_BITMAP, 
                                   &gm, 
                                   0, nullptr,
                                   &matrix);

      if (len == GDI_ERROR)
         return false;

      // No visible representation of glyph? Whitespace.
      if (len == 0)
      {
         // Put empty record into cache
         const CachedGlyph glyph = 
         { 
            nullptr, 
            NDimensions(),
            NDimensions(gm.gmCellIncX, gm.gmCellIncY),
            NPos(),
            true
         };
         m_cachedGlyphs.insert(std::make_pair(ch, glyph));
         return true;
      }

      // Receive glyph image data
      std::vector<byte> glyphImgData(len);
      if (GetGlyphOutlineW(m_hDC,
                           UINT(ch),
                           GGO_GRAY8_BITMAP,
                           &gm,
                           len, glyphImgData.data(),
                           &matrix) == GDI_ERROR)
      {
         return false;
      }

      // Transform to raw sprite format
      uint width = (gm.gmBlackBoxX + sizeof(uint) - 1) & ~(sizeof(uint) - 1);
      std::vector<NSimpleColor> textureData(gm.gmBlackBoxX * gm.gmBlackBoxY);

      for (uint y = 0; y < gm.gmBlackBoxY; ++y)
      {
         for (uint x = 0; x < gm.gmBlackBoxX; ++x)
         {
            // Transform 64 shades of gray color to 8 bit alpha channel
            NSimpleColor curShade = glyphImgData[y * width + x];
            curShade = curShade * 255 / 64;
            textureData[y * gm.gmBlackBoxX + x] = curShade << 24;
         }
      }
      
      // Put data into look-up map
      const CachedGlyph glyph =
      {
         g_NConfig.gfwObjFactory().createSprite(
            textureData.data(),
            gm.gmBlackBoxX, gm.gmBlackBoxY,
            true
            ),
         NDimensions(gm.gmBlackBoxX, gm.gmBlackBoxY),
         NDimensions(gm.gmCellIncX, gm.gmCellIncY),
         NPos(gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y),
         true
      };
      m_cachedGlyphs.insert(std::make_pair(ch, glyph));

      return true;
   } // ==> _cacheGlyph

   // -------------------------------------------------------------------------

   /**
    * \brief   Gets a cached glyph
    * \param   character   The character to retrieve the glyph for
    * \throws  NXGeneral   Thrown when caching the glyph fails
    * \return  The cached glyph
    */

   const NFont::CachedGlyph& NFont::_getCachedGlyph(wchar_t character) const
   {
      NScopedLock lock(&m_lock);

      // Is glyph already cached?
      auto iGlyph = m_cachedGlyphs.find(character);
      if (iGlyph != m_cachedGlyphs.end())
         return (*iGlyph).second;

      // Nope, try to cache it now
      if (_cacheGlyph(character))
         return _getCachedGlyph(character);
      
      // Did not work, either? Throw exception.
      throw NX(NXGeneral, "unable to cache glyph for font");
   } // ==> _getCachedGlyph

   // -------------------------------------------------------------------------

   /**
    * \brief   Gets the glyph drawn for the given character
    * \param   character   The character to retrieve the glyph for
    * \return  nullptr if it fails, else the glyph drawn for the given
    * 			character. See remarks.
    * \remarks If the font lacks the character, the glyph for '?' is returned 
    * 			instead.  If the '?' glyph isn't present, either, nullptr is 
    * 			returned.
    */

   const NFont::CachedGlyph* NFont::_getActualGlyph(wchar_t character) const
   {
      NScopedLock lock(&m_lock);

      const CachedGlyph *pGlyph = &_getCachedGlyph(character);

      // Does font lack this character? Use question mark instead.
      if (!pGlyph->presentInFont)
      {
         pGlyph = &_getCachedGlyph('?');

         // Still not present? Crappy font, return nullptr.
         if (!pGlyph->presentInFont)
            pGlyph = nullptr;
      }

      return pGlyph;
   } // ==> _getActualGlyph

   // -------------------------------------------------------------------------
   
   /**
    * \brief   Draws a single character to a given position using the font
    * 			
    * \param   rPos  The screen position to draw the glyph to in pixels
    * \param   ch    The character to draw
    * \param   color The color to draw with
    * 			
    * \throws  NXGFWError Thrown in case drawing the glyph fails
    */

   void NFont::draw(const NPos &rPos,
                    wchar_t ch,
                    NSimpleColor color) const
   {
      NScopedLock lock(&m_lock);

      const CachedGlyph *pGlyph = _getActualGlyph(ch);

      // If non-drawable, give up
      if (pGlyph == nullptr || pGlyph->pSprite == nullptr)
         return;

      try
      {
         pGlyph->pSprite->diffuseColor(color);
         pGlyph->pSprite->draw(float(rPos.x), float(rPos.y));
      }
      catch (const NXGFWError&)
      {
         throw NX(NXGFWError, "could not draw glyph");
      }
   } // ==> draw

   // -------------------------------------------------------------------------

   /**
    * \brief   Draws text to a given position using the font
    * 			
    * \param   rPos  The screen position to draw the text to in pixels
    * \param   rText The text to draw
    * \param   color The color to draw with
    * 			
    * \throws  NXGFWError Thrown in case drawing the glyphs fails
    */

   void NFont::draw(const NPos &rPos, 
                    const std::wstring &rText, 
                    NSimpleColor color) const
   {
      NScopedLock lock(&m_lock);

      uint curX = rPos.x;

      // Iterate through string
      for (auto iCurChar = rText.cbegin()
         ; iCurChar != rText.cend()
         ; ++iCurChar)
      {
         const CachedGlyph *pGlyph = _getActualGlyph(*iCurChar);

         // Skip lacking character
         if (pGlyph == nullptr)
            continue;

         // Draw glyph, if non-whitespace
         if (pGlyph->pSprite != nullptr)
         {
            try
            {
               pGlyph->pSprite->diffuseColor(color);
               pGlyph->pSprite->draw(
                  float(curX     + pGlyph->relGlyphPosition.x           ),
                  float(rPos.y   - pGlyph->relGlyphPosition.y + m_height)
                  );
            } 
            catch (const NXGFWError&)
            {
               throw NX(NXGFWError, "could not draw glyphs");
            }
         }
         
         // Adjust draw position
         curX += pGlyph->cellDimensions.width;
      }

      // Underline, if requested
      if (isUnderlined())
      {
         g_NConfig.renderEngine().drawRect(float(rPos.x),
                                           float(rPos.y),
                                           float(curX - rPos.x),
                                           1.f,
                                           makeBasicColor(color));
      }
   } // ==> draw(const NPos&, const std::wstring&, NSimpleColor)
   
   // -------------------------------------------------------------------------

   /**
    * \brief   Checks whether the given character is present in the font
    * \param   character   The character
    * \return  true if it present, else false
    */

   bool NFont::_isGlyphPresentInFont(wchar_t character) const
   {
      NScopedLock lock(&m_lock);

      // Query supported characters
      NByteBuffer data(GetFontUnicodeRanges(m_hDC, nullptr));
      GetFontUnicodeRanges(m_hDC, data.ptr<GLYPHSET>());

      // Check if character is inside of one of the ranges
      const GLYPHSET *pGlyphSet = data.constPtr<GLYPHSET>();
      for (uint i = 0; i < pGlyphSet->cRanges; ++i)
      {
         const WCRANGE *pCurRange = &pGlyphSet->ranges[i];
         if (character >= pCurRange->wcLow
            && character <= pCurRange->wcLow + pCurRange->cGlyphs)
         {
            return true;
         }
      }

      return false;
   } // ==> _isGlyphPresentInFont

   // -------------------------------------------------------------------------

   /**
    * \brief   Calculates the text length in pixels
    * \param   rText The text to calculate the length for
    * \return  The calculated text length
    */

   uint NFont::calcTextLen(const std::wstring &rText) const
   {
      NScopedLock lock(&m_lock);
      uint        len = 0;

      // Accumulate widths of single glyphs
      for (wchar_t curChar : rText)
         len += getGlyphWidth(curChar);

      return len;
   } // ==> calcTextLen(const std::wstring&) const

   // -------------------------------------------------------------------------

   /**
    * \brief   Computes the text offset from a relative pixel offset
    * \param   rText    The text to calculate the text offset for
    * \param   pxOffs   The offset in pixels from the beginning of the text
    * \return  The translated offset
    */

   int NFont::textOffsFromPxOffs(const std::wstring &rText, uint pxOffs) const
   { 
      NScopedLock lock(&m_lock);
      uint curPxOffs    = 0;
      uint curTextOffs  = 0;
      
      // Find first character below pxOffs
      for (auto iCurChar = rText.cbegin()
         ; iCurChar != rText.cend()
         ; ++iCurChar, ++curTextOffs)
      {
         curPxOffs += getGlyphWidth(*iCurChar);

         if (curPxOffs > pxOffs) 
            return curTextOffs;
      }

      return -1;
   } // ==> textOffsFromPxOffs

   // -------------------------------------------------------------------------
   
   /**
    * \brief   Allocates a new font instance or retrieves one from cache
    * 			
    * \param   rFontFace   The font face
    * \param   height      The height
    * \param   flags       The font flags
    * 							
    * \throws  NXGeneral   Thrown if the font couldn't be created
    * 							
    * \return  The font instance with the desired properties
    */

   NShared<NFont> NFont::get(const std::wstring &rFontFace,
                             uint height,
                             uint32_t flags)
   {
      NScopedLock lock(&m_cacheLock);
      size_t      fontFaceHash = std::hash<std::wstring>()(rFontFace);

      // Already cached?
      for (auto i = m_fontCache.begin(); i != m_fontCache.end();)
      {
         auto pCurItem = i->lock();

         // Dead reference? Remove from cache
         if (pCurItem == nullptr)
         {
            i = m_fontCache.erase(i);
            continue;
         }

         // Desired item?
         if (std::hash<std::wstring>()(pCurItem->fontFace()) == fontFaceHash
             && pCurItem->flags() == flags
             && pCurItem->height() == height)
         {
            return std::move(pCurItem);
         }

         ++i;
      }

      // Nope, cache now
      std::shared_ptr<NFont> pNew(new NFont(rFontFace, height, flags));
      m_fontCache.push_back(pNew);

      return std::move(pNew);
   } // ==> get(const std::wstring&, uint, uint32_t)

   // =========================================================================

} // ==> Narea
Ende! is offline  
Thanks
4 Users
Old 03/17/2013, 20:31   #5
 
Master674b's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
Vielen dank, werde ich mir morgen direkt mal ansehen ^^
Die Sprites ziehst du dann einfach über n Rechteck auf und lässt es eventuell noch durch nen Shader laufen nehme ich an?
Master674b is offline  
Old 03/17/2013, 20:39   #6


 
Ende!'s Avatar
 
elite*gold: 1
Join Date: Feb 2009
Posts: 6,379
Received Thanks: 7,998
Quote:
Originally Posted by Master674b View Post
Die Sprites ziehst du dann einfach über n Rechteck auf und lässt es eventuell noch durch nen Shader laufen nehme ich an?
Exakt.

Die Glyphs der Font sind bei mir allerdings nur Alpha-Schablonen, die Farbe kommt dann durch die Diffuse-Color ins Spiel. So muss ich nicht für jede Schrift-Farbe extra cachen.
Ende! is offline  
Thanks
1 User
Old 03/17/2013, 21:43   #7
 
Master674b's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
Das wichtigste was ich so mitgenommen hab beim überfliegen war einfach Font in GDI rendern, Farbwerte in die Textur packen (LockRect?) (Danke, der Ausschnitt war recht wichtig!) die Texturen und Dimensionen des Buchstabens anschließend speichern und dann einfach beim Text zeichnen glyphs[character]->texture rendern und halt den Offset vom Start anpassen.

Sehr einfach umzusetzen die Alphawerte in die Textur zu schreiben hätte mir denke ich dennoch Probleme bereitet, danke.

Btw:
Wie heißt die Erweiterung für die Kommentare die du da oben benutzt? Sieht gut aus!
(Ich hab keine Ahnung ob das maschinell kommentiert ist^^ z.B. am Ende jeder funktion nochmal ne Deklarationswiederholung. Mir wärs per Hand viel zu viel Arbeit, kommentiere wie du siehst eh selten bis nie...)

Inline ist übrigens unnötig und wird vom Compiler ignoriert. Alle Funktionen die direkt im Header implementiert sind werden direkt als inline angesehen, das schreibt der Standard vor. Für den ScopedMutex gibts std::lock_guard<std::mutex>
Master674b is offline  
Old 03/17/2013, 22:05   #8


 
Ende!'s Avatar
 
elite*gold: 1
Join Date: Feb 2009
Posts: 6,379
Received Thanks: 7,998
Quote:
Originally Posted by Master674b View Post
Wie heißt die Erweiterung für die Kommentare die du da oben benutzt? Sieht gut aus!
(Ich hab keine Ahnung ob das maschinell kommentiert ist^^ z.B. am Ende jeder funktion nochmal ne Deklarationswiederholung. Mir wärs per Hand viel zu viel Arbeit, kommentiere wie du siehst eh selten bis nie...)
Danke. ˆˆ Ist größtenteils Handarbeit, bin bei meinem Codestil recht penibel. Die Vorlagen für die Doxygen-Comments generiert mir ein Plugin, dessen Namen ich allerdings gerade vergessen haben. Ist aber kostenpflichtig und gekekst auch nicht erhältlich. Mit sinnvollem Inhalt muss man es allerdings meistens selbst füllen, da die automatisch generierten Texte halt oft Crap sind.

Quote:
Originally Posted by Master674b View Post
Inline ist übrigens unnötig und wird vom Compiler ignoriert. Alle Funktionen die direkt im Header implementiert sind werden direkt als inline angesehen, das schreibt der Standard vor. Für den ScopedMutex gibts std::lock_guard<std::mutex>
Inline ist nur dann implizit, wenn die Funktionen auch IN der Klasse implementiert werden. Implementiert man Funktionen außerhalb der Klasse selbst, ist diese wieder vonnöten - auch im Header. Dieser Teil meines Frameworks ist noch mit VS10 entstanden, welches noch kein C++11-Threading unterstützt hat. Die range-based-fors sind nur deshalb schon drin, weil ich meine eigene for_each Funktion nach dem Umstieg auf VS12 removed hab, da sie nun ja nicht mehr benötigt wurde. Beim Threading bin ich noch nicht zum Updaten gekommen (hab das Update auf MSVC12 erst kürzlich vorgenommen).
Ende! is offline  
Thanks
1 User
Old 03/17/2013, 22:11   #9
 
Master674b's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
Quote:
Originally Posted by Ende! View Post
Danke. ˆˆ Ist größtenteils Handarbeit, bin bei meinem Codestil recht penibel. Die Vorlagen für die Doxygen-Comments generiert mir ein Plugin, dessen Namen ich allerdings gerade vergessen haben. Ist aber kostenpflichtig und gekekst auch nicht erhältlich. Mit sinnvollem Inhalt muss man es allerdings meistens selbst füllen, da die automatisch generierten Texte halt oft **** sind.


Inline ist nur dann implizit, wenn die Funktionen auch IN der Klasse implementiert werden. Implementiert man Funktionen außerhalb der Klasse selbst, ist diese wieder vonnöten - auch im Header. Dieser Teil meines Frameworks ist noch mit VS10 entstanden, welches noch kein C++11-Threading unterstützt hat. Die range-based-fors sind nur deshalb schon drin, weil ich meine eigene for_each Funktion nach dem Umstieg auf VS12 removed hab, da sie nun ja nicht mehr benötigt wurde. Beim Threading bin ich noch nicht zum Updaten gekommen (hab das Update auf MSVC12 erst kürzlich vorgenommen).
Oh ja stimmt, mir ist gar nicht aufgefallen, dass du sie außerhalb der Klassen implementiert hast. Ich mache das bei kleinen Funktionen immer direkt in der Klasse. Selbst wenn du das inline weglässt wirst du merken, dass der Compiler es allerdings trotzdem so optimiert. Der benutzt inline wann es ihm passt.
Master674b is offline  
Old 03/17/2013, 22:37   #10
 
.SkyneT.'s Avatar
 
elite*gold: 273
Join Date: Sep 2010
Posts: 1,831
Received Thanks: 786
Toller Release, ich war bisher immer viel zu faul eine schöne GUI
zu zeichnen :P
.SkyneT. is offline  
Reply


Similar Threads Similar Threads
Component zu HDMI Converter (HDpvr)
07/17/2012 - Technical Support - 0 Replies
Hallo zusammen. Ich habe eine Frage bezüglich eines Component zu HDMI Konverters. Und zwar habe ich ihn gekauft um auf meinem PC-Monitor zu spielen, während ich mit der Hauppage HDPVR, Xbox 360 Gameplay aufnehme. Verkabelung also folgendermassen: * XBOX 360 (Component) > HDPVR (Component) > HDMI Konverter (HDMI) > HP Monitor
PSP to Component mit uncracked version ?
03/05/2012 - Technical Support - 2 Replies
Da ich eine HD PVR besitze dacht ich mir das ich gerne auch ab und zu mal ein paar PSP Games aufnehmen wollen würde. Dazu gibts ja Kabel wie: Component Kabel HD-AV für PSP Slim / PSP 3000: Amazon.de: Computer & Zubehör Die Frage ist ob es eine Hardwareseitige Sperre auf der PSP gibt die dies verhindert falls sie nicht cracked ist ? Hatte nämlich nicht vor diese zu "cracken"
Shaiya Server Enhance Component for EP70
12/19/2011 - Shaiya - 11 Replies
First of all, what I’m selling is not a complete Shaiya PServer program or its database. I’m selling an add-in DLL of ps_game.exe which written by myself. This component’s name is PsGameSuperExt.dll. I think the most fascinating place of Shaiya is the PVP-battle-zone. So I wrote this add-in to improve some game experiences of PVP, this is the main purpose. And everything listed blow is related with PVP more or less. Now, let us take a look at the main features: 1. Extend the max team...
May I post an advertisement of PServer Component here?
12/14/2011 - Shaiya Private Server - 2 Replies
I have a PServer Component on sale now. And may I post an advertisement of my PServer Component here? I'm a PServer-Developer. The PServer Component would bring your server some more fun than the original one. If I could post this , I would bring all the details of the Component. :D:D:D
[REQUEST] NET FRAMEWORK COMPONENT INSTALLATION
01/17/2010 - EO PServer Hosting - 5 Replies
im always get problem on this..so for who have a component installation please share with me..i dont want to open my internet connection while installing NET.. Problem.... 1.Virus Attacking when i turn on my IE..im not using antivirus coz after im open my ACC it will detect SALITY viruses to at pc and all exe file will be quarantine(also exe from windows) so im use deepfreeze..im also have make a exclusion to my antivirus but it still same..it will detect all exe as SALITY 2.Noob Internet...



All times are GMT +2. The time now is 03:05.


Powered by vBulletin®
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2024 elitepvpers All Rights Reserved.