Layered architecture by Zenject's DiContainers with flat GameObjectContext hierarchy - zenject

Previous question: link
In my application I have three layers:
Data (Entities and Data Access Objects)
Model (Managers)
Presentation (Views)
How can I setup Game Object Context that Model layer will include all Data layer dependencies and Presentation layer will include all Model&Data layers dependencies?
Is there any way to set parent component for Game Object Context?

You can add a GameObjectContext by right clicking in the Scene Hierarchy and selecting Zenject -> GameObjectContext. You can add one for data, model, and presentation. Then you just have to set the transform parents up the same way you want the container parents to be. From your description I think you probably want it like this:
Then you can add each installer by attaching a MonoInstaller to each context. You an also do all this dynamically using a FromSubContainerResolve inside a SceneContext installer as well, if you prefer.

Related

Do I need to redesign my application?

I may be bordering on a discussion type question here so I apologise if the question is not specific enough.
I would like to know if I my current application design is inherently weak/flawed. My background is C so I am not using clever c++ patterns to their fullest extent, of this I am sure.
My application is similar to a 3D modelling package, without geometry creation (e.g setting up animations using existing models). The user imports a geometry and can set various parameters on pre existing geometry, and there are time dependent values that relate to the whole system. The output is a text file to be processed by another application.
I am using a QTreeview to render a QStandardItemModel. I simply store pointers to my core classes in the model's items. These have specific UI for each class type, and are all descended from a common base class. They all have a QWidget which is their "mainwidget"
When the user clicks on part of the treeview, the stored class is retrieved and its mainwidget is displayed on a pane on the UI. So - treeview on the left, pane to the right with the current item's contents, and a 3D view showing the geometry.
Most of my data is stored in the classes UI elements themselves; I don't have a central database which stores anything, and when it's time to save the project, I traverse the tree and let every item write itself to a QSettings file. This feels quite naive but it does work, and the reverse happens on project load. The project class generates new classes based on the type information in the settings file and they then read the contents out of the file themselves.
Similarly when writing the output file, each item knows how to write itself and does so. Where other classes can influence the output of others (for example, start and end times), higher level classes process the children and will set start and end times based on the order and duration of each child.
Should I be storing more data in the QStandardItemModel itself, or defining my own model perhaps? Does it sound like I have set myself up for future problems?
At the moment I have modified this system a couple of times to provide customised applications, but I am about to try and make it more generic. I welcome suggestions for improving my design. Go easy, please!
You should try to avoid creating god objects. Split your tasks and duties into smaller chunks. It makes it much easier to maintain and also much easier to extend if you need to.
Your specific use-case would benefit a lot from a more complete use of the Model-View-Controller pattern.
What doesn't make sense in your design is that your data objects hold a UI element. Since only one item can be shown in the right pane, this seems like a waste of resources. It makes more sense to have a single object that then gets passed a data object to display.
What I suggest for your program is the following:
Splitting your data into classes that only have functions for reporting and modifying values. There should be no knowledge of how to display data or store to a file.
Create separate class that handles the reading and writing from a file. If your model is very simple, you could just use single functions to do this using the method shown in the documentation for QDataStream or QTextStream.
Use your QTreeView and QStandardItemModel as Adaptor class between your data objects and the left pannel.
Create a controller class that gets informed by the QTreeView if data needs to be displayed in the right panel. The controller will then retrieve the data item and pass it to the right panel in order to be displayed.
The right panel should act like another View class with the sole responsibility of graphically displaying the data passed in from the controller class.
One advantage of doing it this way is that, if there are different categories of data that get displayed differently in the right panel, the controller could examine the selected data item, determine what the category is, create a view widget to put in the right panel, and then pass it the data to display.
This pattern is open-ended as far as extendability is concerned because you do not need to change your data classes if you need a new display, you merely need to create a new right-panel widget, and then teach your controller class how to determine when the new view should be used.
Another advantage of this pattern is that you only ever need to have a single widget created to display data in your right panel. If you change your selected item, you can just pass it to the view class that already exists and get it to refresh its display with the newly selected data. You only need to distroy the right-panel view widget if a different category of data object is selected and its data needs to be drawn in a different way. The controller class can determine whether a right-panel view widget can be re-used or whether it needs to be swapped out for a different widget.

Modelling self-modifying data / wrapper models in Qt

In Qt, I'm writing my own tree model (by subclassing QAbstractItemModel) which wraps around an existing data structure. It should be possible to update the data structure internally (not via the model) as well as via the model (so views can change it). In order to imagine it better: it's a scene graph which should be possible to edit using a scene view (without going via the Qt model) but also using an outliner (QTreeView which uses a Qt model as a proxy around the scene graph).
To avoid confusion we should consider two different scenarios (in the following, I use the "remove" operation as an example):
The user uses the Qt view to remove a node. The view wants to remove a row from the model using QAbstractItemModel::removeRow. This should in turn remove a corresponding node from the underlying data structure, the scene graph.
The user uses the scene view to remove a node. The scene view wants to remove a node from the scene graph. The model which wraps around the scene graph gets notified and in turn wants to notify connected views that a row has just been removed.
While I think I know how to implement 1., I don't know how to implement the notifying part in 2. There is the signal QAbstractItemModel::rowsAboutToBeRemoved() as well as rowsRemoved() which sound like they're my friends. But they are private signals (they say in the header source code: "can only be emitted by QAbstractItemModel"). There also is beginRemoveRows() and endRemoveRows() but according to their documentation, they should be called when the updates happens from the view, i.e. when removeRow has been called. Also, when I tried to use them, the view was screwed up totally.
According to the documentation it seems like it's not intended that the model class can model self-modifying data. Let's take a file system as another example. When using file system watching, which can detect changes in directories, a model should notify a view so the changes in the directory can be displayed live, even if the view was not used to modify the file system. Are such models even possible in Qt?
You're reading it wrong. The model must signal to its users when it's about to start changing its "geometry". So, no matter what is removing the rows from the model, it must tell the outside world that it happened. The sequence of events when a view removes rows from the model is such:
The view calls model->removeRows().
The model calls beginRemoveRows()
The model actually removes the rows from the internal data.
The model calls endRemoveRows().
If you implement some other interface that will remove the rows without calling model->removeRows(), you have to do exactly the same thing. It doesn't matter if it's a view or some other code that removes rows from the model, the model's behavior must be the same or else nothing will work.
You can architect an adapter class that's inserted between your SceneGraph and the Model. It should hold a pointer to the scenegraph and the model, and translate the operations between the two.

