• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[System] Region Utilities

Level 7
Joined
Apr 30, 2011
Messages
359
JASS:
//========================================================================================
//
//      Region Utilities
//      -*- overcold_ice -*-
//
//     -[*] Requirements:
//          - JNGP
//          - latest version of JassHelper
//
//     -[*] Optional Requirements:
//          - /*New*/ Table             hiveworkshop.com/forums/showthread.php?t=188084
//
//          For your region-manipulating needs
//      This system provides easier and dynamic region-handling.
//      Besides providing easy to use APIs to create/add/destroy regions, this library
//      also stores what it contains (rects and cells).
//
//     -[*] API:
//
//      struct Region extends array
//          static method create takes nothing returns Region
//              creates an empty region
//
//          static method operator fromRect takes rect r returns Region
//              creates a region and adds rect r to it
//
//          method operator addRect takes rect r returns Region
//              adds a rect to the region
//
//          static method fromCell takes real x, real y returns Region
//              creates a region and adds cell [x, y] to it
//
//          method addCell takes real x, real y returns Region
//              adds a cell [x, y] to the region
//
//          method operator region takes nothing returns region
//              returns the 'real' region
//
//          method operator rect[] takes integer i returns rect
//              returns a rect from given rect id
//
//          method rect.getId takes rect r returns integer
//              returns the rect id of rect r
//
//          method operator cell.x[] takes integer i returns real
//          method operator cell.y[] takes integer i returns real
//              returns the x coordinate of a cell from given cell number
//          
//          method cell.getId takes real x, real y returns integer
//              returns the cell number of cell [x, y]
//
//          method clearRectById takes integer i returns nothing
//              removes a rect of given rect id from the region
//
//          method clearCellById takes integer i returns nothing
//              removes a cell of given cell id from the region
//
//          method clear takes nothing returns nothing
//              clears the regions from all rects and cells
//
//          method destroy takes nothing returns nothing
//              destroys the region
//
//     -[*] Required Example:
//
//          local Region reg1 = Region.fromCell(x1, y1).addCell(x2, y2).addCell(x3, y3)
//          local Region reg2
//          set reg1 = reg1.addRect(r1).addRect(r2).addRect(r3).addRect(r4).addRect(r5).addRect(r6)
//          set reg2 = Region.fromRect(r1).addCell(x1, y1).addRect(r2).addRect(r3).addCell(x2, y2).addCell(x3, y3)
//
//          List of rect/cell numbers:
//                      NUM   RECT        CELL
//              reg1:
//                       1     r1         x1y1
//                       2     r2         x2y2
//                       3     r3         x3y3
//                       4     r4
//                       5     r5
//                       6     r6
//              reg2:
//                       1     r1         x1y1
//                       2     r2         x2y2
//                       3     r3         x3y3
//
//========================================================================================
library RegionUtils requires optional /*New*/Table
    
    static if not LIBRARY_Table then
        private struct T extends array
            static hashtable t = InitHashtable()
        endstruct
    endif
    
    private struct RectV extends array
        integer c
        
        static if LIBRARY_Table then
            Table t
        endif
        
        method register takes rect r returns nothing
            set this.c = this.c + 1
            
            static if LIBRARY_Table then
                if this.t == 0 then
                    set this.t = Table.create()
                endif
                
                set this.t.rect [this.c] = r
            else
                call SaveRectHandle(T.t, this, this.c, r)
            endif
        endmethod
        
        method unregister takes integer i returns nothing
            local integer m = this.c
            
            call RemoveRect(this.t.rect [i])
            
            loop
                exitwhen i == m
                
                static if LIBRARY_Table then
                    set this.t.rect [i] = this.t.rect [i + 1]
                else
                    call SaveRectHandle(T.t, this, i, LoadRectHandle(t, this, i + 1))
                endif
                
                set i = i + 1
            endloop
            
            call RemoveRect(this.t.rect [m])
            set this.c = this.c - 1
            
            static if LIBRARY_Table then
                call this.t.handle.remove(m)
                
                if this.c == 0 then
                    call this.t.destroy()
                endif
            else
                call RemoveSavedHandle(T.t, this, m)
            endif
        endmethod
    endstruct
    
    private struct RectO extends array
        method operator [] takes integer i returns rect
            static if LIBRARY_Table then
                return RectV(this).t.rect [i]
            else
                return LoadRectHandle(T.t, this, i)
            endif
        endmethod
        
        method getId takes rect r returns integer
            local integer l = 1
            
            loop
                exitwhen l == RectV(this).c
                
                if this [l] == r then
                    return l
                endif
                
                set l = l + 1
            endloop
            
            return 0
        endmethod
    endstruct
    
    private struct CellV extends array
        integer c
        
        static if LIBRARY_Table then
            TableArray t
        endif
        
        method register takes real x, real y returns nothing
            set this.c = this.c + 1
            
            static if LIBRARY_Table then
                if this.t == 0 then
                    set this.t = TableArray [2]
                endif
                
                set this.t [1].real [this.c] = x
                set this.t [2].real [this.c] = y
            else
                call SaveReal(T.t, this +  8192, this.c, x)
                call SaveReal(T.t, this + 16384, this.c, y)
            endif
        endmethod
        
        method unregister takes integer i returns nothing
            local integer m = this.c
            
            loop
                exitwhen i == m
                
                static if LIBRARY_Table then
                    set this.t [1].real [i] = this.t [1].real [i + 1]
                    set this.t [2].real [i] = this.t [2].real [i + 1]
                else
                    call SaveReal(T.t, this +  8192, i, LoadReal(t, this +  8192, i + 1))
                    call SaveReal(T.t, this + 16384, i, LoadReal(t, this + 16384, i + 1))
                endif
                
                set i = i + 1
            endloop
            
            set this.c = this.c - 1
            
            static if LIBRARY_Table then
                call this.t [1].real.remove(m)
                call this.t [2].real.remove(m)
                
                if this.c == 0 then
                    call this.t.destroy()
                endif
            else
                call RemoveSavedReal(T.t, this +  8192, m)
                call RemoveSavedReal(T.t, this + 16384, m)
            endif
        endmethod
    endstruct
    
    private struct CellX extends array
        method operator [] takes integer i returns real
            static if LIBRARY_Table then
                return CellV(this).t [1].real [i]
            else
                return LoadReal(T.t, this +  8192, i)
            endif
        endmethod
    endstruct
    
    private struct CellY extends array
        method operator [] takes integer i returns real
            static if LIBRARY_Table then
                return CellV(this).t [2].real [i]
            else
                return LoadReal(T.t, this + 16384, i)
            endif
        endmethod
    endstruct
    
    private struct CellO extends array
        method operator x takes nothing returns CellX
            return this
        endmethod
        
        method operator y takes nothing returns CellY
            return this
        endmethod
        
        method getId takes real x, real y returns integer
            local integer  l = 1
            
            loop
                exitwhen l == CellV(this).c
                
                if this.x [l] == x and this.y [l] == y then
                    return l
                endif
                
                set l = l + 1
            endloop
            
            return 0
        endmethod
    endstruct
    
    struct Region extends array
        private        thistype ir
        private static thistype ic
        
        readonly region region
        
        static method create takes nothing returns thistype
            local thistype this = thistype(0).ir
            
            if this == 0 then
                set .ic   = .ic + 1
                set this  = .ic
            else
                set thistype(0).ir = this.ir
            endif
            
            set this.region = CreateRegion()
            
            return this
        endmethod
        
        method addRect takes rect r returns thistype
            call RegionAddRect(this.region, r)
            call RectV(this).register(r)
            
            return this
        endmethod
        
        static method fromRect takes rect r returns thistype
            return Region.create().addRect(r)
        endmethod
        
        method addCell takes real x, real y returns thistype
            call RegionAddCell(this.region, x, y)
            call CellV(this).register(x, y)
            
            return this
        endmethod
        
        static method fromCell takes real x, real y returns thistype
            return Region.create().addCell(x, y)
        endmethod
        
        method operator rect takes nothing returns RectO
            return this
        endmethod
        
        method operator cell takes nothing returns CellO
            return this
        endmethod
        
        method clearRectById takes integer i returns nothing
            call RegionClearRect(this.region, this.rect [i])
            call RectV(this).unregister(i)
        endmethod
        
        method clearCellById takes integer i returns nothing
            call RegionClearCell(this.region, this.cell.x [i], this.cell.y [i])
            call CellV(this).unregister(i)
        endmethod
        
        method clear takes nothing returns nothing
            local RectV r = RectV(this)
            local CellV c = CellV(this)
            
            loop
                exitwhen r.c == 0
                
                call this.clearRectById(r.c)
                
                set r.c = r.c - 1
            endloop
            
            loop
                exitwhen c.c == 0
                
                call this.clearCellById(c.c)
                
                set c.c = c.c - 1
            endloop
        endmethod
        
        method destroy takes nothing returns nothing
            local RectV r = RectV(this)
            local CellV c = CellV(this)
            
            loop
                exitwhen r.c == 0
                
                call r.unregister(r.c)
                
                set r.c = r.c - 1
            endloop
            
            loop
                exitwhen c.c == 0
                
                call c.unregister(c.c)
                
                set c.c = c.c - 1
            endloop
            
            call RemoveRegion(this.region)
            
            set        this.ir = thistype(0).ir
            set thistype(0).ir = this
        endmethod
    endstruct
