Jump to content
XCOMUFO & Xenocide

Recruits Post Patches Here


dteviot

Recommended Posts

Alright here is the baselisting and example screens and dialogs that reist wanted. (PurchaseScreen and Launch Interception dialog)

 

Note: I kept the interceptscreen.py, probably should really go into the dialogs folder, and should probably have its own layout (currently uses transactions layout).

 

Any questions or comments PM me or talk to me in IRC like usual.

baselisting.zip

Edited by Pi Masta
Link to comment
Share on other sites

Got another little tweak here.

 

I was originally going to add code to display info when you click on an icon on the geoscape, but since model is going to be moving to C++ sometime I instead added some select target code.

 

In this patch I mainly made modifications to the selecttarget.py.

 

I'll give a brief overview of what I did in each file:

  • selecttarget.py - removed the test code and added a boolean that can be passed. If true will look for objects near the position clicked, otherwise will just get a coordinate.
  • geoscape.py - mainly changed how the UFOs are spawned slightly. Allowed up to 3 UFOs to be on the map, and prevented spawning of UFOs if the game is paused. The onIntercept function is obsolete as my interceptdialog handles it
  • interceptdialog.py - added selecting target after selecting craft, if a craft and target are selected the craft will launch and intercept the target (previously would just send first craft after the first UFO), if you cancel on either of these it will resume the game as normal
  • scheduler.py - added a check in the main loop so that UFOs and other craft won't tick when the game is paused
  • world.py - fixed a small typo in an exception print statement, and added a function to return all objects within a specified radius of a position. This is called by the SelectTarget method when looking for objects. This should also come in handy when we display info on a clicked target.
  • ufocraft.py - modified it to continuously go to random points and at random speeds (this is mainly so it is more likely a UFO will get close to some other object)
  • messagebox_general.layout - actually unrelated to the rest of this patch, just noticed one of the buttons had 'Cancel' for its text, changed it to 'STR_CANCEL'
  • selecttarget.layout - increased the height of the box that shows what is selected so it is more readable

There's still some issues to iron out with it, but it does kinda make the game playable. You can send your 2 interceptors to 2 different targets, and sometimes the UFOs are faster than the interceptors so they chase for a bit before being destroyed.

 

TODO:

Currently there is no validation of the target that is selected, so you can send the intercepters to attack your base or another interceptor. (Which will destroy them!)

 

The SelectTarget method does recognize when multiple objects are in close proximity, but currently just prints a message to the console 'several objects close' and grabs the first one from the list of close objects. When we get a selectFromMultipleTargets dialog we can use that to resolve the issue.

 

Enjoy!

selecttarget.zip

Link to comment
Share on other sites

  • 3 weeks later...

Alright this has to be the biggest change I've ever done.

 

I'll breifly go over what I did with each file:

  • startup.py - updated call to UIManager (more on that later)
  • baseui.py - The very heart and core of this patch, EVERY screen/dialog/window uses this (except console)
  • (deleted) dialogbase.py - obsoleted by baseui, copied the susbscribeEvents directly from it
  • dialogs/options.py - updated to the new framework and hooked up the load and save dialogs
  • dialogs/savegamedialog.py - updated to the new framework and added a couple of classes to ease use
  • (deleted) earthscenedialog.py - looked like a good place to make an abstract class for anything that needs to click the globe, but I believe only selecttarget does this, so I just moved it in there
  • earthui.py - updated to the new framework, though one quirk about the 'tickers' (see below)
  • interceptdialog.py - updated to the new framework using ModalDialog
  • messagebox.py - completely revamped to use the new framework. MessageBoxes can now be executed on 1 line (save for importing)
  • (deleted) modaldialog.py - obsoleted by baseui.py, as it defines a ModalDialog class itself
  • purchaseui.py - updated to the current framework
  • selecttarget.py - updated to the new framework. however not currently hooked up, and will crash when you click on a point on the globe, but this is for another patch
  • uimanager.py - changed to work in tandem with the ScreenManager C++ class, also holds the mapping of what C++ Screen a Python Script UI needs
  • util.py - renamed setRootScreen to setRootWindow
  • xnetui.py - updated to the current framework (one issue I must have forgotten some initilization code, but the last object you viewed will be shown when you go back into xnet, easy fix for this though)
  • layouts/ *.layout - I didn't change all the layout files but the ones I did either had incorrect window names and/or event bindings in them (more on this later)

