igneous01 19 Posted February 17, 2017 I have a build script where I'm trying to generate some UI classes and attaching some handlers to them using macros. #include "BIS_Defaults.hpp" #include "Font_Definitions.hpp" #include "Color_Definitions.hpp" #include "Template_Default_Definitions.hpp" // ************* MACROS ************************************************************************ // Directory macro //#define IGN_DLG_DIR 'scripted\\IGN_DLG\\IGN_DLG_raiseEvent.sqf' //scripted\IGN_DLG\IGN_DLG_raiseEvent.sqf // CONTROL EVENTS #define ctrlOnButtonClick \ onButtonClick = "['IGN_Event_onButtonClick', [ctrlParent (_this select 0), _this select 0]] execVM 'scripted\IGN_DLG\IGN_DLG_raiseEvent.sqf'" #define ctrlOnButtonDown \ onButtonDown = "['IGN_Event_onButtonDown', [ctrlParent (_this select 0), _this select 0]] execVM 'scripted\IGN_DLG\IGN_DLG_raiseEvent.sqf'" Everything works as long as my script folder is inside a 'scripted' folder, but if I want to add flexibility of relocating my scripts to a different path, this breaks. I want to be able to define the parent path like so: #define LIB_PATH = "AnotherFolder\IGN_DLG" Then on the #define ctrlOnButtonClick replace only a part of the definition with part of the LIB_PATH macro like so: #define ctrlOnButtonClick \ onButtonClick = "['IGN_Event_onButtonClick', [ctrlParent (_this select 0), _this select 0]] execVM 'LIB_PATH\IGN_DLG_raiseEvent.sqf'" But this doesn't work. I've read you can combine macros together like so: ##LIB_PATH##\IGN_fnc_raiseEvent.sqf but I also have problems getting this to work (I'm assuming if you #define "MyPath\IGN_DLG" it also inserts the quotes, which screws up the original string. Anyone know a way around this? Share this post Link to post Share on other sites
gc8 977 Posted February 18, 2017 Hi there's couple of changes you need to make. like this: #define LIB_PATH "AnotherFolder\IGN_DLG" onButtonClick = "['IGN_Event_onButtonClick', [ctrlParent (_this select 0), _this select 0]] execVM (LIB_PATH + '\IGN_DLG_raiseEvent.sqf')"; Share this post Link to post Share on other sites
igneous01 19 Posted February 19, 2017 That doesn't work, as the macro doesn't get processed inside double quotes. However it appears that the BI Sim wiki is more explanatory about macros: https://resources.bisimulations.com/wiki/PreProcessor_Commands#Defines_in_strings You can expand a macro if it's inside single quotes like so: #define MY_NUM 2 player sidechat 'The number is MY_NUM'; // shows "The number is 2" // with double quotes the define will be output verbatim: player sidechat "The number is MY_NUM"; // shows "The number is MY_NUM" This works in Arma 3 as well, however there appears to be a bug with the description.ext parsing if you use single quotes: onCanDestroy = '[] execVM MYMACRO; true;'; // MYMACRO expands, but description.ext parser thinks that ';' ends the line, and later complains that myControl.true - encountered ';' expected '=' This doesn't happen with double quotes, but with single quotes the parser interprets this: #define MYMACRO "somepath\somescript.sqf" onCanDestroy = '[] execVM MYMACRO; true;' Parser defines as: class myControl { onCanDestroy = '[] execVM "mypath\somescript.sqf"; true; '; }; So unless BIS fixes this for description.ext, looks like what I want to do is not possible. Share this post Link to post Share on other sites
killzone_kid 1331 Posted February 19, 2017 38 minutes ago, igneous01 said: So unless BIS fixes this for description.ext, looks like what I want to do is not possible. Yeah! It is very easy and comfortable to blame BIS for everything. Use command with wrong type, the command must be broken! Fail to define a variable, WTF BIS!!11!! Not understanding how pre-processor works, BIS FIX THIS!!!!!!!!!! You made 2 errors minimum: 41 minutes ago, igneous01 said: call "mypath\somescript.sqf" You cannot call the string path of a script 42 minutes ago, igneous01 said: onCanDestroy = '[] call "mypath\somescript.sqf"; true;' It has to finish with ; Anyway. The following works.... just to prove my point above: #define MYMACRO(SCRIPT) onCanDestroy = [] call compile preprocessFileLineNumbers SCRIPT class myControl { MYMACRO("pathtosomescript"); }; 1 Share this post Link to post Share on other sites
igneous01 19 Posted February 19, 2017 24 minutes ago, killzone_kid said: Yeah! It is very easy and comfortable to blame BIS for everything. Use command with wrong type, the command must be broken! Fail to define a variable, WTF BIS!!11!! Not understanding how pre-processor works, BIS FIX THIS!!!!!!!!!! I made a typo with my example above try this in description.ext and you'll see what I mean: class myControl { onCanDestroy = '[] execVM ''Somescript.sqf''; true;'; }; // or class myControl { onCanDestroy = '[] execVM "Somescript.sqf"; true;'; }; This will not properly compile, it will think that true is a new property you are defining for the control. This is what you'll see when you do this: http://steamcommunity.com/sharedfiles/filedetails/?id=867939804 Quote You made 2 errors minimum: You cannot call the string path of a script That was a typo - I'll correct it in my comment (should be execVM) Quote It has to finish with ; Anyway. The following works.... just to prove my point above: #define MYMACRO(SCRIPT) onCanDestroy = [] call compile preprocessFileLineNumbers SCRIPT class myControl { MYMACRO("pathtosomescript"); }; I can get that working using the following as well: #define IGN_DLG_DIR scripted\IGN_DLG\internal\IGN_DLG_raiseEvent.sqf #define ctrlOnButtonClick \ onButtonClick = '[''IGN_Event_onButtonClick'', [ctrlParent (_this select 0), _this select 0]] execVM ''IGN_DLG_DIR''' The problem is when I need to add additional statements using ';' (such as returning true onCanDestroy) I had this, and it was not working: #define IGN_DLG_DIR scripted\IGN_DLG\internal\IGN_DLG_raiseEvent.sqf #define ctrlOnCanDestroy \ onCanDestroy = '[''IGN_Event_onCanDestroy'', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ''IGN_DLG_DIR''; true;' class ignBase { access = 0; idc = -1; x = 0.5; y = 0.5; w = 0.2; h = 0.2; moving = IGN_DLG_Template_ControlMoving; font = IGN_DLG_Template_Font; sizeEx = IGN_DLG_Template_FontSize; colorText[] = IGN_DLG_Template_ColorText; colorBackground[] = IGN_DLG_Template_ColorBackground; text = ""; shadow = IGN_DLG_Template_Shadow; size = 1; // based on defaults provided in rscText tooltipColorText[] = IGN_DLG_Template_ToolTipColorText; tooltipColorBox[] = IGN_DLG_Template_ToolTipColorBox; tooltipColorShade[] = IGN_DLG_Template_ToolTipColorShade; // Events - all controls implement these events ctrlOnCanDestroy; // error here - ignBase.True missing definition }; Share this post Link to post Share on other sites
igneous01 19 Posted February 19, 2017 33 minutes ago, killzone_kid said: Anyway. The following works.... just to prove my point above: #define MYMACRO(SCRIPT) onCanDestroy = [] call compile preprocessFileLineNumbers SCRIPT class myControl { MYMACRO("pathtosomescript"); }; Also, this is not useful as each control event passes in different sets of parameters - so I would have to define a macro for each event (which defeats the purpose) Correction - this wont work either because onCanDestroy needs the code passed in as a string. The moment you use double quotes to surround MYMACRO, the SCRIPT parameter will not be replaced with a path. 33 minutes ago, killzone_kid said: For example, I have this right now: #include "BIS_Defaults.hpp" #include "Font_Definitions.hpp" #include "Color_Definitions.hpp" #include "Template_Default_Definitions.hpp" // ************* MACROS ************************************************************************ // Directory macro #define IGN_DLG_DIR scripted\IGN_DLG\internal\IGN_DLG_raiseEvent.sqf #define ctrlOnCanDestroy \ onCanDestroy = "['IGN_Event_onCanDestroy', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM 'scripted\IGN_DLG\internal\IGN_DLG_raiseEvent.sqf'; true;" #define displayOnLoad \ onLoad = "['IGN_Event_onLoadDisplay', _this, ctrlIDD (_this select 0)] execVM 'scripted\IGN_DLG\internal\IGN_DLG_raiseEventDisplay.sqf'; true;" #define displayOnUnload \ onUnload = "['IGN_Event_onUnloadDisplay', _this, ctrlIDD (_this select 0)] execVM 'scripted\IGN_DLG\internal\IGN_DLG_raiseEventDisplay.sqf'; true;" // CONTROL EVENTS #define ctrlOnButtonClick \ onButtonClick = '[''IGN_Event_onButtonClick'', [ctrlParent (_this select 0), _this select 0]] execVM ''IGN_DLG_DIR''' #define ctrlOnButtonDown \ onButtonDown = '[''IGN_Event_onButtonDown'', [ctrlParent (_this select 0), _this select 0]] execVM ''IGN_DLG_DIR''' #define ctrlOnButtonUp \ onButtonUp = '[''IGN_Event_onButtonUp'', [ctrlParent (_this select 0), _this select 0]] execVM ''IGN_DLG_DIR''' #define ctrlOnMouseEnter \ onMouseEnter = '[''IGN_Event_onMouseEnter'', [ctrlParent (_this select 0), _this select 0]] execVM ''IGN_DLG_DIR''' #define ctrlOnMouseExit \ onMouseExit = '[''IGN_Event_onMouseExit'', [ctrlParent (_this select 0), _this select 0]] execVM ''IGN_DLG_DIR''' #define ctrlOnSetFocus \ onSetFocus = '[''IGN_Event_onSetFocus'', [ctrlParent (_this select 0), _this select 0]] execVM ''IGN_DLG_DIR''' #define ctrlOnKillFocus \ onKillFocus = '[''IGN_Event_onKillFocus'', [ctrlParent (_this select 0), _this select 0]] execVM ''IGN_DLG_DIR''' #define ctrlOnTimer \ onTimer = '[''IGN_Event_onTimer'', [ctrlParent (_this select 0), _this select 0]] execVM ''IGN_DLG_DIR''' #define ctrlOnLBDrop \ onLBDrop = '[''IGN_Event_onLBDrop'', [ctrlParent (_this select 0), _this select 0, _this select 1, _this select 2]] execVM ''IGN_DLG_DIR''' #define ctrlOnKeyDown \ onKeyDown = '[''IGN_Event_onKeyDown'', [ctrlParent (_this select 0), _this select 0, _this select 1, _this select 2, _this select 3, _this select 4]] execVM ''IGN_DLG_DIR''' #define ctrlOnKeyUp \ onKeyUp = '[''IGN_Event_onKeyUp'', [ctrlParent (_this select 0), _this select 0, _this select 1, _this select 2, _this select 3, _this select 4]] execVM ''IGN_DLG_DIR''' #define ctrlOnChar \ onChar = '[''IGN_Event_onChar'', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ''IGN_DLG_DIR''' #define ctrlOnMouseButtonDown \ onMouseButtonDown = '[''IGN_Event_onMouseButtonDown'', [ctrlParent (_this select 0), _this select 0, _this select 1, _this select 2, _this select 3, _this select 4, _this select 5, _this select 6]] execVM ''IGN_DLG_DIR''' #define ctrlOnMouseButtonUp \ onMouseButtonUp = '[''IGN_Event_onMouseButtonUp'', [ctrlParent (_this select 0), _this select 0, _this select 1, _this select 2, _this select 3, _this select 4, _this select 5, _this select 6]] execVM ''IGN_DLG_DIR''' #define ctrlOnMouseButtonClick \ onMouseButtonClick = '[''IGN_Event_onMouseButtonClick'', [ctrlParent (_this select 0), _this select 0, _this select 1, _this select 2, _this select 3, _this select 4, _this select 5, _this select 6]] execVM ''IGN_DLG_DIR''' #define ctrlOnMouseButtonDblClick \ onMouseButtonDblClick = '[''IGN_Event_onMouseButtonDblClick'', [ctrlParent (_this select 0), _this select 0, _this select 1, _this select 2, _this select 3, _this select 4, _this select 5, _this select 6]] execVM ''IGN_DLG_DIR''' #define ctrlOnMouseMoving \ onMouseMoving = '[''IGN_Event_onMouseMoving'', [ctrlParent (_this select 0), _this select 0, _this select 1, _this select 2, _this select 3]] execVM ''IGN_DLG_DIR''' #define ctrlOnMouseHolding \ onMouseHolding = '[''IGN_Event_onMouseHolding'', [ctrlParent (_this select 0), _this select 0, _this select 1, _this select 2, _this select 3]] execVM ''IGN_DLG_DIR''' #define ctrlOnMouseZChanged \ onMouseZChanged = '[''IGN_Event_onMouseZChanged'', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ''IGN_DLG_DIR''' #define ctrlOnDestroy \ onDestroy = '[''IGN_Event_onDestroy'', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ''IGN_DLG_DIR''' #define ctrlOnIMEChar \ onIMEChar = '[''IGN_Event_onIMEChar'', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ''IGN_DLG_DIR''' #define ctrlOnIMEComposition \ onIMEComposition = '[''IGN_Event_onIMEComposition'', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ''IGN_DLG_DIR''' #define ctrlOnJoystickButton \ onJoystickButton = '[''IGN_Event_onJoystickButton'', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ''IGN_DLG_DIR''' #define ctrlOnLBSelChanged \ onLBSelChanged = '[''IGN_Event_onLBSelChanged'', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ''IGN_DLG_DIR''' #define ctrlOnLBListSelChanged \ onLBListSelChanged = '[''IGN_Event_onLBListSelChanged'', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ''IGN_DLG_DIR''' #define ctrlOnLBDblClick \ onLBDblClick = '[''IGN_Event_onLBDblClick'', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ''IGN_DLG_DIR''' #define ctrlOnLBDrag \ onLBDrag = '[''IGN_Event_onLBDrag'', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ''IGN_DLG_DIR''' #define ctrlOnLBDragging \ onLBDragging = '[''IGN_Event_onLBDragging'', [ctrlParent (_this select 0), _this select 0, _this select 1, _this select 2]] execVM ''IGN_DLG_DIR''' #define ctrlOnCheckBoxesSelChanged \ onCheckBoxesSelChanged = '[''IGN_Event_onCheckBoxesSelChanged'', [ctrlParent (_this select 0), _this select 0, _this select 1, _this select 2]] execVM ''IGN_DLG_DIR''' #define ctrlOnSliderPosChanged \ onSliderPosChanged = '[''IGN_Event_onSliderPosChanged'', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ''IGN_DLG_DIR''' #define ctrlOnVideoStopped \ onVideoStopped = '[''IGN_Event_onVideoStopped'', [ctrlParent (_this select 0), _this select 0]] execVM ''IGN_DLG_DIR''' // ********************** MACROS END *************************************************************** // Base control class class ignBase { access = 0; idc = -1; x = 0.5; y = 0.5; w = 0.2; h = 0.2; moving = IGN_DLG_Template_ControlMoving; font = IGN_DLG_Template_Font; sizeEx = IGN_DLG_Template_FontSize; colorText[] = IGN_DLG_Template_ColorText; colorBackground[] = IGN_DLG_Template_ColorBackground; text = ""; shadow = IGN_DLG_Template_Shadow; size = 1; // based on defaults provided in rscText tooltipColorText[] = IGN_DLG_Template_ToolTipColorText; tooltipColorBox[] = IGN_DLG_Template_ToolTipColorBox; tooltipColorShade[] = IGN_DLG_Template_ToolTipColorShade; // Events - all controls implement these events ctrlOnCanDestroy; ctrlOnDestroy; ctrlOnMouseEnter; ctrlOnMouseExit; ctrlOnTimer; ctrlOnKeyDown; ctrlOnKeyUp; ctrlOnMouseButtonDown; ctrlOnMouseButtonUp; ctrlOnMouseButtonDblClick; ctrlOnMouseMoving; ctrlOnMouseHolding; ctrlOnMouseZChanged; }; Share this post Link to post Share on other sites
killzone_kid 1331 Posted February 19, 2017 39 minutes ago, igneous01 said: Correction - this wont work This works. You haven't tried it, have you? Share this post Link to post Share on other sites
killzone_kid 1331 Posted February 19, 2017 44 minutes ago, igneous01 said: The problem is when I need to add additional statements using ';' (such as returning true onCanDestroy) Hate to state the obvious, but you can return true in your script Share this post Link to post Share on other sites
igneous01 19 Posted February 19, 2017 2 minutes ago, killzone_kid said: Hate to state the obvious, but you can return true in your script The script doesn't return true, it's meant to call handlers registered to my events. Although I suppose the workaround is to pass it as an argument to the function and return true if something is passed in. I think I'll just do that instead - thanks for the idea. 6 minutes ago, killzone_kid said: This works. You haven't tried it, have you? Yes I did - same problem: #define MYMACRO(SCRIPT) \ onCanDestroy = ['IGN_Event_onCanDestroy', [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM SCRIPT; true // Base control class class ignBase { access = 0; idc = -1; x = 0.5; y = 0.5; w = 0.2; h = 0.2; moving = IGN_DLG_Template_ControlMoving; font = IGN_DLG_Template_Font; sizeEx = IGN_DLG_Template_FontSize; colorText[] = IGN_DLG_Template_ColorText; colorBackground[] = IGN_DLG_Template_ColorBackground; text = ""; shadow = IGN_DLG_Template_Shadow; size = 1; // based on defaults provided in rscText tooltipColorText[] = IGN_DLG_Template_ToolTipColorText; tooltipColorBox[] = IGN_DLG_Template_ToolTipColorBox; tooltipColorShade[] = IGN_DLG_Template_ToolTipColorShade; // Events - all controls implement these two events MYMACRO("scripted\IGN_DLG\internal\IGN_DLG_raiseEvent.sqf"); // true is a new definition, not treated as part of same code. Share this post Link to post Share on other sites
killzone_kid 1331 Posted February 19, 2017 29 minutes ago, igneous01 said: Yes I did - same problem: This is not what I posted. 1. you cannot execVM if you need to return true 2. you cannot have ;true in macro 3. missing } So once again, you haven't tried the solution I posted, have you? Share this post Link to post Share on other sites
igneous01 19 Posted February 19, 2017 3 minutes ago, killzone_kid said: This is not what I posted. 1. you cannot execVM if you need to return true 2. you cannot have ;true in macro 3. missing } So once again, you haven't tried the solution I posted, have you? What you posted does not apply to my problem. Ok seriously, whats with the toxicity here? I remember this community was A LOT more well behaved than it is now. I was not expecting to be insulted and treated as incompetent when asking some questions (and the fact that you tried to insult me as being wrong about the single quotes is ridiculous - have you even tested this yourself?) Yes, I did try your original code, it worked, but it wasn't the problem or the use case I was describing. Don't be a hypocrite about not trying your code when you havn't even bothered testing what I deem as a bug in the parser. I think it's best we leave this thread here. There is nothing more to be said besides insults at this point. I'll say thanks for the brainstorming as it gave me an idea for working around this, but I am absolutely disgusted with your behavior. Share this post Link to post Share on other sites
killzone_kid 1331 Posted February 19, 2017 1 hour ago, igneous01 said: and the fact that you tried to insult me as being wrong about the single quotes is ridiculous It wasn't my intention to insult you, especially about single quotes which I have zero clue what you are talking about. I actually re-read the thread and couldn't find the reference. Anyway, it kinda felt it might end this way. I just want to wish you good luck. Share this post Link to post Share on other sites
killzone_kid 1331 Posted February 20, 2017 #define MYMACRO(SCRIPT) \ format ["[""IGN_Event_onCanDestroy"", [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ""%1""%2 true", SCRIPT, toString [59]] class myControl { // Events - all controls implement these two events onCanDestroy = __EVAL(MYMACRO("scripted\IGN_DLG\internal\IGN_DLG_raiseEvent.sqf")); // true is a new definition, not treated as part of same code. }; hint str getText (missionconfigfile >> "myControl" >> "onCanDestroy"); // "[""IGN_Event_onCanDestroy"", [ctrlParent (_this select 0), _this select 0, _this select 1]] execVM ""scripted\IGN_DLG\internal\IGN_DLG_raiseEvent.sqf""; true" I'm done here. Share this post Link to post Share on other sites
gc8 977 Posted February 20, 2017 11 hours ago, igneous01 said: That doesn't work, as the macro doesn't get processed inside double quotes. sorry about that my bad. what about this macro: #define MAKEPATH(filename,path) path\filename use like this: var = MAKEPATH(test.sqf,dir); this will result in: "dir\test.sqf" Share this post Link to post Share on other sites