• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

CustomWindow v1.1.1.2

JASS:
/*************************************************
 *  CustomWindow v1.1.1.2 by Maker
 * 
 *  Allows the creation of custom windows.
 *
 *  Requires Table by Bribe and TimerUtils by Vexorian
 *
 * Importing instructions:
 * 1.   Import all images with the name beginning with Border.
 *      There are 8 of them. Also copy background.TGA.
 * 2.   Make sure the image paths are correct in the globals block in this library.
 * 3.   Copy CustomTextWindow, Table and TimerUtilsEx into your map.
 *
 *
 * API
 *
 * struct CustowWindow
 *
 * o method destroy takes nothing returns nothing
 *      Destroys a custom window
 * o method setHeight takes real height returns nothing
 *      Sets the height of a custom window
 * o method setTransparency takes integer alpha returns nothing
 *      Sets the transparency of a window
 * o method show takes boolean show returns nothing
 *      Shows/hides a custom window
 * o static method create takes real scale, real sizeX, real sizeY, real posX, real posY, integer imageType returns thistype
 *      Creates a custom window
 *
 * struct CustomTextWindow
 *
 * o method destroy takes nothing returns nothing
 *      Destroys a custom text window
 * o method show takes boolean show returns nothing
 *      Shows/hides a custom text window
 * o method setTransparency takes integer alpha returns nothing
 *      Sets the transparency of a custom text window
 * o method fadeOut real time, real delay, boolean destroy returns nothing
 *      Fades out a custom text window. Time is the fade time, delay the time before fading.
 *      If destroy is true, the window will be destroyed when it has faded out.
 * o method setHeight real height returns nothing
 *      Sets the height of a custom window
 * o static method create takes string title, string text, real posX, real posY, real textSize, real borderScale, integer maxWidth, integer imageType returns thistype
 *      Creates a custom text window
 *
 *
 *  Try to avoid large text sizes, over about 28, since
 *  the game engine will add a line break if text tag width
 *  would become too large.
 *
 ************************************************/

