// *************************************************************// * 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()// *// *************************************************************libraryImageUtilsrequiresARGBglobalsprivateconstantintegerMAX_IMAGES = 8190// Doesnt get rendered// using this type in CreateImage returns an invalid image (id of -1)constantintegerIMAGE_TYPE_SHADOW = 0// Gets drawn above fog of warconstantintegerIMAGE_TYPE_SELECTION = 1// Gets drawn above fog of warconstantintegerIMAGE_TYPE_INDICATOR = 2// Gets drawn above fog of warconstantintegerIMAGE_TYPE_OCCLUSION_MASK = 3// Gets tinted based on time of day ingame.// Gets drawn below fog of warconstantintegerIMAGE_TYPE_UBERSPLAT = 4// Doesnt get renderedconstantintegerIMAGE_TYPE_TOPMOST = 5privateconstantintegerDEFAULT_IMAGE_TYPE = IMAGE_TYPE_INDICATORprivateARGBDEFAULT_COLOR = 0xFFFFFFFFprivateconstantintegerINVALID_IMAGE_ID = -1// go complain about that at Blizzard,// i have nothing to do with that endglobalsglobalsprivatebooleanarrayImageValid[MAX_IMAGES]
endglobalsfunctionNewImagetakesstringpath, realsizex, realsizey, realsizez, realposx, realposy, realposz, realoffx, realoffy, realoffz, integerimagetypereturnsimagelocalimagei=CreateImage(path, sizex, sizey, sizez, posx, posy, posz, offx, offy, offz, imagetype)
localintegerid=GetHandleId(i)
ifid<0thendebugcallBJDebugMsg("NewImage: Invalid imagepath!")
returnnullelseifid>=MAX_IMAGESthendebugcallBJDebugMsg("NewImage: Exceeded Maximum Images!")
returniendifsetImageValid[id]=truereturniendfunctionfunctionCreateImageExtakesstringpath, realsizex, realsizey, realsizez, realposx, realposy, realposz, realoffx, realoffy, realoffz, integerimagetypereturnsimagedebugcallBJDebugMsg("CreateImageEx: Use NewImage instead, CreateImageEx is deprecated!")
returnNewImage(path, sizex, sizey, sizez, posx, posy, posz, offx, offy, offz, imagetype)
endfunctionfunctionReleaseImagetakesimageireturnsnothinglocalintegerid=GetHandleId(i)
ifid>=MAX_IMAGESthencallDestroyImage(i)
elseifid>0andImageValid[id] thencallDestroyImage(i)
setImageValid[id]=falsedebugelseifid>0thendebugcallBJDebugMsg("ReleaseImage: Double free of image "+I2S(id)+".")
debugelsedebugcallBJDebugMsg("ReleaseImage: Trying to free invalid image.")
endifendfunctionstructimagex[MAX_IMAGES]
privateimageimgprivatestringPathprivaterealSizeXprivaterealSizeYprivaterealXprivaterealYprivaterealZprivateARGBColorprivatebooleanShowprivatebooleanWrapprivateintegerType// Get Methodsmethodoperatorpathtakesnothingreturnsstringreturn.PathendmethodmethodoperatorsizeXtakesnothingreturnsrealreturn.SizeXendmethodmethodoperatorsizeYtakesnothingreturnsrealreturn.SizeYendmethodmethodoperatorxtakesnothingreturnsrealreturn.Xendmethodmethodoperatorytakesnothingreturnsrealreturn.Yendmethodmethodoperatorztakesnothingreturnsrealreturn.Zendmethodmethodoperatorredtakesnothingreturnsintegerreturn.Color.redendmethodmethodoperatorgreentakesnothingreturnsintegerreturn.Color.greenendmethodmethodoperatorbluetakesnothingreturnsintegerreturn.Color.blueendmethodmethodoperatoralphatakesnothingreturnsintegerreturn.Color.alphaendmethodmethodoperatorcolortakesnothingreturnsARGBreturn.Colorendmethodmethodoperatorshowtakesnothingreturnsbooleanreturn.Showendmethodmethodoperatorwraptakesnothingreturnsbooleanreturnnot.Wrapendmethodmethodoperatortypetakesnothingreturnsintegerreturn.Typeendmethod// Private ProxiesprivatemethodNewPositiontakesnothingreturnsnothingcallSetImagePosition(.img, .x, .y, 0)
endmethodprivatemethodNewZPostakesrealzreturnsnothingcallSetImageConstantHeight(.img, .wrap, z)
endmethodprivatemethodRecolortakesnothingreturnsnothingcallSetImageColor(.img, .red, .green, .blue, .alpha)
endmethodprivatemethodRecreatetakesnothingreturnsnothingif.img!=nullthencallReleaseImage(.img) // never destroy null images, if you dont want hell unleashedendifset.img=NewImage(.path, .sizeX, .sizeY, 0, .x, .y, 0, 0, 0, 0, .type)
call.NewZPos(.z)
call.Recolor()
callSetImageRenderAlways(.img, .show)
endmethod// Set Methods// Set the image's filepathmethodoperatorpath= takesstringpathreturnsnothingset.Path=pathcall.Recreate()
endmethod// Set the size of the imagemethodoperatorsizeX= takesrealsizexreturnsnothingset.SizeX=sizexcall.Recreate()
endmethodmethodoperatorsizeY= takesrealsizeyreturnsnothingset.SizeY=sizeycall.Recreate()
endmethodmethodsetSizetakesrealsizex, realsizeyreturnsnothingset.SizeX=sizexset.SizeY=sizeycall.Recreate()
endmethod// Set the position of the imagemethodoperatorx= takesrealxreturnsnothingset.X=xcall.NewPosition()
endmethodmethodoperatory= takesrealyreturnsnothingset.Y=ycall.NewPosition()
endmethodmethodoperatorz= takesrealzreturnsnothingset.Z=zcall.NewZPos(z)
endmethodmethodsetPositiontakesrealx, realy, realzreturnsnothingset.X=xset.Y=yset.Z=zcall.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*/methodoperatorcolor= takesARGBnewreturnsnothingset.Color=newcall.Recolor()
endmethod// Do you want to display the image?methodoperatorshow= takesbooleanshowreturnsnothingset.Show=showcallSetImageRenderAlways(.img, .show)
endmethodmethodoperatorwrap= takesbooleanwrapreturnsnothingset.Wrap=notwrapcall.NewZPos(.z)
endmethod// On which layer should the image be rendered?methodoperatortype= takesintegerimageTypereturnsnothingset.Type=imageTypecallSetImageType(.img, imageType)
endmethod// constructor and destructorstaticmethodcreatetakesstringpath, realsizeX, realsizeY, realposX, realposY, realposZ, booleanshowreturnsthistypelocalthistypes=.allocate()
sets.Path=pathsets.SizeX=sizeXsets.SizeY=sizeYsets.X=posXsets.Y=posYsets.Z=posZsets.Show=showsets.Wrap=falsesets.Type=DEFAULT_IMAGE_TYPEsets.Color=DEFAULT_COLORcalls.Recreate()
returnsendmethodmethodonDestroytakesnothingreturnsnothingif.img!=nullthencallReleaseImage(.img)
endifset.img=nullendmethodprivatestaticmethodonInittakesnothingreturnsnothingifGetHandleId(CreateImage("ReplaceableTextures\\CommandButtons\\BTNSlowOn.blp", 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)) != nullthendebugcallBJDebugMsg("ImageUtils: image(null) already allocated, there might be errors")
endifendmethodendstructendlibrary

