The Red Pill

Welcome Guest ( Log In | Register )

let's see if this old chunk of junk still works

Posted by Bunnywabbit, Oct 10 2017, 08:46 AM in GUI-Modding

*kicks blog window*
ok, that looks like it still actually works. Awesome.

Ok, so we're going to revamp the UI for Allegiance. Lots do do.

good news is; I'm going to solicit help this time.

It's going to be a rather big project. More on this later.

If you have skills in this department, drop me a line. We need mdl codemonkeys, layout designers and graphic artists.



damn, im good.

Posted by Bunnywabbit, Feb 23 2011, 12:19 PM in GUI-Modding

CODE

////////////////////////////////////////////////
//
// Inventorys Pane
//
///////////////////////////////////////////////

InvTopImage =
SwitchImage(
NormalHUDMode,
ImportImageFromFile("mods/CortUI/media/classic/inventorytop.png", false),
[
(1, ImportImageFromFile("mods/CortUI/media/greytones/inventorytop.png", false)),
(2, ImportImageFromFile("mods/CortUI/media/greytones/inventorytop.png", false)),
(3, ImportImageFromFile("mods/CortUI/media/GlassHUD/inventorytop.png", false))
]
);

InvLineImage =
SwitchImage(
NormalHUDMode,
ImportImageFromFile("mods/CortUI/media/classic/inventorylinebkgnd.png", false),
[
(1, ImportImageFromFile("mods/CortUI/media/greytones/inventorylinebkgnd.png", false)),
(2, ImportImageFromFile("mods/CortUI/media/greytones/inventorylinebkgnd.png", false)),
(3, ImportImageFromFile("mods/CortUI/media/GlassHUD/inventorylinebkgnd.png", false))
]
);

InvBottomImage =
SwitchImage(
NormalHUDMode,
ImportImageFromFile("mods/CortUI/media/classic/inventorybottom.png", false),
[
(1, ImportImageFromFile("mods/CortUI/media/greytones/inventorybottom.png", false)),
(2, ImportImageFromFile("mods/CortUI/media/greytones/inventorybottom.png", false)),
(3, ImportImageFromFile("mods/CortUI/media/GlassHUD/inventorybottom.png", false))
]
);

InventoryHeight =
PointY(
ImageSize(
InventoryImage()
)
);

ILH = 18;

IL = Divide(Subtract(InventoryHeight,Multiply(ILH,2)),ILH);

LN1 = SwitchImage(Min(IL,1),emptyImage,[(1, InvLineImage)]);
LN2 = SwitchImage(Min(IL,2),emptyImage,[(2, InvLineImage)]);
LN3 = SwitchImage(Min(IL,3),emptyImage,[(3, InvLineImage)]);
LN4 = SwitchImage(Min(IL,4),emptyImage,[(4, InvLineImage)]);
LN5 = SwitchImage(Min(IL,5),emptyImage,[(5, InvLineImage)]);
LN6 = SwitchImage(Min(IL,6),emptyImage,[(6, InvLineImage)]);
LN7 = SwitchImage(Min(IL,7),emptyImage,[(7, InvLineImage)]);
LN8 = SwitchImage(Min(IL,8),emptyImage,[(8, InvLineImage)]);
LN9 = SwitchImage(Min(IL,9),emptyImage,[(9, InvLineImage)]);
LN10 = SwitchImage(Min(IL,10),emptyImage,[(10, InvLineImage)]);
LN11 = SwitchImage(Min(IL,11),emptyImage,[(11, InvLineImage)]);
LN12 = SwitchImage(Min(IL,12),emptyImage,[(12, InvLineImage)]);
LN13 = SwitchImage(Min(IL,13),emptyImage,[(13, InvLineImage)]);
LN14 = SwitchImage(Min(IL,14),emptyImage,[(14, InvLineImage)]);
LN15 = SwitchImage(Min(IL,15),emptyImage,[(15, InvLineImage)]);
LN16 = SwitchImage(Min(IL,16),emptyImage,[(16, InvLineImage)]);

