Jump to content
celludriel

Is custom GUI element creation possible ?

Recommended Posts

I'm working on a custom gametype at the moment where I want to display some data on the screen visually.  I have a global variable that can range from -100 to 100.  With zero being the nilpoint I like to represent this variable visually like this (but shouldn't be exactly like this)

 

In this one the players are winning and the score seems to be around 75

 

winning.png

In this one the players lost a few missions and the AI is winning the mission the score is probably around -65

losing.png

I would like to show this bar then somewhere on top of the screen, and who knows if possible, give the player the option to move the bar anywhere on the screen.

 

I'm just wondering is this possible and if so, could you help me point me to the right tutorials or give some pointers ?

 

Thanks in advance

Share this post


Link to post
Share on other sites

Oh boy, (for me) this is a difficult one to answer in a clear and simple way.

 

If I was creating this I would create that yellow bar separately from the blue/red bars by using a dialog.  This gives  the red/blue bars freedom to move around.

So first I would permanently display the yellow bar on the players screen using a display, and then I would have a blue/red bar (depending on the points) that would move X coordinates to fit where it needed to be. I imagine a lot of this would involve a fair amount of trial and error.

 

Here is an example of something like this I did for BattleGrid

 

DisplayHud.hpp - Put " #include DisplayHud.hpp " in your description.ext

 

#define CT_STATIC         0
#define ST_LEFT           0x00
#define ST_CENTER         0x02

class KOZHUD_4
{
  idd = 1005;
  movingEnable=0;
  duration=1e+011;
  name = "KOZHUD_4_name";
  onLoad = "uiNamespace setVariable ['KOZHUD_4', _this select 0];";
onUnLoad = "uiNamespace setVariable ['KOZHUD_4', nil]";
  controlsBackground[] = {};
  objects[] = {};
class controls
{
class BG_ScreenMessageBox2: RscStructuredText
{
idc = 1100;
x = 0.38375 * safezoneW + safezoneX;
y = 0.416 * safezoneH + safezoneY;
w = 0.4125 * safezoneW;
h = 0.088 * safezoneH;
};
};
};

And once you have the above defined, you can call it/use it with a separate script.

    (_RandomNumber + 1) cutRsc ["KOZHUD_4","PLAIN"]; //Call in the cutRsc with a random layer

    _NewYPosition2 = _NewYPosition + 0.05; //I wanted to adjust the Y coordinate up by 0.05
    
    _ui = uiNamespace getVariable "KOZHUD_4"; //This actually displays what I wanted here below
    (_ui displayCtrl 1100) ctrlSetPosition [_NewXPosition,_NewYPosition2];
    (_ui displayCtrl 1100) ctrlCommit 0;     
    (_ui displayCtrl 1100) ctrlSetStructuredText (parseText format ["<t shadow='true' shadowColor='#000000'><t size='0.8'><t align='left'><t color='%2'>+%1 XP</t> </t></t></t>",_XPGained,_TextColor]);//I used ctrlsetstructredtext here. You can also just use ctrlsettext I believe.
    (_RandomNumber + 1) cutFadeOut 10; //Fade it out

So, using cutRSC you can spawn in the dialog (which doesn't take control of the players game) and then you can use cutrsc again to display the red/blue bar where you would want it by changing the X coordinate via script.

 

You can use ctrlsettext or ctrlsetstructuredtext to show images as well. So in this case, make all the bars separate pictures.

((findDisplay DGN_BaseMenu) displayCtrl 1100) ctrlSetText "\DGN_Core\ZombieScripts\Dgn_civilianplayer\Pictures\GasMask.paa";  
  • Like 2

Share this post


Link to post
Share on other sites

Just to spark some solutions, maybe use the Dialog "Progress Bar" and use :

_control progressSetPosition 0.01; //ranges from 0 to 1

You can have the background red or blue, and the progress bar red or blue.  ;)

 

 

More info on the dialog and setup here: 

 

https://community.bistudio.com/wiki/DialogControls-ProgressBar

 

 

I would also like to point out that there are differences between dialogs and UI. Dialogs are menus which basically keeps the player in idle, but UI displays while the player is moving. (much like KOTH)

 

Sadly, though, there is no solution (yet...) for how BI have done it with their inventory, but for your case the UI seems to be an appropriate approach.

 

 

Hell, I'm going to be generous and post an already made one for you:  :P (note this is for UI)

 

progress.hpp:

class ProgressBaseTextHUD
{
	access = 0;
	type = CT_STATIC;
	style = ST_CENTER;
	idc = -1;
	colorBackground[] = {0,0,0,0};
	colorText[] = {1,1,1,0.8};
	text = "";
	fixedWidth = 0;
	x = 0;
	y = 0;
	h = 0;
	w = 0;
	shadow = 2;
	font = "puristaMedium";
	sizeEx = "0.035";  
};
class RscProgressBar 
{
	type = 8;
	style = 0;
	x = 0.344;
	y = 0.619;
	w = 0.313726;
	h = 0.0261438;
	texture = "";
	shadow = 2;
	colorFrame[] = {0, 0, 0, 1};
	colorBackground[] = {0,0,0,0.7};
	colorBar[] = {"(profilenamespace getvariable ['GUI_BCG_RGB_R',0.3843])", "(profilenamespace getvariable ['GUI_BCG_RGB_G',0.7019])", "(profilenamespace getvariable ['GUI_BCG_RGB_B',0.8862])", "(profilenamespace getvariable ['GUI_BCG_RGB_A',0.7])"};
};
class MyProgressBar
{
	name = "MyProgressBar";
	idd = 37200;
	fadein=0;
	duration = 99999999999;
	fadeout=0;
	movingEnable = 0;
	onLoad = "uiNamespace setVariable ['PBarProgress',_this select 0];";
	class Controls
	{
		class background: ProgressBaseTextHUD
		{
			idc = 37201;

			x = 0.292948 * safezoneW + safezoneX;
			y = 0.72101 * safezoneH + safezoneY;
			w = 0.65; h = 0.05;
			colorBackground[] = {0,0,0,0.7};
		};
		class Progress: RscProgressBar
		{
			idc = 37202;

			x = 0.292948 * safezoneW + safezoneX;
			y = 0.72101 * safezoneH + safezoneY;
			w = 0.65; h = 0.05;
		};
		class ProgressText: ProgressBaseTextHUD
		{
			idc = 37203;
	
			text = "$STR_DIALOG_PROGRESS_FUEL";
			x = 0.420365 * safezoneW + safezoneX;
			y = 0.72101 * safezoneH + safezoneY;
			w = 0.286687 * safezoneW;
			h = 0.0340016 * safezoneH;
		};
	};
};

description.ext or config.cpp:

class RscTitles
{
	#include "progress.hpp"
};
  • Like 2

Share this post


Link to post
Share on other sites

Thanks guys,for the conceptual and actual stuff.  I'm learning a lot from it.  I was thinking the same thing that I had two bars to content with.  The background bar with a width of 210% and then the moving bars with a width of 100% but different x offsets.  I just didn't know how to get this started. 

 

The progressbar approach is very creative, I hadn't even considered that one yet.

 

I'm at work now but once I get home I'll try out your examples.

 

again thanks for this effort

  • Like 1

Share this post


Link to post
Share on other sites

Glad that I can help.  ;)

 

 

Also: For some more detail in case if you get stuck, here is the code to display it:

5 cutRsc ["MyProgressBar","PLAIN"];

and to set the progress' position, here is some code to get you started:  ;)

_ui = uiNamespace getVariable "PBarProgress";
_progressBar = _ui displayCtrl 37202;
_progressBar progressSetPosition 0.01; //Length of Progress bar's completion. Ranges from 0 to 1
  • Like 1

Share this post


Link to post
Share on other sites

I kinda fell asleep after work so I couldn't write it yet, but I'll see if I can get it written during my lunch break today.  When I get home I'll just have to plug it in and maybe debug a bit if I can't get it going straight away.  Thanks again though

Share this post


Link to post
Share on other sites

I finally got around to implementing the bar but I ran into a snag and don't understand how you debug these kind of errors with no information

 

18:43:59 Error loading control C:\Users\Sunspot\Documents\Arma 3\mpmissions\Tug%20Of%20War.Stratis\description.ext/RscTitles/MyProgressBar/Controls/Background/
18:43:59 Error loading control C:\Users\Sunspot\Documents\Arma 3\mpmissions\Tug%20Of%20War.Stratis\description.ext/RscTitles/MyProgressBar/Controls/ProgressText/

 

It doesn't state what line is in error or what the exception cause actually could be.  Can you give me some tips how to debug this, I've went over any typos but I'll check again just to be sure.

Share this post


Link to post
Share on other sites

