PDA

View Full Version : Script Drawing Improvements.



Gleeok
03-15-2016, 06:42 AM
[edit] Added the following:


Screen->SetRenderSource(source, x, y, w, h);
Screen->CreateBitmap(w, h, depth = 8);
Screen->DrawBitmapEx(layer, bitmap, x, y, w, h, tx, ty, tw, th, mask, bool, bool);
Screen->Polygon(...);
Screen->DrawPixelArray(layer, count, []x, []y, []colors);
Screen->DrawTileArray(layer, count, []tiles, []x, []y, []colors);
Screen->DrawComboArray(layer, count, []combos, []x, []y, []colors);

TODO:
Screen->Polygon(...);
Screen->DrawBitmapEx(...);
int opacity arguments to Tile() and Combo() will accept 128, or 256 to draw a cloaked tile or combo.



Post anything I'm missing here. It's better just to get everything in one go, so I'm making super duper sure berforhand. :) *cough* I'm lazy *cough*

Likely candidates so far:

[1] Screen->DrawBitmapEx(...);
[2] Screen->SetRenderSource(source, x, y, w, h);
[3] Screen->Polygon(...);
[4] Screen->DrawPixelArray([]x, []y, []colors, int count);

[1] Most common bitching about bitmaps is the way allegro does translucency and the fact that drawing inverted things is all the rage with the kiddies these days.... fair enough. Let's make one specially designed for those cases then.
[2] Instead of drawing from tiles or combos with other 3D (Quad, Triangle, etc..) drawing commands you could draw from bitmaps instead. Usage:


Screen->SetRenderSource(RT_BITMAP1, ...);
Screen->Quad(...);
Screen->SetRenderSource(RT_DEFAULT);


[3] Not sure really... It's over 9000!!! (ZoriaRPG was going to test this one)
[4] Because PutPixel is slow and crappy, and if you ever want to draw single pixels then you probably want to draw a lot more than 1000 of them.

Others (?) XOR drawing mode. ZoriaRPG expressed interest in this, but I'm a bit skeptical on the usefulness (Not too mention the testing! Oh noes, the tesing! :P ) Though, it could be easy enough to support other drawing modes by introducing a simple mask to opacity. [Example: DrawSomething(x, y, 128 | DM_XOR] ..or some other non-intrusive thing.

[5] Screen->CreateBitmap(w, h); // let users specify the size of bitmaps.
[6] Screen->DrawCloakedTile/Combo(); // Draw invisible stuff. ...Confused yet? ;) (Perhaps instead add a mask to other drawing commands, ie; translucent = 64, opaque = 128, cloakes = 256, - might be better.

Saffith
03-15-2016, 04:02 PM
Others (?) XOR drawing mode. ZoriaRPG expressed interest in this, but I'm a bit skeptical on the usefulness (Not too mention the testing! Oh noes, the tesing! :P ) Though, it could be easy enough to support other drawing modes by introducing a simple mask to opacity. [Example: DrawSomething(x, y, 128 | DM_XOR] ..or some other non-intrusive thing.
I've been opposed to XOR drawing for two reasons.
One, no one asking for it seems to understand what it would actually do. It doesn't simply cut shapes out, and it wouldn't erase upper layers. People say they want it for LttP-style dark rooms, and it simply isn't appropriate for that.
Two, Allegro's implementation is problematic. It doesn't XOR the colors; it XORs the palette indices. That makes it too unpredictable to be useful at all, and it would be very difficult to support in the future.

I would like to see additive and subtractive drawing modes, but adding those in 8-bit color would mean keeping two more translucency tables. I don't think it's worth the added effort and overhead.

Tamamo
03-15-2016, 04:41 PM
I've been opposed to XOR drawing for two reasons.
One, no one asking for it seems to understand what it would actually do. It doesn't simply cut shapes out, and it wouldn't erase upper layers. People say they want it for LttP-style dark rooms, and it simply isn't appropriate for that.
Two, Allegro's implementation is problematic. It doesn't XOR the colors; it XORs the palette indices. That makes it too unpredictable to be useful at all, and it would be very difficult to support in the future.

I would like to see additive and subtractive drawing modes, but adding those in 8-bit color would mean keeping two more translucency tables. I don't think it's worth the added effort and overhead.

