AudioClip ID

Started by Crimson Wizard, Wed 29/03/2017 22:44:30

Previous topic - Next topic

Crimson Wizard

Quote from: Gilbert on Wed 29/03/2017 18:44:36
It's a pity that the audio clips in the renewed audio system couldn't be referenced by numbers without complicated methods, so IMO the current AGS versions are broken and thus I refuse to use the recent versions.

First of all, since AGS 3.4.0 there is Game.AudioClips array where you can access audio clips by numeric index. You can even modify that index in project by reordering items by dragging them around. The caveat there is that clips do not have explicit ID (other than script name), so it is never displayed anywhere, but in theory it may be added similarily how characters etc display theirs (although characters and other items cannot have their ids altered, so there will be a confusing discrepancy).

Regarding the rest, I disagree with two things.

I do not agree that the method to index audio clips are complicated, it is just about creating an array of AudioClip references in script. This way you could even have same audio clip in two or more lists to choose from with different algorithms if wanted. There are script modules for making playlists with random shuffle and stuff. Of course, all this comes at the cost of extra scripting.
But that's one thing.


I always had a disagreement with having a global numeric resource ID for such purposes. In my opinion this comes from a misconception between order of resources in the project, which should not be user's bother at all, and order of resources in use list(s). Respectively, at one hand there is a unique ID of a resource in game (which can even be string), and an ID of a resource's order in list. One belongs to resource - and used as a unique reference, another belongs to the list - and used to set up certain algorithm.

The only real issue IMO is that currently you have to write these lists in script instead of using some quicker GUI method.


Since sprites, audio clips, and other game items (I think all or most of them) may already be arranged in subfolders, including reordering in subfolder (although that does not always lead to changing their existing ID, or maybe even never), the potential method could be to allow to reference them by the order in the subfolder. In other words - treating such subfolder as an ordered list.

What that would require -
1) Make sure that the order in subfolder is strictly maintained as the game project is saved and loaded. (I think it already does, but double check is needed)
2) Display the zero-based index of an item in subfolder (?)
3) Save subfolders into game in some way.
4) Design syntax for referencing such subfolders in script.

That's generally my opinion, and how I would approach this if I were to work on this.

But that's also is a "quick solution", using only the existing entities. Because for more universal approach, I would rather suggest separate list of resources (just a big stash) and "use lists" (strictly ordered in some arbitrary way), and make able to drag resource items (which are unique) into the use lists (which contain copyable references).

Gilbert

#1
Quote from: Crimson Wizard on Wed 29/03/2017 22:44:30
First of all, since AGS 3.4.0 there is Game.AudioClips array where you can access audio clips by numeric index. You can even modify that index in project by reordering items by dragging them around. The caveat...
I haven't tried v3.4 onward yet, but if this is accessible then it is fine, but from your descriptions do you mean the numerical IDs aren't accessible by script yet? Then it's not very useful.

Quote
I do not agree that the method to index audio clips are complicated, it is just about creating an array of AudioClip references in script. This way you could even have same audio clip in two or more lists to choose from with different algorithms if wanted. There are script modules for making playlists with random shuffle and stuff. Of course, all this comes at the cost of extra scripting.
It IS complicated if you have to do something like below, which repeats hundreds of time:
Code: ags

AudioClip ac[100];
ac[0] = aScream;
ac[1] = aShout;
...

