- Joined
- Sep 26, 2009
- Messages
- 9,528
This is part 1 of my overall initiative to do automatic memory leak cleanup for GUI. Part 2 will be unit groups.
I have not tested every single aspect of the API, but I've attached a demo map which shows that the location API works successfully behind the scenes.
One thing that needs stating is that Hashtables themselves do not store Locations. I have a GUI hashtable wrapper which (hypothetically) solves that problem, which you can find in hidden tags below. I haven't tested the hashtable stuff at all, so none of this is ready to be submitted to the code section yet.
I have not tested every single aspect of the API, but I've attached a demo map which shows that the location API works successfully behind the scenes.
One thing that needs stating is that Hashtables themselves do not store Locations. I have a GUI hashtable wrapper which (hypothetically) solves that problem, which you can find in hidden tags below. I haven't tested the hashtable stuff at all, so none of this is ready to be submitted to the code section yet.
Lua:
--Replace all locations with Lua Tables, allowing for automatic garbage collection by not even using locations to begin with.
do
local oldLoc, oldMoveLoc = Location, MoveLocation
local oldGetX=GetLocationX
local oldGetY=GetLocationY
local oldGetZ=GetLocationZ
local oldRally = GetUnitRallyPoint
local oldRemove = RemoveLocation
OnMainInit(function()
local location = oldLoc(0,0) --one single location to govern the cases where a location needs to be referenced.
--First, the easy stuff:
RemoveLocation = DoNothing
function Location(x,y)
return {x,y}
end
function MoveLocation(loc, x, y)
loc[1]=x
loc[2]=y
end
function GetLocationX(loc) return loc[1] end
function GetLocationY(loc) return loc[2] end
function GetLocationZ(loc)
oldMoveLoc(location, loc[1], loc[2])
return oldGetZ(loc)
end
function GetUnitLoc(unit)
return {GetUnitX(unit), GetUnitY(unit)}
end
local function fakeCreate(varName, suffix)
local getX=_G[varName.."X"]
local getY=_G[varName.."Y"]
_G[varName..(suffix or "Loc")]=function() return {getX(), getY()} end
end
fakeCreate("GetOrderPoint")
fakeCreate("GetSpellTarget")
fakeCreate("CameraSetupGetDestPosition")
fakeCreate("GetCameraTargetPosition")
fakeCreate("GetCameraEyePosition")
fakeCreate("BlzGetTriggerPlayerMouse", "Position")
fakeCreate("GetStartLocation")
--Actually needs to create a location for a brief moment, as there is no GetUnitRallyX/Y
function GetUnitRallyPoint(unit)
local removeThis = oldRally(unit)
local loc = {oldGetX(removeThis), oldGetY(removeThis)}
oldRemove(removeThis)
return loc
end
do local old = BlzSetSpecialEffectPositionLoc
BlzSetSpecialEffectPositionLoc = function(effect, loc)
oldMoveLoc(location, loc[1], loc[2])
old(effect, location)
end
end
---@param oldVarName string
---@param newVarName string
---@param index integer needed to determine which of the parameters calls for a location.
local function hook(oldVarName, newVarName, index)
local new = _G[newVarName]
local func
if index==1 then
func=function(loc, ...)
return new(loc[1], loc[2], ...)
end
elseif index==2 then
func=function(a, loc, ...)
return new(a, loc[1], loc[2], ...)
end
else--index==3
func=function(a, b, loc, ...)
return new(a, b, loc[1], loc[2], ...)
end
end
_G[oldVarName] = func
end
hook("IsLocationInRegion", "IsPointInRegion", 2)
hook("IsUnitInRangeLoc", "IsUnitInRangeXY", 2)
hook("IssuePointOrderLoc", "IssuePointOrder", 3)
IssuePointOrderLocBJ=IssuePointOrderLoc
hook("IssuePointOrderByIdLoc", "IssuePointOrderById", 3)
hook("IsLocationVisibleToPlayer", "IsVisibleToPlayer", 1)
hook("IsLocationFoggedToPlayer", "IsFoggedToPlayer", 1)
hook("IsLocationMaskedToPlayer", "IsMaskedToPlayer", 1)
hook("CreateFogModifierRadiusLoc", "CreateFogModifierRadius", 3)
hook("AddSpecialEffectLoc", "AddSpecialEffect", 2)
hook("AddSpellEffectLoc", "AddSpellEffect", 3)
hook("AddSpellEffectByIdLoc", "AddSpellEffectById", 3)
hook("SetBlightLoc", "SetBlight", 2)
hook("DefineStartLocationLoc", "DefineStartLocation", 2)
hook("GroupEnumUnitsInRangeOfLoc", "GroupEnumUnitsInRange", 2)
hook("GroupEnumUnitsInRangeOfLocCounted", "GroupEnumUnitsInRangeCounted", 2)
hook("GroupPointOrderLoc", "GroupPointOrder", 3)
GroupPointOrderLocBJ=GroupPointOrderLoc
hook("GroupPointOrderByIdLoc", "GroupPointOrderById", 3)
hook("MoveRectToLoc", "MoveRectTo", 2)
hook("RegionAddCellAtLoc", "RegionAddCell", 2)
hook("RegionClearCellAtLoc", "RegionClearCell", 2)
hook("CreateUnitAtLoc", "CreateUnit", 3)
hook("CreateUnitAtLocByName", "CreateUnitByName", 3)
hook("SetUnitPositionLoc", "SetUnitPosition", 2)
hook("ReviveHeroLoc", "ReviveHero", 2)
hook("SetFogStateRadiusLoc", "SetFogStateRadius", 3)
---@param min table location
---@param max table location
---@return rect newRect
RectFromLoc = function(min, max)
return Rect(min[1], min[2], max[1], max[2])
end
---@param whichRect rect
---@param min table location
---@param max table location
SetRectFromLoc = function(whichRect, min, max)
SetRect(whichRect, min[1], min[2], max[1], max[2])
end
end)
end
Lua:
do --[[
GUI hashtable converter version 1.1 by Tasyen and Bribe
Converts GUI hashtables API into Lua Tables, overwrites StringHashBJ and GetHandleIdBJ to permit
typecasting, bypasses the 256 hashtable limit by avoiding hashtables, provides the variable
"HashTableArray", which automatically creates hashtables for you as needed (so you don't have to
initialize them each time).
Be sure to include the GUI Enhancer Collection to ensure that the object references don't create
memory leaks over time: https://github.com/BribeFromTheHive/Lua-Core/blob/main/GUI%20Enhancer%20Collection.lua
]]
--GUI typecasting yo.
function StringHashBJ(s) return s end
function GetHandleIdBJ(id) return id end
if OnLibraryInit then OnLibraryInit("GlobalRemapArray", function()
local hashes = {}
GlobalRemapArray("udg_HashTableArray", function(index)
local val = hashes[index]
if not val then
val = HashTable.create()
hashes[index] = val
end
return val
end)
end) end
function InitHashtableBJ() return HashTable.create() end
local function saveInto(value, childKey, parentKey, whichHashTable)
whichHashTable[parentKey][childKey] = value
end
local function loadFrom(childKey, parentKey, whichHashTable, default)
local val = whichHashTable[parentKey][childKey]
if default and val == nil then
return default
end
return val
end
SaveIntegerBJ = saveInto
SaveRealBJ = saveInto
SaveBooleanBJ = saveInto
SaveStringBJ = saveInto
local loadNumber = function(childKey, parentKey, whichHashTable) return loadFrom(childKey, parentKey, whichHashTable, 0) end
LoadIntegerBJ = loadNumber
LoadRealBJ = loadNumber
LoadBooleanBJ = function(childKey, parentKey, whichHashTable) return loadFrom(childKey, parentKey, whichHashTable, false) end
LoadStringBJ = function(childKey, parentKey, whichHashTable) return loadFrom(childKey, parentKey, whichHashTable, "") end
local sub = string.sub
for key in pairs(_G) do
if sub(key, -8)=="HandleBJ" then
local str=sub(key, 1,4)
if str=="Save" then _G[key] = saveInto
elseif str=="Load" then _G[key] = loadFrom end
end
end
function HaveSavedValue(childKey, _, parentKey, whichHashTable)
return whichHashTable[parentKey][childKey] ~= nil
end
FlushParentHashtableBJ = HashTable.flush
function FlushChildHashtableBJ(whichHashTable, parentKey)
whichHashTable[parentKey].flush()
end
end