• 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.

Images/Desyncs

Status
Not open for further replies.
Level 7
Joined
Dec 3, 2006
Messages
339
I'm using ImageUtils:
JASS:
// *************************************************************
// *                       ImageUtils 
// *                        by Deaod
// *************************************************************
// *
// *    CREDITS:
// *        - Vexorian (JassHelper, ARGB)
// *        - MindWorX and PitzerMike (JassNewGenPack)
// *        - Pipedream (Grimoire)
// *        - SFilip (TESH)
// *
// *    HOW TO IMPORT:
// *        * C'n'P the code into your map
// *        * If you haven't done that already, import ARGB into your map
// *
// *    HOW TO USE:
// *        * this library provides you with wrappers for CreateImage and DestroyImage (NewImage and ReleaseImage respectively).
// *          Those are necessary to work around creating invalid images. They also catch attempts to destroy images created by WC3 itself
// *          (although thats rather conditional, you need to use NewImage and ReleaseImage correctly for it to work).
// *          CreateImageEx also exists (for backwards compatibility), but is deprecated.
// *
// *        This library also comes with an object oriented wrapper for images, heres how to use those:
// *
// *        * declare a variable of type imagex
// *
// *        * use imagex.create(string path, real sizeX, real sizeY, real posX, real posY, real posZ, boolean show) to create a new image
// *            - path is the path to the imagefile that you want to display
// *            - sizeX and sizeY are the dimensions of the image displayed in standard WC3 units of length
// *            - posX, posY and posZ specifiy the position where the image is created.
// *              Note that this point is the lower left corner of the image.
// *
// *        * you can change the path of the image youre displaying by setting the path member of an instance of the imagex struct.
// *          Example: set yourimage.path="Path\\To\\The\\Image.blp"
// *
// *        * you can change the size of the image by setting the sizeX and sizeY member of an instance of the imagex struct.
// *          Example: set yourimage.sizeX=64.
// *                   set yourimage.sizeY=64.
// *          Theres also a method combining those two: yourimage.setSize(real sizex, real sizey)
// *          Example: call yourimage.setSize(64., 64.)
// *          Sizes work like describen in the create method.
// *
// *        * you can change the position of the image by setting the X, Y and Z members of an instance of the imagex struct.
// *          Example: set yourimage.X=128.
// *                   set yourimage.Y=128.
// *                   set yourimage.Z=0.
// *          Theres also a method combining those three: yourimage.setPosition(real x, real y, real z)
// *          Example: call yourimage.setPosition(128.,128.,0.)
// *          The point specified is the lower left corner of the image. 
// *
// *        * you can access the individual values of the red, green, blue and alpha channels of the current color of the image
// *          with the red, green, blue and alpha members of an instance of the imagex struct.
// *          Example: set red = yourimage.red
// *                   set green = yourimage.green
// *                   set blue = yourimage.blue
// *                   set alpha = yourimage.alpha
// *          I planned adding a way to change the value of the individual color channels,
// *          but unfortunately i cant due to a limitation in JassHelper.
// *
// *        * you can change the color of the image by setting the color member of an instance of the imagex struct.
// *          Example: set yourimage.color=ARGB(0xFF808080)
// *          Refer to ARGBs manual for more information on what is a valid ARGB instance.
// *
// *        * you can decide whether to display the image or not by setting the show member of an instance of the imagex struct.
// *          Example: set yourimage.show=true
// *          true displays the image, false hides it.
// *
// *        * you can make the image wrap to the ground by setting the wrap member of an instance of the imagex struct.
// *          Example: set yourimage.wrap=true
// *          true makes the image wrap to the ground, but makes the image ignore its Z position.
// *          false allows you to change the Z position of the image freely.
// *          Defaults to false for new instances.
// *
// *        * you can change the type of an image by setting the type member of an instance of the imagex struct.
// *          Example: set yourimage.type=IMAGE_TYPE_INDICATOR
// *          A list of all known image types can be found below.
// *          Note that not every image type known works, and that image types influence
// *          the order in which images are stacked on top of each other.
// *
// *        NOTE: although i have only shown examples for changing the value of members,
// *        its also possible to read them, unless stated otherwise.
// *
// *        * to destroy an image use yourimage.destroy()
// *
// *************************************************************
library ImageUtils requires ARGB
    
    globals
        private constant    integer                 MAX_IMAGES                      = 8190
        
                // Doesnt get rendered
                // using this type in CreateImage returns an invalid image (id of -1)
                constant    integer                 IMAGE_TYPE_SHADOW               = 0
                // Gets drawn above fog of war
                constant    integer                 IMAGE_TYPE_SELECTION            = 1
                // Gets drawn above fog of war
                constant    integer                 IMAGE_TYPE_INDICATOR            = 2
                // Gets drawn above fog of war
                constant    integer                 IMAGE_TYPE_OCCLUSION_MASK       = 3
                // Gets tinted based on time of day ingame.
                // Gets drawn below fog of war
                constant    integer                 IMAGE_TYPE_UBERSPLAT            = 4
                // Doesnt get rendered
                constant    integer                 IMAGE_TYPE_TOPMOST              = 5
        
        private constant    integer                 DEFAULT_IMAGE_TYPE              = IMAGE_TYPE_INDICATOR
        private             ARGB                    DEFAULT_COLOR                   = 0xFFFFFFFF
        
        private constant    integer                 INVALID_IMAGE_ID                = -1 // go complain about that at Blizzard,
                                                                                         // i have nothing to do with that 
    endglobals
    
    globals
        private boolean array ImageValid[MAX_IMAGES]
    endglobals
    
    function NewImage takes string path, real sizex, real sizey, real sizez, real posx, real posy, real posz, real offx, real offy, real offz, integer imagetype returns image
        local image i=CreateImage(path, sizex, sizey, sizez, posx, posy, posz, offx, offy, offz, imagetype)
        local integer id=GetHandleId(i)
        if id<0 then
            debug call BJDebugMsg("NewImage: Invalid imagepath!")
            return null
        elseif id>=MAX_IMAGES then
            debug call BJDebugMsg("NewImage: Exceeded Maximum Images!")
            return i
        endif
        set ImageValid[id]=true
        return i
    endfunction
    
    function CreateImageEx takes string path, real sizex, real sizey, real sizez, real posx, real posy, real posz, real offx, real offy, real offz, integer imagetype returns image
        debug call BJDebugMsg("CreateImageEx: Use NewImage instead, CreateImageEx is deprecated!")
        return NewImage(path, sizex, sizey, sizez, posx, posy, posz, offx, offy, offz, imagetype)
    endfunction
    
    function ReleaseImage takes image i returns nothing
        local integer id=GetHandleId(i)
        if id>=MAX_IMAGES then
            call DestroyImage(i)
        elseif id>0 and ImageValid[id] then
            call DestroyImage(i)
            set ImageValid[id]=false
        debug elseif id>0 then
            debug call BJDebugMsg("ReleaseImage: Double free of image "+I2S(id)+".")
        debug else
            debug call BJDebugMsg("ReleaseImage: Trying to free invalid image.")
        endif
    endfunction
    
    struct imagex[MAX_IMAGES]
        private image img
        private string Path
        private real SizeX
        private real SizeY
        private real X
        private real Y
        private real Z
        private ARGB Color
        private boolean Show
        private boolean Wrap
        private integer Type
        // Get Methods
   
        
        method operator path takes nothing returns string
            return .Path
        endmethod
        
        method operator sizeX takes nothing returns real
            return .SizeX
        endmethod
        method operator sizeY takes nothing returns real
            return .SizeY
        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 red takes nothing returns integer
            return .Color.red
        endmethod
        method operator green takes nothing returns integer
            return .Color.green
        endmethod
        method operator blue takes nothing returns integer
            return .Color.blue
        endmethod
        method operator alpha takes nothing returns integer
            return .Color.alpha
        endmethod
        method operator color takes nothing returns ARGB
            return .Color
        endmethod
        
        method operator show takes nothing returns boolean
            return .Show
        endmethod
        
        method operator wrap takes nothing returns boolean
            return not .Wrap
        endmethod
        
        method operator type takes nothing returns integer
            return .Type
        endmethod
        
        // Private Proxies
        
        private method NewPosition takes nothing returns nothing
            call SetImagePosition(.img, .x, .y, 0)
        endmethod
        private method NewZPos takes real z returns nothing
            call SetImageConstantHeight(.img, .wrap, z)
        endmethod
        
        private method Recolor takes nothing returns nothing
            call SetImageColor(.img, .red, .green, .blue, .alpha)
        endmethod
        
        private method Recreate takes nothing returns nothing
            if .img!=null then
                call ReleaseImage(.img) // never destroy null images, if you dont want hell unleashed
            endif
            set .img=NewImage(.path, .sizeX, .sizeY, 0, .x, .y, 0, 0, 0, 0, .type)
            call .NewZPos(.z)
            call .Recolor() 
            call SetImageRenderAlways(.img, .show)
        endmethod
        
        // Set Methods
        
        // Set the image's filepath
        method operator path= takes string path returns nothing
            set .Path=path
            call .Recreate()
        endmethod
        
        // Set the size of the image
        method operator sizeX= takes real sizex returns nothing
            set .SizeX=sizex
            call .Recreate()
        endmethod
        method operator sizeY= takes real sizey returns nothing
            set .SizeY=sizey
            call .Recreate()
        endmethod
        method setSize takes real sizex, real sizey returns nothing
            set .SizeX=sizex
            set .SizeY=sizey
            call .Recreate()
        endmethod
        
        // Set the position of the image
        method operator x= takes real x returns nothing
            set .X=x
            call .NewPosition()
        endmethod
        method operator y= takes real y returns nothing
            set .Y=y
            call .NewPosition()
        endmethod
        method operator z= takes real z returns nothing
            set .Z=z
            call .NewZPos(z)
        endmethod
        method setPosition takes real x, real y, real z returns nothing
            set .X=x
            set .Y=y
            set .Z=z
            call .NewPosition()
            call .NewZPos(z)
        endmethod
        
        // Set the color of the image // due to a limtation in JassHelper, only the operator color= works
        /*method operator red= takes integer red returns nothing
            set .Color.red=red
            call .Recolor()
        endmethod
        method operator green= takes integer green returns nothing
            set .Color.green=green
            call .Recolor()
        endmethod
        method operator blue= takes integer blue returns nothing
            set .Color.blue=blue
            call .Recolor()
        endmethod
        method operator alpha= takes integer alpha returns nothing
            set .Color.alpha=alpha
            call .Recolor()
        endmethod*/
        method operator color= takes ARGB new returns nothing
            set .Color=new
            call .Recolor()
        endmethod
        
        // Do you want to display the image?
        method operator show= takes boolean show returns nothing
                set .Show=show
                call SetImageRenderAlways(.img, .show)
        endmethod
        
        method operator wrap= takes boolean wrap returns nothing
            set .Wrap=not wrap
            call .NewZPos(.z)
        endmethod
        
        // On which layer should the image be rendered?
        method operator type= takes integer imageType returns nothing
            set .Type=imageType
            call SetImageType(.img, imageType)
        endmethod
        
        // constructor and destructor
        
        static method create takes string path, real sizeX, real sizeY, real posX, real posY, real posZ, boolean show returns thistype
        local thistype s=.allocate()
            set s.Path=path
            set s.SizeX=sizeX
            set s.SizeY=sizeY
            set s.X=posX
            set s.Y=posY
            set s.Z=posZ
            set s.Show=show
            set s.Wrap=false
            set s.Type=DEFAULT_IMAGE_TYPE
            set s.Color=DEFAULT_COLOR
            call s.Recreate()
            return s
        endmethod
        
        method onDestroy takes nothing returns nothing
            if .img!=null then
                call ReleaseImage(.img)
            endif
            set .img=null
        endmethod
        
        private static method onInit takes nothing returns nothing
            if GetHandleId(CreateImage("ReplaceableTextures\\CommandButtons\\BTNSlowOn.blp", 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)) != null then
                debug call BJDebugMsg("ImageUtils: image(null) already allocated, there might be errors")
            endif
        endmethod
    endstruct
    
endlibrary

Would this desync? Cause i'm thinking of just creating an image for every button of the inventory i'm coding and setting paths/shows locally rather than creating and destroying new ones every time. It would save lots of other function calls and also lots of images if i can set paths and show locally.

JASS:
local player p = Player(0)
local imagex im = imagex.create(path, sizeX, sizeY, posX, posY, posZ, false)
local string s = path
      if GetLocalPlayer() == p then
          set im.path= s
          set im.show=true
      endif
 
Nah it shouldn't desync, as long as you don't do something like:
JASS:
if im.show then
    call CreateUnit(...)
endif

Or something like that. You can do the boolean check, but remember that it will only be locally shown to one player, and therefore the boolean will only be true for one player. Just keep that in mind if you do end up doing that, as the content of the block would need to be locally safe as well.

Otherwise, it should work fine, local images worked fine for me iirc.

edit: Now that I think about it, since images have their own handle stack, they can work asynchronously just fine. (similar to texttags) Meaning, you are probably even be able to create and destroy images locally without any problems.
 
Last edited:
Status
Not open for further replies.
Top