library CustomWindow requires Table, TimerUtils

    globals
        private constant string     BACKGROUND  = "war3mapImported\\background.TGA"
        private constant string     BOTTOM_L    = "war3mapImported\\BorderDownLeftNE.TGA"
        private constant string     TOP_L       = "war3mapImported\\BorderUpLeftNE.TGA"
        private constant string     BOTTOM_R    = "war3mapImported\\BorderDownRightNE.TGA"
        private constant string     TOP_R       = "war3mapImported\\BorderUpRightNE.TGA"
        private constant string     LEFT        = "war3mapImported\\BorderLeftNE.TGA"
        private constant string     TOP         = "war3mapImported\\BorderUpNE.TGA"
        private constant string     RIGHT       = "war3mapImported\\BorderRightNE.TGA"
        private constant string     BOTTOM      = "war3mapImported\\BorderDownNE.TGA"
        
        private constant integer    TRANS       = 200       // Transparency of the background, 0 = fully transparent, 255 = not transparent
        private constant integer    MAXCHARS    = 38        // Maximum number of characters in a row
        private constant real       CHARHEIGHT  = 4         // Height of a letter in pixels
        private constant real       CHARWIDTH   = 1.5       // Width of a letter in pixels
        private constant real       BORDERWIDTH = 28        // Width of borders, visible portion of default size
        private constant real       LOOPTIME    = 0.03125
        
        /* Use CHARHEIGHT and CHARWIDTH to adjust the window's wrapping around the text */
    endglobals
    
    // Not to be changed
    globals
        private             real        X
        private             real        Y
        private constant    real        DEFSIZE     = 64    // Size of visible portion of an image
        private constant    real        RATIO       = (DEFSIZE+2)/DEFSIZE
        private             location    LOC         = Location(0,0)
    endglobals

    struct CustomWindow extends array
        private integer images
        private static Table array imgs
        private static integer ic = 0
        private static integer ir = 0
        private thistype rn
        
        method destroy takes nothing returns nothing
            local integer i = this.images
            loop
                exitwhen i == 0
                call DestroyImage(imgs[this].image[i])
                set i = i - 1
            endloop
            call imgs[this].destroy()
            set .rn = ir
            set ir = this
        endmethod
        
        method setHeight takes real height returns nothing
            local integer i = .images
            loop
                exitwhen i == 0
                call SetImageConstantHeight(imgs[this].image[i], true, height)
                set i = i - 1
            endloop
        endmethod
        
        method show takes boolean show returns nothing
            local integer i = .images
            loop
                exitwhen i == 0
                call SetImageRenderAlways(imgs[this].image[i], show)
                call ShowImage(imgs[this].image[i], show)
                set i = i - 1
            endloop
        endmethod
        
        method setTransparency takes integer alpha returns nothing
            local integer i = .images
            loop
                exitwhen i == 0
                if i != 1 then
                    call SetImageColor(imgs[this].image[i], 255, 255, 255, alpha)
                elseif alpha < TRANS then
                    call SetImageColor(imgs[this].image[i], 255, 255, 255, alpha)
                else
                    call SetImageColor(imgs[this].image[i], 255, 255, 255, TRANS)
                endif
                set i = i - 1
            endloop
        endmethod
    
        private static method addRecycle takes nothing returns thistype
            local thistype this
            if ir == 0 then
                set ic = ic + 1
                set this = ic
            else
                set this = ir
                set ir = .rn
            endif
            return this
        endmethod
        
        // posX and posY are the coordinates of the center of the image
        static method create takes real borderScale, real sizeX, real sizeY, real posX, real posY, integer imageType returns thistype
            local thistype this     = thistype.addRecycle()
            local integer   i       = 0             // Image counter
            local integer   j                       // For loops
            local integer   nx      = 0             // How many x pieces
            local integer   ny      = 0             // How many y pieces
            local real      sx      = 0             // X size
            local real      sy      = 0             // Y size
            local real      cx      = 0             // X coordinate of lower left corner
            local real      cy      = 0             // Y coordinate of lower left corner
            local real      bwidth                  // Border width
            local real      sxa
            local real      sya
                   
            set X = DEFSIZE*borderScale                               // Visible image size of one image
            set Y = DEFSIZE*borderScale
            set bwidth = BORDERWIDTH * borderScale                    // Visible border width
            set imgs[this] = Table.create()
            
            if sizeX < 2*X then
                set sizeX = 2*X
            endif
            set sx = X * RATIO                                  // X size of one block, corners
            set nx = R2I((sizeX-2*X) / X)                       // How many top/bottom blocks, excluding corner blocks          
            set sxa = (sizeX-2*X) / (nx * X) * sx               // X size of one block, top and bottom
            set cx = posX - sizeX/2 + X - borderScale                 

            if sizeY < 2*Y then
                set sizeY = 2*Y
            endif
            set sy = Y * RATIO
            set ny = R2I((sizeY-2*Y) / Y)
            set sya = (sizeY-2*X) / (ny * X) * sy
            set cy = posY - sizeY/2 + Y - borderScale
            
            set i = i + 1   // Background
            set imgs[this].image[i] = CreateImage(BACKGROUND, sizeX-bwidth, sizeY-bwidth, 0, posX - (sizeX-bwidth)/2, posY - (sizeY-bwidth)/2, 0, 0, 0, 0, imageType)
            call SetImageColor(imgs[this].image[i], 255, 255, 255, TRANS)
            
            set posX = posX - borderScale
            set posY = posY - borderScale

            set i = i + 1   // Down left corner
            set imgs[this].image[i] = CreateImage(BOTTOM_L, sx, sy, 0, posX - sizeX/2, posY - sizeY/2, 0, 0, 0, 0, imageType)
            
            set i = i + 1   // Up left corner
            set imgs[this].image[i] = CreateImage(TOP_L,    sx, sy, 0, posX - sizeX/2, posY + sizeY/2 - sy/RATIO, 0, 0, 0, 0, imageType)
            
            set i = i + 1   // Up right corner
            set imgs[this].image[i] = CreateImage(TOP_R,    sx, sy, 0, posX + sizeX/2 - X, posY + sizeY/2 - sy/RATIO, 0, 0, 0, 0, imageType)
            
            set i = i + 1   // Down right corner
            set imgs[this].image[i] = CreateImage(BOTTOM_R, sx, sy, 0, posX + sizeX/2 - X, posY - sizeY/2, 0, 0, 0, 0, imageType)

            set j = 0
            loop            // Up and down blocks
                set i = i + 1
                set imgs[this].image[i] = CreateImage(TOP, sxa, sy, 0, cx, posY + sizeY/2 - Y, 0, 0, 0, 0, imageType)
                set i = i + 1
                set imgs[this].image[i] = CreateImage(BOTTOM, sxa, sy, 0, cx, posY - sizeY/2, 0, 0, 0, 0, imageType)
                set j = j + 1
                exitwhen j == nx
                set cx = cx + sxa/RATIO
            endloop
            
            set j = 0
            loop            // Left and right blocks
                set i = i + 1
                set imgs[this].image[i] = CreateImage(LEFT, sx, sya, 0, posX - sizeX/2, cy, 0, 0, 0, 0, imageType)
                set i = i + 1
                set imgs[this].image[i] = CreateImage(RIGHT, sx, sya, 0, posX + sizeX/2 - X, cy, 0, 0, 0, 0, imageType)
                set j = j + 1
                exitwhen j == ny
                set cy = cy + sya/RATIO
            endloop
            
            set this.images = i
            
            return this
        endmethod
        
    endstruct
    
    struct CustomTextWindow extends array
        private real ttPosX
        private real ttPosY
        private real height
        private real ttSize
        private integer visibility
        private integer fadeRate
        private integer fadeOutRate
        private timer t
        private timer tOut
        private string title
        private string text
        texttag tt
        private boolean destroys
        private boolean destroysOut
        CustomWindow cw
        private thistype rn
        private static integer ic = 0
        private static integer ir = 0
        
        method destroy takes nothing returns nothing
            if this.tt != null then
                call DestroyTextTag(this.tt)
                set this.tt = null
            endif
            set this.title = null
            set this.text = null
            set this.destroys = false
            if this.t != null then
                call ReleaseTimer(this.t)
                set this.t = null
            endif
            if this.tOut != null then
                call ReleaseTimer(this.tOut)
                set this.tOut = null
            endif
            call this.cw.destroy()
            set this.rn = ir
            set ir = this
        endmethod
        
        method setTransparency takes integer alpha returns nothing
            set this.visibility = alpha
            if this.tt == null and alpha > 0 and alpha < 255 then
                call this.show(true)
                call SetTextTagPermanent(this.tt, false)
                call SetTextTagColor(this.tt, 255, 255, 255, alpha)
            elseif alpha > 0 then
                call SetTextTagColor(this.tt, 255, 255, 255, alpha)
            elseif this.tt != null and alpha <= 0 then
                call DestroyTextTag(this.tt)
                set this.tt = null
            endif
            call this.cw.setTransparency(alpha)
        endmethod
        
        method show takes boolean show returns nothing
            if show then
                if this.tt == null then
                    call MoveLocation(LOC, .ttPosX, .ttPosY)
                    set this.tt = CreateTextTag()
                    call SetTextTagText(this.tt, this.text, this.ttSize/1000)
                    call SetTextTagPos(this.tt, this.ttPosX, this.ttPosY, .height - GetLocationZ(LOC))
                    call SetTextTagColor(this.tt, 255, 255, 255, 255)
                    call SetTextTagVisibility(this.tt, true)
                endif
            else
                if this.t != null then
                    call PauseTimer(this.t)
                endif
                call DestroyTextTag(this.tt)
                set this.tt = null
            endif
            call this.cw.show(show)
        endmethod
        
        private static method fade takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            set this.visibility = this.visibility - this.fadeRate
            if this.visibility > 0 and this.visibility < 255 then
                call this.setTransparency(this.visibility)
            else
                call PauseTimer(this.t)
                if this.destroys then
                    call this.destroy()
                else
                    if this.fadeRate < 0 then
                        call this.setTransparency(255)
                    elseif this.fadeRate > 0 then
                        call this.setTransparency(0)
                    endif
                    if this.t != null then
                        call ReleaseTimer(this.t)
                        set this.t = null
                    endif
                endif
            endif
        endmethod
        
        private static method fadeDelay takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            set this.fadeRate = this.fadeOutRate
            set this.destroys = this.destroysOut
            call SetTextTagPermanent(this.tt, false)
            if this.tOut != null then
                call ReleaseTimer(this.tOut)
                set this.tOut = null
            endif
            if this.t == null then
                set this.t = NewTimerEx(this)
            endif
            call TimerStart(this.t, LOOPTIME, true, function thistype.fade)
        endmethod
        
        method fadeIn takes real time returns nothing
            if .t == null then
                set .t = NewTimerEx(this)
            endif
            if time == 0 then
                set time = 0.01
            endif
            set .destroys = false
            set .fadeRate = -(R2I(255*LOOPTIME/time) + 1)
            call SetTextTagPermanent(.tt, false)
            call TimerStart(.t, LOOPTIME, true, function thistype.fade)
        endmethod
        
        method fadeOut takes real time, real delay, boolean destroys returns nothing
            if time == 0 then
                set time = 0.01
            endif
            set .fadeOutRate = R2I(255*LOOPTIME/time) + 1
            set .destroysOut = destroys
            call SetTextTagPermanent(.tt, false)
            if delay != 0 then
                if .tOut == null then
                    set .tOut = NewTimerEx(this)
                endif
                call TimerStart(.tOut, delay, false, function thistype.fadeDelay)
            else
                if .tOut != null then
                    call PauseTimer(.tOut)
                endif
                if .t == null then
                    set .t = NewTimerEx(this)
                endif
                set this.fadeRate = this.fadeOutRate
                set this.destroys = this.destroysOut
                call TimerStart(.t, LOOPTIME, true, function thistype.fade)
            endif
        endmethod
        
        method setHeight takes real height returns nothing
            call MoveLocation(LOC, .ttPosX, .ttPosY)
            call SetTextTagPos(.tt, .ttPosX, .ttPosY, height - GetLocationZ(LOC))
            call this.cw.setHeight(height)
            set .height = height
        endmethod
    
        private static method addRecycle takes nothing returns thistype
            local thistype this
            if 0==ir then
                set ic=ic+1
                set this=ic
            else
                set this=ir
                set ir=.rn
            endif
            return this
        endmethod
    
        // posX and pos Y are the coordinates of bottom left corner
        static method create takes string title, string text, real posX, real posY, real textSize, real borderScale, integer maxWidth, integer imageType returns thistype
            local thistype this = thistype.addRecycle()
            local integer i
            local integer rows = 1
            local integer wordlength = 0
            local string word = null
            local string newStr = null
            local string char
            local integer chars = 0
            local integer charsMax = 0
            local real width
            local real sizeX
            local real sizeY
            
            if maxWidth > MAXCHARS or maxWidth == 0 then
                set maxWidth = MAXCHARS
            endif
            
            if text != null then
                set rows = rows + 1
                set width = 0
                set i = 0
                loop
                    set char = SubString(text, i, i+1)
                    if char == " " or char == "" then
                        if chars < maxWidth then
                            set newStr = newStr + " " + word
                            if char == " " then
                                set chars = chars + 1
                            endif
                            if chars > charsMax then
                                set charsMax = chars
                            endif
                        else
                            if chars - wordlength > charsMax then
                                set charsMax = chars - wordlength
                            endif
                            set newStr = newStr + "\n" + " " + word
                            set chars = 1 + wordlength
                            set rows = rows + 1
                        endif
                        set word = null
                        set wordlength = 0
                    else
                        set chars = chars + 1
                        set wordlength = wordlength + 1
                        set word = word + char
                    endif
                    exitwhen char == ""
                    set i = i + 1
                endloop
            else
                set charsMax = StringLength(title) + 2
            endif
            
            call MoveLocation(LOC, posX, posY)
            set this.height = GetLocationZ(LOC)
            
            set sizeX = charsMax * CHARWIDTH * textSize/5 + 2*DEFSIZE*borderScale
            set sizeY = rows * CHARHEIGHT * textSize/5 + 2*DEFSIZE*borderScale
            
            set this.ttSize = textSize
            set this.ttPosX = posX
            set this.ttPosY = posY
            set this.title = title
            set this.text = "|cffffcc00" + this.title + "|r\n" + newStr
            set this.cw = CustomWindow.create(borderScale, sizeX, sizeY, posX+sizeX/2-DEFSIZE*borderScale, posY+sizeY/2-DEFSIZE*borderScale, imageType)
            
            set char = null
            set newStr = null
            
            return this
        endmethod
    endstruct
        
