Jump to content
R3vo

Creating combo box attribute in 3den

Recommended Posts

Hey folks,

has anyone yet created a combo box for a custom attribute or similar? I can't wrap my mind around it.

class Attributes // Attribute UI controls are placed in this pre-defined class
{
    // Base class templates
    class Default; // Empty template with pre-defined width and single line height
    class Title: Default {class Title;}; // Two-column template with title on the left and space for content on the right
    class TitleWide: Default {class Title;}; // Template with full-width single line title and space for content below it
    class combo;
    // Your attribute class
    class test: Combo
    {
        // Expression called when the control is loaded, used to apply the value
        // Passed params are: _this - control, _value - saved value
        attributeLoad = "_control = (_this controlsGroupCtrl 100); if (lbSize _control == 0) then {{;_control lbAdd _x; lbSetData [_control, _forEachIndex, _x];} forEach ['TEXT_1','TEXT_2'];};";
        // Expression called when attributes window is closed and changes confirmed. Used to save the value.
        // Passed param: _this - control
        attributeSave =    "_ctrl = (_this controlsGroupCtrl 100);_value = _ctrl lbData (lbCurSel _ctrl);";
        // List of controls, structure is the same as with any other controls group
        // Static items
        class Items
        {
            class None
            {
                text = "None";
                data = "";
            };
        };
        // Dynamically loaded items
        class ItemsConfig
        {
            path[] = {"CfgNotifications"}; // Path to config container
            localConfig = 1; // 1 to search local Description.ext as well
            // Name of the property which will be used for item text
            propertyText = "title";
            // Name of the property which will be used for item right text
            propertyTextRight = "description";
            // Name of the property which will be used for item picture
            propertyPicture = "iconPicture";
            // Name of the property which will be used for item text color
            propertyColor = "color";
        };
    };
};

That's what I got so far, well, that's basically just copied from the wiki.

 

My main problem is, that the box is not returning the _value.

 

Any help is apprechiated.

 

Share this post


Link to post
Share on other sites

I have not done any tests yet, ive only just started reading through the documentation but from what ive read so far i presume it to look like this. Using an Object Attribute as an example.

// Include Eden Editor UI macros
// For attributes, you'll be interested in these:
// ATTRIBUTE_TITLE_W - title width
// ATTRIBUTE_CONTENT_W - content width
#include "\a3\3DEN\UI\macros.inc"

// Inherit base classes
class ctrlCombo;

class Cfg3DEN
{
	// Configuration of all objects
	class Object
	{
		// Categories collapsible in "Edit Attributes" window
		class AttributeCategories
		{
			// Category class, can be anything
			class MyCategory
			{
				displayName = "My Test Combo"; // Category name visible in Edit Attributes window
				collapsed = 1; // When 1, the category is collapsed by default
				class Attributes
				{
					// Attribute class, can be anything
					class MyAttribute
					{
						//--- Mandatory properties
						displayName = "Test Combo"; // Name assigned to UI control class Title
						tooltip = "Test Combo"; // Tooltip assigned to UI control class Title
						property = "TestCombo"; // Unique config property name saved in SQM
						control = "testCombo"; // UI control base class displayed in Edit Attributes window, points to Cfg3DEN >> Attributes

						// Expression called when applying the attribute in Eden and at the scenario start
						// Entity is passed as _this, value is passed as _value, property name is passed as _property
						// %s is replaced by attribute config name. It can be used only once in the expression
						// In MP scenario, the expression is called only on server.
						expression = "_this setVariable [%s,_value];";

						// Expression called when custom property is undefined yet (i.e., when setting the attribute for the first time)
						// Entity is passed as _this
						// Returned value is the default value
						// Used when no value is returned, or when it's of other type than NUMBER, STRING or ARRAY
						// Custom attributes of logic entities (e.g., modules) are saved always, even when they have default value
						defaultValue = "1";

						//--- Optional properties
						unique = 0; // When 1, only one entity of the type can have the value in the mission (used for example for variable names or player control)
						validate = "none"; // Validate the value before saving. Can be "none", "expression", "condition", "number" or "variable"
						condition = "object"; // Condition for attribute to appear (see the table below)
						typeName = "STRING"; // Defines data type of saved value, can be STRING, NUMBER or BOOL. Used only when control is "Combo", "Edit" or their variants
					};
				};
			};
		};
	};