One of the many reasons I hate Allegro and think we should get rid of it entirely.
It's possible to create LttP-style dark rooms with bitmap drawing thankfully, I've already crossed that bridge before.

ZoriaRPG
03-15-2016, 09:08 PM
As far as I'm aware, I've solved the translucent drawing and 'cut-outs' without XOR drawing. It needs a build, and some testing.
I have, ready and prepared, a variation of DrawBitmap() that is set to roll out as DrawSprite(), or whatever you intend to call it, that has settings for all the Allegro 4 sprite modes. I did not yet add this to the bytecode, or elsewhere, but I planned to do this in the next build.

Xor would be interesting for a handful of visual effects, but I agree that the problems it presents versus the needs/desires of other people that care about it, make it infeasible to implement, and to support. For the record, I wanted to do overlapping 'additive' drawing, that Xor'd out the overlapped areas, but drew the non-overlapping areas.

If we do get sprite effects in here as planned, there's no reason no to allow that sort of thing with the understanding that it only works properly on bitmap layers, and not when rendered tot he screen; but if you expect to move to ag5, at some future point, you'll need to figure out how to handle replicating the effect. I personally have no concern with ag5, at present, and no intention to move to it as things stand.

SetRenderSource() would be interesting enough.

I'm pretty much in favour of an expansion of the pasudo-3D functions. I've done that partly, and have solutions for handling it without massive rewriting. Polygon() might be usable. I'm not entirely sure. I worked on it in August, and when I saw that it wasn't going to be included in 2.50.2, I stopped dead. Now I don't recall where I left off, but I sent the files to both of you at the time. I might just start from scratch.

I think I was unsure how best to read the array values passed into the ZScript params with it;and I never did a non-filled version, as that would be solved with drawing the shape again in colour 0.

On that topic,what I sense that people want to do, is to exclude out objects drawn to the screen in colour 0 on a given layer. That is, if you draw a rect in colour 13, and draw a rect inside of it in colour 0, it would slice out that portion; just as it would on a bitmap layer. I have no idea how to accomplish that at present, but I do know how to achieve this goal with bitmap usage, as I stated above.

Regarding bytecode, and other word table concerns: Does anyone care if I use some of the present, 'reserved' fields for this? I'd rather do that than expand the table, and that's why they were reserved, in theory.

One thing that is absent here, is a much larger bitmap area. I think CreateBitmap(int ID, int width, int height, int cdepth, [...]) would be the most useful command, in which an area can be defined as a specific size, and then selected as a target.

Additional drawing layers above 7 would also be interesting, but I've no examined the difficulty.

I'll remind everyone that all the other interesting ag4 drawing can only be accomplished in 32b colour depths, but it _may_ be possible to create 32b bitmaps, do things such as alpha layers, ans then render them to the screen in 8-bit mode. The results, I can't guarantee.

Some way to save bitmaps tot he quest file, such as StoreBitmap() or SaveBitmap() would be useful as well. Ideally, this would work in cojunctiom with CreateBitmap() using the ID specified on creation; and would allow preconfiguring graphics that the author intends to reuse, without needing to set them up on each quest load. They can be configured with ~Init or something, and then called instantly.

Another (infrequent, but multiple-instance) user request has been an increased number of draws per frame. I haven't looked into that at all.

I should probably pull the script drawing sections from the to-do list and expand on them here.

Gleeok
03-15-2016, 09:34 PM
One thing that is absent here, is a much larger bitmap area. I think CreateBitmap(int ID, int width, int height, int cdepth, [...]) would be the most useful command, in which an area can be defined as a specific size, and then selected as a target.



Ha! You've just been ninja'd. :P

The other things are good, but not part of this go. I do like the idea of loading and storing bitmaps into the quest file itself through the editor, possibly even multiple tile pages, etc., but that's for another day.

The limit on draws per frame can be fixed without much problem, but it requires me to rewrite the current system. It's always been on my todo radar, but it's very low priority.

I only mentioned Polygon because you said you had it partially done. I can add the bytecode and array handling for it, then you can just see how I do it.

ZoriaRPG
03-16-2016, 04:59 AM
Ha! You've just been ninja'd. :P

The other things are good, but not part of this go. I do like the idea of loading and storing bitmaps into the quest file itself through the editor, possibly even multiple tile pages, etc., but that's for another day.

The limit on draws per frame can be fixed without much problem, but it requires me to rewrite the current system. It's always been on my todo radar, but it's very low priority.

