Jump to content

GWEN Renderer for Leadwerks


smashthewindow
 Share

Recommended Posts

GWEN is a GUI system written by Garry Newman, creator of Garry's Mod.

I was in the process of writing a GWEN Leadwerks Renderer using only native commands (unlike all the other libraries out there), but is leaving at it's current progress.

The main reason is the inability to crop textures only using native Leadwerks commands. (Using OpenGL is a solution though.)

Even though not all the features are converted to Leadwerks, below library is more than enough to write a beautiful imageless GUI in Leadwerks. (Which is basically what I want biggrin.png )

I'm posting it here in hopes of someone benefiting out of this in some way.

 

The Header.

#ifndef GWEN_RENDERERS_LEADWERKS_H
#define GWEN_RENDERERS_LEADWERKS_H
#include "Gwen/Gwen.h"
#include "Gwen/BaseRender.h"
namespace Gwen
{
namespace Renderer
{
 class Leadwerks : public Gwen::Renderer::Base
 {
  public:
Leadwerks();
~Leadwerks();
virtual void Begin();
virtual void End();
virtual void SetDrawColor( Color color );
virtual void DrawFilledRect( Gwen::Rect rect );
virtual void LoadTexture( Gwen::Texture* pTexture );
virtual void FreeTexture( Gwen::Texture* pTexture );
virtual void DrawTexturedRect( Gwen::Texture* pTexture, Gwen::Rect pTargetRect, float u1=0.0f, float v1=0.0f, float u2=1.0f, float v2=1.0f );

virtual void LoadFont( Gwen::Font* pFont );
virtual void FreeFont( Gwen::Font* pFont );
virtual void RenderText( Gwen::Font* pFont, Gwen::Point pos, const Gwen::UnicodeString& text );
virtual Gwen::Point MeasureText( Gwen::Font* pFont, const Gwen::UnicodeString& text );
virtual void DrawPixel( int x, int y );
virtual Gwen::Point MeasureText( Gwen::Font* pFont, const Gwen::String& text );
virtual void RenderText( Gwen::Font* pFont, Gwen::Point pos, const Gwen::String& text );
 };
}
}
#endif

 

And the cpp file. Make sure to read comments biggrin.png.

#include <GwenRenderersLeadwerks.h>
#include <GwenUtility.h>
#include <GwenTexture.h>
#include <engine.h>
namespace Gwen
{
namespace Renderer
{
 Leadwerks::Leadwerks() {
 }
 Leadwerks::~Leadwerks() {
 }
 void Leadwerks::Begin() {
  LE::SetBlend(1);
 }
 void Leadwerks::End() {
  LE::SetBlend(0);
 }
 void Leadwerks::SetDrawColor( Color color ) {
  LE::TVec4 c;
  c.X = color.r/255;
  c.Y = color.g/255;
  c.Z = color.b/255;
  c.W = color.a/255;
  LE::SetColor( c );
 }

 void Leadwerks::DrawFilledRect( Gwen::Rect rect ) {
  Translate( rect );
  if( rect.w == 1 ) {
LE::DrawLine( rect.x, rect.y, rect.x, rect.y + rect.h );
return;
  }
  if( rect.h == 1 ) {
LE::DrawLine( rect.x, rect.y, rect.x + rect.w, rect.y );
return;
  }
  LE::DrawRect( rect.x, rect.y, rect.w, rect.h );
 }
 void Leadwerks::LoadTexture( Gwen::Texture* pTexture ) {
  BP tex = LE::LoadTexture( pTexture->name.Get().c_str() );

  pTexture->data = tex;
  pTexture->failed = (tex == nullptr);
  pTexture->width = LE::TextureWidth( tex );
  pTexture->height = LE::TextureHeight( tex );
 }
 void Leadwerks::FreeTexture( Gwen::Texture* pTexture ) {
  LE::FreeTexture( (BP)pTexture->data );
 }
 void Leadwerks::DrawTexturedRect( Gwen::Texture* pTexture, Gwen::Rect pTargetRect, float u1, float v1, float u2, float v2 ) {
  //Ignore this function. Right now you can't crop textures in Leadwerks.
  /*
  Translate( pTargetRect );
  LE::DrawImage( (BP)pTexture->data, pTargetRect.x, pTargetRect.y, pTargetRect.w, pTargetRect.h );
  */
 }