endlibrary



The system is useful in creating tooltips for buttons in inventory systems, creating windows for full screen invetories and hero pic systems.

You could create all windows with this and hide the images easily so the system doesn't take map space.

The system creates the border from blocks, avoiding overly stretched images. For example with image size 1, a window 320 pixels wide would horizontally consist of two corner pieces and 3 top border pieces.

The default size of a block is 64. You can use scale parameter in create method to change the value.

CustomWindow creates a window without text, CustomTextWindow adds text.

The system goes through the given text and breaks it down to words. It keeps track of the character count per line, and adds line breaks when needed. It then calculates the amount of blocks in width and height needed to wrap the text.

Floating texts suffer from automated line breaks if they become too wide, so avoid large text sizes.



v0.9.0.0 Uploaded 22.11.2011
v0.9.0.1 Uploaded 23.11.2011
-Changed text casing
-Changed image path variable names
-Replaced TimerUtilsEx library with TimerUtils
-Changed static method destroyCW/destroyCT to method destroy
-Changed add method to create
-CustomTextWindow struct extends array now
v0.9.0.2 Uploaded 29.11.2011
-Reduced the imported image size from 96x96 to 66x66. File size from 36 kb to 17 kb.
-set nx = R2I((sizeX-2*X) / X) + 1 -> set nx = R2I(0.5 + (sizeX-2*X) / X). Results in tighter wraps in some cases.
v0.9.0.3 Uploaded 13.12.2011
-Changed static methods that manipulate spesific windows to non static methods
v0.9.1.0 Uploaded 19.01.2012
-Prevented floating texts from being faded out by the game engine
-If a custom text window is not destroyed after fading out, it doesn't release and null the timer of the struct. Pauses it instead
v1.0.0.0
-Floating text now fades instead of disappering immediately, just like the borders
-Rather than storing the floating text, the system stores the text as a string when the text is not visible
v1.0.1.0 Uploaded 08.01.2013
-Now the windows can fade in
-Renamed CTW.fade to CTW.setTransparency
v1.0.1.1 Uploaded 09.01.2013
-Optimized code
-Removed a bug which caused the text to appear and disappear after the default
floating text removal time. Text tag are set to destroy when set to invisible now
v1.1.1.1 Uploaded 10.01.2013
-Now supports exact window sizes instead of rounding. This means you can align windows next to
each other more easily and the texts are wrapped more aesthetically and consistently
-v1.1.1.2 Uploaded 18.01.2013
-Added GetLocationZ when creating floating texts. Images and texts are now at the same height regardless of terrain height