I only mentioned Polygon because you said you had it partially done. I can add the bytecode and array handling for it, then you can just see how I do it.

I do have it partially done. In fact, I have two distinct versions of it. I'm pretty sure that I sent both of them to you... I set it aside when it seemed as if it wasn't going to happen.

If you want to do the bytecode and params, and a send me the revised file, or some notes on what you changed to add a new function, that would be very useful; as at present, all that I know if based on presumptions on how to properly add things. If it proves what I'm doing is right, fantastic. Otherwise, I can correct any issues, and add the other components at the same time.

Some code comments on how you handle passing the ZScript arrays should suffice for that. I still do not know if there is a way to allow the user to pass either an entire array via its pointer, or a specific variable value/index value, to the same param, and detect which was passed. Knowing this would be very useful to some of the plans.

I haven;t added any of the recent changes to a git fork or anything like that; as GitHub is being prissy, and giving me errors when i try to merge them into the present fork... They are all on one of the private servers though, so I will link you to them, if you want to have a look. I've been doing some things with the parser itself, that I believe can easily go into the next build, but they may need tinkering.

DrawSprite() with params for pretty much all the modes (e.g. DrawBitmapEx(), whatever 'Ex' is supposed to mean) is complete enough for me to finish in twenty minutes and send over, but if you send me the bytecode changes for Polygon(), I can use that to do all of the work needed to implement it.

I'm going to mention that I somewhat favour DrawSprite(0 for this, as that is how allegro works, but I see the concern with the word 'sprite' as a user-end confusion/conflict. I think we can come up with a better name, unless you know a way to use the number of params to call a different internal function.

That is, DrawBitmap() with more params than now, calls do_drawaspriter(), but with the present number of params, calls do_drawbitmapr(). That would be ideal, as it would function as a simple overload, and be generally transparent to the user.

P.S. Where was I ninja'd here? Oh, you edited the top post. I see.

So, aye, option [5] sounds good. I'd consider the args that I specified, though, so that we can implement other colour depths in the future. I'm pretty sure that allegro will translate downward, after applying effects to a 32b bitmap, when copying it to an 8-bit bitmap in memory. That would allow 'using' advanced editing, before rendering it.

Also, my modifications to the pseduo-3d functions go hand-in-hand with all of this, and should be in the next version. The changes allow using a bitmap as a drawing texture, and would be very useful for advanced visual effects. Again, a param overload would be good for them, if possible.

Here's a copy from the list:

ZScript::Script Drawing

Add additional routines for bitmap handling, including translucent rendering to screen.
Increase bitmap area to a very large size (possibly for advanced panning, or scrolling)
Add missing drawing functions, such as Polygon() and Polygon3d()
Allow setting a bitmap as a texture to a drawn object.


3/4 are at least partially done, or mostly implemented. I didn't touch making larger bitmaps...yet; nor did I handle the 3D version of Polygon(), although that shouldn't be too much of a pain in the arse once Polygon() is implemented.

Let me know what files you want, or need.

Also...I need some documentation on how you changed DrawBitmap() between 2.50.0/1 and 2.50.2, that changed the offset bug, so that I can supply a version-reading workaround for the users that need one. I should be able to do that simply enough, in an automatic fashion, but I have no idea what you changed, and I do not believe I have the version of the codebase prior to your changes.

Gleeok
03-16-2016, 05:14 AM
Wait until I get to it and I'll set those up for you. Just tell me the parameters your DrawSprite takes.

ZoriaRPG
03-16-2016, 09:12 AM
Wait until I get to it and I'll set those up for you. Just tell me the parameters your DrawSprite takes.