	class Attributes // Attribute UI controls are placed in this pre-defined class
	{
		// Base class templates
		class Default; // Empty template with pre-defined width and single line height
		class Title: Default {class Title;}; // Two-column template with title on the left and space for content on the right
		class TitleWide: Default {class Title;}; // Template with full-width single line title and space for content below it

		// Your attribute class
		class testCombo : Title
		{
			// Expression called when the control is loaded, used to apply the value
			// Passed params are: _this - control, _value - saved value
			attributeLoad = "\
				_ctrl = (_this controlsGroupCtrl 100);\
				for '_i' from 0 to ( lbSize _ctrl ) -1 do {\
					if ( _ctrl lbData _i == _value ) exitwith {\
						_ctrl lbSetCurSel _i;\
					};\
				};\
			";
			// Expression called when attributes window is closed and changes confirmed. Used to save the value.
			// Passed param: _this - control
			attributeSave =    "_ctrl = (_this controlsGroupCtrl 100); _ctrl lbData (lbCurSel _ctrl);";

			// List of controls, structure is the same as with any other controls group
			// Static items
			class Controls {
				class Title: Title{}; // Inherit existing title control. Text of any control with class Title will be changed to attribute displayName
				class Value: ctrlCombo
				{
					idc = 100;

					// Static items
					class Items
					{
						class TEXT_1
						{
							text = "TEXT_1";
							data = "1";
							default = 0;
						};
						class TEXT_2
						{
							text = "TEXT_2";
							data = "2";
						};
					};
					class ItemsConfig
					{
						path[] = {"CfgTestCombo"}; // Path to config container
						localConfig = 1; // 1 to search local Description.ext as well
						// Name of the property which will be used for item text
						propertyText = "title";
						// Name of the property which will be used for data
						propertyData = "data";
					};
				};
			};
		};
	};
};
Although you may find you need some position or height defines for the control.

And any dynamically loaded from the description...

Description.ext

class CfgTestCombo {
	class TEXT_3 {
		title = "TEXT_3";
		data = "3";
	};
	class TEXT_4 {
		title = "TEXT_4";
		data = "4";
	};
};

Share this post


Link to post
Share on other sites

Nope, that unfortunately doesn't work, some classes are undefined.

 

But actually, it should not be that difficult. I mean, we already have the pre-configured attribute class combo. Shouldn't it be possible to simply create a new class by inheriting from class combo? Then just changing the code or value entries?

Share this post


Link to post
Share on other sites

But actually, it should not be that difficult. I mean, we already have the pre-configured attribute class combo. Shouldn't it be possible to simply create a new class by inheriting from class combo? Then just changing the code or value entries?

Which from the documentation is what

class ctrlCombo;

class Value: ctrlCombo
should be doing.

 

Nope, that unfortunately doesn't work, some classes are undefined.

What exactly is it complaining about?

To late in the evening for me but ill try some tests out tomorrow.

Share this post


Link to post
Share on other sites

 

What exactly is it complaining about?

To late in the evening for me but ill try some tests out tomorrow.

 

 

 

 

Class title seems to be undefined once you start up eden and open up the attribute.

 

I am not gonna bother with it anymore today, gonna look into it again tomorrow.

Share this post


Link to post
Share on other sites

Here's a small popup combo box script I built

 

Config.cpp

class cfgPatches HERE

class CfgFunctions {
	class Lootpos {
		class init {
			file = "lootpos\init";
			class init {
				postInit = 1;
			};
		};
	};
};
////////////////////////////////////////////////////////
// GUI EDITOR OUTPUT START (by Patrix, v1.063, #Nazibi)
////////////////////////////////////////////////////////

class IGUIBack;
class RscCombo;
class RscText;
class RscButtonMenuOK;