This cripples codes very heavily which should be unnecessary before the changes. I understand how the new system can be useful to some people(which personally is useless to me though) but sacrificing some really handy features for this is not a really good idea.
For multiple lists(which I don't need) it is actually even easier to do with just numbers than the names. For example, you can make another remapping array easily, like:
Code: ags

int alist2[100];
alist[0] = 5;
alist[71] = 71;
...

You may even put these remapping indices in an external file, load the file in the script and use a for loop to do the mappings, which is much cleaner.

About the subfolder and global indices thing(sorry I haven't read the whole post in detail yet), IMO the subfolders are just for easy management of resources, and are not necessarily related to the internal indices. Personally I think a global index which is unique to each clip is enough, though I won't oppose to have something like audiofolder1.clip[4], etc.

Crimson Wizard

#2
Quote from: Gilbert on Thu 30/03/2017 02:59:51
I haven't tried v3.4 onward yet, but if this is accessible then it is fine, but from your descriptions do you mean the numerical IDs aren't accessible by script yet? Then it's not very useful.
If you mean getting numeric index of particular clip by its pointer, like clip.ID, then there is no such thing, but can you explain why do you need that?


Quote from: Gilbert on Thu 30/03/2017 02:59:51
It IS complicated if you have to do something like below, which repeats hundreds of time:
Code: ags

AudioClip ac[100];
ac[0] = aScream;
ac[1] = aShout;
...

I am curious why would do you need to make a single list of hungreds of sounds, but even then, what's so difficult to start making one from the beginning of the game, and keep adding to it while you are progressing futher? This may be related to workflow, but I honestly do not see how that is different from having to arrange numbers in the file names on disk (sound0, music1 etc) - that you had to do with the old system. Neither I see how can that "cripple" the code... unless you copy&paste that all around instead of having picked out in a single init function.


The only thing that is missing with the new system is being able to distinct a clip referenced by random pointer, or alternatively get a clip by string containing name easily, which makes it harder to parse a map from the file like in your example, but that may be solved by making an ordered array of clips in script, as above. (Or, alternatively, by exporting audio clip's Name into script API, which would let you parse index/string pairs)


The thing is that in either case you must maintain a numbered list of clips:
1) by appropriately naming sound files on disk (while loosing meaningful titles)
OR
2) by appropriately asigning sound names to array in script.

I sincerely cannot see why the first is better/easier than the second. Or maybe I am missing something...


Although that's technically possible to re-add global ID to audio clips if this all is so serious... I guess AGS is just so numbers-based that it takes more effort to support name IDs properly in both script and UI.



Gilbert

Quote from: Crimson Wizard on Thu 30/03/2017 03:22:35
If you mean getting numeric index of particular clip by its pointer, like clip.ID, then there is no such thing, but can you explain why do you need that?
No, I didn't mean clip.ID (it's not that useful anyway), I just meant whether the array itself is accessible via script(as I mentioned I haven't tried 3.4 yet), if it is the problem is already solved.

Quote
... what's so difficult to start making one from the beginning of the game, and keep adding to it while you are progressing futher?
This is not actually difficult, but is actually awful, to include such a HUGE chunk of codes doing nothing apart from tiresome assignments. Personally I think the less resource management done in the scripts the better. This is like, striping the function to assign sprites to individual frames of individual loops in the editor, and require the users to put such stuff in the scripts themselves, which is quite bad.

Quote(Or, alternatively, by exporting audio clip's Name into script API, which would let you parse index/string pairs)
This is a solution too, though not as straight forward and simple as maintaining just an array of numbers.

Quote
The thing is that in either case you must maintain a numbered list of clips:
1) by appropriately naming sound files on disk (while loosing meaningful titles)
OR
2) by appropriately asigning sound names to array in script.

I sincerely cannot see why the first is better/easier than the second. Or maybe I am missing something...
Actually I never said it's a good idea to force users to name sound files according to some conventions (like the old system), what I really said was that as long as you have a global array of indices of all the sound clips and that you can manually reassign them when needed, like with sprites. There is nothing wrong to have meaningful script names for the clips(though it's not useful to me), as long as after importing the file into the editor it is still assigned an index number, and that index could be manually changed and accessible via script then it's done. So, if these features are already in 3.4+ then there is nothing to worry.

Quote
Although that's technically possible to re-add global ID to audio clips if this all is so serious... I guess AGS is just so numbers-based that it takes more effort to support name IDs properly in both script and UI.
I'm quite serious with this though. I haven't thought of other use for sounds yet, but making it easy to say play a random sound from a certain index range, or jukebox like stuff are good enough reasons already. Finding the index to an entity is quite handy and important (which is not so easily done when you can only use "OO" style script names for stuff), for example, in a certain (not done yet) game I use them to draw tiles on the playfield. I may say number a tile with the number "UDLRNN", where NN is the base index of an sprite (such as a tree, or a wall) and the four digits UDLR are determined by what are present in the four adjacent squares, so you may easily choose the right sprite according to what are around the square.

Snarky

If the AudioClip IDs are just the order they appear in the project, then if you add a clip to a higher folder, it invalidates the IDs of all clips in folders below it, right? That seems like such a severe limitation that it makes the feature almost unusable.