 void Leadwerks::LoadFont( Gwen::Font* pFont ) {
  //Uncomment the lines below if you're going to use Leadwerks fonts.
  //I personally prefer the default font better...
  /*
  TFont font = LE::LoadFont( Gwen::Utility::UnicodeToString(pFont->facename).c_str() );
  LE::SetFont(font);
  pFont->data = font;
  */
  pFont->realsize = LE::FontHeight();
 }
 void Leadwerks::FreeFont( Gwen::Font* pFont ) {
  if( pFont->data ) LE::FreeFont( (BP)pFont->data );
 }
 void Leadwerks::RenderText( Gwen::Font* pFont, Gwen::Point pos, const Gwen::UnicodeString& text ) {
  RenderText( pFont, pos, Gwen::Utility::UnicodeToString(text) );
 }
 Gwen::Point Leadwerks::MeasureText( Gwen::Font* pFont, const Gwen::UnicodeString& text ) {
  return MeasureText( pFont, Gwen::Utility::UnicodeToString(text) );
 }
 void Leadwerks::DrawPixel( int x, int y ) {
  Translate( x, y );
  LE::Plot( x, y );
 }
 Gwen::Point Leadwerks::MeasureText( Gwen::Font* pFont, const Gwen::String& text ) {
  if( pFont->data ) LoadFont( pFont );
  return Gwen::Point( LE::TextWidth( text.c_str()), LE::FontHeight() );
 }
 void Leadwerks::RenderText( Gwen::Font* pFont, Gwen::Point pos, const Gwen::String& text ) {
  Translate( pos.x, pos.y );
  if( pFont->data ) LoadFont( pFont );
  LE::DrawTextA( pos.x, pos.y, text.c_str() );
 }
}
}

  • Upvote 1

Blog & Portfolio

 

Current project: moon.chase.star

Link to comment
Share on other sites

  • 1 month later...

I took a break from coding due to heavy workload on school life, but I finally got to work.

I went to finishing the renderer was like the first thing I done when I got back, so here it is.

I had to rely on a few OpenGL functions but it's not that heavy.

 

#ifndef GWEN_RENDERERS_LEADWERKS_H
#define GWEN_RENDERERS_LEADWERKS_H
#include <Gwen/Gwen.h>
#include <Gwen/BaseRender.h>
#include <engine.h>
#include <glGL.h>
#include <glGLU.h>
namespace Gwen
{
namespace Renderer
{
 class Leadwerks : public Gwen::Renderer::Base
 {
 public:
  Leadwerks();
  ~Leadwerks();
  virtual void Begin();
  virtual void End();
  virtual void SetDrawColor( Color color );
  virtual void DrawFilledRect( Gwen::Rect rect );
  virtual void LoadTexture( Gwen::Texture* pTexture );
  virtual void FreeTexture( Gwen::Texture* pTexture );
  virtual void DrawTexturedRect( Gwen::Texture* pTexture, Gwen::Rect pTargetRect, float u1=0.0f, float v1=0.0f, float u2=1.0f, float v2=1.0f );
  virtual void LoadFont( Gwen::Font* pFont );
  virtual void FreeFont( Gwen::Font* pFont );
  virtual void RenderText( Gwen::Font* pFont, Gwen::Point pos, const Gwen::UnicodeString& text );
  virtual Gwen::Point MeasureText( Gwen::Font* pFont, const Gwen::UnicodeString& text );
  virtual void DrawPixel( int x, int y );
  virtual void DrawLinedRect( Gwen::Rect rect );
  virtual Gwen::Point MeasureText( Gwen::Font* pFont, const Gwen::String& text );
  virtual void RenderText( Gwen::Font* pFont, Gwen::Point pos, const Gwen::String& text );
 private:
  enum CullMode
  {
CULL_NONE,
CULL_DRAW_CCW,
CULL_DRAW_CW
  };
  void leglBegin   (TCamera camera = NULL, float zoom = 1.0f, CullMode cm = CULL_DRAW_CCW);
  void leglEnd  (bool was3D = false);
  void leglBindTexture(TTexture texture);
 };
}
}
#endif

 

