• 🏆 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!

ImageBars 1.1.3

  • Like
Reactions: hell gate
To make it short, after messing around with images for some time and after rewriting TextSplat, i found using TextTags for bars a terrible approach (especially since its HARD to center those bars). So i wrote a library to display bars out of images.

This library uses vJass, ARGB and ImageUtils.

ImageBar with full alpha background filling from left to right:
ImageBars_01.jpg


ImageBar with full alpha background filling from right to left:
ImageBars_02.jpg


ImageBar with full alpha background filling from bottom to top:
ImageBars_03.jpg


ImageBar with full alpha background filling from top to bottom:
ImageBars_04.jpg




21/11/2009 - Version 1.0.0
- initial release

27/11/2009 - Version 1.1.0
- increased TICK to 1./40 to increase performance
- made the Z position of ImageBars relative to the Z of the ground
- added a way to get the color of each layer of a bar
- added a method to get the unit the bar is currently locked to
- added some more samples to the testmap
- included more sophisticated base images for bars based off of images included in Ammorth's MultiBar system.

08/12/2009 - Version 1.1.1
- added a Z offset from the unit the bar is currently locked to.
- integrated some samples into the test code (and fixed the samples' code).

23/01/10 - Version 1.1.2
- corrected documentation errors

28/02/2010 - Version 1.1.3
- fixed errors from ImageUtils popping up


Library Code + Credits
JASS:
// *************************************************************
// *                ImageBars -- Version 1.1.3
// *                        by Deaod
// *************************************************************
// *
// *    CREDITS:
// *        - Anitarf and Rising_Dusk (Help, Suggestions)
// *        - Vexorian (JassHelper, ARGB)
// *        - MindWorX and PitzerMike (JassNewGenPack)
// *        - Pipedream (Grimoire)
// *        - SFilip (TESH)
// *
// *        - grim001 (AutoIndex)
// *        - cohadar (some snippets from PUI i used)
// *        - zwiebelchen (original CastingBar library)
// *
// *    HOW TO IMPORT:
// *        * C'n'P the code into your map
// *        * If you haven't done that already, import ARGB into your map
// *        * Import the images you want to use for the bars
// *
// *    DESCRIPTION:
// *
// *    I'll use this approach for this library, since documenting
// *    the whole API in detail would be a pain in the ass for 
// *    both you and me.
// *
// *    You can create a new imagebar using the following function:
// *        static method create takes string bgimage, string fgimage, real sizex, real sizey, real x, real y, real z returns thistype
// *    Note that sizex and sizey are the initial dimensions for
// *    both, back- and foreground, and that the initial offset
// *    of the foreground is 0 in both directions (X and Y).
// *    Also note that as of Version 1.1.0 all z heights are offsets
// *    from the height of the ground at the origin of the bar.
// *
// *    But what good is a bar when you cant fill it? Nothing,
// *    so here's how you actually fill the bar:
// *    By changing the percentFill instance member. Valid values
// *    range from 0 to 1.
// *
// *    By default the bar is horizontal and fills from left to right.
// *    This can be changed using the following method:
// *        method setOrientation takes boolean horizontal, boolean righttoleft returns nothing
// *    Note that righttoleft becomes uptodown if horizontal is true.
// *
// *    ImageBars consist of up to three layers. A foreground,
// *    a background and optionally a mask.
// *    The background is rendered below the foreground, and the
// *    mask in turn is rendered above the foreground.
// *    The position of the image is the lower left corner
// *    of the BACKGROUND. The foreground and the mask can be
// *    offset from that position individually.
// *
// *    Foreground and background are activated by default. You
// *    can add a mask by calling the instance method addMask.
// *        method addMask takes string maskimage, ARGB color, real sizex, real sizey, real offx, real offy returns nothing
// *    You can adjust the mask using the following methods:
// *        method setMaskOffset takes real offx, real offy returns nothing
// *        method setMaskSize takes real sizex, real sizey returns nothing
// *        method setMaskImage takes string maskimage returns nothing
// *        method setMaskColor takes ARGB color returns nothing
// *    Additionally, you can use addMask to combine these methods.
// *    Should you ever decide not to use a mask at runtime anymore,
// *    you can remove the mask using the following method:
// *        method removeMask takes nothing returns nothing
// *    You can get the color of the mask using the following method:
// *        method getMaskColor takes nothing returns ARGB
// *
// *    You can adjust the foreground using the following methods:
// *        method adjustForeground takes string fgimage, ARGB color, real sizex, real sizey, real offx, real offy returns nothing
// *        method setForegroundOffset takes real offx, real offy returns nothing
// *        method setForegroundSize takes real sizex, real sizey returns nothing
// *        method setForegroundImage takes string fgimage returns nothing
// *        method setForegroundColor takes ARGB color returns nothing
// *    You can get the color of the foreground using the following method:
// *        method getForegroundColor takes nothing returns ARGB
// *
// *    You can adjust the background using the following methods:
// *        method adjustBackground takes string bgimage, ARGB color, real sizex, real sizey returns nothing
// *        method setBackgroundSize takes real sizex, real sizey returns nothing
// *        method setBackgroundImage takes string bgimage returns nothing
// *        method setBackgroundColor takes ARGB color returns nothing
// *    You can get the color of the background using the following method:
// *        method getBackgroundColor takes nothing returns ARGB
// *
// *    You can change the position of the imagebar using the
// *    following method:
// *        method setPosition takes real x, real y, real z returns nothing
// *    Additionally, there are the variables x, y and z, which
// *    can be changed individually.
// *
// *    If you want the bar to follow a unit, use the method
// *    lockToUnit.
// *        method lockToUnit takes unit which, real offx, real offy, real offz returns nothing
// *    which is the unit you want to lock the bar to; offx, offy and
// *    offz are the offset in the respective direction from the
// *    origin of the unit.
// *    You can adjust the offset from the unit by using the
// *    following method:
// *        method setOffset takes real offx, real offy, real offz returns nothing
// *    If you want to unlock the bar, you can either pass "null"
// *    as the unit parameter to lockToUnit, or you can use the
// *    following method:
// *        method unlock takes nothing returns nothing
// *    Should you want to access the unit the bars locked to, use
// *    the following method:
// *        method getUnitLockedTo takes nothing returns unit
// *    NOTE: While being locked to a unit, you cant change the
// *    position of the bar freely.
// *    Also note, that changing the offset is only possible when the
// *    bar is locked to a unit.
// *
// *    You can show and hide the imagebar at will by changing
// *    the "show" member. true shows the imagebar, false hides
// *    it.
// *
// *    You can make imagebars wrap to the terrain by changing
// *    the "wrap" member. true wraps the imagebar to the ground,
// *    false doesnt.
// *    Note that while being wrapped to the ground, changing the
// *    Z position of the imagebar wont have any effect.
// *
// *    You can destroy an imagebar using the following method:
// *        method destroy takes nothing returns nothing
// *
// *************************************************************
library ImageBars uses ARGB, ImageUtils
    
    globals
        private constant    real                    TICK                        = 1./40 // frequency of syncing bars with position of units theyre locked to
        
        private constant    integer                 DEFAULT_BACKGROUND_COLOR    = 0xFFFFFFFF
        private constant    integer                 DEFAULT_FOREGROUND_COLOR    = 0xFF002040
        
        private constant    integer                 BACKGROUND_IMAGE_TYPE       = IMAGE_TYPE_INDICATOR // 2 // lowest layer
        private constant    integer                 FOREGROUND_IMAGE_TYPE       = IMAGE_TYPE_OCCLUSION_MASK // 3 // middle layer
        private constant    integer                 MASK_IMAGE_TYPE             = IMAGE_TYPE_SELECTION // 1 // top layer
    endglobals
    
    struct imagebar
        private imagex FG
        private imagex BG
        
        // position of the bar
        private real X
        private real Y
        private real Z
        
        // Colors
        private ARGB BGColor
        private ARGB FGColor
        
        // OffX/Y is the offset when locked to a unit
        // FGOffX/Y is always active
        private real OffX
        private real OffY
        private real OffZ
        private real FGOffX
        private real FGOffY
        
        // SizeX/Y is the size of the background
        // FGSizeX/Y is the maximum size of the foreground.
        private real SizeX
        private real SizeY
        private real FGSizeX
        private real FGSizeY
        
        // Mask
        private boolean Mask=false
        private imagex MI // mask image
        private ARGB MaskColor
        private real MaskSizeX
        private real MaskSizeY
        private real MaskOffX
        private real MaskOffY
        
        private real Value=0.
        private boolean Show=true
        private boolean Wrap=false
        
        private boolean Locked=false
        private unit Which=null
        
        private boolean Horizontal=true
        private boolean RightToLeft=false // UpToDown, if Horizontal is false
        
        private integer i
        
        private static thistype array Structs
        private static integer Count=0
        private static timer T=CreateTimer()
        
        private static location LocZ=Location(0,0)
        
        // private methods
        
        private static method GetPointZ takes real x, real y returns real
            call MoveLocation(.LocZ, x, y)
            return GetLocationZ(.LocZ)
        endmethod
        
        private static method GetUnitZ takes unit u returns real
            return .GetPointZ(GetUnitX(u), GetUnitY(u))+GetUnitFlyHeight(u)
        endmethod
        
        private method GetZ takes nothing returns real
            if .Locked then
                return .GetUnitZ(.Which)+.OffZ
            else
                return .GetPointZ(.X, .Y)+.Z
            endif
        endmethod
        
        private method MapForeground takes string fgimage returns nothing
            call .FG.destroy()
            if .Horizontal then
                if .RightToLeft then
                    set .FG=imagex.create(fgimage, .Value*.FGSizeX, .FGSizeY, .X+.FGOffX+.OffX+(1-.Value)*.FGSizeX, .Y+.FGOffY+.OffY, .GetZ(), .Show)
                else
                    set .FG=imagex.create(fgimage, .Value*.FGSizeX, .FGSizeY, .X+.FGOffX+.OffX, .Y+.FGOffY+.OffY, .GetZ(), .Show)
                endif
            else
                if .RightToLeft then
                    set .FG=imagex.create(fgimage, .FGSizeX, .Value*.FGSizeY, .X+.FGOffX+.OffX, .Y+.FGOffY+.OffY+(1-.Value)*.FGSizeY, .GetZ(), .Show)
                else
                    set .FG=imagex.create(fgimage, .FGSizeX, .Value*.FGSizeY, .X+.FGOffX+.OffX, .Y+.FGOffY+.OffY, .GetZ(), .Show)
                endif
            endif
            set .FG.type=FOREGROUND_IMAGE_TYPE
            set .FG.color=.FGColor
        endmethod
        
        private static method Callback takes nothing returns nothing
        local integer i=.Count-1
        local thistype s
        local real dx
        local real dy
        local real x
        local real y
        local real z
            loop
                exitwhen i<0
                set s=.Structs[i]
                set x=GetUnitX(s.Which)
                set y=GetUnitY(s.Which)
                set dx=x-s.X
                set dy=y-s.Y
                set s.X=x
                set s.Y=y
                set z=.GetUnitZ(s.Which)+s.OffZ
                call s.BG.setPosition(s.BG.x+dx, s.BG.y+dy, z)
                if s.Mask then
                    call s.MI.setPosition(s.MI.x+dx, s.MI.y+dy, z)
                endif
                call s.FG.setPosition(s.FG.x+dx, s.FG.y+dy, z)
                set i=i-1
            endloop
        endmethod
        
        // Foreground related methods
        
        method adjustForeground takes string fgimage, ARGB color, real sizex, real sizey, real offx, real offy returns nothing
            set .FGOffX=-offx
            set .FGOffY=-offy
            set .FGSizeX=sizex
            set .FGSizeY=sizey
            set .FGColor=color
            call .MapForeground(fgimage)
        endmethod
        
        method setForegroundOffset takes real offx, real offy returns nothing
        local real dx=-.FGOffX-offx
        local real dy=-.FGOffY-offy
            set .FGOffX=-offx
            set .FGOffY=-offy
            call .FG.setPosition(.FG.x+dx, .FG.y+dy, .GetZ())
        endmethod
        
        method setForegroundSize takes real sizex, real sizey returns nothing
            set .FGSizeX=sizex
            set .FGSizeY=sizey
            call .MapForeground(.FG.path)
        endmethod
        
        method setForegroundImage takes string fgimage returns nothing
            set .FG.path=fgimage
        endmethod
        
        method getForegroundColor takes nothing returns ARGB
            return .FGColor
        endmethod
        method setForegroundColor takes ARGB color returns nothing
            set .FGColor=color
            set .FG.color=color
        endmethod
        
        // Background related methods
        
        method adjustBackground takes string bgimage, ARGB color, real sizex, real sizey returns nothing
            set .SizeX=sizex
            set .SizeY=sizey
            set .BGColor=color
            call .BG.destroy()
            set .BG=imagex.create(bgimage, sizex, sizey, .X+OffX, .Y+.OffY, .GetZ(), .Show)
            set .BG.type=BACKGROUND_IMAGE_TYPE
            set .BG.color=color
        endmethod
        
        method setBackgroundSize takes real sizex, real sizey returns nothing
            set .SizeX=sizex
            set .SizeY=sizey
            call .BG.setSize(sizex, sizey)
        endmethod
        
        method setBackgroundImage takes string bgimage returns nothing
            set .BG.path=bgimage
        endmethod
        
        method getBackgroundColor takes nothing returns ARGB
            return .BGColor
        endmethod
        method setBackgroundColor takes ARGB color returns nothing
            set .BGColor=color
            set .BG.color=color
        endmethod
        
        // Mask related methods
        
        method addMask takes string maskimage, ARGB color, real sizex, real sizey, real offx, real offy returns nothing
            if .Mask then
                call .MI.destroy()
            endif
            set .MI=imagex.create(maskimage, sizex, sizey, .X+.OffX+offx, .Y+.OffY+offy, .GetZ(), .Show)
            set .MI.type=MASK_IMAGE_TYPE
            set .MI.color=color
            set .MaskColor=color
            set .MaskSizeX=sizex
            set .MaskSizeY=sizey
            set .MaskOffX=offx
            set .MaskOffY=offy
            set .Mask=true
        endmethod
        
        method removeMask takes nothing returns nothing
            if .Mask then
                call .MI.destroy()
                set .Mask=false
            endif
        endmethod
        
        method setMaskImage takes string maskimage returns nothing
            if .Mask then
                set .MI.path=maskimage
            endif
        endmethod
        
        method getMaskColor takes nothing returns ARGB
            return .MaskColor
        endmethod
        method setMaskColor takes ARGB color returns nothing
            if .Mask then
                set .MaskColor=color
                set .MI.color=color
            endif
        endmethod
        
        method setMaskSize takes real sizex, real sizey returns nothing
            if .Mask then
                set .MaskSizeX=sizex
                set .MaskSizeY=sizey
                call .MI.setSize(sizex, sizey)
            endif
        endmethod
        
        method setMaskOffset takes real offx, real offy returns nothing
        local real dx=offx-.MaskOffX
        local real dy=offy-.MaskOffY
            if .Mask then
                set .MaskOffX=offx
                set .MaskOffY=offy
                call .MI.setPosition(.MI.x+dx, .MI.y+dy, .GetZ())
            endif
        endmethod
        
        // General methods
        
        static method create takes string bgimage, string fgimage, real sizex, real sizey, real x, real y, real z returns thistype
        local thistype s=.allocate()
            set s.BG=imagex.create(bgimage, sizex, sizey, x, y, .GetPointZ(x,y)+z, true)
            set s.FG=imagex.create(fgimage, 1, sizey, x, y, .GetPointZ(x,y)+z, true)
            set s.X=x
            set s.Y=y
            set s.Z=z
            set s.BGColor=ARGB(DEFAULT_BACKGROUND_COLOR)
            set s.FGColor=ARGB(DEFAULT_FOREGROUND_COLOR)
            
            set s.SizeX=sizex
            set s.SizeY=sizey
            set s.FGSizeX=sizex
            set s.FGSizeY=sizey
            return s
        endmethod
        
        method operator percentFill takes nothing returns real
            return .Value
        endmethod
        
        method operator percentFill= takes real new returns nothing
            set .Value=new
            if .Value>1. then
                set .Value=1.
            elseif .Value<0. then
                set .Value=0.
            endif
            call .MapForeground(.FG.path)
        endmethod
        
        method setOrientation takes boolean horizontal, boolean righttoleft returns nothing
            set .Horizontal=horizontal
            set .RightToLeft=righttoleft
            call .MapForeground(.FG.path)
        endmethod
        
        method operator x takes nothing returns real
            return .X
        endmethod
        method operator y takes nothing returns real
            return .Y
        endmethod
        method operator z takes nothing returns real
            return .Z
        endmethod
        
        method operator x= takes real new returns nothing
        local real dx=new-.X
            if not .Locked then
                set .X=new
                set .BG.x=.BG.x+dx
                set .FG.x=.FG.x+dx
                if .Mask then
                    set .MI.x=.MI.x+dx
                endif
            endif
        endmethod
        method operator y= takes real new returns nothing
        local real dy=new-.Y
            if not .Locked then
                set .Y=new
                set .BG.y=.BG.y+dy
                set .FG.y=.FG.y+dy
                if .Mask then
                    set .MI.y=.MI.y+dy
                endif
            endif
        endmethod
        method operator z= takes real new returns nothing
        local real dz=new-.Z
            if not .Locked then
                set .Z=new
                set .BG.z=.BG.z+dz
                set .FG.z=.FG.z+dz
                if .Mask then
                    set .MI.z=.MI.z+dz
                endif
            endif
        endmethod
        
        method setPosition takes real x, real y, real z returns nothing
        local real dx=x-.X
        local real dy=y-.Y
        local real nz
            if not .Locked then
                set .X=x
                set .Y=y
                set .Z=z
                set nz=.GetPointZ(.BG.x+dx, .BG.y+dy)+.Z
                call .BG.setPosition(.BG.x+dx, .BG.y+dy, nz)
                if .Mask then
                    call .MI.setPosition(.MI.x+dx, .MI.y+dy, nz)
                endif
                call .FG.setPosition(.FG.x+dx, .FG.y+dy, nz)
            endif
        endmethod
        
        method unlock takes nothing returns nothing
            if .Locked then
                set .Which=null
                set .Locked=false
                call .BG.setPosition(.BG.x-.OffX, .BG.y-.OffY, .GetPointZ(.BG.x-.OffX, .BG.y-.OffY)+.Z)
                if .Mask then
                    call .MI.setPosition(.MI.x-.OffX, .MI.y-.OffY, .GetPointZ(.MI.x-.OffX, .MI.y-.OffY)+.Z)
                endif
                call .MapForeground(.FG.path)
                set .OffX=0
                set .OffY=0
                
                set .Count=.Count-1
                set .Structs[.i]=.Structs[.Count]
                set .Structs[.i].i=.i
                if .Count==0 then
                    call PauseTimer(.T)
                endif
            endif
        endmethod
        
        method lockToUnit takes unit which, real offx, real offy, real offz returns nothing
            if which==null then
                call .unlock()
            elseif .Locked then
                set .Which=which
                set .OffZ=offz
                call .BG.setPosition(.BG.x+(offx-.OffX), .BG.y+(offy-.OffY), .GetZ())
                if .Mask then
                    call .MI.setPosition(.MI.x+(offx-.OffX), .MI.y+(offy-.OffY), .GetZ())
                endif
                call .MapForeground(.FG.path)
                set .OffX=offx
                set .OffY=offy
            else
                set .Locked=true
                set .Which=which
                set .OffX=offx
                set .OffY=offy
                set .OffZ=offz
                call .BG.setPosition(.BG.x+offx, .BG.y+offy, .GetZ())
                if .Mask then
                    call .MI.setPosition(.MI.x+offx, .MI.y+offy, .GetZ())
                endif
                call .MapForeground(.FG.path)
                
                set .Structs[.Count]=this
                set .i=.Count
                if .Count==0 then
                    call TimerStart(.T, TICK, true, function thistype.Callback)
                endif
                set .Count=.Count+1
            endif
        endmethod
        
        method getUnitLockedTo takes nothing returns unit
            return .Which
        endmethod
        
        method setOffset takes real offx, real offy, real offz returns nothing
        local real dx
        local real dy
            if .Locked then
                set dx=offx-.OffX
                set dy=offy-.OffY
                set .OffX=offx
                set .OffY=offy
                set .OffZ=offz
                call .BG.setPosition(.BG.x+dx, .BG.y+dy, .GetUnitZ(.Which)+.OffZ)
                if .Mask then
                    call .MI.setPosition(.MI.x+dx, .MI.y+dy, .GetUnitZ(.Which)+.OffZ)
                endif
                call .MapForeground(.FG.path)
            endif
        endmethod
        
        method operator show takes nothing returns boolean
            return .Show
        endmethod
        
        method operator show= takes boolean new returns nothing
            set .Show=new
            set .BG.show=new
            if .Mask then
                set .MI.show=new
            endif
            set .FG.show=new
        endmethod
        
        method operator wrap takes nothing returns boolean
            return .Wrap
        endmethod
        
        method operator wrap= takes boolean new returns nothing
            set .Wrap=new
            set .BG.wrap=new
            if .Mask then
                set .MI.wrap=new
            endif
            set .FG.wrap=new
        endmethod
        
        method onDestroy takes nothing returns nothing
            if .Locked then
                call .unlock()
            endif
            if .Mask then
                call .MI.destroy()
            endif
            call .BG.destroy()
            call .FG.destroy()
        endmethod
    endstruct
    
endlibrary
Test Code
JASS:
library Test initializer Init requires ImageBars, ARGB
    
    globals
        private constant real TICK = 1./32
        private integer MODE
        private real TIME=5. // seconds
        private imagebar ib
    endglobals
    
    private function Callback takes nothing returns nothing
    local real new
        if MODE==0 then
            set new=ib.percentFill+(1./TIME*TICK)
            if new>1 then
                set MODE=1
                call ib.setOrientation(true, true)
                set ib.percentFill=0
            else
                set ib.percentFill=new
            endif
        elseif MODE==1 then
            set new=ib.percentFill+(1./TIME*TICK)
            if new>1 then
                set MODE=2
                call ib.setOrientation(false, false)
                set ib.percentFill=0
                call ib.setForegroundSize(64, 512)
                call ib.setForegroundImage("war3mapimported\\ExperienceFG2.tga")
                call ib.setBackgroundSize(64, 512)
                call ib.setMaskSize(68,516)
                call ib.setMaskImage("war3mapimported\\ExperienceMask3.tga")
                call ib.setOffset(0, -256)
            else
                set ib.percentFill=new
            endif
        elseif MODE==2 then
            set new=ib.percentFill+(1./TIME*TICK)
            if new>1 then
                set MODE=3
                call ib.setOrientation(false, true)
                set ib.percentFill=0
            else
                set ib.percentFill=new
            endif
        elseif MODE==3 then
            set new=ib.percentFill+(1./TIME*TICK)
            if new>1 then
                call PauseTimer(GetExpiredTimer())
                call ib.destroy()
            else
                set ib.percentFill=new
            endif
        endif
    endfunction
    
    private function Init takes nothing returns nothing
    //string bgimage, string fgimage, real sizex, real sizey, real x, real y, real z
    local unit u=CreateUnit(Player(0), 'hfoo', 0,0,0)
        set ib=imagebar.create("war3mapimported\\Minimal.blp", "war3mapimported\\ExperienceFG.tga", 512, 64, 0,0,0)
        call ib.setForegroundColor(0xFFFFFFFF)
        call ib.addMask("war3mapimported\\ExperienceMask2.tga", 0xFFFFFFFF, 516,68,-2,-2)
        call ib.lockToUnit(u, -256, 0)
        set ib.wrap=true
        call SetCameraPosition(0,0)
        set MODE=0
        call TimerStart(CreateTimer(), TICK, true, function Callback)
    endfunction
    
endlibrary

There are four more samples inside the testmap.

Keywords:
Custom, image, bar
Contents

ImageBars (Map)

Reviews
03:17, 24th Nov 2009 TriggerHappy: This is neat. Though, there is no reason to give credits to Sfilip for TESH. It's not required to have TESH.

Moderator

M

Moderator

03:17, 24th Nov 2009
TriggerHappy:

This is neat. Though, there is no reason to give credits to Sfilip for TESH. It's not required to have TESH.
 
Top