Author
|
Topic: UQM Tools (Read 23420 times)
|
Elestan
*Smell* controller
Offline
Posts: 431
|
If you're defining an XML format for conversations, you might look at http://www.w3.org/TR/ttaf1-dfxp. It's the W3C standard XML format for timed text.
|
|
|
Logged
|
|
|
|
Megagun
Enlightened
Offline
Gender:
Posts: 580
Moo
|
UQMAnimationTool v0.41 released. Binary here
Changelog: +Added in-tool editing. W/A/S/D to move a frame up/left/down/right. Shift+W/A/S/D to move all frames up/left/down/right. +Added in-tool saving of files. +Added transparency helpers and selected frame highlighting, which should make editing/viewing easier +Added text at the bottom that displays the coordinates of the pixel the mouse is hovering on (as requested) +Added a button that sets the X/Y offsets for all frames in an animation +Keyboard shortcut: UP/DOWN arrow selects the next/previous frame in the animation +Keyboard shortcut: SPACE plays one loop of the animation +Keyboard shortcut: P plays/pauses the animation -Removed 'reload file' button -Removed ability to ignore duplicate lines (because that may cause things to break if you save later) *Bugfixes *Debug printout in case a file can't be found
|
|
« Last Edit: November 08, 2011, 09:00:41 pm by Megagun »
|
Logged
|
|
|
|
dczanik
*Smell* controller
Offline
Posts: 306
|
Damn you sir.
Damn you for not making this earlier! This would have saved a ton of time if I had this earlier. I'm loving this version. It's really starting to feel like a real animation tool, instead of an animation player. This is a big deal to me.
As probably your biggest user of this tool, some suggestions:
1. Sometimes there's blocks of files that need to have the same coordinates. I don't know how you would handle this, but I would just load up my editor and do a SEARCH/REPLACE to replace those lines. It's quicker than going line by line. But now, without the reload button I have to: click load file, click type of file .ani find the .ani file click the .ani file, click load. Go back to the frame I was looking at. Not a huge amount of time. But when you're talking about 120 lines, that can add up. It would be easier to just hit F5 to reload the file, or have some way to edit the file.
2. A Save icon: So I can tweak the file, hit save, move on to the next frame. 3. X,Y input boxes. So I can just type in a number to jump the thing over instead of moving something from one side to another. WASD is great for fine tuning, but for my high res stuff, moving an image over can be a little slow.
As far as the XML stuff. One thing I'd like. Some way to associate animation to a sound file. Like a timed animation event. That way I can put in actual lip syncing in the game. I can also sell the dialog better. When Hayes finds out you sold all his crew to slavery have him show some emotion instead of just standing there like a statue. Have Fwiffo shake in fear when he talks about the "ULTIMATE EVIL". Stuff like that. Some aliens like the Orz probably work better without the lip syncing. But for the humans, Syreen I just see lip syncing helpful. It's not so bad at low res but you really notice it at higher resolutions.
|
|
« Last Edit: November 09, 2011, 06:55:51 pm by dczanik »
|
Logged
|
|
|
|
dczanik
*Smell* controller
Offline
Posts: 306
|
In addition you can change the "Change X,Y for all frames", to "Change X,Y for selected frames". Or at least an option for that. With these changes, I don't think there would even be a need to use a text editor after that.
|
|
|
Logged
|
|
|
|
Quinarbre
Frungy champion
Offline
Posts: 60
|
Yeah, I know. It's not the most usable tool yet. UQMConversationTool v0.03 alpha released: -Conversation Simulator added. -Internal changes to Conversation nodes and options; these now use all the internal statement types. -Changes to the XML format. A lot cleaner now. -Allowing multiple alien phrase responses in the ConversationOption editor. -Bugfixes, small tweaks, ... - Note: help dialogs are NOT updated. Yeah, I am lazy. Production-ready-ability: average. Things should work nicely, but it's probably a bit clunky to use right now. Furthermore, there are a few features lacking, and a lot of the more core-game stuff (gamestates, if/then/else statements) aren't implemented and thus need to be done by hand using a CustomCode statement. Binary (Java/zlib): http://mooses.nl/uqm/tools/uqmconversation.zip Sources (zlib): http://mooses.nl/uqm/tools/uqmconversation_src.zipScreenshot of simulator: XML file for this conversation: http://mooses.nl/uqm/tools/conved_examples/picard.xmlTodo: a few things... -Rework 'Statement editor' GUI. It's ugly and uses interface elements wrong (tabbedpane where a radiobutton group should be used).. -Allow deletion of statements, conversation options, functions and conversation nodes. -Allow moving of statements. Move up/move down, that sort of thing. -Allow adding statements to conversation options (Conversation Option Editor dialog) -Add statements: Set Gamestate, IF (+ IF GAMESTATE), ELSE -other stuff.. Maybe we'll have some time to elaborate on this baby now... I've got to admit I've never tested it, simply because I had never coded a dialog before. After a quick test : - I have a .txt where the first line is a #(...), this identifier and the corresponding entry are ignored. Most probably because I've played too much with changing the ANSI/UTF-8/CR/LF encoding of this particular file, but I thought I'd let know anyway. - The "disable-afterwards" button should probably be checked by default - Are the "functions used in node XXX" really necessary ? It seems to me you could (and should) replace something like
static void main_node (RESPONSE_REF R) { //START BODY GENERATE if (PHRASE_ENABLED (did_we_speak)) { Response (did_we_speak, genF_523217fe_5a4e_4065_a938_6956cbfd275d); } //END BODY GENERATE } //Functions used in main_node static void genF_523217fe_5a4e_4065_a938_6956cbfd275d (RESPONSE_REF R) { //START BODY GENERATE DISABLE_PHRASE (did_we_speak); NPCPhrase (HOWDY); toto (R); //END BODY GENERATE } static void toto (RESPONSE_REF R) { //START BODY GENERATE //END BODY GENERATE } with something like
static void main_node (RESPONSE_REF R) { //START BODY GENERATE if (PHRASE_ENABLED (did_we_speak)) { Response (did_we_speak, toto); } //END BODY GENERATE } static void toto (RESPONSE_REF R) { //START BODY GENERATE if (PLAYER_SAID(did_we_speak)) { DISABLE_PHRASE (did_we_speak); NPCPhrase (HOWDY); } //END BODY GENERATE }
|
|
|
Logged
|
|
|
|
Megagun
Enlightened
Offline
Gender:
Posts: 580
Moo
|
dczanik: I'll probably get around to implementing those suggestions soon, now that the new demo has been released
Quinarbre: You're right, the way I'm generating code isn't the best way ever thought of. The main reason why I'm doing things that way, if I recall correctly, was that it made writing the soure-code outputting code easier. Essentially, I loop through every conversation node, and ask it for a source-code representation of the conversation node. There's no further clever logic behind it, which makes things easy to code and quite fail-safe, yet produce really crappy code.
As far as the conversation tools in general go: they're probably completely useless because of the crappy code they produce. Ideally, we'd have some file-based representation of a conversation that gets loaded and processed by the game, with some scripting (LUA? Python?) that's embedded in these files that is being executed and deals with advanced dialogue control ("if variable 1 is true and variable 2 is false, yet variable 3 is bigger than 200, enable this conversation option"). Unfortunately, that will take a lot of time, and will demand a certain quality standard of the tools which I'm not certain I can achieve. That is also mostly why I've given up on conversation tools: I just don't think I can make them work well enough in most situations for someone who's not very familiar with the game code, with a GUI that actually sort of makes sense.
|
|
|
Logged
|
|
|
|
dczanik
*Smell* controller
Offline
Posts: 306
|
Megagun: I'd like to offer you an additional challenge. As you can see from my post:
http://forum.uqm.stack.nl/index.php?topic=5152.0
I'd like the chance to have animation data outside the code. I bet you could help us with some of that. Something that artists (non-coders) can use to set up animations. Right now, once a comm animation is set up it becomes a delicate balance of working with a programmer to get it to look just right. Most of the time, we're setting for 'good enough' because it's just too much of a burden of time for both sides. Without some fundamental changes, I don't see how we can change this. I'm hoping somebody has the skills to help us out. You keep impressing me with your stuff, so I hope you can find a way to help us.
|
|
|
Logged
|
|
|
|
Megagun
Enlightened
Offline
Gender:
Posts: 580
Moo
|
dczanik: Yeah, that animation problem sounded like something that needed fixing to me, too. If you can come up with a somewhat detailed description of what you want to do, I might be able to help you. I'm not exactly familiar with what you and the programmers you work with usually talk about when trying to get an animation to look just right.
|
|
|
Logged
|
|
|
|
dczanik
*Smell* controller
Offline
Posts: 306
|
Well, my idea is to have everything inside an .XML file and your animation program reads the .XML file. The UQM reads the file too. So what we see in your tool is what we get. I've thought about how the animation file would work. I'm not too familiar with XML but I can take a stab at it.
There's a few types of animation, defined by <animationtype>. They are CIRCULAR, TALK, RANDOM, and YO_YO.
CIRCULAR: animation is in a loop. RANDOM: Random frames get used. TALK: Used as a default for talking. It's really just RANDOM, but only fires when the character is talking. This goes away if a timed animation is set. YO_YO: Animation goes through the loop, then comes back in reverse. Think the Cylon eye, or the Knight Rider light.
Additional options: Framerate: Frames per second (is this set by the game?) interval: For YO_YO and CIRCULAR: After the animation has played, the time you wait before it plays again. For example, blinking every 4 seconds. frametime: amount of time to hold that frame. Layer: Just like in Photoshop or traditional animation with plates. Different layers can be stacked to have animation behind animations. x_frame: X coordinates of the picture. y_frame: Y coordinates of the picture.
Take for example this test of Hayes muttering his lines: For example: Take Hayes muttering this line: http://www.youtube.com/watch?v=EqDVPHN3rJA
The COMMANDER.ANI would be:
<animation> <animationsubset> <name>BLINK</name> <animationtype>CIRCULAR_ANIM<animationtype> <animationlayer>1</animationlayer> <framerate>30</framerate> <interval>4000</interval> <frames> <animationframe> <framename>commander-001.png<framename> <x_frame>-65</x_frame> <y_frame>-17</y_frame> <frametime>3</frametime> </animationframe> <animationframe> <framename>commander-002.png<framename> <x_frame>-65</x_frame> <y_frame>-17</y_frame> <frametime>3</frametime> </animationframe> <animationframe> <framename>commander-003.png<framename> <x_frame>-65</x_frame> <y_frame>-17</y_frame> <frametime>3</frametime> </animationframe> </frames> </animationsubset>
<animationsubset> <name>MOUTH</name> <animationtype>TALK<animationtype> <animationlayer>1</animationlayer> <framerate>30</framerate> <frames> <animationframe> <framename>commander-004.png<framename> <x_frame>-60</x_frame> <y_frame>-19</y_frame> <frametime>2</frametime> </animationframe> <animationframe> <framename>commander-005.png<framename> <x_frame>-60</x_frame> <y_frame>-19</y_frame> <frametime>2</frametime> </animationframe> <animationframe> <framename>commander-006.png<framename> <x_frame>-60</x_frame> <y_frame>-19</y_frame> <frametime>2</frametime> </animationframe> <animationframe> <framename>commander-007.png<framename> <x_frame>-60</x_frame> <y_frame>-19</y_frame> <frametime>2</frametime> </animationframe> <animationframe> <framename>commander-008.png<framename> <x_frame>-60</x_frame> <y_frame>-19</y_frame> <frametime>2</frametime> </animationframe> <animationframe> <framename>commander-009.png<framename> <x_frame>-60</x_frame> <y_frame>-19</y_frame> <frametime>2</frametime> </animationframe> </frames> </animationsubset>
<animationsubset> <name>Light_BG</name> <animationtype>CIRCULAR_ANIM<animationtype> <framerate>30</framerate> <interval>0</interval> <animationlayer>1</animationlayer>
<frames> <animationframe> <framename>commander-010.png<framename> <x_frame>-722</x_frame> <y_frame>-392</y_frame> <frametime>1</frametime> </animationframe> <animationframe> <framename>commander-011.png<framename> <x_frame>-722</x_frame> <y_frame>-392</y_frame> <frametime>1</frametime> </animationframe> <animationframe> <framename>commander-012.png<framename> <x_frame>-722</x_frame> <y_frame>-392</y_frame> <frametime>1</frametime> </animationframe> <animationframe> <framename>commander-013.png<framename> <x_frame>-722</x_frame> <y_frame>-392</y_frame> <frametime>1</frametime> </animationframe> <animationframe> <framename>commander-014.png<framename> <x_frame>-722</x_frame> <y_frame>-392</y_frame> <frametime>1</frametime> </animationframe> <animationframe> <framename>commander-015.png<framename> <x_frame>-722</x_frame> <y_frame>-392</y_frame> <frametime>1</frametime> </animationframe> <animationframe> <framename>commander-016.png<framename> <x_frame>-722</x_frame> <y_frame>-392</y_frame> <frametime>1</frametime> </animationframe> <animationframe> <framename>commander-017.png<framename> <x_frame>-722</x_frame> <y_frame>-392</y_frame> <frametime>1</frametime> </animationframe> <animationframe> <framename>commander-018.png<framename> <x_frame>-722</x_frame> <y_frame>-392</y_frame> <frametime>1</frametime> </animationframe> <animationframe> <framename>commander-019.png<framename> <x_frame>-722</x_frame> <y_frame>-392</y_frame> <frametime>1</frametime> </animationframe> </animationsubset>
And for the voice data. The voice packs would override the TALK animation. Here we have the animation type: TIMED TIMESTAMP would be measured in something like milliseconds or something. The program would just hit the animation at certain time stamps. The command: TEXTFLIP would flip the text to the next screen. NAME is part of the text file that would show. file is the .OGG file.
<animation> <animationsubset> <name>BASE_ON_MOON</name> <file>coman027.ogg</file> <animationtype>TIMED<animationtype> <framerate>15</framerate> <layer>1</layer> <frames> <animationframe> <framename>commander-004.png<framename> <x_frame>-60</x_frame> <y_frame>-19</y_frame> </animationframe> <animationframe> <framename>commander-005.png<framename> <x_frame>-60</x_frame> <y_frame>-19</y_frame> <frametime>5</frametime> </animationframe> <animationframe> <framename>commander-006.png<framename> <x_frame>-60</x_frame> <y_frame>-19</y_frame> <frametime>5</frametime> </animationframe> </frames> <timedanimation> <timing> <timestamp>0</timestamp> <file>commander-004.png</file> <action>textflip</action> </timing> <timing> <timestamp>1000</timestamp> <file>commander-005.png</file> </timing> <timing> <timestamp>2300</timestamp> <file>commander-005.png</file> </timing> <timing> <timestamp>3300</timestamp> <file>commander-006.png</file> <action>textflip</action> </timing> <timedanimation> </animationsubset> </animation>
The code just goes through all the <timestamp> items. 1. At 0, it shows the first frame, and shows the text. 2. At 1000 ms it brings up the next file. 3. At 2300 ms it brings up the next file. 4. At 3300 ms it brings up the next file, and flips to the next text screen.
This is really top of my head stuff. I'm not sure how much more detailed you'd want it. Some stuff can be separated or combined. There's probably types of animation or stuff I haven't thought of just yet. There's definitely more data to the files, but the hopefully the artist won't ever have to open up the text file, your program would do it for them. I know UQM is messing with things like palettes and color tables. So that would have to be added in too.
|
|
|
Logged
|
|
|
|
Megagun
Enlightened
Offline
Gender:
Posts: 580
Moo
|
Outputting an XML like the one you described at the top should be fairly doable. I'll probably have to alter it a bit so that the references to frames don't copy any data like filename and offsets, as that would probably make coding it in the game a bit easier (load all frames specified in the global animation frame, then load all animation templates which references the global list of frames when needed)
Do you happen to know how the game displays different animation frames? I know that it hides/shows certain frames based on the animation, but do you know if the game does anything with the Z-Index of frames? Detail like that can be pretty important, as I will have to replicate it perfectly in my animation tool.
|
|
|
Logged
|
|
|
|
Elestan
*Smell* controller
Offline
Posts: 431
|
Before branching out on your own, I'd suggest reviewing any standards that already exist for doing this sort of thing, like http://www.w3.org/TR/SMIL, and the Timed Text specification I linked to above. There may already be libraries that you could leverage for using those, and at the least, it might turn up issues that could inform your own design. The whole software ecosystem is more efficient when we each build on each others' work when possible, instead of reinventing the wheel in every project.
|
|
|
Logged
|
|
|
|
dczanik
*Smell* controller
Offline
Posts: 306
|
Before branching out on your own, I'd suggest reviewing any standards that already exist for doing this sort of thing, like http://www.w3.org/TR/SMIL, and the Timed Text specification I linked to above. There may already be libraries that you could leverage for using those, and at the least, it might turn up issues that could inform your own design. The whole software ecosystem is more efficient when we each build on each others' work when possible, instead of reinventing the wheel in every project. Eeegads. The table of contents alone is 23 pages. I'll have to sit down and read that later. I agree. No need to re-invent the wheel. But could that also be overkill for what we're trying to do? Spline animation, SVGs, Linking?
Megagun: If you can implement it Megagun, and make it easier enough for the artists, then I don't mind at all. That could also make it easier for something like porting an HTML 5 version of the game. As far as I know, everything I covered in the above pseudo xml stuff would work for us. So I leave that stuff in your capable hands.
The game doesn't do anything with Z-index of frames. Every comm image is just wiped out by the previous image. A Z-Index would be really useful to the 6014 team. It's one of the problems I thought the engine would have when doing the animation for the Lurg. So some animation conflicts with other animation. The programmers have done an amazing job trying to hide that wherever possible. I imagined the background throbbing continuously like a heartbeat, but with the arms and tentacles moving that would have messed things up too much. So things are done in an order.
|
|
|
Logged
|
|
|
|
Megagun
Enlightened
Offline
Gender:
Posts: 580
Moo
|
Thanks for the links, Elestan, but it would seem to me that this is indeed a bit overkill. Currently, all animations are baked into the binaries, and we (presumably) want to get them out of there as soon as possible. I think that using our own format would be the best idea here, as we only have a limited set of features we can support. Although something as you suggested may be very useful, I fear that we'll have to pick-and-choose which features to support from that (based on engine limitations), which would mean that we're using only a subset of the entire standard, which I must say I'm not too fond of.
Also, we'll have to deeply integrate this technology within the UQM engine. This isn't like using something like XMPP to provide realtime communication where you essentially have to tell a library to connect to something and then handle the "receive message" events manually. This technology needs to be integrated into the sound system, the graphics system, and (I guess) the resource loading system. Seems like too much work for what we're trying to do.
|
|
|
Logged
|
|
|
|
|
Elestan
*Smell* controller
Offline
Posts: 431
|
Certainly, SMIL/TTML have way more than we need. But they can still be useful in two ways:
First, looking at how the existing standards have specified these features can help to inform the design. If there is particular terminology used in a problem domain, it will reduce confusion if we use the same terms for the same concepts instead of introducing new words (elements, attributes, etc) for the same thing. And if these specs actually are a superset of what's needed, it might be worth re-using the XML format by implementing just the subset that you need, rather than inventing a whole new set of tags. The more similar your approach is to existing standards, the less cognitive clash it will cause to those who know both.
Second, if SMIL is capable of doing what you need, it's worth stepping back and asking whether you could just pull in an existing open-source SMIL library like Ambulant, and save yourself a bunch of work. Learning to use someone else's tech may be less fun than developing the tech yourself, but it's usually more productive in the long run.
|
|
|
Logged
|
|
|
|
|