class popup 
{
	idd=983475;
	class controlsBackground 
	{
		class Background: IGUIBack
		{
			idc = 2200;
			x = 0.37625 * safezoneW + safezoneX;
			y = 0.291 * safezoneH + safezoneY;
			w = 0.2475 * safezoneW;
			h = 0.121 * safezoneH;
		};
	};
	class controls 
	{
		class combobox: RscCombo
		{
			idc = 2100;
			x = 0.386562 * safezoneW + safezoneX;
			y = 0.346 * safezoneH + safezoneY;
			w = 0.226875 * safezoneW;
			h = 0.022 * safezoneH;
		};
		class instructions: RscText
		{
			idc = 1000;
			text = "Select building category"; //--- ToDo: Localize;
			x = 0.381406 * safezoneW + safezoneX;
			y = 0.313 * safezoneH + safezoneY;
			w = 0.232031 * safezoneW;
			h = 0.022 * safezoneH;
		};
		class okButton: RscButtonMenuOK
		{
			x = 0.448438 * safezoneW + safezoneX;
			y = 0.379 * safezoneH + safezoneY;
			w = 0.103125 * safezoneW;
			h = 0.022 * safezoneH;	
			onButtonClick = "call popupclose;";
		};
	};
};

init\fn_init.sqf

 

catList = ["Tourist","Military","Medical","VehicleService","CivillianLowerClass","CivillianUpperClass","Shop","Industrial"];

//Script called on ok button click
popupclose = {
	_combobox = (findDisplay 983475) displayCtrl 2100;
	_sel = lbCurSel _combobox;
	ComboboxValue = _combobox lbText _sel;
};

//this script create the dialog and fill it.
//the filling part could be called By Onload of the dialog.
_ok = createDialog "popup";
_combobox = (findDisplay 983475) displayCtrl 2100;
{_combobox lbAdd _x} forEach catList;

PS: that could would only work in an addon, not a mission, since in mission file you somehow can't inherit from arma 3 classes.

Share this post


Link to post
Share on other sites

Here is as far as ive got today after hours of messing with it.

// Include Eden Editor UI macros
// For attributes, you'll be interested in these:
// ATTRIBUTE_TITLE_W - title width
// ATTRIBUTE_CONTENT_W - content width
#include "\a3\3DEN\UI\macros.inc"

// Inherit base classes
class ctrlCombo;
class ctrlStatic;

class Cfg3DEN
{

	// Configuration of all objects
	class Object
	{
		// Categories collapsible in "Edit Attributes" window
		class AttributeCategories
		{
			// Category class, can be anything
			class MyCategory
			{
				displayName = "My Test Combo"; // Category name visible in Edit Attributes window
				collapsed = 1; // When 1, the category is collapsed by default
				class Attributes
				{
					// Attribute class, can be anything
					class MyAttribute
					{
						//--- Mandatory properties
						displayName = "Test Combo"; // Name assigned to UI control class Title
						tooltip = "Test Combo"; // Tooltip assigned to UI control class Title
						property = "TestCombo"; // Unique config property name saved in SQM
						control = "testCombo"; // UI control base class displayed in Edit Attributes window, points to Cfg3DEN >> Attributes

						// Expression called when applying the attribute in Eden and at the scenario start
						// Entity is passed as _this, value is passed as _value, property name is passed as _property
						// %s is replaced by attribute config name. It can be used only once in the expression
						// In MP scenario, the expression is called only on server.
						expression = "\
							_this setvariable [ 'TestCombo', _value ];\
							systemchat str _property;\
						";//_this setVariable [_property,_value];

						// Expression called when custom property is undefined yet (i.e., when setting the attribute for the first time)
						// Entity is passed as _this
						// Returned value is the default value
						// Used when no value is returned, or when it's of other type than NUMBER, STRING or ARRAY
						// Custom attributes of logic entities (e.g., modules) are saved always, even when they have default value
						defaultValue = "_this getvariable [ 'TestCombo', '2' ]";

						//--- Optional properties
						unique = 0; // When 1, only one entity of the type can have the value in the mission (used for example for variable names or player control)
						validate = "none"; // Validate the value before saving. Can be "none", "expression", "condition", "number" or "variable"
						condition = "object"; // Condition for attribute to appear (see the table below)
						typeName = "STRING"; // Defines data type of saved value, can be STRING, NUMBER or BOOL. Used only when control is "Combo", "Edit" or their variants
					};
				};
			};
		};
	};

	class Attributes // Attribute UI controls are placed in this pre-defined class
	{
		// Base class templates
		class Default; // Empty template with pre-defined width and single line height
		class Title: Default{}; // Two-column template with title on the left and space for content on the right
		class TitleWide: Default{}; // Template with full-width single line title and space for content below it

