HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

ForGroup+method

10-20-2009, 02:05 PM#1
blanc_dummy
is there possible to call a method from ForGroup native like: ForGroup(group,method blabla)??
10-20-2009, 02:08 PM#2
Anachron
Yes. You can do it like that:

Collapse JASS:
native ForGroup takes group whichGroup, code callback returns nothing
So its actually
Collapse JASS:

call ForGroup(g, function $CodeFunc$)
10-20-2009, 02:35 PM#3
fX_
the callback has to be a static method i think
10-21-2009, 05:05 AM#4
blanc_dummy
oh i got it :)..but if the method is static, how can i use "this" pointer?
10-21-2009, 05:47 AM#5
Earth-Fury
You can not use ForGroup with a method.

You can, however, use function interfaces with methods. This leads me to an idea.

Collapse JASS:
library ForGroupMethod

function interface ForGroupWithObject takes integer obj, unit enum returns nothing

globals
    private integer enumObj
    private ForGroupWithObject enumFunc
endglobals

private function ForGroupMethodChild takes nothing returns nothing
    local integer obj = enumObj
    local ForGroupWithObject enum = enumFunc
    
    call enum.evaluate(obj, GetEnumUnit())
    
    set enumObj = obj
    set enumFunc = enum
endfunction

function ForGroupMethod takes group g, integer obj, ForGroupWithObject func returns nothing
    set enumObj = obj
    set enumFunc = func
    call ForGroup(g, function ForGroupMethodChild)
endfunction
endlibrary

I haven't tried compiling the above. I haven't even ever actually used this methods-as-function-interface-functions stuff yet, so this is all a bit of a guess syntax-wise. but still, probable example usage:
Collapse JASS:
call ForGroupMethod(myGroup, someObject, SomeClass.methodName)

Bam. ForGroup with methods. Also, I forget if ForGroup supports waits inside it's callback. If it didn't before, it may now. If it did before, it still does. Through MAGIC!

Edit: note that your method needs to have one argument: a unit. The unit is the enum unit.

Edit 2:
---------------------------------------------------------------------------
This version works with TriggerSleepAction() in a ForGroup callback:
Collapse JASS:
library ForGroupMethod

function interface ForGroupWithObject takes integer obj, unit enum returns nothing

globals
    private integer enumObj
    private ForGroupWithObject enumFunc
endglobals

private function ForGroupMethodChild takes nothing returns nothing
    local integer obj = enumObj
    local ForGroupWithObject enum = enumFunc
    
    call enum.execute(obj, GetEnumUnit())
    
    set enumObj = obj
    set enumFunc = enum
endfunction

function ForGroupMethod takes group g, integer obj, ForGroupWithObject func returns nothing
    set enumObj = obj
    set enumFunc = func
    call ForGroup(g, function ForGroupMethodChild)
endfunction
endlibrary

This version doesn't:
Collapse JASS:
library ForGroupMethod

function interface ForGroupWithObject takes integer obj, unit enum returns nothing

globals
    private integer enumObj
    private ForGroupWithObject enumFunc
endglobals

private function ForGroupMethodChild takes nothing returns nothing
    call enumFunc.evaluate(enumObj, GetEnumUnit())
endfunction

function ForGroupMethod takes group g, integer obj, ForGroupWithObject func returns nothing
    set enumObj = obj
    set enumFunc = func
    call ForGroup(g, function ForGroupMethodChild)
endfunction
endlibrary

Example usage of the one that works with TSA() (and the one that doesn't. Set DO_TEST_2 to false for the latter.):
Collapse JASS:
scope A initializer OnInit

globals
    private integer count = 0
    private constant boolean DO_TEST_2 = true
endglobals

struct Test
    integer a
    
    static method create takes integer a returns thistype
        local thistype this = thistype.allocate()
        
        set this.a = a
        
        return this
    endmethod
    
    method enumUnits takes unit u returns nothing
        local integer c = count
        
        call SetUnitScale(u, this.a / 100.0, this.a / 100.0, this.a / 100.0)
        static if DO_TEST_2 then
            call BJDebugMsg("Pre-wait " + I2S(c))
            set count = count + 1
            call TriggerSleepAction(0.1)
            call BJDebugMsg("Post-wait " + I2S(c))
        endif
    endmethod
endstruct

private function OnInit takes nothing returns nothing
    local group g = CreateGroup()
    local integer i = 0
    
    loop
        exitwhen i == 10
        
        call GroupAddUnit(g, CreateUnit(Player(0), 'hpea', i*10, i*10, 0))
        
        set i = i + 1
    endloop
    
    call ForGroupMethod(g, Test.create(200), Test.enumUnits)
endfunction
endscope

Notes about all this:
#1: The version that works with TSA() in the callback is slower. Quite a bit slower, actually.
#2: The version that doesn't work with TSA() in the callback is slower than simply passing a struct to a ForGroup callback using a global, and calling the method on the struct. This is due to the overhead of function interfaces.
#3: The version that doesn't work with TSA() may still be faster than a FirstOfGroup() loop. You tell me, I'm too lazy to benchmark this stuff.
10-21-2009, 07:32 AM#6
Anachron
EF, one of your suggestions is exactly how I solved the problem.

Anyway, you could also just create an global tmp variable and add the instance to it and in the static method you just refer to that variable. I think that is much easier.
10-21-2009, 08:47 AM#7
blanc_dummy
i see, that's clear now. thanks :)
10-25-2009, 07:31 PM#8
Vexorian
// on the global idea...
Collapse JASS:
struct meh
    integer x
    integer y
    private static passInstance
    static method enum takes nothing returns nothing 
      local thistype this = instance //magic

             set x = y + 4
    endmethod
    method xxx takes nothing returns nothing
           set instance = this
           call ForGroup(g, function meh.enum)
    endmethod

endstruct