I'm not a huge fan of a generic Game.AudioClips[] array (or similar for any of the other resource arrays AGS offers), though it's probably necessary given other limitations. Ideally I think it would be nice if the project folders were accessible from the script, and then if you needed to choose some clip algorithmically you could just get the clips for that folder as an array.

One version of this solution would be that all folders automatically create an AudioFolder* object, with an accessible AudioFolder.Clips[] array. (In this case there should also be a way to get them for the audio types.) Another and more general possibility would be to create a ResourceFolder static class, on which you could call methods such as ResourceFolder.GetAudioClips("/Music/Jukebox") or ResourceFolder.GetSprites("Characters/Roger/Tuxedo"). (There would then also need to be a way to iterate through subfolders.)

Quote from: Gilbert on Thu 30/03/2017 02:59:51
It IS complicated if you have to do something like below, which repeats hundreds of time:
Code: ags

AudioClip ac[100];
ac[0] = aScream;
ac[1] = aShout;
...

This cripples codes very heavily which should be unnecessary before the changes. I understand how the new system can be useful to some people(which personally is useless to me though) but sacrificing some really handy features for this is not a really good idea.
For multiple lists(which I don't need) it is actually even easier to do with just numbers than the names. For example, you can make another remapping array easily, like:
Code: ags

int alist2[100];
alist[0] = 5;
alist[71] = 71;
...


Hold on! Your second, "easy" example is just the same as the first, except worse because it uses cryptic numbers instead of transparent names.

I would also note that since there's no way to assign a name to an audio clip, for a jukebox you would still need a function that is just one long list of assignments.

Monsieur OUXX

#5
I'm sorry to mix two conversations (on the one hand, the overall conversation about the best practices for handling stuff in the code using numbers/pointers/arrays of those, and on the other hand the original conversation about the usefulness of setting custom sprite numbers). But I feel the urge of pushing forward the investigation on why people use custom sprite numbers :

Gilbert, you said you use special algorithms to predict the number of a sprite or a sound.
I suppose you use this to manipulate sequences of sprites or sounds, based on the number of the first one (for example, if you know that the first sprite of an animaiton is 1,000, then you can predict that the 3rd sprite is 1,002 -- but that works only if the numbers ar ein sequence). did I guess right?
Could you give an accurate example of such use? A module you made, maybe?


=========

Also, this:
Quote from: Snarky on Thu 30/03/2017 09:23:12
I'm not a huge fan of a generic Game.AudioClips[] array (or similar for any of the other resource arrays AGS offers), though it's probably necessary given other limitations.
It's always vital to be able to iterate on every stuff in the game. This is what allows universal powerful scripts, as opposed to hand-made scripts with limited scope.

========

Also, this:
Quote
Although that's technically possible to re-add global ID to audio clips if this all is so serious... I guess AGS is just so numbers-based that it takes more effort to support name IDs properly in both script and UI.
I think that everything should have an ID. That's how it's made in professional tools, like, let's say, Sharepoint. On the one hand there's the actual pointer to manipulate stuff at execution time, but on the other hand there's always a unique numerical Guid hidden somewhere, as the unique identity of this item.
They don't have the same use : the reference or lightweight ID or even url makes the object unique at execution time. I don't mean only code execution, but also what you could call databse instantiation -- had you instantiated that database slightly differently (for example: in dev environment or in production environment, some basic settings are slightly different), then some urls would be different.
However the Guid makes it unique before the execution and even before instantiation. For example, even before databases get built, at the time the columns get defined, everything gets a unique ID.
--> And that's precisely the paradigm that we encounter in AGS : we add/delete/move items in the Editor outside of the execution time. And yet we want their identity to remain stable, to disambiguate the identities of these sprites/sounds/whatnot when required. That's what IDs are for.
One might argue that sprites do need an ID because they don't have names, but sounds do have names. Well, there is indeed a contradiction there. Snarky pointed it out in his "hold on, these are the same examples" remark. True. In the case of sounds, IDs would be exactly like names. But a name is easy to change (woops, I mistyped something). Whereas an ID should be, and remain, unique.

======

also, also : have you ntocied how this entire thread exactly addresses the issues I've raised regarding the half-baked pointers system of AGS? What is Gilbert doing, apart from working around the lack of pointers and referencing capabilities by using the lightweight and "universal" type that is int -- which he can easily reaffect, iterate on, and store into arrays?
 

Snarky

#6
Quote from: Monsieur OUXX on Thu 30/03/2017 10:56:08
Quote from: Snarky on Thu 30/03/2017 09:23:12
I'm not a huge fan of a generic Game.AudioClips[] array (or similar for any of the other resource arrays AGS offers), though it's probably necessary given other limitations.
It's always vital to be able to iterate on every stuff in the game. This is what allows universal powerful scripts, as opposed to hand-made scripts with limited scope.

:P I don't know about "always vital", but I'm not against iteration. Indeed, it's the fact that I don't think a generic arrays offers good enough support for iteration that makes me not a fan.

Sprite IDs offer the perfect example: in order to iterate properly over some subset of sprites, they all have to be imported sequentially (and there can't be any holes in your sprite numbering), or you'll have to tediously renumber them individually. If you've used a range of, let's say, sprite index 256-380 for some index-arithmetic code, and then need to add another twenty after you've already used the slots from 381 to 1475, you're basically screwed (the best I can think of is to export the sprites in question and reimport them, creating a copy with a new series of sequential indexes, then add the new sprites, and ONLY THEN delete the original copies, before finally updating the index values in the code).

It should be obvious that this sucks.

If instead you could get lists of sprites based on the sprite folder structure (and the sort order within the folder), this would not be a problem: you can now very easily iterate across any group of sprites defined in the editor, and updating them wouldn't require any changes to (well-written) code, or messing around with the sprite index.

It's basically the same way you can iterate through a set of related GUIControls using GUI.Controls[], rather than by having some global array of all GUIControls, and having to ensure that the indexes of all the ones belonging to one GUI are consecutive in that array.

Sure, for the (I suspect) rare-to-the-point-of-nonexistence case where you really want to iterate through EVERY instance of a sprite or other resource in the game, you might offer access to a generic array*, but it should not be the primary basis for code that manipulates sets of resources.

(* Of course, there's no sprite array explicitly available to AGS code; instead all functions that use or work on sprites just take the int sprite index as an argument.)

Quote from: Monsieur OUXX on Thu 30/03/2017 10:56:08
I think that everything should have an ID. That's how it's made in professional tools, like, let's say, Sharepoint. On the one hand there's the actual pointer to manipulate stuff at execution time, but on the other hand there's always a unique numerical Guid hidden somewhere, as the unique identity of this item.
They don't have the same use : the reference or lightweight ID or even url makes the object unique at execution time. I don't mean only code execution, but also what you could call databse instantiation -- had you instantiated that database slightly differently (for example: in dev environment or in production environment, some basic settings are slightly different), then some urls would be different.
However the Guid makes it unique before the execution and even before instantiation. For example, even before databases get built, at the time the columns get defined, everything gets a unique ID.
--> And that's precisely the paradigm that we encounter in AGS : we add/delete/move items in the Editor outside of the execution time. And yet we want their identity to remain stable, to disambiguate the identities of these sprites/sounds/whatnot when required. That's what IDs are for.
One might argue that sprites do need an ID because they don't have names, but sounds do have names. Well, there is indeed a contradiction there. Snarky pointed it out in his "hold on, these are the same examples" remark. True. In the case of sounds, IDs would be exactly like names. But a name is easy to change (woops, I mistyped something). Whereas an ID should be, and remain, unique.

The corollary of that argument is that it should not be possible to change the ID: if it is necessary to do so, it's because we're abusing it for something it's not suited for.

Crimson Wizard

#7
So, the current problem is that -
1) AudioClips do not have any ID property whatsoever. Script-name is not really an ID in AGS, you cannot convert it to basic type and store somewhere (like in file). In fact, script-name is a name of variable that will be declared in your game's invisible built-in script header.
2) AudioClips cannot be meaningfully arranged in the strictly ordered list within editor's UI. Dragging them around folders works, but it is error-prone and easily broken, as Snarky pointed out in one of his posts above.

No matter how I look at this, adding unique numeric ID to AudioClip is the only solution that is:
a) Easy enough to work on (in the situation when we have little human/time resource)
b) Consistent with the rest of AGS (since [almost] every other item in project has a unique numeric ID).