Alrighty, before I delve into the changes in the existing files, let me explain what I've added and how to use them. The rest of the changes were done to take advantage of them.

 

baseui.py

The core library for hopefully any python UI scripts we do. I believe I documented every class and function in the python script file but I'll delve further here and even provide some examples

 

subscribeEvents - I wish I could take credit for this handy thing, but I copy pasted it from the dialogbase.py

 

BaseUI - Here is where the 'magic' happens. This is even the base for the dialog classes detailed below. Basically all UI's inheirit from this class and will pass information relavent to the particular instance, for example XnetUI does a

super(XnetUI, self).__init__('XNet', 'xnet', controller)

(read the script for more details)

 

Since every screen and dialog eventually inheirits from this class we can guarantee 3 methods will exist on any UI.

 

show

This will actually load the window into self.mainWindow (this was originally done in Init, but I'll explain why it was moved), activates the screen's controller, and sets it up as the rootWindow (formerly rootScreen). Then it will call self.onShow if available. This is for child classes to set up the window, that is subscribe events and load data. After that returns the BaseUI will call UISystem.resolveStrings to convert all the strings, thus you can dynamically change a window's contents in onShow and the correct strings will be shown.

 

hide

This was formerally called destroy, and is actually a bit more descriptive of what it does. It will destroy the window (thus removing it from sight) and then call onHide for child classes to react to the event similarly to the onShow method

 

onDel

This only exists because of the tickers for EarthUI (I'll talk more about this later). Basically it will be called before the class is suppose to be deleted so that you can remove any external references, it will also be called AFTER hide so CEGUI references won't exist.

 

EarthUI, XnetUI, and PurchaceUI are good examples of how to use this class. Override __init__ and call the parent with the and (without 'layouts/' or the '.layout') and then set up anything else that needs to be initialized. It is optional to define onShow, but it is the only place you should subscribe events. It will be called everytime your screen shows up, first time or coming back to it. I believe PurchaceUI doesn't use anything other than onShow, just defines methods for it's use and for CEGUI to bind with.

 

BaseDialog

This is for a dialog that does NOT prevent interaction with elements below. It also defines a stackless channel for you (self.channel). Send on this channel to close the dialog. It does NOT pause the game either.

 

show

Dialog's show method is a little different because it creates a tasklet and recieves on the channel waiting. When you show a dialog you have a couple of options how to use it. Let me give some examples.

(1)
Dialog.show()

(2)
Dialog.show(callback=myFunc)

(3)
s = Dialog.show(halt=True)

 

The first line is a very basic use. It will create the dialog and a tasklet for it to wait on the channel, however it will return as soon as the dialog is SHOWN. However there is no way of getting any information back from the dialog (though the dialog itself could do something). This is good for things like messageboxes that just require the user to acknowledge.

 

The second line registers a callback. It will return as soon as the dialog is shown like before but when the dialog is closed myFunc will be called with the response (what was sent on the channel) therefore myFunc should take another argument.

 

The third line is for a possible convience use. As you can guess it will halt execution until the dialog is closed, at which point the response will be returned. Only if halt is true will the function return anything (well it could still return none, if that is what the response was).

 

Dialogs (both normal and modal) can define an onResponse(self, response) method. It will be called before the dialog is closed, any other sources get a response and before onHide. It will recieve the same response variable to allow the dialog to centralize any processing it might need to do.

 

ModalDialog

This does not allow the user to click on any other windows and will pause and resume the game for you. It is otherwise functionally equivalent to the base dialog

 

messagebox.py

As I said I revamped the classes in here. There are 3 classes you can use MessageBox (just an OK), YesNoDialog and OkCancelDialog (self expanatory). You must pass in a string to use as the text during the constructor. You then simply its show method (registering call backs if you wish). Also defined is an enum: MessageResponse with attributes: Affirmative, Negative, and Cancel which will be its response. (Closing a window will produce the same result as hitting No or Cancel for YesNoDialog and OkCancelDialog, and Affirmative for MessageBox).

 

YesNoDialog('STR_ABANDON_GAME').show(callback=self.handleQuit)

This was taken from options.py, and shows how a simple dialog can be constructed and shown in one line. In this case self.handleQuit will be called when the decision is made.

 

Other Issues

Ok, I'm getting tired of this long post so I'll wrap things up:

 

EarthUI - I mentioned to reist about using weak references for the tickers so that we don't have to worry about having that 'onDel' method and making sure that we call it before we delete a screen. Reist mentioned possible perfomance issues which I haven't looked into yet. Another option is to append the tickers in onShow and remove them in onHide, and require any screen that has external references to do similar.

 

UIManager - this will hide all screens, including EarthUI (I believe however it leads to some lengthy loading times when going back to the EarthUI), effectively destroying the windows. Of course it will still show the current screen. Also I removed the ScrId Enum and replaced it with a mapping. So now calls to pushUI must pass a string as a key to that dictionary. Shorter too, look at: ui.uimanager.ScrId.xnet vs 'xnet'

 

My python UI Script Paradigm

With this, I am hoping to make future UI development a lot faster as UI scripts will handle just that, UI. No more fooling with loading and destroying windows (done by BaseUI and UIManager), messing with tasklets and dialogs, or resolving strings (well sorta). They will simply specify the layout file, hook events ups, and do any logic/processing necessary by the UI system.

 

Following this are the reasons for the changes in the .layout files. Some of the files did not follow the convention of 'Parent/Child/ChildChild' naming. Thus causing some difficulties in using the subscribeEvents function.

 

The other issue is the .layout files were binding events. Personally I don't like this, mainly because I'd like to keep calls to python in python as much as possible. I'd like to see where and why a python call is made by tracking the python code. The layout files will cause functions to be 'magically' called with no other python interaction involved. I think it's better in the long run incase a function is renamed or a file moved we don't have to go to a layout file to fix it. Just my :mytwocents:

ui_overhaul.zip

Link to comment
Share on other sites

  • 8 months later...
Changed Xnet listbox sizes to fit with current background...

 

boxes seem to small, shouldn't have to scroll horz Might have to edit the background..

Don't worry, I'll take care of it tomorrow night. er, tonight. It's past midnight. I need to get some sleep.

Link to comment
Share on other sites

Sound script fully working, plus plays on xnet planetview and screenselect.

 

Wave files I created will have to be downloaded seperately, but would be nice if you put in the svn

 

files should be

/Content/Audio/XenoAudio.xap

/Content/Audio/Music/main_theme.wav

/Content/Audio/Music/planetview.wav

/Content/Audio/Music/xnet.wav

 

/Content/Audio/Effects/Menu/buttonclick1_ok.wav

/Content/Audio/Effects/Menu/buttonclick2_changesetting.wav

/Content/Audio/Effects/Menu/buttonover.wav

/Content/Audio/Effects/PlanetView/ (Will add later)

 

This uses XACT

Patch attached

 

Waves zipped and rapidshared. Extract to Content directory

(90 Meg)

 

edit here it is http://rapidshare.com/files/52613247/Audio.zip.html

Sound.zip

Edited by Darkhomb
Link to comment
Share on other sites

I didn't feel like messing with compression it was 4 in the morning, but it brought it down from 90 meg to a usable 25 But to compile you still need the uncompressed wave's once compiled it will create a xwb file containing all audio...

 

For those who want to try it, I compiled it with Audio and my ghetto wigget set that looks lil better then standard.

 

http://rapidshare.com/files/52711795/XenoAudio.zip.html

Edited by Darkhomb
Link to comment
Share on other sites

I just found out FMOD which we were using for C++ also supports C# if this is true then we have ogg support. I am looking into this right now.
http://www.chromecode.com/articles/fmodcsharp/ :)

 

Btw, a free for non-commercial use audio engine can be found here http://www.ambiera.com/irrklang/ , and seems surprisingly easy to code :S

Link to comment
Share on other sites

FMOD up and running, patch attached, (Much nicer to work with, plus 8 meg for ogg's vs 90 for wave...)

Dll has to be added to main directory..

 

ogg files via rapidshare...

http://rapidshare.com/files/52822046/Music.zip.html

 

Compiled version added via rapidshare as well (13 Meg)

http://rapidshare.com/files/52824395/XenoFMOD.zip.html

FMOD.zip

fmodex.dll

Edited by Darkhomb
Link to comment
Share on other sites

Very nice. :)

 

I assume we can just copy the OGGs off the C++ branch?

 

Yes just put them in /contents/audio/music

Nice job Darkhomb, I'm really impressed. (Both with the FMOD and the GUI.)

I'm going to take a close look at your code and if it checks out, merge your patch into the C# trunk later this week.

I'm probably going to make a couple of minor changes. Specifically,

1. Make sure it works when there are no sound files.

2. And I might also look at wrapping FMOD as a GameService/GameComponent.

 

There are two reasons for getting it to work with no sound files.

1. When you are constantly starting and stopping the code in a debugger, the sound starts looping on 3 or 4 second intervals. It gets on the nerves very quickly, so I normally don't have sound.

2. The sound files change slowly. So, to minimise the download size, we can package the sound as a separate, optional download. That people only need to download once.

Link to comment
Share on other sites

Very nice. :)

 

I assume we can just copy the OGGs off the C++ branch?

 

Yes just put them in /contents/audio/music

Nice job Darkhomb, I'm really impressed. (Both with the FMOD and the GUI.)

I'm going to take a close look at your code and if it checks out, merge your patch into the C# trunk later this week.

I'm probably going to make a couple of minor changes. Specifically,

1. Make sure it works when there are no sound files.

2. And I might also look at wrapping FMOD as a GameService/GameComponent.

 

There are two reasons for getting it to work with no sound files.

1. When you are constantly starting and stopping the code in a debugger, the sound starts looping on 3 or 4 second intervals. It gets on the nerves very quickly, so I normally don't have sound.

2. The sound files change slowly. So, to minimise the download size, we can package the sound as a separate, optional download. That people only need to download once.

 

Thats fine, I would like it to play without sound too because it errors out with out sound if i rename or move the files.

 

If you are going to change my code let me submit a new patch because I now have gotten it to randomly select a tracks for planetview and any other screen that has multiple music files and play one of them

 

Since I am not really a programmer I am sure you will change what I have to be more profressional in the code

 

 

 

Edit - actually I don't need to make a new patch I will paste the code here..

 

in the AudioEngine Class I added

 

private static string musicScreen = "blank";

 

then below I added

 

        /// <summary>
       /// Checks if Planetview music if playing then randomly generates a track to play.
       /// </summary>
       public static void PlanetMusic()
   {   
           if (musicScreen == "PlanetMusic")
               return;
      int track = (Xenocide.Rng.Next(3));
           if (track == 0)
               AudioEngine.PlayMusic(@"Content\Audio\Music\PlanetView\planetview.ogg");
           else if (track == 1)
               AudioEngine.PlayMusic(@"Content\Audio\Music\PlanetView\Tiskaite_-_Xenocide_Geoscape.mp3");
           else if (track == 2)
               AudioEngine.PlayMusic(@"Content\Audio\Music\PlanetView\10. Thomas Torfs - Planetview.ogg");

           musicScreen = "PlanetMusic";
   }

 

 

For Geoscape screen We no longer have to call the audio we just call

 

AudioEngine.PlanetMusic();

 

I actually have one for each screen (Xnet, BaseView, Battleview, etc) but depending how you change that I will change the rest.

Edited by Darkhomb
Link to comment
Share on other sites

I just found out FMOD which we were using for C++ also supports C# if this is true then we have ogg support. I am looking into this right now.
http://www.chromecode.com/articles/fmodcsharp/ :)

Just to give everyone a laugh, the 2nd line of the article:

Copyright ? 2006 Martin Nordholts. All rights reserved. Published 2006-05-01.
Link to comment
Share on other sites

Ok,

 

Added subdirectories instead of having all music in one folder.

 

 

Patch randomly selects a song and plays it when you enter planetview.

Right now only have 3 songs for planetview.

 

Added baseview music.

 

If you want music, download the audio from sound SVN with these names and directories.

 

Content/Audio/Music/BaseView/XerO - Baseview.mp3

Content/Audio/Music/PlanetView/10. Thomas Torfs - Planetview.ogg

Content/Audio/Music/PlanetView/planetview.ogg

Content/Audio/Music/PlanetView/Tiskaite_-_Xenocide_Geoscape.ogg

Content/Audio/Music/XNet/xnet.ogg

Content/Audio/Music/main_theme.ogg

-

 

 

 

Known issue, because using multiple files for a scene, if you go into another scene that doesn't switch music IE statistics and the random code selects a different file then playing will change to that file... I am working on that

 

edit - remove patch

Edited by Darkhomb
Link to comment
Share on other sites

1st fix, crash when there is no sound playing and you switch to another working song. (it trys to stop what isn't playing)

 

2nd fix. nulls out filename if no song otherwise will not play song you go into if just played. IE exit Xnet, go back in.

 

3nd fix. Stops crashing if you close Xenocide in a screen with no sound (tries stoping again)

 

 

edit - remove patch

Edited by Darkhomb
Link to comment
Share on other sites

taz0k has created a patch to reset the camera for every xnet entry.

I can't accept taz0k's patch. It has two bugs.

1. PolarScene tracks the camera's position in polar co-ordinates, not cartesian.

2. Polarscene doesn't record the default camera distance.

 

That said, I've implemented "reset the camera for each entry" functionality. (I was in the area anyway.)

 

Darkhomb,

I can't accept your patch either.

1. While it does fix the some missing files problem, I discovered a much more serious bug, and the fix for that also solves the missing files problem.

2. I've implemented random play in a way that I think is better. You just give it a directory, and it picks a song at random from the directory.

Link to comment
Share on other sites

Alright, Try 2...

 

Menu sounds for 80 percent of buttons/clicks etc.

 

Want to see if you like how I am doing this before I continue..

 

Crashes if files are not present.. maybe we should do the same for this as music?

 

Need to have following sound files.. I believe these are included in the soundpack from kafros

 

/Content/Sound/Menu/buttonclick1_ok.ogg

/Content/Sound/Menu/buttonclick2_changesetting.ogg

/Content/Sound/Menu/buttonover.ogg

/Content/Sound/Menu/exitgame.ogg

 

/Content/Sound/PlanetView/clickobjectonplanet.ogg

/Content/Sound/PlanetView/speedfast.ogg

/Content/Sound/PlanetView/speedslow.ogg

/Content/Sound/PlanetView/speedveryslow.ogg

/Content/Sound/PlanetView/zoomin.ogg

/Content/Sound/PlanetView/zoomout.ogg

MenuSound.zip

Edited by Darkhomb
Link to comment
Share on other sites

This one line patch slows down zooming when the camera height is lower.

In PolarScene.ZoomCamera:

 

- cameraPosition.Z += distance;

+ cameraPosition.Z += distance * (CameraHeight + 0.01f);

 

I am working a little on changing the camera for the XNetScene so that one can rotate 360degs in all directions and with some improved controls. Expect that patch to come up at some time in the future.

ptch.zip

Link to comment
Share on other sites

I just noted some strange CeGui behavior.

Apparently a MouseMove can be triggered not only by mouse movement but also by clicking the mouse (without any movement at all).

 

So I made a patch that adds a short if statement that immediatly returns "if e.MoveDelta.IsEmpty == true" in our onmousemoveInScene functions, to make sure a movement really occured.

 

I case anyone would find that silly for whatever reason, I will justify the patch with a short story :P

 

For some reason I wanted to make out the direction of a mouse movement as a normalized vector.

So I did a

Vector2 direction = new Vector2(e.MoveDelta.X, e.MoveDelta.Y);

 

A mouse click trigger the function, altough no problems yet as "direction" is {0.0f, 0.0f}, BUT when we try to normalize "direction"

direction.Normalize();

 

Now all of a sudden we have a huge problem as "direction" turns out to be {NaN, NaN} as it doesn't make any sense normalizing the zero vector.

Not a fun vector to work with at all to say the least.

MouseMove.zip

Edited by taz0k
Link to comment
Share on other sites

This is the improved MouseMove patch.

 

Before the patch the InjectMousePosition(int x, int y) and InjectMouseMove(int deltaX, int deltaY) just called MouseMove without even checking if x and y even "suggested" a real "movement".

 

The patch adds an if statement in the beginning of InjectMousePosition and InjectMouseMove that returns true immediatly if there is no movement suggested.

 

 

I verified that this solves the problem with MouseMove:s that aren't mouse moves by adding a delegate like this to PolarScreen:

scenewindow.MouseMove += new CeGui.MouseEventHandler(
               delegate(object sender, CeGui.MouseEventArgs e)
               {
                   if (e.MoveDelta.IsEmpty || (e.MoveDelta.X == 0 && e.MoveDelta.Y == 0))
                   {
                       throw new Exception(String.Format("sender:{0}", sender.ToString()));
                   }
               });

 

The exception inside the delegate is thrown immediatly if one is not using my patch. However after the patch I was not able to get the exception the throw so the problem is solved.

cegui.zip

Edited by taz0k
Link to comment
Share on other sites

Nice job, the Xenocide XNA is really coming close to Xenocide C++ now. :) (look-wise)

 

Some things that's been bugging me though:

- The default ButtonPressed image is still used, that should probably be replaced with a Xeno one, even if you reuse some other image.

- Button text vanishes on hover. Is this a CeGUI issue, Xenocide issue, or just my issue?

- Some of the original Taharez graphics seem to have been broken. Some cursors seem corrupted, there's no Selection graphic for listboxes or editboxes anymore, and selected text disappears on the latter.

Edited by SupSuper
Link to comment
Share on other sites

- Button text vanishes on hover. Is this a CeGUI issue, Xenocide issue, or just my issue?

- Some of the original Taharez graphics seem to have been broken. Some cursors seem corrupted, there's no Selection graphic for listboxes or editboxes anymore, and selected text disappears on the latter.

 

I was seeing the same issues, so it's not just you.

Link to comment
Share on other sites

Can fix hover text, but it will only be white can't change colors.

I'll try and get a pushed graphic up

which cursors? they seem to all work for me.

 

don't know about selection, i don't remember ever having it. I'll look at it

 

 

edit here pushed is fixed. replaces these in your resources folder.

Edited by Darkhomb
Link to comment
Share on other sites

Looks great. :) And hover text can stay white, no problem.