I got it to work , I was missing defines.hpp containting all the static variables, this was a bitch to find out though wtihout proper logging :(

Share this post


Link to post
Share on other sites

Normally when you have problems loading GUI elements, it's because your base classes (classes that your controls are derived from) are missing some (or all, in your case) required attributes

  • Like 1

Share this post


Link to post
Share on other sites

Well this is what I have sofar

class ProgressBaseTextHUD{
	access = 0;
	type = CT_STATIC;
	style = ST_CENTER;
	idc = -1;
	colorBackground[] = {0,0,0,0};
	colorText[] = {1,1,1,0.8};
	text = "";
	fixedWidth = 0;
	x = 0;
	y = 0;
	h = 0;
	w = 0;
	shadow = 2;
	font = GUI_FONT_NORMAL;
	sizeEx = "0.035";
};

class RscProgressBar{
	type = CT_PROGRESS;
	style = ST_HORIZONTAL;
	x = 0.344;
	y = 0.619;
	w = 0.313726;
	h = 0.0261438;
	texture = "";
	shadow = 2;
	colorFrame[] = {0, 0, 0, 1};
	colorBackground[] = {0,0,0,0.7};
	colorBar[] = {"(profilenamespace getvariable ['GUI_BCG_RGB_R',0.3843])", "(profilenamespace getvariable ['GUI_BCG_RGB_G',0.7019])", "(profilenamespace getvariable ['GUI_BCG_RGB_B',0.8862])", "(profilenamespace getvariable ['GUI_BCG_RGB_A',0.7])"};
};

class WarProgressBar{
	name = "WarProgressBar";
	idd = 37200;
	fadein=0;
	duration = 99999999999;
	fadeout=0;
	movingEnable = 1;
	onLoad = "uiNamespace setVariable ['OWarProgressBar',_this select 0];";
	class Controls{
		class Background: ProgressBaseTextHUD{
			idc = 37201;

			x = 0.292948 * safezoneW + safezoneX;
			y = 0.72101 * safezoneH + safezoneY;
			w = 0.64;
			h = 0.05;
			colorBackground[] = {0,0,0,0.7};
		};
		class LoseProgress: RscProgressBar{
			idc = 37202;

			x = 0.29 * safezoneW + safezoneX;
			y = 0.72 * safezoneH + safezoneY;
			w = 0.32;
			h = 0.05;
		};
		class WinProgress: RscProgressBar{
			idc = 37203;

			text = "";
			x = 0.29 * safezoneW + safezoneX;
			y = 0.72 * safezoneH + safezoneY;
			w = 0.32;
			h = 0.05;
		};
	};
};

I just can't get x right for the winbar I have tried a few permuations of math formulas to get it right using the w of the bar, but I'm always of by a bunch of pixels either left or right.  I keep on trying but if anyone could explain the coordinate system to me that would be great.  I'm assuming the safezones are dependant on the screen resolution so that has to stay relative.

Share this post


Link to post
Share on other sites

Nice I believe I'm finsihed with it here is all the code should anyone else want to create a likewise component

defines.hpp

// Control types
#define CT_STATIC           0
#define CT_BUTTON           1
#define CT_EDIT             2
#define CT_SLIDER           3
#define CT_COMBO            4
#define CT_LISTBOX          5
#define CT_TOOLBOX          6
#define CT_CHECKBOXES       7
#define CT_PROGRESS         8
#define CT_HTML             9
#define CT_STATIC_SKEW      10
#define CT_ACTIVETEXT       11
#define CT_TREE             12
#define CT_STRUCTURED_TEXT  13
#define CT_CONTEXT_MENU     14
#define CT_CONTROLS_GROUP   15
#define CT_SHORTCUTBUTTON   16
#define CT_HITZONES         17
#define CT_XKEYDESC         40
#define CT_XBUTTON          41
#define CT_XLISTBOX         42
#define CT_XSLIDER          43
#define CT_XCOMBO           44
#define CT_ANIMATED_TEXTURE 45
#define CT_OBJECT           80
#define CT_OBJECT_ZOOM      81
#define CT_OBJECT_CONTAINER 82
#define CT_OBJECT_CONT_ANIM 83
#define CT_LINEBREAK        98
#define CT_USER             99
#define CT_MAP              100
#define CT_MAP_MAIN         101
#define CT_LISTNBOX         102
#define CT_ITEMSLOT         103
#define CT_CHECKBOX         77

// Static styles
#define ST_POS            0x0F
#define ST_HPOS           0x03
#define ST_VPOS           0x0C
#define ST_LEFT           0x00
#define ST_RIGHT          0x01
#define ST_CENTER         0x02
#define ST_DOWN           0x04
#define ST_UP             0x08
#define ST_VCENTER        0x0C

#define ST_TYPE           0xF0
#define ST_SINGLE         0x00
#define ST_MULTI          0x10
#define ST_TITLE_BAR      0x20
#define ST_PICTURE        0x30
#define ST_FRAME          0x40
#define ST_BACKGROUND     0x50
#define ST_GROUP_BOX      0x60
#define ST_GROUP_BOX2     0x70
#define ST_HUD_BACKGROUND 0x80
#define ST_TILE_PICTURE   0x90
#define ST_WITH_RECT      0xA0
#define ST_LINE           0xB0
#define ST_UPPERCASE      0xC0
#define ST_LOWERCASE      0xD0

#define ST_SHADOW         0x100
#define ST_NO_RECT        0x200
#define ST_KEEP_ASPECT_RATIO  0x800

#define ST_TITLE          ST_TITLE_BAR + ST_CENTER

// Slider styles
#define SL_DIR            0x400
#define SL_VERT           0
#define SL_HORZ           0x400

#define SL_TEXTURES       0x10

// progress bar
#define ST_VERTICAL       0x01
#define ST_HORIZONTAL     0

// Listbox styles
#define LB_TEXTURES       0x10
#define LB_MULTI          0x20

// Tree styles
#define TR_SHOWROOT       1
#define TR_AUTOCOLLAPSE   2

// MessageBox styles
#define MB_BUTTON_OK      1
#define MB_BUTTON_CANCEL  2
#define MB_BUTTON_USER    4
#define MB_ERROR_DIALOG   8

// Xbox buttons
#define KEY_XINPUT                0x00050000
#define KEY_XBOX_A                KEY_XINPUT + 0
#define KEY_XBOX_B                KEY_XINPUT + 1
#define KEY_XBOX_X                KEY_XINPUT + 2
#define KEY_XBOX_Y                KEY_XINPUT + 3
#define KEY_XBOX_Up               KEY_XINPUT + 4
#define KEY_XBOX_Down             KEY_XINPUT + 5
#define KEY_XBOX_Left             KEY_XINPUT + 6
#define KEY_XBOX_Right            KEY_XINPUT + 7
#define KEY_XBOX_Start            KEY_XINPUT + 8
#define KEY_XBOX_Back             KEY_XINPUT + 9
#define KEY_XBOX_LeftBumper       KEY_XINPUT + 10
#define KEY_XBOX_RightBumper      KEY_XINPUT + 11
#define KEY_XBOX_LeftTrigger      KEY_XINPUT + 12
#define KEY_XBOX_RightTrigger     KEY_XINPUT + 13
#define KEY_XBOX_LeftThumb        KEY_XINPUT + 14
#define KEY_XBOX_RightThumb       KEY_XINPUT + 15
#define KEY_XBOX_LeftThumbXRight  KEY_XINPUT + 16
#define KEY_XBOX_LeftThumbYUp     KEY_XINPUT + 17
#define KEY_XBOX_RightThumbXRight KEY_XINPUT + 18
#define KEY_XBOX_RightThumbYUp    KEY_XINPUT + 19
#define KEY_XBOX_LeftThumbXLeft   KEY_XINPUT + 20
#define KEY_XBOX_LeftThumbYDown   KEY_XINPUT + 21
#define KEY_XBOX_RightThumbXLeft  KEY_XINPUT + 22
#define KEY_XBOX_RightThumbYDown  KEY_XINPUT + 23

// Fonts
#define GUI_FONT_NORMAL			PuristaMedium
#define GUI_FONT_BOLD			PuristaSemibold
#define GUI_FONT_THIN			PuristaLight
#define GUI_FONT_MONO			EtelkaMonospacePro
#define GUI_FONT_NARROW			EtelkaNarrowMediumPro
#define GUI_FONT_CODE			LucidaConsoleB
#define GUI_FONT_SYSTEM			TahomaB

// Grids
#define GUI_GRID_CENTER_WAbs	((safezoneW / safezoneH) min 1.2)
#define GUI_GRID_CENTER_HAbs	(GUI_GRID_CENTER_WAbs / 1.2)
#define GUI_GRID_CENTER_W		(GUI_GRID_CENTER_WAbs / 40)
#define GUI_GRID_CENTER_H		(GUI_GRID_CENTER_HAbs / 25)
#define GUI_GRID_CENTER_X		(safezoneX + (safezoneW - GUI_GRID_CENTER_WAbs)/2)
#define GUI_GRID_CENTER_Y		(safezoneY + (safezoneH - GUI_GRID_CENTER_HAbs)/2)

progress.hpp

class ProgressBaseTextHUD{
	access = 0;
	type = CT_STATIC;
	style = ST_CENTER;
	idc = -1;
	colorBackground[] = {0,0,0,0};
	colorText[] = {1,1,1,0.8};
	text = "";
	fixedWidth = 0;
	x = 0;
	y = 0;
	h = 0;
	w = 0;
	shadow = 2;
	font = GUI_FONT_NORMAL;
	sizeEx = "0.035";
};

class RscProgressBar{
	type = CT_PROGRESS;
	style = ST_HORIZONTAL;
	x = 0.344;
	y = 0.619;
	w = 0.313726;
	h = 0.0261438;
	texture = "";
	shadow = 2;
	colorFrame[] = {0, 0, 0, 1};
	colorBackground[] = {0,0,0,0.7};
	colorBar[] = {"(profilenamespace getvariable ['GUI_BCG_RGB_R',0.3843])", "(profilenamespace getvariable ['GUI_BCG_RGB_G',0.7019])", "(profilenamespace getvariable ['GUI_BCG_RGB_B',0.8862])", "(profilenamespace getvariable ['GUI_BCG_RGB_A',0.7])"};
};

class WarProgressBar{
	name = "WarProgressBar";
	idd = 37200;
	fadein=0;
	duration = 99999999999;
	fadeout=0;
	movingEnable = 1;
	onLoad = "uiNamespace setVariable ['OWarProgressBar',_this select 0];";
	class Controls{
		class LoseBackground: ProgressBaseTextHUD{
			idc = 37201;

			x = safezoneX + (safeZoneW * 0.20);
			y = safeZoneY + (safeZoneH * 0.02);
			w = 0.32 * 3 / 4;
			h = 0.05;
			colorBackground[] = {1,0,0,1};
		};
		class WinBackground: ProgressBaseTextHUD{
			idc = 37202;

			x = (safezoneX + (safeZoneW * 0.20)) + (0.32 * 3 / 4);
			y = safeZoneY + (safeZoneH * 0.02);
			w = 0.32 * 3 / 4;
			h = 0.05;
			colorBackground[] = {0,0,0,1};
		};
		class LoseProgress: RscProgressBar{
			idc = 37203;

			x = safezoneX + (safeZoneW * 0.20);
			y = safeZoneY + (safeZoneH * 0.02);
			w = 0.32 * 3 / 4;
			h = 0.05;
			colorBar[] = {0,0,0,1};
		};
		class WinProgress: RscProgressBar{
			idc = 37204;

			x = (safezoneX + (safeZoneW * 0.20)) + (0.32 * 3 / 4);
			y = safeZoneY + (safeZoneH * 0.02);
			w = 0.32 * 3 / 4;
			h = 0.05;
			colorBar[] = {0,0,1,1};
		};
	};
};

functions.sfq

if (!isDedicated) then {
	updateProgressBar = {
		diag_log format ["Calling updateProgressBar with %1", _this];
		private ["_delta"];

		_delta = _this select 0;

		disableSerialization;
		_ui = uiNamespace getVariable "OWarProgressBar";

		if(_delta >= 0) then {
			_progressBar = _ui displayCtrl 37204;
			_progressBar progressSetPosition (warProgress / 100.0);
			_progressBar = _ui displayCtrl 37203;
			_progressBar progressSetPosition 100.0;
		} else {
			_progressBar = _ui displayCtrl 37203;
			_progressBar progressSetPosition (1 + (warProgress / 100.0));
			_progressBar = _ui displayCtrl 37204;
			_progressBar progressSetPosition 0;
		};
	};
	warProgressUpdateEvent = {
		diag_log format ["Executing warProgress update event with warProgress %1", warProgress];
		[warProgress] call updateProgressBar;
		if(warProgress == 100 || warProgress == -100) then {
			sleep 2;
			diag_log format ["Cleaning progressbar"];
			5 cutText ["", "PLAIN"];
		};
	};
	initProgressBar = {
		diag_log format ["Calling initProgressBar"];
		5 cutRsc ["WarProgressBar","PLAIN"];
		[warProgress] call updateProgressBar;

		"warProgress" addPublicVariableEventHandler {
			[] call warProgressUpdateEvent;
		};
	};
};

init.sqf

if(hasInterface) then {
	diag_log format ["Client code is running for %1", {getPlayerUID player}];
	call compile preprocessFileLineNumbers "functions.sqf";

	[] call initProgressBar;
};

warProgress is the global variable that steers the entire progressbar it ranges from -100 to +100 everything minus will move to the left, and positive to the right.  I scripted my mission that it would end if it reaches either treshold but I didn't include that code here since that doesn't really matters for this topic, if you have questions just ask them I'll try my best to respond to them

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×