So... yes, I guess this is what we should do.

NOTE: scripting subfolders is a good idea too, but that's rather complementary, also being a completely new feature.


EDIT: there was something else in the post, but I decided to remove it, because text was rather raw.
Sorry for editing my posts so much.

Gilbert

#8
Quote from: Snarky on Thu 30/03/2017 09:23:12
Hold on! Your second, "easy" example is just the same as the first, except worse because it uses cryptic numbers instead of transparent names.
Read my post more carefully, it IS easier when you can store the mapping in an external data file and you only need to have a for loop instead of hundred lines of codes. Also, IMO using well defined numerical indices is much less error prone than names, as long as you have good planning you can manage this easier, but to each his own, I wouldn't argue on this aspect. Also, I already mentioned I actually don't need this kind of mappings myself as I don't need multiple lists of different orders. It's because CW mentioned multiple lists that I explain why it is easier to manage with numbers instead of names. If there is only one list you don't even need to do anything in the script to remap everything.

Quote from: Monsieur OUXX on Thu 30/03/2017 10:56:08
Could you give an accurate example of such use? A module you made, maybe?
I've already posted an example in how to choose the appropriate sprites for use in a tile map. This is what I am really doing in my game, but I was just to lazy to dig up the actual codes and show the actual formulae, etc. Also, personally I don't write modules often, as I'd rather put everything in one place, so when I want to reuse codes I just copy-paste codes from one project to another and make necessary modifications to them to more match the new project's need.

