Jump to content

How to create custom gui/dashboard


Recommended Posts

I know there is so many topic with titles like "how to create custom gui" etc but never found how these guys are doing these good looking dashboard for example. 

So I know that I can create with built-in functions like guiCreateWindow etc. Or dxgui/thisdp's gui but then I can't make look like this (below the picture)

I want to know more about how I can create gridlist, dropdown (not with the in-built functions) and if I hover to the button then change to other image (or just add a little more light) 

spacer.png

158884413_3754874791255251_8511639522948

Link to comment

You either use a resource that already exists or create something yourself.

If you want to create something yourself, then you need a layout engine, a UI layout and a concrete UI design. If you don't know where to start, then you should first get your Lua skills up-to-speed. Then research the topics plus the mathematics behind them. After the mathematics you can go to the UI layout and design which require just applications of the layout engine. And then after all the hard work you can get to fun stuff like the pictures you have posted above.

The quality of the UI depends on the amount of care you put into the single components and their versatility.

Link to comment

If you have a problem with the big idea behind gridlist/scrollbar/dropdown then try playing around with the MTA dx functions until you get something done that converges against the idea of the UI elements that you have. I have yet to see any code from you.

To give you a hint about the math, a layout engine is typically based around the following concept: each UI element is a box with position (x,y) and a size (w,h). Children can be placed inside each element with an offset (ox,oy) so their "screen"/absolute position would be (x+ox,y+oy). This system does form a tree of UI elements.

Helpful ideas for UI element layouts:

A gridlist is a 2D matrix of rows and columns with the top row typically used for details. The rows are consecutive on the y-axis, the columns consecutive on the x-axis.

A scrollbar is a box with another box inside of it. It can be layed-out vertically or horizontally. By clicking the inner box you can move it either horizontally or vertically inside the outer box.

A dropdown is a 1D array of rows which are layed out consecutively on the y-axis.

Edited by The_GTA
  • Like 1
Link to comment
23 minutes ago, spaghetti1337 said:

Oh, well it's difficult to understand at first reading but I'll try to get the best out of myself. Thanks

Please come back at me if you have any questions during the process. I will be able to answer most of your questions.

  • Like 1
Link to comment
On 31/08/2021 at 12:38, The_GTA said:

Please come back at me if you have any questions during the process. I will be able to answer most of your questions.

Hello,

I did some research and if I'm get it right then I can "reproduce" the gridlist's scrollbar (I just needed the gridlist because of the scrollbar)

So basically, if I draw a 200x200 rectangle for example with DxDrawRectangle and add text from a table for example with GuiSetText inside the rectangle and I determine the mouse x,y position when scroll_up, scroll_down then I can create my own "gridlist" with scrollbar? or it's a "bit" harder? I found NeXuS's code which is a dx scroll... but erm I want to add a table in the DxDrawRectangle which you can scroll down and up until the last "item" in the table.

Also I know that I need the onClientKey function for the move up and down like this:
 

addEventHandler( "onClientKey", root,
	function (button, press)
		if button == "mouse_wheel_up" then
			--- scroll up
		elseif button == "mouse_wheel_down" then
			--- scroll down
		end
	end
)

 

Link to comment

@spaghetti1337 You are listing some of the key ideas about the implementation of so called "scroll panes"! A scrollpane is a rectangle connected to a vertical and a horizontal scrollbar. The scrollpane has a content rectangle in which you can place other rectangles, in your example a text display. The content of a scrollpane forms it's own UI hierarchy which has a 2D bounding box that contains all scollpane-contained UI elements. Now imagine that you put another cut-out rectangle above the bounding box that forms the "view" of the elements on the contents of the scrollpane.

Now about the mathematics: the contents of the scrollpane are based on a 2D coordinate system centered around the (0,0) point. Each contained UI element has a coordinate (x,y) and a size (w,h) inside the scrollpane content, forming a rectangle UI_rect. The combined region of all UI_rect is enclosed by the bounding box with position (cx,cy) and size (cw,ch). The scrollpane itself has a view rectangle with "position" 2D vector (vx,xy) and a "viewport size" 2D vector (vw,vh). The viewport position is linked to the progress of your scrollbars:

vx = ( cx + hscroll_progress * max( 0, cw - vw ) )
vy = ( cy + vscroll_progress * max( 0, ch - vh ) )

where the progress of each scrollbar ranges from numeric values between 0 and 1, the maximum function returns the biggest of the passed values.

If you cut the viewport rectangle with the content bounding box, you get the region of UI that should be displayed within your scrollpane viewport. The implementation is up to you.

IMPLEMENTATION NOTE: there are certain limitations in MTA's ability regarding dxDrawText that force you to use so called "render targets" for cut-out rectangles. You basically have a rectangle that functions as your scrollpane viewport and perform the drawing inside of the render-target, which will cut-out any unwanted text that clips outside the width and height that you created the render-target with. This will be important for your idea.

Edited by The_GTA
Link to comment
4 hours ago, The_GTA said:

@spaghetti1337 You are listing some of the key ideas about the implementation of so called "scroll panes"! A scrollpane is a rectangle connected to a vertical and a horizontal scrollbar. The scrollpane has a content rectangle in which you can place other rectangles, in your example a text display. The content of a scrollpane forms it's own UI hierarchy which has a 2D bounding box that contains all scollpane-contained UI elements. Now imagine that you put another cut-out rectangle above the bounding box that forms the "view" of the elements on the contents of the scrollpane.

Now about the mathematics: the contents of the scrollpane are based on a 2D coordinate system centered around the (0,0) point. Each contained UI element has a coordinate (x,y) and a size (w,h) inside the scrollpane content, forming a rectangle UI_rect. The combined region of all UI_rect is enclosed by the bounding box with position (cx,cy) and size (cw,ch). The scrollpane itself has a view rectangle with "position" 2D vector (vx,xy) and a "viewport size" 2D vector (vw,vh). The viewport position is linked to the progress of your scrollbars:

vx = ( cx + hscroll_progress * max( 0, cw - vw ) )
vy = ( cy + vscroll_progress * max( 0, ch - vh ) )

where the progress of each scrollbar ranges from numeric values between 0 and 1, the maximum function returns the biggest of the passed values.

If you cut the viewport rectangle with the content bounding box, you get the region of UI that should be displayed within your scrollpane viewport. The implementation is up to you.

IMPLEMENTATION NOTE: there are certain limitations in MTA's ability regarding dxDrawText that force you to use so called "render targets" for cut-out rectangles. You basically have a rectangle that functions as your scrollpane viewport and perform the drawing inside of the render-target, which will cut-out any unwanted text that clips outside the width and height that you created the render-target with. This will be important for your idea.

Okay I think this is hard for me with my current lua "skill" :D so I decided to use an external dxlib, I'll try DGS but then I can't combine the default gui with this dxlib?

function showDashBoard ()
        if showdashboard == true then
	    dxDrawRectangle(screenW * 0.2130, screenH * 0.1676, screenW * 0.5745, screenH * 0.6648, tocolor(47, 45, 47, 255), false)
        loadstring(exports.dgs:dgsImportFunction())()
		local gridlist = dgsCreateGridList(screenW * 0.2443, screenH * 0.2241, screenW * 0.1313, screenH * 0.2148,false)
		dgsGridListAddColumn(gridlist,"test1",0.4)
                dgsGridListAddColumn(gridlist,"test2",0.4)
		for i=1,20 do
		local row = dgsGridListAddRow(gridlist)
		dgsGridListSetItemText(gridlist,row,1,i)
		dgsGridListSetItemText(gridlist,row,2,i-1)
		end
	end
end
addEventHandler ( "onClientRender", root, showDashBoard )

Because if I combine them in this way I can't scroll the gridlist and so laggy... (and the gridlist doesn't disappear when I close the dashboard)

Link to comment

I am no user of DGS but you are not supposed to create UI elements or load the DGS environment variables every frame. I have no idea what you are trying to do, but try this?

loadstring(exports.dgs:dgsImportFunction())()
local gridlist = dgsCreateGridList(screenW * 0.2443, screenH * 0.2241, screenW * 0.1313, screenH * 0.2148,false)
dgsGridListAddColumn(gridlist,"test1",0.4)
dgsGridListAddColumn(gridlist,"test2",0.4)
for i=1,20 do
    local row = dgsGridListAddRow(gridlist)
    dgsGridListSetItemText(gridlist,row,1,i)
    dgsGridListSetItemText(gridlist,row,2,i-1)
end
-- TODO: hide the gridlist if showdashboard == false
-- TODO: show the gridlist if you set showdashboard to true

function showDashBoard ()
    if showdashboard == true then
        dxDrawRectangle(screenW * 0.2130, screenH * 0.1676, screenW * 0.5745, screenH * 0.6648, tocolor(47, 45, 47, 255), false)
    end
end
addEventHandler ( "onClientRender", root, showDashBoard )

DGS comes with it's own rendering code which runs every frame. You have to consult the manuals of the resource if you want to know about customization.

Edited by The_GTA
Link to comment
23 hours ago, The_GTA said:

I am no user of DGS but you are not supposed to create UI elements or load the DGS environment variables every frame. I have no idea what you are trying to do, but try this?

loadstring(exports.dgs:dgsImportFunction())()
local gridlist = dgsCreateGridList(screenW * 0.2443, screenH * 0.2241, screenW * 0.1313, screenH * 0.2148,false)
dgsGridListAddColumn(gridlist,"test1",0.4)
dgsGridListAddColumn(gridlist,"test2",0.4)
for i=1,20 do
    local row = dgsGridListAddRow(gridlist)
    dgsGridListSetItemText(gridlist,row,1,i)
    dgsGridListSetItemText(gridlist,row,2,i-1)
end
-- TODO: hide the gridlist if showdashboard == false
-- TODO: show the gridlist if you set showdashboard to true

function showDashBoard ()
    if showdashboard == true then
        dxDrawRectangle(screenW * 0.2130, screenH * 0.1676, screenW * 0.5745, screenH * 0.6648, tocolor(47, 45, 47, 255), false)
    end
end
addEventHandler ( "onClientRender", root, showDashBoard )

DGS comes with it's own rendering code which runs every frame. You have to consult the manuals of the resource if you want to know about customization.

Okay, I chosen this one https://github.com/t3wz/dxGridlists , this is works.

I can scroll inside the gridlist but doesn't have a scrollbar can you take a look inside that code and help me out please? and I want to display the items like every second item color is light gray and other ones is a bit darker you can see what I mean below:

spacer.png 

Link to comment

I can surely help you with the coloring question. For that you should create a local copy of the code inside your MTA resource project and modify it in the following way:

Insert this at the top:

local colors_cicled =
{
    tocolor( 80, 80, 80, 200 ),
    tocolor( 110, 110, 110, 200 )
};

Then go to line 317 and replace it with the following:

dxDrawText ( cData[iIndex]["text"], x, y, cData.info.width + x, ( 30 % data.h ) + y, colors_cicled[ ( ( iIndex - 1 ) % #colors_cicled ) + 1 ], FIT_MODE and ( 1 * SCALE ) or 1, "default-bold", "center", "center", true, true, data.pg, false, true );

About your other demand: I refuse to do it for free, the code does resemble more of an artistic masterpiece than a scientifically authenticable work.

Edited by The_GTA
  • Like 1
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...