This is the Chernobyl todo list. These are features or fixes that need to be implemented in the future (probably post-Canisk). Bugs Their is a bug that causes problems for list views when they are refreshed twice in a row. Some Geometries don't check for null properly in their equality operator so they will cause a crash if this is done: if(null == circle) This needs to be fixed and tests need to be created for those geometries. This has already been fixed with tests created for Rectangle. Chernobyl.Mathematics.Movement.Layout doesn't offset children transforms, it only offsets shapes. INamed There needs to be an INamed which is static (i.e. cant be changed). Some of the types that implement INamed need to prevent the changing of that name (for example the IControl types). File/Directory We need a set of interfaces for going over directories and files without knowing where the files/directories are coming from (OS file system, http, ftp, zip, etc.) IReadyable Some instance that derive from IReadyable are allowing their properties, methods, etc. to be accessed when they are not ready (such as ITexture and its implementations). This should be remedied somehow in those classes. It would be nice if this were enforced at compile time. That may not be possible though, we'll have to think about it. One way it could be done is to have a Readyable type that does not give the client access to an instance of type T until that instance has become ready. This Readyable type could take in IReadyable instances and wait for them to be "readied" before providing the instance itself. This type could also derive from IReadyable. IValue IValue should be IReadyable. IValue/IDynamicValue should be used to replace anything that still uses parent level events for change notifications. IServices/ServiceAttribute There is a bug where IServices instances assume that the location of services are relative to them. For example, if you attempt to add an Cursor to an IServices two levels deep, then the IServices instance assumes the Cursor's service (injected or provided) are relative to itself when they are really relative to the IServices instance that it was originally injected into (which is at the application's root IServices). Additionally, this means that you can place the same instance as an IService in two different locations in an IServices hierarchy. This issue needs to be fixed. Should probably rename "InjectAttribute" and "ProvideAttribute" since the names don't describe what they do very well. Those names could be very confusing to new users of Chernobyl; even I get confused sometimes. We could possibly rename "InjectAttribute" to "RequestAttribute" and keep the "ProvideAttribute". That makes more sense. Needs to be able to handler service dependencies, i.e., a service should not get injected if that service hasn't had all of it's dependencies injected into it. It would also be nice if, in the event that a service implements IReadyable, that the service is not set until the service has become ready (i.e., IReadyable.BecameReady has been raised). Needs to be able to handle multithreaded situations, i.e., multiple classes are requesting services in multiple different threads. This may also require the classes that takes services to be able to handle services being set from another thread. Needs to be able to set services on methods with one or more parameters. Likely the methods would use their argument list to specify the services needed by the method. The method would not be called until all of the services specified in that method's argument list were fulfilled. This could be used in cases where multiple requested services are used together in some fashion and, if one service is not available, then there's no point in specifying the other services. It would be nice if there were a new ServiceAttribute derived type that could search the IServices instance for an IFactory that creates instances of the type specified by ServiceAttribute.Type, create an instance from the IFactory it found, and then set that created instance on the property/method/whatever as the service. This new type should also be able to tell if the created instance is ready to be set (i.e. all of its services have been resolved) and only set the newly created instance when it is ready. This attribute should also be able to set entire IEnumerables of created instances. For example, if we need 5 instances from a specific IFactory, then it should be able to deliver that. It would be nice to be able to request a set of services of the same type from an IService instances. For example, in Canisk we have a service type called an IPlayerServices. Each IPlayerServices instance represents a single player. In a game with multiple players, it is necessary to have multiple IPlayerServices but the IServices mechanism only allows one IService of any single type. We need a mechanism to allow the player to request all of the services available of a single type. Unfortunately, this also means that if you set a service, it does not replace the previous service with the new service but instead just adds the new service to a list. Being able to replace IServices was useful. Perhaps we could have the best of both worlds. Perhaps the mechanism that is used to retrieve a specific service is also used to overwrite a specific service. Perhaps, by default, when you set a service you are actually overwriting the original service. Only by specifying that you want to add to the services available will the service get added. IFactory The plug-in code (Chernobyl.Plugin) use their own factory type. Convert them so that they use the IFactory type(s). TransformFactory{T} has a property called "ModifyLocalMatrix" that determines whether the configured ITransform's LocalMatrix should be made equal to the TransformFactory{T}s WorldMatrix. This property should probably be modified so that it can take a function which modifies a passed in Matrix4 as is needed by the client. Then we could have predifined functions which serve common purposes. For example, we could have functions that only modify position, rotation, scale, etc. IBuffers, Mesh, and IndexBuffers Make three different types of buffers: IReadBuffer - can only be read from. IWriteBuffer - can only be written to. IReadWriteBuffer - can be written and read to. Derives from IReadBuffer and IWriteBuffer Then create a read, write, and read/write buffer for the mesh and index buffers. The mesh and index buffer factories are created using a factory that takes in a Type. This factory is put into the IServices instance. The mesh and index buffer factories should be the ones in the IServices instance but that requires that the IServices be able to locate generic services without a type's generic arguments. Add this feature to IServices and its implementations and then remove the MeshFactoryServiceCreator and IndexBufferFactoryServiceCreator methods. Consider changing the name of anything called a MeshElement to just 'Vertex'. Although, the name 'Vertex' is confusing because it can be used to describe the Vertex + attributes and also the position attribute of the vertex, it may be less confusing than creating a new name that the graphics/game world is not familiar with. Also, the position of the vertex should just be called 'Position' (rename it where applicable). ITexture Consider making the textures derive from the IBuffers and take in a generic parameter like the Mesh does. After doing this, allow the texture to take in data and hold onto it until it can be used. ICollidable ICollidable uses the names OnCollisionStarted and OnCollisionEnded. These need to be refactored to CollisionStarted and CollisionEnded to match the pattern set by Chernobyl. "On" is used with event handlers not events. QuadTree QuadTree needs to become it's own geometrical type which doesn't use Rectangle. For a QuadTree, using Rectangle duplicates too much data and operations. For example, a node in a quad tree could be represented as just a center and a width and height and collision could be optimized to take this into account. QuadTree should take in an Enumerable of volumes that represents the initial objects that are contained within it, the same way a collection takes in an Enumerable. If the user does not have this initial list of volumes, then they can specify an initial volume that defines the area which the quadtree might cover. The QuadTree should also expand or contract as volumes are added to it or removed from it. QuadTree should be able to transform using its ITransform interface. QuadTree should not sort it's collidables downwards until someone accesses that QuadTree for collision checking or containment checking. However, sorts should continue upward in the normal fashion or bugs will result. This is done for several reasons: - If the collidables moves it will need to be resorted anyway. Waiting until the last minute might save us a few re-sorts. - In a large scene, many portions of the QuadTree may not be accessed, it may come to be that the re-sort isn't even necessary. IDrawable IDrawable needs to derive from ITreeEnumerable. Need to finish the DrawOrderIndex work. Get rid of the PreDraw/PostDraw methods. The Draw method can already do the work of PreDraw/PostDraw by adding code before/after it invokes its Childrens draw methods (or base class Draw). Removing them would clean up the draw API. IKeyboard The [] bracket operator needs to define some standard inputs. In addition, the IKeyboard needs more properties for different keys on the keyboard. Find out which of the following keyboard shortcuts need to be implemented in Chernobyl: http://en.wikipedia.org/wiki/Table_of_keyboard_shortcuts Implement these and consider adding a Lokas Gate Law for certain shortcuts. Volume There are other types within Chernobyl deriving from Rectangle when they should probably be deriving from Volume. Found these types and analyze whether they need to be deriving from Rectangle (IEnumerableListView is probably one of them). We need some method of clamping volumes to and edge, transform, or some number. ITransform Get rid of the IsUpdateNeeded set call from ITransform and child classes. You shouldn't be able to specify whether the transform needs to be updated. That is the job of the transform itself. Allow parent/child relationships to be established by just setting the parent or adding the child to the childrens list. Right now it is done through MakeParentChild. Problems can arise if a user tries to set the parent and/or add the child to a ITransform's children list - this shouldn't be a problem. Consider breaking ITransform down into multiple interfaces. For example, break it down into ITransformTranslatable, ITransformRotatable, ITransformScalable. Maybe those interfaces could be broken down further. For example, ITransformTranslatable could be broken down into ITransformTranslatableX, ITransformTranslatableY, ITransformTranslatableZ. Doing this is important for things like Rectangle as Rectangle can only translate in X, Y, Z and scale in X and Y (it can't rotate). Cameras can only translate and rotate; they can't scale. They could also be broken down into readable/writable as well. Breaking the ITransform down could also lead to a replacement of IAxis and the like. The axis only translate in one or more particular axis. This could be accomplished using ITransformTranslation[X|Y|Z] (or whatever we end up calling it). No need to duplicate work. IAxis does have another benefit though: it can dictate the axis on which the translation lies (i.e. through the Axis enum). But maybe that can be performed by this new transform but with more type safety involved. Move some of the Translate, Rotate, etc., methods from the ITransform interface and its implementations into another class (maybe Transform) as extension methods. Remember to modify the tests to reflect the change. The TransformFactory.ChildrenFactories property is an ICollection when it should be an IList because the ordering of the IFactory instances is important. In order to make it an IList we will have to create an FactoryList type and use that instead of the FactoryCollection the property currently uses. CagedTransform2D CagedTransform2D.DefaultBorderDistance is using a value that we just pulled out of our ass. Need a better value, specifically, one that's the closest positive value to zero (though float.Epsilon doesn't seem to work). Need to finish creating the tests in CagedTransform2DTests. See the todo in that file. IShape Some of IShape's member's return values in specific units. These units should be strongly typed. For example, IShape.Perimeter, whose comment says it returns its value in metres, currently returns its value as a float when it should really return it as the type Metres. We could use some IComparer types that compare the Area, Perimeter, and Volume of IShapes. These could be used to sort IShapes in a collection by these properties. They would need to be generic with an IShape constraint so that they could work with all IShape types. They could be placed inside the Shape class. RemoveScaleTransform The KeepScaleAffectedPosition doesn't work; I believe there is a bug in the calculation. Even if it did 'work' there is still another problem: it is dependent on when the scale is applied. If the scale is applied after the position is set then it will work because the scale is being applied to the position. However, if the scale is applied first and the position second then the position isn't affected by the scale. If the scales effect (or lack thereof) is removed from the position in the latter case then we obviously get an incorrect result. Too fix this we need to either remove the method or make a note of the issue in the comments. IAxis Consider giving the IAxis a min and max property. By default the min/max would be float.Min and float.Max. Additionally, consider creating a CurrentNormalizedValue() extension method that uses the min/max to return the current value of the IAxis in a 0 to 1 form (consider a PreviousNormalizedValue() as well). Axis2DTransform Axis2DTransform is using IService.GetService(). It should be modified to use IService.Inject(). We should consider removing Axis2DTransform and just making the IAxis code implement ITransform. The reason we didn't do this before is because the IAxis code doesn't dictate that axis on which the transformations take place. What we could do is make it implement ITransform and allow the user to dictate the ITransform axis the transformations take place on using the axis' constructor. Note that this may become a moot point, see the todo under ITransform regarding breaking the ITransform interface down. IButton Rename "OnDown", "OnUp", "OnChange", etc. to proper event names (i.e., not using the word "on" which is generally used by the event handlers). Something like "PressedDown", "LetUp", "Changed", etc. IMouse IMouse should derive from ITransform (and possibly the IAxis3D). The IMouse.Position property should be gotten rid of since it will no longer be useful after this change occurs. After this is done, we should look into whether ICursor and Cursor are needed. IMouse, at that point, would probably have an interface similar to that of ICursor. Additionally, the work Cursor is doing could be accomplished simply by attaching a Sprite to an IMouse. ICursor Get rid of FirstButton, SecondButton, and ThirdButton. This functionality (but in a more ACTION based form) needs to be given to an interface similar to what was done for Canisk. The interface might be called "IMenuControl" and would provide control functionality for menus. The implementations of the interface would be for different control mechanisms (one for mouse/keyboard, cursor, etc.). Additionally an IEventCollection of these controls will need to be provided as part of Chernobyl.Interface similar to what was done for gamepads. ICursor is no longer provided as a service by Chernobyl.Interface. Client code will have to create it themselves. We will need to update the rest of Chernobyl so that it no longer attempts to access the ICursor service. Removed Chernobyl Functionality The following files were removed from Chernobyl because they were not needed at the time and there were not enough resources to maintain them. The should be re-added when they are needed: - Chernobyl\1\Chernobyl.Input\Movement\ - FirstPersonShooterTransform.cs - Chernobyl\1\Chernobyl.Interface\ - SpinBox.cs - Selectable.cs - TransformEditor.cs - EnumerableListView.cs XnaGamepad, IAxis2D, and ISlider XnaGamepad is currently retrieving the state of the gamepad using "GamePadDeadZone.Circular". It would be better to calculate our own deadzone so that we could use it in other cases (Linux, Mac, DirectX, etc.). Note that deadzone processing must be done off of the IAxis.ChangeAmount since the position can't be used to handle deadzone (as it is not a velocity where ChangeAmount can be considered a velocity). VelocityTransform Consider giving this class the members IsEnabled, Enable(object, EventArgs), Disable(object, EventArgs) instead of the members it currently uses for the same purpose (Start, Stop, etc.). This will make it match LookAtTransform and make things more uniform across Chernobyl. Review Chernobyl's Security Some things in Chernobyl require high security permissions (such as the WeakReference class caused by deriving from WeakReference) We need to review these things and lower the security permissions where we can. We also need to ensure our code is using the security infrastructure correctly. One security flaw is in the CodeDOMContentResourceProcessor::CompileScriptsAndCreateComponent. This file loads a script into the main assembly without first checking for security vulnerabilities. Review Fall File Processing It is a mess and needs to be redesigned. Type parsing needs to be able to handle arrays and generics with empty generic parameter list (for example, "List<>") Need to be able to xlink:href to an instance defined in the same file as the linking instances. Need to be able to xlink:href to a property, method, etc., that is two or more "levels down". For example: xlink:href="scene.fall#scene/Value/Draw2D. Need to be able to use "typeof". Need to be able to access methods and generic methods. (with and without arguments) You cannot reference instances within the same fall file. This is because the fall file processing needs to know the type of the instance but that can't be known until the fall file has been compiled which can't be done until it has been processed and on and on. Fall file processing should be no different than binary file processing (in that the use a lot of the same code). Additionally, this binary file processing should be used when we create remote instances from the network. Additionally, the file processing mechanism should allow for any type of file (like binary, XML, ini, etc.) It would be cool if the file processing mechanism somehow implemented the IServices mechanism. Both mechanisms do about the same thing: retrieve an instance of some type, for some purpose, and from some unknown location. It would be nice to be able to request a service and not know whether that service was coming from an XML file, from binary data from some other computer, from a local instance created by the local application, etc. IUpdateable Get rid of this interface and replace updating with thread pooling or threads. We'll have to do some research to know when to use thread pools and when to use threads. Decorators We are using several different methods for the "decoration" pattern (see DrawableDecorator, ComponentDecorator, etc.). We need to bring this down to using only one method for all decorators. We'll have to do some research and design to figure out the best method. System.Test MathematicalOperatorTests needs to implement tests for the increment(++x), decrement(--x), and unary plus (+x) operators. Measurement Types (Metres, Seconds, Radians, etc.) Need to implement increment and decrement operators. Need to figure out a better way to convert Metres types. Right now there is a method called Conversions.ToMetersPerMillisecond() which needs to be removed when we've thought of a better way. That function is difficult to call and I would prefer to see conversions be implicit. Velocity doesn't offer an easy way to convert to other forms of velocity, like meters per millisecond. This needs to be fixed. Then the VelocityTransform needs to use this method in it's Transform.Update() method where it is using another method of conversion. Children and parent properties For types that have one or more children and/or parents (like ITransform and IDrawable) we should change the child/parent property from {Typename}{Children|Parent} to {Children|Parent}{Typename}. For example, ITransform.TransformChildren should become ITransform.ChildrenTransform. This was already done with Chernobyl.StateMachine.IState. The reason it should be done is because (1) it sounds more natural and (2) its quicker for autocomplete to locate the property you want (for example, TransformChildren and TransformParent both start with Transform so you have to type more for it to know which one you are referring to). Any type that implements Parent/Child relationships needs to use the new code provided by TreeExtensions. By doing this we'll have most of the logic for parent/child work in one place. Chernobyl.DesignPatterns namespace This namespace should be gotten rid of. All code below it should be placed into another namespace. The reason for this is because having a "DesignPatterns" namespace doesn't make sense when Chernobyl should be using design patterns in all of the namespaces. This has already been done to IState which now resides in Chernobyl.StateMachine when it used to reside in Chernobyl.DesignPatterns.StateMachine.