#include "Renderer.h"
#include <GwenUtility.h>
#include <GwenTexture.h>
#include <engine.h>
namespace Gwen
{
namespace Renderer
{
 Leadwerks::Leadwerks() {
 }
 Leadwerks::~Leadwerks() {
 }
 void Leadwerks::Begin() {
  LE::SetBlend(1);
 }
 void Leadwerks::End() {
  LE::SetBlend(0);
 }
 void Leadwerks::SetDrawColor( Color color ) {
  LE::TVec4 c;
  c.X = color.r/255;
  c.Y = color.g/255;
  c.Z = color.b/255;
  c.W = color.a/255;
  LE::SetColor( c );
 }
 void Leadwerks::DrawFilledRect( Gwen::Rect rect ) {
  Translate( rect );
  if( rect.w == 1 && rect.h == 1 )
  {
LE::Plot( rect.x, rect.y );
return;
  }
  if( rect.w == 1 ) {
LE::DrawLine( rect.x, rect.y, rect.x, rect.y + rect.h );
return;
  }
  if( rect.h == 1 ) {
LE::DrawLine( rect.x, rect.y, rect.x + rect.w, rect.y );
return;
  }
  LE::DrawRect( rect.x, rect.y, rect.w, rect.h );
 }
 void Leadwerks::LoadTexture( Gwen::Texture* pTexture ) {
  BP tex = LE::LoadTexture( pTexture->name.Get().c_str() );
  pTexture->data = tex;
  pTexture->failed = (tex == nullptr);
  if( tex != nullptr )
  {
pTexture->width = LE::TextureWidth( tex );
pTexture->height = LE::TextureHeight( tex );
  }
 }
 void Leadwerks::FreeTexture( Gwen::Texture* pTexture ) {
  LE::FreeTexture( (BP)pTexture->data );
 }
 void Leadwerks::DrawTexturedRect( Gwen::Texture* pTexture, Gwen::Rect pTargetRect, float u1, float v1, float u2, float v2 ) {
  Translate( pTargetRect );
  leglBegin();
  leglBindTexture( (BP)pTexture->data );
  glBegin( GL_QUADS );
  glTexCoord2f(u2, v2); glVertex2i(pTargetRect.x + pTargetRect.w, pTargetRect.y + pTargetRect.h);
  glTexCoord2f(u2, v1); glVertex2i(pTargetRect.x + pTargetRect.w, pTargetRect.y);
  glTexCoord2f(u1, v1); glVertex2i(pTargetRect.x, pTargetRect.y );
  glTexCoord2f(u1, v2); glVertex2i(pTargetRect.x, pTargetRect.y + pTargetRect.h );
  glEnd();

  leglBindTexture(NULL);
  leglEnd();
 }
 void Leadwerks::LoadFont( Gwen::Font* pFont ) {
  if(  Gwen::Utility::UnicodeToString(pFont->facename) != "Default" )
  {
TFont font = LE::LoadFont( Gwen::Utility::UnicodeToString(pFont->facename).c_str() );
LE::SetFont(font);
pFont->data = font;
  }
  pFont->size = LE::FontHeight();
 }
 void Leadwerks::FreeFont( Gwen::Font* pFont ) {
  if( pFont->data ) LE::FreeFont( (BP)pFont->data );
 }
 void Leadwerks::RenderText( Gwen::Font* pFont, Gwen::Point pos, const Gwen::UnicodeString& text ) {
  RenderText( pFont, pos, Gwen::Utility::UnicodeToString(text) );
 }
 Gwen::Point Leadwerks::MeasureText( Gwen::Font* pFont, const Gwen::UnicodeString& text ) {
  return MeasureText( pFont, Gwen::Utility::UnicodeToString(text) );
 }
 void Leadwerks::DrawLinedRect( Gwen::Rect rect )
 {
  Translate( rect );
  LE::DrawLine( rect.x + 1, rect.y, rect.x + rect.w - 1, rect.y );
  LE::DrawLine( rect.x + rect.w, rect.y, rect.x + rect.w, rect.y + rect.h );
  LE::DrawLine( rect.x + rect.w - 1, rect.y + rect.h, rect.x + 1, rect.y + rect.h );
  LE::DrawLine( rect.x, rect.y + rect.h, rect.x, rect.y );
 }
 void Leadwerks::DrawPixel( int x, int y ) {
  Translate( x, y );
  LE::Plot( x, y );
 }
 Gwen::Point Leadwerks::MeasureText( Gwen::Font* pFont, const Gwen::String& text ) {
  if( pFont->data ) LoadFont( pFont );
  return Gwen::Point( LE::TextWidth( text.c_str()), LE::FontHeight() );
 }
 void Leadwerks::RenderText( Gwen::Font* pFont, Gwen::Point pos, const Gwen::String& text ) {
  Translate( pos.x, pos.y );
  if( pFont->data ) LoadFont( pFont );
  LE::DrawTextA( pos.x, pos.y, text.c_str() );
 }
 void Leadwerks::leglBegin(TCamera camera, float zoom, CullMode cm)
 {
  // Setup projetion according to argument
  if (NULL != camera)
  {
// Save current projection matrix. Then reset
glMatrixMode(GL_PROJECTION); glPushMatrix();
glLoadIdentity();
// Calculate the view frustum
float nearRange, farRange; GetCameraRange(camera, nearRange, farRange);
float theta = 1.0f / zoom; // tan(45°) = 1.0f
float aspect = float(BufferWidth(CurrentBuffer()))/BufferHeight(CurrentBuffer());
glFrustum (-nearRange*theta, nearRange*theta, -nearRange/aspect*theta, nearRange/aspect*theta, nearRange,farRange);
// Reset transformation
glMatrixMode(GL_MODELVIEW); glPushMatrix();
glLoadIdentity();
// LE uses a differently handed coordinate system than ogl does
glScalef(1.0f, 1.0f, -1.0f);
// Calculate the LookAt vectors (camera direction and up vector)...
TVec3 from = EntityPosition(camera, true);
TVec3 to = {0,0,-1}; to = TFormVector(to, camera, NULL); to += from;
TVec3 up = {0,1,0}; up = TFormVector(up, camera, NULL);
// Set LookAt
gluLookAt(from.X, from.Y, from.Z, to.X, to.Y , to.Z, up.X, up.Y, up.Z);
  }
  else
  {
glPushMatrix();
// Set orthographic projection (used for 2D drawing)
// Get the current viewport/buffer size.
int vPort[4]; glGetIntegerv(GL_VIEWPORT, vPort);
// Set the projection
gluOrtho2D(0, vPort[2], vPort[3], 0); // like glOrtho(0, vPort[2], vPort[3], 0, -1, 1);
// Reset transformation
glMatrixMode(GL_MODELVIEW); glPushMatrix();
glLoadIdentity();
  }
  // Setup default drawing settings.
  // Alpha blending.
  glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  // Backface culling.
  if (CULL_NONE != cm)glEnable(GL_CULL_FACE);
  if (NULL != camera)glCullFace((CULL_DRAW_CCW == cm) ? GL_BACK : GL_FRONT);
  else glCullFace((CULL_DRAW_CCW == cm) ? GL_FRONT : GL_BACK);
  // Depth test for 3D projection
  if (NULL != camera)glEnable(GL_DEPTH_TEST);
  // Drawing color.
  glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
 }