void do_drawspriter(BITMAP *bmp, int *sdci, int xoffset, int yoffset)
{
//sdci[1]=layer
//sdci[2]=bitmap
//sdci[3]=sourcex
//sdci[4]=sourcey
//sdci[5]=sourcew
//sdci[6]=sourceh
//sdci[7]=destx
//sdci[8]=desty
//sdci[9]=destw
//sdci[10]=desth
//sdci[11]=int rot
//sdci[12]=bool mask
//scdi[13]=bool lit
//scdi[14]=bool trans
//scdi[15]=bool stretch
//scdi[16]=int flip (none, horiz, vert, both)



I'm also going to suggest doing a poll for the function name on Pure, and a discussion here, to determine if people want it to be called DrawSprite(), or something else. We can put together some suggestions...unless it is possible to choose from multiple internal funcntions (in this case, do_drawbitmapr() and do_drawspriter() based on the number of parameters passed to DrawBitmap() in ZScript.

Meaning, if 12 params are passed to DrawBitmap(...), the parser will compile as the ZASM word BITMAPR, but if 16 params are passed to DrawBitmap(...), it will compile to SPRITER (or DRAWSPRITER ... I think that I prefer the latter).

As a note, I'd like to explain why i want to use an overload for this:

I wish to use DrawBitmap() as a single function, and use these 16 params as the prime instruction for 2.55/2.60; bit I want to ensure that older scripts do not lose compatibility. If we can make that work, it'll avoid any user confusion based on the naming, we won't have two similar functions with different names, and all scripts made to use the prior function will still compile; but we can effectively deprecate it.

Otherwise, we have two functions in ZScript, with different names, that do the same thing, except that one will be more limited, and it happens to be the one with the better function name. I know that the instruction index includes a 'number of parameters' entry, so is it possible to use this to determine the output, or is that params value only valid for the ZASM side of things?

It'd help to have a little more documentation on how to modify the table, and so forth, so that I can patch that into my docs. I've done what I can, but some of it is guesswork, and I'd rather have the straight dope on something this important. Do you think you can write up a quick 'how to' on adding a function, as a step-by-step process; and on how to set up reading it; so that I can add it to the docs?

Gleeok
03-16-2016, 05:54 PM
If I've learned anything from naming functions from game programming it's don't be arbitrarily over generic because it just ends up being confusing. Sprite really isn't a good name because it's not a sprite. It's a function that draws a rectangle from a memory bitmap with some params in a purely procedural context. What if, later on, scripts can actually create sprite objects. What do we call the function that draws that? Then DrawSprite() draws bitmap stuff and DrawObjectGrapghicDataInstance() draws sprites. See what I mean? ;)

I think you're thinking about this too hard. A separate function is fine because it fundamentally does something different, and, also to retain backwards compatibility with 2.50. Also, I'm not going anywhere near trying to hack in some weird call stack replacement thing. I'd prefer to not have to worry about corrupting peoples scripts in the first place. :)

Tamamo
03-16-2016, 11:20 PM
Gleeok Saffith
I'd hate to be the asshole to ask this question but..

How much of a pain in the ass would it be to just replace Allegro 4? Allegro 4 needs to be removed entirely it's visa has expired you both know that. Sure we'll break ZC all the way to it's core and have to fix it back up again. It would be a monster project and AGN might even need to find another dedicated ZC Dev who knows. But it's not the 90s anymore damn it. We've been using Allegro 4 since the beginning. Don't you think it's time we move on to a more modern library.

Allegro 5 does not count.

ZoriaRPG
03-17-2016, 10:36 AM
Gleeok Saffith
I'd hate to be the asshole to ask this question but..

How much of a pain in the ass would it be to just replace Allegro 4? Allegro 4 needs to be removed entirely it's visa has expired you both know that. Sure we'll break ZC all the way to it's core and have to fix it back up again. It would be a monster project and AGN might even need to find another dedicated ZC Dev who knows. But it's not the 90s anymore damn it. We've been using Allegro 4 since the beginning. Don't you think it's time we move on to a more modern library.

Allegro 5 does not count.

May as well start from scratch at that point, and probably write the core libs instead of relying on anything made by a third-party.

Gleeok
03-30-2016, 02:38 AM
Added the following:

Screen->SetRenderSource(source, x, y, w, h);
Screen->CreateBitmap(w, h, depth = 8);
Screen->DrawBitmapEx(layer, bitmap, x, y, w, h, tx, ty, tw, th, mask, bool, bool);
Screen->Polygon(...);
Screen->DrawPixelArray(layer, count, []x, []y, []colors);
Screen->DrawTileArray(layer, count, []tiles, []x, []y, []colors);
Screen->DrawComboArray(layer, count, []combos, []x, []y, []colors);

TODO:
Screen->Polygon(...);
Screen->DrawBitmapEx(...);
int opacity arguments to Tile() and Combo() will accept 128, or 256 to draw a cloaked tile or combo.