endlibrary
 
Last edited:
I recommend improving your function names. cC could be renamed to createCell, for example.

Why does the Table version use locations but the hashtable version uses coordinates? They should both function the same each instance of Table can store the values -2^31 up to 2^31-1, so you can add 8192 and 8192*2 to your indices just the same. Plus you leak some handle ID's with the current use of locations.
 
Level 7
Joined
Apr 30, 2011
Messages
359
i use cC and cA for shorther function calls
see this: local Region r = cellCreate(100, 100).cellAdd(200, 200).cellAdd(300, 300)
this is shorter: local Region r = cC(100, 100).cA(200, 200).cA(300, 300)

and for that location thing, i'll fix it later xD
 
Since your API is really messed up, I highlighted the changes I feel make things way more intuitive and readable.

JASS:
//========================================================================================
//
//      Region Utilities
//      -*- overcold_ice -*-
//
//     -[*] Requirements:
//          - JNGP
//          - latest version of JassHelper
//
//     -[*] Optional Requirements:
//          - /*New*/ Table             hiveworkshop.com/forums/showthread.php?t=188084
//
//          For your region-manipulating needs
//      This system provides easier and dynamic region-handling.
//      Besides providing easy to use APIs to create/add/destroy regions, this library
//      also stores what it contains (rects and cells).
//
//     -[*] API:
//
//      struct Region extends array
//          static method create takes nothing returns Region
//              creates an empty region
//
//          static method operator fromRect takes rect r returns Region
//              creates a region and adds rect r to it
//
//          method operator addRect takes rect r returns Region
//              adds a rect to the region
//
//          static method fromCell takes real x, real y returns Region
//              creates a region and adds cell [x, y] to it
//
//          method addCell takes real x, real y returns Region
//              adds a cell [x, y] to the region
//
//          method operator region takes nothing returns region
//              returns the 'real' region
//
//          method operator rect[] takes integer i returns rect
//              returns a rect from given rect number
//
//          method rect.getId takes rect r returns integer
//              returns the rect number of rect r
//
//          method operator cell.x[] takes integer i returns real
//          method operator cell.y[] takes integer i returns real
//              returns the x coordinate of a cell from given cell number
//
//          method cell.getId takes real x, real y returns integer
//              returns the cell number of cell [x, y]
//
//          method clearRectById takes integer i returns nothing
//              removes a rect of given rect number from the region
//
//          method clearCellById takes integer i returns nothing
//              removes a cell of given cell number from the region
//
//          method clear takes nothing returns nothing
//              clears the regions from all rects and cells
//
//          method destroy takes nothing returns nothing
//              destroys the region
//
//     -[*] Required Example:
//
//          local Region reg1 = Region.fromCell(x1, y1).addCell(x2, y2).addCell(x3, y3)
//          local Region reg2
//          set reg1 = reg1 [r1] [r2] [r3] [r4] [r5] [r6]
//          set reg2 = Region.fromRect(r1).addCell(x1, y1) [r2] [r3].addCell(x2, y2).addCell(x3, y3)
//
//          List of rect/cell numbers:
//                      NUM   RECT        CELL
//              reg1:
//                       1     r1         x1y1
//                       2     r2         x2y2
//                       3     r3         x3y3
//                       4     r4
//                       5     r5
//                       6     r6
//              reg2:
//                       1     r1         x1y1
//                       2     r2         x2y2
//                       3     r3         x3y3
//
//========================================================================================
library RegionUtils requires optional /*New*/Table
    
    static if not LIBRARY_Table then
        private struct T extends array
            static hashtable t = InitHashtable()
        endstruct
    endif
    
    private struct RectV extends array
        integer c
        
        static if LIBRARY_Table then
            Table t
        endif
        
        method register takes rect r returns nothing
            set this.c = this.c + 1
            
            static if LIBRARY_Table then
                if this.t == 0 then
                    set this.t = Table.create()
                endif
                
                set this.t.rect [this.c] = r
            else
                call SaveRectHandle(T.t, this, this.c, r)
            endif
        endmethod
        
        method unregister takes integer i returns nothing
            local integer m = this.c
            
            call RemoveRect(this.t.rect [i])
            
            loop
                exitwhen i == m
                
                static if LIBRARY_Table then
                    set this.t.rect [i] = this.t.rect [i + 1]
                else
                    call SaveRectHandle(T.t, this, i, LoadRectHandle(t, this, i + 1))
                endif
                
                set i = i + 1
            endloop
            
            call RemoveRect(this.t.rect [m])
            set this.c = this.c - 1
            
            static if LIBRARY_Table then
                call this.t.handle.remove(m)
                
                if this.c == 0 then
                    call this.t.destroy()
                endif
            else
                call RemoveSavedHandle(T.t, this, m)
            endif
        endmethod
    endstruct
    
    @private @struct RectO extends array
        method operator [] takes integer i returns rect
            static if LIBRARY_Table then
                return RectV(this).t.rect [i]
            else
                return LoadRectHandle(T.t, this, i)
            endif
        endmethod
        
        method @getId@ takes rect r returns integer
            local integer l = 1
            
            loop
                exitwhen l == RectV(this).c
                
                if this [l] == r then
                    return l
                endif
                
                set l = l + 1
            endloop
            
            return 0
        endmethod
    endstruct
    
    private struct CellV extends array
        integer c
        
        static if LIBRARY_Table then
            TableArray t
        endif
        
        method register takes real x, real y returns nothing
            set this.c = this.c + 1
            
            static if LIBRARY_Table then
                if this.t == 0 then
                    set this.t = TableArray [2]
                endif
                
                set this.t [1].real [this.c] = x
                set this.t [2].real [this.c] = y
            else
                call SaveReal(T.t, this +  8192, this.c, x)
                call SaveReal(T.t, this + 16384, this.c, y)
            endif
        endmethod
        
        method unregister takes integer i returns nothing
            local integer m = this.c
            
            loop
                exitwhen i == m
                
                static if LIBRARY_Table then
                    set this.t [1].real [i] = this.t [1].real [i + 1]
                    set this.t [2].real [i] = this.t [2].real [i + 1]
                else
                    call SaveReal(T.t, this +  8192, i, LoadReal(t, this +  8192, i + 1))
                    call SaveReal(T.t, this + 16384, i, LoadReal(t, this + 16384, i + 1))
                endif
                
                set i = i + 1
            endloop
            
            set this.c = this.c - 1
            
            static if LIBRARY_Table then
                call this.t [1].real.remove(m)
                call this.t [2].real.remove(m)
                
                if this.c == 0 then
                    call this.t.destroy()
                endif
            else
                call RemoveSavedReal(T.t, this +  8192, m)
                call RemoveSavedReal(T.t, this + 16384, m)
            endif
        endmethod
    endstruct
    
    private struct CellX extends array
        method operator [] takes integer i returns real
            static if LIBRARY_Table then
                return CellV(this).t [1].real [i]
            else
                return LoadReal(T.t, this +  8192, i)
            endif
        endmethod
    endstruct
    
    private struct CellY extends array
        method operator [] takes integer i returns real
            static if LIBRARY_Table then
                return CellV(this).t [2].real [i]
            else
                return LoadReal(T.t, this + 16384, i)
            endif
        endmethod
    endstruct
    
    @private @struct CellO
        method operator x takes nothing returns CellX
            return this
        endmethod
        
        method operator y takes nothing returns CellY
            return this
        endmethod
        
        method @getId@ takes real x, real y returns integer
            local integer  l = 1
            
            loop
                exitwhen l == CellV(this).c
                
                if this.x [l] == x and this.y [l] == y then
                    return l
                endif
                
                set l = l + 1
            endloop
            
            return 0
        endmethod
    endstruct
    
    struct Region extends array
        private        thistype ir
        private static thistype ic
        
        readonly region region
        
        static method create takes nothing returns thistype
            local thistype this = thistype(0).ir
            
            if this == 0 then
                set .ic   = .ic + 1
                set this  = .ic
            else
                set thistype(0).ir = this.ir
            endif
            
            set this.reg = CreateRegion()
            
            return this
        endmethod
        
        method @addRect@ rect r returns thistype
            call RegionAddRect(this.reg, r)
            call RectV(this).register(r)
            
            return this
        endmethod
        
        static method @fromRect@ takes rect r returns thistype
            @return Region.create().addRect(r)@
        endmethod
        
        method @addCell@ takes real x, real y returns thistype
            call RegionAddCell(this.reg, x, y)
            call CellV(this).register(x, y)
            
            return this
        endmethod
        
        static method @fromCell@ takes real x, real y returns thistype
            @return Region.create().addCell(x, y)@
        endmethod
        
        method operator rect takes nothing returns RectO
            return this
        endmethod
        
        method operator cell takes nothing returns CellO
            return this
        endmethod
        
        method @clear@Rect@ById@ takes integer i returns nothing
            call RegionClearRect(this.reg, this.rect [i])
            call RectV(this).unregister(i)
        endmethod
        
        method @clear@Cell@ById@ takes integer i returns nothing
            call RegionClearCell(this.reg, this.cell.x [i], this.cell.y [i])
            call CellV(this).unregister(i)
        endmethod
        
        method clear takes nothing returns nothing
            local RectV r = RectV(this)
            local CellV c = CellV(this)
            
            loop
                exitwhen r.c == 0
                
                call this.@clear@Rect@ById@(r.c)
                
                set r.c = r.c - 1
            endloop
            
            loop
                exitwhen c.c == 0
                
                call this.@clear@Cell@ById@(c.c)
                
                set c.c = c.c - 1
            endloop
        endmethod
        
        method destroy takes nothing returns nothing
            local RectV r = RectV(this)
            local CellV c = CellV(this)
            
            loop
                exitwhen r.c == 0
                
                call r.unregister(r.c)
                
                set r.c = r.c - 1
            endloop
            
            loop
                exitwhen c.c == 0
                
                call c.unregister(c.c)
                
                set c.c = c.c - 1
            endloop
            
            call RemoveRegion(this.reg)
            
            set        this.ir = thistype(0).ir
            set thistype(0).ir = this
        endmethod
    endstruct
endlibrary
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
overlord, here is the big question. Would you ever use this system for anything? Or did you just submit it because you thought it might be cool to code?

The reason Bribe asked for a demo map is because this resource appears to be completely useless ;\.


If you yourself would never use this for anything, then why should this be approved?


Submit resources out of necessity, not out of some sort of weird cool factor ;p. If you want the cool factor, put it up in Triggers & Scripts and tell everyone how cool it is.
 
Last edited:
Top