 // Use NULL (0) for the texture to reset (bind no texture)
 void Leadwerks::leglBindTexture(TTexture texture)
 {
  if(NULL != texture)
  {
glEnable(GL_TEXTURE_2D);
BindTexture(texture, 0); // LE command.
  }
  else
  {
glBindTexture(GL_TEXTURE_2D, NULL);
glDisable(GL_TEXTURE_2D);
  }
 }
 // End drawing. Set "was3D" to true if you specified a camera at leglBegin (= used 3D projection).
 void Leadwerks::leglEnd(bool was3D)
 {
  // Undo changes only made in 3D mode (camera != NULL)
  if (was3D)
  {
glMatrixMode(GL_PROJECTION); glPopMatrix();
glDisable(GL_DEPTH_TEST);
  }
  else
glPopMatrix();
  // Reset transformation.
  glMatrixMode(GL_MODELVIEW); glPopMatrix();
  // Undo changed settings.
  glDisable(GL_BLEND);
  glCullFace(GL_BACK); glDisable(GL_CULL_FACE);
  glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  leglBindTexture(NULL);
 }
}
}

 

 

/*
GWEN
Copyright (c) 2011 Facepunch Studios
See license in Gwen.h
*/
#ifndef GWEN_INPUT_LEADWERKS_H
#define GWEN_INPUT_LEADWERKS_H
#include "Gwen/InputHandler.h"
#include "Gwen/Gwen.h"
#include "Gwen/Controls/Canvas.h"
#include <engine.h>
namespace Gwen
{
namespace Input
{
 class Leadwerks
 {
  public:
Leadwerks()
{
 m_Canvas = NULL;
 m_MouseX = 0;
 m_MouseY = 0;
 m_MouseZ = 0;
 m_LMouseDown = false;
 m_RMouseDown = false;
 m_MMouseDown = false;
}
void Initialize( Gwen::Controls::Canvas* c )
{
 m_Canvas = c;
}
bool ProcessMessage( void )
{
 if ( !m_Canvas ) return false;
 if( m_MouseX != LE::MouseX() ||
  m_MouseY != LE::MouseY() )
 {
  int dx = LE::MouseX() - m_MouseX;
  int dy = LE::MouseY() - m_MouseY;
  m_MouseX = LE::MouseX();
  m_MouseY = LE::MouseY();
  return m_Canvas->InputMouseMoved( LE::MouseX(), LE::MouseY(), dx, dy );
 }
 //TODO:: Charatcer input
 if( m_MouseZ != LE::MouseZ() )
 {
  int dz = LE::MouseZ() - m_MouseZ;
  return m_Canvas->InputMouseWheel( dz );
 }
 if( m_LMouseDown != LE::MouseDown( LE::MOUSE_LEFT ) )
 {
  m_LMouseDown = LE::MouseDown( LE::MOUSE_LEFT );
  return m_Canvas->InputMouseButton( 0, m_LMouseDown );
 }
 if( m_RMouseDown != LE::MouseDown( LE::MOUSE_RIGHT ) )
 {
  m_RMouseDown = LE::MouseDown( LE::MOUSE_RIGHT );
  return m_Canvas->InputMouseButton( 1, m_RMouseDown );
 }
 if( m_MMouseDown != LE::MouseDown( LE::MOUSE_MIDDLE ) )
 {
  m_MMouseDown = LE::MouseDown( LE::MOUSE_MIDDLE );
  return m_Canvas->InputMouseButton( 2, m_MMouseDown );
 }
 //KEY INPUT
 if( LE::KeyHit( LE::KEY_RSHIFT ) ||
  LE::KeyHit( LE::KEY_LSHIFT ) )
 {
  bool down = LE::KeyDown( LE::KEY_RSHIFT ) || LE::KeyDown( LE::KEY_LSHIFT );
  return m_Canvas->InputKey( Gwen::Key::Shift, down );
 }
 if( LE::KeyHit( LE::KEY_ENTER ) )
 {
  bool down = LE::KeyDown( LE::KEY_ENTER );
  return m_Canvas->InputKey( Gwen::Key::Return, down );
 }
 if( LE::KeyHit( LE::KEY_BACKSPACE ) )
 {
  bool down = LE::KeyDown( LE::KEY_BACKSPACE );
  return m_Canvas->InputKey( Gwen::Key::Backspace, down );
 }
 if( LE::KeyHit( LE::KEY_DELETE ) )
 {
  bool down = LE::KeyDown( LE::KEY_DELETE );
  return m_Canvas->InputKey( Gwen::Key::Delete, down );
 }
 if( LE::KeyHit( LE::KEY_LEFT ) )
 {
  bool down = LE::KeyDown( LE::KEY_LEFT );
  return m_Canvas->InputKey( Gwen::Key::Left, down );
 }
 if( LE::KeyHit( LE::KEY_RIGHT ) )
 {
  bool down = LE::KeyDown( LE::KEY_RIGHT );
  return m_Canvas->InputKey( Gwen::Key::Right, down );
 }
 if( LE::KeyHit( LE::KEY_TAB ) )
 {
  bool down = LE::KeyDown( LE::KEY_TAB );
  return m_Canvas->InputKey( Gwen::Key::Tab, down );
 }
 if( LE::KeyHit( LE::KEY_SPACE ) )
 {
  bool down = LE::KeyDown( LE::KEY_SPACE );
  return m_Canvas->InputKey( Gwen::Key::Space, down );
 }
 if( LE::KeyHit( LE::KEY_HOME ) )
 {
  bool down = LE::KeyDown( LE::KEY_HOME );
  return m_Canvas->InputKey( Gwen::Key::Home, down );
 }
 if( LE::KeyHit( LE::KEY_END ) )
 {
  bool down = LE::KeyDown( LE::KEY_END );
  return m_Canvas->InputKey( Gwen::Key::End, down );
 }
 if( LE::KeyHit( LE::KEY_RCONTROL ) ||
  LE::KeyHit( LE::KEY_LCONTROL ) )
 {
  bool down = LE::KeyDown( LE::KEY_RCONTROL ) ||
   LE::KeyDown( LE::KEY_LCONTROL );
  return m_Canvas->InputKey( Gwen::Key::Control, down );
 }
 if( LE::KeyHit( LE::KEY_UP ) )
 {
  bool down = LE::KeyDown( LE::KEY_UP );
  return m_Canvas->InputKey( Gwen::Key::Up, down );
 }
 if( LE::KeyHit( LE::KEY_DOWN ) )
 {
  bool down = LE::KeyDown( LE::KEY_DOWN );
  return m_Canvas->InputKey( Gwen::Key::Down, down );
 }
 return false;
}
protected:
 Gwen::Controls::Canvas* m_Canvas;
 int m_MouseX;
 int m_MouseY;
 int m_MouseZ;
 bool m_LMouseDown;
 bool m_RMouseDown;
 bool m_MMouseDown;
 };
}
}
#endif

 

2d9e6vn.jpg

 

Big thanks to Masterxilo who wrote the OpenGL tutorial over here.

Blog & Portfolio

 

Current project: moon.chase.star

Link to comment
Share on other sites

Thanks for this! I'll have a go with it. By the way, what do you need to name the 3 different bits of code you provided? Like *.cpp or *.h

Win7 64bit, Leadwerks SDK 2.5, Visual Studio 2012, 3DWS, 3ds Max, Photoshop CS5.

 

 

 

Life is too short to remove USB safely.

Link to comment
Share on other sites

I like this because he uses the same event styles I use. This is a very nice and clean way to do events. No polling!

 

    Button* pQuitButton= new Button( this );
    pQuitButton->onPress.Add( this, &MyDerivedControl::OnQuit );

 

 

@Smash, could you package this up in a zip file and attach it to the post if possible? Just a little cleaner than scrapping the site. Big thanks for doing this!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...