EDIT 1: Updated ImageUtils to incorporate the result of my research. Attached a map demonstrating use of ImageUtils in the context of a TextSplat library.
EDIT 2: Added a documentation. If you still need something explained, feel free to ask.
EDIT 3: Made the link to my research more visible.
EDIT 4: Fixed two bugs.
EDIT 5: Now supports wrapping to the ground. Fixed documentation errors.
EDIT 6: Updated with workarounds to the newfound bug. As a result, CreateImageEx was added. Refer to the documentation for more information.
EDIT 7: Deprecated CreateImageEx in favour of NewImage/ReleaseImage. Now also tries to work around the most common errors with images (and reports those to the user).
EDIT 8: Fixed imagex instances causing errors.

Man, fix the bloody spacing... Also, did you verify that this is actually the order (from bottommost to topmost) that Blizzard uses in actual WC3 or are these the (obviously incorrect) names used in GUI?

JASS:

callBJDebugMsg("ImageUtils: Invalid imagepath!")

Use SCOPE_PREFIX.

Oh, and put the "ImageUtils" library on top of the example, and have both of them use [hiddenjass][/hiddenjass] tags around them.

You will also need better documentation. By a lot.

Also, I am calling forth the necessity of a demo map for this library. I refuse to let it get approved without one that shows all of the working image types, how they stack on each other, and gives some examples of how they work when you change their values and such.

This does not constitute proper script documentation. Parts of your image test experiment thing will basically need to be copied and pasted into the library to explain why the library does what it does and how it does it.