Keywords:
custom, window, image, maker, tooltip, text
Contents

CustomWindow (Map)

Reviews
24th Nov 2011 Bribe: Approved. Highly recommended with potential for Director's Cut as it gets more refined.

Moderator

M

Moderator

24th Nov 2011
Bribe: Approved.

Highly recommended with potential for Director's Cut as it gets more refined.
 
The word Custom is an ugly one ;o
Can you make it "Window"? (You are Maker after all ;p)

static method destroyCTW takes CustomTextWindow CTW returns nothing
->
method destroy takes nothing returns nothing

By the way, I like how your algorithm is O(n) for the text wrapping :)

edit

By the way, TimerUtilsEx was graveyarded ages ago ;o
Vexorian finally decided to update TU.
Too bad it still doesn't support the "ReleaseTimer -> integer data" thing :/
 
Level 7
Joined
Dec 3, 2006
Messages
339
By the way, TimerUtilsEx was graveyarded ages ago ;o
Vexorian finally decided to update TU.
Too bad it still doesn't support the "ReleaseTimer -> integer data" thing :/

I think it's ok to use either TimerUtils or TimerUtilsEx since it's compatible. I'm still using the graveyarded one actually too :D.

This doesn't seem to work very well for wrapping the text for me. Maybe it's to do with my resolution? 1280 by 800 is rather a strange resolution. I actually prefer WindowInterface's way of doing these tooltips: http://www.wc3c.net/showthread.php?p=1129410 .