InvBackgroundLines =
GroupImage([
TranslateImage(InvBottomImage, Point(0,Subtract(ILH,PointY(ImageSize(InvBottomImage))))), //because size may differ.
TranslateImage(LN1, Point(0,ILH)),
TranslateImage(LN2, Point(0,Multiply(2,ILH))),
TranslateImage(LN3, Point(0,Multiply(3,ILH))),
TranslateImage(LN4, Point(0,Multiply(4,ILH))),
TranslateImage(LN5, Point(0,Multiply(5,ILH))),
TranslateImage(LN6, Point(0,Multiply(6,ILH))),
TranslateImage(LN7, Point(0,Multiply(7,ILH))),
TranslateImage(LN8, Point(0,Multiply(8,ILH))),
TranslateImage(LN9, Point(0,Multiply(9,ILH))),
TranslateImage(LN10, Point(0,Multiply(10,ILH))),
TranslateImage(LN11, Point(0,Multiply(11,ILH))),
TranslateImage(LN12, Point(0,Multiply(12,ILH))),
TranslateImage(LN13, Point(0,Multiply(13,ILH))),
TranslateImage(LN14, Point(0,Multiply(14,ILH))),
TranslateImage(LN15, Point(0,Multiply(15,ILH))),
TranslateImage(LN16, Point(0,Multiply(16,ILH))),
TranslateImage(InvTopImage, Point(0,Subtract(InventoryHeight, ILH)))
]);



may have gotten a handle on flexible menu-style switching

Posted by Bunnywabbit, Feb 23 2011, 10:16 AM in GUI-Modding

one of the hard bits is trying to make our inventory and minimap mods in such a way, that users can easily switch between versions.

And by easily, i mean in flight, for preference.

Trouble is that SwitchImage pretty much only works in dialog.mdl

One way to achieve this, would be to place all the artwork in dialog.mdl and give the mdl's that build the inventory and minimap wholly transparent, 0 opacity images. That way, the real inventory would be just the text, digits and smaller icons and completely transparent images that serve only to determine the height and width of each line. Meanwhile, the background artwork would be right behind those transparent pics, and determined in dialog mdl.

Trouble is that both the minimap and the inventory change sizes in game, so you need some way in dialog.mdl to find out whether the minimap is expanded, and how many parts are mounted on the current ship. The first is easy. The second is not. There is no direct way to get the number of mounted parts, and so there is no way to figure out how high the background image should be for the inventory.

So an interesting idea came up.

You can use ImageSize(image) to return a point value, giving the image's top right coordinates as a point value.
There are also the functions PointX(pointvalue) and PointY(pointvalue) which allow you to take a pointvalue apart as numbervalues for the X and Y axis respectively.

the upshot is, that you can do the following:

CODE
InventoryHeight =
PointY(
ImageSize(
InventoryImage()
)
);

which gives you the height of the Inventory Menu dynamically.

Now if we had a working ClipImage() function, all we had to do was make a large background image of a decent enough width, and use clipimage plus our new InventoryHeight value to cut a nice piece out of it that we can use.

Sadly we don't. All we have that can crop a part of an image, is GaugeImage, so i'm either forced to use that, or think of something else.

/me ponders.


GOT IT!

Posted by Bunnywabbit, Apr 11 2010, 11:44 AM in GUI-Modding

Ok, so i got it. And completely by accident too.

Turns out it's as simple as can be, maybe the graphics-updates in the new releases payed off.

Basically, i was experimenting with the UI, and i decided to start from scratch and create a testing image. I saved it in the following path: "Artwork/mods/MyMod/media/".

Note that this is a partly transparent PNG-file. Although you probably can't tell in a browser, it's mostly transparent. The second gradient fades to transparency.

I then edited the dialog.mdl so that it would load that file, thusly:

CODE
MyModTestImage1 =
    JustifyImage( //justifying the image in the center. It will fall off screen otherwise, sse below
        ImportImageFromFile("mods/MyMod/media/TestImage1.png", true),
        JustifyCenter // position the center of the image over the point that we'll specify later on.
    );

MyModCenterHudOn =     
    TranslateImage(InHudTestImage1, Point(320,240)); //this is where we specify the point.


Then I used CortUi's switch command to load MyModCenterHudOn instead of the other ones.

CODE
CenterHudOn = SwitchImage(
    NormalHUDMode,
    emptyImage,
    [
        (0, DefaultCenterHudOn), // Default Normal HUD
        (1, fpCenterHudOn), // lessHUD
        //(2, fp2CenterHudOn), // JelloShot
        (2, MyModCenterHudOn) // MyMod
    ]
);



to my great surprise, the second gradient in my testimage dissolved beautifully into nothingness. (in this image, i had already replaced inventorytopbmp.mdl - the top of the f4-pane - with a gradient-to-transparency).

That was weird, because as you can see, i hadn't used any kind of blending function . all i did was import a PNG with transparent bits and the engine interpreted it perfectly.