This pretty much completes the script drawing. I don't plan on adding anything else at this point. At least not until angelscript, where we can create a new drawing API that's much, much, better.

ZoriaRPG
04-11-2016, 02:35 AM
I'd just do int bitdepth on CreateBitmap(). In theory, a user could make 32b bitmaps, do alpha stuff, and render them back as 8-bit. Might make interesting effects. Might look dreadful, but Allegroshould auto downsample 32b to 8b when rendering it via a release. then we can add all those 32b only modes that you wanted.

I also noticed that in CreateBitmap, you added static sizes of min =1 max = 2048. Care to explain?why not just allocate whatever the user wishes, up to zscript numbering limitations? Won't this also conflict with the other preddefined constraints too?

I'll go over it al in more detail, and patch in the functions. If you thought Polygon was big, BitmapEx is bigger. I'd alllso sugest DrawBitmapFx() (as in 'effects'). I think that's more on the money than Ex (Experimental, or Extended?)

I'll see if I can connect all the dots and make a text file on adding functions. We absolutely need this, including for adding setter/getter stuff.

Gleeok
04-11-2016, 06:52 PM
Nothing is finished yet, so anything may and probably will change slightly.

If you want 10,000 x 10,000 bitmaps at 32bit I'll leave it to you to figure out how much memory that would require/ costs/ effects on CPU cache/ etc.
Sounds like a bad idea to me, but whatever. If anyone can give me a single use case that isn't completely bat-shit dumb-dumb then that's fine with me.

ZoriaRPG
07-11-2016, 06:32 PM
The Moosh has been asking me to add allegro light table things, which we could, and may as well do, or at least discuss, at the same time. I suppose I could just pile up a full set of DrawLit*() functions, but IDK if we properly support lit drawing modes. If we cannot support light tables, then i should rip out lit modes in DrawBitmapEx().

Tamamo
07-12-2016, 12:30 AM
Hold up on that, I want to add Dynamic Lighting.
That is to say. Where CSets 2-4 all have different dark levels like in LttP.

ZoriaRPG
07-12-2016, 12:51 AM
Hold up on that, I want to add Dynamic Lighting.
That is to say. Where CSets 2-4 all have different dark levels like in LttP.



So...light tables are an allegro thing. It's possible to manually change them, but it's not something I'd call fun. I don't even know if they will work properly with the present set-up. It's just DRAW_LIT_SRITE or DRAW_MODE_LIT, which is a subset of DRAW_MODE_TRANS. In fact, DRAW_MODE_TRANS is supposed to support light tables, but we don't use them. (We use a simple trans table, instead.)

What exactly are you planning to do, and by what method; and does it tie into the base drawing functions?

FWIW I was just going to to slap Lit* versions of all the drawing commands in there, to support light table transparency. There's not really a better way to do it that wouldn't break piles of existing scripts. LitCombo(), LitTile(), LitLine(), LitCircle(), and so forth, all functioning as the ordinary draw command, except that they are always in DRAW_MODE_LIT/TRANS and the opacity arg is the actual lit/trans level, rather than an arbitrary value, so 0 to 256 would all be 'gradients'.

I also went ahead and simplified DrawBitmapEx() quite a bit. I added a second sub-bitmap, set to '10'--may need to change that-- to which rotation is drawn, if we're rotating things. Then, the rotated sprite is released to the first sub-bitmap, and that is rendered to the screen bitmap with one of the effects (modes, flips). That's in the file, here:

http://timelord.insomnia247.nl/zc/zc_dev/2.53/script_drawing.cpp

So, the first sub-bitmap is always in use. The second is only used for rotation. I hope this makes sense.

Polygon is also in there, but it lacks rotation maths, if we want to automate those somehow at all. I'm sort of at a loss for a good way to do that, or do an outline mode, because there's no way to predict the number of vertices: It technically supports up to 214747 / 2 angles per shape. There's just no realistic way to rotate all of those, that comes to mind, and forget doing an outline mode with that many variables. If people want an outline of their polygon, they can draw a second polygon that is slightly smaller, in colour 0.

If they want it to rotate, they should probably just adjust the vertices in the array to make it rotate manually, or draw it to a bitmap and rotate the bitmap. That would be the easiest solution.

The temporary 'lit' functions, that at present do nothing, are here: http://timelord.insomnia247.nl/zc/zc_dev/2.53/script_drawing_lit.cpp