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

Custom Bar Library 1.5.0

Yet another system to create custom bars based off of texttags.
Whats so special about it? Well, this one was built for the many ways there are to use custom bars (its not limited to displaying a units current mana or health).

This uses vJass and requires ARGB and TimerUtils.

12/13/08 - Version 1.0
- initial release

02/22/09 - Version 1.0.1
- removed TTBase
- cleaned up the API (removed RemoveGradient and added better encapsulation)
- fixed a bug, where you couldnt add MAX_GRADIENTS gradients
- a few other minor improvements

03/16/2009 - Version 1.1.0
- heavy API changes, mainly in relation to background coloring (uses ARGB now)
- Bars are now initialized to be displayed to all players by default
- Adding no gradients or insufficient gradients is now handled gracefully
- each bar can now have distinct primitive strings ("|" gets converted to "||" automatically to avoid some problems)
- some speed improvements
- documented what i left out initially

03/17/2009 - Version 1.2.0
- more API changes, this time in relation to coloring the Bar.
- Added the SetForeground method and a default gradient parameter to the create method. You can now select a default gradient on a per-bar basis.
- separated the Gradients from the initial TTBar struct. The new struct is called TTGradBar and inherits all members and methods TTBar has.

03/17/2009 - Version 1.3.0
- unified API to use ARGB
- removed parameter of the create method for defining a default gradient. Added a global to fill in that parameter.
- corrected the way SetForeground behaves (in TTGradBar structs). Gradients now take precedence over the color specified by this method.

03/18/2009 - Version 1.3.1
- reordered some methods as to improve efficiency a bit.

07/02/2009 - Version 1.4.0
- some optimization behind the scenes (complexity for creating the text of the bar changed to O(1))
- added interface for using strings to color the foreground of a bar (AddGradientString, SetForegroundString)
- made the primitive char the bar consists of and the number of primitive chars the bar consists of changeable after creating the bar.

07/29/2009 - Version 1.4.1
- a few bugfixes. Thanks to map-maker for reporting them.

09/10/2009 - Version 1.5.0
- Added the ability to fade out bars (which is another way of destroying it).
- Added an additional demonstration for TTBars based on zwiebelchen's recent submission (credits for it go to him)