		// Your attribute class
		class testCombo : Title
		{
			// Expression called when the control is loaded, used to apply the value
			// Passed params are: _this - control, _value - saved value
			attributeLoad = "\
				systemchat str _config;\
				_ctrl = _this controlsGroupCtrl 100;\
				_attCtrl = getText( _config >> 'control' );\
				_staticItemsCfg = configFile >> 'Cfg3DEN' >> 'Attributes' >> _attCtrl >> 'Controls' >> 'Value' >> 'items';\
				\
				_fnc_setValues = {\
					private [ '_index' ];\
					params[ '_path', [ '_apply', true ] ];\
					{\
						_cfg = _x;\
						if ( _apply ) then {\
							_index = _ctrl lbAdd getText( _cfg >> 'text' );\
							_ctrl lbSetData [ _index, getText( _cfg >> 'data' ) ];\
						}else{\
							_index = _foreachindex;\
						};\
						if ( !( _value isEqualType '' ) ) then {\
							if ( _index isEqualTo _value ) then {\
								_ctrl lbSetCurSel _index;\
							};\
						}else{\
							if ( _value == getText( _cfg >> 'data' ) ) then {\
								_ctrl lbSetCurSel _index;\
							};\
						};\
					}forEach configProperties [_path,'isclass _x'];\
				};\
				if ( isClass _staticItemsCfg ) then {\
					[ _staticItemsCfg, false ] call _fnc_setValues;\
				};\
				\
				_dynamicItemsCfg = configFile >> 'Cfg3DEN' >> 'Attributes' >> _attCtrl >> 'Controls' >> 'Value' >> 'ItemsConfig';\
				if ( isNumber( _dynamicItemsCfg >> 'localConfig' ) && { getNumber( _dynamicItemsCfg >> 'localConfig' ) > 0 } ) then {\
					_class = getArray( _dynamicItemsCfg >> 'path' ) select 0;\
					_path = missionConfigFile >> _class;\
					if ( isClass _path ) then {\
						_path call _fnc_setValues;\
					};\
				};\
			";
			// Expression called when attributes window is closed and changes confirmed. Used to save the value.
			// Passed param: _this - control
			attributeSave = "\
				systemchat str _config;\
				_ctrl = (_this controlsGroupCtrl 100);\
				_value = _ctrl lbData lbCurSel _ctrl;\
				_att = getText( _config >> 'property' );\
				collect3DENHistory {\
					{\
						_x set3DENAttribute [_att,_value];\
					} forEach ( get3DENSelected 'object' );\
				};\
			";

			// List of controls, structure is the same as with any other controls group
			// Static items
			class Controls {
				class Title: Title{}; // Inherit existing title control. Text of any control with class Title will be changed to attribute displayName
				class Value: ctrlCombo
				{
					idc = 100;
					x = ATTRIBUTE_TITLE_W * GRID_W;
					w = ATTRIBUTE_CONTENT_W * GRID_W;
					h = SIZE_M * GRID_H;

					// Static items
					class Items
					{
						class TEXT_1
						{
							text = "TEXT_1";
							data = "1";
							default = 0;
						};
						class TEXT_2
						{
							text = "TEXT_2";
							data = "2";
						};
					};
					class ItemsConfig
					{
						path[] = {"CfgTestCombo"}; // Path to config container
						localConfig = 1; // 1 to search local Description.ext as well
						// Name of the property which will be used for item text
						propertyText = "text";
						// Name of the property which will be used for data
						propertyData = "data";
					};
				};
			};
		};
	};
};
Working example and reads data from the description.ext ..

class CfgTestCombo {
	class TEXT_3 {
		text = "TEXT_3";
		data = "3";
	};
	class TEXT_4 {
		text = "TEXT_4";
		data = "4";
	};
};

There are some inconsistencies with the example configs on the wiki..

The class Title error is because the Title is not defined in Default but in the base Title class so trying to inherit it from Default was throwing errors.

_property does not seem to be populating inside object attribute expression.

There is a _config variable passed to attributeLoad/Save expressions that points to the object attribute. MyAttribute in my example.

Share this post


Link to post
Share on other sites

That seems to work Larrow, but the fact that you spend several hours on that shows me, that the documentation needs some work.

 

 

@patrix87

Thanks for your work, but the issue I had was 3den specific. ;)

Share this post


Link to post
Share on other sites

I fixed the code example, thanks for noticing. class Title and class TitleWide were indeed declared incorrectly, and class Controls was supposed to be class Controls: Controls

  • Like 2

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

×