Next, i created some PNG's for the F4 menu and put the in my "MyMod" directory. I toned down these images' opacity, so they'd be translucent.

Note that I did NOT use a black background to provide transparency.

inventorytop.png, inventorybottom.png and inventorylinebkgnd.png

i replaced inventorytopbmp.mdl with the following text mdl file, and did the same for the other two:
CODE
use "model";
    inventorytopbmp =
        ImportImageFromFile("mods/MyMod/media/inventorytop.png", true);


then i powered up the training mission and *poof*.



This will make every UI-modder's life a LOT easier.

cheers!


Round 2: battling the inventory menu

Posted by Bunnywabbit, Jun 10 2009, 06:26 AM in GUI-Modding

hey.

The inventory screen is a bit complicated. At least, I think it is. I may be a dumb person. I wouldn't know. After all, my ability to estimate the depth of my own cluelessness is inversely proportional to how thick i really am.

Blablabla.

Anyway...

If i got this correctly, the inventory is called by the engine based on the core files. I will note exactly how I understand the whole process to work, knowing full well that this will enable others to estimate my cluelessness with depressing precision.

So what happens is, the engine is busy assembling the inventory pane. It grabs the bottom, it grabs the top, now it needs to grab the stuff inbetween.
It talks to the core file regarding the available ship slots and learns how many and which kinds are available. It then asks the core for the info regarding the parts that are mounted and loaded.

The engine now know how many rows it needs to make, what kind they are, and also it know the properties of the parts that should go in them.

Then the engine starts looping through the slots it know are there and opens the mdl files that correspond with the kind of slot. It asks those mdl files for one specific item each; a variable called: 'InventoryLine'.

Here's an example for the afterburner slot. Comments are in the code.