I just spent some time today re-working the WindowInterface and Math/Camera libraries to make em more readable and I might use them for something in my map. I'm thinking of having just the DM player have a fullscreen type UI with it.
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
v0.9.0.1 Uploaded 23.11.2011
-Changed text casing
-Changed image path variable names
-Replaced TimerUtilsEx library with TimerUtils
-Changed static method destroyCW/destroyCT to method destroy
-Changed add method to create

The word Custom is an ugly one ;o
Can you make it "Window"? (You are Maker after all ;p)

Wouldn't Window be too generic? I'll think of some good name.

This doesn't seem to work very well for wrapping the text for me. Maybe it's to do with my resolution? 1280 by 800 is rather a strange resolution. I actually prefer WindowInterface's way of doing these tooltips: http://www.wc3c.net/showthread.php?p=1129410.

The system was created with 1920x1080 resolution. I did try 1280x800, 1366x768 and 1600x900. They seemed to work correctly. However the native resolution for my monitor is 1920x1080, and it isn't well suited for any other resolution. Could you post a screenshot?

Camera height and floating text size may cause it to malfunction, you have to adjust the parameters you give to the create method to adjust the text.

The WindowInterface you linked looks nice. But it lacks the fade feature. It's amusing to me that the test is done with units, since I spesifically wanted to avoid using units, that's why I created this system.
 