Qt Editing Custom Data Structures

I am trying to utilize the Model/View architecture to accomplish my goal but I am unsure as to whether this is the proper tool to use for this task.
I have a Material System I have been using, which I more recently have created an editor for using Qt, it uses a QGraphicsView to display items which are interconnected to form a final fragment shader code, this works extremely well however, I am having difficulties finding a way to display these custom data structures without hand coding widgets for each type of item.
These custom data structures are simply classes with members which I wish to modify using an interface depending on each members type. For instance if the item is a Value which in my material system represents a single variable, like a texture, I would like to be able to have 2 editable areas, one for the texture's path on disk, and one for the name of the variable.
What is the best approach for interpreting custom structures like this and creating widgets based on their type, and then mapping those widgets to edit/display them. All the google searching I found led me to the Model/View architecture however it seems this is more made for things like SQL databases and XML files.
class Value
{
std::string m_strType, m_strName, m_strValue, m_strLocation;
};
It sounds like you're looking for something like the Property Browser Framework. In short, you'll make all of the members you want to edit properties, and then use the property browser framework to create a model that you can then attach a view to.

What level of seperation should my UI elements and model objects have?

I'm building a desktop app in QT (although that may be irrelevant) and I'm having a hard time working through the class structure and layout. The data model is fairly simple with a root container with a number of containers of items. Consider the following representation:
Root
+ Parent
+ Child
The UI is fairly simple and follows that data model with a main window with a scrollable area (root), widgets that contain layouts (parents) of custom widgets (children) with some labels and buttons.
My trouble is with handling events that need to go up the chain and then back down like moving a child from one parent to another, moving elements, or updating child meta-data that impacts several to many other widgets.
I'm currently splitting UI widgets and model objects but having each widget and corresponding model object pointing to and from each other feels cumbersome and I think it is leading to too much maintenance.
I'd suggest following a standard MVC pattern and ensure there are no dependencies from the model to the view; in your case this would mean that while there is a widget for every model item, the model items do not reference their corresponding widgets.
While the MVC pattern has many flavours, one way to accomplish this would be to have a view class that monitors the model for any changes and updates the view accordingly (this can be accomplished by connecting a slot in the view class to a signal emitted from the model class). Any changes the user initiates through the view can then be:
1) handled directly by the model
through a simple signal/slot
connection
2) handled
by a controller class which can
direct the model to update accordingly
Either of these would then cause the model to emit an update signal which would cause your view to update. The benefit of this is the ability to change your view (or add additional views) without having to update your model.
I'd recommend reading Qt's Model/View Programming Guide to better understand how MVC works in Qt and to see if there's an existing class or interface (e.g. QAbstractItemModel) that you could use instead of baking your own.
Consider using factory pattern and command pattern. There are plenty of samples. I am just giving a hint here.
http://en.wikipedia.org/wiki/Factory_method_pattern
http://en.wikipedia.org/wiki/Command_pattern
Forgot mention about qt book: cartan-cas-dot-suffolk-dot-edu/oopdocbook/html/

How can I visually design a component in C++ Builder?

I have been away from C++ for a couple of years now doing AS3/Flex work. I have gotten used to being able to create a component and place it in design mode with very little fuss and I am struggling to get my head around the C++ Builder way of doing the same thing.
I have written many components for C++ Builder in the past, but none of them have been visual. What I would like to do now is create a component for customer search and another for order processing because I want to be able to create a new instance of these on the fly. What I don't want to do is have to place each of the components like the dbgrid and search fields manually in code. I would like to do this (as well as set their properties) in design mode.
How do I go about this? I have browsed the source for other Delphi components and I notice they have dfm files which seems to be what I need. How do I do this in C++ Builder? The only option I see is to add a new form if I want a dfm, but this isn't what I want as my components will be based on TPanel.
Is there a way to do this or do I have to resort to doing it all in code with no visual reference?
Pursuing the DFM idea I did a test this morning where I created a component based on TPanel and added a new form to it which I create and parent in the constructor of the component. In design mode I set the form border to none and placed a grid on it. This all looks OK until I place the component in my application, at that point it looks like a panel with a standard looking form in it and the grid is missing. If I run the app the panel shows as expected, borderless and with a grid. The DFM appears to be ignored in design mode for some reason.
If you know a better way to do this than using components then please give me some pointers.
Any help and advice will be appreciated beyond words
You might want to have a look at frames (look for "Frame objects"). They are "subforms" you can design visually and then place on forms.
Just as an FYI item, you can also drop the panel on a form, put any other controls on it, position them, set captions, etc..
Now, click the panel to select it, and use Component->Create Component Template from the IDE's main menu. This creates a unit you can install as a component which will add the panel and it's sub-controls (as a single component) to the IDE's component palette.
Of course, you can then modify the source for that new component like any other component source.