JASS:
// *************************************************************
// *                   TTBars -- Version 1.5.0
// *                        by Deaod
// *************************************************************
// *
// *    CREDITS:
// *        - Ammorth (found a bug)
// *        - Anitarf (suggestions)
// *        - Ddyq (helped testing)
// *        - Vexorian (JassHelper, ARGB)
// *        - PitzerMike (JassNewGenPack)
// *        - Pipedream (Grimoire)
// *
// *        - cohadar (used PUI for demonstration purposes)
// *        - zwiebelchen (used a modified version of a script he wrote (CastingBar) for demonstration puposes)
// *
// *    HOW TO USE:
// *        * declare a variable of type TTBar or TTGradBar
// *            - TTGradBar only has the additional feature of adding Gradients. TTBar and TTGradBar are identical in all other regards.
// *
// *        * use [TTBar or TTGradBar].create(string char, integer numochars, real size, real x, real y, real z)
// *            - char is the basic string the bar is made out of
// *            - numochars is the number of chars this bar consits of
// *            - size is the textsize of the bar
// *            - x is the x-coord of the point where this bar is created
// *            - y is the y-coord of the point where this bar is created
// *            - z is the height offset above the ground
// *
// *        * add a gradient by using YourBar.AddGradient(real threshold, ARGB color)
// *            !! This is a feature of TTGradBar. Will not work with TTBar !!
// *            - threshold is the value the bar must be equal to or lower than to apply the color specified in colorstring
// *            - example input would be "ARGB.create(SOME_ALPHA, SOME_RED, SOME_GREEN, SOME_BLUE)" or "0xAARRGGBB"
// *              Look at ARGB's manual for detailed reference
// *            - there exists an alternative version named AddGradientString(real, threshold, string color),
// *              where the color argument is formatted as follows: "|cAARRGGBB"
// *
// *        * you can change the value of the bar at any time by using "set YourBar.Value=newval"
// *            - value is a percentage
// *              --> use 100 to fill it completely, use 0 to display an empty bar
// *
// *        * you can lock this bar to a unit using YourBar.LockToUnit(unit u, real xOffset, real yOffset, real zOffset)
// *            - u is the unit this bar is locked to
// *            - xOffset is the offset in x from the position of the unit the bar is locked to
// *            - yOffset is the offset in y from the position of the unit the bar is locked to
// *            - zOffset is the height offset above ground level
// *
// *        * of course you can also unlock the bar via YourBar.Unlock()
// *
// *        * you can change the foreground color with YourBar.SetForeground(ARGB color)
// *            !! Gradients are preferred over this !!
// *            - example input would be "ARGB.create(SOME_ALPHA, SOME_RED, SOME_GREEN, SOME_BLUE)" or "0xAARRGGBB"
// *              Look at ARGB's manual for detailed reference
// *            - there exitsts an alternative version named SetForegroundString(string color),
// *              which takes a string formatted as follows: "|cAARRGGBB"
// *
// *        * you can change the background color with YouBar.SetBackground(ARGB color)
// *            - example input would be "ARGB.create(SOME_ALPHA, SOME_RED, SOME_GREEN, SOME_BLUE)" or "0xAARRGGBB"
// *              Look at ARGB's manual for detailed reference
// *
// *        * want to show the bar to more players? Use YourBar.ChangeVisibility(force disp)
// *            - disp should contain all players this bar should be displayed to; note that you have to destroy this parameter for yourself
// *              inserting null will show the bar to all players
// *
// *        * you can change the size of the bar any time by using "set YourBar.Size=newval"
// *
// *        * you can read and write a bar's X, Y and Z coordinate by using the X, and X= operators (Y and Z respectively as well).
// *          I added another method, YourBar.SetPosXY(real x, real y), which sets the bars X and Y coordinate, for speed reasons.
// *
// *        * you have access to XOffset and YOffset members (both are of type real). They are only important when locking a bar to a unit.
// *          You can probably guess by their names what i added them for.
// *
// *        * you can read/change a bars primitive char by reading/changing the member Char
// *
// *        * you can read/change a bars number of chars by reading/changing the member Width
// *
// *        * you can fade out bars when destroying them using YourBar.FadeOut(real overTime, boolean followThrough, real xVel, real yVel)
// *            - overTime is the time fading should take
// *            - followThrough changes whether the TTBar instance should be destroyed on the spot
// *              of if it should destroy it when the fading is finished
// *              "true" destroys the TTBar instance when the fading is finished
// *              "false" destroys the TTBar instance on the spot
// *            - xVel and yVel can only be used if the Bar is not locked to a unit
// *              and move the bar into x and y direction (respectively) by the amount specified
// *
// *************************************************************

