From 29ed630536ef4429f425da52f927f7c972d2a37d Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 13 Aug 2023 17:40:28 +0200 Subject: [PATCH] COORDINATE - Generalized MarkupToAllFreeForm UTILS - Added some functions from MIST --- Moose Development/Moose/Core/Point.lua | 26 +++- Moose Development/Moose/Utilities/Utils.lua | 160 +++++++++++++++++++- 2 files changed, 181 insertions(+), 5 deletions(-) diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index d942e49ba..99e8eb593 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -2389,7 +2389,6 @@ do -- COORDINATE end --- Creates a free form shape on the F10 map. The first point is the current COORDINATE. The remaining points need to be specified. - -- **NOTE**: A free form polygon must have **at least three points** in total and currently only **up to 15 points** in total are supported. -- @param #COORDINATE self -- @param #table Coordinates Table of coordinates of the remaining points of the shape. -- @param #number Coalition Coalition: All=-1, Neutral=0, Red=1, Blue=2. Default -1=All. @@ -2463,9 +2462,30 @@ do -- COORDINATE vecs[11], vecs[12], vecs[13], vecs[14], vecs[15], Color, FillColor, LineType, ReadOnly, Text or "") else - self:E("ERROR: Currently a free form polygon can only have 15 points in total!") + -- Unfortunately, unpack(vecs) does not work! So no idea how to generalize this :( - trigger.action.markupToAll(7, Coalition, MarkID, unpack(vecs), Color, FillColor, LineType, ReadOnly, Text or "") + --trigger.action.markupToAll(7, Coalition, MarkID, unpack(vecs), Color, FillColor, LineType, ReadOnly, Text or "") + + -- Write command as string and execute that. Idea by Grimes https://forum.dcs.world/topic/324201-mark-to-all-function/#comment-5273793 + local s=string.format("trigger.action.markupToAll(7, %d, %d,", Coalition, MarkID) + for _,vec in pairs(vecs) do + s=s..string.format("%s,", UTILS._OneLineSerialize(vec)) + end + s=s..string.format("%s, %s, %s, %s", UTILS._OneLineSerialize(Color), UTILS._OneLineSerialize(FillColor), tostring(LineType), tostring(ReadOnly)) + if Text and Text~="" then + s=s..string.format(", \"%s\"", Text) + end + s=s..")" + + + -- Execute string command + local success=UTILS.DoString(s) + + if not success then + self:E("ERROR: Could not draw polygon") + env.info(s) + end + end return MarkID diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index 7b0467ed1..cc5f1df8b 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -293,8 +293,9 @@ UTILS.DeepCopy = function(object) end ---- Porting in Slmod's serialize_slmod2. +--- Serialize a given table. -- @param #table tbl Input table. +-- @return #string Table as a string. UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function lookup_table = {} @@ -371,7 +372,54 @@ UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a s return objectreturn end ---porting in Slmod's "safestring" basic serialize +--- Serialize a table to a single line string. +-- @param #table tbl table to serialize. +-- @return #string string containing serialized table. +function UTILS._OneLineSerialize(tbl) + + if type(tbl) == 'table' then --function only works for tables! + + local tbl_str = {} + + tbl_str[#tbl_str + 1] = '{ ' + + for ind,val in pairs(tbl) do -- serialize its fields + if type(ind) == "number" then + tbl_str[#tbl_str + 1] = '[' + tbl_str[#tbl_str + 1] = tostring(ind) + tbl_str[#tbl_str + 1] = '] = ' + else --must be a string + tbl_str[#tbl_str + 1] = '[' + tbl_str[#tbl_str + 1] = UTILS.BasicSerialize(ind) + tbl_str[#tbl_str + 1] = '] = ' + end + + if ((type(val) == 'number') or (type(val) == 'boolean')) then + tbl_str[#tbl_str + 1] = tostring(val) + tbl_str[#tbl_str + 1] = ', ' + elseif type(val) == 'string' then + tbl_str[#tbl_str + 1] = UTILS.BasicSerialize(val) + tbl_str[#tbl_str + 1] = ', ' + elseif type(val) == 'nil' then -- won't ever happen, right? + tbl_str[#tbl_str + 1] = 'nil, ' + elseif type(val) == 'table' then + tbl_str[#tbl_str + 1] = UTILS._OneLineSerialize(val) + tbl_str[#tbl_str + 1] = ', ' --I think this is right, I just added it + else + --log:warn('Unable to serialize value type $1 at index $2', mist.utils.basicSerialize(type(val)), tostring(ind)) + end + + end + + tbl_str[#tbl_str + 1] = '}' + return table.concat(tbl_str) + else + return UTILS.BasicSerialize(tbl) + end +end + +--- Basic serialize (porting in Slmod's "safestring" basic serialize). +-- @param #string s Table to serialize. UTILS.BasicSerialize = function(s) if s == nil then return "\"\"" @@ -402,6 +450,114 @@ function UTILS.PrintTableToLog(table, indent) end end +--- Returns table in a easy readable string representation. +-- @param tbl table to show +-- @param loc +-- @param indent +-- @param tableshow_tbls +-- @return Human readable string representation of given table. +function UTILS.TableShow(tbl, loc, indent, tableshow_tbls) + tableshow_tbls = tableshow_tbls or {} --create table of tables + loc = loc or "" + indent = indent or "" + if type(tbl) == 'table' then --function only works for tables! + tableshow_tbls[tbl] = loc + + local tbl_str = {} + + tbl_str[#tbl_str + 1] = indent .. '{\n' + + for ind,val in pairs(tbl) do -- serialize its fields + if type(ind) == "number" then + tbl_str[#tbl_str + 1] = indent + tbl_str[#tbl_str + 1] = loc .. '[' + tbl_str[#tbl_str + 1] = tostring(ind) + tbl_str[#tbl_str + 1] = '] = ' + else + tbl_str[#tbl_str + 1] = indent + tbl_str[#tbl_str + 1] = loc .. '[' + tbl_str[#tbl_str + 1] = UTILS.BasicSerialize(ind) + tbl_str[#tbl_str + 1] = '] = ' + end + + if ((type(val) == 'number') or (type(val) == 'boolean')) then + tbl_str[#tbl_str + 1] = tostring(val) + tbl_str[#tbl_str + 1] = ',\n' + elseif type(val) == 'string' then + tbl_str[#tbl_str + 1] = UTILS.BasicSerialize(val) + tbl_str[#tbl_str + 1] = ',\n' + elseif type(val) == 'nil' then -- won't ever happen, right? + tbl_str[#tbl_str + 1] = 'nil,\n' + elseif type(val) == 'table' then + if tableshow_tbls[val] then + tbl_str[#tbl_str + 1] = tostring(val) .. ' already defined: ' .. tableshow_tbls[val] .. ',\n' + else + tableshow_tbls[val] = loc .. '[' .. UTILS.BasicSerialize(ind) .. ']' + tbl_str[#tbl_str + 1] = tostring(val) .. ' ' + tbl_str[#tbl_str + 1] = UTILS.TableShow(val, loc .. '[' .. UTILS.BasicSerialize(ind).. ']', indent .. ' ', tableshow_tbls) + tbl_str[#tbl_str + 1] = ',\n' + end + elseif type(val) == 'function' then + if debug and debug.getinfo then + local fcnname = tostring(val) + local info = debug.getinfo(val, "S") + if info.what == "C" then + tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', C function') .. ',\n' + else + if (string.sub(info.source, 1, 2) == [[./]]) then + tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', defined in (' .. info.linedefined .. '-' .. info.lastlinedefined .. ')' .. info.source) ..',\n' + else + tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', defined in (' .. info.linedefined .. '-' .. info.lastlinedefined .. ')') ..',\n' + end + end + + else + tbl_str[#tbl_str + 1] = 'a function,\n' + end + else + tbl_str[#tbl_str + 1] = 'unable to serialize value type ' .. UTILS.BasicSerialize(type(val)) .. ' at index ' .. tostring(ind) + end + end + + tbl_str[#tbl_str + 1] = indent .. '}' + return table.concat(tbl_str) + end +end + +--- Dumps the global table _G. +-- This dumps the global table _G to a file in the DCS\Logs directory. +-- This function requires you to disable script sanitization in $DCS_ROOT\Scripts\MissionScripting.lua to access lfs and io libraries. +-- @param #string fname File name. +function UTILS.Gdump(fname) + if lfs and io then + + local fdir = lfs.writedir() .. [[Logs\]] .. fname + + local f = io.open(fdir, 'w') + + f:write(UTILS.TableShow(_G)) + + f:close() + + env.info(string.format('Wrote debug data to $1', fdir)) + else + env.error("WARNING: lfs and/or io not de-sanitized - cannot dump _G!") + end +end + +--- Executes the given string. +-- borrowed from Slmod +-- @param #string s string containing LUA code. +-- @return #boolean `true` if successfully executed, `false` otherwise. +function UTILS.DoString(s) + local f, err = loadstring(s) + if f then + return true, f() + else + return false, err + end +end + UTILS.ToDegree = function(angle) return angle*180/math.pi