Nice job. I was making something similar to this as well. (but a little different)

This doesn't seem to work very well for wrapping the text for me. Maybe it's to do with my resolution? 1280 by 800 is rather a strange resolution. I actually prefer WindowInterface's way of doing these tooltips:

Yes, it has to do with resolution. Wc3 text-tags and multiboards do not share letter sizes. For example, an l would be much shorter in length compared to W. With resolution, those sizes change. (which makes life just much more annoying) There are ways to work-around this, however. The easiest way is to allow the user to input their resolution and then adjust the maximum size in accordance to it. (this allows for the most accurate precision) However, I don't think that has to be included in the system, it is something more suited as an extension.

In terms of line breaking and whatnot, you can always use my snippets for it: http://www.hiveworkshop.com/forums/triggers-scripts-269/small-code-snippets-40758/index26.html

However, it isn't necessary. After all, it is unlikely that anyone will care that much about proper line breaking. xP

Does this support color codes? ex: |cffffcc00This is a text|r with some white text.

I'll run some tests later. Good job overall though.
 
For each icon you must create a 64x64 image with a 1 pixel transparent border. For more information, see this tutorial:
http://world-editor-tutorials.thehelper.net/cat_usersubmit.php?view=66955

You can also use a destructable instead. The method I am describing is used in Anachron's Custom Inventory system. You can just export the model (in his map, called base icon or something) and import it into your map. Then, in the object editor, just change the replaceable texture to that of your icon's, and you are good to go. (no extra work needed) You can take a look at the object editor in his map for more information.

@Maker: Generally, images are a bit more manageable in terms of being able to be moved easily and whatnot, but I think you should look into using destructables. They are much better. =) The only annoying part is making them seamless but I got them close enough to being seamless and they work just fine.

orrr.... you can just use a mixture. Use images for borders and destructables for icons, although that may make it a bit more complex, huh?
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
Add something like setText( aText ) please...

Yeah, I'm planning that, but I might not add it afterall. I'll have to see. Doing that would make the system create/destroy border blocks, and reapply the text parsing function. I think it's quite easy to just destroy the old and create new window instead of setting text.

may be you can adjust the floating text size by calculating a factor based on the camera distance... thats what i did when i created custom windows with texts :D

Actually I had that but removed it. Since I leave it to the user to set the text size correctly. I don't expect a window to be viewed from different distances. Cameras viewing stuff like this are static almost with no exception.

Thanks for the comments, I'll take them into consideration!
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
v0.9.1.0 Uploaded 19.01.2012
-Prevented floating texts from being faded out by the game engine
-If a custom text window is not destroyed after fading out, it doesn't release and null the timer of the struct. Pauses it instead