As for selections, try clicking on something in a list or selecting text in an editbox. You'll notice it's no longer highlighted. That's what I'm talking about.

 

As for the corrupted graphics, I compared the original TaharezLook.tga and XenoLook.png and apparently some transparency effects on the Taharez graphics were lost during the TGA > PNG conversion, so I knocked up a fixed version for you. You probably won't notice the difference, but I'm just picky like that.

 

Edit: Speaking of picky, your Zoom In/Out buttons need to be nudged a bit to the right :P

XenoNew.png

Edited by SupSuper
Link to comment
Share on other sites

I've noticed, thanks for finding that.. I'll look into the selecting text

 

Edit - not worried bout the buttons yet, I was just working on getting the images to work, I'll tweak though later. We might be getting the layouts to work so that will be great

 

edit 2 the reason for no selection is because it is actually black highlight, so I'll try and change the background.

Edited by Darkhomb
Link to comment
Share on other sites

Uhhh, there's a random brush spot on top of one of the Xeno scroll arrows.

 

I think one of our programmers hacked CEGUI C++ so you could have normal/hover/pressed images on a per-button basis. Maybe it's worth implementing on CEGUI C#?

Edited by SupSuper
Link to comment
Share on other sites

I think one of our programmers hacked CEGUI C++ so you could have normal/hover/pressed images on a per-button basis. Maybe it's worth implementing on CEGUI C#?

 

This is on my list for looking at next. I don't think it will be too difficult.

 

I was able to get layouts working tonight and was able to replicate the Research Dialog box using a layout. Some things have to stay in code since they are dynamic but the button layouts and such can be defined outside of code. I'm not to the point of putting up a patch yet but I've attached my sample layout file so you can take a look.

 

The long term goal is to see if we can get the falagard capabilities working in CEGUI#.

Layout.zip

Link to comment
Share on other sites

×
×
  • Create New...