scope fillReg initializer init
globals
private real minX
private real maxX
private real minY
private real maxY
private trigger fill_child_trig
//resolution, smallest cell a region can have is 32, but that would result in many more iterations, 128 is terrain node size
private constant real dist = 128
//heavy iterations can easily break the op limit
private constant integer maxIterationsPerThread = 2000
private rect rec
private hashtable xTable
private hashtable yTable
//private hashtable checkedTable
private real array xStack
private real array yStack
private integer stackDepth = -1
private region reg
endglobals
private function push takes real x, real y returns nothing
set stackDepth = stackDepth + 1
//may easily stackDepth > 8k
call SaveReal(xTable, 0, stackDepth, x)
call SaveReal(yTable, 0, stackDepth, y)
endfunction
private function add takes real x, real y returns nothing
if x < minX then
return
endif
if x > maxX then
return
endif
if y < minY then
return
endif
if y > maxY then
return
endif
//may be faster via hashtable
//if LoadBoolean(checkedTable, R2I(x), R2I(y)) then
// return
//endif
if IsPointInRegion(reg, x, y) then
return
endif
//actual condition for neighboring cells
if GetTerrainCliffLevel(x, y) > 2 then
return
endif
//call SaveBoolean(checkedTable, R2I(x), R2I(y), true)
call SetRect(rec, x, y, x + dist - 32, y + dist - 32)
call RegionAddRect(reg, rec)
call push(x - dist, y)
call push(x + dist, y)
call push(x, y - dist)
call push(x, y + dist)
endfunction
private function fill_child takes nothing returns nothing
local integer c = 0
local real x
local real y
loop
exitwhen (c > maxIterationsPerThread)
exitwhen (stackDepth < 0)
set c = c + 1
set x = LoadReal(xTable, 0, stackDepth)
set y = LoadReal(yTable, 0, stackDepth)
set stackDepth = stackDepth - 1
call add(x, y)
endloop
endfunction
public function fill takes region targetReg, real x, real y returns nothing
set x = R2I(x) / dist * dist
set y = R2I(y) / dist * dist
set reg = targetReg
call push(x, y)
loop
exitwhen (stackDepth < 0)
call TriggerEvaluate(fill_child_trig)
endloop
endfunction
private function init takes nothing returns nothing
local rect world = GetWorldBounds()
set minX = GetRectMinX(world)
set maxX = GetRectMaxX(world) - dist
set minY = GetRectMinY(world)
set maxY = GetRectMaxY(world) - dist
set fill_child_trig = CreateTrigger()
call TriggerAddCondition(fill_child_trig, function fill_child)
set rec = Rect(0, 0, 0, 0)
set xTable = InitHashtable()
set yTable = InitHashtable()
//set checkedTable = InitHashtable()
endfunction
endscope
function start takes nothing returns nothing
local region targetReg = CreateRegion()
local rect sourceRect = gg_rct_sourceRect
call fillReg_fill(targetReg, sourceRect)
endfunction