Apparently if one does
JASS:
set tt = CreateTextTag()
call SetTextTagPermanent(tt, false)
then the engine applies an expiration timer of about 90 seconds to the tt, after which the tt fades out and is destroyed. Setting the boolean to true afterwards does not seem to pause that timer. Good job Blizzard. Good job.
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
v1.0.0.0
-Floating text now fades instead of disappering immediately, just like the borders
-Rather than storing the floating text, the system stores the text as a string when the text is not visible

The second change is very useful to avoid hitting the 100 limit of floating texts.

When a window is not visible, the text tag is destroyed and the text is stored as a string. The text tag is re-created when the window is displayed the next time.
 
You know, I've been facing crashes with this in the past.
Images are known to cause crashes often. (If you destroy a null image, the game crashes.)

I can't identify the problem though.
The code seems fine.

edit
By the way, I really think you should prevent users from passing in an imageType value, as some of the image types don't actually work, and I think one of them causes a crash.
 
Use destructables instead of images.
Problems solved.

The end.

Destrcutibles have set coordinates, you can't place them exactly the way you want. This is huge problem sometimes.

Also 1 image or few are less work that 50 destructibles of many types that still need to be created.
 
Level 25
Joined
Jun 5, 2008
Messages
2,573
You can scale up/down and move them on the X/Y/Z axis.
Not to mention you can do precise work with ease, i can move my destructibles from 0.001 X to 0.002 X without problems, any problems you might have is in the object editor area, not the trigger one.

At least i never had the issue of destructibles crashing the game, so i would always go with the safer route.

And you need about 8 destructible types for a full window rendering, 4 if you are smart.
Not to say this is a bad system or anything, i just prefer destructable rendered interface over images.
 
Level 25
Joined
Jun 5, 2008
Messages
2,573
I would rather say this does.
Seeing as this whole thing is only a small part of that system i see not how it alone can be a DC, but then again Director Cut isn't a value of supreme quality, it's a pick of the moderators or so have we been told at least.
And the system i linked also dynamically creates the windows with the exception of text tags i guess so it isn't a brand new idea, only a refined one.

We are not posting fail comments, we are simply saying there are alternatives to images and they are destructibles. For all i am concerned he could make a destructible version also if he wants to.
 
Did you use parts of my CustomWindow posted by CustomInventory?

JASS:
static method create takes real scale, real sizeX, real sizeY, real posX, real posY, integer imageType returns thistype
            local thistype this     = thistype.addRecycle()
            local integer   i       = 0             // Image counter
            local integer   j                       // For loops
            local integer   nx      = 0             // How many x pieces
            local integer   ny      = 0             // How many y pieces
            local real      sx      = 0             // X size
            local real      sy      = 0             // Y size
            local real      cx      = 0             // X coordinate of lower left corner
            local real      cy      = 0             // Y coordinate of lower left corner
            local real      bwidth                  // Border width
            
            set X = DEFSIZE*scale
            set Y = DEFSIZE*scale
            set bwidth = BORDERWIDTH * scale
            set imgs[this] = Table.create()
            
            if sizeX < 2*X then
                set sizeX = 2*X
            endif
            set sx = X * RATIO
            set nx = R2I(0.2 + (sizeX-2*X) / X)
            set sizeX = (2+nx)*X
            set cx = posX - sizeX/2 + X - 1*scale

            if sizeY < 2*Y then
                set sizeY = 2*Y
            endif
            set sy = Y * RATIO
            set ny = R2I(0.2 + (sizeY-2*Y) / Y)
            set sizeY = (2+ny)*Y
            set cy = posY - sizeY/2 + Y - 1*scale

If yes, please at least give me credits.
I have like the same thing in my CWBorder library which is from 2010...
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
Did you use parts of my CustomWindow posted by CustomInventory?
If yes, please at least give me credits.
I have like the same thing in my CWBorder library which is from 2010...

No, I didn't use part of your library. Everything in my system is the result of many hours of coding through trial and error.

Some aspects of the libraries are similar due to the math it is based on. For example set nx = R2I(0.2 + (sizeX-2*X) / X) could not be much different as far as I can tell. I need the number of pieces and that is the simplest way to get it. The 0.2 adds an extra piece in some cases, but that is besides the point.

Sorry for the late reply.
 
Top