( At this point, having a quick glance at Ksero's MDL Language Documentation might be a good idea. (yes Badp, i do wikify stuff mrgreen.gif ))

CODE
use "inventorypart";
//this calls a 'namespace', basically tells the engine what it is dealing with here and how it should interpret the variables.

//TimeLeft will be used in StatsBar
//SwitchString does what it says on the tin. GetAfterburnerTimeLeft retrieves an attribute from the part.
//Note that the 'part' used as an argument below is not specified any further. The engine is using it to call the appropriate mdl. It already knows which part it is dealing with, in this case a booster.

TimeLeft = SwitchString(GetAfterburnerTimeLeft(part, OnEveryFrame),
                    NumberString(GetAfterburnerTimeLeft(part, OnEveryFrame)),
                    [
                        (-1, "Inf.")
                    ]);

//Statsbar will be used below. StringPane is what you'd think it would be.                    
StatsBar =
    StringPane(
        ConcatinatedString( // lines up multiple strings
            ConcatinatedString(
                NumberString(GetAfterburnerTopSpeed(part, OnEveryFrame)),
                "mps / "
            ),
            TimeLeft //This one got created above
        ),
        Color(1,1,1), //color of the string in RGB, where RGB values are from 0 to 1. So this would be white.
        Point(83, 12) //Size. I guess these are xmax and ymax coordinates
    );

//yay, our first ImagePane, a collection of 2D images. In this case, a background and an overlay in the form of a gauge.
//It's the little 'mounting' gauge that you wait for while your fuel reloads. ImagepaneSyntax is as follows:
//ImagePane(BackgroundImage,[(ForeGroundImage1,Point(x,y)),(ForeGroundImage2,Point(x,y)),(ForeGroundImagen,Point(x,y))];    
//Now the size of the BackgroundImage determines the dimensions of the pane.
//The ForeGroundImages have coordinates that tell us where they are relative to the Background.

MountingBar =
    ImagePane(ImportImage("mountingbarbkgndbmp", true), //does what it says on the tin.
        [
            (
                GaugePane(
                    ImportImage("mountingbarbmp", false),
                    GetMountedFraction(part, OnEveryFrame),
                    Color(0, 0, 0),
                    Color(0, 0, 0)
                ),
                Point(0,0)
            )
        ]
    );

    
//this bit is what it's all about. This is what the engine is after. A variable called 'InventoryLine'.
//I think this must contain an ImagePane. I need to experiment, though.
InventoryLine = ImagePane(ImportImage("inventorylinebkgndbmp", false),
    [    
        (ImagePane(ImportImage("invequipmenticonbmp", true), []), Point(5, 5)),
        (StringPane(partkey, Color(1,1,1), Point(12, 12)), Point(23, 5)),

        (StringPane(GetPartName(part, OnEveryFrame), Color(1,1,1), Point(88, 12)), Point(35,5)),
        
        
      
        (
            SwitchPane(
                GetReadyState(part, OnEveryFrame),
                [
                    (StatsBar,      0),
                    (MountingBar,   1),
                    (StatsBar,      3)
                ]
            ),
            Point(130, 5)
        )
    ]
);


That was relatively straightforward, right?

Ok, so the engine wants a variable containing an imagepane.

A quick note about imagepanes:
A 2D collection of images containing a background plus zero or more images or panes that are positioned relative to the background. The size of the BackgroundImage determines the dimensions of the pane.
syntax:
CODE
ImagePane(BackgroundImage,[(ForeGroundImage1,Point(x,y)),(ForeGroundImage2,Point(x,y)),(ForeGroundImage3,Point(x,y))];

You can use it to convert an image to a pane by passing it an empty variable by way of foregroundimages, e.g. ImagePane(YourImage,[])
( The other way around is not entirely clear: PaneImage(YourPane,boolean, boolean) where the first boolean's nature is suspected to regard something called a Zbuffer and the other one is a colorkey of which Ksero also tends to be unsure).

So what the engine gets is a Pane with a backgroundimage called 'inventorylinebkgndbmp', which determines the line's height and, theoretically, its width. (In practice, the width is (also) determined elsewhere, could be the top and bottom parts have a hand in maintaining the width as well.
The pane further contains several strings regarding some stats related to the part involved, and some mounting and/or arming gauges that appear as needed.

I guess now is a good time to list all the mdls involved:

the line mdls
invafterburn.mdl
invchaff.mdl
invcloak.mdl
invdefault.mdl
invobserver.mdl
invsmine.mdl
invsmissile.mdl
invshield.mdl
invturret.mdl
invsweapon.mdl
invemptyafterburner.mdl
invemptyammo.mdl
invemptycargo.mdl
invemptychaff.mdl
invemptycloak.mdl
invemptymine.mdl
invemptymissile.mdl
invemptyshield.mdl
invemptyturret.mdl
invemptyweapon.mdl

images called and assembled by the line mdl's
armingbarbkgndbmp.mdl
armingbarbmp.mdl
mountingbarbkgndbmp.mdl
mountingbarbmp.mdl
inventorylinebkgndbmp.mdl

images called and assembled by the game engine
inventoryselectedbmp.mdl
inventorytabbmp.mdl
inventorytopbmp.mdl
inventorybottombmp.mdl

icons
invequipmenticonbmp.mdl
invcargoiconbmp.mdl
invturreticonbmp.mdl
invweaponiconbmp.mdl


About SwitchPane:
Fun fact about SwitchPane is that it doesn't actually switch images. In fact it re-arranges them in front of/ behind the stack of rendered images.

How do i know this?
Find out soon in the next installment of my continuing struggle with the gamepanes. "crashes and workarounds"

-- BW


round 1: figuring stuff out.

Posted by Bunnywabbit, Jun 8 2009, 10:53 AM in GUI-Modding

Question:
What am i trying to do?

Answer:
I'm trying to accomplish two things: 1) make a GUI mod involving the minimap and the inventory tab. 2) make it in such a way that other modders won't have to jump through so many hoops to make their own.


Question:
Why is this hard?

Answer:
Because many reasons, some of which i probably haven't even run into yet.
It's not difficult to make plain, opaque images to replace the ones currently in use. There's a very limited amount of those and you could just take the bmp.mdl's and make them forward to an image of your choice.

(wha?
i mean you do this:
make a backup of inventorylinebkgndbmp.mdl,
replace the original with a text file with the same name and extension, edit the text file like so, where 'ImageFolder/ImageFile.ext' is an image in a folder in your artwork folder whose naming i leave to you.

CODE
use "model";
inventorylinebkgndbmp =
             ImportImageFromFile("ImageFolder/ImageFile.ext", true);


end of tidbit)

So i could just forward the bmp mdls involved to new images of my own making and this mode is done, right?

Right. If I didn't have ambition that would be it. But I do, so it isn't.

The thing is, with the nice huds that FlingPu made, plain opaque menus don't really fit. I would like to see them be slightly spiffier, with transparency effects and the whole shebang.

That, it turns out, is ridiculously difficult to do. See my topic here.

What complicates matters is that a lot of the functions mentioned in Ksero's excellent reference, either don't actually appear to do anything, or do something subtly, yet crucially, different than what it says on the tin, or finally: crash the game.

So maybe one of my sidequests in this venture should be to update and wikify ksero's list. Maybe someone can help me on that score. Actually, i hope so because i'm bound to make loads of mistakes since i am after all, completely and utterly clueless.

Ok, so what makes this hard?

First of all; it's apparently the division in the Alleg game code between Panes and Images. Panes being, apparently, 2D GUI-elements designed to be not much more spiffy than a slightly pimped form. A couple of interactive elements, some mouseover effects etc.
Images are the stuff that makes the game look cool: 3D textures, transparent elements, all kinds of ingame stuff.

Anyway, that's what i get from a PM conversation with KGJV, who is awesome, and writes (quoted with permission):

QUOTE ("KGJV")
hi

Sorry been too long time since I looked at this.

For transparency/blending I dont recall exactly to help you but I do recall that it was hell of a hack in the engine code ... wink.gif

Dunno if other devs are active out there, if so ask them to look at how the "Image" and "Pane" classes are handled by the engine.

AFAIR, Pane is the base class of all 2D classes and they are rendered 'on demand' by calling their 'Paint' method. Image is the base class of all rendering classes and they are rendered every frame by calling their 'Render' method.

The ImagePane class is used to set an Image in a Pane.

and the PaneImage class is used to render a Pane to an Image.

So there are really 2 distinct 'worlds' in the engine: the Pane world and the Image world. Each with their own features and limitations.

Transparency and other fancy stuff have big problems when going from one "world" to another. Even more if there is a lot of transitions between the 2 worlds (over using ImagePane and PaneImage for instance). Some where in the process, transparency is often lost.

This is one of the biggest flaw and limitation of the current Alleg engine and also one of the reason it's very hard to port it to another engine too because of this "dual world" concept.


So there you have problem one:
The transparency stuff belongs in the 'image-world' and the inventory and sector map sections are in the 'pane-world' and translating transparency effects twixt the two makes for many crashes.


problem two has more to do with the mdl syntax.
As i mentioned above, a lot of the mdl functions do anything, don't do what you'd think they would or crash the game. (Especially, of course, if a total nubbin like me messes with them).


i'm probably gonna ad to the following list while moving along (i warned you this blog was going to be a bit random):

What doesn't really appear to do anything:
CODE
BlendImage(image,blendmodeconstant) //also the blendmodeconstants don't do what you'd hope they would

CODE
ImportImage3D(image,colorconstant, boolean)


what doesn't do what you'd think it would:
CODE
BlendModeAdd, BlendModeSource, BlendModeSourceAlpha // blendmodeconstants. This one is used all the time, but i don't know why. Not using it seems to produce no difference...
Rect(xmin, ymin, xmax, ymax) ... this draws a rectangle on an existing image, but it's often hard to tell which way round it will draw.


what crashes the game:
CODE
ExtentImage(Color(R,G,B),Rect()) // From the documentation i would guess that this would 'procedurally' create an image. It doesn't.



-- BW


&^%*ing around with mdl

Posted by Bunnywabbit, Jun 8 2009, 09:27 AM in GUI-Modding

Hey,

So this may or may not be one of those blogs that get started up and get posted in once or twice, only to lead a kind of zombie-existence on the web for a few years until a merciful admin finally puts it out of its misery.

I have always resisted the urge to start a diary. Not out of modesty, but because i'm lazy and because I have the urge to try and come up with aforisms. The lazyness may still come up and snuff this endeavour. The aforisms i wil try to combat by making this blog about something other than my life or lack thereof.

The last few days i've been messing with mdl files trying to come up with a version that will make it easier for GUI-modders like myself to edit it. So far i've been having extremely limited success, and i'm beginning to suspect that the whole enterprise may be in vain, until some guru comes along and gets around to straightening out the game code to handle things properly.

I figure that if it all comes to nothing it won't be a total waste of time if i can at least gather the info so someone else does not waste any more running into walls that already ran into.

I'll try and wikify some of the stuff I found inasfar as it's wikifyable. Sometimes, though, you have to write stuff down before you can write it down properly. That is what this blog is for.

It probably won't be very reader-friendly. This will be a collection of scribblings and notes and bits of code, formatted or otherwise. And if i decide not to maintain this after all, i will probably delete it to avoid using more elektrons than necessary. After all, there aren't that many elektrons in the universe.

-- BW