Jump to content
  • entries
    15
  • comments
    50
  • views
    25,703

Abstract All The Things!!!


Einlander

2,179 views

 Share

It's been a while since I last posted an update on my lua based GUI. That was the second time that I have rewrote it. Now I'm on my third rewrite. This time the reason is that I am using the Lua OOP module Averice has made available. My GUI was already object oriented but it was messy to code. Now it looks sensible and has much less code.

 

I have no pretty images to show but I will detail some of the major structural changes and concepts that i have employed.

 

I no longer use the require keyword. I use the import command now since it plays better with the lua sandbox and can be used in the workshop games

 

Window Manager Changes

If you have followed the development of this gui, you may already know that there is a window manager that controls all the states of the windows. This was so that programmers can have multiple window managers that have different interfaces (think game menu gui, and in-game computer interfaces). Now there a window manager manager (collect all the things!). This allows the programmer to have a system that will manager and update all of the window managers autonomously if they so choose.

 

Drawing

Before, each component (windows, buttons, etc..), did their own drawing. This was fine for the most part, but this limited me to the Leadwerks line and box command. Now I use
to allow me to draw whatever shape I want to. There is an almost negligible performance hit, since it has to process the shape and scan-line draw the image. This will also allow me to use the point in polygon algorithm to select items, creating the possibility of selecting non square objects with the mouse.

 

Abstraction

Along with changing the drawing, I have abstracted all drawing to a single class. This class contains all the drawing and text commands that the gui uses. This makes the gui more portable and if Leadwerks changes something there will only be one location to change them instead of multiple places.

 

The rewrite should take substantially less time, and with the new class system adding components should be easier and faster.

  • Upvote 2
 Share

2 Comments


Recommended Comments

Along with changing the drawing, I have abstracted all drawing to a single class. This class contains all the drawing and text commands that the gui uses. This makes the gui more portable and if Leadwerks changes something there will only be one location to change them instead of multiple places.

 

What does this mean for users extending the library and adding their own controls? They have to modify this 1 drawing class that draws all controls? Are you drawing each control that you have inside this 1 class? If so I would rethink that approach as it'll make extending your library for the user a little more complicated and not self contained. Imagine if I want to add a control. I have to tell the users to alter their 1 drawing class to get my control to work? Instead if all my controls drawing is done in it's own class then all I have to do is give the user my class file. They aren't required to modify this 1 draw class at all.

 

To me it sounds like you've already extracted the LE portion in your 2d polygons post you linked to (paintPoly). Seems to me those are the only LE commands that would need to be changed for whatever library you used. Normally you'd want to turn that into it's own (driver) class. You'd create some base class for "GfxDrivers" and then you'd make an LEGfxDriver that has the specific LE stuff in it. Then to make it work for other libraries you'd just make a new Driver class for that library. These driver classes are abstracting the actual libraries drawing commands (could make input drivers as well for processing input).

 

You then put each control's drawing in it's own class. For example you make a TextBox class that uses the generic gfx driver interface (but the specific driver that you setup to use at the start) to draw itself. That's really the abstraction you want I believe. Placing all control's drawing into 1 class isn't really abstraction. It's just lumping everything together.

 

class "GfxDriver"

-- in Lua we don't really need to do this to override it but it's nice to have this to show what we are doing. we are defining an interface that ALL specific gfx drivers must implement

function GfxDriver:PaintPoly()
end

class "LEGfxDriver" : extends "GfxDriver"

function LEGfxDriver:PaintPoly()
-- this is where specific LE commands go
end


-- then at the start of the users app they set which specific gfx driver they want to use

leGfx = new "LEGfxDriver"
GUI:SetGfxDriver(leGfx)

-- a look at possibly how to define controls

class "TextBox" : extends "Control"

function TextBox:Draw(gfx)
-- our GUI system will pass in the current gfx driver to each controls draw function. as you can see when I make the control I don't care what gfx driver gets used. all that needs to happen is each gfx driver needs to have the same methods/properties in order for this to work. this is the contract
gfx:PaintPoly(...)
end

 

This is abstraction and self containment. Each control is it's own contained logic. I can just give anyone my control's lua file and they can use it with no modification.

Link to comment

I see where the confusion is.

 

I have a class:

class "SGUIWindow"

That defines the window container. All gui componets have something like this.

 

In each gui component i have a Draw method:

 

function SGUIWindow:Draw()
--Draw from bottom to the top
--draw window body
local WindowDraw = new "SGUIDraw"
WindowDraw:PaintPolygon(self.objectshape, self.properties.x, self.properties.y, {self.properties.color.windowbody[1],self.properties.color.windowbody[2],self.properties.color.windowbody[3],self.properties.color.windowtransparancy})
--Draw Window Contents
--Draw Window Chrome
end

 

This would draw all the window itself. Instead of any of the components calling the leadwerks drawing features, It calls the class SGUIDraw.

 

In SGUIDraw all the drawing is done. To draw a line, I would use this code

 

function SGUIDraw:Line(x1,y1,x2,y2,ColorAsRGBATable)
--In Leadwerks to not inturupt the set modes you need to remember it, change it, then set it back
--This method should not cause any problems in other engines
local TempContext = Context:GetCurrent()
local tempblendmode = TempContext:GetBlendMode()
local oldcolor = SGUIDraw:GetCurrentColor()
SGUIDraw:SetColor(ColorAsRGBATable)
TempContext:DrawLine(x1,y1,x2,y2)
SGUIDraw:SetColor(Vec4(oldcolor.r,oldcolor.g,oldcolor.b,255)) 
end

 

If I were to move this to another engine that would be the only function that I would change.

 

So to condense it all, Each gui object is a class, that has its own self draw method, which uses an abstracted drawing command, which is mapped to the engines drawing command.

Link to comment
Guest
Add a comment...

×   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.

×
×
  • Create New...