library TTBARS uses ARGB, TimerUtils

    globals
        // TTBar
        private constant    integer         DEFAULT_BACKGROUND  = 0xFF000000 // 0xAARRGGBB // alpha channel is non-functional (blame blizzard for that)
        private constant    real            TICK                = 1./64 // in seconds // how often are bars moved to a units pos?
        
        // TTBar and TTGradBar
        private constant    integer         DEFAULT_FOREGROUND  = 0xFFFFFFFF // 0xAARRGGBB
        
        // TTGradBar
        private constant    integer         MAX_GRADIENTS       = 10 // Maximum number of gradients you can add
    endglobals
    
    // I dont recommend to change anything below this line
    
    globals
        private force tmp
        private TTBar array Bars
        private integer Count=0
        private timer T=CreateTimer()
    endglobals
    
    struct TTBar
        private texttag t
        // background color
        private ARGB bg_color
        // foreground color
        private string fg_color
        // Position
        private real x
        private real y
        private real z
        // Text
        private string txt
        private real textsize
        // locking to units
        private integer lockindex
        private boolean locked
        private unit u
        real XOffset
        real YOffset
        // misc
        private force disp
        private real Value2 // value
        private integer NUM_CHARS // number of chars this bar uses
        private string char // primitive char/string
        private string ptext // primitive text without colors
        
        private static method CopyForce takes nothing returns nothing
            call ForceAddPlayer(tmp, GetEnumPlayer())
        endmethod
        
        private static method LockCallback takes nothing returns nothing
        local integer i=Count-1
        local TTBar s
            loop
                exitwhen i<0
                set s=Bars[i]
                set s.x=GetUnitX(s.u)
                set s.y=GetUnitY(s.u)
                call SetTextTagPos(s.t, s.x+s.XOffset, s.y+s.YOffset, s.z)
                set i=i-1
            endloop
        endmethod
        
        method operator Size takes nothing returns real
            return .textsize/0.0023
        endmethod
        
        method operator Size= takes real size returns nothing
            set .textsize=TextTagSize2Height(size)
        endmethod
        
        method operator Value takes nothing returns real
            return .Value2*100.
        endmethod
        
        method operator Value= takes real newval returns nothing
        local integer chars
        local integer i=0
            // keep newval inside possible boundaries
            if newval>100. then
                set newval=100.
            elseif newval<0. then
                set newval=0.
            endif
            set .Value2=newval/100. // set the new value
            set .txt=.fg_color
            set chars=(R2I((.Value2*.NUM_CHARS*StringLength(.char))+0.5)/StringLength(.char))*StringLength(.char) // calculate the number of chars needed to display the new value
            set .txt=.txt+SubString(.ptext, 0, chars)
            set .txt=.txt+"|r"
            set .txt=.txt+SubString(.ptext, 0, StringLength(.ptext)-chars)
            if .t!=null then
                call SetTextTagText(.t, .txt, .textsize)
            endif
        endmethod
        
        method operator X takes nothing returns real
            return .x
        endmethod
        
        method operator X= takes real x returns nothing
            set .x=x
            if .t!=null and not .locked then
                call SetTextTagPos(.t, .x, .y, .z)
            endif
        endmethod
        
        method operator Y takes nothing returns real
            return .y
        endmethod
        
        method operator Y= takes real y returns nothing
            set .y=y
            if .t!=null and not .locked then
                call SetTextTagPos(.t, .x, .y, .z)
            endif
        endmethod
        
        method operator Z takes nothing returns real
            return .z
        endmethod
        
        method operator Z= takes real z returns nothing
            set .z=z
            if .t!=null then
                call SetTextTagPos(.t, .x, .y, .z)
            endif
        endmethod
        
        method operator Locked takes nothing returns boolean
            return .locked
        endmethod
        
        private method RebuildText takes nothing returns nothing
        local integer i=0
            set .ptext=""
            loop
                exitwhen i>=.NUM_CHARS
                set .ptext=.ptext+.char
                set i=i+1
            endloop
        endmethod
        
        method operator Char takes nothing returns string
            return .char
        endmethod
        
        method operator Char= takes string new returns nothing
            if new=="|" then
                set new="||"
            endif
            set .char=new
            call .RebuildText()
            set .Value=.Value
        endmethod
        
        method operator Width takes nothing returns integer
            return .NUM_CHARS
        endmethod
        
        method operator Width= takes integer new returns nothing
            set .NUM_CHARS=new
            call .RebuildText()
            set .Value=.Value
        endmethod
        
        method SetPosXY takes real x, real y returns nothing // added for speed reasons
            set .x=x
            set .y=y
            if .t!=null and not .locked then
                call SetTextTagPos(.t, .x, .y, .z)
            endif
        endmethod
        
        method SetBackground takes ARGB color returns nothing
            set .bg_color=color
            if .t!=null then
                call SetTextTagColor(.t, .bg_color.red, .bg_color.green, .bg_color.blue, .bg_color.alpha)
            endif
        endmethod
        
        method SetForeground takes ARGB color returns nothing
            set .fg_color=SubString(color.str(""), 0, 10)
            set .Value=.Value
        endmethod
        
        method SetForegroundString takes string color returns nothing
            set .fg_color=color
            set .Value=.Value
        endmethod
        
        method ChangeVisibility takes force disp returns nothing
            if disp!=null then
                if .disp==null then
                    set .disp=CreateForce()
                else
                    call ForceClear(.disp)
                endif
                set tmp=.disp
                call ForForce(disp, function TTBar.CopyForce)
                if IsPlayerInForce(GetLocalPlayer(), .disp) and .t==null then
                    set .t=CreateTextTag()
                    if .t!=null then
                        call SetTextTagColor(.t, .bg_color.red, .bg_color.green, .bg_color.blue, .bg_color.alpha)
                        call SetTextTagText(.t, .txt, .textsize)
                        call SetTextTagPos(.t, .x, .y, .z)
                    debug else
                    debug     call BJDebugMsg("TTBARS: TextTag limit reached!")
                    endif
                elseif .t!=null and not IsPlayerInForce(GetLocalPlayer(), .disp) then
                    call DestroyTextTag(.t)
                    set .t=null
                endif
            else
                if .t==null then
                    set .t=CreateTextTag()
                    if .t!=null then
                        call SetTextTagColor(.t, .bg_color.red, .bg_color.green, .bg_color.blue, .bg_color.alpha)
                        call SetTextTagText(.t, .txt, .textsize)
                        call SetTextTagPos(.t, .x, .y, .z)
                    debug else
                    debug     call BJDebugMsg("TTBARS: TextTag limit reached!")
                    endif
                endif
            endif
        endmethod
        
        method LockToUnit takes unit u, real xOffset, real yOffset, real zOffset returns nothing
            if not .locked then
                set Bars[Count]=this
                set .u=u
                set .locked=true
                set .lockindex=Count
                set .XOffset=xOffset
                set .YOffset=yOffset
                set .Z=zOffset
                if Count==0 then
                    call TimerStart(T, TICK, true, function thistype.LockCallback)
                endif
                set Count=Count+1
            endif
        endmethod
        
        method Unlock takes nothing returns nothing
        local integer i=0
            if not .locked then
                return
            endif
            set Count=Count-1
            if Count==0 then
                call PauseTimer(T)
            endif
            set Bars[.lockindex]=Bars[Count]
            set Bars[Count].lockindex=.lockindex
            set .locked=false
        endmethod
        
        static method create takes string char, integer numochars, real size, real x, real y, real z returns TTBar
        local TTBar s=TTBar.allocate()
            set s.t=CreateTextTag()
            debug if s.t==null then
            debug     call BJDebugMsg("TTBARS: TextTag limit reached!")
            debug endif
            set s.bg_color=ARGB(DEFAULT_BACKGROUND)
            set s.x=x
            set s.y=y
            set s.z=z
            set s.textsize=TextTagSize2Height(size)
            set s.fg_color=SubString(ARGB(DEFAULT_FOREGROUND).str(""), 0, 10)
            set s.NUM_CHARS=numochars
            if char=="|" then // ugly hack
                set s.char="||"
            else
                set s.char=char
            endif
            set s.locked=false
            set s.Value=0
            if s.t!=null then
                call SetTextTagPos(s.t, s.x, s.y, s.z)
                call SetTextTagColor(s.t, s.bg_color.red, s.bg_color.green, s.bg_color.blue, s.bg_color.alpha)
                call SetTextTagText(s.t, s.txt, s.textsize)
            endif
            call s.RebuildText()
            return s
        endmethod
        
        method onDestroy takes nothing returns nothing
            if .t!=null then
                call DestroyTextTag(.t)
                set .t=null
            endif
            if .locked then
                call .Unlock()
                set .u=null
            endif
        endmethod
        
        private static method FadeOutCallback takes nothing returns nothing
        local thistype s=thistype(GetTimerData(GetExpiredTimer()))
            set s.t=null
            call s.destroy()
            call ReleaseTimer(GetExpiredTimer())
        endmethod
        
        method FadeOut takes real overTime, boolean followThrough, real xVel, real yVel returns nothing
        local timer t
            if .t!=null then
                call SetTextTagLifespan(.t, overTime)
                call SetTextTagAge(.t, 0)
                call SetTextTagFadepoint(.t, 0)
                call SetTextTagPermanent(.t, false)
                if not .locked then
                    call SetTextTagVelocity(.t, TextTagSpeed2Velocity(xVel), TextTagSpeed2Velocity(yVel))
                endif
            endif
            if followThrough then
                set t=NewTimer()
                call SetTimerData(t, this)
                call TimerStart(t, overTime, false, function thistype.FadeOutCallback)
            else
                set .t=null
                call .destroy()
            endif
        endmethod
    endstruct
    
    struct TTGradBar
        private delegate TTBar Bar
        
        private string fg_color
        
        private string array GradientColor[MAX_GRADIENTS]
        private real array GradientValue[MAX_GRADIENTS]
        private integer GradCnt
        
        static method create takes string char, integer numochars, real size, real x, real y, real z returns TTGradBar
        local TTGradBar s=TTGradBar.allocate()
            set s.Bar=TTBar.create(char, numochars, size, x, y, z)
            set s.GradCnt=0
            set s.fg_color=SubString(ARGB(DEFAULT_FOREGROUND).str(""), 0, 10)
            return s
        endmethod
        
        method AddGradient takes real threshold, ARGB color returns nothing
            if .GradCnt>=MAX_GRADIENTS then
                debug call BJDebugMsg("TTGradBar: Cannot add any more Gradients to TTGradBar "+I2S(this)+"!")
                return
            endif
            if threshold>100 then
                set threshold=100
            elseif threshold<0 then
                set threshold=0
            endif
            set .GradientValue[.GradCnt]=threshold
            set .GradientColor[.GradCnt]=SubString(color.str(""), 0, 10)
            set .GradCnt=.GradCnt+1
        endmethod
        
        method AddGradientString takes real threshold, string color returns nothing
            if .GradCnt>=MAX_GRADIENTS then
                debug call BJDebugMsg("TTGradBar: Cannot add any more Gradients to TTGradBar "+I2S(this)+"!")
                return
            endif
            if threshold>100 then
                set threshold=100
            elseif threshold<0 then
                set threshold=0
            endif
            set .GradientValue[.GradCnt]=threshold
            set .GradientColor[.GradCnt]=color
            set .GradCnt=.GradCnt+1
        endmethod
        
        method operator Value= takes real newval returns nothing
        local integer i=0
        local real k
        local integer j
        local integer l=0
            // keep newval inside possible boundaries
            if newval>100 then
                set newval=100
            elseif newval<0 then
                set newval=0
            endif
            set k=110 // some value above 100 will work just as well
            // find appropriate gradient
            loop
                exitwhen i>=.GradCnt
                if newval<=.GradientValue[i] and ((.GradientValue[i]-newval)<k) then
                    set k=.GradientValue[i]-newval
                    set j=i
                    set l=l+1 // count how many gradients have been considered for use
                endif
                set i=i+1
            endloop
            // colorize the bar
            if l>0 then
                call .Bar.SetForegroundString(.GradientColor[j])
            else
                call .Bar.SetForegroundString(.fg_color)
            endif
            set .Bar.Value=newval
        endmethod
        
        method SetForeground takes ARGB color returns nothing
            set .fg_color=SubString(color.str(""), 0, 10)
            set .Value=.Value
        endmethod
        
        method SetForegroundString takes string color returns nothing
            set .fg_color=color
            set .Value=.Value
        endmethod
        
        method onDestroy takes nothing returns nothing
            call .Bar.destroy()
        endmethod
    endstruct
    
endlibrary

I added a simple map that demonstrates basic use of this system.

Type in "-test" to start testing.

Have fun with it.

Deaod

Keywords:
Custom, Bar, Texttag
Contents

TTBARS TestMap (Map)

Reviews
19:20, 11th Oct 2009 The_Reborn_Devil: The coding looks good and I couldn't find any leaks. There were some very minor things that could be better, but that's not necessary. Approved. I also give this system the rating Useful. If you feel...

Moderator

M

Moderator

19:20, 11th Oct 2009
The_Reborn_Devil:

The coding looks good and I couldn't find any leaks.
There were some very minor things that could be better, but that's not necessary.
Approved.
I also give this system the rating Useful.

If you feel that the rating I gave this system is wrong or if there's something you want to ask just PM me.
 
Level 14
Joined
Nov 18, 2007
Messages
816
You cant do gradients (easily).
Your code is badly encapsulated.
Your library is a behemoth that noone will understand without spending much time trying.
Your library is less efficient than mine (O(n) for bar composition + unneeded junk for coloring the individual primitive strings).

I wouldnt use your library over this one.
I wouldnt want to use your library at all, since i think its coded badly.
 
Top