Monsieur OUXX

Quote from: Crimson Wizard on Thu 30/03/2017 14:03:48
So, the current problem is that -
1) AudioClips do not have any ID property whatsoever. Script-name is not really an ID in AGS, you cannot convert it to basic type and store somewhere (like in file). In fact, script-name is a name of variable that will be declared in your game's invisible built-in script header.
2) AudioClips cannot be meaningfully arranged in the strictly ordered list within editor's UI. Dragging them around folders works, but it is error-prone and easily broken, as Snarky pointed out in one of his posts above.

Yes.
 

Snarky

Quote from: Gilbert on Thu 30/03/2017 15:56:17
Quote from: Snarky on Thu 30/03/2017 09:23:12
Hold on! Your second, "easy" example is just the same as the first, except worse because it uses cryptic numbers instead of transparent names.
Read my post more carefully, it IS easier when you can store the mapping in an external data file and you only need to have a for loop instead of hundred lines of codes.

First, that wasn't your actual example. Second, storing it in an external file may be cleaner in various ways, but it's not significantly easier. You still have to enter all the same data.

Gilbert

How is it NOT much simpler and easier to just have a file of plain values compared to multiple lines of assignment? I'd rather not argue about this anymore as it's probably based on personal coding preference.
As I mentioned I don't really need multiple lists and this was not something I brought up, so how can I have an actual example here? For only one list (i.e. the one and only array indices) you don't even need to do anything in the script, as it just works naturally without any need for those multiple lines of assignments which are only required when those indices aren't accessible to the users in the first place.

Crimson Wizard

#12
Quote from: Gilbert on Thu 30/03/2017 16:35:33
How is it NOT much simpler and easier to just have a file of plain values compared to multiple lines of assignment?
Personally I do not compare files with plain values to assignments in script, obviously these have separate uses.
I compare values of different types (numbers and string). So, e.g., that is a file with number/number pairs and file with number/string pairs.
At the very least these methods are equal, but in practice it depends on what it is easier for you to distinct, remember and work with in the particular case.

Ofcourse numbers also have certain technical advantage in AGS because of little (actually none) built-in means AGS provides to get an item by the string key.


EDIT: Uhhhhh.... there is something in these discussions, or myself, that I cannot concentrate and forget my own point. Because this is not what I was going to say... this has not to be an argument of "number vs string". This was about unique ID (which may as well be numbers without problem) and using them to create sequences.

-------------------------------------------------------------------------------------


For the rest, this is a concept vs UI simplicity. As I mentioned in one of the posts above, there is a concept of unique resource identifier, which does not have to be ordered, but only being a unique key. And there is a concept of ordered list you use to perform certain operations with. From this pov, AGS traditionally uses mixed resource list, which combines both global unique id and sorted index in one (number). Thus users get ability to create a sorted list immediately as they add items to the project.

This works, and may be very convenient, while you are good with using only one numbered sequence, but that is a particular use case which requires certain approach and habit.

Even with subfolders in latest versions of AGS this already may cause confusion, since you may drag items around, but their order in folders tree and numeric ID are not related.

SMF spam blocked by CleanTalk